Merge remote-tracking branch 'upstream/master' into tizen
authorGilbok Lee <gilbok.lee@samsung.com>
Wed, 12 Jan 2022 05:31:00 +0000 (14:31 +0900)
committerGilbok Lee <gilbok.lee@samsung.com>
Wed, 12 Jan 2022 08:47:38 +0000 (17:47 +0900)
Change-Id: If3cf3c18b851741dcaec1b5a01796b7ba12242bc

620 files changed:
.gitignore
.gitlab-ci.yml
.gitlab/issue_templates/Bug.md [new file with mode: 0644]
.gitmodules [deleted file]
COPYING
ChangeLog
Makefile.am [deleted file]
NEWS
README
RELEASE
TODO [deleted file]
autogen.sh [deleted file]
common [deleted submodule]
configure.ac [deleted file]
data/Makefile.am [deleted file]
data/bash-completion/completions/gst-inspect-1.0
data/bash-completion/completions/gst-launch-1.0
data/bash-completion/helpers/.gitignore [deleted file]
data/bash-completion/helpers/gst.in
docs/.gitignore [deleted file]
docs/Makefile.am [deleted file]
docs/README
docs/gst-hotdoc-plugins-scanner.c [new file with mode: 0644]
docs/gst-plugins-doc-cache-generator.py [new file with mode: 0755]
docs/gst/.gitignore [deleted file]
docs/gst/Makefile.am [deleted file]
docs/gst/building.md [new file with mode: 0644]
docs/gst/building.xml [deleted file]
docs/gst/gi-index.md [new file with mode: 0644]
docs/gst/gst-universe.dot [deleted file]
docs/gst/gstreamer-docs.sgml [deleted file]
docs/gst/gstreamer-overrides.txt [deleted file]
docs/gst/gstreamer-sections.txt [deleted file]
docs/gst/gstreamer.types.in [deleted file]
docs/gst/index.md [new file with mode: 0644]
docs/gst/meson.build [deleted file]
docs/gst/overview.md [new file with mode: 0644]
docs/gst/running.md [new file with mode: 0644]
docs/gst/running.xml [deleted file]
docs/gst/sitemap.txt [new file with mode: 0644]
docs/images/gdp-header.png [moved from docs/libs/gdp-header.png with 100% similarity]
docs/images/gdp-header.svg [deleted file]
docs/images/gst-universe.svg [new file with mode: 0644]
docs/index.md [new file with mode: 0644]
docs/libs/.gitignore [deleted file]
docs/libs/Makefile.am [deleted file]
docs/libs/base/index.md [new file with mode: 0644]
docs/libs/base/sitemap.txt [new file with mode: 0644]
docs/libs/check/index.md [new file with mode: 0644]
docs/libs/check/sitemap.txt [new file with mode: 0644]
docs/libs/controller/index.md [new file with mode: 0644]
docs/libs/controller/sitemap.txt [new file with mode: 0644]
docs/libs/gstreamer-libs-docs.sgml [deleted file]
docs/libs/gstreamer-libs-overrides.txt [deleted file]
docs/libs/gstreamer-libs-sections.txt [deleted file]
docs/libs/gstreamer-libs.types [deleted file]
docs/libs/index.md [new file with mode: 0644]
docs/libs/meson.build [deleted file]
docs/libs/net/index.md [new file with mode: 0644]
docs/libs/net/sitemap.txt [new file with mode: 0644]
docs/list-ulink.xsl [deleted file]
docs/meson.build
docs/plugins/.gitignore [deleted file]
docs/plugins/Makefile.am [deleted file]
docs/plugins/blank.md [moved from docs/random/.gitignore with 100% similarity]
docs/plugins/gst_plugins_cache.json [new file with mode: 0644]
docs/plugins/gstreamer-plugins-docs.sgml [deleted file]
docs/plugins/gstreamer-plugins-sections.txt [deleted file]
docs/plugins/gstreamer-plugins.args [deleted file]
docs/plugins/gstreamer-plugins.hierarchy [deleted file]
docs/plugins/gstreamer-plugins.interfaces [deleted file]
docs/plugins/gstreamer-plugins.prerequisites [deleted file]
docs/plugins/gstreamer-plugins.signals [deleted file]
docs/plugins/gstreamer-plugins.types [deleted file]
docs/plugins/index.md [new file with mode: 0644]
docs/plugins/inspect/plugin-coreelements.xml [deleted file]
docs/plugins/inspect/plugin-coretracers.xml [deleted file]
docs/plugins/sitemap.txt [new file with mode: 0644]
docs/random/API [deleted file]
docs/random/TODO-pre-0.9 [deleted file]
docs/random/autoplug1 [deleted file]
docs/random/autoplug2 [deleted file]
docs/random/autotools [deleted file]
docs/random/bbb/streamselection [deleted file]
docs/random/bbb/subtitles [deleted file]
docs/random/buffers [deleted file]
docs/random/caps [deleted file]
docs/random/caps.dia [deleted file]
docs/random/caps2 [deleted file]
docs/random/classes.dia [deleted file]
docs/random/ds/0.9-planning [deleted file]
docs/random/ds/buffer_locking [deleted file]
docs/random/ds/bufferpools [deleted file]
docs/random/ds/categories [deleted file]
docs/random/ds/element-checklist [deleted file]
docs/random/ds/registry [deleted file]
docs/random/ds/roadmap [deleted file]
docs/random/ensonic/audiobaseclasses.txt [deleted file]
docs/random/ensonic/dparams.txt [deleted file]
docs/random/ensonic/draft-registry-change-hooks.txt [deleted file]
docs/random/ensonic/dynlink.txt [deleted file]
docs/random/ensonic/interfaces.txt [deleted file]
docs/random/ensonic/lazycaps.txt [deleted file]
docs/random/ensonic/logging.txt [deleted file]
docs/random/ensonic/media-device-daemon.txt [deleted file]
docs/random/ensonic/plugindocs.txt [deleted file]
docs/random/ensonic/receipies.txt [deleted file]
docs/random/eos [deleted file]
docs/random/error [deleted file]
docs/random/example [deleted file]
docs/random/hierarchy [deleted file]
docs/random/interfaces [deleted file]
docs/random/metadata [deleted file]
docs/random/moving-plugins
docs/random/mutability [deleted file]
docs/random/negotiation [deleted file]
docs/random/omega/EOS/chain-walkthrough [deleted file]
docs/random/omega/IDEAS [deleted file]
docs/random/omega/TODO-0.1.0 [deleted file]
docs/random/omega/TYPE_FOURCC [deleted file]
docs/random/omega/build/TODO [deleted file]
docs/random/omega/caps2 [deleted file]
docs/random/omega/caps3 [deleted file]
docs/random/omega/debug-commit [deleted file]
docs/random/omega/eos.old [deleted file]
docs/random/omega/filterfactory [deleted file]
docs/random/omega/output_policies [deleted file]
docs/random/omega/pad-negotiation [deleted file]
docs/random/omega/padtemplates [deleted file]
docs/random/omega/plan-generation [deleted file]
docs/random/omega/sched-case [deleted file]
docs/random/omega/sched-commit1 [deleted file]
docs/random/omega/sched/chains [deleted file]
docs/random/omega/sched/walkthrough-72 [deleted file]
docs/random/omega/sched2 [deleted file]
docs/random/omega/scheduling [deleted file]
docs/random/omega/testing/.gitignore [deleted file]
docs/random/omega/testing/Makefile [deleted file]
docs/random/omega/testing/framework [deleted file]
docs/random/omega/testing/gstobject.c [deleted file]
docs/random/omega/testing/gstobject.txt [deleted file]
docs/random/omega/type-properties [deleted file]
docs/random/phonon-gst [deleted file]
docs/random/plugins [deleted file]
docs/random/plugins.dia [deleted file]
docs/random/porting-to-0.11.txt [deleted file]
docs/random/queue [deleted file]
docs/random/richardb/syncmail [deleted file]
docs/random/rtp [deleted file]
docs/random/signal [deleted file]
docs/random/sources [deleted file]
docs/random/status-0.11-14-jun-2011.txt [deleted file]
docs/random/styleguide [deleted file]
docs/random/testing/syntax [deleted file]
docs/random/thaytan/opengl [deleted file]
docs/random/thaytan/video-overlays [deleted file]
docs/random/thomasvs/0.10 [deleted file]
docs/random/thomasvs/0.4.0 [deleted file]
docs/random/thomasvs/TODO [deleted file]
docs/random/thomasvs/docreview [deleted file]
docs/random/thomasvs/features [deleted file]
docs/random/thomasvs/guadec-4 [deleted file]
docs/random/thomasvs/pthread [deleted file]
docs/random/thomasvs/pwg [deleted file]
docs/random/thomasvs/registry [deleted file]
docs/random/types [deleted file]
docs/random/types2 [deleted file]
docs/random/types3 [deleted file]
docs/random/use-cases-0.11.txt [deleted file]
docs/random/usecases [deleted file]
docs/random/vis-transform [deleted file]
docs/random/wingo/porting-plugins-to-0.9 [deleted file]
docs/random/wingo/threadsafe-properties [deleted file]
docs/random/wingo/without-factories [deleted file]
docs/random/wtay/autoplug2
docs/random/wtay/eos-19012001
docs/random/wtay/eos2
docs/random/wtay/eos4
docs/random/wtay/negotiation3
docs/random/wtay/network-transp
docs/random/wtay/pipelineinfo
docs/random/wtay/porting-list-0.11.txt
docs/random/wtay/scheduling_ideas
docs/random/zaheerm/dvb-interface.txt [deleted file]
docs/version.entities.in [deleted file]
docs/version.in [new file with mode: 0644]
gst/.gitignore [deleted file]
gst/Makefile.am [deleted file]
gst/glib-compat-private.h
gst/gst.c
gst/gst.h
gst/gst_private.h
gst/gstallocator.c
gst/gstallocator.h
gst/gstatomicqueue.c
gst/gstatomicqueue.h
gst/gstbin.c
gst/gstbin.h
gst/gstbuffer.c
gst/gstbuffer.h
gst/gstbufferlist.c
gst/gstbufferlist.h
gst/gstbufferpool.c
gst/gstbufferpool.h
gst/gstbus.c
gst/gstbus.h
gst/gstcaps.c
gst/gstcaps.h
gst/gstcapsfeatures.c
gst/gstcapsfeatures.h
gst/gstchildproxy.c
gst/gstchildproxy.h
gst/gstclock.c
gst/gstclock.h
gst/gstconfig.h.in
gst/gstcontext.c
gst/gstcontext.h
gst/gstcontrolbinding.c
gst/gstcontrolbinding.h
gst/gstcontrolsource.c
gst/gstcontrolsource.h
gst/gstdatetime.c
gst/gstdatetime.h
gst/gstdebugutils.c
gst/gstdebugutils.h
gst/gstdevice.c
gst/gstdevice.h
gst/gstdevicemonitor.c
gst/gstdevicemonitor.h
gst/gstdeviceprovider.c
gst/gstdeviceprovider.h
gst/gstdeviceproviderfactory.c
gst/gstdeviceproviderfactory.h
gst/gstdynamictypefactory.c
gst/gstdynamictypefactory.h
gst/gstelement.c
gst/gstelement.h
gst/gstelementfactory.c
gst/gstelementfactory.h
gst/gsterror.c
gst/gsterror.h
gst/gstevent.c
gst/gstevent.h
gst/gstghostpad.c
gst/gstghostpad.h
gst/gstinfo.c
gst/gstinfo.h
gst/gstiterator.c
gst/gstiterator.h
gst/gstmemory.c
gst/gstmemory.h
gst/gstmessage.c
gst/gstmessage.h
gst/gstmeta.c
gst/gstmeta.h
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/gstparse.c
gst/gstparse.h
gst/gstpipeline.c
gst/gstpipeline.h
gst/gstplugin.c
gst/gstplugin.h
gst/gstpluginfeature.c
gst/gstpluginfeature.h
gst/gstpluginloader.c
gst/gstpoll.c
gst/gstpreset.c
gst/gstpromise.c
gst/gstpromise.h
gst/gstprotection.c
gst/gstprotection.h
gst/gstquark.c
gst/gstquark.h
gst/gstquery.c
gst/gstquery.h
gst/gstquery.h.tv
gst/gstregistry.c
gst/gstregistry.h
gst/gstregistrybinary.c
gst/gstregistrychunks.c
gst/gstsample.c
gst/gstsample.h
gst/gstsegment.c
gst/gstsegment.h
gst/gststreamcollection.c
gst/gststreamcollection.h
gst/gststreams.c
gst/gststreams.h
gst/gststructure.c
gst/gststructure.h
gst/gstsystemclock.c
gst/gstsystemclock.h
gst/gsttaglist.c
gst/gsttaglist.h
gst/gsttask.c
gst/gsttask.h
gst/gsttaskpool.c
gst/gsttaskpool.h
gst/gsttoc.h
gst/gsttracer.c
gst/gsttracer.h
gst/gsttracerfactory.c
gst/gsttracerfactory.h
gst/gsttracerrecord.c
gst/gsttracerrecord.h
gst/gsttracerutils.c
gst/gsttracerutils.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/math-compat.h
gst/meson.build
gst/parse/.gitignore [deleted file]
gst/parse/Makefile.am [deleted file]
gst/parse/grammar.y.in [moved from gst/parse/grammar.y with 96% similarity]
gst/parse/meson.build
gst/parse/parse.l
gst/printf/Makefile.am [deleted file]
gstreamer.doap
hooks/pre-commit.hook
libs/Makefile.am [deleted file]
libs/gst/Makefile.am [deleted file]
libs/gst/base/.gitignore [deleted file]
libs/gst/base/Makefile.am [deleted file]
libs/gst/base/gstadapter.c
libs/gst/base/gstadapter.h
libs/gst/base/gstaggregator.c
libs/gst/base/gstaggregator.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.c
libs/gst/base/gstbitwriter.c
libs/gst/base/gstbytereader.c
libs/gst/base/gstbytereader.h
libs/gst/base/gstbytewriter.c
libs/gst/base/gstcollectpads.c
libs/gst/base/gstcollectpads.h
libs/gst/base/gstdataqueue.c
libs/gst/base/gstdataqueue.h
libs/gst/base/gstflowcombiner.c
libs/gst/base/gstflowcombiner.h
libs/gst/base/gstindex.c
libs/gst/base/gstpushsrc.h
libs/gst/base/meson.build
libs/gst/check/.gitignore [deleted file]
libs/gst/check/Makefile.am [deleted file]
libs/gst/check/gstcheck.c
libs/gst/check/gstcheck.h
libs/gst/check/gstconsistencychecker.c
libs/gst/check/gstharness.c
libs/gst/check/gstharness.h
libs/gst/check/gsttestclock.c
libs/gst/check/gsttestclock.h
libs/gst/check/libcheck/Makefile.am [deleted file]
libs/gst/check/libcheck/check.c
libs/gst/check/libcheck/check.h.in
libs/gst/check/libcheck/check_pack.c
libs/gst/check/libcheck/check_run.c
libs/gst/check/libcheck/meson.build
libs/gst/check/meson.build
libs/gst/controller/.gitignore [deleted file]
libs/gst/controller/Makefile.am [deleted file]
libs/gst/controller/gstargbcontrolbinding.h
libs/gst/controller/gstdirectcontrolbinding.c
libs/gst/controller/gstdirectcontrolbinding.h
libs/gst/controller/gstinterpolationcontrolsource.h
libs/gst/controller/gstlfocontrolsource.h
libs/gst/controller/gstproxycontrolbinding.c
libs/gst/controller/gstproxycontrolbinding.h
libs/gst/controller/gsttimedvaluecontrolsource.c
libs/gst/controller/gsttimedvaluecontrolsource.h
libs/gst/controller/gsttriggercontrolsource.h
libs/gst/controller/meson.build
libs/gst/helpers/.gitignore [deleted file]
libs/gst/helpers/Makefile.am [deleted file]
libs/gst/helpers/gst_gdb.py
libs/gst/helpers/meson.build
libs/gst/helpers/ptp_helper_post_install.sh
libs/gst/net/.gitignore [deleted file]
libs/gst/net/Makefile.am [deleted file]
libs/gst/net/gstnetaddressmeta.c
libs/gst/net/gstnetclientclock.c
libs/gst/net/gstnetclientclock.h
libs/gst/net/gstnetcontrolmessagemeta.c
libs/gst/net/gstnettimepacket.h
libs/gst/net/gstnettimeprovider.c
libs/gst/net/gstnettimeprovider.h
libs/gst/net/gstnetutils.c
libs/gst/net/gstnetutils.h
libs/gst/net/gstptpclock.c
libs/gst/net/gstptpclock.h
libs/gst/net/meson.build
libs/gst/net/net.h
m4/.gitignore [deleted file]
m4/Makefile.am [deleted file]
m4/check-checks.m4 [deleted file]
meson.build
meson_options.txt
packaging/gstreamer.spec
pkgconfig/.gitignore [deleted file]
pkgconfig/Makefile.am [deleted file]
pkgconfig/gstreamer-base-uninstalled.pc.in [deleted file]
pkgconfig/gstreamer-base.pc.in [deleted file]
pkgconfig/gstreamer-check-uninstalled.pc.in [deleted file]
pkgconfig/gstreamer-check.pc.in [deleted file]
pkgconfig/gstreamer-controller-uninstalled.pc.in [deleted file]
pkgconfig/gstreamer-controller.pc.in [deleted file]
pkgconfig/gstreamer-net-uninstalled.pc.in [deleted file]
pkgconfig/gstreamer-net.pc.in [deleted file]
pkgconfig/gstreamer-uninstalled.pc.in [deleted file]
pkgconfig/gstreamer.pc.in [deleted file]
pkgconfig/meson.build [deleted file]
plugins/Makefile.am [deleted file]
plugins/elements/.gitignore [deleted file]
plugins/elements/Makefile.am [deleted file]
plugins/elements/gstcapsfilter.c
plugins/elements/gstclocksync.c
plugins/elements/gstclocksync.h
plugins/elements/gstconcat.c
plugins/elements/gstcoreelementselements.h [new file with mode: 0644]
plugins/elements/gstcoreelementsplugin.c [new file with mode: 0644]
plugins/elements/gstdataurisrc.c
plugins/elements/gstdownloadbuffer.c
plugins/elements/gstelements.c [deleted file]
plugins/elements/gstelements_private.c
plugins/elements/gstelements_private.h
plugins/elements/gstfakesink.c
plugins/elements/gstfakesrc.c
plugins/elements/gstfdsink.c
plugins/elements/gstfdsink.h
plugins/elements/gstfdsrc.c
plugins/elements/gstfilesink.c
plugins/elements/gstfilesink.h
plugins/elements/gstfilesrc.c
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/gstoutputselector.c
plugins/elements/gstoutputselector.h
plugins/elements/gstqueue.c
plugins/elements/gstqueue2.c
plugins/elements/gstqueue2.h
plugins/elements/gstsparsefile.c
plugins/elements/gststreamiddemux.c
plugins/elements/gsttee.c
plugins/elements/gsttypefindelement.c
plugins/elements/gsttypefindelement.h
plugins/elements/gstvalve.c
plugins/elements/gstvalve.h
plugins/elements/meson.build
plugins/meson.build
plugins/tracers/.gitignore [deleted file]
plugins/tracers/Makefile.am [deleted file]
plugins/tracers/gstfactories.c [new file with mode: 0644]
plugins/tracers/gstfactories.h [moved from docs/random/LICENSE with 55% similarity]
plugins/tracers/gstlatency.c
plugins/tracers/gstleaks.c
plugins/tracers/gstleaks.h
plugins/tracers/gstlog.c
plugins/tracers/gstrusage.c
plugins/tracers/gstrusage.h
plugins/tracers/gststats.c
plugins/tracers/gsttracers.c
plugins/tracers/meson.build
po/.gitignore [deleted file]
po/Makevars [deleted file]
po/POTFILES [moved from po/POTFILES.in with 96% similarity]
po/README [deleted file]
po/remove-potcdate.sin [deleted file]
scripts/create-uninstalled-setup.sh [deleted file]
scripts/dist-translations.py [new file with mode: 0755]
scripts/extract-release-date-from-doap-file.py [new file with mode: 0755]
scripts/five-bugs-a-day.pl [deleted file]
scripts/git-update.sh [deleted file]
scripts/gst-uninstalled [deleted file]
scripts/meson.build [new file with mode: 0644]
stamp.h.in [deleted file]
tests/.gitignore [deleted file]
tests/Makefile.am [deleted file]
tests/benchmarks/.gitignore [deleted file]
tests/benchmarks/Makefile.am [deleted file]
tests/benchmarks/complexity.c
tests/benchmarks/mass-elements.c
tests/check/.gitignore [deleted file]
tests/check/Makefile.am [deleted file]
tests/check/elements/.gitignore [deleted file]
tests/check/elements/clocksync.c
tests/check/elements/concat.c
tests/check/elements/dataurisrc.c
tests/check/elements/funnel.c
tests/check/elements/leaks.c [new file with mode: 0644]
tests/check/elements/multiqueue.c
tests/check/elements/queue.c
tests/check/elements/queue2.c
tests/check/elements/selector.c
tests/check/elements/tee.c
tests/check/generic/.gitignore [deleted file]
tests/check/gst/.gitignore [deleted file]
tests/check/gst/capslist.h
tests/check/gst/gst.c
tests/check/gst/gstbin.c
tests/check/gst/gstbuffer.c
tests/check/gst/gstbufferlist.c
tests/check/gst/gstbufferpool.c
tests/check/gst/gstbus.c
tests/check/gst/gstcaps.c
tests/check/gst/gstcontroller.c
tests/check/gst/gstdatetime.c
tests/check/gst/gstdevice.c
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/gstmessage.c
tests/check/gst/gstmeta.c
tests/check/gst/gstminiobject.c
tests/check/gst/gstobject.c
tests/check/gst/gstpad.c
tests/check/gst/gstparamspecs.c
tests/check/gst/gstpreset.c
tests/check/gst/gstprintf.c
tests/check/gst/gstpromise.c
tests/check/gst/gstprotection.c
tests/check/gst/gstsegment.c
tests/check/gst/gststructure.c
tests/check/gst/gstsystemclock.c
tests/check/gst/gsttag.c
tests/check/gst/gsttagsetter.c
tests/check/gst/gsttask.c
tests/check/gst/gsttocsetter.c
tests/check/gst/gsttracerrecord.c
tests/check/gst/gsturi.c
tests/check/gst/gstutils.c
tests/check/gst/gstvalue.c
tests/check/gstreamer.supp
tests/check/libs/.gitignore [deleted file]
tests/check/libs/aggregator.c
tests/check/libs/baseparse.c
tests/check/libs/basesrc.c
tests/check/libs/bitwriter.c
tests/check/libs/bytereader.c
tests/check/libs/bytewriter.c
tests/check/libs/collectpads.c
tests/check/libs/controller.c
tests/check/libs/flowcombiner.c
tests/check/libs/gstharness.c
tests/check/libs/gsttestclock.c
tests/check/libs/test_transform.c
tests/check/libs/transform1.c
tests/check/meson.build
tests/check/pipelines/.gitignore [deleted file]
tests/check/pipelines/cleanup.c
tests/check/pipelines/parse-launch.c
tests/check/pipelines/seek.c
tests/check/pipelines/simple-launch-lines.c
tests/examples/Makefile.am [deleted file]
tests/examples/adapter/.gitignore [deleted file]
tests/examples/adapter/Makefile.am [deleted file]
tests/examples/controller/.gitignore [deleted file]
tests/examples/controller/Makefile.am [deleted file]
tests/examples/controller/control-sources.c
tests/examples/controller/controller-graph.c
tests/examples/helloworld/.gitignore [deleted file]
tests/examples/helloworld/Makefile.am [deleted file]
tests/examples/helloworld/helloworld.c
tests/examples/memory/.gitignore [deleted file]
tests/examples/memory/Makefile.am [deleted file]
tests/examples/netclock/.gitignore [deleted file]
tests/examples/netclock/Makefile.am [deleted file]
tests/examples/netclock/netclock-client.c
tests/examples/ptp/.gitignore [deleted file]
tests/examples/ptp/Makefile.am [deleted file]
tests/examples/stepping/.gitignore [deleted file]
tests/examples/stepping/Makefile.am [deleted file]
tests/examples/streamiddemux/Makefile.am [deleted file]
tests/examples/streamiddemux/streamiddemux-stream.c
tests/examples/streams/.gitignore [deleted file]
tests/examples/streams/Makefile.am [deleted file]
tests/meson.build
tests/misc/Makefile.am [deleted file]
tests/misc/netclock-replay.c
tests/validate/gst-tester.c [new file with mode: 0644]
tests/validate/meson.build [new file with mode: 0644]
tests/validate/simplest.validatetest [new file with mode: 0644]
tests/validate/simplest/flow-expectations/log-sink-sink-expected [new file with mode: 0644]
tools/.gitignore [deleted file]
tools/Makefile.am [deleted file]
tools/gst-inspect-1.0.1
tools/gst-inspect.c
tools/gst-launch-1.0.1
tools/gst-launch.c
tools/gst-stats.c
tools/meson.build
tools/tools.h

index f8adb7f..9cf107a 100644 (file)
@@ -1,48 +1,6 @@
-ABOUT-NLS
-INSTALL
-Makefile
-Makefile.in
-aclocal.m4
-config.cache
-config.guess
-config.h
-config.h.in
-config.h-new
-config.log
-config.rpath
-config.status*
-config.sub
-configure
-gstreamer-[0-9]*
-gstreamer-config
-gstreamer.pc
-gstreamer-uninstalled.pc
-gst-element-check-*.m4
-libtool
-ltconfig
-ltmain.sh
-missing
-stamp-h
-stamp-h.in
-stamp.h
-autom4te.cache
-autom4te-2.53.cache
-stamp-h1
-autoregen.sh
-compile
-depcomp
-install-sh
-mkinstalldirs
-py-compile
-registry.*
-coverage-report.txt
-/test-driver
-.deps
-.libs
 *~
-_stdint.h
-*.gir
-*.typelib
+*.bak
+
 Build
 *.user
 *.suo
@@ -50,14 +8,8 @@ Build
 *.sdf
 *.opensdf
 *.DS_Store
-*.log
-*.trs
-.dirstamp
-*.gc??
-*.swp
-
-/libs/gst/*/*-enumtypes.[ch]
-/libs/gst/helpers/gst-completion-helper-1.0
 
-/tests/misc/netclock-replay
+# Meson
 /build
+/_build
+/subprojects
index bed438d..c61aa7a 100644 (file)
@@ -1 +1 @@
-include: "https://gitlab.freedesktop.org/gstreamer/gst-ci/raw/1.16/gitlab/ci_template.yml"
+include: "https://gitlab.freedesktop.org/gstreamer/gst-ci/raw/master/gitlab/ci_template.yml"
diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md
new file mode 100644 (file)
index 0000000..71c79ac
--- /dev/null
@@ -0,0 +1,32 @@
+### Describe your issue
+<!-- a clear and concise summary of the bug. -->
+<!-- For any GStreamer usage question, please contact the community using the #gstreamer channel on IRC https://www.oftc.net/ or the mailing list on https://gstreamer.freedesktop.org/lists/ -->
+
+#### Expected Behavior
+<!-- What did you expect to happen -->
+
+#### Observed Behavior
+<!-- What actually happened -->
+
+#### Setup
+- **Operating System:**
+- **Device:** Computer / Tablet / Mobile / Virtual Machine <!-- Delete as appropriate !-->
+- **GStreamer Version:**
+- **Command line:**
+
+### Steps to reproduce the bug
+<!-- please fill in exact steps which reproduce the bug on your system, for example: -->
+1. open terminal
+2. type `command`
+
+### How reproducible is the bug?
+<!-- The reproducibility of the bug is Always/Intermittent/Only once after doing a very specific set of steps-->
+
+### Screenshots if relevant
+
+### Solutions you have tried
+
+### Related non-duplicate issues
+
+### Additional Information
+<!-- Any other information such as logs. Make use of <details> for long output -->
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644 (file)
index 596ee78..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "common"]
-        path = common
-        url = https://gitlab.freedesktop.org/gstreamer/common.git
diff --git a/COPYING b/COPYING
index c87cfe8..efce2a8 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -1,13 +1,14 @@
-                 GNU LIBRARY GENERAL PUBLIC LICENSE
-                      Version 2, June 1991
+                 GNU LESSER GENERAL PUBLIC LICENSE
+                      Version 2.1, February 1999
 
- Copyright (C) 1991 Free Software Foundation, Inc.
-                    51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
-[This is the first released version of the library GPL.  It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
 
                            Preamble
 
@@ -16,97 +17,109 @@ freedom to share and change it.  By contrast, the GNU General Public
 Licenses are intended to guarantee your freedom to share and change
 free software--to make sure the software is free for all its users.
 
-  This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it.  You can use it for
-your libraries, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
 
   To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
 
   For example, if you distribute copies of the library, whether gratis
 or for a fee, you must give the recipients all the rights that we gave
 you.  You must make sure that they, too, receive or can get the source
-code.  If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
 it.  And you must show them these terms so they know their rights.
 
-  Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
 permission to copy, distribute and/or modify the library.
 
-  Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library.  If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
 \f
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software.  To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
-  Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs.  This
-license, the GNU Library General Public License, applies to certain
-designated libraries.  This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
-  The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it.  Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program.  However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
-  Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries.  We
-concluded that weaker conditions might promote sharing better.
-
-  However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves.  This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them.  (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.)  The hope is that this
-will lead to faster development of free libraries.
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
 
   The precise terms and conditions for copying, distribution and
 modification follow.  Pay close attention to the difference between a
 "work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, while the latter only
-works together with the library.
-
-  Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
 \f
-                 GNU LIBRARY GENERAL PUBLIC LICENSE
+                 GNU LESSER GENERAL PUBLIC LICENSE
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
-  0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License").  Each licensee is
-addressed as "you".
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
 
   A "library" means a collection of software functions and/or data
 prepared so as to be conveniently linked with application programs
@@ -255,7 +268,7 @@ distribute the object code for the work under the terms of Section 6.
 Any executables containing that work also fall under Section 6,
 whether or not they are linked directly with the Library itself.
 \f
-  6. As an exception to the Sections above, you may also compile or
+  6. As an exception to the Sections above, you may also combine or
 link a "work that uses the Library" with the Library to produce a
 work containing portions of the Library, and distribute that work
 under terms of your choice, provided that the terms permit
@@ -282,23 +295,31 @@ of these things:
     Library will not necessarily be able to recompile the application
     to use the modified definitions.)
 
-    b) Accompany the work with a written offer, valid for at
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
     least three years, to give the same user the materials
     specified in Subsection 6a, above, for a charge no more
     than the cost of performing this distribution.
 
-    c) If distribution of the work is made by offering access to copy
+    d) If distribution of the work is made by offering access to copy
     from a designated place, offer equivalent access to copy the above
     specified materials from the same place.
 
-    d) Verify that the user has already received a copy of these
+    e) Verify that the user has already received a copy of these
     materials or that you have already sent this user a copy.
 
   For an executable, the required form of the "work that uses the
 Library" must include any data and utility programs needed for
 reproducing the executable from it.  However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
 components (compiler, kernel, and so on) of the operating system on
 which the executable runs, unless that component itself accompanies
 the executable.
@@ -347,7 +368,7 @@ Library), the recipient automatically receives a license from the
 original licensor to copy, distribute, link with or modify the Library
 subject to these terms and conditions.  You may not impose any further
 restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
+You are not responsible for enforcing compliance by third parties with
 this License.
 \f
   11. If, as a consequence of a court judgment or allegation of patent
@@ -390,7 +411,7 @@ excluded.  In such case, this License incorporates the limitation as if
 written in the body of this License.
 
   13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
+versions of the Lesser General Public License from time to time.
 Such new versions will be similar in spirit to the present version,
 but may differ in detail to address new problems or concerns.
 
@@ -436,7 +457,7 @@ DAMAGES.
 
                     END OF TERMS AND CONDITIONS
 \f
-     Appendix: How to Apply These Terms to Your New Libraries
+           How to Apply These Terms to Your New Libraries
 
   If you develop a new library, and you want it to be of the greatest
 possible use to the public, we recommend making it free software that
@@ -453,18 +474,18 @@ convey the exclusion of warranty; and each file should have at least the
     Copyright (C) <year>  <name of author>
 
     This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
+    modify it under the terms of the GNU Lesser General Public
     License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
+    version 2.1 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.
+    Lesser General Public License for more details.
 
-    You should have received a copy of the GNU Library General Public
-    License along with this library; if not, write to the Free
-    Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 Also add information on how to contact you by electronic and paper mail.
 
@@ -479,3 +500,4 @@ necessary.  Here is a sample; alter the names:
   Ty Coon, President of Vice
 
 That's all there is to it!
+
index bf07de8..34f23a6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
-=== release 1.16.2 ===
+=== release 1.19.2 ===
 
-2019-12-03 10:57:30 +0000  Tim-Philipp Müller <tim@centricular.com>
+2021-09-23 01:32:32 +0100  Tim-Philipp Müller <tim@centricular.com>
 
        * ChangeLog:
        * NEWS:
        * RELEASE:
-       * configure.ac:
        * gstreamer.doap:
        * meson.build:
-         Release 1.16.2
+         Release 1.19.2
 
-2019-12-03 10:57:30 +0000  Tim-Philipp Müller <tim@centricular.com>
+2021-06-23 16:41:20 +0300  Sebastian Dröge <sebastian@centricular.com>
 
-       * docs/plugins/inspect/plugin-coreelements.xml:
-       * docs/plugins/inspect/plugin-coretracers.xml:
-         Update docs
+       * plugins/elements/gstclocksync.c:
+         clocksync: Add some debug output to the clock waiting code
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/841>
+
+2021-09-20 13:12:12 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstevent.c:
+       * gst/gstmessage.c:
+         gst: Initialize optional event/message fields when parsing
+         These might not exist inside the structure and then we would potentially
+         keep around uninitialized memory from the caller in the out parameter.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/887>
+
+2021-09-19 21:01:21 +0800  He Junyan <junyan.he@intel.com>
+
+       * tests/check/libs/bitwriter.c:
+         test: bitwriter: Add a test for reset_and_get_data when not byte unaligned.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/886>
+
+2021-09-19 22:39:09 +0800  He Junyan <junyan.he@intel.com>
+
+       * libs/gst/base/gstbitwriter.c:
+         bitwriter: Fix a memory leak in reset_and_get_buffer.
+         We should record the ownership of the data before we reset the bitwriter.
+         Or we will always dup the buffer data and leak the memory.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/886>
+
+2021-09-19 00:19:43 +0800  He Junyan <junyan.he@intel.com>
+
+       * libs/gst/base/gstbitwriter.c:
+         bitwriter: Fix the trailing bits lost when getting its data.
+         In reset_and_get_data and reset_and_get_buffer, it fails to include
+         the trailing bits less than 8. So, when the bit_size is not byte
+         aligned, the trailing bits are lost in the return buffer.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/886>
+
+2021-09-10 01:43:18 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * plugins/elements/gstmultiqueue.c:
+         multiqueue: fix obsolete comment re initial flow status
+         The initial single queue srcresult is OK, it hasn't been
+         NOT_LINKED since 2007.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/885>
+
+2021-09-09 20:25:25 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * plugins/elements/gstmultiqueue.c:
+         multiqueue: never consider a queue that is not waiting
+         .. when computing the high id.
+         After a flush for instance, sq->srcresult is reset to OK,
+         yet it doesn't make sense to pick a non-existing position
+         id as the high id when a queue doesn't contain any items
+         in that situation either.
+         It is in any case completely OK to let the not-linked stream
+         get consumed without throttling at this stage, as any
+         first packet arriving on other single queues will get assigned
+         a higher position id.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/885>
+
+2021-09-09 04:08:22 +0000  Andika Triwidada <andika@gmail.com>
+
+       * tools/gst-inspect.c:
+         add missing space
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/884>
+
+2021-09-06 01:43:57 +1000  Jan Schmidt <jan@centricular.com>
+
+       * plugins/elements/gstmultiqueue.c:
+         multiqueue: Use running time of gap events for wakeups.
+         Use gap events to update the next_time of a queue the same
+         as buffers or segment events. Fixes problems where a group
+         consisting only of sparse streams primarily driven by
+         gap events would stall with a full multiqueue because
+         unlinked streams in the group were not being woken to
+         push data.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/879>
+
+2021-08-27 13:51:07 +1000  Matthew Waters <matthew@centricular.com>
+
+       * gst/gstelement.c:
+         element: NULL the lists of contexts in dispose()
+         If dispose() is called more than once, we may double unref the list of
+         GstContext's.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/875>
+
+2021-08-24 14:53:30 +0200  Jan Alexander Steffens (heftig) <jan.steffens@ltnglobal.com>
+
+       * gst/gstpad.c:
+         pad: Keep IDLE probe hook alive during immediate callback
+         When the probe returns GST_PAD_PROBE_REMOVE and gets called concurrently
+         from the streaming thread while we're in the callback here, the hook has
+         already been destroyed by the time we've reacquired the object lock.
+         Consequently, cleanup_hook gets passed an invalid pointer.
+         Keep another reference to the hook alive to avoid this situation.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/873>
+
+2021-08-20 16:34:16 +0200  Edward Hervey <edward@centricular.com>
+
+       * plugins/elements/gstconcat.c:
+         concat: Properly propagate seqnum of segment events
+         Was broken by https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/819
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/871>
+
+2021-01-10 23:37:21 +0100  Théo MAILLART <tmaillart@gmail.com>
+
+       * tests/check/gst/gstelementfactory.c:
+         tests: elementfactory: add element creation tests
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/736>
+
+2021-01-29 20:36:51 +0100  Théo MAILLART <tmaillart@gmail.com>
+
+       * gst/gstelementfactory.c:
+       * gst/gstelementfactory.h:
+         elementfactory: enable construct only property passing
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/736>
+
+2021-03-31 18:36:00 -0400  Olivier Crête <olivier.crete@collabora.com>
+
+       * docs/plugins/gst_plugins_cache.json:
+       * plugins/tracers/gstfactories.c:
+       * plugins/tracers/gstfactories.h:
+       * plugins/tracers/gsttracers.c:
+       * plugins/tracers/meson.build:
+       * tools/gst-stats.c:
+         tracer: Add new tracer to list loaded elements and other features
+         This new tracer will list loaded elements and plugins. This should
+         make it easier to generate minimal builds of GStreamer.
+         This also traces other features such as typefind functions, device
+         providers and dynamic types.
+         The format of the output of gst-stats should match the parameters
+         expected by the meson based gst-build system.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/782>
+
+2021-04-23 15:34:26 -0400  Olivier Crête <olivier.crete@collabora.com>
+
+       * gst/gstpluginfeature.c:
+       * gst/gsttracerutils.c:
+       * gst/gsttracerutils.h:
+         tracers: Add tracepoint when a plugin feature it loaded
+         This makes it possible to trace which ones are loaded in a specific
+         program to make nice statistics.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/782>
+
+2021-08-18 10:23:38 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstpad.c:
+       * tests/check/gst/gstpad.c:
+         pad: Ensure last flow return is set on sink pads in push mode
+         The last flow return field was never updated on sink pads in push mode. This
+         fixes it and makes it consistent.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/868>
+
+2021-08-13 19:21:41 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * gst/gstbuffer.c:
+         gstbuffer: Use g_memdup2 instead of g_memdup
+         This was added in !826 which was created after !803 (which changes
+         g_memdup -> g_memdup2), but merged before it, so it slipped through.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/866>
+
+2021-08-10 13:35:14 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * gst/gstplugin.c:
+         plugin: load plugins with unknown license strings
+         We shouldn't fail to load plugins just because we don't
+         recognise the license string. It's not our job to validate
+         licenses, and the license list is outdated and ambiguous
+         anyway.
+         Also add MPL-2.0 to the list, and fix some defunct license
+         URLs in the code comments.
+         Get rid of the hard-coded skip index, doesn't really buy us
+         much versus just skipping with a few strlens, and is harder
+         to maintain.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/864>
+
+2021-08-02 14:23:58 +0200  Stéphane Cerveau <scerveau@collabora.com>
+
+       * plugins/elements/gstidentity.c:
+         identity: provide a log to check the buffers
+         In order to not rely only on app to display the
+         message from identity, display the message in the logs
+         too.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/863>
+
+2021-08-01 03:36:31 +0900  Seungha Yang <seungha@centricular.com>
+
+       * tests/examples/controller/controller-graph.c:
+         examples: controller-graph: Fix build with MSVC
+         To use macros in math.h, one needs to define _USE_MATH_DEFINES
+         before including the math.h file. Use glib's math define instead.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/862>
+
+2021-05-12 00:54:43 +0900  Seungha Yang <seungha@centricular.com>
+
+       * tools/gst-launch.c:
+       * tools/meson.build:
+         gst-launch: Enable Windows high-resolution clock
+         Default timer precision of Windows is dependent on system, but
+         usually it's known to be about 15ms in worst case.
+         That's not an enough precision for multimedia application.
+         Enable high-resolution clock in gst-launch to demonstrate
+         the usage of Windows high-precision clock for application developers.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/817>
+
+2021-07-23 16:20:20 +0200  Jan Alexander Steffens (heftig) <jan.steffens@ltnglobal.com>
+
+       * plugins/elements/gstinputselector.c:
+         input-selector: Use proper segments when cleaning cached buffers
+         We need to use the segment associated with the cached buffer, not the
+         current segment of the pad, otherwise we miscalculate the running time
+         of cached buffers from before a segment change.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/859>
+
+2021-07-20 09:51:04 +0200  Stéphane Cerveau <scerveau@collabora.com>
+
+       * .gitlab/issue_templates/Bug.md:
+         gitlab: update bug template
+         Finetune the bug description.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/854>
+
+2021-05-09 11:45:49 +0800  Zhao, Gang <gang.zhao.42@gmail.com>
+
+       * gst/gsturi.c:
+         gsturi: Set GError if uri is invalid
+         GError should be set if function call failed and the failed reason is
+         not a programmer error.
+         Fixed: https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/issues/1380
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/816>
+
+2021-05-09 11:13:48 +0800  Zhao, Gang <gang.zhao.42@gmail.com>
+
+       * gst/gsturi.c:
+         gsturi: Don't treat invalid format of uri as critical error
+         Normally uri is get from user input and invalid user input should not
+         be treated as critical error. Moved gst_uri_is_valid outside of
+         g_return_val_if_fail.
+         NULL uri is checked inside of gst_uri_is_valid and is correctly
+         treated as critical error, removed unneeded checks of NULL uri outside
+         of gst_uri_is_valid function.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/816>
+
+2021-07-20 16:52:12 +0900  Seungha Yang <seungha@centricular.com>
+
+       * gst/gstsystemclock.c:
+         systemclock: Restore default clock mode to monotonic for non-linux system
+         Before the MR https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/829
+         Windows and macOS system clock used monotonic clock regardless of
+         selected clock mode. And because of clock resolution, we should prefer
+         monotonic over realtime unless realtime clock is selected explicitly.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/855>
+
+2021-07-07 20:11:13 +0900  Seungha Yang <seungha@centricular.com>
+
+       * libs/gst/base/gstbasesink.c:
+         basesink: Don't swap rstart/rstop when stepping
+         Step handling is implemented based on unmodified start/stop
+         segment running time, and basesink takes rate into account for
+         stepping. This commit is partially undoing new behavior introduced by
+         the commit of 39b9cc554c960fec8d41f8394c41390883cadeed when stepping.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/848>
+
+2021-07-19 20:04:16 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * libs/gst/net/gstptpclock.c:
+         gstptpclock: Don't leak the GList
+         120 bytes in 5 blocks are definitely lost in loss record 7,615 of 9,510
+         at 0x484486F: malloc (vg_replace_malloc.c:380)
+         by 0x58A2938: g_malloc (gmem.c:106)
+         by 0x58BA1F4: g_slice_alloc (gslice.c:1069)
+         by 0x588F059: g_list_prepend (glist.c:335)
+         by 0x5B9C5C0: select_best_master_clock (gstptpclock.c:756)
+         by 0x5B9CA8E: cleanup_cb (gstptpclock.c:1930)
+         by 0x589AD20: g_timeout_dispatch (gmain.c:4889)
+         by 0x589A4CE: UnknownInlinedFun (gmain.c:3337)
+         by 0x589A4CE: g_main_context_dispatch (gmain.c:4055)
+         by 0x58EE4E7: g_main_context_iterate.constprop.0 (gmain.c:4131)
+         by 0x5899A92: g_main_loop_run (gmain.c:4329)
+         by 0x5B9BA4C: ptp_helper_main (gstptpclock.c:1980)
+         by 0x58C8C31: g_thread_proxy (gthread.c:826)
+         576 bytes in 24 blocks are definitely lost in loss record 8,782 of 9,510
+         at 0x484486F: malloc (vg_replace_malloc.c:380)
+         by 0x58A2938: g_malloc (gmem.c:106)
+         by 0x58BA1F4: g_slice_alloc (gslice.c:1069)
+         by 0x588F059: g_list_prepend (glist.c:335)
+         by 0x5B9C5C0: select_best_master_clock (gstptpclock.c:756)
+         by 0x5B9EFA0: handle_announce_message (gstptpclock.c:934)
+         by 0x5B9EFA0: handle_ptp_message (gstptpclock.c:1765)
+         by 0x5B9EFA0: have_stdin_data_cb (gstptpclock.c:1851)
+         by 0x589A4CE: UnknownInlinedFun (gmain.c:3337)
+         by 0x589A4CE: g_main_context_dispatch (gmain.c:4055)
+         by 0x58EE4E7: g_main_context_iterate.constprop.0 (gmain.c:4131)
+         by 0x5899A92: g_main_loop_run (gmain.c:4329)
+         by 0x5B9BA4C: ptp_helper_main (gstptpclock.c:1980)
+         by 0x58C8C31: g_thread_proxy (gthread.c:826)
+         by 0x5DA4298: start_thread (pthread_create.c:481)
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/852>
+
+2021-07-06 13:04:04 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * gst/gstpad.c:
+         gstpad: Don't spam INFO when default-chaining a buffer list
+         This is being logged for each buffer, so it should not use INFO.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/853>
+
+2021-06-15 10:23:33 +0200  Stéphane Cerveau <scerveau@collabora.com>
+
+       * .gitlab/issue_templates/Bug.md:
+         gitlab: add bug template
+         To clarify what is expected in an issue description and avoid
+         issue which is just an usage issue, add a bug template in gitlab.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/836>
+
+2021-07-08 11:48:58 +0200  Kasper Steensig Jensen <kasper.steensig@gmail.com>
+
+       * meson_options.txt:
+         Add meson description for tracer_hooks
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/849>
+
+2020-05-28 08:06:59 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstinfo.c:
+         gstinfo: Improve usage of libdw for backtraces
+         When getting backtraces, we were always creating a new Dwfl context and then
+         discarding it. The problem with that is that it resulted in having to re-scan a
+         lot of information for every single backtrace.
+         In order to fix that issue, use a global on-demand Dwfl context and use it with
+         a lock.
+         Furthermore, we were scanning the mappings of the
+         process (dwfl_linux_proc_report) for *every single step* in the backtrace, and
+         that function is horrendously expensive (does sscanf on /proc/PID/maps
+         ...). While there is a possibility that new mappings might be available (new
+         plugins being loaded for example), we can limit ourselves to just do it once per
+         backtrace.
+         These two modifications speed up the elements_leaks unit test (which traces all
+         pads with full backtraces) by a factor of 6.
+         Partially fixes #567
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/504>
+
+2021-07-02 01:59:18 +1000  Jan Schmidt <jan@centricular.com>
+
+       * gst/parse/grammar.y.in:
+         parse: Fix a critical when using the : operator.
+         Fix "has no handler with id" output criticals when the :
+         multilink operator is used. These were caused by disconnecting
+         a signal handler multiple times.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/846>
+
+2021-06-24 11:28:28 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstbasesink.c:
+       * tests/check/gst/gstbin.c:
+       * tests/check/pipelines/cleanup.c:
+       * tests/check/pipelines/simple-launch-lines.c:
+         basesink: Post a latency message whenever we're ready to answer the query
+         Usually the latency message is only posted whenever latency of an
+         element changes but that might be too early as the sinks might not be
+         able to query the latency at that point yet.
+         Similarly adding a new sink should cause latency reconfiguration once
+         that new sink is able to report its latency.
+         This fixes latency configuration in pipelines where webrtcbin is the
+         only "sink", i.e. it is used in a sendonly session. Before, the latency
+         would always be configured to 0.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/843>
+
+2021-06-24 10:00:28 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: Print segments with GST_SEGMENT_FORMAT and not GST_PTR_FORMAT
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/842>
+
+2021-06-22 13:02:41 +0200  Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
+
+       * gst/gstpreset.c:
+       * gst/gstregistry.c:
+         Fix GI annotations.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/840>
+
+2021-06-15 08:10:16 +0000  Corentin Damman <c.damman@intopix.com>
+
+       * COPYING:
+         Update COPYING to LGPL 2.1
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/835>
+
+2021-06-09 02:35:00 +1000  Jan Schmidt <jan@centricular.com>
+
+       * gst/parse/grammar.y.in:
+         parse: Don't do delayed property setting for top-level properties.
+         If a property is supplied to gst-launch-1.0 to set on a property that
+         implements GstChildProxy, it would always accept any property name
+         and try to set it later. This means that (for example) decodebin
+         will accept and not complain about property names that can never exist like:
+         gst-launch-1.0 videotestsrc ! decodebin NON-EXISTING_PROPERTY=adsfdasf ! fakesink
+         Instead, only try to do deferred property setting for property names
+         that contain the :: separator that indicates it's a setting on a child
+         that might appear later.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/832>
+
+2021-06-16 11:59:20 +0200  François Laignel <fengalin@free.fr>
+
+       * gst/gstclock.c:
+       * gst/gstcontrolbinding.c:
+       * gst/gstcontrolsource.c:
+       * gst/gstelement.c:
+       * gst/gstevent.c:
+       * gst/gstmessage.c:
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/check/gstharness.c:
+         Check mandatory ClockTime arguments
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/837>
+
+2021-04-23 12:12:58 -0400  Doug Nazar <nazard@nazar.ca>
+
+       * gst/glib-compat-private.h:
+       * gst/gstregistrychunks.c:
+       * libs/gst/base/gstbitwriter.c:
+       * libs/gst/base/gstbytereader.c:
+       * libs/gst/base/gstbytereader.h:
+       * libs/gst/base/gstbytewriter.c:
+       * libs/gst/base/gstindex.c:
+       * tests/check/libs/bitwriter.c:
+       * tests/check/libs/bytereader.c:
+       * tests/check/libs/bytewriter.c:
+         Use g_memdup2() where available and add fallback for older GLib versions
+         glib 2.68 deprecates g_memdup(). Replace with g_memdup2() and
+         add fallback if compiling against older versions, since we
+         want to avoid deprecation warnings.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/803>
+
+2021-06-07 09:29:58 +0000  Alba Mendez <me@alba.sh>
+
+       * libs/gst/base/gstbasetransform.h:
+         introspection: annotate ownership in more vfuncs
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/831>
+
+2021-06-03 23:46:06 +0000  Alba Mendez <me@alba.sh>
+
+       * gst/gstbin.h:
+         introspection: annotate handle_message ownership
+         (fixup/improvement to !747) Correct the ownership
+         annotation for `message` in the `handle_message` vfunc,
+         and remove the equivalent phrase elsewhere (following
+         rules of !747.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/830>
+
+2021-05-25 13:26:11 +0200  Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+       * plugins/tracers/gstleaks.c:
+         tracers: leaks: log when tracer is exiting
+         Useful when debugging leaks to make sure that the tracer is properly
+         finalized (gst_deinit() being actually called, etc).
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/828>
+
+2021-06-01 15:28:13 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * meson.build:
+         Back to development
+
+=== release 1.19.1 ===
+
+2021-06-01 00:07:53 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * ChangeLog:
+       * NEWS:
+       * README:
+       * RELEASE:
+       * gstreamer.doap:
+       * meson.build:
+         Release 1.19.1
+
+2021-05-27 16:01:17 -0500  tyler-aicradle <tyler@safex.ai>
+
+       * gst/gstsystemclock.c:
+         systemclock: fall back to g_get_monotonic_time
+         This allows us to cover the case where we're on some unknown system that
+         doesn't have a known native precision monotonic time source. Sadly this
+         reintroduces some of the complexity removed in previous commits.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/829>
+
+2021-05-27 09:44:29 -0500  tyler-aicradle <tyler@safex.ai>
+
+       * gst/gstsystemclock.c:
+         systemclock: reorg real and mono time functions for macOS and win32
+         This simplifies the pre-processor checks a little to make it easier to
+         follow the code.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/829>
+
+2021-05-26 14:55:55 -0500  tyler-aicradle <tyler@safex.ai>
+
+       * gst/gstsystemclock.c:
+         systemclock: Use g_get_real_time on Windows and macOS for realtime clock
+         These targets previously were unable to produce wall clock times when
+         using GstSystemClock, this change makes it possible.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/829>
+
+2021-05-26 12:55:42 -0500  tyler-aicradle <tyler@safex.ai>
+
+       * gst/gstsystemclock.c:
+         systemclock: Reorganize defined checks for parts of GstSystemClock
+         The gst_system_clock_get_internal_time and
+         gst_system_clock_get_resolution functions had some nested defined checks
+         making this code somewhat harder to reason about and much harder to
+         change. The logical meaning of the checks has changed but the actual
+         code coming out of the pre-processor should not have changed
+         significantly. The main logical change was flattening the checks for
+         existence of posix timing functionality, from what I can tell these
+         functions aren't available on Windows where they were trying to be
+         included. I have checked the Linux and macOS output and they are
+         functionally unchanged.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/829>
+
+2021-05-24 18:27:08 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * tests/check/gst/gstbuffer.c:
+         buffer: rename new gst_buffer_new_copy() to gst_buffer_new_memdup()
+         https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/826
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/827>
+
+2021-05-22 19:32:55 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * tests/check/gst/gstbuffer.c:
+         buffer: add gst_buffer_new_copy() convenience function
+         More convenient and discoverable variant of the fairly widely-used
+         gst_buffer_new_wrapped(g_memdup(data,size),size).
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/826>
+
+2021-05-16 02:10:55 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * docs/random/API:
+       * docs/random/LICENSE:
+       * docs/random/TODO-pre-0.9:
+       * docs/random/autoplug1:
+       * docs/random/autoplug2:
+       * docs/random/bbb/streamselection:
+       * docs/random/bbb/subtitles:
+       * docs/random/buffers:
+       * docs/random/caps:
+       * docs/random/caps.dia:
+       * docs/random/caps2:
+       * docs/random/classes.dia:
+       * docs/random/ds/0.9-planning:
+       * docs/random/ds/buffer_locking:
+       * docs/random/ds/bufferpools:
+       * docs/random/ds/categories:
+       * docs/random/ds/element-checklist:
+       * docs/random/ds/registry:
+       * docs/random/ds/roadmap:
+       * docs/random/ensonic/audiobaseclasses.txt:
+       * docs/random/ensonic/dparams.txt:
+       * docs/random/ensonic/draft-registry-change-hooks.txt:
+       * docs/random/ensonic/dynlink.txt:
+       * docs/random/ensonic/interfaces.txt:
+       * docs/random/ensonic/lazycaps.txt:
+       * docs/random/ensonic/logging.txt:
+       * docs/random/ensonic/media-device-daemon.txt:
+       * docs/random/ensonic/plugindocs.txt:
+       * docs/random/ensonic/receipies.txt:
+       * docs/random/eos:
+       * docs/random/error:
+       * docs/random/example:
+       * docs/random/hierarchy:
+       * docs/random/interfaces:
+       * docs/random/metadata:
+       * docs/random/mutability:
+       * docs/random/negotiation:
+       * docs/random/omega/EOS/chain-walkthrough:
+       * docs/random/omega/IDEAS:
+       * docs/random/omega/TODO-0.1.0:
+       * docs/random/omega/TYPE_FOURCC:
+       * docs/random/omega/build/TODO:
+       * docs/random/omega/caps2:
+       * docs/random/omega/caps3:
+       * docs/random/omega/debug-commit:
+       * docs/random/omega/eos.old:
+       * docs/random/omega/filterfactory:
+       * docs/random/omega/output_policies:
+       * docs/random/omega/pad-negotiation:
+       * docs/random/omega/padtemplates:
+       * docs/random/omega/plan-generation:
+       * docs/random/omega/sched-case:
+       * docs/random/omega/sched-commit1:
+       * docs/random/omega/sched/chains:
+       * docs/random/omega/sched/walkthrough-72:
+       * docs/random/omega/sched2:
+       * docs/random/omega/scheduling:
+       * docs/random/omega/testing/Makefile:
+       * docs/random/omega/testing/framework:
+       * docs/random/omega/testing/gstobject.c:
+       * docs/random/omega/testing/gstobject.txt:
+       * docs/random/omega/type-properties:
+       * docs/random/phonon-gst:
+       * docs/random/plugins:
+       * docs/random/plugins.dia:
+       * docs/random/porting-to-0.11.txt:
+       * docs/random/queue:
+       * docs/random/richardb/syncmail:
+       * docs/random/rtp:
+       * docs/random/signal:
+       * docs/random/sources:
+       * docs/random/status-0.11-14-jun-2011.txt:
+       * docs/random/styleguide:
+       * docs/random/testing/syntax:
+       * docs/random/thaytan/opengl:
+       * docs/random/thaytan/video-overlays:
+       * docs/random/thomasvs/0.10:
+       * docs/random/thomasvs/0.4.0:
+       * docs/random/thomasvs/TODO:
+       * docs/random/thomasvs/docreview:
+       * docs/random/thomasvs/features:
+       * docs/random/thomasvs/guadec-4:
+       * docs/random/thomasvs/pthread:
+       * docs/random/thomasvs/pwg:
+       * docs/random/thomasvs/registry:
+       * docs/random/types:
+       * docs/random/types2:
+       * docs/random/types3:
+       * docs/random/use-cases-0.11.txt:
+       * docs/random/usecases:
+       * docs/random/vis-transform:
+       * docs/random/wingo/porting-plugins-to-0.9:
+       * docs/random/wingo/threadsafe-properties:
+       * docs/random/wingo/without-factories:
+       * docs/random/zaheerm/dvb-interface.txt:
+         docs: random: clean up outdated documents
+         Most of these are only of historical interest, and for that it's
+         fine if they're maintained in the git history. They're confusing
+         for anyone stumbling across them expecting documentation relating
+         to current versions of GStreamer.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/824>
+
+2021-05-11 21:16:01 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * plugins/elements/gstconcat.c:
+         concat: adjust running time offsets on events
+         When concat adjusts the base of the segments it forwards
+         downstream, it needs to also adjust the running time offsets,
+         as GstPad does when an offset is set by the application on a pad.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/819>
+
+2021-05-05 15:45:40 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+       * libs/gst/base/gstaggregator.c:
+       * 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:
+         doc: base: Fix reference to virtual function
+         The hotdoc syntax is #ClassName::function, but the code was using
+         without anything before.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/808>
+
+2021-05-06 13:03:15 -0400  Doug Nazar <nazard@nazar.ca>
+
+       * libs/gst/check/gstcheck.c:
+       * libs/gst/check/libcheck/check.c:
+       * libs/gst/check/libcheck/check_run.c:
+       * libs/gst/check/libcheck/meson.build:
+         gstcheck: Ensure unused threadpool threads are stopped
+         Ensures that all unused threads are exited before the atexit()
+         handlers run.
+         This prevents a race with any thread that used the OpenSSL library
+         between it's thread cleanup routine and it's atexit() cleanup routine
+         which can cause a SIGSEGV.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/812>
+
+2021-05-11 19:02:28 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * plugins/elements/gstconcat.c:
+         concat: fix locking in SEGMENT event handler
+         concat->current_start_offset needs the lock taken for safe access,
+         as it can be accessed from outside of the streaming thread, eg
+         in release_pad.
+         An early break is also added for an error case.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/818>
+
+2021-05-06 23:02:35 -0400  Doug Nazar <nazard@nazar.ca>
+
+       * plugins/elements/gstsparsefile.c:
+         sparsefile: Fix sparsefile on Win32
+         When switching between read/write a fseek() or fflush() is required.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/814>
+
+2021-05-06 23:00:57 -0400  Doug Nazar <nazard@nazar.ca>
+
+       * plugins/elements/gstdownloadbuffer.c:
+         downloadbuffer: close file before trying to remove
+         On Windows, the file handles must be closed before you can delete a file.
+         Also, it would cause an error if you try to close an already closed handle.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/814>
+
+2021-05-06 23:00:07 -0400  Doug Nazar <nazard@nazar.ca>
+
+       * plugins/elements/gstdownloadbuffer.c:
+         downloadbuffer: return flow error on read error
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/814>
+
+2021-05-06 22:20:57 +0300  Nikolay Sivov <nsivov@codeweavers.com>
+
+       * gst/gstutils.c:
+         gstutils: Fix typo in the comment.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/813>
+
+2021-05-06 12:54:46 +0200  Jan Alexander Steffens (heftig) <jan.steffens@ltnglobal.com>
+
+       * plugins/elements/gstmultiqueue.c:
+         multiqueue: Ensure peer pad exists when iterating internal links
+         The pads can be NULL when we're racing with pad removal, e.g. when the
+         pads get removed between `gst_pad_iterate_internal_links` acquiring the
+         parent element and `gst_multi_queue_iterate_internal_links` locking the
+         multiqueue.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/810>
+
+2021-04-02 19:48:26 -0400  Chris White <cxwembedded@gmail.com>
+
+       * gst/gstchildproxy.c:
+         gst_child_proxy_get_property: accept G_VALUE_INIT
+         gst_child_proxy_get_property() can now take a value initialized to
+         G_VALUE_INIT.  This parallels the corresponding change in
+         g_object_get_property(), GLib 2.60+.
+         https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/724#note_738531
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/809>
+
+2021-04-22 17:53:44 +0200  François Laignel <fengalin@free.fr>
+
+       * gst/gstelement.c:
+       * gst/gstelement.h:
+       * gst/gstpadtemplate.c:
+       * gst/gstutils.c:
+       * libs/gst/check/gstcheck.c:
+       * libs/gst/check/gstharness.c:
+       * tests/check/elements/concat.c:
+       * tests/check/elements/funnel.c:
+       * tests/check/elements/multiqueue.c:
+       * tests/check/elements/selector.c:
+       * tests/check/elements/tee.c:
+       * tests/check/gst/gstelement.c:
+       * tests/check/gst/gstutils.c:
+       * tests/check/libs/aggregator.c:
+       * tests/check/libs/collectpads.c:
+       * tests/examples/streamiddemux/streamiddemux-stream.c:
+         Introduce gst_element_request_pad_simple
+         The name `gst_element_get_request_pad()` is confusing to people
+         learning GStreamer. `gst_element_request_pad_simple()` aims at
+         providing the exact same functionality, while making it more
+         explicit it is a simplified `gst_element_request_pad()`.
+         `gst_element_request_pad_simple()` is consistent with other
+         functions such as `gst_element_seek_simple`.
+         This commit deprecates `gst_element_get_request_pad()` so that a
+         compilation warning is emitted when used and incite developers
+         to use the more explicit `gst_element_request_pad_simple()`.
+         See also https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/743#note_886586
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/802>
+
+2021-04-20 23:54:52 -0400  Doug Nazar <nazard@nazar.ca>
+
+       * libs/gst/check/gstharness.c:
+         harness: Fix object used to log caps warning.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/801>
+
+2021-04-16 11:14:31 +0200  Miguel Paris <mparisdiaz@gmail.com>
+
+       * gst/gstpad.c:
+         pad: clear probes holding mutex
+         Protect clearing probes against concurrent modification which might happen
+         due to dispose does NOT guarantee that the object is not used anymore, as
+         it could be referenced again and so being continued used.
+         So, as in the rest of places where probes hook list is used, on dispose
+         it should be accessed holding the mutex "GST_OBJECT_LOCK (pad);" as
+         GHookList is not thread-safe.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/798>
+
+2021-04-16 11:36:33 +0200  Edward Hervey <edward@centricular.com>
+
+       * plugins/elements/gstqueue2.c:
+         queue2: Refuse all serialized queries when posting buffering messages
+         When posting buffering messages there are no safe places or timing to avoid
+         deadlocks.
+         Previously the code was trying to be "smart" by only forwarding serialized
+         queries if the queue was empty ... but that could happen when queue2 hadn't yet
+         posted a 100% buffering message. Meaning the pipeline might be paused and
+         pushing a serialized query downstream might never complete.
+         Therefore let's completely disable forwarding of serialized queries when
+         `queue2` is used as a buffering element (meaning `ALLOCATION` and `DRAIN`
+         queries).
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/796>
+
+2021-04-11 08:23:27 -0400  Doug Nazar <nazard@nazar.ca>
+
+       * tests/check/gst/gstpad.c:
+         tests: Remove invalid buffer test in test_get_allowed_caps.
+         Passing a non-GObject pointer causes SIGSEGV on certain architectures.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/790>
+
+2021-04-11 10:24:01 -0400  Doug Nazar <nazard@nazar.ca>
+
+       * plugins/tracers/gstleaks.c:
+         leaks: Fix SIGSEGV detecting object type.
+         G_IS_OBJECT & GST_IS_OBJECT work by following pointers which is unsafe
+         on certain architectures. GstMiniObject detection however does a lookup
+         to see if it's a valid type derived from G_TYPE_BOXED.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/791>
+
+2021-04-10 10:46:28 -0400  Chris White <cxwembedded@gmail.com>
+
+       * gst/gstallocator.c:
+       * gst/gstallocator.h:
+         allocator: add gst_allocation_params_new()
+         This permits creating GstAllocationParams instances on the heap, which
+         is useful for language bindings that can handle GBoxed types.
+         https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/683
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/788>
+
+2021-04-07 04:46:23 -0400  Doug Nazar <nazard@nazar.ca>
+
+       * plugins/elements/gstclocksync.c:
+         clocksync: Fix providing system clock by default
+         clocksync defaults to sync=true so should advertise it by default.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/786>
+
+2020-10-10 19:09:03 +0000  Jose Quaresma <quaresma.jose@gmail.com>
+
+       * gst/gstpluginloader.c:
+         gstpluginloader: when env var is set do not fall through to system plugin scanner
+         If we set a custom GST_PLUGIN_SCANNER env var, then we probably want to use that and only that.
+         Falling through to the one installed on the system is problamatic in cross-compilation
+         environemnts, regardless of whether one pointed to by the env var succeeded or failed.
+         taken from:
+         http://cgit.openembedded.org/openembedded-core/commit/meta/recipes-multimedia/gstreamer/gstreamer1.0/0001-gst-gstpluginloader.c-when-env-var-is-set-do-not-fal.patch?id=0db7ba34ca41b107042306d13a6f0162885c123b
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/669>
+
+2021-03-19 13:46:13 +0100  Jan Alexander Steffens (heftig) <jan.steffens@ltnglobal.com>
+
+       * tools/gst-inspect-1.0.1:
+       * tools/gst-inspect.c:
+         gst-inspect: Allow overriding DEFAULT_LESS_OPTS with GST_LESS
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/777>
+
+2021-04-06 20:56:55 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+       * tests/check/libs/aggregator.c:
+         aggregator: Release pads' peeked buffer when removing the pad or finalizing it
+         The peeked buffer was always reset after calling ::aggregate() but under
+         no other circumstances. If a pad was removed after peeking and before
+         ::aggregate() returned then the peeked buffer would be leaked.
+         This can easily happen if pads are removed from the aggregator from a
+         pad probe downstream of the source pad but still in the source pad's
+         streaming thread.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/784>
+
+2021-03-30 20:24:07 -0400  Chris White <cxwembedded@gmail.com>
+
+       * gst/gstcapsfeatures.c:
+       * gst/gstcapsfeatures.h:
+         caps: Add gst_caps_features_new_single()
+         For use with a single feature now that gst_caps_features_new() is
+         G_GNUC_NULL_TERMINATED.
+         https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/774#note_855357
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/774>
+
+2021-03-27 17:10:06 -0400  Chris White <cxwembedded@gmail.com>
+
+       * gst/gsttypefind.c:
+       * gst/gsttypefind.h:
+         typefind: add gst_type_find_suggest_empty_simple()
+         For cases where you only need a media type and no other fields.
+         https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/774#note_848664
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/774>
+
+2021-03-18 19:06:20 -0400  Chris White <cxwembedded@gmail.com>
+
+       * gst/gstcapsfeatures.h:
+       * gst/gstelement.c:
+       * gst/gstelement.h:
+       * gst/gsttaglist.h:
+       * gst/gsttracerrecord.c:
+       * gst/gsttracerrecord.h:
+       * gst/gsttypefind.h:
+       * libs/gst/check/gstharness.h:
+         gst: Add missing G_GNUC_NULL_TERMINATED markers
+         Functions that require NULL as their last vararg are marked so the
+         compiler can warn on missing NULL.
+         Also, document the NULL terminator for gst_make_element_message_details()
+         and gst_tracer_record_new().
+         https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/669
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/774>
+
+2021-03-31 21:13:45 +0200  Pieter Willem Jordaan <pieterwjordaanpc@gmail.com>
+
+       * gst/gstsystemclock.c:
+         systemclock: Fix deadlock on clock_nanosleep
+         Always use the monotonic clock's diff and end time for clock_nanosleep to have predictable behaviour even with other clock types.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/779>
+
+2021-03-26 21:00:54 +0000  Jason Carrete <jasoncarrete5@gmail.com>
+
+       * tools/gst-launch-1.0.1:
+         Update gst-launch-1.0.1
+         Fixed a small typo in the gst-launch-1.0 man page
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/780>
+
+2021-03-19 10:33:13 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstbin.c:
+         bin: Don't special-case G_SIGNAL_RUN_CLEANUP stage in latency signal accumulator
+         This signal don't run the class handler in the CLEANUP stage.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/776>
+
+2019-08-11 19:13:57 -0400  Aaron Boxer <aaron.boxer@collabora.com>
+
+       * gst/gst.c:
+       * tests/check/gst/gst.c:
+         gst: enforce gst_deinit one call per process
+         unit tests do not need to call deinit as it is already called in exit handler
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/236>
+
+2019-08-11 14:20:42 -0400  Aaron Boxer <aaron.boxer@collabora.com>
+
+       * gst/gst.c:
+         gst: disable indent for  parse_goption_arg
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/236>
+
+2021-03-17 16:39:30 +0100  Stéphane Cerveau <scerveau@collabora.com>
+
+       * gst/gstdeviceprovider.h:
+         device provider: add custom register macro
+         This macro allows to register a device provider with
+         a custom function which gives more flexibility when
+         registering it (see v4l2 register).
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/773>
+
+2021-03-18 14:46:15 +1100  Matthew Waters <matthew@centricular.com>
+
+       * gst/gstatomicqueue.c:
+       * gst/gstbuffer.c:
+       * gst/gstchildproxy.c:
+       * gst/gstdeviceprovider.c:
+       * gst/gstelement.c:
+       * gst/gstinfo.c:
+       * gst/gstparamspecs.c:
+       * gst/gstpluginloader.c:
+       * gst/gstpoll.c:
+       * gst/gstpreset.c:
+       * gst/gstpromise.c:
+       * gst/gstprotection.c:
+       * gst/gsttask.c:
+       * gst/gsturi.c:
+       * gst/gstvalue.c:
+       * libs/gst/base/gstaggregator.c:
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstflowcombiner.c:
+       * libs/gst/check/gstconsistencychecker.c:
+       * libs/gst/check/gstharness.c:
+       * libs/gst/controller/gsttimedvaluecontrolsource.c:
+       * libs/gst/net/gstnetaddressmeta.c:
+       * libs/gst/net/gstnetcontrolmessagemeta.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstqueue2.h:
+       * plugins/elements/gstvalve.h:
+       * tests/check/gst/gstcontroller.c:
+       * tests/check/gst/gstmeta.c:
+       * tests/check/gst/gstminiobject.c:
+       * tests/check/gst/gstobject.c:
+       * tests/check/gst/gstpreset.c:
+       * tests/check/gst/gstprotection.c:
+       * tests/check/gst/gstvalue.c:
+       * tests/check/libs/controller.c:
+       * tests/examples/controller/control-sources.c:
+         gst: don't use volatile to mean atomic
+         volatile is not sufficient to provide atomic guarantees and real atomics
+         should be used instead.  GCC 11 has started warning about using volatile
+         with atomic operations.
+         https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1719
+         Discovered in https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/issues/868
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/775>
+
+2020-11-18 22:32:30 +0900  Seungha Yang <seungha@centricular.com>
+
+       * docs/plugins/gst_plugins_cache.json:
+       * plugins/elements/gstclocksync.c:
+       * plugins/elements/gstclocksync.h:
+       * tests/check/elements/clocksync.c:
+         clocksync: Add a new property "sync-to-first" for automatic ts-offset setup
+         Add a new property so that clocksync can setup "ts-offset" value
+         based on the first buffer and pipeline's running time when the
+         first arrived. Newly update "ts-offset" in this case would be
+         a value that allows outputting the first buffer without clock waiting.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/702>
+
+2021-03-16 19:02:06 -0400  Olivier Crête <olivier.crete@collabora.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: Release the SRC lock while querying latency
+         This is required because the query could be intercepted and the
+         application could send any other requests to the element from this
+         thread.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/771>
+
+2021-03-17 14:06:51 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstvalue.c:
+         value: fix parsing of explicit value casts
+         Since acdb4ce03d525a18f6c351a040b8446c7bbd98bd , parsing of the
+         value for a property can use the pspec to determine what type
+         a value should be casted to.
+         However, this broke the case where the value is explicitly casted
+         to a type (eg <(float) 0.0>). In that situation, we want to respect
+         the casting decision, and only use the pspec to perform "implicit"
+         casts.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/issues/881
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/772>
+
+2021-03-11 15:41:16 +0100  Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+       * gst/gstclock.h:
+         clock: define AUTO_CLEANUP_FREE_FUNC for GstClockID
+         GstClockID is secretly a gpointer so we can't use g_autoptr(),
+         instead user can do:
+         g_auto (GstClockID) clock_id = 0;
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/769>
+
+2021-03-08 10:27:15 +0100  Stéphane Cerveau <scerveau@collabora.com>
+
+       * gst/gstelement.h:
+         element: remove useless ret test
+         The ret test is unrelevant and confusing.
+         We dont want the code to fail and the register
+         to succeed by example.
+         In the case of a conditional element_init,
+         the element should be defined with
+         GST_ELEMENT_REGISTER_DEFINE_CUSTOM instead
+         of GST_ELEMENT_REGISTER_DEFINE_WITH_CODE.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/768>
+
+2021-02-26 10:47:38 +0100  Stéphane Cerveau <scerveau@collabora.com>
+
+       * data/bash-completion/completions/gst-inspect-1.0:
+       * data/bash-completion/completions/gst-launch-1.0:
+       * data/bash-completion/helpers/gst.in:
+         bash-completion: various bash fixes
+         -d tests the folder which is existing but with .in file, so I prefered
+         the -f to test if the gst file was available which is not the case, so
+         it fallbacks on the pkg-config
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/766>
+
+2021-02-26 10:01:56 +0100  Stéphane Cerveau <scerveau@collabora.com>
+
+       * gst/meson.build:
+       * meson.build:
+         meson: add uninstalled var for bash-completion
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/766>
+
+2021-02-24 13:03:47 +0100  Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+       * gst/gstminiobject.c:
+       * gst/gstminiobject.h:
+         miniobject: add GST_TYPE_MINI_OBJECT
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/764>
+
+2021-02-17 18:35:33 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstdebugutils.c:
+       * gst/gstdebugutils.h:
+         docs: standardize debugutils documentation
+         * add a SECTION comment
+         * Misc cleanup / typo fixes / addition of links
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/760>
+
+2021-02-16 16:18:08 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstcontrolsource.h:
+       * gst/gstdatetime.c:
+       * gst/gstdatetime.h:
+         docs: standardize GstControlSource, GstDateTime documentation
+         * Don't repeat what annotations are stating with respect to ownership
+         transfer, nullability
+         * Misc cleanup / typo fixes / addition of links
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/759>
+
+2021-01-21 02:04:25 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/base/gstbaseparse.c:
+         Revert "baseparse: always use incoming DTS"
+         This reverts commit fc5cd9591a3fe09458342cfedfff88d57bc330c7.
+
+2021-02-15 15:06:46 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstcontext.c:
+       * gst/gstcontrolbinding.c:
+       * gst/gstcontrolbinding.h:
+         docs: standardize GstContext, GstControlBinding documentation
+         * Document virtual methods in standalone comments, in order to properly
+         annotate them
+         * Don't repeat what annotations are stating with respect to ownership
+         transfer, nullability
+         * Mark GstControlBinding ABI field as private
+         * Misc cleanup / typo fixes / addition of links
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/758>
 
-2019-12-03 10:57:29 +0000  Tim-Philipp Müller <tim@centricular.com>
+2021-02-12 17:50:21 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstclock.c:
+       * gst/gstclock.h:
+         docs: standardize GstClock documentation
+         * Don't mention explicitly that API is MT safe, this implies that
+         other API is not. GStreamer API is assumed to be MT safe, thread
+         safety should only be explicitly mentioned when API is *not* MT safe
+         * Don't repeat what annotations are stating with respect to ownership
+         transfer, nullability
+         * Document virtual methods in standalone comments, so that parameters
+         can be documented. This is not critical here, as parameters do not
+         need annotations / specific documentation, but serves as an up to
+         date example
+         * Document enumeration members in standalone comments, so that their
+         Since tag is accounted for by gobject-introspection
+         * Misc cleanup / typo fixes / addition of links
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/756>
+
+2021-02-15 09:54:51 +0100  Stéphane Cerveau <scerveau@collabora.com>
+
+       * gst/gstelement.h:
+         features: remove extra G_BEGIN_DECLS/G_END_DECLS
+         _GST_ELEMENT_REGISTER_DEFINE_BEGIN
+         _GST_ELEMENT_REGISTER_DEFINE_END was introducing
+         an extra extern "C" in case of c++ build.
+         Add missing ";" in GST_ELEMENT_REGISTER_DECLARE
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/757>
+
+2021-02-11 16:04:01 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstcapsfeatures.c:
+       * gst/gstchildproxy.c:
+       * gst/gstchildproxy.h:
+         docs: standardize GstCapsFeatures, GstChildProxy documentation
+         * Don't mention explicitly that API is MT safe, this implies that
+         other API is not. GStreamer API is assumed to be MT safe, thread
+         safety should only be explicitly mentioned when API is *not* MT safe
+         * Document virtual methods in standalone comments, in order to properly
+         annotate them
+         * Don't repeat what annotations are stating with respect to ownership
+         transfer, nullability
+         * Misc cleanup / typo fixes / addition of links
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/755>
+
+2021-02-10 14:19:18 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstcaps.c:
+       * gst/gstcaps.h:
+         docs: standardize GstCaps documentation
+         * Don't repeat what annotations are stating with respect to ownership
+         transfer, nullability
+         * Reword the warnings for caps nestability in light of the 1.20
+         improvements
+         * Misc cleanup / typo fixes / addition of links
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/754>
+
+2021-02-10 04:14:48 +1100  Jan Schmidt <jan@centricular.com>
+
+       * tests/check/gst/gstpad.c:
+         tests: Add disjoint pad probe removal test.
+         Add a test that removing a blocking probe on events when there
+         is a different blocking probe on buffers releases the data flow.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/749>
+
+2021-02-06 03:58:54 +1100  Jan Schmidt <jan@centricular.com>
+
+       * gst/gstpad.h:
+         pad: Improve the documentation for GstPadProbeReturn.
+         Explain that GST_PAD_PROBE_PASS will pass data even if there is
+         another pad probe that says to block, and that GST_PAD_PROBE_REMOVE
+         passes data and potentially unblocks the pad.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/749>
+
+2021-02-06 03:41:23 +1100  Jan Schmidt <jan@centricular.com>
+
+       * gst/gstpad.c:
+         pad: Fix for multiple blocking probes interaction.
+         Change the way the marshalled flag in the internal ProbeMarshall state
+         is handled when iterating over pad probes so that it only counts
+         probes that still exist and would be called when retrying.
+         This improves the way that removing a blocking probe works when
+         there are multiple blocking probes for different conditions (data vs
+         events for example).
+         As a side-effect, probes aren't put into the the called_probes array
+         unless they actually match the current probe type and would be called,
+         potentially reducing the number of hooks that get stored in the
+         called_probes array, and the cost of the looping check on retries.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/658
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/749>
+
+2021-02-09 15:30:50 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstbus.c:
+       * gst/gstbus.h:
+         docs: standardize GstBus documentation
+         * Don't mention explicitly that API is MT safe, this implies that
+         other API is not. GStreamer API is assumed to be MT safe, thread
+         safety should only be explicitly mentioned when API is *not* MT safe
+         * Don't repeat what annotations are stating with respect to ownership
+         transfer, nullability
+         * Document virtual methods and the class structure
+         * Misc cleanup / typo fixes / addition of links
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/753>
+
+2021-02-08 15:17:05 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+         docs: standardize GstBufferPool documentation
+         * Don't repeat what annotations are stating with respect to ownership
+         transfer, nullability
+         * Document virtual methods in standalone comments, so that parameters
+         can be documented. This is functionally useful here, as parameters
+         require annotations, and should make the class more usable by
+         bindings.
+         * Misc cleanup / typo fixes / addition of links
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/752>
+
+2021-02-08 14:31:09 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstbufferlist.c:
+       * gst/gstbufferlist.h:
+         docs: standardize GstBufferList documentation
+         * Don't repeat what annotations are stating with respect to ownership
+         transfer, nullability
+         * Misc cleanup / typo fixes / addition of links
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/752>
+
+2021-02-08 13:53:51 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstbuffer.h:
+         docs: fix GST_BUFFER_COPY_DEEP comment title
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/752>
+
+2021-02-05 14:55:37 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstprotection.c:
+         docs: standardize GstBuffer documentation
+         * Don't mention explicitly that API is MT safe, this implies that
+         other API is not. GStreamer API is assumed to be MT safe, thread
+         safety should only be explicitly mentioned when API is *not* MT safe
+         * Don't repeat what annotations are stating with respect to ownership
+         transfer, nullability
+         * Document enumeration members in standalone comments, so that their
+         Since tag is accounted for by gobject-introspection
+         * Misc cleanup / typo fixes / addition of links
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/748>
+
+2021-02-04 16:15:39 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstbin.c:
+       * gst/gstbin.h:
+       * gst/gstutils.c:
+         docs: standardize GstBin documentation
+         * Don't mention explicitly that API is MT safe, this implies that
+         other API is not. GStreamer API is assumed to be MT safe, thread
+         safety should only be explicitly mentioned when API is *not* MT safe
+         * Don't repeat what annotations are stating with respect to ownership
+         transfer, nullability
+         * Document virtual methods in standalone comments, so that parameters
+         can be documented. This is not critical here, as parameters do not
+         need annotations / specific documentation, but serves as an up to
+         date example
+         * Document enumeration members in standalone comments, so that their
+         Since tag is accounted for by gobject-introspection
+         * Misc cleanup / typo fixes / addition of links
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/747>
+
+2021-02-04 15:18:04 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstbin.c:
+         docs: reformat and cleanup GstBin SECTION comment
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/747>
+
+2021-02-02 16:41:28 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstallocator.c:
+         docs: clean up GstAllocator documentation
+         In particular, there is no need to explicitly mention free
+         functions / ownership transfers, this should be obvious from
+         the annotations.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/745>
+
+2021-02-02 16:34:03 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstallocator.c:
+         docs: sort GstAllocator doc so that GstAllocator appears first
+         The default ordering is alphabetical, causing GstAllocationParams
+         to appear first in the page if left auto-sorted
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/745>
+
+2021-02-02 16:19:46 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gst.c:
+       * gst/gst.h:
+         docs: cleanup gst.c documentation
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/745>
+
+2021-01-29 23:07:34 +0900  Seungha Yang <seungha@centricular.com>
+
+       * plugins/elements/gstfilesink.c:
+       * plugins/elements/gstfilesrc.c:
+         filesrc/filesink: Use g_open/g_fopen and g_close instead of ours
+         There should be no more cross-CRT issue on Windows since we bumped
+         MinGW toolchain
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/744>
+
+2021-01-31 12:12:09 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstinfo.c:
+         info: Don't leak log function user_data if the debug system is compiled out
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/742>
+
+2021-01-25 22:51:33 +0100  Aleksandr Slobodeniuk <aslobodeniuk@fluendo.com>
+
+       * gst/gstvalue.h:
+         gstvalue: fix compilation warning in "holds" macros
+         GST_VALUE_HOLDS_... macros may cause -Waddress warning
+         on gcc if GValue is allocated on stack:
+         gstvalue.h:145:46: warning: the comparison will always
+         evaluate as ‘true’ for the address of ‘v’ will never
+         be NULL [-Waddress]
+         #define GST_VALUE_HOLDS_CAPS(x)         ((x) != NULL &&
+         G_VALUE_TYPE(x) == _gst_caps_type)
+         Fixes #653
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/738>
+
+2020-12-24 14:06:29 -0500  Chris White <cxwembedded@gmail.com>
+
+       * tests/check/gst/gststructure.c:
+         structure: add tests of deserializing strings with escapes
+         Shows the issue described in
+         <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/303#note_272629>
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/303>
+
+2019-10-28 18:06:14 +0000  Henry Wilkes <hwilkes@igalia.com>
+
+       * gst/gstvalue.c:
+         gstvalue: preserve parse behaviour with warning
+         Preserve the previous behaviour where:
+         name, val="5";
+         passed to gst_structure_from_string would have resulted in an int value,
+         rather than a string, despite the quote marks.
+         This will be changed to being interpreted as a string in the future, but
+         for the time being we will issue a warning about this to give users time
+         to fix their code to no longer rely on this bug.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/303>
+
+2019-10-23 12:48:32 +0100  Henry Wilkes <hwilkes@igalia.com>
+
+       * gst/gstvalue.c:
+       * tests/check/gst/gstvalue.c:
+         gstvalue: make gst_string_unwrap less strict
+         Allow a string in gst_string_unwrap to include unescaped characters that
+         are not in GST_STRING_IS_ASCII. This extra leniency allows
+         gst_structure_from_string to, e.g., receive
+         name, val=(string)"string with space";
+         Note that many gst tests, and potentially users, exploited this behaviour
+         by giving
+         name, val="string with space";
+         i.e. without the (string) type specifier. This was allowed before
+         because, without a type specifier, the string was passed to
+         _priv_gst_value_parse_string with unescape set to TRUE, *rather* than
+         being sent to gst_string_unwrap. This caused a difference in behaviour
+         between strings that are or are not preceded by (string). E.g.
+         name, val=(string)"string with space";
+         would fail, whilst
+         name, val="string with space";
+         would not. And
+         name, val=(string)"\316\261";
+         would produce a val="α", whereas
+         name, val=(string)"\316\261";
+         would produce a val="316261" (a bug).
+         The current behaviour is to treat both of these cases the same, which is
+         desirable. But in order to not break potentially common usage of this
+         discrepancy (it was in our own tests), the best option is to make string
+         parsing less strict in general.
+         New behaviour would be for
+         name, val=(string)"string with space";
+         to pass and give val="string with space", and
+         name, val="\316\261";
+         would produce a val="α".
+         Also changed deserializing string test to expect successes where
+         previously a failure was expected.
+         In a similar way, this also effected the deserializing of GstStructure,
+         GstCaps, GstTagList and GstCapsFeatures. So, now
+         name, val=(structure)"sub-name, sub-val=(string)\"a: \\316\\261\";";
+         will also pass and give sub-val="a: α". Note that the quote marks
+         and backslash still need to be escaped for the sub-structure, but other
+         characters need not be.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/303>
+
+2019-10-18 23:11:44 +0100  Henry Wilkes <hwilkes@igalia.com>
+
+       * tests/check/gst/gstvalue.c:
+         value: add serialize-deserialize tests
+         Added tests to ensure that the gst_value_deserialize reverses
+         gst_value_serialize.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/303>
+
+2019-10-18 13:00:33 +0100  Henry Wilkes <hwilkes@igalia.com>
+
+       * gst/gstvalue.c:
+       * tests/check/gst/gstvalue.c:
+         structure: don't unescape values before deserializing
+         No longer call _priv_gst_value_parse_string with unescape set to TRUE
+         before passing a value to gst_value_deserialize in
+         _priv_gst_value_parse_value. This latter function is called by
+         gst_structure_from_string and gst_caps_from_string.
+         When gst_structure_to_string and gst_caps_to_string are called, no
+         escaping is performed after calling gst_value_serialize. Therefore, by
+         unescaping the value string, we were introducing an additional operation
+         that was not performed by the original *_to_string functions. In
+         particular, this has meant that the derialization functions for many
+         non-basic types are incomplete reverses of the corresponding
+         serialization function (i.e., if you pipe the output of the
+         serialization function into the deserialization function it could fail)
+         because they have to compensate for this additional escaping operation,
+         when really this should be the domain of the deserialization functions
+         instead.
+         Correspondingly changed a few deserialization functions.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/452
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/303>
+
+2021-01-15 01:16:34 +0900  Seungha Yang <seungha@centricular.com>
+
+       * gst/gsttask.c:
+         task: Use SetThreadDescription Win32 API for setting thread name
+         Since Windows 10 1607, we can make use of SetThreadDescription() API
+         for setting thread name. Unlike previously used exception based
+         method, this API will preserve configured thread name on dump file.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/735>
+
+2021-01-14 15:50:05 +0100  Jan Alexander Steffens (heftig) <jan.steffens@ltnglobal.com>
+
+       * tests/check/gst/gstsystemclock.c:
+         tests: systemclock: Stop all stress threads before joining them
+         This reduces the chance of the main thread getting starved while trying
+         to shut down the test, potentially causing a timeout.
+         Even on an idle 96-processor system this reduces the duration of the
+         systemclock tests from ~8s to ~3s.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/734>
+
+2021-01-14 10:18:51 +0100  Marijn Suijten <marijns95@gmail.com>
+
+       * gst/gstmemory.c:
+         gstmemory: Mark memory_map @info as `caller-allocates`
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/730>
+
+2021-01-14 10:20:41 +0100  Marijn Suijten <marijns95@gmail.com>
+
+       * gst/gstbuffer.c:
+         gstbuffer: Mark buffer_map* @info as `caller-allocates`
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/730>
+
+2021-01-07 09:53:41 +0100  Marijn Suijten <marijns95@gmail.com>
+
+       * libs/gst/base/gstaggregator.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+         gst,base: Take GstAllocationParams parameter by const ptr
+         This parameter is only informational and should not be modified. Enforce
+         this at compile-time and to get the right signature in G-IR.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/730>
+
+2021-01-13 03:01:57 +0900  Seungha Yang <seungha@centricular.com>
+
+       * gst/gsturi.h:
+         uri: Remove leftover documentation
+         Follow-up from https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/728
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/732>
+
+2021-01-08 20:23:23 +0900  Seungha Yang <seungha@centricular.com>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstbufferlist.c:
+       * gst/gstbufferlist.h:
+       * gst/gstcaps.c:
+       * gst/gstcaps.h:
+       * gst/gstcontext.c:
+       * gst/gstcontext.h:
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+       * gst/gstmessage.c:
+       * gst/gstmessage.h:
+       * gst/gstpromise.c:
+       * gst/gstpromise.h:
+       * gst/gstquery.c:
+       * gst/gstquery.h:
+       * gst/gstsample.c:
+       * gst/gstsample.h:
+       * gst/gsttaglist.c:
+       * gst/gsttaglist.h:
+       * gst/gsturi.c:
+       * gst/gsturi.h:
+       * gst/meson.build:
+         gst: Add non-inline methods for bindings to able to use core APIs
+         Provide non-inline version of refcounting APIs so that it can be
+         consumed by bindings
+         Fixes: https://gitlab.freedesktop.org/gstreamer/gstreamer-sharp/-/issues/46
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/728>
+
+2021-01-07 11:04:48 +0000  Philippe Normand <philn@igalia.com>
+
+       * docs/plugins/gst_plugins_cache.json:
+       * plugins/elements/gstconcat.c:
+         concat: Fix active-pad property doc typo
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/727>
+
+2020-12-24 00:40:33 +0700  Dmitry Samoylov <dmitry.samoylov@quantumsoft.ru>
+
+       * gst/gstvalue.c:
+         gst: Fix doc comments
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/725>
+
+2020-10-23 17:44:10 +0200  Michael Tretter <m.tretter@pengutronix.de>
+
+       * gst/gstpipeline.c:
+         pipeline: clarify that applications should handle bus messages
+         The pipeline posts messages on the bus even if an application does not
+         handle the messages. This is expected behavior but may leak messages if
+         the messages are not handled.
+         Clarify the documentation.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/680>
+
+2020-12-12 22:28:46 +0000  Fredrik Pålsson <fredrik.palsson@isg.se>
+
+       * gst/gstbus.c:
+         gstbus: change log level of repeated messages from INFO to DEBUG
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/722>
+
+2020-12-11 16:01:27 +0100  Jakub Adam <jakub.adam@collabora.com>
+
+       * libs/gst/check/gstharness.c:
+         harness: don't use GST_DEBUG_OBJECT with GstHarness
+         GstHarness is not a GObject. Fixes assert on recently added check in
+         gst_debug_log_valist() if GST_ENABLE_EXTRA_CHECKS is enabled.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/720>
+
+2020-12-10 15:48:32 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gstbus.c:
+       * tests/check/gst/gstbus.c:
+         bus: Ensure that only one GSource can be attached to the bus
+         Until now we were enforcing that only 1 signal GSource was attached
+         the bus but we could attach as many GSource with `gst_bus_create_watch`
+         as we wanted... but in the end only 1 GSource will ever be dispatched for
+         a given `GstMessage` leading to totally broken behavior.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/718>
+
+2020-12-10 15:05:31 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gstbus.c:
+         bus: Do not override source->prepare
+         Since GLib 2.36 we do not need it.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/718>
+
+2020-12-10 14:08:53 -0500  Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+         gir: Fix parser warning due to empty line
+         The GIR parser does not want any empty line after the function or macro
+         name line.
+         Fixes the following warning:
+         [309/4246] Generating Gst-1.0.gir with a custom command
+         ../subprojects/gstreamer/gst/gstelement.h:57: Warning: Gst: "@element" parameter unexpected at this location:
+         * @element: The element name in lower case, with words separated by '_'.
+         ^
+         ../subprojects/gstreamer/gst/gstelement.h:84: Warning: Gst: "@e" parameter unexpected at this location:
+         * @e: The element name in lower case, with words separated by '_'.
+         ^
+         ../subprojects/gstreamer/gst/gstelement.h:106: Warning: Gst: "@e" parameter unexpected at this location:
+         * @e: The element name in lower case, with words separated by '_'.
+         ^
+         ../subprojects/gstreamer/gst/gstdeviceprovider.h:32: Warning: Gst: "@d_p" parameter unexpected at this location:
+         * @d_p: The device provider name in lower case, with words separated by '_'.
+         ^
+         ../subprojects/gstreamer/gst/gstdynamictypefactory.h:28: Warning: Gst: "@t_n" parameter unexpected at this location:
+         * @t_n: The dynamic type name in lower case, with words separated by '_'.
+         ^
+         ../subprojects/gstreamer/gst/gsttypefind.h:34: Warning: Gst: "@type_find" parameter unexpected at this location:
+         * @type_find: The type find name in lower case, with words separated by '_'.
+         ^
+         ../subprojects/gstreamer/gst/gsttypefind.h:61: Warning: Gst: "@t_f" parameter unexpected at this location:
+         * @t_f: The type find name in lower case, with words separated by '_'.
+         ^
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/719>
+
+2020-12-10 09:57:37 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gststructure.c:
+       * tests/check/gst/gststructure.c:
+         structure: Handle trailing comas in serialized structs
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/717>
+
+2020-10-06 14:26:30 +0200  Stéphane Cerveau <scerveau@collabora.com>
+
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gstclocksync.c:
+       * plugins/elements/gstconcat.c:
+       * plugins/elements/gstcoreelementselements.h:
+       * plugins/elements/gstcoreelementsplugin.c:
+       * plugins/elements/gstdataurisrc.c:
+       * plugins/elements/gstdownloadbuffer.c:
+       * plugins/elements/gstelements.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/gststreamiddemux.c:
+       * plugins/elements/gsttee.c:
+       * plugins/elements/gsttypefindelement.c:
+       * plugins/elements/gstvalve.c:
+       * plugins/elements/meson.build:
+         coreelements: allow per features registration
+         Split plugin into features including
+         dynamic types which can be indiviually
+         registered during a static build.
+         More details here:
+         https://gitlab.freedesktop.org/gstreamer/gst-build/-/merge_requests/199
+         https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/661
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/661>
+
+2020-12-01 12:46:19 +0100  Stéphane Cerveau <scerveau@collabora.com>
+
+       * gst/gstdynamictypefactory.h:
+         dynamic type: add convenience macros to register
+         This macros will help to register a dynamic type
+         apart from a given plugin such as in a static build
+         of gstreamer where libgstreamer-full is generated.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/661>
+
+2020-11-30 11:51:59 +0100  Stéphane Cerveau <scerveau@collabora.com>
+
+       * gst/gsttypefind.h:
+         type find: add convenience macros to register
+         This macros will help to register a device provider
+         apart from a given plugin such as in a static build
+         of gstreamer where libgstreamer-full is generated.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/661>
+
+2020-11-27 17:33:33 +0100  Stéphane Cerveau <scerveau@collabora.com>
+
+       * gst/gstdeviceprovider.h:
+       * tests/check/gst/gstdevice.c:
+         device provider: add convenience macros to register
+         This macros will help to register a device provider
+         apart from a given plugin such as in a static build
+         of gstreamer where libgstreamer-full is generated.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/661>
+
+2020-08-31 14:05:49 -0400  Julian Bouzas <julian.bouzas@collabora.com>
+
+       * gst/gstelement.h:
+         element: add convenience macros to register
+         Define separate macros to define an element
+         apart from the plugin itself.
+         These macros will help to register
+         elements a part from a plugin.
+         By example in the case of a gstreamer static build
+         producing the libgstreamer-full library.
+         More details here:
+         https://gitlab.freedesktop.org/gstreamer/gst-build/-/merge_requests/199
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/661>
+
+2020-12-01 17:17:30 +0100  Stéphane Cerveau <scerveau@collabora.com>
+
+       * tools/gst-inspect.c:
+         gst-inspect: add an option to sort plugins
+         with the option --sort, the output is sort by default
+         with alphabetical order with plugins and features.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/709>
+
+2020-12-07 12:23:15 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * tests/check/gst/gstdatetime.c:
+         datetime: Update tests for returning NULL instead of g_return_val_if_fail() in error cases
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/706>
+
+2020-11-25 14:02:23 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstdatetime.c:
+         datetime: Make use of new g_time_zone_new_identifier() that properly handles errors
+         g_time_zone_new() returns UTC if it fails to parse the timezone
+         identifier, which is rather suboptimal and causes wrong datetimes to be
+         created silently.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/706>
+
+2020-11-25 14:00:45 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstdatetime.c:
+         datetime: Clean up all constructors to fail gracefully if invalid dates/times are provided
+         And also don't crash dereferencing a NULL pointer if the GDateTime
+         functions return NULL.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/632
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/706>
+
+2020-11-25 13:36:19 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstdatetime.c:
+         datetime: Change getters to return specific invalid values if the value is not set
+         This is more bindings friendly than requiring a special function to be
+         called beforehand or getting an assertion instead, and should also
+         simplify some usage.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/706>
+
+2020-11-25 13:35:57 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstdatetime.c:
+         datetime: Improve documentation a bit to explain when NULL is returned
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/706>
+
+2020-07-14 22:36:36 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gst_private.h:
+       * gst/gstcaps.c:
+       * gst/gstcaps.h:
+       * gst/gststructure.c:
+       * gst/gststructure.h:
+       * hooks/pre-commit.hook:
+       * tests/check/gst/capslist.h:
+       * tests/check/gst/gstcaps.c:
+       * tests/check/gst/gststructure.c:
+         gst: Add new structure/caps/_to_string using the brackets for nesting
+         This adds `gst_structure_serialize` and `gst_caps_serialize` which use
+         the newly introduced bracket delimiters for nested structures.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/532>
+
+2020-06-17 09:31:18 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gstvalue.c:
+         value: Cleanup on range parsing failures
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/532>
+
+2020-06-16 00:07:51 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gst_private.h:
+       * gst/gstcaps.c:
+       * gst/gststructure.c:
+       * gst/gstvalue.c:
+       * tests/check/gst/gstvalue.c:
+         structure: Add support for brackets as nested structures/caps specifiers
+         This introduces a more human friendly syntax to specify nested
+         structures It does so by using 2 different markers for opening and
+         closing them instead of abusing quotes which lead to requiring an insane
+         amount of escaping to match nesting levels.
+         The brackets (`[` and `]`) have been chosen as they avoid complex
+         constructions with curly brackets (or lower/higher than signs) where you
+         could have structures embedded inside arrays (which also use curly
+         brackets), ie. `s, array=(structure){{struct}}` should be parsed as an
+         array of structures, but the cast seems to imply something different. We
+         do not have this issue with brackets as they are currently used for
+         ranges, which can only be casted to numeric types.
+         This commit does not make use of that new syntax for serialization as
+         that would break backward compatibility, so it is basically a 'sugar'
+         syntax for humans. A notice has been explicitly made in the
+         documentation to let the user know about it.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/532>
+
+2020-12-03 19:22:43 +0100  Marijn Suijten <marijns95@gmail.com>
+
+       * libs/gst/check/gsttestclock.c:
+         check: gst_test_clock_process_next_clock_id returns nullable
+         It is possible there are no more pending clocks in the chain, in which
+         case this function returns null.
+         See also tests like test_single_shot_async_future that validate NULL
+         returns.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/714>
+
+2020-12-01 19:17:05 +0000  Jose Quaresma <quaresma.jose@gmail.com>
+
+       * meson_options.txt:
+         meson: gtk_doc is not supported anymore
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/710>
+
+2020-12-02 09:22:35 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gststreams.c:
+         streams: gst_stream_type_get_name() is not nullable
+         It takes an enum and only the defined values are valid to pass in here
+         as it's not extensible from the outside.
+         Add a g_return_val_if_reached() for the unreachable case and return
+         "invalid".
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/711>
+
+2020-12-02 09:35:26 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstinfo.c:
+         info: Warn if logging with a non-GObject object if GST_ENABLE_EXTRA_CHECKS is enabled
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/712>
+
+2020-11-20 14:55:17 +0000  Tim-Philipp Müller <tim@centricular.com>
+
+       * gst/gsttaskpool.c:
+         taskpool: fix docs warnings
+         gsttaskpool.c:507: Warning: Gst: gst_shared_task_pool_get_max_threads: unknown parameter 'max_threads' in documentation comment
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/703>
+
+2020-11-10 21:39:13 +1000  Jonathan Matthew <jonathan@d14n.org>
+
+       * plugins/elements/gsttypefindelement.c:
+       * plugins/elements/gsttypefindelement.h:
+         typefind: copy seqnum to new segment event
+         Fixes: #635
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/700>
+
+2020-10-30 16:58:52 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gstsystemclock.c:
+       * meson.build:
+         systemclock: Use clock_nanosleep for higher accuracy
+         The various wait implementation have a latency ranging from 50 to 500+
+         microseconds. While this is not a major issue when dealing with a low number of
+         waits per second (for ex: video), it does introduce a non-negligeable jitter for
+         synchronization of higher packet rate systems.
+         The `clock_nanosleep` syscall does offer a lower-latency waiting system but is
+         unfortunately blocking, so we don't want to use it in all scenarios nor for too
+         long.
+         This patch makes GstSystemClock use clock_nanosleep (if available) as such:
+         * Any wait below 500us uses it
+         * Any wait below 2ms will first use the regular waiting system and then
+         clock_nanosleep
+         #     modified:   gst/gstsystemclock.c
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/688>
+
+2020-11-03 02:43:26 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gsttaskpool.c:
+       * gst/gsttaskpool.h:
+       * tests/check/gst/gsttask.c:
+         taskpool: expose new "shared" task pool implementation
+         While the default implementation will spawn a thread per new
+         pushed task, this new implementation instead spawns a maximum
+         number of threads, then queues new tasks on existing threads.
+         The thread that the new task will be queued on is picked in
+         a pretty naive fashion, by simply popping the first thread
+         from a queue and pushing it back to the tail, but this is
+         an implementation detail and can always be sophisticated
+         in the future if the need arises.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/692>
+
+2020-11-03 02:41:31 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gsttaskpool.c:
+       * gst/gsttaskpool.h:
+         taskpool: expose dispose_handle() API
+         This is useful when the subclass does return a non-NULL pointer
+         in push(), and the user doesn't want to call join()
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/692>
+
+2020-11-03 02:39:37 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gsttaskpool.c:
+         taskpool: improve join() documentation
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/692>
+
+2020-11-03 02:33:32 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gsttaskpool.c:
+         taskpool: modify transfer annotations for push() and join()
+         While the default implementation passes NULL around as the
+         task handle, other implementations can only provide a safe
+         API by having that handle map to a refcounted opaque type.
+         While what's passed around is a gpointer, a valid transfer
+         type annotation has informative value.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/692>
+
+2020-10-17 12:34:20 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstbufferpool.c:
+       * gst/gstdatetime.c:
+       * gst/gstdeviceprovider.c:
+       * gst/gstelement.c:
+       * gst/gstparse.c:
+       * gst/gstplugin.c:
+       * gst/gstregistry.c:
+       * gst/gststreamcollection.c:
+       * gst/gsttypefind.c:
+       * gst/gsttypefindfactory.c:
+       * gst/gsturi.c:
+       * gst/gstutils.c:
+       * libs/gst/base/gstaggregator.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+         Add some missing nullable annotations
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/678>
+
+2020-11-04 18:37:32 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * meson.build:
+         meson: Enable some MSVC warnings for parity with GCC/Clang
+         This makes it easier to do development with MSVC by making it warn
+         on common issues that GCC/Clang error out for in our CI configuration.
+         Continuation from https://gitlab.freedesktop.org/gstreamer/gst-build/-/merge_requests/223
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/698>
+
+2020-11-02 17:43:42 +0800  Bing Song <bing.song@nxp.com>
+
+       * plugins/elements/gstclocksync.c:
+       * plugins/elements/gstidentity.c:
+         identity/clocksync: Also provide system clock if sync=false
+         identity should provide when sync=true. Don't provide when sync=false.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/630
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/690>
+
+2020-11-03 22:39:54 +1000  Jonathan Matthew <jonathan@d14n.org>
+
+       * plugins/elements/gstqueue2.c:
+         queue2: Fix modes in scheduling query handling
+         Create a new query to send upstream and copy the flags across from it,
+         rather than reusing the same query, as this allows us to prevent use
+         of pull mode when we don't have a download file.
+         Fixes: #629
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/693>
+
+2020-11-03 22:58:26 -0800  Khem Raj <raj.khem@gmail.com>
+
+       * gst/gst_private.h:
+         gst_private.h: increse padding in struct _GstClockEntryImpl
+         When compiling for 32bit architectures with 64bit time_t e.g. riscv32,
+         the static assert that the GstClockEntryImpl smaller or
+         equal to the struct _GstClockEntryImpl triggered.
+         (they were 12bytes off).
+         To fix this, the padding is increased by 8 bytes (on 32bit).
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/694>
+
+2020-10-31 15:10:23 -0400  Chris White <cxwembedded@gmail.com>
+
+       * gst/gstinfo.c:
+         gstinfo: colorize PIDs in log messages
+         The PIDs on log lines were supposed to be colorized before, but the
+         escape sequence was incorrect.  With this change, the code uses the
+         correct sequence to colorize those PIDs.  E.g., instead of `\033[334m`
+         (incorrect), use `\033[34m` (correct).
+         This makes the log messages easier to read.  It also reduces the chance
+         that a buggy terminal will choke on the invalid escape sequence.
+         https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/624
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/689>
+
+2020-10-30 23:46:07 +1100  Jan Schmidt <jan@centricular.com>
+
+       * libs/gst/check/gstharness.c:
+       * tests/check/libs/gstharness.c:
+         harness: Handle element not being set cleanly.
+         If a harness is created with gst_harness_new_empty(), there
+         might not be an internal element to unref on cleanup.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/686>
+
+2020-10-30 00:45:42 +1100  Jan Schmidt <jan@centricular.com>
+
+       * gst/gstbin.c:
+       * tests/check/gst/gstbin.c:
+         bin: When removing a sink, check if the EOS status changed.
+         Removing a sink that hasn't posted EOS might change the bin itself
+         to EOS if it's the last remaining non-EOSed sink.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/683>
+
+2020-10-26 23:17:59 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: always use incoming DTS
+         When parsing interlaced video streams, ignoring incoming DTS could
+         cause the parser to end up with PTS < DTS output buffers, for example
+         when increasing next_dts using the duration of the last pushed
+         buffer.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/681>
+
+2020-10-21 09:43:43 +0100  Philippe Normand <philn@igalia.com>
+
+       * gst/gstdevicemonitor.c:
+       * gst/gstdeviceprovider.c:
+       * gst/gstdeviceprovider.h:
+       * tests/check/gst/gstdevice.c:
+         devicemonitor: Stop only the already started providers
+         If a device provider fails to start (for instance the pulseaudio provider unable
+         to connect to the PulseAudio daemon) then the monitor should not keep track of
+         it in its `started` providers list. Otherwise a false positive critical warning
+         would be raised.
+         This patch also switches the started_count type from bool to int, for
+         consistency. This is a counter, after all.
+         API: gst_device_provider_is_started
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/679>
+
+2020-10-21 17:24:01 +0900  Seungha Yang <seungha@centricular.com>
+
+       * plugins/elements/gstfilesrc.c:
+         filesrc: Use *Ex Win32 method for UWP
+         non-*Ex methods are not allowed for UWP
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/610>
+
+2020-09-02 17:01:42 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gstfilesrc.c:
+         filesrc: Don't use fstat() on Windows but use specific Windows APIs
+         fstat() fails on Windows in various situations if the file metadata has
+         invalid values, and we only care about getting attributes and the file
+         size.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/610>
+
+2020-09-02 17:01:35 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gstfilesrc.c:
+         filesrc: Remove unused #define on Windows
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/610>
+
+2020-10-16 10:22:04 -0400  Xavier Claessens <xavier.claessens@collabora.com>
+
+       * libs/gst/check/meson.build:
+         pkgconfig: Fix missing libcheck dependencies in gstreamer-check-1.0
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/676>
+
+2020-10-16 10:39:08 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: Include min-upstream-latency in buffering time
+         While we can fixe the upstream latency using the min-upstream-latency, we
+         are now forced to use queues (hence more thread) in order to store the pending
+         data whenever we have an upstream source that has lower latency.
+         This fixes the issue by allowing to buffer the fixed upstream latency. This is
+         particularly handy on single core systems were having too many threads can
+         cause serious performance issues.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/677>
+
+2017-09-08 19:59:27 -0400  Olivier Crête <olivier.crete@collabora.com>
+
+       * docs/plugins/gst_plugins_cache.json:
+       * plugins/elements/gstidentity.c:
+       * plugins/elements/gstidentity.h:
+         identity: Add a stats property
+         This is inspired by the stats on rtpjitterbuffer, it's useful
+         to be able to get some simple stats out of the pipeline without having
+         to write yet another pad probe.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/615>
+
+2019-07-03 09:29:26 +0200  Stéphane Cerveau <scerveau@collabora.com>
+
+       * gst/gstiterator.c:
+       * meson.build:
+       * tests/misc/netclock-replay.c:
+       * tools/gst-inspect.c:
+         meson: update glib minimum version to 2.56
+         In order to support the symbol g_enum_to_string in various
+         project using GStreamer ( gst-validate etc.), the glib minimum
+         version should be 2.56.0.
+         Remove compat code as glib requirement
+         is now > 2.56
+         Version used by Ubuntu 18.04 LTS
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/199>
+
+2020-10-13 01:19:47 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstvalue.c:
+         gstvalue: don't write to const char *
+         Our various deserializing functions require NULL terminators
+         to not over consume substrings (eg fields of an array). Instead
+         of writing a NULL terminator to the passed-in string, which may
+         result in segfaults, make a copy of the substring we're interested
+         in.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/446
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/672>
+
+2018-10-27 13:01:02 -0400  Xavier Claessens <xavier.claessens@collabora.com>
+
+       * gst/meson.build:
+       * libs/gst/base/meson.build:
+       * libs/gst/check/meson.build:
+       * libs/gst/controller/meson.build:
+       * libs/gst/net/meson.build:
+       * meson.build:
+       * pkgconfig/gstreamer-base-uninstalled.pc.in:
+       * pkgconfig/gstreamer-base.pc.in:
+       * pkgconfig/gstreamer-check-uninstalled.pc.in:
+       * pkgconfig/gstreamer-check.pc.in:
+       * pkgconfig/gstreamer-controller-uninstalled.pc.in:
+       * pkgconfig/gstreamer-controller.pc.in:
+       * pkgconfig/gstreamer-net-uninstalled.pc.in:
+       * pkgconfig/gstreamer-net.pc.in:
+       * pkgconfig/gstreamer-uninstalled.pc.in:
+       * pkgconfig/gstreamer.pc.in:
+       * pkgconfig/meson.build:
+         Meson: Use pkg-config generator
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4>
+
+2020-10-10 00:53:42 +0900  Seungha Yang <seungha@centricular.com>
+
+       * meson.build:
+         meson: Disallow DbgHelp for UWP build
+         Most symbols in DbgHelp.h are not allowed for UWP
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/665>
+
+2020-08-14 16:38:26 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * gst/gst_private.h:
+       * gst/gstinfo.c:
+       * meson.build:
+         Remove unused valgrind detection
+         Having this just to log a debug message in case we're
+         running inside valgrind doesn't seem very useful, and
+         the code that used to use this no longer exists it seems.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/595>
+
+2020-10-07 03:49:33 +0900  Seungha Yang <seungha@centricular.com>
+
+       * gst/gstinfo.c:
+         info: Fix build on Windows ARM64 device
+         gstinfo.c(3086): error C2094: label 'done' was undefined
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/662>
+
+2020-10-09 12:13:15 +1100  Matthew Waters <matthew@centricular.com>
+
+       * meson.build:
+         build: use cpu_family for arch checks
+         e.g. on 32-bit arm, we may have armv6, armv7l, armv7hf, etc which all
+         generally have the same layouts.  cpu_family() groups all of these into
+         just 'arm' that the ABI check table is expecting.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/664>
+
+2020-10-08 13:37:41 +0200  Jan Alexander Steffens (heftig) <jan.steffens@ltnglobal.com>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: Fix in/outbuf confusion of _default_transform_meta
+         The default implementation doesn't actually use its buffer parameters,
+         but this error might have been the cause of some actual confusion in
+         the plugins code.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/663>
+
+2020-09-04 20:47:18 -0400  Xavier Claessens <xavier.claessens@collabora.com>
+
+       * gst/gst.c:
+         gst_init: Call gst_init_static_plugins() when available
+         When doing a static build, gstreamer-full-1.0 defines that symbol to
+         register static plugins. Cerbero's Android build will be updated to
+         implement that symbol too.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/641>
+
+2020-09-17 20:44:43 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gst_private.h:
+       * gst/gststructure.c:
+       * gst/gstutils.c:
+       * gst/gstvalue.c:
+       * gst/gstvalue.h:
+       * gst/parse/grammar.y.in:
+       * tests/check/gst/gstvalue.c:
+         gstvalue: expose gst_value_deserialize_with_pspec()
+         Typing hints can only be passed to gst_value_deserialize()
+         through the type of the passed-in value. This means deserialization
+         can only target the desired type for the top-level elements,
+         making it for example impossible to deserialize an array of
+         flags to the expected type.
+         This commit exposes a new function, gst_value_deserialize_full(),
+         that takes an optional pspec as the extra parameter, and updates
+         the deserialization code to pass around that pspec, or the
+         element_spec when recursively parsing the elements of a list-type
+         value.
+         This allows for example passing arrays of flags through the
+         command line or gst_util_set_object_arg, eg:
+         foo="<bar,bar+baz>"
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/629>
+
+2020-09-15 21:07:27 +0900  Seungha Yang <seungha@centricular.com>
+
+       * gst/gstinfo.c:
+       * meson.build:
+         info: Load DbgHelp.dll using g_module_open()
+         ... and update meson file so that enable it only using required headers.
+         "dependency(...)" is unlikely successful for Windows SDK libraries
+         since it doesn't ship pkg-config file. So it needs to be changed
+         to "find_library()" to link corresponding .lib file. That would
+         result to most MSVC build system will link dbghelp.dll. However,
+         one drawback of the change is that gstreamer-1.0.dll will mandate
+         dbghelp.dll although it should be optional. So g_module_open() way
+         can be the most safe way in this case.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/626>
+
+2020-09-30 11:56:40 +1000  Matthew Waters <matthew@centricular.com>
+
+       * gst/gstpadtemplate.c:
+         padtemplate: mark documentation caps as may be leaked
+         The template itself is already marked as such and the caps, the
+         documentation caps are a logical extension of those two.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/650>
+
+2020-09-26 09:11:40 +0200  Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
+
+       * gst/gstpadtemplate.c:
+         padtemplate: add missing annotation
+         Adds missing "transfer full" annotation for caps parameter in
+         gst_pad_template_set_documentation_caps()
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/648>
+
+2020-09-26 09:09:48 +0200  Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
+
+       * gst/gstmemory.h:
+         memory: fix documentation to display in html
+         Commit e9c99c05 added a deprecation message, but this message is not
+         displayed in the html page since the format was not correct.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/648>
+
+2020-09-01 23:03:18 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gst.c:
+       * gst/gst_private.h:
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstmeta.c:
+       * gst/gstmeta.h:
+       * tests/check/gst/gstmeta.c:
+         meta: expose API to register and create custom meta
+         Custom meta is backed by a GstStructure, and does not require
+         that users of the API expose their GstMeta implementation as
+         public API for other components to make use of it.
+         In addition, it provides a simpler interface by ignoring the
+         impl vs. api distinction that the regular API exposes.
+         This new API is meant to be the meta counterpart to custom events
+         and messages, and to be more convenient than the lower-level API
+         when the absolute best performance isn't a requirement.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/609>
+
+2017-07-11 18:54:05 -0400  Olivier Crête <olivier.crete@collabora.com>
+
+       * gst/gstmemory.h:
+         memory: Deprecate GST_MEMORY_FLAG_NO_SHARE
+         This flag always causes problems as it prevents subbuffering,
+         instead one should create a custom GstAllocator to pool the GstMemory objects
+         and not rely on the lifetime of the GstBuffer object they were originally
+         attached to.
+         https://bugzilla.gnome.org/show_bug.cgi?id=757254
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/614>
+
+2020-09-16 02:16:52 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstmeta.c:
+         gstmeta: intern registered impl string
+         Subsequent lookups in the hashtable are probably better done
+         on memory we're confident is allocated to us :)
+         It was easy to trigger invalid reads by calling gst_meta_register
+         with dynamically allocated memory, freeing that memory, then
+         calling gst_meta_get_info()
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/628>
+
+2020-07-06 14:55:38 -0400  Olivier Crête <olivier.crete@collabora.com>
+
+       * gst/gstdeviceprovider.c:
+       * gst/gstdeviceprovider.h:
+         deviceprovider: Returns non-floating devices from gst_device_provider_probe
+         This should make the API usage more consistent. Also document that the subclasses
+         should just return the devices as floating.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/558>
+
+2020-07-31 16:02:03 +1000  Matthew Waters <matthew@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: don't fail all sink pads when a caps event fails negotiation
+         If one pad returns not-negotiated from a caps event, then all other sink
+         pads were returning not-negotiated.
+         In our case, we can't reliably easily fail at all so just remove that
+         code.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/623>
+
+2020-07-31 01:10:27 +1000  Matthew Waters <matthew@centricular.com>
+
+       * libs/gst/base/gstbaseparse.c:
+       * tests/check/libs/baseparse.c:
+         baseparse: prefer upstream caps rather than overriding
+         e.g. h264parse ! video/x-h264,stream-format=avc receives the following:
+         - caps: video/x-raw,stream-format=byte-stream
+         - gap event: baseparse tries to choose some default caps but would
+         override the downstream chosen caps field with upstreams value.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/581>
+
+2020-09-18 09:59:03 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: Hold SRC_LOCK while unblocking via SRC_BROADCAST()
+         Otherwise the clock id we access might not be a valid pointer anymore.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/630>
+
+2020-09-15 06:35:34 +0900  Seungha Yang <seungha@centricular.com>
+
+       * tests/check/elements/leaks.c:
+         tests: leaks: Allow null tracer string if there's no available stack trace
+         In case that no available stack tracer, leak tracer will set
+         null string value for `trace` field. I would likely happen
+         on Windows.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/625>
+
+2020-09-15 04:24:20 +0900  Seungha Yang <seungha@centricular.com>
+
+       * tests/check/gst/gstelement.c:
+         tests: element: Don't run too many loop
+         g_thread_yield() doesn't ensure thread switching actually.
+         It would result to adding so many pads. Depending on system,
+         timeout might happen then.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/625>
+
+2020-09-15 00:54:58 +0900  Seungha Yang <seungha@centricular.com>
+
+       * tests/check/pipelines/seek.c:
+         tests: seek: Don't use too strict timeout for validation
+         Expected segment-done message might not be seen within expected
+         time if system is not powerful enough.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/625>
+
+2020-09-11 02:59:51 +0900  Seungha Yang <seungha@centricular.com>
+
+       * plugins/elements/gstvalve.c:
+         valve: Fix MSVC compile warning
+         gstvalve.c(285) : warning C4715: 'gst_valve_event_needs_dropping':
+         not all control paths return a value
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/624>
+
+2020-07-01 19:15:42 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+         event: Add optional flags to the GAP event
+         This allows to signal the reason for the gap, for example missing data
+         like packet loss.
+         Based on a patch by Mikhail Fludkov <misha@pexip.com>
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/551>
+
+2020-09-10 14:17:26 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/check/gstharness.c:
+       * libs/gst/check/gstharness.h:
+         harness: Add gst_harness_set_live()
+         By default each harness returns is_live=TRUE in latency queries. This is
+         often not desired and can now be overridden.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/599>
+
+2020-08-19 21:17:31 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: Reset latency values in start()
+         Some base classes like videoaggregator try retrieving the latency during
+         construction, which causes the latency values to be set already until
+         reconfiguration happens.
+         By resetting them the same way as in stop() we ensure that we always
+         start cleanly.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/599>
+
+2020-09-08 12:45:42 +0100  Tom Schoonjans <Tom.Schoonjans@rfi.ac.uk>
+
+       * libs/gst/helpers/ptp_helper_post_install.sh:
+         ptp_helper_post_install.sh: deal with none
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/620>
+
+2020-09-09 01:23:11 +0800  Xℹ Ruoyao <xry111@mengyan1223.wang>
+
+       * tests/check/meson.build:
+         skip elements/leak.c if tracer is not available
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/621>
+
+2020-08-20 11:09:11 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: Wake up source pad in PAUSED<->PLAYING transitions
+         When going to PLAYING we will now have a clock and can stop waiting on
+         the condition variable and instead start waiting on the clock if
+         necessary for the current configuration.
+         In the other direction when going to PAUSED the clock might have
+         disappeared and we might need to wait on the condition variable again
+         instead.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/601>
+
+2020-08-24 11:59:51 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gstinputselector.c:
+         input-selector: Wake up blocking pads when releasing them
+         Otherwise deactivating them will cause a deadlock as they're blocking
+         inside the streaming thread.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/601
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/606>
+
+2020-08-14 11:40:30 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * docs/plugins/gst_plugins_cache.json:
+       * plugins/elements/gstvalve.c:
+       * plugins/elements/gstvalve.h:
+         valve: Add modes to forward sticky events when dropping and to convert buffers into gap events
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/587
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/84
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/594>
+
+2020-09-01 00:26:31 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+       * tests/check/libs/aggregator.c:
+         aggregator: make peek() has() pop() drop() buffer API threadsafe
+         Enforce that the last buffer that was peeked (or had its existence
+         checked) on a pad is the one that gets popped / dropped, resetting
+         at the end of each aggregation cycle.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/603
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/608>
+
+2020-09-08 13:40:25 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/helpers/meson.build:
+         ptp: Also handle gnu/kfreebsd
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/619>
+
+2020-09-08 17:30:27 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * .gitlab-ci.yml:
+         ci: include template from gst-ci master branch again
+
+2020-09-08 16:58:20 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * meson.build:
+         Back to development
+
+=== release 1.18.0 ===
+
+2020-09-08 00:01:33 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * .gitlab-ci.yml:
+       * ChangeLog:
+       * NEWS:
+       * README:
+       * RELEASE:
+       * gstreamer.doap:
+       * meson.build:
+         Release 1.18.0
+
+2020-09-07 20:22:38 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * meson.build:
+       * scripts/dist-translations.py:
+       * scripts/meson.build:
+         meson: dist pot file in tarballs
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/618>
+
+2020-08-21 11:06:57 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: Document that samples_selected() must only be called from the aggregate() function
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/607>
+
+2020-08-20 10:54:12 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: Don't automatically adjust segment if subclass provided one
+         On the first buffer the base class would update the segment position
+         based on the start-time-selection. If the subclass provides its own
+         segment this will caused unexpected behaviour and override segment
+         information that was explicitly set by the subclass.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/600>
+
+=== release 1.17.90 ===
+
+2020-08-20 16:08:25 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * ChangeLog:
+       * NEWS:
+       * RELEASE:
+       * gstreamer.doap:
+       * meson.build:
+         Release 1.17.90
+
+2020-08-10 22:42:54 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: fix documentation for samples-selected and buffer-consumed
+         GI expects the instance parameter to be documented, omitting it
+         leads to a msismatched output in the gir.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/592>
+
+2020-08-07 09:30:55 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+       * libs/gst/base/gstaggregator.h:
+         aggregator: Add optional GstStructure info parameter to "samples-selected" signal
+         Subclasses can use this to provide more information, for example
+         audioaggregator could provide the offset into the output buffer where
+         the next data is going to be filled.
+         See https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/issues/805
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/590>
+
+2020-08-05 16:54:44 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+       * libs/gst/base/gstaggregator.h:
+         aggregator: add segment, pts, dts and duration to samples-selected
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/588>
+
+2020-08-04 07:10:03 -0400  Xavier Claessens <xavier.claessens@collabora.com>
+
+       * tests/validate/meson.build:
+         Meson: Override gst-tester-1.0 program to find it in other modules
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/586>
+
+2020-08-03 16:26:58 +0300  Jordan Petridis <jordan@centricular.com>
+
+       * gst/gstcaps.c:
+       * gst/gstdeviceproviderfactory.c:
+       * gst/gstelementfactory.c:
+       * gst/gstminiobject.c:
+       * gst/gstobject.c:
+       * gst/gststructure.c:
+         fix clang 10 warnings
+         the typesystem checks in g_atomic_pointer_compare_and_exchange
+         seem to trigger some false positives with clang 10
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/584>
+
+2020-08-04 11:13:51 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: fix iteration direction in skip_buffers
+         Subclasses use the pad segment to determine whether a buffer
+         should be skipped, we thus don't want to check if a buffer
+         needs to be skipped before processing the segment it's part
+         of.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/585>
+
+2020-07-30 19:31:55 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * gst/gsturi.c:
+       * gst/gsturi.h:
+       * tests/check/gst/gsturi.c:
+         gsturi: Add new API for storing unmodified userinfo / fragment
+         New API: gst_uri_from_string_escaped()
+         Identical to gst_uri_from_string() except that the userinfo and
+         fragment components of the URI will not be unescaped while parsing.
+         This is needed for correctly parsing usernames or passwords with `:`
+         in them such as reported at:
+         https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/issues/831
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/583>
+
+2020-08-01 01:57:06 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * tests/check/gst/gsturi.c:
+         tests: Add more tests for gsturi
+         Add tests that exercise unescaping of userinfo and fragments.
+         Also convert to a modular macro-based definition so that we can reuse
+         the list of tests in the next commit.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/583>
+
+2020-07-30 19:53:10 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * tools/gst-inspect.c:
+         inspect: Print preset description when available
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/582>
+
+2020-06-30 21:10:05 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+       * libs/gst/base/gstaggregator.h:
+         aggregator: expose sample selection API
+         See https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/issues/771
+         for context.
+         This exposes new API that subclasses must call from their
+         aggregate() implementation to signal that they have selected
+         the next samples they will aggregate: gst_aggregator_selected_samples()
+         GstAggregator will emit a new signal there, `samples-selected`,
+         handlers can then look up samples per pad with the newly-added
+         gst_aggregator_peek_next_sample.
+         In addition, a new FIXME is logged when subclasses haven't actually
+         called `selected_samples` from their aggregate() implementation.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/549>
+
+2020-07-28 10:59:35 +0900  Hosang Lee <hosang10.lee@lge.com>
+
+       * gst/gsturi.c:
+       * tests/check/gst/gsturi.c:
+         gsturi: unescape '=' in http query
+         Don't use percent-encoding for '=' in http queries.
+         '=' in the following kind of http query should be maintained.
+         example:
+         ?token=exp=123~acl=/QualityLevels(*~hmac=0cb ...
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/580>
+
+2020-07-24 13:31:47 +0200  Camilo Celis Guzman <camilo@pexip.com>
+
+       * libs/gst/base/gstbasetransform.c:
+       * tests/check/libs/test_transform.c:
+       * tests/check/libs/transform1.c:
+         basetransform: handle invalid subclass implementation for fixate_caps
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/575>
+
+2020-07-24 17:53:00 -0400  Olivier Crête <olivier.crete@collabora.com>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: Don't push pointless new segment events
+         In 1.0, there is no concept of segment update, so don't push new
+         identical segments.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/578>
+
+2020-07-24 11:38:28 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: Fix seqnum handling in pull mode
+         After a seek in pull mode, we should use the seek seqnum for all
+         following operations, not some random seqnums
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/577>
+
+2020-07-26 15:30:26 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * libs/gst/check/gstcheck.h:
+         check: suppress g-ir-scanner warnings
+         Make g-ir-scanner skip all those check macros that are
+         not useful for or usable from bindings.
+         gstcheck.h:209: Warning: GstCheck: Unknown namespace for symbol 'fail_unless_message_error'
+         gstcheck.h:212: Warning: GstCheck: Unknown namespace for symbol 'assert_message_error'
+         gstcheck.h:251: Warning: GstCheck: Unknown namespace for symbol 'fail_unless_equals_int'
+         gstcheck.h:267: Warning: GstCheck: Unknown namespace for symbol 'assert_equals_int'
+         gstcheck.h:280: Warning: GstCheck: Unknown namespace for symbol 'fail_unless_equals_int_hex'
+         gstcheck.h:299: Warning: GstCheck: Unknown namespace for symbol 'assert_equals_int_hex'
+         gstcheck.h:310: Warning: GstCheck: Unknown namespace for symbol 'fail_unless_equals_int64'
+         gstcheck.h:327: Warning: GstCheck: Unknown namespace for symbol 'assert_equals_int64'
+         gstcheck.h:340: Warning: GstCheck: Unknown namespace for symbol 'fail_unless_equals_int64_hex'
+         gstcheck.h:358: Warning: GstCheck: Unknown namespace for symbol 'assert_equals_int64_hex'
+         gstcheck.h:369: Warning: GstCheck: Unknown namespace for symbol 'fail_unless_equals_uint64'
+         gstcheck.h:386: Warning: GstCheck: Unknown namespace for symbol 'assert_equals_uint64'
+         gstcheck.h:399: Warning: GstCheck: Unknown namespace for symbol 'fail_unless_equals_uint64_hex'
+         gstcheck.h:417: Warning: GstCheck: Unknown namespace for symbol 'assert_equals_uint64_hex'
+         gstcheck.h:428: Warning: GstCheck: Unknown namespace for symbol 'fail_unless_equals_string'
+         gstcheck.h:444: Warning: GstCheck: Unknown namespace for symbol 'assert_equals_string'
+         gstcheck.h:455: Warning: GstCheck: Unknown namespace for symbol 'fail_unless_equals_float'
+         gstcheck.h:474: Warning: GstCheck: Unknown namespace for symbol 'assert_equals_float'
+         gstcheck.h:487: Warning: GstCheck: Unknown namespace for symbol 'fail_unless_equals_pointer'
+         gstcheck.h:506: Warning: GstCheck: Unknown namespace for symbol 'assert_equals_pointer'
+         gstcheck.h:517: Warning: GstCheck: Unknown namespace for symbol 'fail_unless_equals_clocktime'
+         gstcheck.h:534: Warning: GstCheck: Unknown namespace for symbol 'MAIN_START_THREADS'
+         gstcheck.h:547: Warning: GstCheck: Unknown namespace for symbol 'MAIN_START_THREAD_FUNCTIONS'
+         gstcheck.h:555: Warning: GstCheck: Unknown namespace for symbol 'MAIN_START_THREAD_FUNCTION'
+         gstcheck.h:626: Warning: GstCheck: Unknown namespace for symbol 'ASSERT_CRITICAL'
+         gstcheck.h:628: Warning: GstCheck: Unknown namespace for symbol 'ASSERT_CRITICAL'
+         gstcheck.h:640: Warning: GstCheck: Unknown namespace for symbol 'ASSERT_WARNING'
+         gstcheck.h:652: Warning: GstCheck: Unknown namespace for symbol 'ASSERT_OBJECT_REFCOUNT'
+         gstcheck.h:661: Warning: GstCheck: Unknown namespace for symbol 'ASSERT_OBJECT_REFCOUNT_BETWEEN'
+         gstcheck.h:676: Warning: GstCheck: Unknown namespace for symbol 'ASSERT_CAPS_REFCOUNT'
+         gstcheck.h:679: Warning: GstCheck: Unknown namespace for symbol 'ASSERT_BUFFER_REFCOUNT'
+         gstcheck.h:682: Warning: GstCheck: Unknown namespace for symbol 'ASSERT_MINI_OBJECT_REFCOUNT'
+         gstcheck.h:690: Warning: GstCheck: Unknown namespace for symbol 'ASSERT_SET_STATE'
+         gstcheck.h:729: Warning: GstCheck: Unknown namespace for symbol 'tcase_skip_broken_test'
+         gstcheck.h:740: Warning: GstCheck: Unknown namespace for symbol 'tcase_skip_broken_loop_test'
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/579>
+
+2020-07-26 14:52:30 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * gst/gstutils.h:
+         utils: silence g-ir-scanner warnings about float conversion macros
+         663: Warning: Gst: symbol='GFLOAT_TO_LE': Unknown namespace for symbol 'GFLOAT_TO_LE'
+         664: Warning: Gst: symbol='GFLOAT_TO_BE': Unknown namespace for symbol 'GFLOAT_TO_BE'
+         665: Warning: Gst: symbol='GDOUBLE_TO_LE': Unknown namespace for symbol 'GDOUBLE_TO_LE'
+         666: Warning: Gst: symbol='GDOUBLE_TO_BE': Unknown namespace for symbol 'GDOUBLE_TO_BE'
+         669: Warning: Gst: symbol='GFLOAT_TO_LE': Unknown namespace for symbol 'GFLOAT_TO_LE'
+         670: Warning: Gst: symbol='GFLOAT_TO_BE': Unknown namespace for symbol 'GFLOAT_TO_BE'
+         671: Warning: Gst: symbol='GDOUBLE_TO_LE': Unknown namespace for symbol 'GDOUBLE_TO_LE'
+         672: Warning: Gst: symbol='GDOUBLE_TO_BE': Unknown namespace for symbol 'GDOUBLE_TO_BE'
+         678: Warning: Gst: symbol='GFLOAT_FROM_LE': Unknown namespace for symbol 'GFLOAT_FROM_LE'
+         679: Warning: Gst: symbol='GFLOAT_FROM_BE': Unknown namespace for symbol 'GFLOAT_FROM_BE'
+         680: Warning: Gst: symbol='GDOUBLE_FROM_LE': Unknown namespace for symbol 'GDOUBLE_FROM_LE'
+         681: Warning: Gst: symbol='GDOUBLE_FROM_BE': Unknown namespace for symbol 'GDOUBLE_FROM_BE'
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/579>
+
+2020-07-26 14:48:52 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * gst/math-compat.h:
+         math-compat.h: silence g-ir-scanner warnings
+         Easier to just make g-ir-scanner skip this header via #ifndef __GI_SCANNER__
+         than maintain different sets of headers in the meson.build file.
+         Warning: Gst: symbol="rint": Unknown namespace for symbol "rint"
+         Warning: Gst: symbol="rintf": Unknown namespace for symbol "rintf"
+         Warning: Gst: symbol="isnan": Unknown namespace for symbol "isnan"
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/579>
+
+2020-07-26 14:42:39 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * gst/gstevent.h:
+       * gst/gstquery.h:
+         event, query: fix g-ir-scanner warnings
+         gstevent.h:72: Warning: Gst: symbol='FLAG': Unknown namespace for symbol 'FLAG'
+         gstquery.h:76: Warning: Gst: symbol='FLAG': Unknown namespace for symbol 'FLAG'
+         Use _FLAG(xyz) instead of FLAG(xyz) to silence g-ir-scanner
+         warnings about this internal helper define.
+         It's also slightly more hygienic.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/579>
+
+2020-07-24 13:30:39 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * gst/gsttracer.c:
+       * gst/gsttracer.h:
+       * gst/gsttracerrecord.c:
+       * gst/gsttracerrecord.h:
+       * gst/gsttracerutils.c:
+       * gst/meson.build:
+       * plugins/tracers/meson.build:
+       * tests/check/meson.build:
+         tracer: declare GstTracer API stable
+         It's been around for more than 4 years and people have built
+         lots of stuff on top of it, doesn't really make sense to keep
+         it marked as unstable. We're unlikely to change it now, and
+         we can always deprecate it and make a new one if needed.
+         This stabilises the following API:
+         - gst_tracer_register()
+         - gst_tracing_get_active_tracers()
+         - gst_tracing_register_hook()
+         - gst_tracer_record_new()
+         - gst_tracer_record_log()
+         Might also help a bit with #424
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/576>
+
+2020-07-23 14:51:51 +1000  Matthew Waters <matthew@centricular.com>
+
+       * libs/gst/check/gstharness.c:
+         harness: unref sink/src caps after deactivating pads
+         Otherwise, access to the harness' sink/src caps is racy between any caps
+         query performed by an element and gst_harness_teardown().
+         Fixes: https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/issues/794
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/574>
+
+2020-07-22 12:44:02 +0200  Jan Alexander Steffens (heftig) <jan.steffens@ltnglobal.com>
+
+       * libs/gst/check/libcheck/check.c:
+       * libs/gst/check/libcheck/check.h.in:
+         check: Always mark _ck_assert_failed as noreturn
+         So that we can use `fail` like `g_assert_not_reached`.
+         The comment is apparently wrong or outdated, as GCC considers it legal
+         for noreturn-marked functions to return using longjmp.
+         See the thread at
+         https://gitlab.freedesktop.org/gstreamer/gst-plugins-ugly/-/merge_requests/59#note_576422
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/573>
+
+2020-07-14 12:15:34 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * gst/gstbuffer.c:
+         buffer: improve seqnum fallback warning message
+         Print target CPU we're building for.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/565>
+
+2020-07-14 12:11:57 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * gst/gstbuffer.c:
+         buffer: fix meta sequence number fallback on rpi
+         The global seqnum variable wasn't actually increased in
+         the fallback code path, leading to all buffers getting
+         a seqnum of 0. Which also made the unit test fail.
+         This affects platforms/toolchains that don't have
+         64-bit atomic ops such as when compiling for armv7 rpi.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/565>
+
+2020-07-09 09:46:07 +0200  Stéphane Cerveau <scerveau@collabora.com>
+
+       * meson.build:
+         meson: add a plugin summary
+         This summary displays a list of plugins which
+         have been enabled.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/560>
+
+2020-07-22 10:51:54 +0300  Eero Nurkkala <eero.nurkkala@offcode.fi>
+
+       * tools/gst-inspect.c:
+         gst-inspect: fix memory leak
+         With meson configure option: -Db_sanitize=address, the following
+         issue is seen while running the test "tools_gstinspect":
+         Running suite(s): gst-inspect
+         =================================================================
+         ==20880==ERROR: LeakSanitizer: detected memory leaks
+         Direct leak of 51 byte(s) in 9 object(s) allocated from:
+         #0 0x7ffb4dbb0b40 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb40)
+         #1 0x7ffb4cdf1ab8 in g_malloc (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x51ab8)
+         SUMMARY: AddressSanitizer: 51 byte(s) leaked in 9 allocation(s).
+         0%: Checks: 1, Failures: 0, Errors: 1
+         GOptionEntry man page states that: "Please note that parsed arguments need to be freed separately (see GOptionEntry)."
+         Thus, free the 'min_version' string that has been allocated but never freed.
+         Signed-off-by: Eero Nurkkala <eero.nurkkala@offcode.fi>
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/572>
+
+2020-07-20 17:08:32 +1000  Matthew Waters <matthew@centricular.com>
+
+       * gst/gstbufferpool.c:
+         gst/bufferpool: only resize in reset when maxsize is larger
+         Only resize the buffer if the maxsize is larger then the configued pool
+         size.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/570>
+
+2020-07-16 23:03:35 +1000  Matthew Waters <matthew@centricular.com>
+
+       * plugins/tracers/meson.build:
+         build/coretracers: add dep on threads
+         Fixes the following build error and missing '-pthread' argument when
+         linking:
+         subprojects/gstreamer/plugins/tracers/libgstcoretracers.so.p/gstleaks.c.o: In function `gst_leaks_tracer_setup_signals':
+         /work/build32/../subprojects/gstreamer/plugins/tracers/gstleaks.c:919: undefined reference to `pthread_atfork'
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/571>
+
+2020-07-14 00:03:18 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * libs/gst/controller/gstdirectcontrolbinding.c:
+       * tests/check/libs/controller.c:
+         directcontrolbinding: Properly initialize default `last_value`
+         It was zero and in some condition it means that the control binding
+         values where ignored (as shown in the test). Setting it to MAXDOUBLE
+         so that the first time we sync the values from a a timestamp in the
+         right range the proper value is computed.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/564>
+
+2020-07-16 18:55:22 +0900  Seungha Yang <seungha@centricular.com>
+
+       * gst/gstinfo.c:
+         info: Fix possible broken debug output on Windows
+         Depending on Windows codepage setting, some characters could
+         be broken when printing on terminal. Fortunatly g_print* family will
+         take care Windows codepage.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/566>
+
+2020-07-16 16:34:05 -0400  Olivier Crête <olivier.crete@collabora.com>
+
+       * gst/gstpad.h:
+         pad: More explicitly explain how to post errors on GST_FLOW_ERROR
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/568>
+
+2020-07-15 16:12:02 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+       * plugins/tracers/gstlatency.c:
+         latency tracer: Fix leaks in the reported latency trace
+         The stack item was not freed as it was supposed, causing leaks.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/269>
+
+2019-08-30 23:59:42 +1000  Jan Schmidt <jan@centricular.com>
+
+       * plugins/tracers/gstlatency.c:
+         latency tracer: Fix unsafe and NULL pointer accesses
+         Use thread-safe accesses to pad peers and parent objects. This
+         fixes some crashers and all the non-safe access patterns I could
+         spot. There's still some weirdness when using the latency
+         tracer on pipeline chains that aren't yet linked, but this
+         at least stops it segfaulting.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/269>
+
+2020-07-13 08:00:15 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstinfo.h:
+         Revert "gstinfo: Check threshold for category from macro"
+         This reverts commit dcece2a878b88335fd1990dbeeb88bdeacba0f06.
+         This increased the code size and number of branches for all debug statements.
+         Fixes #564
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/563>
+
+2020-07-10 17:11:08 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+       * libs/gst/base/gstaggregator.h:
+         aggregator: expose gst_aggregator_finish_buffer_list API
+         See https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/issues/1276
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/562>
+
+2020-07-06 11:55:38 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * tests/check/elements/leaks.c:
+         tests/elements/leaks.c: check get_tracer_by_name return value
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/557>
+
+2020-05-18 19:45:35 +0900  Seungha Yang <seungha@centricular.com>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: Deprecate gst_base_src_new_seamless_segment()
+         It can be replaced by gst_base_src_new_segment()
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/490>
+
+2020-05-17 00:08:56 +0900  Seungha Yang <seungha@centricular.com>
+
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasesrc.h:
+         basesrc: Add new API for handling GstSegment update by subclass
+         Add API gst_base_src_new_segment() for subclass to be able to
+         signalling new GstSegment which should be applied to following
+         buffers.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/490>
+
+2020-07-09 07:57:01 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gsttaglist.c:
+       * gst/gsttaglist.h:
+         taglist: Stop inlining gst_tag_list_copy
+         This way it gets exposed to bindings through GObject Introspection.
+         Same logic as with d1b2d3429c66d80b8d38f9afc6a8dfca49f3a71a
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/561>
+
+2020-07-08 05:15:28 +0900  Seungha Yang <seungha@centricular.com>
+
+       * libs/gst/check/gstcheck.h:
+         check: Use g_thread_yield instead of g_usleep(1)
+         Since the commit
+         https://gitlab.gnome.org/GNOME/glib/-/commit/01c02ac08b682de622930b1278c9c14d0ffe6c49,
+         g_usleep(1) will be translated to Sleep(1) on Windows which means
+         sleep in 1 millisecond. But GLib provides g_thread_yield() API
+         which is exactly what we required here for thread context switching.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/559>
+
+2020-01-08 19:38:45 -0500  Olivier Crête <olivier.crete@collabora.com>
+
+       * gst/gstdevicemonitor.c:
+       * gst/gstdeviceprovider.c:
+       * tests/check/gst/gstdevice.c:
+         deviceprovider: Do static probe on start as fallback
+         For providers that don't support dynamic probing, just fall back to doing
+         a static one on start() to make the UI developers life easier.
+         This also means that the monitor doesn't need to call _can_monitor() before
+         calling start.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/353>
+
+2018-05-02 13:05:21 +0200  Christoph Reiter <reiter.christoph@gmail.com>
+
+       * gst/gstelementfactory.c:
+         gstelementfactory: Fix missing features in case a feature moves to another filename
+         In case a plugin filename was renamed with the plugin being in the registry cache
+         the features were not loaded after the rename:
+         1) Cache of old/gone filename was loaded, features added
+         2) New filename was loaded, features where not added because
+         they were already found in the registry.
+         3) In the end stale cache entries for files which are no longer there
+         are removed, including the wanted features.
+         4) The cache gets updated without the features.
+         Fix this by also checking at (2) that the found feature is from the loaded plugin
+         and not from some stale cache entry.
+         This affected directsoundsink where libgstdirectsoundsink.dll was renamed
+         to libgstdirectsound.dll, losing the directsoundsink element in the process.
+         Fixes #290
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/102>
+
+2020-07-04 16:59:23 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * meson.build:
+       * scripts/extract-release-date-from-doap-file.py:
+         meson: set release date from .doap file for releases
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/555>
+
+2020-07-05 18:17:48 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * po/POTFILES:
+         po: update POTFILES
+         xgettext: error while opening "gst/parse/grammar.y" for reading: No such file or directory
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/586
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/556>
+
+2020-07-03 11:45:36 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/helpers/meson.build:
+         ptp: Add GNU Hurd to the list of supported platforms and fix the Solaris name
+         https://mesonbuild.com/Reference-tables.html#operating-system-names has
+         the table of all supported names right now.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/583
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/554>
+
+2020-07-02 11:21:27 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstelement.c:
+         element: When removing a ghost pad also unset its target
+         Otherwise the proxy pad of the ghost pad still stays linked to some
+         element inside the bin, which is not allowed anymore according to the
+         topology.
+         In 2.0 this should be fixed more generically from inside GstGhostPad but
+         currently there is no way to get notified that the ghost pad is
+         unparented.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/553>
+
+2020-07-03 02:03:15 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * meson.build:
+         Back to development
+
+=== release 1.17.2 ===
+
+2020-07-03 00:22:34 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * ChangeLog:
+       * NEWS:
+       * RELEASE:
+       * gstreamer.doap:
+       * meson.build:
+         Release 1.17.2
+
+2020-07-01 20:20:16 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gststreams.c:
+         stream: Don't use GST_FIXME_OBJECT() when generating a random stream id if the caller didn't provide one
+         That would call into gst_info_describe_stream(), which takes the same
+         mutex a second time and then deadlocks.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/552>
+
+2020-05-11 17:44:43 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstutils.c:
+         gstutils: fix link in parse_bin_from_description_full doc
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/475>
+
+2020-06-26 00:50:44 +1000  Jan Schmidt <jan@centricular.com>
+
+       * gst/gstbin.h:
+         gstbin: Fix docs typo
+         element-added-deep -> deep-element-added in the GstBin doc header
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/547>
+
+2020-06-25 02:14:56 +0900  Seungha Yang <seungha@centricular.com>
+
+       * docs/gst-plugins-doc-cache-generator.py:
+         docs: Specify UTF-8 encoding everywhere
+         Otherwise some non-English character might be broken depending on
+         OS and/or locale.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/545>
+
+2020-06-25 01:37:43 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * hooks/pre-commit.hook:
+         hooks: add opt-in cache update hook
+         CI now checks that plugin caches are up to date, for example
+         when adding a new property to an element.
+         This is something pretty easy to forget, and it can be checked
+         in a pre-commit hook provided the cache generator generates no
+         unnecessart diff on the developer's machine. This is now the
+         case for me in core, -base and -good, and eventually all the
+         repositories should behave appropriately, at least on my
+         development machine.
+         The new check in the pre-commit hook is only performed when
+         the user is in the development environment (it checks
+         $MESON_BUILD_ROOT to determine that), and when the developer
+         has opted-in by setting `GST_CACHE_HOOK=enabled`. That is
+         because the hook will actually rebuild the cache with ninja,
+         and modify it in the source directory, that's not a behaviour
+         we want to enable by default.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/546>
+
+2020-06-24 22:51:48 +0900  Seungha Yang <seungha@centricular.com>
+
+       * tools/gst-inspect.c:
+         gst-inspect: Use gst_info_strdup_vprintf to print string
+         g_vprintf() will write a string binary to stdout directly using fwrite().
+         So, depending on character in the string, fwrite to stdout can
+         print broken one but printf family might not cause the issue.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/544>
+
+2020-06-24 07:54:42 +0200  Michael Olbrich <m.olbrich@pengutronix.de>
+
+       * gst/gstbus.c:
+       * tests/check/gst/gstbus.c:
+         bus: clear bus->priv->signal_watch immediately when the source is removed
+         There is a race-condition that can trigger the assertion in
+         gst_bus_add_signal_watch_full():
+         If gst_bus_add_signal_watch_full() is called immediately after
+         gst_bus_remove_signal_watch() then bus->priv->signal_watch may still be set
+         because gst_bus_source_dispose() or gst_bus_source_finalize() was not yet
+         called.
+         This happens if the corresponding GMainContext has the source queued for
+         dispatch. In this case, the following dispatch will only unref and delete
+         the signal_watch because it was already destroyed. Any pending messages
+         will remain until a new watch is installed.
+         So bus->priv->signal_watch can be cleared immediately when the watch is
+         removed. This avoid the race condition.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/543>
+
+2020-06-23 01:54:15 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+         gst-hotdoc-plugins-scanner: serialize interfaces
+
+2020-06-22 23:41:06 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+         gst-hotdoc-plugins-scanner: don't instantiate base classes
+
+2020-06-21 02:00:54 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+         gst-hotdoc-plugins-scanner: serialize parents in hierarchy when needed
+
+2020-06-22 09:11:07 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+       * docs/meson.build:
+         docs: Document signals and properties only for current type
+
+2020-06-19 22:52:01 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * docs/plugins/gst_plugins_cache.json:
+         doc: Stop documenting properties from parents
+
+2020-06-23 05:18:11 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * gst/gstregistrychunks.c:
+         registry: Print the pointer when printing features
+         This is what we do everywhere else too, useful for debugging.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/542>
+
+2020-06-23 03:43:53 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * gst/gstregistry.c:
+         registry: Use a toolchain-specific registry file on Windows
+         If we load a plugin registry for MinGW plugins when running with MSVC,
+         we will have to write out the whole cache again, and vice-versa. Just
+         use separate cache files so that the cache is actually useful.
+         Closes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/427
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/542>
+
+2020-06-22 12:26:46 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstghostpad.c:
+       * gst/gstghostpad.h:
+         ghostpad: Deprecate gst_ghost_pad_construct()
+         Instead do everything it did as part of GObject::constructed() and
+         change the function to always return TRUE.
+         gst_ghost_pad_construct() was meant to be called by subclasses right
+         after construction of the object to finish construction as it can fail
+         in theory. In practice it's impossible for it to fail, even more so if
+         called directly from GObject::constructed(): The only failure condition
+         is if the newly created proxy pad already has a parent, which is
+         impossible at this point as nothing else can have a reference to it.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/540>
+
+2020-05-19 22:54:20 +0200  Thor Andreassen <ta@toggle.be>
+
+       * tools/gst-inspect-1.0.1:
+       * tools/gst-inspect.c:
+         tools: gst-inspect, add option '--color' with short option '-C'
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/498>
+
+2020-06-18 13:46:29 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gstinfo.c:
+       * gst/gstinfo.h:
+         info: Add a printf extension for ClockTime/ClockTimeDiff pointers
+         Using both GST_TIME_FORMAT+GST_TIME_ARGS and friend is cumbersome, this
+         makes it sensibly more user friendly.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/535>
+
+2020-06-20 00:27:57 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * meson.build:
+         Back to development
+
+=== release 1.17.1 ===
+
+2020-06-19 19:13:36 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * ChangeLog:
+       * NEWS:
+       * RELEASE:
+       * gstreamer.doap:
+       * meson.build:
+         Release 1.17.1
+
+2020-06-19 11:19:43 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * docs/gst-plugins-doc-cache-generator.py:
+       * docs/plugins/gst_plugins_cache.json:
+         doc: Stop recording if building from source/release in plugin cache
+         Closes: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/537
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/537>
+
+2020-06-19 12:01:49 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstbuffer.c:
+       * gst/gstdynamictypefactory.c:
+       * gst/gstdynamictypefactory.h:
+       * gst/gstelement.c:
+       * gst/gstparamspecs.h:
+       * gst/gstparse.c:
+       * gst/gststructure.c:
+       * gst/gsttracerfactory.c:
+       * gst/gsttracerrecord.c:
+       * gst/gsttracerrecord.h:
+       * gst/gsttracerutils.c:
+       * libs/gst/base/gstadapter.c:
+       * libs/gst/base/gstaggregator.h:
+       * libs/gst/base/gstbaseparse.c:
+         Fix up and add various "Since" markers and other related docs fixes
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/536>
+
+2020-06-18 15:52:40 +0700  Roman Shpuntov <roman.shpuntov@gmail.com>
+
+       * gst/gstsystemclock.c:
+         systemclock: Fix clock time conversion on Windows/xbox
+         The returned ratio can be bigger than GST_SECOND, in which case we would
+         forever return 0 for the system clock time. Even in other cases if it's
+         close to GST_SECOND it would result in accuracy loss.
+         Instead of doing the division by GST_CLOCK_TIME_NONE during
+         initialization once, do it every time the clock time is requested.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/575
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/534>
+
+2020-06-12 15:07:42 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstelement.c:
+       * gst/gsttask.c:
+         gst: Delay creation of threadpools
+         Since glib 2.64, gthreadpool will start waiting on a GCond immediately upon
+         creation. This can cause issues if we fork *before* actually using the
+         threadpool since we will then be signalling that GCond ... from another process
+         and that will never work.
+         Instead, delay creationg of thread pools until the very first time we need
+         them. This introduces a minor (un-noticeable) delay when needing a new thread
+         but fixes the issues for all users of GSTreamer that will call gst_init, then
+         fork and actually start pipelines.
+         See https://gitlab.gnome.org/GNOME/glib/-/issues/2131 for more context.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/531>
+
+2020-06-07 12:05:07 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * plugins/elements/gstinputselector.c:
+         inputselector: Push event on selected pad only when one is selected
+         Calling `gst_input_selector_get_active_sinkpad` triggers sinkpad
+         selection but won't notify about it, leading  to breaking code that
+         relying on it. This new code added as part of
+         63ccf45395ce734a2044a58193939a3eda50eb0c was thought to be triggered only
+         when a pad was already selected and not change the behavior otherwise
+         so this commit makes sure it is actually the case.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/issues/766
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/522>
+
+2020-05-27 15:35:41 +0200  Edward Hervey <edward@centricular.com>
+
+       * tests/check/gst/gstdatetime.c:
+         check: Fix datetime unit test for builds without assert
+         If built with assertions disabled, we need to ensure the variable is properly
+         reset before testing
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/530>
+
+2020-06-11 10:56:10 +0900  sohwan.park <sohwan.park@lge.com>
+
+       * tests/check/gst/gstmessage.c:
+         message: Add unit test for GST_MESSAGE_RATE_CHANGE
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/528>
+
+2020-06-11 10:54:54 +0900  sohwan.park <sohwan.park@lge.com>
+
+       * tests/check/gst/gstevent.c:
+         event: Add unit test for INSTANT_RATE_CHANGE and INSTANT_RATE_SYNC_TIME
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/528>
+
+2020-06-11 10:53:59 +0900  sohwan.park <sohwan.park@lge.com>
+
+       * tests/check/gst/gstsegment.c:
+         segment: Add unit test for GST_SEEK_FLAG_INSTANT_RATE_CHANGE
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/528>
+
+2020-06-09 15:06:52 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * docs/plugins/gst_plugins_cache.json:
+         docs: Update plugins cache
+
+2020-06-09 15:05:54 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+         docs: Fix the way we mark properties mutability
+         When nothing is specified, we should default to NULL, not PLAYING
+
+2020-06-10 11:23:42 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: Fix StartTimeSelection enum type registration
+         Make it thread-safe and use the actual C identifiers for the "name"
+         field, as otherwise gobject-introspection will fall apart.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/527>
+
+2020-06-08 10:51:57 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * docs/plugins/gst_plugins_cache.json:
+         docs: Update plugins cache
+
+2016-09-01 17:33:13 +1000  Matthew Waters <matthew@centricular.com>
+
+       * plugins/tracers/gstleaks.c:
+         tracers/leaks: fix reentrancy issues with the custom signal handlers
+         The signal handlers were performing mutex operations in the signal handlers
+         which is bad idea that may lead to deadlocks.
+         1. Implement a separate signal thread to handle the signals.
+         2. Use the glib provided signal GSource to avoid performing operations in
+         the signal handler.
+         Fix #186
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/487>
+
+2020-06-08 22:47:56 +0200  Havard Graff <havard.graff@gmail.com>
+
+       * gst/gst_private.h:
+         gst_private.h: increse padding in struct _GstClockEntryImpl
+         When compiling for 32bit ios arm, the static assert that the
+         GstClockEntryImpl smaller or equal to the struct _GstClockEntryImpl
+         triggered. (they were 12bytes off).
+         To fix this, the padding is increased by 12 bytes (on 32bit).
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/525>
+
+2020-06-08 16:04:51 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * gst/gstparamspecs.h:
+         paramspecs: add 'Since: 1.18' markers for new param spec flags
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/524>
+
+2020-06-07 20:56:49 +0900  Seungha Yang <seungha@centricular.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+         doc: Add GstObject specific GParamFlags
+         Document "controllable", "mutable-{ready, paused, playing}" and
+         "conditonally-available" GParamFlags
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/283>
+
+2019-09-11 13:51:04 +0900  Seungha Yang <seungha.yang@navercorp.com>
+
+       * gst/gstparamspecs.h:
+       * tools/gst-inspect.c:
+         paramspecs: Add a GParamSpecFlag to indicate the property might not always exists
+         Add new flag for users to notice that the property is not guaranteed
+         to exist depending on environment.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/283>
+
+2020-06-07 18:42:21 +0200  Edward Hervey <edward@centricular.com>
+
+       * tests/check/elements/leaks.c:
+         check: Avoid race with leaks test
+         The problem is that the taskpool might not have completely drained by the time
+         we check for leaks.
+         Instead, ensure all tasks have stopped before testing for valid results.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/523>
+
+2020-06-04 17:50:01 +0200  Camilo Celis Guzman <camilo@pexip.com>
+
+       * plugins/elements/gstqueue.c:
+         queue: protect against lost wakeups for iterm_del condition
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/513>
+
+2020-06-06 10:19:57 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+         docs: Prevent potential NULL pointer dereference when serializing plugin object types
+         CID 1464007
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/516>
+
+2020-06-06 08:24:01 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstpadtemplate.c:
+         padtemplate: Directly unreference the documentation caps
+         The public-facing API has a (valid) protection against NULL caps. We can just
+         directly remove it.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/515>
+
+2020-06-06 01:10:09 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstutils.c:
+         utils: fix markdown link to #GstPluginAPIFlags
+
+2020-06-05 23:28:38 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+       * gst/gstpadtemplate.c:
+       * gst/gstpadtemplate.h:
+         padtemplate: expose getters and setters "documentation caps"
+         This can be used in elements where the caps of pad templates
+         are dynamically generated and dependent on the environment.
+         An example is x265enc.
+
+2020-06-05 21:10:29 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+       * gst/gstutils.c:
+       * gst/gstutils.h:
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gstfakesink.c:
+       * plugins/elements/gstfakesrc.c:
+       * plugins/elements/gstfilesink.c:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstoutputselector.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gsttee.c:
+       * tests/check/gst/gstutils.c:
+         utils: expose GstPluginAPIFlags
+         These can be passed to gst_type_mark_as_plugin_api, to inform
+         plugin cache generation.
+         For now a single flag is specified, "IGNORE_ENUM_MEMBERS", it
+         can be used for dynamically generated enums to avoid documenting
+         environment-specific enumeration members. An example is
+         GstX265EncTune.
+
+2020-06-01 16:18:50 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * plugins/elements/gstclocksync.c:
+       * plugins/elements/gstidentity.c:
+       * tests/check/gst/gstbin.c:
+         identity, clocksync: implement provide_clock
+         Since those are using the clock for sync, they need to also
+         provide a clock for good measure. The reason is that even if
+         downstream elements provide a clock, we don't want to have
+         that clock selected because it might not be running yet.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/509>
+
+2020-06-02 22:39:41 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gststructure.c:
+         structure: Quickly document serialization format
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/510>
+
+2020-06-03 09:17:32 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gststructure.c:
+         structure: Reflow the SECTION comment
+         Removing trailing whitespaces and avoiding to exceed 80chars
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/510>
+
+2020-05-27 03:41:37 +1000  Jan Schmidt <jan@centricular.com>
+
+       * plugins/elements/gstqueue2.c:
+         queue2: Defer downstream bitrate query to the streaming thread.
+         When we want to perform a downstream bitrate query, just
+         set the reconfigure flag on the srcpad and get the streaming
+         thread to do it. That avoids emitting a downstream query
+         when receiving the upstream RECONFIGURE event - which can
+         lead to deadlocks if downstream is sending the event from
+         within a lock - e.g. input-selector.
+         If querying the downstream bitrate changes the cached
+         value, then make sure to update our buffering state
+         and potentially post a BUFFERING message to the application.
+         Fixes: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/566
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/501>
+
+2020-06-03 08:09:04 +0200  Edward Hervey <edward@centricular.com>
+
+       * plugins/elements/gstinputselector.c:
+         inputselector: Avoid deadlock when requesting pads
+         The deadlock was the following:
+         * One thread requests a new pad, the internal lock is kept while adding the pad
+         * Another thread (or the same one) requests the internal links of a pad (could
+         be that pad)... which also requires that lock.
+         That internal lock is not required when adding the pad to the element (which is
+         the last action when requesting a new pad). The fact it will be actually used
+         will be *after* the request pad function is released.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/512>
+
+2020-06-04 03:24:50 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstparamspecs.h:
+       * gst/gstvalue.h:
+         doc: document fundamental types
+
+2020-06-03 18:33:51 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * docs/meson.build:
+         doc: Require hotdoc >= 0.11.0
+
+2020-06-02 22:25:24 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+         docs: Don't include GObject and GstPipeline signals
+         They're already documented from elsewhere.
+
+2020-06-02 12:25:00 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+       * libs/gst/base/gstaggregator.h:
+         aggregator: Export GstAggregatorStartTimeSelection in the header and document it
+         It is used by one of the aggregator properties and was private in the
+         source file before.
+
+2020-05-25 16:21:12 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * docs/plugins/gst_plugins_cache.json:
+         docs: Update gst_plugins_cache.json
+
+2020-05-28 21:51:22 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gstfakesink.c:
+       * plugins/elements/gstfakesrc.c:
+       * plugins/elements/gstfilesink.c:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstoutputselector.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gsttee.c:
+         plugins: Use gst_type_mark_as_plugin_api() for all non-element plugin types
+
+2020-05-28 23:40:09 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+         docs: Store all non-element types in a separate other-types array
+         And also make sure to not duplicate them.
+
+2020-05-28 22:59:09 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+         docs: Use gst_type_is_plugin_api() for deciding whether a type should be included in the docs
+
+2020-05-28 20:56:14 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+       * gst/gstutils.c:
+       * gst/gstutils.h:
+         utils: Add helper function for marking types as plugin API
+         This can be used to mark additional types exposed by plugins (i.e.
+         enums, flags and GObjects) via properties, signals or pad templates as
+         plugin API. They can then be picked up by the documentation for the
+         plugin.
+         Not all types exposed by plugins are documented automatically because
+         they might come from an external library and should be documented from
+         there instead.
+
+2020-05-26 13:06:20 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+         docs: Don't try to print pad templates of non-GstElement types
+
+2020-05-21 17:33:36 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+       * docs/meson.build:
+         docs: Print object/flag/enum type information in a more structured way and in more places
+         Custom types are printed now for signal parameters/return value and properties, and more consistently.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gst-docs/-/issues/59
+
+2020-06-04 11:21:45 +0200  Edward Hervey <edward@centricular.com>
+
+       * plugins/elements/gstqueue2.c:
+         queue2: Avoid races when posting buffering messages
+         When posting a buffering message succesfully:
+         * Remember the *actual* percentage value that was posted
+         * Make sure we only reset the percent_changed variable if the value we just
+         posted is indeed different from the current value
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/511>
+
+2020-05-28 14:56:26 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * tests/validate/meson.build:
+         tests:validate: Whitelist validate plugins
+         This is required so we can use validateflow for example
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/506>
+
+2020-05-28 12:39:08 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * tests/validate/gst-tester.c:
+         tester: Fix exit code on bailout/skipping
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/506>
+
+2020-05-27 20:22:49 +1000  Matthew Waters <matthew@centricular.com>
+
+       * gst/gstpromise.c:
+         promise: update documentation and annotations for NULL replies
+         The implementation and tests already handle NULL replies.
+         Fixes: https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/issues/1300
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/502>
+
+2020-05-27 12:26:01 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * tests/check/elements/leaks.c:
+         tests: leak tracer: disable stack traces for faster test execution
+         This test takes 39 seconds on my machine even though it just runs
+         a couple of fakesrc num-buffers=2 ! fakesink pipelines. Most of
+         the cpu seems to be spent in libz, related to stack trace management.
+         Use stack-traces-flags=none instead of stack-traces-flags=full
+         until a better solution can be found. Might warrant more
+         investigation in any case..
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/503>
+
+2020-05-20 17:32:48 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * plugins/elements/gstqueue2.c:
+       * tests/check/elements/queue2.c:
+         queue2: don't post unnecessary buffering message, refine locking
+         This is a follow up to review comments in !297
+         + The posting of the buffering message in READY_TO_PAUSED isn't
+         needed, removing it made the test fail, but the correct fix
+         was simply to link elements together
+         + Move code to relock the queue and set last_posted_buffering_percent
+         and percent_changed inside the buffering_post_lock in create_write().
+         This makes locking consistent with post_buffering()
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/297>
+
+2019-10-04 16:57:29 +0200  Carlos Rafael Giani <crg7475@mailbox.org>
+
+       * plugins/elements/gstqueue2.c:
+       * tests/check/elements/queue2.c:
+         queue2: Fix missing/dropped buffering messages at startup
+         This fixes a bug that occurs when an attempt is made to post a buffering
+         message before the queue2 was assigned a bus. One common situation where
+         this happens is when the use-buffering property is set to TRUE before the
+         queue2 was added to a bin.
+         If the result of gst_element_post_message() is not checked, and the
+         aforementioned situation occurs, then last_posted_buffering_percent and
+         percent_changed will still be updated, as if posting the message succeeded.
+         Later attempts to post again will not do anything because the code then
+         assumes that a message with the same percentage was previously posted
+         successfully and posting again is redundant.
+         Updating these variables only if posting succeed and explicitely
+         posting a buffering message in the READY->PAUSED state change ensure that
+         a buffering message is posted as early as possible.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/297>
+
+2020-05-25 14:56:10 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstsystemclock.c:
+         systemclock: Only try initializing entries if they were not initialized before
+         And add assertions accordingly.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/500>
+
+2020-05-25 12:51:19 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstsystemclock.c:
+         systemclock: Clarify comment that described a previous version of the code
+         Nowadays we are only waking up the head entry waiting if either the head
+         entry is unscheduled (which is handled some lines above already), or
+         when the head entry specifically is woken up because a new entry became
+         the new head entry.
+         We're not waking up *all* entries anymore whenever any entry in the last
+         was unscheduled.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/500>
+
+2020-05-22 19:28:54 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstsystemclock.c:
+         systemclock: Get rid of atomic access to clock entry status and use the mutex instead
+         We already have a mutex in each clock entry anyway and need to make use
+         of that mutex in most cases when the status changes. Removal of the
+         atomic operations and usage of the mutex instead simplifies the code
+         considerably.
+         The only downside is that unscheduling a clock entry might block for the
+         time it needs for the waiting thread to go from checking the status of
+         the entry to actually waiting, which is not a lot of code.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/500>
+
+2020-05-22 18:12:55 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstsystemclock.c:
+         systemclock: Don't start waiting for a clock id if it was signalled before
+         Otherwise it can happen that unscheduling a clock id never takes place
+         and instead it is waiting until the normal timeout. This can happen if
+         the wait thread checks the status and sets it to busy, then the
+         unschedule thread sets it to unscheduled and signals the condition
+         variable, and then the waiting thread starts waiting. As condition
+         variables don't have a state (unlike Windows event objects), we have to
+         remember ourselves in a new boolean flag protected by the entry mutex
+         whether it is currently signalled, and reset this after waiting.
+         Previously this was not a problem because a file descriptor was written
+         to for waking up, and the token was left on the file descriptor until
+         the read from it for waiting.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/500>
+
+2020-02-15 22:20:18 +0530  dhilshad <mohddhilshadm@gmail.com>
+
+       * plugins/elements/gstsparsefile.c:
+         sparsefile: fix possible crash when seeking
+         In gst_sparse_file_clear function we were closing a file and
+         reopening it using closed file descriptor.
+         Fix: Removed closing and reopening of file.
+         Fixes #512
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/372>
+
+2017-11-04 13:28:03 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gstvalue.c:
+       * tests/check/gst/gstvalue.c:
+         value: Fix comparison of int/int64 ranges
+         ranges are only equal if:
+         * Their bounds are equal
+         * And their step value are equal *IF* they contain more than one value
+         https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/253
+
+2020-05-12 02:05:25 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * plugins/elements/gstfdsink.c:
+         fdsink: do not supress legitimate errors when unlocking
+         Instead, only wait_preroll when writev_* returns FLUSHING
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/476>
+
+2020-05-12 00:57:36 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * plugins/elements/gstfdsink.c:
+       * plugins/elements/gstfdsink.h:
+         fdsink: remove unused struct member `bytes_written`
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/476>
+
+2020-05-12 00:54:56 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * plugins/elements/gstfilesink.c:
+         filesink: port over unlock code from fdsink
+         See also: 5216322d39448ed61c86bb1b3dd9c8c5e6feccf3
+         The previous code was causing "random" flushing returns
+         in scenarios with intensive state changes such as within
+         a buffering pipeline.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/476>
+
+2020-05-19 22:24:39 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+         docs: Add boolean field for readability of properties
+         Some properties are write-only.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/496>
+
+2020-05-19 10:34:01 +0200  Thor Andreassen <ta@toggle.be>
+
+       * tools/gst-inspect-1.0.1:
+         tools: option '-u' occurs twice in gst-inspect-1.0.1
+         I have removed the erroneous one according to the source file.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/492>
+
+2020-05-19 14:16:49 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * tests/validate/gst-tester.c:
+         tester: Stop using g_file_new_build_filename
+         It was introduced in GLib 2.56 only
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/560
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/495>
+
+2020-05-04 17:05:07 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * tests/meson.build:
+       * tests/validate/gst-tester.c:
+       * tests/validate/meson.build:
+       * tests/validate/simplest.validatetest:
+       * tests/validate/simplest/flow-expectations/log-sink-sink-expected:
+         tests: Add a gst-tester utility
+         gst-tester is a tool to launch `.validatetest` files with
+         TAP[0] compatible output and supporting missing `gst-validate`
+         application which means that it can be cleanly integrated with meson
+         test harness.
+         It allows us to use `gst-validate` to write integration tests in any
+         GStreamer repository keeping them as close as possible to the code. It
+         can simplify a lot test writing and reading and not having to go into
+         another repository to implement or run tests makes it more convenient to
+         use.
+         This also implements a stupid simple test to show how that works
+         [0] https://testanything.org/
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/461>
+
+2020-05-19 09:30:50 +0000  Stéphane Cerveau <scerveau@collabora.com>
+
+       * docs/random/moving-plugins:
+         docs: update moving-plugins to use gitlab and meson
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/493>
+
+2020-05-18 10:46:04 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstbin.c:
+         gstbin: Remove mentions of duration caching
+         This was effectively disabled in 1.0 with the intent of maybe re-enabling it.
+         The problem is that caching duration at a bin level doesn't make much sense
+         since there might be queueing/buffering taking place internally and therefore
+         the duration reported might have no correlation to what is actually being
+         outputted.
+         Remove commented code and fixmes, and update documentation
+         Fixes #4
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/489>
+
+2020-05-15 11:48:07 +0000  Thibault Saunier <tsaunier@igalia.com>
+
+       * plugins/elements/gstinputselector.c:
+         input-selector: Ensure events are forwarded only once per pad
+         The code was prepared to do it but was missing to fill the pushed_pads
+         list.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/485>
+
+2020-05-14 17:13:05 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * plugins/elements/gstinputselector.c:
+         inputselector: Ensure that events are pushed first on active pad
+         Making it less random and fixing a race in a GES test where we have
+         as pipeline:
+         ```
+         videotestsrc ! output-selector name=s ! input-selector name=i s. ! timecodestamper ! i.
+         ```
+         which we seek, leading to the seek reaching the video testsrc
+         without going through the timecodestamper and generating a buffer
+         even before timecodestamper gets the seek which means that its internal
+         state is wrong compared to the datastream it gets and attaches wrong
+         timecode metas.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/485>
+
+2020-05-15 10:38:30 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+         docs: Add list of interfaces implemented by elements to the docs
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/486>
+
+2020-05-13 17:35:01 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * libs/gst/helpers/gst_gdb.py:
+         gdb: Print event seqnums, object pointers and structures
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/482>
+
+2020-05-13 17:34:12 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * libs/gst/helpers/gst_gdb.py:
+         gdb: Add support for queries and buffers
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/482>
+
+2020-05-13 17:07:43 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstinputselector.h:
+         inputselector: Never reset active pad set from the user
+         This was leading to interesting races in a GES test.
+         Related to: https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/issues/108
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/481>
+
+2020-05-14 12:13:07 +0200  Edward Hervey <edward@centricular.com>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: Minor refactoring
+         Move checks related to peerfilter in one place. No impact except for logic.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/484>
+
+2020-05-14 11:32:39 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstvalue.c:
+         gstvalue: Minor list intersection optimization
+         When matching against the 2nd list, increment the starting position of the inner
+         list iteration.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/484>
+
+2020-05-07 21:06:18 +0800  Xu Guangxin <guangxin.xu@intel.com>
+
+       * gst/gstbufferpool.c:
+         bufferpool: unblock acquire thread when we discard buffer
+         else the acquire thread will wait infinitely.
+         The deadlock showed in prevous unit test commit. This will fix it
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/470>
+
+2020-05-11 18:21:48 +0800  Xu Guangxin <guangxin.xu@intel.com>
+
+       * tests/check/gst/gstbufferpool.c:
+         tests: bufferpool: add dead lock test for buffer discard
+         you will see a deadlock after you apply this patch, and run following commandline:
+         GST_STATE_IGNORE_ELEMENTS=1 tests/check/gst_gstbufferpool
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/470>
+
+2020-05-11 22:27:14 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * plugins/elements/gstoutputselector.c:
+       * plugins/elements/gstoutputselector.h:
+         output-selector: Drop duplicated seek events
+         When we get a seek event on several source pads, we should drop
+         the duplicated ones as any element that has several srcpads (like
+         demuxers).
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/478>
+
+2020-05-12 05:58:38 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * tests/check/meson.build:
+         meson: Pass native: false to add_languages()
+         This is needed for cross-compiling without a build machine compiler
+         available. The option was added in 0.54, but we only need this in
+         Cerbero and it doesn't affect older versions so it should be ok.
+         Will just cause a spurious warning.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/477>
+
+2020-05-12 16:42:42 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * libs/gst/helpers/gst_gdb.py:
+         gdb: Fix iterating GstStructure fields
+         This broke with 1b568fa01fa16885c3a7368551034c206493a41a where we inlined the array
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/479>
+
+2020-05-10 11:37:45 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * docs/plugins/gst_plugins_cache.json:
+         docs: Update gst_plugins_cache.json
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/474>
+
+2020-05-10 11:35:53 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * docs/gst-plugins-doc-cache-generator.py:
+         docs: Output JSON files with UTF-8 encoding
+         Otherwise non-ASCII characters are encoded as \uXXXX.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/474>
+
+2020-05-08 17:21:20 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstvalue.c:
+         gstvalue: Fix segment (de)serialization
+         By using the proper quarks (stored in the indirection table) and not the *enums*
+         of those entry in the quark table.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/473>
+
+2020-05-08 08:03:54 +0200  Edward Hervey <edward@centricular.com>
+
+       * tests/check/gst/gsturi.c:
+         check: uri: Check return value
+         CID #1455381
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/472>
+
+2020-05-08 08:02:12 +0200  Edward Hervey <edward@centricular.com>
+
+       * tests/check/gst/gstvalue.c:
+         check: gstvalue: Check return value
+         As is done everywhere else
+         CID #1455540
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/472>
+
+2020-05-08 07:43:02 +0200  Edward Hervey <edward@centricular.com>
+
+       * tests/check/libs/gsttestclock.c:
+         check: testclock: Check return values
+         As done everywhere else.
+         CID #1455383
+         CID #1455524
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/472>
+
+2020-05-08 07:03:49 +0200  Edward Hervey <edward@centricular.com>
+
+       * tests/check/gst/gstpromise.c:
+         check: gst_promise_reply() takes ownership
+         Copy the structure temporarily to check it further down.
+         CID #1455392
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/472>
+
+2020-05-08 06:49:45 +0200  Edward Hervey <edward@centricular.com>
+
+       * tests/check/gst/gstprintf.c:
+         check: Don't leak test string
+         Turns out the length returned by `__gst_vasprintf()` doesn't include the final
+         `\0`.
+         CID #1455430
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/472>
+
+2020-05-07 23:00:13 +0200  Matej Knopp <matej.knopp@gmail.com>
+
+       * gst/gsttaglist.c:
+       * tests/check/gst/gsttag.c:
+         taglist: Fix crash when comparing two lists of the same length but with different items
+         Fixes #549
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/469>
+
+2020-05-07 03:28:59 +1000  Jan Schmidt <jan@centricular.com>
+
+       * tests/check/elements/selector.c:
+         tests/input selector: Fix a shutdown crash
+         Hold a ref to the pad we're planning on sending EOS too, so that
+         it doesn't disappear if things shut down before the thread gets
+         to actually send the EOS event.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/467>
+
+2020-04-28 22:21:13 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * plugins/elements/gstidentity.c:
+       * plugins/elements/gstidentity.h:
+         identity: Handle seeking with single_segment=True
+         Identity was ignoring seek and flush events even when using
+         a single segment. In the end it means that we couldn't compute
+         buffers running-time and stream time after seeks.
+         This commits adds support for flushing seeks only as I have no idea
+         what to do for non flushing ones.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/450>
+
+2020-04-28 13:28:32 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * plugins/elements/gstclocksync.c:
+       * plugins/elements/gstidentity.c:
+         identity,clocksync: Fix timestamping inside single segment in reverse playback
+         In reverse playback, buffers are played back from buffer.stop
+         (buffer.pts + buffer.duration) to buffer.pts running times which
+         mean that we need to use the buffer end running time as a buffer
+         timestsamp, not the buffer pts when using a single segment in reverse
+         playback.
+         This is now being tested in
+         `validate.test.identity.reverse_single_segment`
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/450>
+
+2020-04-23 16:24:15 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * libs/gst/base/gstbasesink.c:
+         basesink: Fix clock synchronization running time in reverse playback
+         In reverse playback, buffers have to be displayed at buffer.stop running
+         time, otherwise a same set of buffer can't be displayed in the exact opposite
+         order to forward playback.
+         For example, seeking a video stream at 1fps with start=0, stop=5s, rate=1.0
+         will display the following buffers:
+         b0.pts = 0s, b0.duration = 1s - at running time = 0s
+         b1.pts = 1s, b1.duration = 1s - at running time = 1s
+         b2.pts = 2s, b2.duration = 1s - at running time = 2s
+         b3.pts = 3s, b3.duration = 1s - at running time = 3s
+         b4.pts = 4s, b4.duration = 1s - at running time = 4s
+         <wait at EOS for 1second>
+         Now, playing that reverse with start=0, stop=5s, rate=1.0 has to display
+         the following buffers:
+         b0.pts = 4s, b0.duration = 1s - at running time = 0s
+         b1.pts = 3s, b1.duration = 1s - at running time = 1s
+         b2.pts = 2s, b2.duration = 1s - at running time = 2s
+         b3.pts = 1s, b3.duration = 1s - at running time = 3s
+         b4.pts = 0s, b4.duration = 1s - at running time = 4s
+         <wait at EOS for 1second>
+         With the previous code, it reproduced the following:
+         b0.pts = 4s, b0.duration = 1s - at running time = 1s
+         b1.pts = 3s, b1.duration = 1s - at running time = 2s
+         b2.pts = 2s, b2.duration = 1s - at running time = 3s
+         b3.pts = 1s, b3.duration = 1s - at running time = 4s
+         b4.pts = 0s, b4.duration = 1s - at running time = 5s
+         <NO WAIT AT EOS AND POST EOS RIGHT AWAY>
+         This is being tested with the `validate.launch_pipeline.sink.reverse_playback_clock_waits.*`
+         set of tests
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/450>
+
+2020-04-23 16:10:24 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: Fix the way position is computed in reverse playback
+         In reverse playback, buffers are played back from buffer.stop
+         (buffer.pts + buffer.duration) to buffer.pts, which means that the
+         position after the buffer is consumed is buffer.pts, not buffer.pts -
+         buffer.duration.
+         Without that change, and when `automatic_eos` feature is on,
+         we were dropping the last buffers as marking the stream EOS one buffer
+         too soon.
+         This is now being tested extensively by GstValidate in the
+         `validate.test.clock_sync.*` set of tests.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/450>
+
+2020-05-02 12:01:49 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * pkgconfig/gstreamer-uninstalled.pc.in:
+       * pkgconfig/gstreamer.pc.in:
+         pkgconfig: add pluginscannerdir variable
+         So we can get this in a unified way from installed
+         and uninstalled GStreamer when using pkg-config to
+         set up test environments in other modules.
+         See https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/582
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/456>
+
+2020-05-06 11:59:15 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gsttaglist.c:
+         taglist: Make equality check more uniform
+         Previously this was iterating over taglists with ... string names.
+         Instead use the same technique as `gst_structure_is_equal()` with the additional
+         double check.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/466>
+
+2020-05-06 10:07:30 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstregistrybinary.c:
+         registrybinary: Also call fclose() if fflush()/fsync() failed
+         Otherwise we would be leaking the file in error cases.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/465>
+
+2020-05-06 09:59:47 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstregistrybinary.c:
+         registrybinary: Don't call fclose() more than once
+         We must not retry fclose() on EINTR as POSIX states:
+         After the call to fclose(), any use of stream results in undefined
+         behavior.
+         We ensure above with fflush() and fsync() that everything is written out
+         so chances of running into EINTR are very low. Nonetheless assume that
+         the file can't be safely renamed, we'll just try again on the next
+         opportunity.
+         CID #1462697
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/465>
+
+2020-05-06 08:04:28 +0200  Edward Hervey <edward@centricular.com>
+
+       * plugins/elements/gstqueue2.c:
+         queue2: Use explicit limit checking
+         When we know we'll only be checking the real limits, use a clearer/simpler
+         macro.
+         CID #1037148
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/464>
+
+2020-04-15 17:49:37 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gstsegment.h:
+         segment: Enhance the GstSegment structure documentation
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/435>
+
+2020-05-05 13:20:10 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+       * docs/plugins/gst_plugins_cache.json:
+         doc: Add signal flags information in the plugin cache
+         Updating the plugin cache file
+         Same behavior as g-ir as the signal flags don't have a GType associated.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/463>
+
+2020-05-03 18:50:26 +0200  Richard Kreckel <kreckel@ginac.de>
+
+       * gst/gstregistrybinary.c:
+         registrybinary: Use a FILE* in BinaryRegistryCache...
+         ...instead of a file descriptor so buffered I/O is used when writing
+         the binary cache. This boosts performance at startup, particularly on
+         network filesystems where writes may be quite slow.
+         Fixes gstreamer#545.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/458>
+
+2020-04-23 14:57:59 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+       * gst/gstvalue.c:
+         gstvalue: Use quark-based structure usage for segment (de)serialization
+         Instead of string-based one. Smaller and faster code
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/453>
+
+2020-04-17 17:14:36 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstvalue.c:
+         value: Handle runtime checks as such
+         The various `g_strdup_printf()` returns values are runtime checks
+         which could be disabled if one wants and therefore should be
+         handled as such with g_return_val_if_fail()
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/453>
+
+2020-05-01 15:15:46 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstvalue.c:
+         gstvalue: Remove useless checks
+         The calling function already checks that the values exists and it's
+         a valid list
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/453>
+
+2020-05-01 14:50:52 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstvalue.c:
+         gstvalue: Use previous assumption
+         The types were already checked for equality just before, not need to
+         check for that again
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/453>
+
+2020-05-01 14:48:37 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstvalue.c:
+         gstvalue: Use comparision functions directly
+         We know the types of values, just use the comparision function directly
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/453>
+
+2020-05-01 14:45:28 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstvalue.c:
+       * gst/gstvalue.h:
+         gstvalue: Minor optimization for checks
+         For value types that aren't subclassable, just check the type directly.
+         For flags, compare against the fundamental type directly instead of going through
+         the more expensive recursive check of `G_TYPE_CHECK_VALUE_TYPE()`
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/453>
+
+2020-03-23 17:03:51 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gstvalue.c:
+         gstvalue: Optimize list subset some more
+         Avoid going through the double subtract function when comparing
+         anything to a list.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/453>
+
+2020-03-23 17:01:20 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gstvalue.c:
+         gstvalue: Optimize gst_value_compare_list
+         The compare function only needs to be retrieved once and used
+         directly
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/453>
+
+2020-03-21 13:05:33 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gstvalue.c:
+         gstvalue: Avoid temporary allocation
+         The problem is that:
+         * g_value_init will end up allocating an internal list/array
+         * g_value_copy *clears* the existing value by calling the free func
+         and then the copy function (creating it again)
+         To avoid that alloc/free/alloc cycle, directly call the appropriate
+         function
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/453>
+
+2020-03-23 08:20:58 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gstcaps.c:
+         gstcaps: Move assignment outside loop
+         s1 and f1 stay the same within the inner loop
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/453>
+
+2020-03-23 08:10:53 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gststructure.c:
+         gststructure: inline gst_structure_is_subset()
+         Having direct access to the iteration allows tighter code and
+         also being able to stop earlier.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/453>
+
+2020-03-23 08:06:26 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gststructure.c:
+         gststructure: Inline gst_structure_intersect()
+         Having direct access to the iteration allows tighter code and
+         also being able to stop earlier.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/453>
+
+2020-05-05 10:47:07 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gst_private.h:
+       * gst/gstregistry.c:
+       * gst/gstregistrychunks.c:
+         gstregistry: Directly get list of plugin features
+         Previously this was:
+         * iterating and referencing all plugin features in a GList
+         * *then* filtering out the ones we want
+         * Was doing that filtering by name (i.e. `strcmp`) instead of direct pointer
+         comparision
+         Instead, just create a private direct function to get the list of plugin
+         features
+         Uses 4 times less instructions ...
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/462>
+
+2020-05-04 16:51:19 +0000  Rubén Gonzalez <rgonzalez@fluendo.com>
+
+       * gst/gstplugin.c:
+         plugin: Fix typo with GStremaer version:
+         ```
+         has incompatible version (plugin: 1.15, gst: 1,12)
+         ```
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/460>
+
+2020-05-01 15:03:55 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstvalue.c:
+         gstvalue: No longer store same-type intersection functions in table
+         The intersection function table is a legacy of 2005, when one could
+         register random intersection functions. This is no longer the case.
+         The only place where that table was used was:
+         * `gst_value_can_intersect()`, where it was already only used for identical
+         GType
+         * `gst_value_intersect()`, where the table iteration was insanely expensive
+         Instead this patch:
+         * Only stored intersection functions for *different* types (of which there are
+         only 4)
+         * Make gst_value_intersect directly call the same-type intersection functions
+         and only use the table if ever it doesn't match.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/454>
+
+2020-05-01 17:27:07 +0200  Edward Hervey <bilboed@bilboed.com>
+
+       * gst/gstpad.c:
+         gstpad: Simplify task name creation
+         This was going through a few locks and doing temporarily allocations for every
+         single task creation.. just to get a name.
+         We don't need to take locks since:
+         * The parent exists (we have a reference to it)
+         * The pad exists (the task belongs to it)
+         * Changing names of pad/elements when activating is a big no-no
+         Instead use the existing direct GST_DEBUG_PAD_NAME macro
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/455>
+
+2020-05-01 17:30:20 +0200  Edward Hervey <bilboed@bilboed.com>
+
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstpad.c:
+         gstevent: Add function for checking event name by GQuark
+         Avoids doing string<=>quark conversions in the sticky event handling path.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/455>
+
+2020-04-17 17:12:10 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstcaps.c:
+         caps: Unify common checks for intersections
+         Regardless of the intersect method chosen, migrate the same checks
+         up into the calling function. Same result, just less code.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/455>
+
+2020-04-15 09:09:22 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstregistry.c:
+         gstregistry: Remove unneeded call
+         _priv_gst_preload_plugins is only filled if option parsing is active.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/455>
+
+2020-05-01 10:19:08 +0200  Edward Hervey <bilboed@bilboed.com>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: Don't get flow name if not needed
+         Put it in the debug call so it's only called when/if needed
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/455>
+
+2020-04-22 10:26:45 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gstclocksync.c:
+       * plugins/elements/gstclocksync.h:
+       * tests/check/elements/clocksync.c:
+         clocksync: Remove handoff signals
+         They're not really useful on this element and were just a leftover from
+         identity.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/540
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/443>
+
+2020-05-03 16:11:39 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+       * libs/gst/base/gstaggregator.h:
+         aggregator: Mark segment parameter as const in gst_aggregator_update_segment()
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/457>
+
+2020-02-24 11:24:16 +0000  Tim-Philipp Müller <tim@centricular.com>
+
+       * tools/gst-stats.c:
+         tools: gst-stats: parse thread-id in windows debug logs properly
+         They don't seem to have the "0x" prefix.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/376>
+
+2020-05-01 10:07:09 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstsystemclock.h:
+       * libs/gst/check/gsttestclock.c:
+         Add missing colons to Since markers in the docs
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/452>
+
+2020-04-28 00:33:22 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * plugins/elements/gstmultiqueue.c:
+         multiqueue: fix link-like syntax in doc
+
+2020-04-24 12:47:52 +1000  Matthew Waters <matthew@centricular.com>
+
+       * libs/gst/check/gstharness.c:
+         harness: also forward context queries between harnesses
+         Fixes multiple OpenGL contexts being created with a setup like:
+         h = gst_harness_new ("glcolorconvert");
+         gst_harness_add_src (h, "gltestsrc", FALSE);
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/448>
+
+2020-04-22 12:58:35 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: Always clear drain flag before pulling
+         In pull mode, each pull is unique. A following pull can be well inside the
+         range even if the previous one wasn't. Fix this my moving the drain flag
+         right before the pull.
+         This avoids passing a bad drain flag to parsers, which may endup truncate
+         buffers causing data corruption.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/issues/1275
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/446>
+
+2020-04-23 15:46:48 +1000  Matthew Waters <matthew@centricular.com>
+
+       * pkgconfig/gstreamer-check-uninstalled.pc.in:
+       * pkgconfig/gstreamer-check.pc.in:
+       * pkgconfig/meson.build:
+         build: libcheck may require linking against rt
+         In static linking scenarios, this is required to avoid this error
+         building tests:
+         /work/prefix/lib/libgstcheck-1.0.a(check_run.c.o): In function `tcase_run_tfun_fork':
+         /work/gstreamer/_builddir/../../../src/gstreamer/libs/gst/check/libcheck/check_run.c:476: undefined reference to `timer_create'
+         /work/gstreamer/_builddir/../../../src/gstreamer/libs/gst/check/libcheck/check_run.c:483: undefined reference to `timer_settime'
+         /work/gstreamer/_builddir/../../../src/gstreamer/libs/gst/check/libcheck/check_run.c:493: undefined reference to `timer_delete'
+         /work/prefix/lib/libgstcheck-1.0.a(check.c.o): In function `check_get_clockid':
+         /work/gstreamer/_builddir/../../../src/gstreamer/libs/gst/check/libcheck/check.c:628: undefined reference to `timer_create'
+         /work/gstreamer/_builddir/../../../src/gstreamer/libs/gst/check/libcheck/check.c:629: undefined reference to `timer_delete'
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/447>
+
+2020-04-22 18:59:54 +0200  Juan Navarro <juan.navarro@gmx.es>
+
+       * gst/gstcaps.c:
+         gstcaps: fix out of bounds checks
+         These two checks could end up allowing out of bounds array access, when
+         the index equals the array size.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/445>
+
+2020-04-21 19:33:08 +1000  Matthew Waters <matthew@centricular.com>
+
+       * gst/gstvalue.c:
+         Revert "gstvalue: Avoid expensive fallback on intersection"
+         This reverts commit cd751c2de39969ab6187eab12e4e8a85e0467cf7.
+         Reverts https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/406
+         Fixes glviewconvert negotiation in e.g.:
+         gltestsrc ! glviewconvert output-mode-override=side-by-side ! glstereosplit name=s s.left ! queue ! fakesink s.right ! queue ! glimagesink
+         Problem here is that intersecting flagsets in gst_value_intersect will
+         always find a value comparison function but may fail a direct type
+         comparison due to flagsets supporting derived types.  When flagset
+         derived types are intersected, an intersection will therefore always
+         fail.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/441>
+
+2020-04-22 20:19:23 +0900  Seungha Yang <seungha@centricular.com>
+
+       * gst/gstsystemclock.c:
+         systemclock: Fix clock waiting on Windows
+         Add missing parentheses in macro for the divide operation
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/444>
+
+2020-04-21 18:14:00 +0100  Charlie Turner <cturner@igalia.com>
+
+       * gst/gstdebugutils.c:
+         debugutils: Skip multiqueue stats in dot dump
+         If this is not done, tools like xdot fail with "unexpected char
+         b'\\'". This is a regression caused by commit
+         74938f07c2a9b3411716fa7595178942c80e20f4 (multiqueue: Add stats
+         property).
+         The deserialized value coming out of g_object_get_property looks like
+         this,
+         $24 = (gchar *) 0x7f560c0046a0 "application/x-gst-multi-queue-stats, queues=(structure)< \\\"queue_0\\\\,\\\\ buffers\\\\=\\\\(uint\\\\)39\\\\,\\\\ bytes\\\\=\\\\(uint\\\\)8
+         120251\\\\,\\\\ time\\\\=\\\\(guint64\\\\)1460000000\\\\;\\\", \\\"queue_1\\\\,\\\\ buffers\\\\=\\\\(uint\\\\)186\\\\,\\\\ bytes\\\\=\\\\(uint\\\\)838020\\\\,\\\\ time\\\\=\
+         \\\(guint64\\\\)1984000002\\\\;\\\" >;"
+         That is immediately looking wrong. I don't know enough about GNOME
+         serialization details to say with confidence what happened here. It
+         gets worse after this is sent through g_strescape and then written to
+         the dot file. Interestingly, dot -Tpng is fine to ignore them it
+         seems.
+         Since the stats are by definition verbose, I decided the best choice
+         to omit them from the dot file, since such details are not of interest
+         there.
+         Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/442>
+
+2020-04-20 16:21:10 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+       * gst/gstbin.c:
+       * gst/gstchildproxy.c:
+       * gst/gstiterator.c:
+       * gst/gstpad.c:
+       * gst/gstpreset.c:
+       * gst/gstregistrychunks.c:
+       * gst/gstsystemclock.c:
+       * gst/parse/grammar.y.in:
+       * libs/gst/base/gstcollectpads.c:
+       * tests/benchmarks/complexity.c:
+       * tests/benchmarks/mass-elements.c:
+       * tests/check/elements/tee.c:
+       * tests/check/gst/gstelement.c:
+       * tests/check/gst/gstelementfactory.c:
+       * tests/check/gst/gstobject.c:
+       * tests/check/gst/gstparamspecs.c:
+       * tests/check/gst/gstsystemclock.c:
+       * tests/check/gst/gsttagsetter.c:
+       * tests/check/gst/gsttocsetter.c:
+       * tests/check/gst/gsttracerrecord.c:
+       * tests/check/pipelines/parse-launch.c:
+       * tests/examples/helloworld/helloworld.c:
+       * tests/examples/netclock/netclock-client.c:
+       * tests/examples/streamiddemux/streamiddemux-stream.c:
+         Use gst_object_unref() / gst_object_clear() instead of the GObject ones
+         To allow the refcounting tracer to work better. In childproxy/iterator
+         these might be plain GObjects but gst_object_unref() also works on them.
+         In other places where it is never GstObject, g_object_unref() is kept.
+
+2020-04-17 11:44:40 +0530  dhilshad <mohddhilshadm@gmail.com>
+
+       * plugins/elements/gstdownloadbuffer.c:
+         downloadbuffer:fix pushing buffer before stream start event
+         downloadbuffer source pad pushes the first buffer before pushing
+         Stream Start and Segment event, when working in Push mode.
+         Fix:Pushing Stream Start and Segment after coming out of
+         wait for data, and before pushing the buffer to next element.
+         Fixes #534
+
+2020-04-17 07:44:55 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstregistrychunks.c:
+         gstregistrychunks: Directly set name on features
+
+2020-04-17 07:44:26 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstobject.c:
+         gstobject: Don't double-notify when setting names
+         If the name is set via the gobject setters, the notificatio will
+         already be emitted.
+
+2020-04-16 11:40:49 +0200  Jan Tojnar <jtojnar@gmail.com>
+
+       * meson.build:
+         build: Install bash-completion relative to datadir
+         Since bash-completion 2.9, it was no longer possible to override
+         the completionsdir through prefix. [1] In 2.10, the overridability
+         was re-estabilished but this time through datadir variable. [2]
+         This should not really matter except for developers installing the project
+         into a custom prefix or distros using per-package prefixes like NixOS.
+         [1]: https://github.com/scop/bash-completion/commit/81ba2c7e7dfbaefbafa1e8615727c9612e5fb314
+         [2]: https://github.com/scop/bash-completion/pull/344
+
+2020-04-15 20:27:36 +1000  Matthew Waters <matthew@centricular.com>
+
+       * gst/gstsystemclock.c:
+         systemclock: introduce a minimum wait time
+         There is not point waiting if the time to wait is less than this
+         platform specific value.  The worst case here is GCond usage on windows
+         where the granularity is 1ms.
+
+2020-04-15 17:54:21 +1000  Matthew Waters <matthew@centricular.com>
+
+       * gst/gst_private.h:
+       * gst/gstclock.c:
+       * gst/gstsystemclock.c:
+       * meson.build:
+         gst/systemclock: wait on each entry individually
+         Problem:
+         multiple aggregator elements (audiomixer, compositor) in a live
+         pipeline use a lot of CPU waiting each other up.  This is because
+         of the previously unused clock entry unscheduling during regular
+         operation.
+         Clock entry unscheduling has the potential to wake up every clock entry
+         waiting using the system clock which may be a large number.
+         Solution:
+         Implement waiting per entry and only wakeup the unscheduled entry.
+         While this may be possible using GCond, theoretically GCond only gives
+         us microsecond accuracy and uses relative waits in a number of places.
+         We can unfortunately do better poking at the platform specifics
+         ourselves by using futexes on linux and pthread on other unix.  Windows
+         may have a possible implementation using Waitable timers but that is
+         not implemented here and instead falls back to the GCond implementation.
+         GCond waits on Windows is still as accurate as the previous GstPoll-based
+         implementation.
+
+2020-04-14 15:08:47 +1000  Matthew Waters <matthew@centricular.com>
+
+       * gst/gstsystemclock.c:
+         systemclock: log the object name with all debug logs
+         Simplifies correlating logs with clock instances
+
+2020-04-14 14:48:20 +1000  Matthew Waters <matthew@centricular.com>
+
+       * gst/gstsystemclock.c:
+         systemclock: move to GCond waiting
+
+2020-04-12 20:33:43 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gstvalue.c:
+       * tests/check/gst/gstvalue.c:
+         value: Fix segfault comparing empty GValueArrays
+         Adding a test
+
+2020-04-08 22:22:48 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstpipeline.c:
+         pipeline: fix base_time selection when flush seeking live
+         When a live pipeline goes to PLAYING, its change_state method
+         is called twice for PAUSED_TO_PLAYING: the first time is
+         from GstElement, when NO_PREROLL is returned, the second
+         is from GstBin, after all async_done messages have been
+         collected.
+         base_time selection is done only the first time, through
+         comparisons with start_time.
+         On the other hand, when this live pipeline gets flush seeked,
+         even though start_time is reset by the sink upon reception
+         of flush_stop(reset_time=TRUE), PAUSED_TO_PLAYING only occurs
+         once, from GstBin, after all async_done messages have been
+         collected. This causes the base_time to be off by <latency>.
+         This commit addresses this by mimicing the behaviour of
+         GstElement on NO_PREROLL, and calling the change_state
+         method manually when the following conditions are met:
+         * The pipeline is live
+         * The target state is PLAYING
+
+2020-04-09 16:38:23 +0300  Vivia Nikolaidou <vivia@ahiru.eu>
+
+       * plugins/elements/gstmultiqueue.c:
+         multiqueue: Add current-level-{buffers, bytes, time} pad properties
+         To get the current buffers/bytes/time levels of the corresponding
+         internal queue
+
+2020-04-09 13:12:22 +0300  Vivia Nikolaidou <vivia@ahiru.eu>
+
+       * plugins/elements/gstmultiqueue.c:
+         multiqueue: Add stats property
+         The returned "stats" structure contains, for now, one array called
+         "queues" with one GstStructure per internal queue, containing said
+         queue's current level of bytes, buffers, and time.
+
+2020-04-08 12:09:10 -0400  Xavier Claessens <xavier.claessens@collabora.com>
+
+       * meson.build:
+       * meson_options.txt:
+         Meson: Change extra-checks to feature option and make it yielding
+
+2020-04-08 17:53:17 +1000  Jan Schmidt <jan@centricular.com>
+
+       * libs/gst/base/gstbaseparse.c:
+       * tests/check/libs/baseparse.c:
+         baseparse: Don't return more data than asked for in pull_range()
+         Even when pulling a new 64KB buffer from upstream, don't return
+         more data than was asked for in the pull_range() method and then
+         return less later, as that confused subclasses like h264parse.
+         Add a unit test that when a subclass asks for more data, it always
+         receives a larger buffer on the next iteration, never less.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/530
+
+2020-04-06 18:14:12 +0300  Vivia Nikolaidou <vivia@ahiru.eu>
+
+       * plugins/elements/gstdownloadbuffer.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstqueue2.c:
+         downloadbuffer, multiqueue, queue2: Fix watermark docs
+         It is not explicitly specified anywhere in the docs that 0% buffering is
+         at low-watermark and 100% buffering is at high-watermark. It was
+         specified only in the sources.
+
+2020-04-02 13:45:48 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstpad.c:
+         pad: Add a guard against getrange functions not filling a caller-provided buffer
+         It's a programming error to not do so and would cause all kinds of
+         problems in the caller that assumed its own buffer to have been filled.
+
+2020-01-31 11:32:10 -0500  Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+       * gst/gsttask.c:
+       * gst/gsttask.h:
+       * tests/check/gst/gsttask.c:
+         task: Introduce gst_task_resume() API
+         This new API allow resuming a task if it was paused, while leaving it to
+         stopped stated if it was stopped or not started yet. This new API can be
+         useful for callback driver workflow, where you basically want to pause and
+         resume the task when buffers are notified while avoiding the race with a
+         gst_task_stop() coming from another thread.
+
+2020-04-01 15:41:49 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * tools/gst-launch.c:
+         gst-launch: go back down to GST_STATE_NULL in one step.
+         Going through each state on the way back down to GST_STATE_NULL
+         can cause deadlocks, for example:
+         gst-launch-1.0 audiotestsrc ! valve drop=true ! autoaudiosink
+         ctrl + C
+         Hangs forever when going to PAUSED, because the "final" state is
+         ASYNC, and the sink blocks waiting for a preroll buffer.
+         Going straight to NULL addresses this issue, and also helps
+         making teardown faster when piping sparse streams to a
+         sync sink.
+
+2020-04-01 02:36:40 +1100  Jan Schmidt <jan@centricular.com>
+
+       * libs/gst/base/gstbaseparse.c:
+       * tests/check/libs/baseparse.c:
+         baseparse: Fix upstream read caching
+         When running in pull mode (for e.g. mp3 reading),
+         baseparse currently reads 64KB from upstream, then mp3parse
+         consumes typically around 417/418 bytes of it. Then
+         on the next loop, it will read a full fresh 64KB again,
+         which is a big waste.
+         Fix the read loop to use the available cache buffer first
+         before going for more data, until the cache drops to < 1KB.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/518
+
+2020-04-01 02:46:52 +1100  Jan Schmidt <jan@centricular.com>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: Fix typo
+
+2020-03-31 19:05:30 +0900  Seungha Yang <seungha@centricular.com>
+
+       * plugins/elements/gstelements_private.c:
+         filesink: Fix for updating the index of memory to write in the next iteration
+         current_buf_mem_idx stands for the index of memory of the corresponding
+         buffer which is scheduled to be written in the next iteration.
+         If all memory objects were scheduled to be written in the current
+         iteration, reset the index to zero so that starting from the first
+         memory object of the next buffer.
+
+2020-03-28 16:20:51 +0900  Seungha Yang <seungha@centricular.com>
+
+       * plugins/elements/gstelements_private.c:
+         filesink: Fix crash caused by zero-size memory allocation
+         If size of vector is greater than one, we are allocating zero-size
+         memory and trying invalid memcpy operation
+
+2019-11-22 23:55:56 +1100  Jan Schmidt <jan@centricular.com>
+
+       * gst/gstsegment.c:
+         gstsegment: Refuse instant-rate seeks in gst_segment_do_seek()
+         Elements that pass a seek with INSTANT_RATE flag to
+         gst_segment_do_seek() haven't been updated and we should
+         refuse the seek.
+
+2019-11-22 23:53:59 +1100  Jan Schmidt <jan@centricular.com>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: Check the return value of gst_segment_do_seek()
+         Don't assume that a given seek succeeds - check the return result.
+
+2020-03-20 19:28:37 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gstfilesink.c:
+       * plugins/elements/gstfilesink.h:
+         filesink: Add a new full buffer mode to filesink
+         Previously the default and full modes were the same. Now the default
+         mode is like before: it accumulates all buffers in a buffer list until
+         the threshold is reached and then writes them all out, potentially in
+         multiple writes.
+         The new full mode works by always copying memory to a single memory area
+         and writing everything out with a single write once the threshold is
+         reached.
+
+2020-03-20 18:48:52 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gstelements_private.c:
+       * plugins/elements/gstelements_private.h:
+         filesink/fdsink: Write 1 iovec directly without copying if there's no writev() support
+
+2020-03-20 18:43:30 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gstelements_private.c:
+       * plugins/elements/gstelements_private.h:
+       * plugins/elements/gstfdsink.c:
+       * plugins/elements/gstfilesink.c:
+         fdsink/filesink: Refactor writev() code to prevent stack overflows
+         If buffer lists with too many buffers would be written before, a stack
+         overflow would happen because of memory linear with the number of
+         GstMemory would be allocated on the stack. This could happen for example
+         when filesink is configured with a very big buffer size.
+         Instead now move the buffer and buffer list writing into the helper
+         functions and at most write IOV_MAX memories at once. Anything bigger
+         than that wouldn't be passed to writev() anyway and written differently
+         in the previous code, so this also potentially speeds up writing for
+         these cases.
+         For example the following pipeline would crash with a stackoverflow:
+         gst-launch-1.0 audiotestsrc ! filesink buffer-size=1073741824 location=/dev/null
+
+2020-03-25 20:23:17 +1100  Matthew Waters <matthew@centricular.com>
+
+       * libs/gst/base/gstflowcombiner.c:
+       * tests/check/libs/flowcombiner.c:
+         flowcombiner: passthrough the flow return if there are no pads
+         What may happen is that during the course of processing a buffer,
+         all of the pads in a flow combiner may disappear.  In this case, we
+         would return NOT_LINKED.  Instead return whatever the input flow return
+         was.
+
+2018-04-10 18:09:18 +0200  Jose Antonio Santos Cadenas <santoscadenas@gmail.com>
+
+       * gst/gstinfo.h:
+         gstinfo: Check threshold for category from macro
+         This way we can avoid to process parameters if log is not going
+         to be printed.
+
+2020-03-24 15:00:03 +1100  Matthew Waters <matthew@centricular.com>
+
+       * docs/gst/running.md:
+         docs/running: be consistent with ordering of full-stops inside ``
+         Everywhere else places the period outside.
+
+2020-03-23 12:28:12 +0100  Jan Alexander Steffens (heftig) <jsteffens@make.tv>
+
+       * gst/gststructure.c:
+         gststructure: Fix gst_structure_take ownership handling
+         The old code would leave a dangling pointer in oldstr_ptr if two threads
+         attempted to take the same structure into the same location at the same
+         time:
+         1. First "oldstr == newstr" check (before the loop) fails.
+         2. Compare-and-exchange fails, due to a second thread completing the
+         same gst_structure_take.
+         3. Second "oldstr == newstr" check (in the loop) succeeds, loop breaks.
+         4. "oldstr" check succeeds, old structure gets freed.
+         5. oldstr_ptr now contains a dangling pointer.
+         This shouldn't happen in code that handles ownership sanely, so check
+         that we don't try to do this and complain loudly.
+         Also simplify the function by using a do-while loop, like
+         gst_mini_object_take.
+         https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/413
+
+2020-03-23 12:36:01 +0100  Jan Alexander Steffens (heftig) <jsteffens@make.tv>
+
+       * gst/gst_private.h:
+         gstdeviceproviderfactory: Remove volatile from provider storage
+         Avoids a few compiler warnings:
+         ../subprojects/gstreamer/gst/gstdeviceproviderfactory.c: In function ‘gst_device_provider_factory_finalize’:
+         ../subprojects/gstreamer/gst/gstdeviceproviderfactory.c:96:12: warning: assignment discards ‘volatile’ qualifier from pointer target type [-Wdiscarded-qualifiers]
+         96 |   provider = g_atomic_pointer_get (&factory->provider);
+         |            ^
+         ../subprojects/gstreamer/gst/gstdeviceproviderfactory.c: In function ‘gst_device_provider_factory_get’:
+         ../subprojects/gstreamer/gst/gstdeviceproviderfactory.c:276:19: warning: assignment discards ‘volatile’ qualifier from pointer target type [-Wdiscarded-qualifiers]
+         276 |   device_provider = g_atomic_pointer_get (&newfactory->provider);
+         |                   ^
+         ../subprojects/gstreamer/gst/gstdeviceproviderfactory.c:309:21: warning: assignment discards ‘volatile’ qualifier from pointer target type [-Wdiscarded-qualifiers]
+         309 |     device_provider = g_atomic_pointer_get (&newfactory->provider);
+         |
+         https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/414
+
+2020-03-22 09:47:35 +0100  Ondřej Hruška <ondra@ondrovo.com>
+
+       * gst/gstdatetime.c:
+       * tests/check/gst/gstdatetime.c:
+         gstdatetime: Add missing NULL check to gst_date_time_new_local_time
+         Also add a unit test for this.
+         Fixes #524
+
+2020-03-20 09:11:02 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gstregistrychunks.c:
+       * meson.build:
+         registrychunks: Use strnlen if available
+         When this `_strnlen` internal method was added, strnlen (in glibc)
+         was not available yet (appeared in 2.10 it was released that same
+         year).
+         If available, use the much more optimized strnlen
+
+2020-03-20 16:32:07 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * meson.build:
+         filesink: Check for sys/uio.h so we can actually use writev()
+
+2020-03-19 11:20:14 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gstvalue.c:
+         gstvalue: Avoid expensive fallback on intersection
+         The type checks at the end of `gst_value_intersect` to call the flagset
+         intersection are relatively expensive.
+         If we already know that:
+         * There was a compare function but it didn't return GST_VALUE_EQUAL
+         * AND none of the registered intersect functions failed
+         Then we know they can't intersect and can return early.
+         Trims ~20% of the instruction calls
+
+2020-03-18 09:43:27 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gstvalue.c:
+         gstvalue: Optimize some list<=>list functions
+         For subtracting a list from another, the previous implementation would
+         do a double subtraction of one from another (which would create temporary
+         arrays/values which would then be discarded). Instead iterate and do
+         the comparision directly.
+         For intersecting a list with another, we can directly iterate both at
+         once and therefore avoid doing a *full* check of all values of the list
+         against all other values of the list.
+
+2020-03-18 09:39:35 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gststructure.c:
+       * gst/gstvalue.c:
+       * gst/gstvalue.h:
+         gstvalue: Inline GstValueList/GstValueArray
+         This tries to inline as much as possible array/list and its contents
+         in order to avoid double allocation/freeing. This also improves the
+         locality of data.
+         The internal value is still API/ABI compatible with the *public*
+         GArray structure. This allows READ-ONLY backwards compatibility with
+         any external users that assume that the content of a list/array value
+         is backed by a GArray.
+
+2020-03-03 15:36:26 +0100  Miguel Paris <mparisdiaz@gmail.com>
+
+       * gst/gstbufferlist.c:
+       * tests/check/gst/gstbufferlist.c:
+         bufferlist: foreach: always remove as parent if buffer is changed
+         In case the buffer is not writable, the parent (the BufferList) is not
+         removed before calling func. So if it is changed, the parent (the BufferList)
+         of the previous buffer should be removed after calling func.
+
+2020-03-18 11:10:13 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gstbufferlist.c:
+         bufferlist: Add check for overflow
+
+2020-03-10 18:14:57 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gststructure.c:
+         gststructure: Optimize pre-allocation of structures
+         For all the structure creation using valist/varargs we calculate
+         the number of fields we will need to store. This ensures all callers
+         will end up with a single allocation.
+
+2020-03-10 18:13:09 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gststructure.c:
+         gststructure: Inline array and contents
+         Instead of having 3 allocations:
+         * One for GstStructure
+         * One for GArray
+         * One for the array *within* GArray
+         We try to limit this to a single allocation, inlining everything. This
+         reduces the number of micro-allocations and improves locality of data
+         access.
+
+2020-03-13 16:41:52 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gstvalue.c:
+       * tests/check/gst/gstvalue.c:
+         value: Handle NULL caps for comparisons
+         Having a NULL caps in a GValue is legal and we should handle it
+         properly for comparisons.
+
+2020-03-13 12:14:08 +0100  Stéphane Cerveau <scerveau@collabora.com>
+
+       * plugins/elements/gstidentity.c:
+         identity: Fix a minor leak using meta_str
+
+2020-03-11 15:19:45 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gstvalue.c:
+       * tests/check/gst/gstvalue.c:
+         value: Refactor parsing lists to allow trailing comas
+         Before that commit `{test, }` wouldn't be accepted as an array
+         because of the trailing coma, the commit fixes that.
+         At the same time, the code has been refactored to avoid special casing
+         the first element of the list, making `{,}` or `<,>` valid lists.
+
+2020-02-10 18:29:41 +0530  Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+       * gst/gstclock.h:
+         clock: remove documentation link on GTimeVal
+         Looks like it's been removed from glib.devhelp2 on Fedora 31.
+         Fix #508
+
+2020-03-11 22:39:35 +1100  Matthew Waters <matthew@centricular.com>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: allow not passthrough if generate_output is implemented
+         This allows an element to not require implementing transform or
+         transform_ip.
+
+2020-03-09 21:32:28 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gstclocksync.c:
+         clocksync: Use g_cond_signal() instead of g_cond_broadcast()
+         There can only be a single waiter: on the streaming thread.
+
+2020-03-09 21:31:48 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gstidentity.c:
+         identity: Use g_cond_signal() instead of g_cond_broadcast()
+         There can only be a single waiter: on the streaming thread.
+
+2020-03-09 20:27:58 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gstidentity.c:
+         identity: Unblock condition variable on FLUSH_START
+         ... and immediately return FLUSHING from the streaming thread instead of
+         waiting potentially forever.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/516
+
+2020-03-09 15:17:08 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstsystemclock.c:
+         systemclock: Don't start the system clock at 0 on Windows
+         We kept the start time around and subtracted it everywhere for "easy of
+         debugging", but we don't do anything like this anywhere else and it
+         only complicates the code unnecessarily.
+
+2020-03-09 15:16:00 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstsystemclock.c:
+         systemclock: Don't divide by zero on Windows if high performance timers are not available
+
+2020-03-07 11:09:05 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstcaps.c:
+       * tests/check/gst/gstcaps.c:
+         caps: Don't assert in fixate() on EMPTY/ANY caps and document EMPTY/ANY behaviour on more functions
+         fixate() will return empty caps if it gets empty caps passed and assert
+         early if any caps are provided as there's no meaningful way of fixating
+         any caps.
+         truncate() and simplify() will return the input caps in case of
+         any/empty caps as before, but slightly optimized and as documented
+         behaviour.
+         Also add tests for this and a few other operations behaviour on
+         empty/any caps.
+
+2020-03-04 22:13:12 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+       * libs/gst/base/gstaggregator.h:
+         gstaggregator: fix the prototype of sink_event_pre_queue
+         This is not an API breakage, as implementors are already
+         expected to return a GstFlowReturn
+
+2020-03-03 18:49:36 +0900  Seungha Yang <seungha.yang@navercorp.com>
+
+       * tools/gst-launch.c:
+         gst-launch: Follow up to missing s/g_print/gst_print/g
+         Required to avoid broken log string on Windows but missed
+         in the commit of 493a3261a9757b5ade7aec289eb07221966f9eed
+
+2020-02-29 19:00:44 +0900  Seungha Yang <seungha.yang@navercorp.com>
+
+       * tests/check/gst/gstinfo.c:
+         tests: info: Fix thread-id pattern matching on Windows
+         The format modifier for thread-id prints hex value without "0x" prefix on Windows.
+
+2020-01-26 00:56:44 +0000  Tim-Philipp Müller <tim@centricular.com>
+
+       * plugins/tracers/gstrusage.c:
+       * plugins/tracers/gstrusage.h:
+         tracers: rusage: use thread-local storage for per-thread stats
+         .. instead of looking things up by thread id from a GHashTable,
+         which also happens to have no locking around insertion/lookup.
+
+2020-01-26 00:32:18 +0000  Tim-Philipp Müller <tim@centricular.com>
+
+       * plugins/tracers/gstrusage.c:
+         tracers: rusage: fix minor string leak in constructor
+
+2019-11-02 11:49:25 +0100  Johan Bjäreholt <johan@bjareho.lt>
+
+       * tools/gst-stats.c:
+         gst-stats: Fix missing NULL checks
+         gst-inspect-1.0 segfaults on tracing logs where it fails to find
+         element stats. So on the pipelines where we get the following WARNING
+         during execution will afterwards crash with a segfault as the
+         g_ptr_array has a index for it but it is just a NULL pointer.
+         WARN default gst-stats.c:444:do_message_stats: no element stats found for ix=X
+         An example of an pipeline which can reproducibly create a trace log
+         where this occurs would be this
+         GST_DEBUG="GST_TRACER:7" GST_TRACERS="stats;rusage;latency" gst-launch-1.0 videotestsrc num-buffers=120 ! autovideosink &> trace.log
+         gst-stats-1.0 trace.log
+
+2020-02-24 15:24:44 -0500  Olivier Crête <olivier.crete@collabora.com>
+
+       * libs/gst/base/gstbasesink.c:
+         basesink: Improve clarity of latency query maths debug message
+         Add the equation to the debug message to make it easier for non-GStreamer
+         experts to understand why their pipeline has latency.
+
+2020-02-26 17:20:04 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * tests/misc/netclock-replay.c:
+         tests: Maintain compatibility with GLib 2.48
+         That's the minimum version of GLib we require right now.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/514
+
+2020-02-25 04:47:35 +1100  Jan Schmidt <jan@centricular.com>
+
+       * docs/plugins/gst_plugins_cache.json:
+       * plugins/elements/gstclocksync.c:
+       * plugins/elements/gstclocksync.h:
+       * plugins/elements/gstelements.c:
+       * plugins/elements/meson.build:
+       * tests/check/elements/clocksync.c:
+       * tests/check/meson.build:
+         clocksync: Add new clocksync element
+         The clocksync element is a generic element that can be
+         placed in a pipeline to synchronise passing buffers to the
+         clock at that point. This is similar to 'identity sync=true',
+         but because it isn't GstBaseTransform-based, it can process
+         GstBufferLists without breaking them into separate GstBuffers
+
+2020-02-26 22:29:43 +0900  Seungha Yang <seungha.yang@navercorp.com>
+
+       * tools/gst-inspect.c:
+         gst-inspect: Add define guard for g_log_writer_supports_color()
+         g_log_writer_supports_color() was introduced since GLib 2.50.0
+         which is slightly higher version than our minimum required GLib version.
+
+2020-02-25 19:13:59 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * tests/misc/netclock-replay.c:
+       * tools/gst-stats.c:
+         Don't use glib format modifiers with sscanf or printf
+         We do not have a way to know the format modifiers to use with string
+         functions provided by the system. `G_GUINT64_FORMAT` and other string
+         modifiers only work for glib string formatting functions. We cannot
+         use them for string functions provided by the stdlib. See:
+         https://developer.gnome.org/glib/stable/glib-Basic-Types.html#glib-Basic-Types.description
+         F.ex.:
+         ```
+         ../tools/gst-stats.c:921:11: error: too many arguments for format [-Werror=format-extra-args]
+         printf ("Number of Buffers passed: %" G_GUINT64_FORMAT "\n", num_buffers);
+         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+         ../tools/gst-stats.c:922:11: error: unknown conversion type character 'l' in format [-Werror=format=]
+         printf ("Number of Events sent: %" G_GUINT64_FORMAT "\n", num_events);
+         ^~~~~~~~~~~~~~~~~~~~~~~~~~
+         In file included from /builds/nirbheek/cerbero/cerbero-build/dist/windows_x86_64/include/glib-2.0/glib/gtypes.h:32,
+         from /builds/nirbheek/cerbero/cerbero-build/dist/windows_x86_64/include/glib-2.0/glib/galloca.h:32,
+         from /builds/nirbheek/cerbero/cerbero-build/dist/windows_x86_64/include/glib-2.0/glib.h:30,
+         from ../gst/gst.h:27,
+         from ../tools/tools.h:28,
+         from ../tools/gst-stats.c:30:
+         /builds/nirbheek/cerbero/cerbero-build/dist/windows_x86_64/lib/glib-2.0/include/glibconfig.h:69:28: note: format string is defined here
+         #define G_GUINT64_FORMAT "llu"
+         ^
+         ```
+         and
+         ```
+         ../tests/misc/netclock-replay.c: In function 'main':
+         ../tests/misc/netclock-replay.c:98:23: error: unknown conversion type character 'l' in format [-Werror=format=]
+         if (sscanf (line, "%" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " %"
+         ^~~
+         In file included from /builds/nirbheek/cerbero/cerbero-build/dist/windows_x86/include/glib-2.0/glib/gtypes.h:32,
+         from /builds/nirbheek/cerbero/cerbero-build/dist/windows_x86/include/glib-2.0/glib/galloca.h:32,
+         from /builds/nirbheek/cerbero/cerbero-build/dist/windows_x86/include/glib-2.0/glib.h:30,
+         from ../tests/misc/../../libs/gst/net/gstntppacket.c:38,
+         from ../tests/misc/netclock-replay.c:31:
+         /builds/nirbheek/cerbero/cerbero-build/dist/windows_x86/lib/glib-2.0/include/glibconfig.h:69:28: note: format string is defined here
+         #define G_GUINT64_FORMAT "llu"
+         ^
+         ```
+         This is needed for upgrading glib inside Cerbero which builds with
+         `-Werror` on Windows:
+         https://gitlab.freedesktop.org/gstreamer/cerbero/merge_requests/419
+
+2020-02-19 18:49:07 +0000  Tim-Philipp Müller <tim@centricular.com>
+
+       * gst/gstdebugutils.c:
+         debugutils: skip "parent" property for elements when dumping pipeline graph
+         Seems unnecessary to print the parent name for every
+         element in the pipeline graph, it's clear from the
+         graph what the parent element is and it's hard to
+         imagine a case where this is useful info rather than
+         just distracting spam. So far this was only done for
+         pads, but we should just do it for everything.
+
+2019-12-19 11:28:13 +0100  Matus Gajdos <matuszpd@gmail.com>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: fix memory leak
+         A buffer to be skipped wasn't unref'd in gst_base_parse_chain().
+         Fixes #406
+
+2020-01-27 14:46:18 -0500  Olivier Crête <olivier.crete@collabora.com>
+
+       * plugins/tracers/gstleaks.c:
+         leak tracer: Initialize GValue
+
+2020-02-13 17:53:29 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+       * plugins/tracers/gstleaks.c:
+         leaks: Do not trace refs for object we do not follow
+         When the user sets filters, we should not trace ref counts of object that
+         are not traced. This optimizes the tracer by potentially avoiding
+         generating useless backtraces.
+
+2020-02-10 16:35:06 -0600  Zebediah Figura <z.figura12@gmail.com>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: Set the private duration before posting a duration-changed message
+         Otherwise an application cannot rely on a subsequent call to e.g. gst_pad_query_duration() succeeding.
+
+2020-02-12 12:32:05 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstbus.c:
+         bus: Make setting/replacing/clearing the sync handler thread-safe
+         Previously we would use the object lock only for storing the sync
+         handler and its user_data in a local variable, then unlock it and only
+         then call the sync handler. Between unlocking and calling the sync
+         handler it might be unset and the user_data be freed, causing it to be
+         called with a freed pointer.
+         To prevent this add a refcounting wrapper struct around the sync
+         handler, hold the object lock while retrieving it and increasing the
+         reference count and only actually free it once the reference count
+         reaches zero.
+         As a side-effect we can now also allow to actually replace the sync
+         handler. Previously it was only allowed to clear it after initially
+         setting it according to the docs, but the code still allowed to clear it
+         and then set a different one.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/506
+
+2020-02-13 15:38:15 +0900  Seungha Yang <seungha.yang@navercorp.com>
+
+       * docs/gst/running.md:
+         docs: Fix bold markdown syntax for GST_DEBUG_NO_COLOR
+         Fixing markdown syntax
+
+2020-01-27 11:58:57 +0000  Henry Wilkes <hwilkes@igalia.com>
+
+       * gst/gstcaps.c:
+       * tests/check/gst/gstcaps.c:
+         caps: keep ANY caps empty internally
+         Keep the ANY caps empty internally when appending and merging
+         caps/structures. Previously, an ANY caps could end up containing
+         internal structures, which could be fetched by the user, and gave the
+         caps a non-zero length.
+         Also, made sure that `gst_caps_set_features_simple` frees the features
+         if caps is empty.
+
+2020-01-21 19:02:48 +0000  Henry Wilkes <hwilkes@igalia.com>
+
+       * gst/gstcaps.c:
+       * tests/check/gst/gstcaps.c:
+         caps: fix is_strictly_equal
+         Fixed gst_caps_is_strictly_equal() to take into account whether either of
+         the caps are ANY caps. Previously, two ANY caps could be considered not
+         strictly equal if one of them still contained some remnant *internal*
+         structure (this can happen if an ANY caps has emerged from an append or
+         merge operation). Also, an ANY caps with no remnant internal structures
+         was considered strictly equal to an EMPTY caps. Similarly, a non-ANY caps
+         was considered strictly equal to an ANY caps if its remnant internal
+         structures happened to match.
+         Also changed gst_caps_is_fixed to take into account that an ANY caps
+         should not be considered fixed even if it contains a single remnant
+         internal fixed structure. This affects gst_caps_is_equal(), which uses a
+         separate method if both caps are fixed. Previously, this meant that a
+         non-ANY fixed caps was considered equal to an ANY caps if it contained a
+         single matching remnant internal structure.
+         Added some tests for these two equality methods, which covers the above
+         examples, as well as asserts existing behaviour.
+         Fixes #496
+
+2020-02-10 12:58:47 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbasetransform.h:
+         basetransform: Make gst_base_transform_reconfigure() public
+         This has the same function as the negotiate() functions in various other
+         base classes and is required to be able to completely re-implement
+         submit_input_buffer() in subclasses.
+
+2020-01-07 17:12:54 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: Don't set meaningless buffer dts from segment->start
+         When we do not have any information about DTSs we shouldn't try to make
+         them up, moreover after seeking `segment->start` has nothing to do with
+         the next buffer timing (and is probably after the actual buffer timestamp)
+         and since, since https://gitlab.freedesktop.org/gstreamer/gstreamer/commit/fa8312472f08d468677d188d5cf1ad52c5b5b0a0
+         we do:
+         ```
+         if (buffer->dts > buffer->dts)
+         buffer->pts = buffer->dts
+         ```
+         we end up setting `buffer->pts = segment->start` which is plain
+         broken and leads to downstream decoder accept the first buffer
+         as it will be inside the segment (its pts==segment->start) which
+         basically means accurate seeking behaves mostly the same way as
+         keyframe seeks.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/492
+
+2019-12-27 12:36:10 -0500  Olivier Crête <olivier.crete@collabora.com>
+
+       * gst/gstsystemclock.c:
+       * meson.build:
+         systemclock: No need to check for CLOCK_TAI in the meson
+         POSIX defines CLOCK_MONOTONIC to always be a macro, so I think
+         it's safe to assume that CLOCK_TAI will also be.
+
+2019-12-13 11:07:40 -0800  Ederson de Souza <ederson.desouza@intel.com>
+
+       * gst/gstsystemclock.c:
+       * gst/gstsystemclock.h:
+       * meson.build:
+         GstSystemClock: Add GST_CLOCK_TYPE_TAI
+         GST_CLOCK_TYPE_TAI is GStreamer abstraction for CLOCK_TAI. Main
+         motivation for this patch is support for transmission offloading features
+         - when network packets are timestamped with the time they are deemed to
+         be actually transmitted. Linux API for that requires that time to be
+         in CLOCK_TAI coordinate.
+         With GST_CLOCK_TYPE_TAI, applications can use CLOCK_TAI directly on
+         their pipelines, avoiding the need to cross timestamp packet times. By
+         leveraging system's CLOCK_TAI, applications also don't need to keep track
+         of leap seconds - less burden for them. Just keep system's CLOCK_TAI
+         accurate and use it.
+
+2020-01-24 23:56:32 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstbin.c:
+         bin: Don't consider having a group-id or being STREAM_START if we have not a single STREAM_START message
+         This would cause us to set GST_GROUP_ID_INVALID as group-id in the
+         aggregated STREAM_START message if there are no sinks at all or none of
+         them have a STREAM_START message, which is simply wrong.
+         If we have not a single STREAM_START message then the bin should not be
+         considered STREAM_START.
+
+2020-01-24 17:52:49 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstevent.c:
+       * gst/gstmessage.c:
+         event/message: Don't allow setting invalid group ids
+         They are optional on STREAM_START messages/events but if available
+         should have at least a valid value.
+         For STREAM_GROUP_DONE events don't allow creating it with an invalid
+         group id as this does not make any sense.
+
+2020-01-23 19:27:14 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: Initialize source pad segment position to -1 when resetting
+         This allows start-time selection in gst_aggregator_pad_chain_internal()
+         to actually work as that code assumes it to be -1 for actually
+         overriding the value.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/500
+
+2020-01-09 20:07:06 +0100  Jan Alexander Steffens (heftig) <jsteffens@make.tv>
+
+       * gst/gstbin.c:
+         bin: Fix deep-element-removed log message
+         child and bin were switched.
+         https://gitlab.freedesktop.org/gstreamer/gstreamer/merge_requests/354
+
+2019-09-03 17:14:49 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gstmessage.h:
+         docs: Document the new 'redirect-location' error message detail field
+
+2014-12-30 11:48:26 +0100  Stefan Sauer <ensonic@users.sf.net>
+
+       * gst/parse/grammar.y.in:
+       * gst/parse/parse.l:
+       * tests/check/pipelines/parse-launch.c:
+       * tools/gst-launch-1.0.1:
+         parse: add support for presets
+         Add new parse syntax: @preset="<preset-name>" to load presets.
+         Fixes #86
+
+2019-12-26 15:08:09 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * tools/gst-launch.c:
+         gst-launch: handle ERROR messages in the sync handler
+         Errors causing the pipeline to fail going from NULL to PAUSED
+         were not displayed, and the pipeline was not dumped either in
+         those cases.
+         In addition, dumping the pipeline from the sync handler means
+         the dump matches exactly the state of the pipeline at the
+         moment the error was posted.
+
+2019-12-22 21:13:00 +0900  Seungha Yang <seungha.yang@navercorp.com>
+
+       * tools/gst-inspect.c:
+         gst-inspect: Increase array size for printing rank name
+         Now the rank value can be MAX_INT (2147483647)
+
+2019-08-15 20:56:40 +0900  Seungha Yang <seungha.yang@navercorp.com>
+
+       * docs/gst/running.md:
+       * gst/gst.c:
+       * gst/gst_private.h:
+       * gst/gstpluginfeature.c:
+         pluginfeature: Allow updating initial rank of plugin feature
+         Introducing "GST_PLUGIN_FEATURE_RANK" environment variable in order for users
+         to adjust rank of plugin(s) via environment.
+         A "feature" and "rank" key-value pair should be separable by ":",
+         and each key-value pair is recognized per "," delimiters. The rank
+         can be a numerical value or one of pre-defined rank values
+         such as "NONE", "MARGINAL", "SECONDARY", and "PRIMARY" in case-insensitive manner.
+         In addition to pre-defined { NONE, MARGINAL, SECONDARY, PRIMARY },
+         "MAX" can be passed to key value used to ensure having a higher rank
+         than other plugin features.
+         Example)
+         - GST_PLUGIN_FEATURE_RANK=qtdemux:256,h264parse:NONE
+         Set rank of qtdemux plugin to 256 (primary) and 0 (none) for h264parse.
+
+2019-08-30 00:23:09 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * gst/gstinfo.c:
+       * gst/gstinfo.h:
+       * tests/check/gst/gstinfo.c:
+         gstinfo: Add new API for getting debug log lines
+         If you're using a custom log handler, you had to reverse-engineer the
+         debug log format and create your own format function. Now, you can
+         call `gst_debug_log_get_line()` and it will return a string (without
+         ANSI escape color codes) representation instead.
+         This is useful in situations when you need to log the ordinary
+         gst_debug log to a resource that can't be opened as a `FILE` handle.
+         Also includes a test.
+
+2019-12-20 14:01:02 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * tests/check/gst/gstsystemclock.c:
+         tests: remove system-dependent tests
+         We now have GstTestClock-based tests that validate the same logic,
+         without inducing spurious timing failures / overly relying on sleeps.
+         Fixes: #346
+         Fixes: #347
+         Fixes: #348
+         Co-authored by: Thibault Saunier <tsaunier@igalia.com>
+
+2019-12-20 10:53:21 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+       * tests/check/libs/gsttestclock.c:
+         tests-clock: Fix race in test_late_crank
+         There was a case where we started waiting on the clock before setting
+         the clock time, leading to the wait succeeding instead of being late:
+         gsttestclock.c:1073:F:testclock:test_late_crank:0: '1 * GST_SECOND' (1000000000) is not equal to 'context.jitter' (-4000000000)
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/426
+         Co-authored by: Mathieu Duponchelle <mathieu@centricular.com>
+
+2019-11-15 15:49:32 +0100  Niels De Graef <niels.degraef@barco.com>
+
+       * gst/gstbin.c:
+       * gst/gstbin.h:
+       * tests/check/gst/gstbin.c:
+         bin: Add method to find elements by factory name
+         A common use case of a dynamically built pipeline is that you want to
+         (conditionally) find a certain element, e.g. the `rtpbin`s in a
+         `uridecodebin`. If that element has a fixed name inside its parent bin
+         (and only has a single instance) this can be easily done by
+         `gst_bin_get_by_name()`.
+         If there are multiple instances of the element however, you can only use
+         `gst_bin_iterate_all_by_interface()`, but this doesn't work if you don't
+         have the specific `GType` (which is often the case, due to plugins being
+         dynamically loaded). As such, another fallback could be to use the
+         well-known name of the element's factory (in case of our example, this
+         is of course `"rtpbin"`).
+
+2019-12-18 15:57:35 +0100  Stéphane Cerveau <scerveau@collabora.com>
+
+       * gst/gstevent.c:
+       * libs/gst/net/gstnettimeprovider.c:
+         gstreamer: use of g_value_dup_string
+         Use helper method to get string from GValue.
+
+2019-12-13 18:21:32 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * tests/check/pipelines/parse-launch.c:
+         tests: fix pipelines_parse_launch.delayed_link flakiness
+         Fixes #345
+         There were two causes for the flakiness, one much rarer than
+         the other.
+         The test sets up a source with a sometimes pad added during
+         the transition of a wrapper bin from READY to PAUSED.
+         It runs 4 iterations, the last of which makes it so the
+         negotiation fails.
+         In that case, the intention as correctly presented by the following
+         comment:
+         /* [..] ie, the pipeline should create ok but fail to change state */
+         However the implementation of run_delayed_test was neither calling
+         get_state on the pipeline (it called it on the wrapper bin), nor
+         checking that the return of get_state was FAILURE (it actually
+         checked that it was not).
+         This led to an obvious race condition, and was fixed by calling
+         get_state on the pipeline, then checking that in this specific
+         case (expect_link == FALSE), the state change has actually failed.
+         The second, rarer race condition is at set_state time. When we
+         don't expect the link to succeed, the return of set_state may
+         either be FAILURE or ASYNC, depending on timing. This was fixed
+         by taking expect_link into account when checking the return value
+         of set_state.
+         Co-authored by: Thibault Saunier <tsaunier@igalia.com>
+
+2019-12-12 11:39:56 +0100  Peter Seiderer <ps.report@gmx.net>
+
+       * gst/gstpluginloader.c:
+         pluginloader: handle fsync interrupted by signal (EINTR)
+         According to [1] EINTR is a possible errno for fsync(),
+         so handle it as all other EINTR (do/while(errno == EINTR)).
+         Signed-off-by: Peter Seiderer <ps.report@gmx.net>
+
+2019-12-12 11:37:56 +0100  Peter Seiderer <ps.report@gmx.net>
+
+       * gst/gstregistrybinary.c:
+         registry: handle fsync interrupted by signal (EINTR)
+         According to [1] EINTR is a possible errno for fsync(),
+         so handle it as all other EINTR (do/while(errno == EINTR)).
+         Signed-off-by: Peter Seiderer <ps.report@gmx.net>
+
+2019-12-12 11:07:07 +0100  Peter Seiderer <ps.report@gmx.net>
+
+       * plugins/elements/gstfilesink.c:
+         filesink: handle fsync interrupted by signal (EINTR)
+         According to [1] EINTR is a possible errno for fsync() and it happens in
+         reality on linux (video writing via splitmuxsink with robust muxing enabled
+         on a cifs mounted network share), so handle it as all other EINTR
+         (do/while(errno == EINTR)).
+         Fixes:
+         GError.message: Error while writing to file "vidoe_001.mp4". GError.domain: 2372 GError.code: 10 from: FileSink debug: gstfilesink.c(849): gst_file_sink_render (): /GstPipeline:Pipeline/GstSplitMuxSink:SplitMuxSink/GstBin:QueueBin/GstFileSink:FileSink: Interrupted system call
+         Signed-off-by: Peter Seiderer <ps.report@gmx.net>
+
+2019-12-10 17:06:02 -0500  Olivier Crête <olivier.crete@collabora.com>
+
+       * gst/gstsystemclock.c:
+       * libs/gst/base/gstcollectpads.c:
+       * tests/check/elements/tee.c:
+         Remove deprecated GTimeVal
+         GTimeVal won't work past 2038
+
+2019-12-10 13:31:50 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstdevice.c:
+       * gst/gstelementfactory.c:
+         device, elementfactory: relax floating requirement
+         Using g_assert() is a bit too extreme, as it will abort the whole
+         program unless G_DISABLE_ASSERTS is true.
+         Switch to g_critical()
+
+2019-12-10 09:42:37 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/check/gstcheck.c:
+         gstcheck: remove bogus refcount asserts
+         As soon as gstcheck potentially calls out to code it does not
+         control, such as gst_element_request_pad, all assertions about
+         pad refcounts go out the window.
+
+2019-12-06 11:40:44 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: fix logging in new update_segment API
+
+2019-12-05 13:44:33 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+       * libs/gst/base/gstaggregator.h:
+         aggregator: add method to update srcpad segment
+
+2019-12-05 09:54:32 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstbus.c:
+         bus: Clean up #ifdefs to compile with debugging enabled in all combinations
+         Thanks to Roland Jon for finding this.
+
+2019-12-04 20:12:02 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstdevice.c:
+       * gst/gstelementfactory.c:
+         device, elementfactory: don't enforce floating status
+         The reference we receive when calling g_object_new should be
+         floating, but we can't force it at our level.
+         Switch from g_object_force_floating() to a simple assertion.
+         See https://gitlab.freedesktop.org/gstreamer/gst-python/issues/27
+
+2019-06-19 13:45:54 +0200  Tulio Beloqui <tulio.beloqui@pexip.com>
+
+       * libs/gst/check/gsttestclock.c:
+       * libs/gst/check/gsttestclock.h:
+         testclock: added single clock id process function
+         Co-authored-by: Havard Graff <hgr@pexip.com>
+
+2019-10-21 17:56:14 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstbus.c:
+         bus: Use new GSource dispose function
+         Without this it is possible that we have a GSource with reference count
+         0 stored in the GstBus that is currently in the process of being
+         destroyed. gst_bus_remove_watch() might then access it, increase its
+         reference count to 1 again, call GSource API on it and then unref it,
+         which will then finalize it a second time.
+         The dispose function allows the GSource to be resurrected until it
+         returned so the above would be safe now.
+         This caused some spurious crashes during shutdown in various
+         applications.
+
+2019-12-03 15:40:59 -0500  Xavier Claessens <xavier.claessens@collabora.com>
+
+       * meson_options.txt:
+       * plugins/meson.build:
+       * plugins/tracers/meson.build:
+         Meson: Add 'coretracers' feature option
+         This was the only plugin still built when using
+         -Dauto_features=disabled, besides coreelements.
+
+2019-12-03 11:23:01 +0000  Håvard Graff <havard.graff@gmail.com>
+
+       * libs/gst/check/gstharness.c:
+         gstharness: don't push the event to the queue before processing
+         The application might pull and unref it by the time the code gets
+         around to check it for EOS.
+
+2019-11-28 13:09:45 +0200  Vivia Nikolaidou <vivia@ahiru.eu>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: Don't copy invalid DTS to the PTS
+         We were checking to make sure the buffer's DTS wouldn't be after its
+         PTS. However, the check would also trigger when DTS is NONE, which is
+         e.g. in the case of some broken cameras.
+         Fixes #470
+
+2019-11-27 15:47:32 +0100  Edward Hervey <bilboed@bilboed.com>
+
+       * plugins/tracers/gstlatency.c:
+         tracers: Don't leak temporary GstStructure
+         CID: 1455462
+
+2018-11-21 16:14:58 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gstbuffer.c:
+         GstBuffer: size-related optimization
+         Avoid calling generic function when it's possible to directly
+         return/get sizes
+
+2018-11-21 16:13:48 +0100  Edward Hervey <edward@centricular.com>
+
+       * gst/gstbuffer.c:
+         GstBuffer: Inline fast-path for merged memory
+
+2019-11-27 09:41:36 +0000  Tim-Philipp Müller <tim@centricular.com>
+
+       * gst/gstparse.c:
+         docs: mention gst_parse_bin_from_description() in gst_parse_launch() docs
+
+2019-11-22 16:04:20 +0100  Linus Svensson <linussn@axis.com>
+
+       * gst/gstdatetime.c:
+       * gst/gstdatetime.h:
+       * tests/check/gst/gstdatetime.c:
+         datetime: Add constructor for timestamps in microseconds
+
+2019-10-11 17:33:42 +0300  Vivia Nikolaidou <vivia@ahiru.eu>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: Make sure PTS >= DTS
+         If, for example, we are accumulating rounding errors from the buffer
+         duration when calculating the PTS/DTS, it can happen that the buffer
+         thinks it should be presented before it's decoded. In that case we just
+         clamp the DTS.
+
+2019-11-18 00:15:31 +0000  Stéphane Cerveau <scerveau@collabora.com>
+
+       * gst/gstbuffer.h:
+         gstbuffer: update documentation
+         remove unclear documentation about GST_BUFFER_FLAG_MARKER
+
+2019-11-12 11:24:45 +0900  Seungha Yang <seungha.yang@navercorp.com>
+
+       * tools/gst-launch-1.0.1:
+       * tools/gst-launch.c:
+         gst-launch: Disable printing current position by default when stdout is not a tty
+         ... and add new option to force-enable printing position even if stdout
+         is not a tty.
+
+2019-11-03 12:55:13 +0100  Havard Graff <havard.graff@gmail.com>
+
+       * gst/gststructure.c:
+       * gst/gststructure.h:
+         structure: add gst_structure_take
+         (╯°□°)╯︵ ┻━┻
+
+2019-08-20 13:57:09 +0200  Tulio Beloqui <tulio.beloqui@pexip.com>
+
+       * libs/gst/check/gstharness.c:
+       * tests/check/libs/gstharness.c:
+         harness: fixed race condition on forward pad while forwarding sticky events to sink harness
+         Co-authored-by: Camilo Celis <camilo@pexip.com>
+         Co-authored-by: Havard Graff <hgr@pexip.com>
+
+2019-11-12 19:15:34 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+         hotdoc: Add missing json escaping
+         Fixes https://gitlab.freedesktop.org/gstreamer/gst-docs/issues/50
+
+2019-11-12 15:19:28 +0900  Wonchul Lee <w.lee@lge.com>
+
+       * gst/gstevent.h:
+         event: Fix gir warning
+         It fixes below gir warnings.
+         ../subprojects/gstreamer/gst/gstevent.c:2246: Warning: Gst:
+         gst_event_new_instant_rate_sync_time: unknown parameter
+         'rate_multiplier' in documentation comment, should be 'rate'
+         ../subprojects/gstreamer/gst/gstevent.c:2296: Warning: Gst:
+         gst_event_parse_instant_rate_sync_time: unknown parameter
+         'rate_multiplier' in documentation comment, should be 'rate'
+
+2019-08-26 12:48:28 +0200  Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
+
+       * gst/parse/grammar.y.in:
+       * gst/parse/meson.build:
+         gst/parse: define pure-parser depending on bison version
+         After release bison 2.5 the declaration %pure-parser was deprecated
+         in favor of %define api.pure
+         Nonetheless, until bison 3.4, the declaration was treated as backward
+         compatibility, but now bison shows a warning:
+         warning: deprecated directive, use ‘%define api.pure’
+         The patch's approach is to handle both directives according with the
+         used bison's version, by string replacement at source configuration
+         stage.
+
+2019-02-21 13:29:31 +0100  Nayana Topolsky <nayana.topolsky@streamunlimited.com>
+
+       * gst/gstpad.c:
+         pad: clear sticky event tag upon stream-start
+         When playing gapless there were situations when some sticky events
+         like tags were stuck at some pad and then revived much later.
+         Therefore it is better to clear them upon stream-start.
+         Fixes #360
+
+2019-05-30 22:29:23 +0900  Seungha Yang <seungha.yang@navercorp.com>
+
+       * gst/gsttaglist.h:
+         taglist: Fix broken empty set character in code
+         Previous one was not a valid ASCII empty set character.
+         'tig' and 'git log -p' couldn't represent it as expected.
+
+2019-05-30 20:53:34 +0900  Seungha Yang <seungha.yang@navercorp.com>
+
+       * tools/gst-launch-1.0.1:
+       * tools/gst-launch.c:
+         gst-launch: Add support printing current position of pipeline
+         By default, gst-launch will print the current position of pipeline (with duration if available).
+         To disable it, use "--no-position" option.
+
+2019-05-29 20:22:54 +0900  Seungha Yang <seungha.yang@navercorp.com>
+
+       * tools/gst-launch.c:
+         gst-launch: Port to the direct use of GMainLoop
+         ... instead of custom event loop.
+         This can make it easy to use GMainLoop related APIs in code.
+
+2019-05-29 20:24:06 +0900  Seungha Yang <seungha.yang@navercorp.com>
+
+       * tools/gst-launch.c:
+         gst-launch: Remove meaningless global variable
+
+2019-02-07 23:59:51 +1100  Jan Schmidt <jan@centricular.com>
+
+       * gst/gstpipeline.c:
+         pipeline: Instant rate change handling
+         Implement aggregation of INSTANT_RATE_REQUEST messages and sending of
+         INSTANT_RATE_SYNC_TIME events.
+
+2018-05-15 18:42:25 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstbasesink.c:
+         basesink: Add support for instant-rate-change events
+         Post instant-rate-request message when receiving an instant-rate-change
+         event, and handle the incoming instant-rate-sync-time events from the
+         pipeline.
+
+2018-05-14 23:14:24 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstmessage.c:
+       * gst/gstmessage.h:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+         event/message: Add new instant-rate-sync-time event and instant-rate-request message
+
+2018-05-09 15:28:13 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+       * gst/gstsegment.h:
+         event: Add new GST_EVENT_INSTANT_RATE_CHANGE and GST_SEEK_FLAGS_INSTANT_RATE_CHANGE
+         A seek with that flag set must be non-flushing, not change the playback
+         direction and start/stop position. A seek handler will then send the new
+         GST_EVENT_INSTANT_RATE_CHANGE event downstream for downstream elements
+         to immediately apply the new playback rate before the new in-band segment
+         event arrives.
+
+2019-11-02 15:06:28 +0100  Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
+
+       * gst/gstelementfactory.c:
+       * gst/gstelementfactory.h:
+         elementfactory: add GST_ELEMENT_FACTORY_TYPE_HARDWARE
+         This new symbol matches with the elements within "Hardware" class.
+
+2019-10-31 11:06:48 +0100  Niels De Graef <niels.degraef@barco.com>
+
+       * plugins/elements/gstqueue2.c:
+         queue2: Use g_object_notify_by_pspec
+         `g_object_notify()` actually takes a global lock to look up the
+         `GParamSpec` that corresponds to the given property name. It's not a
+         huge performance hit, but it's easily avoidable by using the
+         `_by_pspec()` variant.
+
+2019-10-25 01:41:27 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gsttee.c:
+         tee: First deactivate the pad and then remove it when releasing pads
+         This reverts a96002bb28c21b30fb9338a4620ad20504c70aa5, which is not
+         necessary anymore. If we release the pad after removing it then none of
+         the deactivation code will actually be called because the pad has no
+         parent anymore, and we require a parent on the pad for deactivation to
+         happen.
+         This can then, among other things, cause a streaming thread to be still
+         stuck in a pad probe because the pad was never flushed, and waiting
+         there forever because now the pad will actually never be flushed anymore.
+
+2019-10-25 01:39:50 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gsttee.c:
+         tee: Check for the removed pad flag also in the slow pushing path
+         If a pad is currently being released we don't want to forward the
+         FLUSHING flow return but instead consider it as NOT_LINKED. FLUSHING
+         would also cause upstream to be FLUSHING.
+         This part was missed in a3c4a3201a705eb1934ceeea34d1ca42d4571c07 and
+         resulted in a different (and wrong) workaround in
+         a96002bb28c21b30fb9338a4620ad20504c70aa5.
+
+2019-10-25 01:39:05 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gsttee.c:
+         tee: Lock mutex before reading the removed flag of the pads
+         Otherwise we're not guaranteed to read the very latest value that
+         another thread might've written in there when the pad was released, and
+         could instead work with an old value.
+
+2019-09-30 11:34:51 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstbin.c:
+         bin: Drop need-context messages without source instead of crashing
+
+2019-10-17 12:13:35 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * meson.build:
+         meson: build gir even when cross-compiling if introspection was enabled explicitly
+         This can be made to work in certain circumstances when
+         cross-compiling, so default to not building g-i stuff
+         when cross-compiling, but allow it if introspection was
+         enabled explicitly via -Dintrospection=enabled.
+         Fixes #454 and #381.
+
+2019-06-09 01:34:04 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * .gitignore:
+       * .gitmodules:
+       * Makefile.am:
+       * README:
+       * TODO:
+       * autogen.sh:
+       * common:
+       * configure.ac:
+       * data/Makefile.am:
+       * data/bash-completion/helpers/.gitignore:
+       * docs/.gitignore:
+       * docs/plugins/.gitignore:
+       * docs/random/.gitignore:
+       * docs/random/autotools:
+       * docs/random/omega/testing/.gitignore:
+       * gst/.gitignore:
+       * gst/Makefile.am:
+       * gst/parse/.gitignore:
+       * gst/parse/Makefile.am:
+       * gst/printf/Makefile.am:
+       * libs/Makefile.am:
+       * libs/gst/Makefile.am:
+       * libs/gst/base/.gitignore:
+       * libs/gst/base/Makefile.am:
+       * libs/gst/check/.gitignore:
+       * libs/gst/check/Makefile.am:
+       * libs/gst/check/libcheck/Makefile.am:
+       * libs/gst/controller/.gitignore:
+       * libs/gst/controller/Makefile.am:
+       * libs/gst/helpers/.gitignore:
+       * libs/gst/helpers/Makefile.am:
+       * libs/gst/net/.gitignore:
+       * libs/gst/net/Makefile.am:
+       * m4/.gitignore:
+       * m4/Makefile.am:
+       * m4/check-checks.m4:
+       * pkgconfig/.gitignore:
+       * pkgconfig/Makefile.am:
+       * plugins/Makefile.am:
+       * plugins/elements/.gitignore:
+       * plugins/elements/Makefile.am:
+       * plugins/tracers/.gitignore:
+       * plugins/tracers/Makefile.am:
+       * po/.gitignore:
+       * po/Makevars:
+       * po/POTFILES:
+       * po/README:
+       * po/remove-potcdate.sin:
+       * scripts/create-uninstalled-setup.sh:
+       * scripts/five-bugs-a-day.pl:
+       * scripts/git-update.sh:
+       * scripts/gst-uninstalled:
+       * stamp.h.in:
+       * tests/.gitignore:
+       * tests/Makefile.am:
+       * tests/benchmarks/.gitignore:
+       * tests/benchmarks/Makefile.am:
+       * tests/check/.gitignore:
+       * tests/check/Makefile.am:
+       * tests/check/elements/.gitignore:
+       * tests/check/generic/.gitignore:
+       * tests/check/gst/.gitignore:
+       * tests/check/libs/.gitignore:
+       * tests/check/pipelines/.gitignore:
+       * tests/examples/Makefile.am:
+       * tests/examples/adapter/.gitignore:
+       * tests/examples/adapter/Makefile.am:
+       * tests/examples/controller/.gitignore:
+       * tests/examples/controller/Makefile.am:
+       * tests/examples/helloworld/.gitignore:
+       * tests/examples/helloworld/Makefile.am:
+       * tests/examples/memory/.gitignore:
+       * tests/examples/memory/Makefile.am:
+       * tests/examples/netclock/.gitignore:
+       * tests/examples/netclock/Makefile.am:
+       * tests/examples/ptp/.gitignore:
+       * tests/examples/ptp/Makefile.am:
+       * tests/examples/stepping/.gitignore:
+       * tests/examples/stepping/Makefile.am:
+       * tests/examples/streamiddemux/Makefile.am:
+       * tests/examples/streams/.gitignore:
+       * tests/examples/streams/Makefile.am:
+       * tests/misc/Makefile.am:
+       * tools/.gitignore:
+       * tools/Makefile.am:
+         Remove autotools build system
+
+2019-10-10 15:53:16 +0200  Edward Hervey <edward@centricular.com>
+
+       * gst/gstbus.c:
+       * tests/check/gst/gstdatetime.c:
+       * tests/check/gst/gstevent.c:
+         core: Avoid usage of deprecated API
+         GTimeval and related functions are now deprecated in glib.
+         Replacement APIs have been present since 2.26
+
+2019-09-23 11:19:07 -0400  Xavier Claessens <xavier.claessens@collabora.com>
+
+       * libs/gst/check/gstcheck.c:
+         Check buffer size before checking buffer data
+         If the expected size is bigger than the actual buffer size, it would
+         memcmp random memory which could lead to crashes instead of proper error
+         reporting.
+
+2019-09-24 10:09:08 -0400  Xavier Claessens <xavier.claessens@collabora.com>
+
+       * plugins/elements/gstdataurisrc.c:
+       * tests/check/elements/dataurisrc.c:
+         dataurisrc: Do not include trailing `\0` into buffer
+
+2019-09-24 10:06:51 -0400  Xavier Claessens <xavier.claessens@collabora.com>
+
+       * libs/gst/check/gstharness.c:
+       * libs/gst/check/gstharness.h:
+         harness: Add gst_harness_pull_until_eos()
+
+2019-10-06 11:12:11 -0400  Aaron Boxer <aaron.boxer@collabora.com>
+
+       * NEWS:
+       * docs/README:
+       * docs/random/TODO-pre-0.9:
+       * docs/random/ensonic/dynlink.txt:
+       * docs/random/ensonic/interfaces.txt:
+       * docs/random/eos:
+       * docs/random/interfaces:
+       * docs/random/phonon-gst:
+       * docs/random/rtp:
+       * docs/random/status-0.11-14-jun-2011.txt:
+       * docs/random/types3:
+       * docs/random/wtay/autoplug2:
+       * docs/random/wtay/eos-19012001:
+       * docs/random/wtay/eos2:
+       * docs/random/wtay/eos4:
+       * docs/random/wtay/negotiation3:
+       * docs/random/wtay/network-transp:
+       * docs/random/wtay/pipelineinfo:
+       * docs/random/wtay/porting-list-0.11.txt:
+       * docs/random/wtay/scheduling_ideas:
+       * gst/gstcontrolbinding.c:
+       * gst/gstdatetime.c:
+       * gst/gstdevicemonitor.c:
+       * gst/gstdeviceprovider.c:
+       * libs/gst/base/gstbitwriter.c:
+       * libs/gst/base/gstindex.c:
+       * libs/gst/check/gstcheck.c:
+       * libs/gst/check/libcheck/check_pack.c:
+       * libs/gst/helpers/gst_gdb.py:
+       * plugins/elements/gstmultiqueue.c:
+       * tests/check/elements/queue.c:
+       * tests/check/gst/gstcontroller.c:
+       * tests/check/gst/gstghostpad.c:
+       * tests/check/libs/collectpads.c:
+       * tests/check/pipelines/parse-launch.c:
+         documentation: fix a number of typos
+
+2019-10-04 20:01:46 +0300  Jordan Petridis <jpetridis@gnome.org>
+
+       * libs/gst/controller/gstdirectcontrolbinding.c:
+         gstdirectcontrolbinding: Fix integer comparison
+         i is declared as gint but then compared against `n_values` guint
+         in the for loop below.
+
+2019-09-30 11:49:35 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstbuffer.c:
+       * gst/gstcaps.c:
+         gst: Don't pass miniobjects to GST_DEBUG_OBJECT() and similar macros
+         The argument must be at least a GObject according to the GstLogFunction
+         definition, and while the default C log function handles miniobjects
+         just fine this is crashing bindings and user-supplied log functions that
+         (rightfully) don't expect anything but GObjects.
+
+2019-09-07 04:36:18 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstvalue.c:
+       * tests/check/gst/gstvalue.c:
+         gstvalue: use value_nick for serialization
+         not value_name . This was causing incorrect launch lines to be
+         displayed by gst-device-monitor, and the deserialization code
+         below works with nicks.
+
+2019-09-10 00:28:45 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstdeviceprovider.c:
+         deviceprovider: set the bus to non-flushing before calling klass->start
+         Not posting DEVICE_ADDED messages while a device provider is being
+         started makes things awkward for applications, as they have to call
+         get_devices() after starting the monitor.
+         This requires redundant code on the application side, and as far as
+         I understand also could cause race conditions, when a device gets
+         added between the calls to gst_device_monitor_start() and
+         gst_device_monitor_get_devices(), causing the application to "see"
+         the same device twice.
+
+2019-09-12 10:09:18 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstelementfactory.c:
+         element: Enforce that elements created by gst_element_factory_create/make() are floating
+         Bindings might have a hard time making sure that the reference is indeed
+         still floating after returning here.
+         See https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/444
+
+2019-09-12 10:08:39 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstdevice.c:
+         device: Enforce that elements created by gst_device_create_element() are floating
+         Bindings might have a hard time making sure that the reference is indeed
+         still floating after returning here.
+         See https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/444
+
+2019-09-12 10:03:08 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstdevice.c:
+         device: gst_device_create_element() is `transfer floating`, not `transfer full`
+         Fixing the annotation fixes leaking of the created element in all
+         bindings using GObject-Introspection.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/444
+
+2019-09-10 12:31:40 +0200  Sebastiano Barrera <sebastiano.barrera@gmail.com>
+
+       * libs/gst/base/gstbasesink.h:
+       * libs/gst/base/gstbasesrc.h:
+         base: GstBaseSrc/GstBaseSink::get_caps: add (nullable) to `filter`
+         The virtual method named `get_caps` in both `GstBaseSrc` and
+         `GstBaseSink` has a `filter` parameter which can be `NULL` (the
+         default implementation in GstBaseSrc already considers the case).
+         Before this commit, there was no gtk-doc annotation representing this
+         fact, which caused the corresponding entry in the GIR file to also
+         miss this fact.
+         This caused bugs in other places, such inducing the Vala compiler to
+         introduce a wrongly assert on `(filter != NULL)` in every
+         implementation of the `get_caps` method implemented in Vala.
+
+2019-08-26 07:34:30 +0200  Niels De Graef <nielsdegraef@gmail.com>
+
+       * gst/gstbin.c:
+       * gst/gstbus.c:
+       * gst/gstchildproxy.c:
+       * gst/gstclock.c:
+       * gst/gstdeviceprovider.c:
+       * gst/gstelement.c:
+       * gst/gstobject.c:
+       * gst/gstpad.c:
+       * gst/gstpadtemplate.c:
+       * gst/gstregistry.c:
+       * gst/gststreamcollection.c:
+       * libs/gst/base/gstaggregator.c:
+       * libs/gst/base/gstdataqueue.c:
+       * libs/gst/base/gstindex.c:
+       * libs/gst/controller/gsttimedvaluecontrolsource.c:
+       * plugins/elements/gstfakesink.c:
+       * plugins/elements/gstfakesrc.c:
+       * plugins/elements/gstidentity.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gsttypefindelement.c:
+         Don't pass default GLib marshallers for signals
+         By passing NULL to `g_signal_new` instead of a marshaller, GLib will
+         actually internally optimize the signal (if the marshaller is available
+         in GLib itself) by also setting the valist marshaller. This makes the
+         signal emission a bit more performant than the regular marshalling,
+         which still needs to box into `GValue` and call libffi in case of a
+         generic marshaller.
+         Note that for custom marshallers, one would use
+         `g_signal_set_va_marshaller()` with the valist marshaller instead.
 
-       * po/hu.po:
-         Update translations
+2019-09-07 12:32:40 +0100  Jim Mason <jmason@ibinx.com>
 
-2019-12-03 10:40:37 +0000  Tim-Philipp Müller <tim@centricular.com>
+       * plugins/elements/gstelements_private.c:
+         consolidated IOV_MAX/UIO_MAXIOV handling per GLib + legacy behaviour for osx/ios
 
-       * gst/parse/grammar.y:
-       * gst/parse/meson.build:
-         Revert "gst/parse: define pure-parser depending on bison version"
-         This reverts commit 77141834bb5d124fb5781ed3be6230cc66cb42de.
-         This breaks the autotools build and it seems too much effort to
-         fix that up just to fix a bison warning.
+2019-09-06 19:23:01 +0100  Jim Mason <jmason@ibinx.com>
 
-2019-11-27 15:47:32 +0100  Edward Hervey <bilboed@bilboed.com>
+       * plugins/elements/gstelements_private.c:
+         gst_writev: respect IOV_MAX for the writev iovec array #439
 
-       * plugins/tracers/gstlatency.c:
-         tracers: Don't leak temporary GstStructure
-         CID: 1455462
+2019-09-04 16:59:58 +0300  Vivia Nikolaidou <vivia@ahiru.eu>
 
-2019-08-26 12:48:28 +0200  Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: Added gst_pad_get_single_internal_link
+         gst_pad_iterate_internal_links is usually used to find a single internal
+         link that a pad has, e.g. to find the corresponding pad of a multiqueue.
+         Added a helper function that will return either a single internal link,
+         if there's no other, or NULL.
 
-       * gst/parse/grammar.y.in:
-       * gst/parse/meson.build:
-         gst/parse: define pure-parser depending on bison version
-         After release bison 2.5 the declaration %pure-parser was deprecated
-         in favor of %define api.pure
-         Nonetheless, until bison 3.4, the declaration was treated as backward
-         compatibility, but now bison shows a warning:
-         warning: deprecated directive, use ‘%define api.pure’
-         The patch's approach is to handle both directives according with the
-         used bison's version, by string replacement at source configuration
-         stage.
+2019-09-03 10:38:13 +0200  David Svensson Fors <davidsf@axis.com>
 
-2019-10-25 01:41:27 +0300  Sebastian Dröge <sebastian@centricular.com>
+       * gst/gstminiobject.c:
+         miniobject: free qdata array when the last qdata is removed
+         In cases with many long-lived buffers that have qdata only very
+         briefly, the memory overhead of keeping an array of 16 GstQData
+         structs for each buffer can be significant. We free the array when
+         the last qdata is removed, like it was done in 1.14.
+         Fixes #436
 
-       * plugins/elements/gsttee.c:
-         tee: First deactivate the pad and then remove it when releasing pads
-         This reverts a96002bb28c21b30fb9338a4620ad20504c70aa5, which is not
-         necessary anymore. If we release the pad after removing it then none of
-         the deactivation code will actually be called because the pad has no
-         parent anymore, and we require a parent on the pad for deactivation to
-         happen.
-         This can then, among other things, cause a streaming thread to be still
-         stuck in a pad probe because the pad was never flushed, and waiting
-         there forever because now the pad will actually never be flushed anymore.
+2019-09-03 13:44:24 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
 
-2019-10-25 01:39:50 +0300  Sebastian Dröge <sebastian@centricular.com>
+       * gst/gstbin.c:
+         bin: Fix minor race when adding to a bin
+         This patch simply add a null check around a case where a child may have
+         been unparented concurrently to the deep_add_remove operation. This was
+         found by accident in the form of an "IS_GST_OBJECT" assertion, but had
+         no other known side effect in that test.
 
-       * plugins/elements/gsttee.c:
-         tee: Check for the removed pad flag also in the slow pushing path
-         If a pad is currently being released we don't want to forward the
-         FLUSHING flow return but instead consider it as NOT_LINKED. FLUSHING
-         would also cause upstream to be FLUSHING.
-         This part was missed in a3c4a3201a705eb1934ceeea34d1ca42d4571c07 and
-         resulted in a different (and wrong) workaround in
-         a96002bb28c21b30fb9338a4620ad20504c70aa5.
+2019-08-30 12:04:40 +1000  Matthew Waters <matthew@centricular.com>
 
-2019-10-25 01:39:05 +0300  Sebastian Dröge <sebastian@centricular.com>
+       * libs/gst/check/libcheck/meson.build:
+         libcheck: fix macos werror build
+         ../libs/gst/check/libcheck/check.c:617:15: error: result of comparison of constant 4294967295 with expression of type 'clockid_t' is always false [-Werror,-Wtautological-constant-out-of-range-compare]
+         if (clockid == -1) {
+         ~~~~~~~ ^  ~~
 
-       * plugins/elements/gsttee.c:
-         tee: Lock mutex before reading the removed flag of the pads
-         Otherwise we're not guaranteed to read the very latest value that
-         another thread might've written in there when the pad was released, and
-         could instead work with an old value.
+2019-08-28 15:19:54 +1000  Matthew Waters <matthew@centricular.com>
 
-2019-09-30 11:34:51 +0300  Sebastian Dröge <sebastian@centricular.com>
+       * plugins/elements/gstfdsink.c:
+       * plugins/elements/gstfdsrc.c:
+       * plugins/elements/gstfilesrc.c:
+         file/fdsrc: use struct stat64 on android to match stat64()
+         Fixes android werror failures:
+         ../plugins/elements/gstfdsrc.c:244:25: error: incompatible pointer types passing 'struct stat *' to parameter of type 'struct stat64 *' [-Werror,-Wincompatible-pointer-types]
+         if (fstat (src->fd, &stat_results) < 0)
+         ^~~~~~~~~~~~~
+         /home/matt/Projects/cerbero/build/android-ndk-18/sysroot/usr/include/sys/stat.h:159:38: note: passing argument to parameter '__buf' here
+         int fstat64(int __fd, struct stat64* __buf) __RENAME_STAT64(fstat, 3, 21);
+         ^
+         ../plugins/elements/gstfdsrc.c:560:23: error: incompatible pointer types passing 'struct stat *' to parameter of type 'struct stat64 *' [-Werror,-Wincompatible-pointer-types]
+         if (fstat (src->fd, &stat_results) < 0)
+         ^~~~~~~~~~~~~
+         /home/matt/Projects/cerbero/build/android-ndk-18/sysroot/usr/include/sys/stat.h:159:38: note: passing argument to parameter '__buf' here
+         int fstat64(int __fd, struct stat64* __buf) __RENAME_STAT64(fstat, 3, 21);
+         ^
+         if (fstat (fd, &stat_results) < 0)
+         ^~~~~~~~~~~~~
+         /home/matt/Projects/cerbero/build/android-ndk-18/sysroot/usr/include/sys/stat.h:159:38: note: passing argument to parameter '__buf' here
+         int fstat64(int __fd, struct stat64* __buf) __RENAME_STAT64(fstat, 3, 21);
+         ^
+         if (fstat (src->fd, &stat_results) < 0)
+         ^~~~~~~~~~~~~
+         ../../../../../android-ndk-18/sysroot/usr/include/sys/stat.h:159:38: note: passing argument to parameter '__buf' here
+         int fstat64(int __fd, struct stat64* __buf) __RENAME_STAT64(fstat, 3, 21);
+         ^
+         ../plugins/elements/gstfilesrc.c:477:23: error: incompatible pointer types passing 'struct stat *' to parameter of type 'struct stat64 *' [-Werror,-Wincompatible-pointer-types]
+         if (fstat (src->fd, &stat_results) < 0)
+         ^~~~~~~~~~~~~
+         ../../../../../android-ndk-18/sysroot/usr/include/sys/stat.h:159:38: note: passing argument to parameter '__buf' here
+         int fstat64(int __fd, struct stat64* __buf) __RENAME_STAT64(fstat, 3, 21);
+         ^
 
-       * gst/gstbin.c:
-         bin: Drop need-context messages without source instead of crashing
+2019-08-26 22:36:25 +1000  Matthew Waters <matthew@centricular.com>
 
-2019-09-30 11:49:35 +0300  Sebastian Dröge <sebastian@centricular.com>
+       * libs/gst/check/libcheck/meson.build:
+         check: fix werror build with clang
+         Silence -Wformat-nonliteral warnings from the internal copy of libcheck
+         ../subprojects/gstreamer/libs/gst/check/libcheck/check.c:379:29: warning: format string is not a string literal [-Wformat-nonliteral]
+         vsnprintf (buf, BUFSIZ, msg, ap);
+         ^~~
+         ../subprojects/gstreamer/libs/gst/check/libcheck/check_error.c:48:21: warning: format string is not a string literal [-Wformat-nonliteral]
+         vfprintf (stderr, fmt, args);
+         ^~~
+         ../subprojects/gstreamer/libs/gst/check/libcheck/check_str.c:92:29: warning: format string is not a string literal [-Wformat-nonliteral]
+         n = vsnprintf (p, size, fmt, ap);
+         ^~~
+
+2019-08-25 19:37:30 +0200  Niels De Graef <nielsdegraef@gmail.com>
 
-       * gst/gstbuffer.c:
-       * gst/gstcaps.c:
-         gst: Don't pass miniobjects to GST_DEBUG_OBJECT() and similar macros
-         The argument must be at least a GObject according to the GstLogFunction
-         definition, and while the default C log function handles miniobjects
-         just fine this is crashing bindings and user-supplied log functions that
-         (rightfully) don't expect anything but GObjects.
+       * gst/gstobject.c:
+         object: Use g_object_notify_by_pspec()
+         `g_object_notify()` actually takes a global lock to look up the
+         `GParamSpec` that corresponds to the given property name. It's not a
+         huge performance hit, but it's easily avoidable by using the
+         `_by_pspec()` variant.
 
 2019-08-20 01:02:48 +0900  Seungha Yang <seungha.yang@navercorp.com>
 
          Since it's OS specific behavior, that's hard to completely avoid it
          but we can protect it at least among our printing interfaces side.
 
-=== release 1.16.1 ===
+2019-08-23 18:17:41 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstpromise.c:
+       * gst/gsttaglist.h:
+         docstrings: port ulinks to markdown links
+
+2019-08-20 17:18:31 +0200  Johan Sternerup <johast@axis.com>
+
+       * gst/gstutils.c:
+         utils: Avoid memory merge in gst_util_dump_buffer()
+         For buffers with multiple memory chunks, gst_buffer_map() has the side
+         effect of merging the memory chunks into one contiguous
+         chunk. Since gst_util_dump_mem() used gst_buffer_map() the internals
+         of the buffer could actually change as a result of printing it.
+         For the case of a buffer containing several memory chunks,
+         gst_memory_map() is now used to obtain the memory address and each
+         memory chunk is dumped separately preceded by a header line. The
+         behaviour for a buffer containing a single memory chunk is left unchanged.
+
+2019-08-19 18:19:50 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: Always handle serialized events/queries directly before waiting
+         Otherwise it can happen that we start waiting for another pad, while one
+         pad already has events that can be handled and potentially also a buffer
+         that can be handled. That buffer would then however not be accessible by
+         the subclass from GstAggregator::get_next_time() as there would be the
+         events in front of it, which doesn't allow the subclass then to
+         calculate the next time based on already available buffers.
+         As a side-effect this also allows removing the duplicated event handling
+         code in the aggregate function as we'll always report pads as not ready
+         when there is a serialized event or query at the top of at least one
+         pad's queue.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/428
+
+2019-08-15 12:56:06 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * libs/gst/check/meson.build:
+         meson: fix warning about configure_file() install kwarg
+         The install kwarg on configure_file() was only added in
+         Meson 0.50 but we're targetting older versions as well,
+         which caused a warning. The install kwarg is not needed
+         here as we specify install_dir, so we can just drop it.
+         Fixes #379
+
+2019-08-14 14:25:48 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+       * libs/gst/base/gstaggregator.h:
+         aggregator: Add sink_event_pre_queue() and sink_query_pre_queue() vfuncs
+         These allow subclasses catching serialized events/queries before they're
+         queued up.
+
+2019-08-14 10:05:53 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+       * libs/gst/base/gstaggregator.h:
+         aggregator: Add GstAggregator::negotiate()
+         For consistency with other base classes and for allowing to completely
+         override the negotiation behaviour.
+
+2019-08-14 09:51:55 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: Actually handle NEED_DATA return from update_src_caps()
+         The documentation says that this allows the subclass to signal that it
+         needs more data before it can decide on caps, so let's actually
+         implement it that way.
+
+2019-08-13 19:57:08 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: Assert if the sink/src pad type that is to be used is not a GstAggregatorPad or subclass thereof
+
+2019-08-13 19:55:59 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: Ensure that the source pad is created as a GstAggregatorPad if no type is given in the pad template
+         Otherwise we would create a GstPad and that causes invalid memory
+         accesses later.
+
+2019-08-06 10:09:22 +0530  Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+       * plugins/tracers/gstlatency.c:
+         latency: fix custom event leaks
+         If the element before the sink needs $n buffers to produce one output
+         buffer, we were reffing $n events and unreffing only one.
+         Prevent this by using g_object_set_qdata_full() to handle the event
+         unreffing so we're sure no ref will be lost.
+
+2019-08-12 11:53:33 +0300  Jan Alexander Steffens (heftig) <jsteffens@make.tv>
+
+       * gst/gstelement.c:
+       * gst/gstelement.h:
+         element: Added gst_element_get_current_clock_time and gst_element_get_current_running_time
+         Helper functions for getting the element clock's time, and the clock
+         time minus base time, respectively.
+
+2019-08-08 13:49:07 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * configure.ac:
+       * gst/gstregistry.c:
+       * meson.build:
+         registry: Use plugin directory from the build system for relocateable Windows builds
+         Instead of guessing something based on preprocessor defines and magic.
+
+2019-04-30 17:24:50 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gstdevicemonitor.c:
+         device-monitor: list hidden providers before listing devices
+         The way it was implemented could make the list updated after the
+         list of device was filled with supposdely hidden devices
+
+2019-08-06 15:28:58 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * plugins/elements/gstfunnel.c:
+         funnel: fix documentation
+         funnel no longer sends its own segment since:
+         bbb26f875692a6cd84050c545ba85a7d2129cf5d
+         Update the documentation to reflect that
+
+2019-08-06 00:05:22 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * gst/gstmessage.h:
+         message: fix up enum value for GST_MESSAGE_DEVICE_CHANGED
+         This was added in 1.16 and accidentally duplicated the value of
+         the existing GST_MESSAGE_REDIRECT.
+         As the only known user of this message is GStreamer core itself,
+         and it is quite an obscure message, it seems best to just fix up
+         the enum value even if that technically breaks API.
+         Fixes #418
+
+2019-08-06 03:16:35 +0000  Keri Henare <keri.freedesktop@henare.co.nz>
+
+       * configure.ac:
+         Removes unnecessary "Sissy" pejorative from configure.ac warning message.
+
+2019-07-30 21:40:47 -0400  Doug Nazar <nazard@nazar.ca>
+
+       * gst/gstinfo.c:
+         info: Fix deadlock in gst_ring_buffer_logger_log
+         gst_ring_buffer_logger_log calls several functions while formatting
+         the message which may in turn log a message while we already hold
+         the mutex. Do all formatting first before acquiring the mutex to
+         avoid this and reduce the time we hold the mutex.
+
+2019-08-02 13:07:58 +0530  Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+       * plugins/tracers/gstlatency.c:
+       * plugins/tracers/gstrusage.c:
+       * plugins/tracers/gststats.c:
+         tracers: set MAY_BE_LEAKED on tracer records
+         The records are static and so appear as false positives when using those
+         tracers with the leaks tracer as well.
+         The leaks tracer was already setting this flag on its record so let's
+         set it on the other ones as well.
+
+2019-07-22 15:06:20 +0000  Alicia Boya García <ntrrgc@gmail.com>
+
+       * plugins/elements/gstdownloadbuffer.c:
+         downloadbuffer: Check for flush after seek
+         In gst_download_buffer_wait_for_data(), when a seek is made with
+         perform_seek_to_offset() the `qlock` is released temporarily. Therefore,
+         the flushing condition can be set during this period and should be
+         checked.
+         This was not being checked before, causing occasional deadlocks when
+         GST_DOWNLOAD_BUFFER_WAIT_ADD_CHECK() was called.
+         GST_DOWNLOAD_BUFFER_WAIT_ADD_CHECK() assumes that the caller has already
+         checked that we're not flushing before, since this is done when
+         acquiring the lock; so if we release it temporarily somewhere, we need
+         to check for flush again.
+         Without that check, the function would keep waiting for the condition
+         variable to be notified before checking for flushing condition again,
+         and that may very well never happen. This was reproduced when during pad
+         deactivation when running WebKit in gdb.
+
+2019-07-19 21:57:09 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+       * plugins/elements/gstidentity.c:
+         identity: Non-live upstream have no max latency
+         sync=TRUE implementation changes the latency query of a non-live
+         upstream into live, though it wrongly set the upstream max latency to 0.
+         As non-live sources won't loose data if we wait longer, this should have
+         been reported as have no max latency limite (-1).
+
+2019-07-19 17:28:25 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: drop duplicated SEEK events
+         This is similar to what demuxers do, and necessary when multiple
+         sinks get seeked downstream of the aggregator: if we forward
+         duplicated seeks upstream, elements such as demuxers may drop
+         the flushing seeks, but return TRUE, aggregator then waits forever
+         for the flushing events.
+         Fixes #276
+
+2019-07-19 11:09:22 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: fix g-i warnings
+
+2019-07-14 22:41:56 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gst.c:
+       * gst/gstinfo.c:
+         info: Free some more memory on gst_deinit()
+
+2019-07-14 21:36:00 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstinfo.c:
+       * gst/gstinfo.h:
+       * tests/check/gst/gstinfo.c:
+         info: Deprecate gst_debug_category_free()
+         And change it to do nothing at all.
+         As debug categories don't use reference counting and they can be
+         retrieved from anywhere at any time by name, it is fundamentally unsafe
+         to free them at any point in time except for right before the end of the
+         process.
+         No code apart from a unit test seems to be currently using the function,
+         so deprecate it and also change it to do nothing at all.
+
+2019-07-11 17:53:53 +0100  Philippe Normand <philn@igalia.com>
+
+       * plugins/elements/gstidentity.c:
+         identity: Fix the ts-offset property getter
+         Previous code was a copy/paste from the property setter function.
+
+2019-07-08 19:09:03 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: Make parsing of explicit sink pad names more robust
+         When passing "sink_%d" twice to aggregator before it would create two
+         pads called "sink_0", because it failed to parse "%d" as integer and
+         used 0 instead then.
+         Instead validate that parsing was actually successful and also don't
+         even try to parse if the requested pad name contains a '%'.
+
+2019-07-08 13:16:08 +0200  Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+       * tools/gst-stats.c:
+         gst-stats: fix leaks
+         String returned from g_match_info_fetch() needs to be freed.
+
+2019-07-08 11:20:26 +0200  Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+       * tools/gst-stats.c:
+         gst-stats: sort latency by first activity before displaying
+         We use to display the latency of each element in random order which is
+         not very convenient when comparing latency between different runs.
+         Sort them by "first activity" (the first latency reported for each
+         element) so it's consistent betwen runs.
+         This is the same logic when sorting and displaying element stats.
+
+2019-07-07 20:42:56 +1000  Jan Schmidt <jan@centricular.com>
+
+       * gst/gsttracerutils.c:
+         gsttracerutils: Fix build with disabled tracer hooks.
+         Add a stub gst_tracing_get_active_tracers() call when building
+         with tracer hooks disabled.
+
+2019-07-02 17:14:50 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * docs/plugins/gst_plugins_cache.json:
+       * plugins/elements/gstmultiqueue.c:
+         multiqueue: Fix possible NULL pointer dereferencing
+         In the hotdoc inspector for example, pads are instantiated with
+         g_object_new, other code paths to get/set properties already make
+         that check.
+         And update doc cache
+
+2019-07-01 23:54:19 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * gst/gstinfo.c:
+         gstinfo: Fix typo in debug log message
+
+2019-07-01 20:20:13 +0530  Tim-Philipp Müller <tim@centricular.com>
+
+       * plugins/tracers/gstleaks.c:
+         leakstracer: Improve notes in the the get-live-objects API docs
+         It may not be obvious to the user how this action signal is meant to
+         be called, so document it.
+
+2019-07-01 15:05:58 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * tests/check/elements/leaks.c:
+         tests: Add test for new activity-tracking leaktracer API
+
+2019-06-21 18:17:13 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * plugins/tracers/gstleaks.c:
+       * plugins/tracers/gstleaks.h:
+         leakstracer: Add API for tracking and checkpointing objects
+         This feature was previously available only through the SIGUSR2 signal,
+         which meant it wasn't available on platforms that don't have UNIX
+         signals, such as Windows and with applications that already use
+         SIGUSR1 for something else.
+         Now we have action-signals for doing the same. These action signals
+         can also be used for fetching the checkpoint information
+         programmatically instead of printing to the debug log.
+
+2019-07-01 15:05:08 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * tests/check/elements/leaks.c:
+       * tests/check/gstreamer.supp:
+       * tests/check/meson.build:
+         tests: Add test for new live-objects leaktracer API
+         Needs a valgrind suppression for:
+         ==11119== Warning: invalid file descriptor -1 in syscall close()
+         ==11119== Warning: invalid file descriptor -1 in syscall close()
+         ==11119== Syscall param write(buf) points to uninitialised byte(s)
+         ==11119==    at 0x4C4AFAD: syscall (in /usr/lib64/libc-2.29.so)
+         ==11119==    by 0x4E70DF9: write_validate (Ginit.c:112)
+         ==11119==    by 0x4E70DF9: UnknownInlinedFun (Ginit.c:148)
+         ==11119==    by 0x4E70DF9: mincore_validate (Ginit.c:131)
+         ==11119==    by 0x4E70CC3: UnknownInlinedFun (Ginit.c:208)
+         ==11119==    by 0x4E70CC3: access_mem (Ginit.c:242)
+         ==11119==    by 0x4E75536: UnknownInlinedFun (libunwind_i.h:168)
+         ==11119==    by 0x4E75536: apply_reg_state (Gparser.c:863)
+         ==11119==    by 0x4E75A71: _ULx86_64_dwarf_step (Gparser.c:952)
+         ==11119==    by 0x4E71BD3: _ULx86_64_step (Gstep.c:71)
+         ==11119==    by 0x48BAF47: generate_unwind_trace (gstinfo.c:2726)
+         ==11119==    by 0x48BC92E: gst_debug_get_stack_trace (gstinfo.c:2908)
+         ==11119==    by 0x49B2BB2: handle_object_created.part.0 (gstleaks.c:384)
+         ==11119==    by 0x488134E: gst_object_constructed (gstobject.c:141)
+         ==11119==    by 0x49EC61B: g_object_new_internal (gobject.c:1845)
+         ==11119==    by 0x49EE347: g_object_new_valist (gobject.c:2128)
+         ==11119==    by 0x49EE69C: g_object_new (gobject.c:1648)
+         ==11119==    by 0x48CA59D: gst_pad_new_from_template (gstpad.c:867)
+         ==11119==    by 0x68C209E: gst_base_src_init (gstbasesrc.c:454)
+         ==11119==    by 0x4A0A0C3: g_type_create_instance (gtype.c:1858)
+         ==11119==    by 0x49EC42C: g_object_new_internal (gobject.c:1805)
+         ==11119==    by 0x49EDB14: g_object_new_with_properties (gobject.c:1973)
+         ==11119==    by 0x49EE6C0: g_object_new (gobject.c:1645)
+         ==11119==    by 0x48AF91A: gst_element_factory_create (gstelementfactory.c:372)
+         ==11119==  Address 0x1ffeffe000 is on thread 1's stack
+         ==11119==  in frame #6, created by generate_unwind_trace (gstinfo.c:2695)
+         Fixed in libunwind commit:
+         https://github.com/libunwind/libunwind/commit/b256722d49a63719c69c0416eba9163a4d069584
+         Needs a separate suppression for Debian because the callstack is
+         different there.
+
+2019-06-28 18:19:31 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * plugins/tracers/gstleaks.c:
+       * plugins/tracers/gstleaks.h:
+         leakstracer: Add API for logging leaks in the debug log
+         This is the equivalent of sending SIGUSR1 to the application, and is
+         useful on platforms where UNIX signals are not available, such as
+         Windows.
+
+2019-06-28 18:19:31 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * plugins/tracers/gstleaks.c:
+       * plugins/tracers/gstleaks.h:
+         leakstracer: Add API for fetching leaked objects
+         This allows programs to inspect the leaked objects directly, log them,
+         and so on. Unlike the existing mechanism to use SIGUSR1, this also
+         works on platforms that do not support UNIX signals, such as Windows
+         and with applications that already use SIGUSR1 for something else.
+
+2019-06-19 04:22:42 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * gst/gsttracer.h:
+       * gst/gsttracerutils.c:
+         gsttracer: Add new API to fetch the list of active tracers
+         This will be useful in the next commit where we add action-signals on
+         the leaks tracer to get information about leaks and to manipulate
+         checkpoints as a replacement for the SIGUSR1 and SIGUSR2 signals for
+         doing the same.
+
+2019-06-19 03:47:18 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * plugins/tracers/gstlatency.c:
+       * plugins/tracers/gstleaks.c:
+       * plugins/tracers/gstlog.c:
+       * plugins/tracers/gstrusage.c:
+       * plugins/tracers/gststats.c:
+         tracers: Allow setting a name for all tracer objects
+         This will be useful in combination with the next commit when we add
+         API to get a list of active tracers so that consumers of the API can
+         easily distinguish tracer objects.
+
+2019-06-29 09:22:05 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+       * gst/gstbufferpool.c:
+       * tests/check/gst/gstbufferpool.c:
+         bufferpool: Fix the buffer size reset code
+         The offset in gst_buffer_resize() is additive. So to move back the
+         offset to zero, we need to pass the opposite of the current offset. This
+         was raised through the related unit test failingon 32bit as on 64bit
+         the alignment padding was enough to hide the issue. The test was
+         modified to also fail on 64bit. This patch will remove spurious
+         assertions like:
+         assertion 'bufmax >= bufoffs + offset + size' failed
+         Fixes #316
+
+2019-06-24 21:14:51 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * plugins/tracers/gstleaks.c:
+         leakstracer: Get rid of GSlice usage
+         It's not faster than malloc, and is slower in most cases. Glib is also
+         getting rid of it entirely: https://gitlab.gnome.org/GNOME/glib/merge_requests/940
+
+2019-06-21 11:26:38 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * plugins/tracers/gstleaks.c:
+         leakstracer: Remove unused and redundant record fields
+         All leak records are obviously scoped to the process, and nothing in
+         the GstTracerRecord code uses these fields anyway.
+
+2019-06-21 10:43:18 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * gst/gsttracerrecord.c:
+         tracerrecord: Be stricter while parsing record templates
+         It's not really possible for us to recover when someone uses the
+         gst_tracer_record_new() API incorrectly. Also, document a piece of
+         somewhat-obscure code.
+
+2019-06-19 03:42:46 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * plugins/tracers/gstleaks.c:
+         leakstracer: Improve documentation for the element
+         Also print a useful g_warning() message when leaks are detected.
+
+2019-07-01 14:55:20 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * libs/gst/check/gstcheck.h:
+         gstcheck: Document strcmp used in string cmp macros
+         strcmp() does not allow the arguments to be NULL, but g_strcmp0()
+         does, so document that we use g_strcmp0() so that people don't need to
+         worry about that.
+
+2019-06-21 10:41:18 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * gst/gstsystemclock.c:
+         gstsystemclock: Mark the clock as MAY_BE_LEAKED
+         It is freed in gst_deinit(), but otherwise it is leaked.
+
+2019-06-19 03:39:59 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * gst/gstinfo.c:
+       * meson.build:
+         gstinfo: Rework stack trace detection a bit
+         Ensure that the code paths for HAVE_UNWIND and HAVE_DBGHELP are never
+         taken at the same time, even if the build file code changes.
+         Prefer DbgHelp over libunwind on Windows in case both are somehow
+         available because DbgHelp is only available when building with the
+         MSVC toolchain, and libunwind won't give us debug symbols from objects
+         built with the MSVC toolchain.
+         Also, print slightly more useful messages for the level of stack trace
+         support enabled, and document what each if conditional does.
+
+2019-06-19 03:19:16 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * gst/gstinfo.c:
+       * gst/gstinfo.h:
+       * plugins/tracers/gstleaks.c:
+         gstinfo: Add an explicit enum for GST_STACK_TRACE_SHOW_NONE
+         The code implicitly uses this value when the stack trace is not FULL.
+         Mostly useful for documenting the behaviour when each flag is passed
+         and for translating to/from strings.
+
+2019-06-24 14:35:16 +0200  Carlos Rafael Giani <crg7475@mailbox.org>
+
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasesrc.h:
+       * tests/check/libs/basesrc.c:
+         basesrc: Add public gst_base_src_negotiate () function
+         This is useful for when format changes occur mid-stream.
+
+2019-06-27 15:51:47 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * plugins/elements/gstmultiqueue.c:
+         multiqueue: Hold weak references to pads/multiqueue in SingleQueue
+         Without holding a ref we have no guarantees that the SingleQueue
+         doesn't have dangling pointers on those objects during its destruction.
+
+2019-05-06 19:19:47 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * gst/gstplugin.c:
+         gstplugin: Don't stat plugins when building for UWP
+         When using GStreamer with Universal Windows Platform apps, dynamic
+         plugins can only be loaded by filename (without a path) using
+         gst_plugin_load_file() which will call into g_module_open().
+         On Windows, GModule calls LoadLibrary() on the filename, but with
+         UWP we need to use LoadPackagedLibrary() which is basically the same
+         as LoadLibrary(), except it looks only for DLLs (by name) that have
+         been packaged as assets with the app.
+         These assets are not files and cannot be accessed using normal file
+         APIs such as open() or stat().
+         The upstream glib merge request for adding LoadPackagedLibrary support
+         is: https://gitlab.gnome.org/GNOME/glib/merge_requests/951
+         NOTE: Whitespcae removal is to make gst-indent happy
+
+2019-05-16 04:57:16 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * gst/gstconfig.h.in:
+         gstconfig.h.in: Windows ARM64 does not allow unaligned access
+
+2019-06-19 17:39:58 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+       * libs/gst/check/gsttestclock.c:
+       * tests/check/libs/gsttestclock.c:
+         testclock: Allow calling crank with a past entry
+         At the moment, we can only use crank if the pending entry is in the
+         future. This patch leaves the clock time to the same point if the
+         pending entry was in the past. This still execute a single entry. This
+         will be needed for the jitterbuffer, since as soon as we stop waking up
+         the jitterbuffer when the timer is reschedule later, we may endup with
+         such case in the unit tests.
+         Related to #608
+
+2019-06-22 23:46:35 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * plugins/elements/gstmultiqueue.c:
+         multiqueue: Stop using the gst_pad_element_private API
+         There was a race where we could still get the pad event function
+         called when its private member were already unset, leading to
+         a segfault in the event handler:
+         ```
+         0  gst_multi_queue_src_event (pad=<optimized out>, parent=<optimized out>, event=0x7f3ff0007600) at ../subprojects/gstreamer/plugins/elements/gstmultiqueue.c:2534
+         2534          ret = gst_pad_push_event (sq->sinkpad, event);
+         [Current thread is 1 (Thread 0x7f406c0258c0 (LWP 21925))]
+         (gdb) bt
+         0  0x00007f4062ec1399 in gst_multi_queue_src_event (pad=<optimized out>, parent=<optimized out>, event=0x7f3ff0007600 [GstEvent]) at ../subprojects/gstreamer/plugins/elements/gstmultiqueue.c:2534
+         1  0x00007f406b40f46d in gst_validate_pad_monitor_src_event_check (handler=0x7f4062ec1360 <gst_multi_queue_src_event>, event=0x7f3ff0007600 [GstEvent], parent=0x7f3fcc01f090 [GstMultiQueue|multiqueue167], pad_monitor=0x7f3fe809e7c0 [GstValidatePadMonitor|validatepadmonitor2213]) at ../subprojects/gst-devtools/validate/gst/validate/gst-validate-pad-monitor.c:2101
+         2  0x00007f406b40f46d in gst_validate_pad_monitor_src_event_func (pad=<optimized out>, parent=0x7f3fcc01f090 [GstMultiQueue|multiqueue167], event=0x7f3ff0007600 [GstEvent]) at ../subprojects/gst-devtools/validate/gst/validate/gst-validate-pad-monitor.c:2374
+         3  0x00007f406b904387 in gst_pad_send_event_unchecked (pad=pad@entry=0x7f3fdc027650 [GstPad|src_0], event=event@entry=0x7f3ff0007600 [GstEvent], type=<optimized out>, type@entry=GST_PAD_PROBE_TYPE_EVENT_UPSTREAM) at ../subprojects/gstreamer/gst/gstpad.c:5772
+         4  0x00007f406b90481b in gst_pad_push_event_unchecked (pad=pad@entry=0x7f4058182fc0 [GstPad|sink], event=event@entry=0x7f3ff0007600 [GstEvent], type=type@entry=GST_PAD_PROBE_TYPE_EVENT_UPSTREAM) at ../subprojects/gstreamer/gst/gstpad.c:5417
+         5  0x00007f406b90f016 in gst_pad_push_event (pad=0x7f4058182fc0 [GstPad|sink], event=event@entry=0x7f3ff0007600 [GstEvent]) at ../subprojects/gstreamer/gst/gstpad.c:5554
+         6  0x00007f406a1c99ba in gst_video_decoder_src_event_default (decoder=0x7f3fe81c6060 [GstTheoraDec|theoradec46], event=<optimized out>) at ../subprojects/gst-plugins-base/gst-libs/gst/video/gstvideodecoder.c:1532
+         7  0x00007f406b40f46d in gst_validate_pad_monitor_src_event_check (handler=0x7f406a1ca270 <gst_video_decoder_src_event>, event=0x7f3ff0007600 [GstEvent], parent=0x7f3fe81c6060 [GstTheoraDec|theoradec46], pad_monitor=0x7f4028163aa0 [GstValidatePadMonitor|validatepadmonitor2216]) at ../subprojects/gst-devtools/validate/gst/validate/gst-validate-pad-monitor.c:2101
+         8  0x00007f406b40f46d in gst_validate_pad_monitor_src_event_func (pad=<optimized out>, parent=0x7f3fe81c6060 [GstTheoraDec|theoradec46], event=0x7f3ff0007600 [GstEvent]) at ../subprojects/gst-devtools/validate/gst/validate/gst-validate-pad-monitor.c:2374
+         ```
+         This make the GstSingleQueue a MiniObject, mainly so it is properly
+         refcounted.
+         This also make use of the GstMultiQueuePad class for srcpads which
+         is totally valid as srcpads and sinkpads share the same SingleQueue
+         object.
+
+2019-06-21 15:38:15 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * gst/gstdevicemonitor.c:
+         devicemonitor: add debug category
+
+2019-06-20 14:04:55 +0200  Michael Bunk <bunk@iat.uni-leipzig.de>
+
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+       * gst/gstutils.c:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbasetransform.h:
+         Fixing various typos
+
+2019-06-20 16:42:01 +0530  Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+       * plugins/tracers/gstlatency.c:
+         latency: display event pointer in logs
+         This is quite useful for debugging when tracer is reporting the wrong
+         latency because of an element breaking the events/buffers ordering.
+
+2019-06-20 13:49:14 +0530  Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+       * plugins/elements/gstelements_private.c:
+         gstelements_private: sync gst_buffer_get_flags_string() with new flags
+
+2019-06-19 23:29:24 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * plugins/elements/gstmultiqueue.c:
+         multiqueue: never unref queries we do not own
+         The `query` argument of gst_pad_query is "transfer none".
+         Query objects are "borrowed" by the pad query handlers and those
+         should never unref them.
+         This was leading to double freed queries in a very racy way with nested
+         GESTimelines.
+
+2019-06-17 09:50:32 +0200  Havard Graff <havard.graff@gmail.com>
+
+       * gst/gstmeta.c:
+         gstmeta: Optimize get_tags() by using private quark table
+
+2019-06-13 10:32:32 +0200  Havard Graff <havard.graff@gmail.com>
+
+       * gst/gstpad.c:
+         pad: increase debug-level to warning for fatal outcomes
+
+2019-06-13 15:21:03 +0000  Håvard Graff <havard.graff@gmail.com>
+
+       * plugins/elements/gstqueue.c:
+         queue: don't report 0 max-latency for leaky queue if max was already 0.
+
+2019-05-22 10:09:47 +0200  Havard Graff <havard.graff@gmail.com>
+
+       * libs/gst/check/gstharness.c:
+         harness: move creating of buffer and event queues to harness itself
+         By only having it on sinkpad-creation, it is racy to write a test
+         with a sometimes-pad (like a demuxer) that you want to pull from, having
+         the pull wait until the pad arrives and the buffer can be produced.
+
+2018-10-03 13:56:22 +0200  Stian Selnes <stian@pexip.com>
+
+       * libs/gst/check/gstharness.c:
+         harness: Fix race when forwarding event while tearing down harness
+
+2018-05-28 10:57:13 +0200  Stian Selnes <stian@pexip.com>
+
+       * libs/gst/check/gstharness.c:
+         harness: Make sure pad functions are not called after teardown
+         For the query function there's a risk that the function may be called
+         after the harness has been teared down. Since the function accesses a
+         pointer to the harness via the pad's data, the harness must protect
+         itself against this.
+         Event and chain function is also handled for constistency, although
+         they don't have the same problem since the gstpad.c checks whether the
+         pad is flushing before calling these.
+
+2019-06-11 22:09:33 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: don't try to take STREAM_LOCK on sink pad flush
+         This was a misguided effort to try and guarantee the buffers of
+         the sink pads would not change during aggregate, when an upstream
+         branch is seeked independently, however this is simply incorrect
+         as downstream has not necessarily been flushed, or the aggregate
+         function might be waiting to receive buffers on other pads.
+
+2019-06-11 15:20:18 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: send flush_stop ourselves if needed
+         In !159 , we switched to sending flush_start ourselves from the
+         do_seek implementation. If no flushing seek successfully made its
+         way upstream, we need to send flush_stop ourselves as well.
+
+2019-06-10 17:23:29 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+         aggregator: don't hold stream lock when flushing
+         Releasing a GRecMutex from a different thread is undefined
+         behaviour.
+         There should be no reason to hold the stream lock from the
+         moment aggregator receives a flush_start until it receives
+         the last flush_stop: the source pad task is stopped, and can
+         only be restarted once the last flush_stop has arrived.
+         I can only speculate as to the reason why this was done,
+         as it was that way since the original commit. My best
+         guess is that aggregator originally didn't marshall events
+         and queries to the aggregate thread, and this somehow
+         helped work around this.
+
+2019-05-22 21:37:43 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * libs/gst/base/gstaggregator.c:
+       * tests/check/libs/aggregator.c:
+         aggregator: refactor flushing logic
+         Instead of tracking "pending_flush_*" on the pads and the
+         aggregator, we now simply track the last seqnum for flush start
+         and flush stop events on the pads, and use it to determine whether
+         we should enter or exit our flushing state.
+         See https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/issues/977
+
+2019-06-05 18:40:12 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * tests/check/gstreamer.supp:
+         valgrind: revert generic suppression of ld-related errors
+         the replacement suppression casts way too large a net, ignoring
+         all leaks in the main thread
+
+2019-06-05 20:58:45 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * tests/check/gstreamer.supp:
+         valgrind: ignore dlopen leaks when parsing launch lines
+
+2019-06-05 20:58:45 +0200  Mathieu Duponchelle <mathieu@centricular.com>
+
+       * tests/check/gstreamer.supp:
+         valgrind: suppress intentional debug list item leak
+
+2019-06-04 17:56:30 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gstconcat.c:
+         concat: Improve debug output a bit
+
+2019-06-04 17:55:30 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gstconcat.c:
+         concat: Reset last_stop on FLUSH_STOP too
+         Otherwise when seeking backwards we would keep the last_stop at the last
+         position we saw until playback passed the seek position again, and if
+         switching to the next pad happens in the meantime we would set the wrong
+         offset in the outgoing segment.
+
+2019-06-04 08:50:59 +0200  Niels De Graef <niels.degraef@barco.com>
+
+       * gst/gstallocator.h:
+       * gst/gstatomicqueue.h:
+       * gst/gstbin.h:
+       * gst/gstbuffer.h:
+       * gst/gstbufferlist.h:
+       * gst/gstbus.h:
+       * gst/gstcaps.h:
+       * gst/gstcapsfeatures.h:
+       * gst/gstclock.h:
+       * gst/gstcontext.h:
+       * gst/gstcontrolbinding.h:
+       * gst/gstcontrolsource.h:
+       * gst/gstdatetime.h:
+       * gst/gstdevice.h:
+       * gst/gstdevicemonitor.h:
+       * gst/gstdeviceprovider.h:
+       * gst/gstdeviceproviderfactory.h:
+       * gst/gstelement.h:
+       * gst/gstelementfactory.h:
+       * gst/gstevent.h:
+       * gst/gstghostpad.h:
+       * gst/gstiterator.h:
+       * gst/gstmemory.h:
+       * gst/gstmessage.h:
+       * gst/gstobject.h:
+       * gst/gstpad.h:
+       * gst/gstpadtemplate.h:
+       * gst/gstparse.h:
+       * gst/gstpipeline.h:
+       * gst/gstplugin.h:
+       * gst/gstpluginfeature.h:
+       * gst/gstpromise.h:
+       * gst/gstquery.h:
+       * gst/gstregistry.h:
+       * gst/gstsample.h:
+       * gst/gstsegment.h:
+       * gst/gststreamcollection.h:
+       * gst/gststreams.h:
+       * gst/gststructure.h:
+       * gst/gstsystemclock.h:
+       * gst/gsttaglist.h:
+       * gst/gsttask.h:
+       * gst/gsttaskpool.h:
+       * gst/gsttoc.h:
+       * gst/gsttracer.h:
+       * gst/gsttracerfactory.h:
+       * gst/gsttracerrecord.h:
+       * gst/gsttypefindfactory.h:
+       * gst/gsturi.h:
+       * libs/gst/base/gstadapter.h:
+       * libs/gst/base/gstaggregator.h:
+       * libs/gst/base/gstbaseparse.h:
+       * libs/gst/base/gstbasesink.h:
+       * libs/gst/base/gstbasesrc.h:
+       * libs/gst/base/gstbasetransform.h:
+       * libs/gst/base/gstcollectpads.h:
+       * libs/gst/base/gstdataqueue.h:
+       * libs/gst/base/gstflowcombiner.h:
+       * libs/gst/base/gstpushsrc.h:
+       * libs/gst/check/gsttestclock.h:
+       * libs/gst/controller/gstargbcontrolbinding.h:
+       * libs/gst/controller/gstdirectcontrolbinding.h:
+       * libs/gst/controller/gstinterpolationcontrolsource.h:
+       * libs/gst/controller/gstlfocontrolsource.h:
+       * libs/gst/controller/gstproxycontrolbinding.h:
+       * libs/gst/controller/gsttimedvaluecontrolsource.h:
+       * libs/gst/controller/gsttriggercontrolsource.h:
+       * libs/gst/net/gstnetclientclock.h:
+       * libs/gst/net/gstnettimepacket.h:
+       * libs/gst/net/gstnettimeprovider.h:
+       * libs/gst/net/gstptpclock.h:
+         Use G_DEFINE_AUTOPTR_CLEANUP_FUNC unconditionally
+         Since we started depending on GLib 2.44, we can be sure this macro is
+         defined (it will be a no-op on compilers that don't support it). For
+         plugins we should just start using `G_DECLARE_FINAL_TYPE` which means
+         we no longer need the macro there, but for most types in core we don't
+         want to break ABI, which means it's better to just keep it like it is
+         (and use the `#ifdef` instead).
 
-2019-09-23 11:01:50 +0100  Tim-Philipp Müller <tim@centricular.com>
+2019-05-31 22:56:09 +0200  Niels De Graef <niels.degraef@barco.com>
 
-       * ChangeLog:
-       * NEWS:
-       * RELEASE:
        * configure.ac:
-       * gstreamer.doap:
        * meson.build:
-         Release 1.16.1
+       * tests/check/elements/dataurisrc.c:
+         meson: Bump minimal GLib version to 2.44
+         This means we can use some newer features and get rid of some
+         boilerplate code using the `G_DECLARE_*` macros.
+         As discussed on IRC, 2.44 is old enough by now to start depending on it.
 
-2019-09-23 11:01:50 +0100  Tim-Philipp Müller <tim@centricular.com>
+2019-06-01 02:37:26 +0200  Mathieu Duponchelle <mathieu@centricular.com>
 
-       * docs/plugins/inspect/plugin-coreelements.xml:
-       * docs/plugins/inspect/plugin-coretracers.xml:
-         Update docs
+       * docs/meson.build:
+         docs: unprefix subproject paths
 
-2019-09-23 11:01:47 +0100  Tim-Philipp Müller <tim@centricular.com>
+2019-05-30 23:23:35 -0400  Thibault Saunier <tsaunier@igalia.com>
 
-       * po/bg.po:
-       * po/de.po:
-       * po/fr.po:
-       * po/hr.po:
-       * po/nb.po:
-       * po/tr.po:
-         Update translations
+       * docs/gst-hotdoc-plugins-scanner.c:
+       * docs/meson.build:
+       * docs/plugins/blank.md:
+       * docs/plugins/gst_plugins_cache.json:
+       * plugins/tracers/gstlatency.c:
+       * plugins/tracers/gstleaks.c:
+       * plugins/tracers/gstlog.c:
+       * plugins/tracers/gstrusage.c:
+       * plugins/tracers/gststats.c:
+         docs: Add tracers support
 
-2019-09-12 10:09:18 +0300  Sebastian Dröge <sebastian@centricular.com>
+2019-05-31 01:56:08 +0200  Mathieu Duponchelle <mathieu@centricular.com>
 
-       * gst/gstelementfactory.c:
-         element: Enforce that elements created by gst_element_factory_create/make() are floating
-         Bindings might have a hard time making sure that the reference is indeed
-         still floating after returning here.
-         See https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/444
+       * gst/gstelement.h:
+         gstelement: fix links to the gsterror page
 
-2019-09-12 10:08:39 +0300  Sebastian Dröge <sebastian@centricular.com>
+2019-05-31 01:45:41 +0200  Mathieu Duponchelle <mathieu@centricular.com>
 
-       * gst/gstdevice.c:
-         device: Enforce that elements created by gst_device_create_element() are floating
-         Bindings might have a hard time making sure that the reference is indeed
-         still floating after returning here.
-         See https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/444
+       * gst/gsttaglist.h:
+         gsttaglist: do not link to symbols from gst-plugins-base in doc
 
-2019-09-12 10:03:08 +0300  Sebastian Dröge <sebastian@centricular.com>
+2019-05-29 21:33:42 +0200  Mathieu Duponchelle <mathieu@centricular.com>
 
-       * gst/gstdevice.c:
-         device: gst_device_create_element() is `transfer floating`, not `transfer full`
-         Fixing the annotation fixes leaking of the created element in all
-         bindings using GObject-Introspection.
-         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/444
+       * gst/gst.c:
+       * gst/gstbus.c:
+       * gst/gstconfig.h.in:
+       * gst/gstdebugutils.c:
+       * gst/gsterror.c:
+       * gst/gstplugin.c:
+       * gst/gsttaglist.h:
+       * plugins/elements/gstdownloadbuffer.c:
+       * plugins/elements/gstfakesrc.c:
+       * plugins/elements/gstfdsrc.c:
+         doc: remove xml from comments
 
-2019-09-07 12:32:40 +0100  Jim Mason <jmason@ibinx.com>
+2019-05-22 18:56:34 -0400  Thibault Saunier <tsaunier@igalia.com>
 
-       * plugins/elements/gstelements_private.c:
-         consolidated IOV_MAX/UIO_MAXIOV handling per GLib + legacy behaviour for osx/ios
+       * docs/gst-hotdoc-plugins-scanner.c:
+       * docs/plugins/gst_plugins_cache.json:
+         docs: Document pad types
+         And update the plugins doc cache
 
-2019-09-06 19:23:01 +0100  Jim Mason <jmason@ibinx.com>
+2019-05-22 09:47:41 -0400  Thibault Saunier <tsaunier@igalia.com>
 
-       * plugins/elements/gstelements_private.c:
-         gst_writev: respect IOV_MAX for the writev iovec array #439
+       * libs/gst/base/gstaggregator.c:
+         aggregator: Minor documentation fix
 
-2019-09-03 10:38:13 +0200  David Svensson Fors <davidsf@axis.com>
+2015-07-29 11:48:33 +0100  Tim-Philipp Müller <tim@centricular.com>
 
-       * gst/gstminiobject.c:
-         miniobject: free qdata array when the last qdata is removed
-         In cases with many long-lived buffers that have qdata only very
-         briefly, the memory overhead of keeping an array of 16 GstQData
-         structs for each buffer can be significant. We free the array when
-         the last qdata is removed, like it was done in 1.14.
-         Fixes #436
+       * libs/gst/base/gstaggregator.c:
+         aggregator: fix flow-return boolean return type mismatch
+         Not that it matters, since we don't check the return value
+         anyway. Unclear why the aggregator pad flush function should
+         have a return value at all really, and perhaps it should be
+         called reset anyway. Spotted by dv on irc.
 
-2019-09-03 13:44:24 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
+2019-05-12 07:45:31 +0200  Michael Olbrich <m.olbrich@pengutronix.de>
 
-       * gst/gstbin.c:
-         bin: Fix minor race when adding to a bin
-         This patch simply add a null check around a case where a child may have
-         been unparented concurrently to the deep_add_remove operation. This was
-         found by accident in the form of an "IS_GST_OBJECT" assertion, but had
-         no other known side effect in that test.
+       * libs/gst/helpers/gst_gdb.py:
+         gdb: add gst_element_pad() function
+         Another helper to navigate a pipeline. It makes it possible to easily
+         access the pads of an element:
+         (gdb) print $gst_element_pad(basesink, "sink")
+         $1 = 0x7fffe80770f0 [GstPad|sink]
 
-2019-08-15 12:56:06 +0100  Tim-Philipp Müller <tim@centricular.com>
+2019-05-11 21:08:50 +0200  Michael Olbrich <m.olbrich@pengutronix.de>
 
-       * libs/gst/check/meson.build:
-         meson: fix warning about configure_file() install kwarg
-         The install kwarg on configure_file() was only added in
-         Meson 0.50 but we're targetting older versions as well,
-         which caused a warning. The install kwarg is not needed
-         here as we specify install_dir, so we can just drop it.
-         Fixes #379
+       * libs/gst/helpers/gst_gdb.py:
+         gdb: print more data for segment events
+         This add the different timestamps for segment events:
+         (gdb) gst-print pad
+         SrcPad(src, push) {
+         events:
+         [...]
+         segment: time
+         rate: 1.1
+         start:    0:03:08.449753330
+         time:     0:03:08.449753330
+         position: 0:03:08.449753330
+         duration: 0:12:14.166687500
+         [...]
+         }
 
-2019-08-14 09:51:55 +0300  Sebastian Dröge <sebastian@centricular.com>
+2019-05-11 21:02:37 +0200  Michael Olbrich <m.olbrich@pengutronix.de>
 
-       * libs/gst/base/gstaggregator.c:
-         aggregator: Actually handle NEED_DATA return from update_src_caps()
-         The documentation says that this allows the subclass to signal that it
-         needs more data before it can decide on caps, so let's actually
-         implement it that way.
+       * libs/gst/helpers/gst_gdb.py:
+         gdb: add 'gst-pipeline-tree' command
+         It shows a simple tree of all elements in pipeline.
+         As with gst-dot, the toplevel bin is found from any element of the
+         pipeline:
+         (gdb) gst-pipeline-tree bsink
+         playbin
+         inputselector1
+         inputselector0
+         uridecodebin0
+         queue2-0
+         decodebin0
+         avdec_aac0
+         aacparse0
+         vaapidecodebin0
+         vaapipostproc0
+         capsfilter1
+         vaapi-queue
+         vaapidecode0
+         capsfilter0
+         h264parse0
+         multiqueue0
+         matroskademux0
+         typefind
+         typefindelement0
+         source
+         playsink
+         abin
+         aconv
+         resample
+         conv
+         identity
+         aqueue
+         pulsesink0
+         vbin
+         vconv
+         scale
+         conv
+         identity
+         vqueue
+         vaapisink0
+         vdbin
+         deinterlace
+         vdconv
+         audiotee
+         streamsynchronizer0
+
+2019-05-11 20:59:04 +0200  Michael Olbrich <m.olbrich@pengutronix.de>
 
-2019-08-13 19:57:08 +0300  Sebastian Dröge <sebastian@centricular.com>
+       * libs/gst/helpers/gst_gdb.py:
+         gdb: add gst_pipeline() and gst_bin_get() functions
+         This simplifies navigating in a GStreamer pipeline, e.g.
+         (gdb) print $gst_bin_get($gst_pipeline(pad), "matroskademux0")
+         $1 = 0x7fffe81b4050 [GstMatroskaDemux|matroskademux0]
 
-       * libs/gst/base/gstaggregator.c:
-         aggregator: Assert if the sink/src pad type that is to be used is not a GstAggregatorPad or subclass thereof
+2019-05-11 20:55:36 +0200  Michael Olbrich <m.olbrich@pengutronix.de>
 
-2019-08-13 19:55:59 +0300  Sebastian Dröge <sebastian@centricular.com>
+       * libs/gst/helpers/gst_gdb.py:
+         gdb: handle ghost and proxy pads while looking for the top-level element
+         The parent object for pads is not always a GstElement. Handle GstProxyPad
+         parents as well.
 
-       * libs/gst/base/gstaggregator.c:
-         aggregator: Ensure that the source pad is created as a GstAggregatorPad if no type is given in the pad template
-         Otherwise we would create a GstPad and that causes invalid memory
-         accesses later.
+2019-05-11 20:53:54 +0200  Michael Olbrich <m.olbrich@pengutronix.de>
 
-2019-08-06 10:09:22 +0530  Guillaume Desmottes <guillaume.desmottes@collabora.com>
+       * libs/gst/helpers/gst_gdb.py:
+         gdb: refactor finding top-level pipeline
+         No functional changes. Just refactoring to make it possible to reuse this
+         later.
 
-       * plugins/tracers/gstlatency.c:
-         latency: fix custom event leaks
-         If the element before the sink needs $n buffers to produce one output
-         buffer, we were reffing $n events and unreffing only one.
-         Prevent this by using g_object_set_qdata_full() to handle the event
-         unreffing so we're sure no ref will be lost.
+2019-05-11 20:53:05 +0200  Michael Olbrich <m.olbrich@pengutronix.de>
 
-2019-08-02 13:07:58 +0530  Guillaume Desmottes <guillaume.desmottes@collabora.com>
+       * libs/gst/helpers/gst_gdb.py:
+         gdb: gst-print add more pad and element information
+         For elements, this adds all child elements, the state and base/start time:
+         (gdb) gst-print pipeline
+         0x5555556ebd20 "pipeline0"
+         GstPipeline(pipeline0) {
+         children:
+         fakesink0
+         queue0
+         videotestsrc0
+         state: PLAYING
+         base_time: +2:54:36.892581150
+         start_time: 0:00:00.000000000
+         }
+         For pads, this adds the peer pads and the current task state and the
+         offset (if not zero):
+         (gdb) gst-print pad
+         SrcGhostPad(src, push) {
+         events:
+         [...]
+         peer: vaapisink0:sink
+         inner peer: scale:src
+         }
+         (gdb) gst-print pad
+         SrcPad(src, push) {
+         events:
+         [...]
+         peer: queue0:sink
+         task: STARTED
+         offset: 30000000 [+0:00:00.030000000]
+         }
 
-       * plugins/tracers/gstlatency.c:
-       * plugins/tracers/gstrusage.c:
-       * plugins/tracers/gststats.c:
-         tracers: set MAY_BE_LEAKED on tracer records
-         The records are static and so appear as false positives when using those
-         tracers with the leaks tracer as well.
-         The leaks tracer was already setting this flag on its record so let's
-         set it on the other ones as well.
+2019-05-11 20:39:00 +0200  Michael Olbrich <m.olbrich@pengutronix.de>
 
-2019-06-20 16:42:01 +0530  Guillaume Desmottes <guillaume.desmottes@collabora.com>
+       * libs/gst/helpers/gst_gdb.py:
+         gdb: refactor time formating
+         Make it reuseable independent of the GstClockTimePrinter.
 
-       * plugins/tracers/gstlatency.c:
-         latency: display event pointer in logs
-         This is quite useful for debugging when tracer is reporting the wrong
-         latency because of an element breaking the events/buffers ordering.
+2019-05-22 10:44:50 +0300  Sebastian Dröge <sebastian@centricular.com>
 
-2019-07-22 15:06:20 +0000  Alicia Boya García <ntrrgc@gmail.com>
+       * tests/check/elements/dataurisrc.c:
+         dataurisrc: Add test that checks various URIs against their expected output
 
-       * plugins/elements/gstdownloadbuffer.c:
-         downloadbuffer: Check for flush after seek
-         In gst_download_buffer_wait_for_data(), when a seek is made with
-         perform_seek_to_offset() the `qlock` is released temporarily. Therefore,
-         the flushing condition can be set during this period and should be
-         checked.
-         This was not being checked before, causing occasional deadlocks when
-         GST_DOWNLOAD_BUFFER_WAIT_ADD_CHECK() was called.
-         GST_DOWNLOAD_BUFFER_WAIT_ADD_CHECK() assumes that the caller has already
-         checked that we're not flushing before, since this is done when
-         acquiring the lock; so if we release it temporarily somewhere, we need
-         to check for flush again.
-         Without that check, the function would keep waiting for the condition
-         variable to be notified before checking for flushing condition again,
-         and that may very well never happen. This was reproduced when during pad
-         deactivation when running WebKit in gdb.
+2019-05-21 17:22:04 +0200  Benjamin Otte <otte@redhat.com>
 
-2019-08-08 13:49:07 +0300  Sebastian Dröge <sebastian@centricular.com>
+       * plugins/elements/gstdataurisrc.c:
+         dataurisrc: Fix crash when semicolon is aprt of data
+         This URI is valid:
+         data:,;base64
+         (It encodes the literal string ";base64")
+         But would lead to a crash because the code assumed the semicolon would
+         be placed before the colon.
 
-       * configure.ac:
-       * gst/gstregistry.c:
-       * meson.build:
-         registry: Use plugin directory from the build system for relocateable Windows builds
-         Instead of guessing something based on preprocessor defines and magic.
+2019-05-21 17:15:52 +0200  Benjamin Otte <otte@redhat.com>
 
-2019-08-06 00:05:22 +0100  Tim-Philipp Müller <tim@centricular.com>
+       * plugins/elements/gstdataurisrc.c:
+         dataurisrc: Allow case-insensitive scheme
+         Quoting RFC 2396:
+         For resiliency, programs interpreting URI should treat upper case
+         letters as equivalent to lower case in scheme names (e.g., allow
+         "HTTP" as well as "http").
 
-       * gst/gstmessage.h:
-         message: fix up enum value for GST_MESSAGE_DEVICE_CHANGED
-         This was added in 1.16 and accidentally duplicated the value of
-         the existing GST_MESSAGE_REDIRECT.
-         As the only known user of this message is GStreamer core itself,
-         and it is quite an obscure message, it seems best to just fix up
-         the enum value even if that technically breaks API.
-         Fixes #418
+2019-05-16 16:17:35 +1000  Matthew Waters <matthew@centricular.com>
 
-2019-07-30 21:40:47 -0400  Doug Nazar <nazard@nazar.ca>
+       * docs/plugins/gst_plugins_cache.json:
+       * plugins/tracers/meson.build:
+         docs: add coretracers to the list of plugins
 
-       * gst/gstinfo.c:
-         info: Fix deadlock in gst_ring_buffer_logger_log
-         gst_ring_buffer_logger_log calls several functions while formatting
-         the message which may in turn log a message while we already hold
-         the mutex. Do all formatting first before acquiring the mutex to
-         avoid this and reduce the time we hold the mutex.
+2019-05-16 09:11:00 -0400  Thibault Saunier <tsaunier@igalia.com>
 
-2019-07-19 21:57:09 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
+       * docs/meson.build:
+         docs: Stop building the doc cache by default
+         Fixes https://gitlab.freedesktop.org/gstreamer/gst-docs/issues/36
 
-       * plugins/elements/gstidentity.c:
-         identity: Non-live upstream have no max latency
-         sync=TRUE implementation changes the latency query of a non-live
-         upstream into live, though it wrongly set the upstream max latency to 0.
-         As non-live sources won't loose data if we wait longer, this should have
-         been reported as have no max latency limite (-1).
+2019-05-15 22:46:45 -0400  Thibault Saunier <tsaunier@igalia.com>
 
-2019-07-11 17:53:53 +0100  Philippe Normand <philn@igalia.com>
+       * docs/gst-hotdoc-plugins-scanner.c:
+       * docs/plugins/gst_plugins_cache.json:
+         docs: Update diplayed plugins filename something stable
 
-       * plugins/elements/gstidentity.c:
-         identity: Fix the ts-offset property getter
-         Previous code was a copy/paste from the property setter function.
+2019-05-15 21:15:35 -0400  Thibault Saunier <tsaunier@igalia.com>
 
-2019-07-08 19:09:03 +0300  Sebastian Dröge <sebastian@centricular.com>
+       * docs/gst-hotdoc-plugins-scanner.c:
+         hotdoc: Let the the registry inspect in forks
+         So that the whole process doesn't segfault if something bad happens while inspecting
 
-       * libs/gst/base/gstaggregator.c:
-         aggregator: Make parsing of explicit sink pad names more robust
-         When passing "sink_%d" twice to aggregator before it would create two
-         pads called "sink_0", because it failed to parse "%d" as integer and
-         used 0 instead then.
-         Instead validate that parsing was actually successful and also don't
-         even try to parse if the requested pad name contains a '%'.
+2019-05-15 09:23:06 -0400  Thibault Saunier <tsaunier@igalia.com>
 
-2019-06-29 09:22:05 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
+       * docs/gst-plugins-doc-cache-generator.py:
+       * docs/meson.build:
+         docs: Use the MESON_BUILD_ROOT env variable in the plugins cache generator
 
-       * gst/gstbufferpool.c:
-       * tests/check/gst/gstbufferpool.c:
-         bufferpool: Fix the buffer size reset code
-         The offset in gst_buffer_resize() is additive. So to move back the
-         offset to zero, we need to pass the opposite of the current offset. This
-         was raised through the related unit test failingon 32bit as on 64bit
-         the alignment padding was enough to hide the issue. The test was
-         modified to also fail on 64bit. This patch will remove spurious
-         assertions like:
-         assertion 'bufmax >= bufoffs + offset + size' failed
-         Fixes #316
+2019-05-14 15:27:05 -0400  Thibault Saunier <tsaunier@igalia.com>
 
-2019-06-20 13:49:14 +0530  Guillaume Desmottes <guillaume.desmottes@collabora.com>
+       * docs/gst-hotdoc-plugins-scanner.c:
+       * docs/gst-plugins-doc-cache-generator.py:
+         docs: Do not pass the json through stdout
+         Unicode encoding breaks on windows when doing so
 
-       * plugins/elements/gstelements_private.c:
-         gstelements_private: sync gst_buffer_get_flags_string() with new flags
+2019-05-14 13:44:43 -0400  Thibault Saunier <tsaunier@igalia.com>
 
-2019-06-19 23:29:24 -0400  Thibault Saunier <tsaunier@igalia.com>
+       * gst/gstregistry.c:
+         registry: Avoid discovering plugins in hotdoc private directories
 
-       * plugins/elements/gstmultiqueue.c:
-         multiqueue: never unref queries we do not own
-         The `query` argument of gst_pad_query is "transfer none".
-         Query objects are "borrowed" by the pad query handlers and those
-         should never unref them.
-         This was leading to double freed queries in a very racy way with nested
-         GESTimelines.
+2019-05-14 13:44:24 -0400  Thibault Saunier <tsaunier@igalia.com>
 
-2019-06-04 17:55:30 +0300  Sebastian Dröge <sebastian@centricular.com>
+       * docs/meson.build:
+         docs: Do not inspect internal files
 
-       * plugins/elements/gstconcat.c:
-         concat: Reset last_stop on FLUSH_STOP too
-         Otherwise when seeking backwards we would keep the last_stop at the last
-         position we saw until playback passed the seek position again, and if
-         switching to the next pad happens in the meantime we would set the wrong
-         offset in the outgoing segment.
+2019-05-14 20:27:47 +0900  Seungha Yang <seungha.yang@navercorp.com>
 
-2019-06-04 17:56:30 +0300  Sebastian Dröge <sebastian@centricular.com>
+       * docs/gst-plugins-doc-cache-generator.py:
+         docs: Always follow Unix style newline
+         The 'open()' follows default behavior of OS (CRLF in case of Windows).
+         So it results in a bunch of git diff on Windows.
 
-       * plugins/elements/gstconcat.c:
-         concat: Improve debug output a bit
+2019-05-16 15:15:27 +0300  Sebastian Dröge <sebastian@centricular.com>
 
-2015-07-29 11:48:33 +0100  Tim-Philipp Müller <tim@centricular.com>
+       * libs/gst/base/gstbasesink.c:
+         basesink: Remove leading space from Since maker of gst_base_sink_get_stats()
+         gobject-introspection does not like this.
 
-       * libs/gst/base/gstaggregator.c:
-         aggregator: fix flow-return boolean return type mismatch
-         Not that it matters, since we don't check the return value
-         anyway. Unclear why the aggregator pad flush function should
-         have a return value at all really, and perhaps it should be
-         called reset anyway. Spotted by dv on irc.
+2019-05-16 15:13:23 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstbasesink.c:
+         basesink: Fix syntax for gtk-doc comment of the new stats property
 
 2019-05-13 16:42:04 +0200  Edward Hervey <bilboed@bilboed.com>
 
          But with GST_PAD_PROBE_HANDLED it is totally fine to reset that, since
          the probe has "handled" it.
 
-2019-05-13 13:24:42 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+2019-05-06 22:17:50 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * plugins/elements/gstelements_private.c:
+       * plugins/elements/gstelements_private.h:
+       * plugins/elements/gstfdsink.c:
+       * plugins/elements/gstfilesink.c:
+       * plugins/elements/gstfilesink.h:
+         filesink: Implement workaround for some (network) filesystems that spuriously return EACCES on write
+         This seems to happen when another client is accessing the file at the
+         same time, and retrying after a short amount of time solves it.
+         Sometimes partial data is written at that point already but we have no
+         idea how much it is, or if what was written is correct (it sometimes
+         isn't) so we always first seek back to the current position and repeat
+         the whole failed write.
+         It happens at least on Linux and macOS on SMB/CIFS and NFS file systems.
+         Between write attempts that failed with EACCES we wait 10ms, and after
+         enough consecutive tries that failed with EACCES we simply time out.
+         In theory a valid EACCES for files to which we simply have no access
+         should've happened already during the call to open(), except for NFS
+         (see open(2)).
+         This can be enabled with the new max-transient-error-timeout property, and
+         a new o-sync boolean property was added to open the file in O_SYNC mode
+         as without that it's not guaranteed that we get EACCES for the actual
+         writev() call that failed but might only get it at a later time.
+         Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/305
+
+2019-05-14 15:44:07 -0400  Aaron Boxer <aaron.boxer@collabora.com>
+
+       * pkgconfig/gstreamer.pc.in:
+         gstreamer.pc.in: exec_prefix must be defined before libexecdir
+
+2019-05-13 22:47:38 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * docs/plugins/gst_plugins_cache.json:
+         docs: Update plugins cache
+
+2019-05-13 22:47:05 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * docs/gst-plugins-doc-cache-generator.py:
+         docs: Fix cache invalidation status
+         The dictionnary is updated in place so we were checking the same twice
+
+2018-11-11 20:11:47 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+       * docs/gst-plugins-doc-cache-generator.py:
+       * docs/meson.build:
+         docs: Use the new GstPluginsPath.json to have the right plugin path
+         When inspecting plugins to generate the json cache file. Otherwise
+         when we are not in the uninstalled env and using `gst-build` plugins
+         with dependency might fail/throw warning, etc..
+
+2018-10-28 12:05:41 +0000  Thibault Saunier <tsaunier@igalia.com>
+
+       * pkgconfig/gstreamer.pc.in:
+       * pkgconfig/meson.build:
+         pkgconfig: Add information about libexecdir
+         https://bugzilla.gnome.org/show_bug.cgi?id=797349
+
+2018-09-13 16:14:22 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+       * docs/README:
+         doc: Update the README
 
+2018-08-19 19:41:41 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+       * docs/plugins/gst_plugins_cache.json:
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstbufferlist.h:
+       * gst/gstcaps.h:
+       * gst/gstcontrolbinding.h:
+       * gst/gstelement.h:
+       * gst/gsterror.c:
+       * gst/gsterror.h:
+       * gst/gstevent.h:
+       * gst/gstinfo.c:
+       * gst/gstinfo.h:
+       * gst/gstmemory.h:
+       * gst/gstmessage.h:
+       * gst/gstminiobject.c:
+       * gst/gstpad.c:
+       * gst/gstpadtemplate.h:
+       * gst/gstpromise.c:
+       * gst/gstprotection.h:
+       * gst/gstquery.h:
+       * gst/gstsample.h:
+       * gst/gststructure.c:
+       * gst/gsttaglist.h:
+       * gst/gsttypefind.h:
+       * gst/gsturi.c:
+       * gst/gsturi.h:
+       * gst/gstvalue.h:
        * gst/meson.build:
-         meson: Link to objects instea of static helper library
-         Otherwise the objects from that static helper library are not included
-         in the gstreamer-1.0 static library. This was supposed to be fixed in
-         Meson, but the pull request hasn't been merged yet:
-         https://github.com/mesonbuild/meson/pull/3939
-         Closes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/398
+       * libs/gst/base/gstadapter.c:
+       * libs/gst/base/gstaggregator.c:
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasesrc.h:
+       * libs/gst/base/gstcollectpads.c:
+       * libs/gst/controller/gstproxycontrolbinding.c:
+       * libs/gst/net/gstnetclientclock.c:
+         doc: Fix hotdoc warnings
+         * Making sure that `static inline` function are in the GIR (by first
+         defining them, and make sure to mark as skiped)
+         * Do not try to link to unexisting symbols
+         * Also generate GIR information about gst_tracers
+
+2018-10-22 03:14:11 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+       * docs/gst-hotdoc-plugins-scanner.c:
+       * docs/gst-plugins-doc-cache-generator.py:
+       * docs/gst/building.md:
+       * docs/gst/gi-index.md:
+       * docs/gst/index.md:
+       * docs/gst/overview.md:
+       * docs/gst/running.md:
+       * docs/gst/sitemap.txt:
+       * docs/images/gdp-header.png:
+       * docs/images/gdp-header.svg:
+       * docs/images/gst-universe.svg:
+       * docs/index.md:
+       * docs/libs/base/index.md:
+       * docs/libs/base/sitemap.txt:
+       * docs/libs/check/index.md:
+       * docs/libs/check/sitemap.txt:
+       * docs/libs/controller/index.md:
+       * docs/libs/controller/sitemap.txt:
+       * docs/libs/index.md:
+       * docs/libs/net/index.md:
+       * docs/libs/net/sitemap.txt:
+       * docs/meson.build:
+       * docs/plugins/Makefile.am:
+       * docs/plugins/gst_plugins_cache.json:
+       * docs/plugins/gstreamer-plugins-docs.sgml:
+       * docs/plugins/gstreamer-plugins-sections.txt:
+       * docs/plugins/gstreamer-plugins.args:
+       * docs/plugins/gstreamer-plugins.hierarchy:
+       * docs/plugins/gstreamer-plugins.interfaces:
+       * docs/plugins/gstreamer-plugins.prerequisites:
+       * docs/plugins/gstreamer-plugins.signals:
+       * docs/plugins/gstreamer-plugins.types:
+       * docs/plugins/index.md:
+       * docs/plugins/inspect/plugin-coreelements.xml:
+       * docs/plugins/inspect/plugin-coretracers.xml:
+       * docs/plugins/sitemap.txt:
+       * docs/version.in:
+       * gst/gstelement.c:
+       * gst/gsterror.c:
+       * gst/gstmessage.c:
+       * gst/gstpoll.c:
+       * gst/meson.build:
+       * libs/gst/base/gstbitreader.c:
+       * libs/gst/base/gstbytereader.c:
+       * libs/gst/base/gstbytewriter.c:
+       * libs/gst/base/meson.build:
+       * libs/gst/check/meson.build:
+       * meson.build:
+       * meson_options.txt:
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gstelements.c:
+       * plugins/elements/meson.build:
+       * plugins/meson.build:
+       * tools/tools.h:
+         Port to hotdoc
+
+2018-09-14 09:24:26 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+       * Makefile.am:
+       * configure.ac:
+       * docs/Makefile.am:
+       * docs/gst/.gitignore:
+       * docs/gst/Makefile.am:
+       * docs/gst/building.xml:
+       * docs/gst/gst-universe.dot:
+       * docs/gst/gstreamer-docs.sgml:
+       * docs/gst/gstreamer-overrides.txt:
+       * docs/gst/gstreamer-sections.txt:
+       * docs/gst/gstreamer.types.in:
+       * docs/gst/meson.build:
+       * docs/gst/running.xml:
+       * docs/libs/.gitignore:
+       * docs/libs/Makefile.am:
+       * docs/libs/gdp-header.png:
+       * docs/libs/gstreamer-libs-docs.sgml:
+       * docs/libs/gstreamer-libs-overrides.txt:
+       * docs/libs/gstreamer-libs-sections.txt:
+       * docs/libs/gstreamer-libs.types:
+       * docs/libs/meson.build:
+       * docs/list-ulink.xsl:
+       * docs/meson.build:
+       * docs/version.entities.in:
+       * meson.build:
+         doc: Remove gtk-doc support
+
+2018-08-11 10:12:27 -0400  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gstobject.c:
+       * gst/gstparamspecs.h:
+         gst: Add a GParamSpecFlag to force gst-inspect to use pspec default value
+         Instead of the object value, this should be used every time a random
+         value will be returned by g_object_get This is also useful to make the
+         values returned by inspecting element stable accross runs.
+
+2018-10-22 11:44:04 +0200  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gstcapsfeatures.c:
+       * gst/gstelement.h:
+       * libs/gst/controller/gsttimedvaluecontrolsource.c:
+         doc: Add some missing docstrings
+
+2018-10-22 11:32:45 +0200  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gstdynamictypefactory.c:
+       * gst/gstelement.c:
+       * gst/gstelementfactory.h:
+       * gst/gsttracer.h:
+       * gst/gsttracerrecord.h:
+       * gst/gstutils.c:
+       * libs/gst/check/gstcheck.c:
+       * libs/gst/check/gstcheck.h:
+       * plugins/elements/gstqueue.c:
+         doc: Fix and add some missing docstrings
+
+2018-10-22 11:32:40 +0200  Thibault Saunier <tsaunier@igalia.com>
+
+       * gst/gststructure.c:
+         structure: Mark _from_string as constructor
 
 2019-05-13 14:42:28 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
 
          to pass it everywhere.
          Closes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/398
 
+2019-05-13 13:24:42 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+       * gst/meson.build:
+         meson: Link to objects instea of static helper library
+         Otherwise the objects from that static helper library are not included
+         in the gstreamer-1.0 static library. This was supposed to be fixed in
+         Meson, but the pull request hasn't been merged yet:
+         https://github.com/mesonbuild/meson/pull/3939
+         Closes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/398
+
 2019-05-11 18:21:19 +0200  Michael Olbrich <m.olbrich@pengutronix.de>
 
        * libs/gst/helpers/meson.build:
          to gstreamer-1.0 for autotools. The meson file was forgotten.
          Fix the path to match the one used in libgstreamer-gdb.py.in.
 
+2019-05-10 14:51:15 +0200  Niels De Graef <niels.degraef@barco.com>
+
+       * gst/gsturi.h:
+         uri: Add gst_clear_uri()
+         Basically, you can use this instead of using `gst_uri_unref()` (which
+         needs to be preceded by a NULL-check).
+         See https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/275
+         and https://gitlab.freedesktop.org/gstreamer/gstreamer/merge_requests/3
+
+2019-05-09 08:59:59 +0200  Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
+
+       * libs/gst/base/gstbasesink.c:
+         gstbasesink: Fix gir annotation
+
+2019-01-26 10:40:19 -0500  Aaron Boxer <aaron.boxer@collabora.com>
+
+       * docs/libs/gstreamer-libs-sections.txt:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesink.h:
+         gstbasesink: add stats getter method
+         fixes #355
+
 2019-05-08 12:11:50 +0200  Niels De Graef <niels.degraef@barco.com>
 
        * gst/gstpromise.h:
          Like all other scripts in the same dir.
          It has a hashbang, so it should be executable.
 
+2019-04-25 10:41:54 +0530  Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+       * tools/gst-stats.c:
+         gst-stats: format latency as GST_TIME
+         Latency is easier to read when formatted as time rather than displayed
+         as a flat number in ns.
+         Especially when displaying GST_CLOCK_TIME_NONE which is now formated as
+         99:99:99.999999999 instead of 18446744073709551615.
+
 2019-04-24 18:22:06 +0200  Andoni Morales Alastruey <ylatuya@gmail.com>
 
        * tools/gst-inspect.c:
          gst-inspect: fix unused-const-variable error in windows
          ../tools/gst-inspect.c:44:20: error: 'DEFAULT_PAGER' defined but not used [-Werror=unused-const-variable=]
 
-2019-04-23 17:33:34 +0300  Sebastian Dröge <sebastian@centricular.com>
+2018-11-12 19:59:41 +0100  Mathieu Duponchelle <mathieu@centricular.com>
 
-       * libs/gst/base/base.h:
-         base: Include gstbitwriter.h in the single-include header
+       * gst/gstsegment.c:
+       * gst/gstsegment.h:
+         gstsegment: Add GST_SEEK_FLAG_TRICKMODE_FORWARD_PREDICTED
+         This is generally useful, and mandated by the ONVIF streaming
+         spec, section 6.5.3
+         <https://www.onvif.org/specs/stream/ONVIF-Streaming-Spec.pdf>
+
+2019-04-20 22:26:52 +0200  Rasmus Thomsen <oss@cogitri.dev>
+
+       * libs/gst/helpers/meson.build:
+         meson: check for libcap via pkg-config
+         It's possible that setcap is installed, but the libcap headers/libs aren't (e.g.
+         during cross compilation, when you have the program installed for the host,
+         but need the headers of the target). Also removes the need to manually check
+         for the libcap headers.
 
 2019-04-23 18:00:59 +0300  Sebastian Dröge <sebastian@centricular.com>
 
          bitwriter->data = g_realloc (bitwriter->data, (new_bit_size >> 3));
          ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-2019-04-23 12:31:07 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-       * libs/gst/base/gstbitwriter.h:
-         bitwriter: Mark the whole type as Since: 1.16
-
-2019-04-23 14:39:48 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-       * gst/gstcaps.c:
-         caps: Add Since: 1.16 marker to gst_caps_copy()
-
-2019-04-23 14:54:03 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-       * libs/gst/base/gstaggregator.h:
-         aggregator: Mark all public structs as Since: 1.14
-
-2019-04-23 15:07:08 +0300  Sebastian Dröge <sebastian@centricular.com>
+2019-04-23 17:33:34 +0300  Sebastian Dröge <sebastian@centricular.com>
 
-       * libs/gst/base/gstbaseparse.h:
-       * libs/gst/base/gstbasetransform.h:
-       * libs/gst/base/gstcollectpads.h:
-       * libs/gst/controller/gstinterpolationcontrolsource.h:
-         libs: Fix various Since markers
+       * libs/gst/base/base.h:
+         base: Include gstbitwriter.h in the single-include header
 
 2019-04-23 15:08:18 +0300  Sebastian Dröge <sebastian@centricular.com>
 
        * gst/gstsystemclock.h:
          gst: Fix various Since markers
 
-2019-05-02 12:35:17 +0100  Tim-Philipp Müller <tim@centricular.com>
+2019-04-23 15:07:08 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstbaseparse.h:
+       * libs/gst/base/gstbasetransform.h:
+       * libs/gst/base/gstcollectpads.h:
+       * libs/gst/controller/gstinterpolationcontrolsource.h:
+         libs: Fix various Since markers
 
-       * .gitlab-ci.yml:
-         ci: use template from 1.16 branch
+2019-04-23 14:54:03 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstaggregator.h:
+         aggregator: Mark all public structs as Since: 1.14
+
+2019-04-23 14:39:48 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * gst/gstcaps.c:
+         caps: Add Since: 1.16 marker to gst_caps_copy()
+
+2019-04-23 12:31:07 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+       * libs/gst/base/gstbitwriter.h:
+         bitwriter: Mark the whole type as Since: 1.16
+
+2018-11-13 13:41:53 +0100  Robert Rosengren <robertr@axis.com>
+
+       * docs/libs/gstreamer-libs-docs.sgml:
+       * docs/libs/gstreamer-libs-sections.txt:
+       * libs/gst/net/Makefile.am:
+       * libs/gst/net/gstnetclientclock.c:
+       * libs/gst/net/gstnettimeprovider.c:
+       * libs/gst/net/gstnetutils.c:
+       * libs/gst/net/gstnetutils.h:
+       * libs/gst/net/meson.build:
+       * libs/gst/net/net.h:
+         netutils: make gst_net_utils_set_socket_dscp external
+         Internal gst_net_utils_set_socket_dscp renamed and turned into external
+         function. Similar functionality exists in e.g. multidupsink, which could
+         instead use this one.
+
+2018-11-13 13:39:43 +0100  Robert Rosengren <robertr@axis.com>
+
+       * libs/gst/net/gstnetutils.c:
+         netutils: Add IPv6 support to QoS DSCP
+         Added IPv6 support as already implemented in multiudpsink
+         (gst-plugins-good).
+
+2019-04-19 12:31:22 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * docs/gst/gstreamer-docs.sgml:
+       * docs/libs/gstreamer-libs-docs.sgml:
+         docs: add index for new symbols in 1.16
+
+2019-04-19 10:20:02 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+       * README:
+       * RELEASE:
+       * configure.ac:
+       * docs/plugins/inspect/plugin-coreelements.xml:
+       * docs/plugins/inspect/plugin-coretracers.xml:
+       * meson.build:
+         Back to development
 
 === release 1.16.0 ===
 
          * gst/parse/types.h:
          config.h already included before
          * tools/gst-inspect.c: (main):
-         sys/wait.h also doesn´t exist on mingw, so change the ifdef check
+         sys/wait.h also doesnt exist on mingw, so change the ifdef check
          check for ENABLE_NLS, not GETTEXT_PACKAGE
          * tools/gst-launch.c: (main):
          check for ENABLE_NLS, not GETTEXT_PACKAGE
diff --git a/Makefile.am b/Makefile.am
deleted file mode 100644 (file)
index d9b3aca..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc
-
-# note: keep in sync with configure.ac
-ACLOCAL_AMFLAGS = -I m4 -I common/m4
-
-aclocaldir = $(datadir)/aclocal
-aclocal_DATA = gst-element-check-1.0.m4
-
-SUBDIRS = pkgconfig \
-       gst libs plugins tests \
-       docs \
-       po \
-       m4 \
-       common \
-       data
-
-if BUILD_TOOLS
-SUBDIRS += tools
-endif
-
-# These are all the possible subdirs
-DIST_SUBDIRS = pkgconfig \
-       gst libs plugins tools tests \
-       docs \
-       po \
-       m4 \
-       common \
-       data
-
-EXTRA_DIST = \
-       gst-element-check-1.0.m4 \
-       configure.ac autogen.sh depcomp \
-       MAINTAINERS ABOUT-NLS RELEASE gstreamer.doap \
-       scripts/gst-uninstalled \
-       $(shell find "$(top_srcdir)" -type f -name meson.build ! -path "$(top_srcdir)/gstreamer-*" ) \
-       meson_options.txt \
-       gst/parse/gen_lex.py.in gst/parse/gen_grammar.py.in
-
-DISTCLEANFILES = _stdint.h
-
-include $(top_srcdir)/common/release.mak
-include $(top_srcdir)/common/po.mak
-
-if GST_GCOV_ENABLED
-clean-gcov:
-       find -name "*.da" -o -name "*.gcov" | xargs rm || true
-
-clean-bbg:
-       find -name "*.bbg" -o -name "*.bb" | xargs rm || true
-
-GCOV_DIRS=gst libs
-
-## .PHONY so it always rebuilds it
-.PHONY: coverage-report.txt
-
-coverage-report.txt:
-       BBG_FILES=`find $(GCOV_DIRS) -name "*.bbg"` ;                     \
-       C_FILES= ;                                                        \
-       for F in $$BBG_FILES ; do                                         \
-               F_nolibs=`echo $$F | sed -e 's/.libs\///g'` ;             \
-               C=`echo $$F_nolibs | sed -e 's/.bbg/.c/g'` ;              \
-               B=`basename $$F .bbg` ;                                   \
-               D=`dirname $$F` ;                                         \
-               DA=`echo $$F | sed -e 's/.bbg/.da/g'` ;                   \
-               DA_libs=`echo $$D/.libs/$$B/.da` ;                        \
-               if test -e $$DA || test -e $$DA_libs; then                \
-                       C_FILES="$$C_FILES $$C" ;                         \
-               fi ;                                                      \
-       done ;                                                            \
-       echo $$C_FILES ;                                                  \
-       $(top_builddir)/testsuite/decode-gcov --report $$C_FILES > coverage-report.txt
-
-check-coverage: clean-gcov all check coverage-report.txt
-       cat coverage-report.txt
-
-else
-coverage-report.txt:
-       echo "Need to reconfigure with --enable-gcov"
-
-check-coverage:
-       echo "Need to reconfigure with --enable-gcov"
-endif
-
-if HAVE_CHECK
-check-valgrind:
-       $(MAKE) -C tests/check check-valgrind
-
-check-torture:
-       $(MAKE) -C tests/check torture
-
-build-checks:
-       $(MAKE) -C tests/check build-checks
-else
-check-valgrind:
-       echo "'check' library not installed, skipping"
-
-check-torture:
-       echo "'check' library not installed, skipping"
-
-build-checks:
-       echo "'check' library not installed, skipping"
-endif
-
-check-enum-gettypes: $(top_builddir)/gst/gstenumtypes.h
-       @echo 'Checking if all enum and flag _get_type() funcs are inited in gst_init()';                        \
-       FUNCS=`grep '_get_type (' gst/gstenumtypes.h | sed -e 's/^.*gst_/gst_/' -e 's/_get_type.*$$/_get_type/'`;\
-       MISSING_FUNCS='';                                                                                        \
-       for f in $$FUNCS; do                                                                                     \
-         INIT_LINE=`grep $$f $(top_srcdir)/gst/*.c | grep g_type_class_ref`;                                    \
-         if test "x$$INIT_LINE" = "x"; then                                                                     \
-           MISSING_FUNCS="$$MISSING_FUNCS $$f";                                                                 \
-         fi;                                                                                                    \
-       done;                                                                                                    \
-       if test "x$$MISSING_FUNCS" != "x"; then                                                                  \
-         echo "FIXME: please add to the following to gst/gst.c init_post():";                                   \
-         for f in $$MISSING_FUNCS; do                                                                           \
-           echo "  g_type_class_ref ($$f ());";                                                                 \
-         done;                                                                                                  \
-         exit 1;                                                                                                \
-       fi;                                                                                                      \
-       echo 'Checking if all enum and flag _get_type() funcs are deinited in gst_deinit()';                     \
-       MISSING_FUNCS='';                                                                                        \
-       for f in $$FUNCS; do                                                                                     \
-         INIT_LINE=`grep $$f $(top_srcdir)/gst/*.c | grep g_type_class_unref`;                                  \
-         if test "x$$INIT_LINE" = "x"; then                                                                     \
-           MISSING_FUNCS="$$MISSING_FUNCS $$f";                                                                 \
-         fi;                                                                                                    \
-       done;                                                                                                    \
-       if test "x$$MISSING_FUNCS" != "x"; then                                                                  \
-         echo "FIXME: please add to the following to gst/gst.c gst_deinit():";                                  \
-         for f in $$MISSING_FUNCS; do                                                                           \
-           echo "  g_type_class_unref (g_type_class_peek ($$f ()));";                                           \
-         done;                                                                                                  \
-         exit 1;                                                                                                \
-       fi
-
-include $(top_srcdir)/common/coverage/lcov.mak
-
-check: check-enum-gettypes
-
-# cruft: plugins that have been merged or moved or renamed
-
-CRUFT_FILES = \
-       $(top_builddir)/win32/common/config.h-new \
-       $(top_builddir)/common/shave \
-       $(top_builddir)/common/shave-libtool \
-       $(top_builddir)/common/m4/codeset.m4 \
-       $(top_builddir)/common/m4/gettext.m4 \
-       $(top_builddir)/common/m4/glibc2.m4 \
-       $(top_builddir)/common/m4/glibc21.m4 \
-       $(top_builddir)/common/m4/iconv.m4 \
-       $(top_builddir)/common/m4/intdiv0.m4 \
-       $(top_builddir)/common/m4/intl.m4 \
-       $(top_builddir)/common/m4/intldir.m4 \
-       $(top_builddir)/common/m4/intlmacosx.m4 \
-       $(top_builddir)/common/m4/intmax.m4 \
-       $(top_builddir)/common/m4/inttypes-pri.m4 \
-       $(top_builddir)/common/m4/inttypes_h.m4 \
-       $(top_builddir)/common/m4/lcmessage.m4 \
-       $(top_builddir)/common/m4/lib-ld.m4 \
-       $(top_builddir)/common/m4/lib-link.m4 \
-       $(top_builddir)/common/m4/lib-prefix.m4 \
-       $(top_builddir)/common/m4/libtool.m4 \
-       $(top_builddir)/common/m4/lock.m4 \
-       $(top_builddir)/common/m4/longlong.m4 \
-       $(top_builddir)/common/m4/ltoptions.m4 \
-       $(top_builddir)/common/m4/ltsugar.m4 \
-       $(top_builddir)/common/m4/ltversion.m4 \
-       $(top_builddir)/common/m4/lt~obsolete.m4 \
-       $(top_builddir)/common/m4/nls.m4 \
-       $(top_builddir)/common/m4/po.m4 \
-       $(top_builddir)/common/m4/printf-posix.m4 \
-       $(top_builddir)/common/m4/progtest.m4 \
-       $(top_builddir)/common/m4/size_max.m4 \
-       $(top_builddir)/common/m4/stdint_h.m4 \
-       $(top_builddir)/common/m4/uintmax_t.m4 \
-       $(top_builddir)/common/m4/visibility.m4 \
-       $(top_builddir)/common/m4/wchar_t.m4 \
-       $(top_builddir)/common/m4/wint_t.m4 \
-       $(top_builddir)/common/m4/xsize.m4
-
-CRUFT_DIRS = \
-       $(top_builddir)/tests/examples/xml \
-       $(top_builddir)/tests/examples/launch \
-       $(top_builddir)/tests/examples/metadata \
-       $(top_builddir)/tests/examples/queue \
-       $(top_builddir)/tests/examples/typefind \
-       $(top_builddir)/gst/tmp-introspect* \
-       $(top_builddir)/libs/gst/*/tmp-introspect* \
-       $(top_srcdir)/docs/plugins/tmpl
-
-include $(top_srcdir)/common/cruft.mak
-
-all-local: check-cruft
diff --git a/NEWS b/NEWS
index 98dc512..0e581c3 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,18 +1,23 @@
+GStreamer 1.20 Release Notes
 
+GStreamer 1.20 has not been released yet. It is scheduled for release
+around October/November 2021.
 
-GSTREAMER 1.16 RELEASE NOTES
+1.19.x is the unstable development version that is being developed in
+the git main branch and which will eventually result in 1.20, and 1.19.2
+is the current development release in that series
 
+It is expected that feature freeze will be in early October 2021,
+followed by one or two 1.19.9x pre-releases and the new 1.20 stable
+release around October/November 2021.
 
-GStreamer 1.16.0 was originally released on 19 April 2019.
+1.20 will be backwards-compatible to the stable 1.18, 1.16, 1.14, 1.12,
+1.10, 1.8, 1.6,, 1.4, 1.2 and 1.0 release series.
 
-The latest bug-fix release in the 1.16 series is 1.16.2 and was released
-on 3 December 2019.
-
-See https://gstreamer.freedesktop.org/releases/1.16/ for the latest
+See https://gstreamer.freedesktop.org/releases/1.20/ for the latest
 version of this document.
 
-_Last updated: Tuesday 03 December 2019, 08:00 UTC (log)_
-
+Last updated: Wednesday 22 September 2021, 18:00 UTC (log)
 
 Introduction
 
@@ -23,1149 +28,169 @@ framework!
 As always, this release is again packed with many new features, bug
 fixes and other improvements.
 
-
 Highlights
 
--   GStreamer WebRTC stack gained support for data channels for
-    peer-to-peer communication based on SCTP, BUNDLE support, as well as
-    support for multiple TURN servers.
-
--   AV1 video codec support for Matroska and QuickTime/MP4 containers
-    and more configuration options and supported input formats for the
-    AOMedia AV1 encoder
-
--   Support for Closed Captions and other Ancillary Data in video
-
--   Support for planar (non-interleaved) raw audio
-
--   GstVideoAggregator, compositor and OpenGL mixer elements are now in
-    -base
-
--   New alternate fields interlace mode where each buffer carries a
-    single field
-
--   WebM and Matroska ContentEncryption support in the Matroska demuxer
-
--   new WebKit WPE-based web browser source element
-
--   Video4Linux: HEVC encoding and decoding, JPEG encoding, and improved
-    dmabuf import/export
-
--   Hardware-accelerated Nvidia video decoder gained support for VP8/VP9
-    decoding, whilst the encoder gained support for H.265/HEVC encoding.
-
--   Many improvements to the Intel Media SDK based hardware-accelerated
-    video decoder and encoder plugin (msdk): dmabuf import/export for
-    zero-copy integration with other components; VP9 decoding; 10-bit
-    HEVC encoding; video post-processing (vpp) support including
-    deinterlacing; and the video decoder now handles dynamic resolution
-    changes.
-
--   The ASS/SSA subtitle overlay renderer can now handle multiple
-    subtitles that overlap in time and will show them on screen
-    simultaneously
-
--   The Meson build is now feature-complete (*) and it is now the
-    recommended build system on all platforms. The Autotools build is
-    scheduled to be removed in the next cycle.
-
--   The GStreamer Rust bindings and Rust plugins module are now
-    officially part of upstream GStreamer.
-
--   The GStreamer Editing Services gained a gesdemux element that allows
-    directly playing back serialized edit list with playbin or
-    (uri)decodebin
-
--   Many performance improvements
-
+-   this section will be completed in due course
 
 Major new features and changes
 
-Noteworthy new API
-
--   GstAggregator has a new "min-upstream-latency" property that forces
-    a minimum aggregate latency for the input branches of an aggregator.
-    This is useful for dynamic pipelines where branches with a higher
-    latency might be added later after the pipeline is already up and
-    running and where a change in the latency would be disruptive. This
-    only applies to the case where at least one of the input branches is
-    live though, it won’t force the aggregator into live mode in the
-    absence of any live inputs.
-
--   GstBaseSink gained a "processing-deadline" property and
-    setter/getter API to configure a processing deadline for live
-    pipelines. The processing deadline is the acceptable amount of time
-    to process the media in a live pipeline before it reaches the sink.
-    This is on top of the systemic latency that is normally reported by
-    the latency query. This defaults to 20ms and should make pipelines
-    such as v4l2src ! xvimagesink not claim that all frames are late in
-    the QoS events. Ideally, this should replace the "max-lateness"
-    property for most applications.
-
--   RTCP Extended Reports (XR) parsing according to RFC 3611:
-    Loss/Duplicate RLE, Packet Receipt Times, Receiver Reference Time,
-    Delay since the last Receiver (DLRR), Statistics Summary, and VoIP
-    Metrics reports. This only provides the ability to parse such
-    packets, generation of XR packets is not supported yet and XR
-    packets are not automatically parsed by rtpbin / rtpsession but must
-    be actively handled by the application.
-
--   a new mode for interlaced video was added where each buffer carries
-    a single field of interlaced video, with buffer flags indicating
-    whether the field is the top field or bottom field. Top and bottom
-    fields are expected to alternate in this mode. Caps for this
-    interlace mode must also carry a format:Interlaced caps feature to
-    ensure backwards compatibility.
-
--   The video library has gained support for three new raw pixel
-    formats:
-
-    -   Y410: packed 4:4:4 YUV, 10 bits per channel
-    -   Y210: packed 4:2:2 YUV, 10 bits per channel
-    -   NV12_10LE40: fully-packed 10-bit variant of NV12_10LE32,
-        i.e. without the padding bits
-
--   GstRTPSourceMeta is a new meta that can be used to transport
-    information about the origin of depayloaded or decoded RTP buffers,
-    e.g. when mixing audio from multiple sources into a single stream. A
-    new "source-info" property on the RTP depayloader base class
-    determines whether depayloaders should put this meta on outgoing
-    buffers. Similarly, the same property on RTP payloaders determines
-    whether they should use the information from this meta to construct
-    the CSRCs list on outgoing RTP buffers.
-
--   gst_sdp_message_from_text() is a convenience constructor to parse
-    SDPs from a string which is particularly useful for language
-    bindings.
-
-Support for Planar (Non-Interleaved) Raw Audio
-
-Raw audio samples are usually passed around in interleaved form in
-GStreamer, which means that if there are multiple audio channels the
-samples for each channel are interleaved in memory,
-e.g. |LEFT|RIGHT|LEFT|RIGHT|LEFT|RIGHT| for stereo audio. A
-non-interleaved or planar arrangement in memory would look like
-|LEFT|LEFT|LEFT|RIGHT|RIGHT|RIGHT| instead, possibly with
-|LEFT|LEFT|LEFT| and |RIGHT|RIGHT|RIGHT| residing in separate memory
-chunks or separated by some padding.
-
-GStreamer has always had signalling for non-interleaved audio since
-version 1.0, but it was never actually properly implemented in any
-elements. audioconvert would advertise support for it, but wasn’t
-actually able to handle it correctly.
-
-With this release we now have full support for non-interleaved audio as
-well, which means more efficient integration with external APIs that
-handle audio this way, but also more efficient processing of certain
-operations like interleaving multiple 1-channel streams into a
-multi-channel stream which can be done without memory copies now.
-
-New API to support this has been added to the GStreamer Audio support
-library: There is now a new GstAudioMeta which describes how data is
-laid out inside the buffer, and buffers with non-interleaved audio must
-always carry this meta. To access the non-interleaved audio samples you
-must map such buffers with gst_audio_buffer_map() which works much like
-gst_buffer_map() or gst_video_frame_map() in that it will populate a
-little GstAudioBuffer helper structure passed to it with the number of
-samples, the number of planes and pointers to the start of each plane in
-memory. This function can also be used to map interleaved audio buffers
-in which case there will be only one plane of interleaved samples.
-
-Of course support for this has also been implemented in the various
-audio helper and conversion APIs, base classes, and in elements such as
-audioconvert, audioresample, audiotestsrc, audiorate.
-
-Support for Closed Captions and Other Ancillary Data in Video
-
-The video support library has gained support for detecting and
-extracting Ancillary Data from videos as per the SMPTE S291M
-specification, including:
-
--   a VBI (Vertical Blanking Interval) parser that can detect and
-    extract Ancillary Data from Vertical Blanking Interval lines of
-    component signals. This is currently supported for videos in v210
-    and UYVY format.
-
--   a new GstMeta for closed captions: GstVideoCaptionMeta. This
-    supports the two types of closed captions, CEA-608 and CEA-708,
-    along with the four different ways they can be transported (other
-    systems are a superset of those).
-
--   a VBI (Vertical Blanking Interval) encoder for writing ancillary
-    data to the Vertical Blanking Interval lines of component signals.
-
-The new closedcaption plugin in gst-plugins-bad then makes use of all
-this new infrastructure and provides the following elements:
-
--   cccombiner: a closed caption combiner that takes a closed captions
-    stream and another stream and adds the closed captions as
-    GstVideoCaptionMeta to the buffers of the other stream.
-
--   ccextractor: a closed caption extractor which will take
-    GstVideoCaptionMeta from input buffers and output them as a separate
-    closed captions stream.
-
--   ccconverter: a closed caption converter that can convert between
-    different formats
-
--   line21encoder, line21decoder: inject/extract line21 closed captions
-    to/from SD video streams
-
--   cc708overlay: decodes CEA 608/708 captions and overlays them on
-    video
-
-Additionally, the following elements have also gained Closed Caption
-support:
-
--   qtdemux and qtmux support CEA 608/708 Closed Caption tracks
-
--   mpegvideoparse, h264parse extracts Closed Captions from MPEG-2/H.264
-    video streams
-
--   avviddec, avvidenc, x264enc got support for extracting/injecting
-    Closed Captions
-
--   decklinkvideosink can output closed captions and decklinkvideosrc
-    can extract closed captions
-
--   playbin and playbin3 learned how to autoplug CEA 608/708 CC overlay
-    elements
-
--   the externally maintained ajavideosrc element for AJA capture cards
-    has support for extracting closed captions
-
-The rsclosedcaption plugin in the Rust plugins collection includes a
-MacCaption (MCC) file parser and encoder.
-
-New Elements
-
--   overlaycomposition: New element that allows applications to draw
-    GstVideoOverlayCompositions on a stream. The element will emit the
-    "draw" signal for each video buffer, and the application then
-    generates an overlay for that frame (or not). This is much more
-    performant than e.g. cairooverlay for many use cases, e.g. because
-    pixel format conversions can be avoided or the blitting of the
-    overlay can be delegated to downstream elements (such as
-    gloverlaycompositor). It’s particularly useful for cases where only
-    a small section of the video frame should be drawn on.
-
--   gloverlaycompositor: New OpenGL-based compositor element that
-    flattens any overlays from GstVideoOverlayCompositionMetas into the
-    video stream. This element is also always part of glimagesink.
-
--   glalpha: New element that adds an alpha channel to a video stream.
-    The values of the alpha channel can either be set to a constant or
-    can be dynamically calculated via chroma keying. It is similar to
-    the existing alpha element but based on OpenGL. Calculations are
-    done in floating point so results may not be identical to the output
-    of the existing alpha element.
-
--   rtpfunnel funnels together RTP streams into a single session. Use
-    cases include multiplexing and bundle. webrtcbin uses it to
-    implement BUNDLE support.
-
--   testsrcbin is a source element that provides an audio and/or video
-    stream and also announces them using the recently-introduced
-    GstStream API. This is useful for testing elements such as playbin3
-    or uridecodebin3 etc.
+Noteworthy new features and API
 
--   New closed caption elements: cccombiner, ccextractor, ccconverter,
-    line21encoder, line21decoder and cc708overlay (see above)
+-   this section will be filled in in due course
 
--   wpesrc: new source element acting as a Web Browser based on WebKit
-    WPE
+New elements
 
--   Two new OpenCV-based elements: cameracalibrate and cameraundistort
-    that can communicate to figure out distortion correction parameters
-    for a camera and correct for the distortion.
-
--   New sctp plugin based on usrsctp with sctpenc and sctpdec elements.
-    These elements are used inside webrtcbin for implementing data
-    channels.
+-   this section will be filled in in due course
 
 New element features and additions
 
--   playbin3, playbin and playsink have gained a new "text-offset"
-    property to adjust the positioning of the selected subtitle stream
-    vis-a-vis the audio and video streams. This uses subtitleoverlay’s
-    new "subtitle-ts-offset" property. GstPlayer has gained matching API
-    for this, namely gst_player_get_text_video_offset().
-
--   playbin3 buffering improvements: in network playback scenarios there
-    may be multiple inputs to decodebin3, and buffering will be done
-    before decodebin3 using queue2 or downloadbuffer elements inside
-    urisourcebin. Since this is before any parsers or demuxers there may
-    not be any bitrate information available for the various streams, so
-    it was difficult to configure the buffering there smartly within
-    global constraints. This was improved now: The queue2 elements
-    inside urisourcebin will now use the new bitrate query to figure out
-    a bitrate estimate for the stream if no bitrate was provided by
-    upstream, and urisourcebin will use the bitrates of the individual
-    queues to distribute the globally-set "buffer-size" budget in bytes
-    to the various queues. urisourcebin also gained "low-watermark" and
-    "high-watermark" properties which will be proxied to the internal
-    queues, as well as a read-only "statistics" property which allows
-    querying of the minimum/maximum/average byte and time levels of the
-    queues inside the urisourcebin in question.
-
--   splitmuxsink has gained a couple of new features:
-
-    -   new "async-finalize" mode: This mode is useful for muxers or
-        outputs that can take a long time to finalize a file. Instead of
-        blocking the whole upstream pipeline while the muxer is doing
-        its stuff, we can unlink it and spawn a new muxer + sink
-        combination to continue running normally. This requires us to
-        receive the muxer and sink (if needed) as factories via the new
-        "muxer-factory" and "sink-factory" properties, optionally
-        accompanied by their respective properties structures (set via
-        the new "muxer-properties" and "sink-properties" properties).
-        There are also new "muxer-added" and "sink-added" signals in
-        case custom code has to be called for them to configure them.
-
-    -   "split-at-running-time" action signal: When called by the user,
-        this action signal ends the current file (and starts a new one)
-        as soon as the given running time is reached. If called multiple
-        times, running times are queued up and processed in the order
-        they were given.
-
-    -   "split-after" action signal to finish outputting the current GOP
-        to the current file and then start a new file as soon as the GOP
-        is finished and a new GOP is opened (unlike the existing
-        "split-now" which immediately finishes the current file and
-        writes the current GOP into the next newly-started file).
-
-    -   "reset-muxer" property: when unset, the muxer is reset using
-        flush events instead of setting its state to NULL and back. This
-        means the muxer can keep state across resets, e.g. mpegtsmux
-        will keep the continuity counter continuous across segments as
-        required by hlssink2.
-
--   qtdemux gained PIFF track encryption box support in addition to the
-    already-existing PIFF sample encryption support, and also allows
-    applications to select which encryption system to use via a
-    "drm-preferred-decryption-system-id" context in case there are
-    multiple options.
-
--   qtmux: the "start-gap-threshold" property determines now whether an
-    edit list will be created to account for small gaps or offsets at
-    the beginning of a stream in case the start timestamps of tracks
-    don’t line up perfectly. Previously the threshold was hard-coded to
-    1% of the (video) frame duration, now it is 0 by default (so edit
-    list will be created even for small differences), but fully
-    configurable.
-
--   rtpjitterbuffer has improved end-of-stream handling
-
--   rtpmp4vpay will be preferred over rtpmp4gpay for MPEG-4 video in
-    autoplugging scenarios now
-
--   rtspsrc now allows applications to send RTSP SET_PARAMETER and
-    GET_PARAMETER requests using action signals.
-
--   rtspsrc has a small (100ms) configurable teardown delay by default
-    to try and make sure an RTSP TEARDOWN request gets sent out when the
-    source element shuts down. This will block the downward PAUSED to
-    READY state change for a short time, but can be disabled where it’s
-    a problem. Some servers only allow a limited number of concurrent
-    clients, so if no proper TEARDOWN is sent new clients may have
-    problems connecting to the server for a while.
-
--   souphttpsrc behaves better with low bitrate streams now. Before it
-    would increase the read block size too quickly which could lead to
-    it not reading any data from the socket for a very long time with
-    low bitrate streams that are output live downstream. This could lead
-    to servers kicking off the client.
-
--   filesink: do internal buffering to avoid performance regression with
-    small writes since we bypass libc buffering by using writev()
-    instead of fwrite()
-
--   identity: add "eos-after" property and fix "error-after" property
-    when the element is reused
-
--   input-selector: lets context queries pass through, so that
-    e.g. upstream OpenGL elements can use contexts and displays
-    advertised by downstream elements
-
--   queue2: avoid ping-pong between 0% and 100% buffering messages if
-    upstream is pushing buffers larger than one of its limits, plus
-    performance optimisations
-
--   opusdec: new "phase-inversion" property to control phase inversion.
-    When enabled, this will slightly increase stereo quality, but
-    produces a stream that when downmixed to mono will suffer audio
-    distortions.
-
--   The x265enc HEVC encoder also exposes a "key-int-max" property to
-    configure the maximum allowed GOP size now.
-
--   decklinkvideosink has seen stability improvements for long-running
-    pipelines (potential crash due to overflow of leaked clock refcount)
-    and clock-slaving improvements when performing flushing seeks
-    (causing stalls in the output timeline), pausing and/or buffering.
-
--   srtpdec, srtpenc: add support for MKIs which allow multiple keys to
-    be used with a single SRTP stream
-
--   srtpdec, srtpenc: add support for AES-GCM and also add support for
-    it in gst-rtsp-server and rtspsrc.
-
--   The srt Secure Reliable Transport plugin has integrated server and
-    client elements srt{client,server}{src,sink} into one (srtsrc and
-    srtsink), since SRT connection mode can be changed by uri
-    parameters.
-
--   h264parse and h265parse will handle SEI recovery point messages and
-    mark recovery points as keyframes as well (in addition to IDR
-    frames)
-
--   webrtcbin: "add-turn-server" action signal to pass multiple ICE
-    relays (TURN servers).
-
--   The removesilence element has received various new features and
-    properties, such as a "threshold" property, detecting silence only
-    after minimum silence time/buffers, a "silent" property to control
-    bus message notifications as well as a "squash" property.
-
--   AOMedia AV1 decoder gained support for 10/12bit decoding whilst the
-    AV1 encoder supports more image formats and subsamplings now and
-    acquired support for rate control and profile related configuration.
-
--   The Fraunhofer fdkaac plugin can now be built against the 2.0.0
-    version API and has improved multichannel support
-
--   kmssink now supports unpadded 24-bit RGB and can configure mode
-    setting from video info, which enables display of multi-planar
-    formats such as I420 or NV12 with modesetting. It has also gained a
-    number of new properties: The "restore-crtc" property does what it
-    says on the tin and is enabled by default. "plane-properties" and
-    "connector-properties" can be used to pass custom properties to the
-    DRM.
-
--   waylandsink has a "fullscreen" property now and supports the
-    XDG-Shell protocol.
-
--   decklinkvideosink, decklinkvideosrc support selecting between
-    half/full duplex
-
--   The vulkan plugin gained support for macOS and iOS via MoltenVK in
-    addition to the existing support for X11 and Wayland
-
--   imagefreeze has a new num-buffers property to limit the number of
-    buffers that are produced and to send an EOS event afterwards
-
--   webrtcbin has a new, introspectable get-transceiver signal in
-    addition to the old get-transceivers signal that couldn’t be used
-    from bindings
-
--   Support for per-element latency information was added to the latency
-    tracer
+-   this section will be filled in in due course
 
 Plugin and library moves
 
--   The stereo element was moved from -bad into the existing audiofx
-    plugin in -good. If you get duplicate type registration warnings
-    when upgrading, check that you don’t have a stale stereoplugin lying
-    about somewhere.
-
-GstVideoAggregator, compositor, and OpenGL mixer elements moved from -bad to -base
-
-GstVideoAggregator is a new base class for raw video mixers and muxers
-and is based on GstAggregator. It provides defined-latency mixing of raw
-video inputs and ensures that the pipeline won’t stall even if one of
-the input streams stops producing data.
-
-As part of the move to stabilise the API there were some last-minute API
-changes and clean-ups, but those should mostly affect internal elements.
-Most notably, the "ignore-eos" pad property was renamed to
-"repeat-after-eos" and the conversion code was moved to a
-GstVideoAggregatorConvertPad subclass to avoid code duplication, make
-things less awkward for subclasses like the OpenGL-based video mixer,
-and make the API more consistent with the audio aggregator API.
-
-It is used by the compositor element, which is a replacement for
-‘videomixer’ which did not handle live inputs very well. compositor
-should behave much better in that respect and generally behave as one
-would expected in most scenarios.
-
-The compositor element has gained support for per-pad blending mode
-operators (SOURCE, OVER, ADD) which determines what operator to use for
-blending this pad over the previous ones. This can be used to implement
-crossfading and the available operators can be extended in the future as
-needed.
-
-A number of OpenGL-based video mixer elements (glvideomixer, glmixerbin,
-glvideomixerelement, glstereomix, glmosaic) which are built on top of
-GstVideoAggregator have also been moved from -bad to -base now. These
-elements have been merged into the existing OpenGL plugin, so if you get
-duplicate type registration warnings when upgrading, check that you
-don’t have a stale openglmixers plugin lying about somewhere.
+-   this section will be filled in in due course
 
-Plugin removals
+-   There were no plugin moves or library moves in this cycle.
 
-The following plugins have been removed from gst-plugins-bad:
-
--   The experimental daala plugin has been removed, since it’s not so
-    useful now that all effort is focused on AV1 instead, and it had to
-    be enabled explicitly with --enable-experimental anyway.
-
--   The spc plugin has been removed. It has been replaced by the gme
-    plugin.
+Plugin removals
 
--   The acmmp3dec and acmenc plugins for Windows have been removed. ACM
-    is an ancient legacy API and there was no point in keeping the
-    plugins around for a licensed MP3 decoder now that the MP3 patents
-    have expired and we have a decoder in -good. We also didn’t ship
-    these in our cerbero-built Windows packages, so it’s unlikely that
-    they’ll be missed.
+The following elements or plugins have been removed:
 
+-   this section will be filled in in due course
 
 Miscellaneous API additions
 
--   GstBitwriter: new generic bit writer API to complement the existing
-    bit reader
-
--   gst_buffer_new_wrapped_bytes() creates a wrap buffer from a GBytes
-
--   gst_caps_set_features_simple() sets a caps feature on all the
-    structures of a GstCaps
-
--   New GST_QUERY_BITRATE query: This allows determining from downstream
-    what the expected bitrate of a stream may be which is useful in
-    queue2 for setting time based limits when upstream does not provide
-    timing information. tsdemux, qtdemux and matroskademux have basic
-    support for this query on their sink pads.
-
--   elements: there is a new “Hardware” class specifier. Elements
-    interacting with hardware devices should specify this classifier in
-    their element factory class metadata. This is useful to advertise as
-    one might need to put such elements into READY state to test if the
-    hardware is present in the system for example.
-
--   protection: Add a new definition for unspecified system protection,
-    GST_PROTECTION_UNSPECIFIED_SYSTEM_ID
-
--   take functions for various mini objects that didn’t have them yet:
-    gst_query_take(), gst_message_take(), gst_tag_list_take(),
-    gst_buffer_list_take(). Unlike the various _replace() functions
-    _take() does not increase the reference count but takes ownership of
-    the mini object passed.
-
--   clear functions for various mini object types and GstObject which
-    unrefs the object or mini object (if non-NULL) and sets the variable
-    pointed to to NULL: gst_clear_structure(), gst_clear_tag_list(),
-    gst_clear_query(), gst_clear_message(), gst_clear_event(),
-    gst_clear_caps(), gst_clear_buffer_list(), gst_clear_buffer(),
-    gst_clear_mini_object(), gst_clear_object()
-
--   miniobject: new API gst_mini_object_add_parent() and
-    gst_mini_object_remove_parent() to set parent pointers on mini
-    objects to ensure correct writability: Every container of
-    miniobjects now needs to store itself as parent in the child object,
-    and remove itself again later. A mini object is then only writable
-    if there is at most one parent, that parent is writable itself, and
-    the reference count of the mini object is 1. GstBuffer (for
-    memories), GstBufferList (for buffers), GstSample (for caps, buffer,
-    bufferlist), and GstVideoOverlayComposition were updated
-    accordingly. Without this it was possible to have e.g. a buffer list
-    with a refcount of 2 used in two places at once that both modify the
-    same buffer with refcount 1 at the same time wrongly thinking it is
-    writable even though it’s really not.
-
--   poll: add API to watch for POLLPRI and stop treating POLLPRI as a
-    read. This is useful to wait for video4linux events which are
-    signalled via POLLPRI.
-
--   sample: new API to update the contents of a GstSample and make it
-    writable: gst_sample_set_buffer(), gst_sample_set_caps(),
-    gst_sample_set_segment(), gst_sample_set_info(), plus
-    gst_sample_is_writable() and gst_sample_make_writable(). This makes
-    it possible to reuse a sample object and avoid unnecessary memory
-    allocations, for example in appsink.
-
--   ClockIDs now keep a weak reference to underlying clock to avoid
-    crashes in basesink in corner cases where a clock goes away while
-    the ClockID is still in use, plus some new API
-    (gst_clock_id_get_clock(), gst_clock_id_uses_clock()) to check the
-    clock a ClockID is linked to.
-
--   The GstCheck unit test library gained a
-    fail_unless_equals_clocktime() convenience macro as well as some new
-    GstHarness API for for proposing meta APIs from the allocation
-    query: gst_harness_add_propose_allocation_meta(). ASSERT_CRITICAL()
-    checks in unit tests are now skipped if GStreamer was compiled with
-    GST_DISABLE_GLIB_CHECKS.
-
--   gst_audio_buffer_truncate() convenience function to truncate a raw
-    audio buffer
-
--   GstDiscoverer has support for caching the results of discovery in
-    the default cache directory. This can be enabled with the use-cache
-    property and is disabled by default.
-
--   GstMeta that are attached to GstBuffers are now always stored in the
-    order in which they were added.
-
--   Additional support for signalling ONVIF specific features were
-    added: the SEEK event can store a trickmode-interval now and support
-    for the Rate-Control and Frames RTSP headers was added to the RTSP
-    library.
-
-
-Miscellaneous performance and memory optimisations
-
-As always there have been many performance and memory usage improvements
-across all components and modules. Some of them (such as dmabuf
-import/export) have already been mentioned elsewhere so won’t be
-repeated here.
-
-The following list is only a small snapshot of some of the more
-interesting optimisations that haven’t been mentioned in other contexts
-yet:
-
--   The GstVideoEncoder and GstVideoDecoder base classes now release the
-    STREAM_LOCK when pushing out buffers, which means (multi-threaded)
-    encoders and decoders can now receive and continue to process input
-    buffers whilst waiting for downstream elements in the pipeline to
-    process the buffer that was pushed out. This increases throughput
-    and reduces processing latency, also and especially for
-    hardware-accelerated encoder/decoder elements.
-
--   GstQueueArray has seen a few API additions
-    (gst_queue_array_peek_nth(), gst_queue_array_set_clear_func(),
-    gst_queue_array_clear()) so that it can be used in other places like
-    GstAdapter instead of a GList, which reduces allocations and
-    improves performance.
-
--   appsink now reuses the sample object in pull_sample() if possible
-
--   rtpsession only starts the RTCP thread when it’s actually needed now
-
--   udpsrc uses a buffer pool now and the GstUdpSrc object structure was
-    optimised for better cache performance
-
-GstPlayer
-
--   API was added to fine-tune the synchronisation offset between
-    subtitles and video
-
-
-Miscellaneous changes
-
--   As a result of moving to newer FFmpeg APIs, encoder and decoder
-    elements exposed by the GStreamer FFmpeg wrapper plugin (gst-libav)
-    may have seen possibly incompatible changes to property names and/or
-    types, and not all properties exposed might be functional. We are
-    still reviewing the new properties and aim to minimise breaking
-    changes at least for the most commonly-used properties, so please
-    report any issues you run into!
-
-OpenGL integration
-
--   The OpenGL mixer elements have been moved from -bad to
-    gst-plugins-base (see above)
-
--   The Mesa GBM backend now supports headless mode
-
--   gloverlaycompositor: New OpenGL-based compositor element that
-    flattens any overlays from GstVideoOverlayCompositionMetas into the
-    video stream.
+-   this section will be filled in in due course
 
--   glalpha: New element that adds an alpha channel to a video stream.
-    The values of the alpha channel can either be set to a constant or
-    can be dynamically calculated via chroma keying. It is similar to
-    the existing alpha element but based on OpenGL. Calculations are
-    done in floating point so results may not be identical to the output
-    of the existing alpha element.
+Miscellaneous performance, latency and memory optimisations
 
--   glupload: Implement direct dmabuf uploader, the idea being that some
-    GPUs (like the Vivante series) can actually perform the YUV->RGB
-    conversion internally, so no custom conversion shaders are needed.
-    To make use of this feature, we need an additional uploader that can
-    import DMABUF FDs and also directly pass the pixel format, relying
-    on the GPU to do the conversion.
+-   this section will be filled in in due course
 
--   The OpenGL library no longer restores the OpenGL viewport. This is a
-    performance optimization to not require performing multiple
-    expensive glGet*() function calls per frame. This affects any
-    application or plugin use of the following functions and objects:
-    -   glcolorconvert library object (not the element)
-    -   glviewconvert library object (not the element)
-    -   gst_gl_framebuffer_draw_to_texture()
-    -   custom GstGLWindow implementations
+Miscellaneous other changes and enhancements
 
+-   this section will be filled in in due course
 
 Tracing framework and debugging improvements
 
--   There is now a GDB PRETTY PRINTER FOR VARIOUS GSTREAMER TYPES: For
-    GstObject pointers the type and name is added, e.g.
-    0x5555557e4110 [GstDecodeBin|decodebin0]. For GstMiniObject pointers
-    the object type is added, e.g. 0x7fffe001fc50 [GstBuffer]. For
-    GstClockTime and GstClockTimeDiff the time is also printed in human
-    readable form, e.g. 150116219955 [+0:02:30.116219955].
-
--   GDB EXTENSION WITH TWO CUSTOM GDB COMMANDS gst-dot AND gst-print:
-
-    -   gst-dot creates dot files that a very close to what
-        GST_DEBUG_BIN_TO_DOT_FILE() produces, but object properties and
-        buffer contents such as codec-data in caps are not available.
-
-    -   gst-print produces high-level information about a GStreamer
-        object. This is currently limited to pads for GstElements and
-        events for the pads. The output may look like this:
-
--   gst_structure_to_string() now serialises the actual value of
-    pointers when serialising GstStructures instead of claiming they’re
-    NULL. This makes debug logging in various places less confusing,
-    because it’s clear now that structure fields actually hold valid
-    objects. Such object pointer values will never be deserialised
-    however.
-
+-   this section will be filled in in due course
 
 Tools
 
--   gst-inspect-1.0 has coloured output now and will automatically use a
-    pager if the output does not fit on a page. This only works in a
-    UNIX environment and if the output is not piped, and on Windows 10
-    build 16257 or newer. If you don’t like the colours you can disable
-    them by setting the GST_INSPECT_NO_COLORS=1 environment variable or
-    passing the --no-color command line option.
-
+-   this section will be filled in in due course
 
 GStreamer RTSP server
 
--   Improved backlog handling when using TCP interleaved for data
-    transport. Before there was a fixed maximum size for backlog
-    messages, which was prone to deadlocks and made it difficult to
-    control memory usage with the watch backlog. The RTSP server now
-    limits queued TCP data messages to one per stream, moving queuing of
-    the data into the pipeline and leaving the RTSP connection
-    responsive to RTSP messages in both directions, preventing all those
-    problems.
-
--   Initial ULP Forward Error Correction support in rtspclientsink and
-    for RECORD mode in the server.
-
--   API to explicitly enable retransmission requests (RTX)
-
--   Lots of multicast-related fixes
-
--   rtsp-auth: Add support for parsing .htdigest files
-
+-   this section will be filled in in due course
 
 GStreamer VAAPI
 
--   Support Wayland’s display for context sharing, so the application
-    can pass its own wl_display in order to be used for the VAAPI
-    display creation.
-
--   A lot of work to support new Intel hardware using media-driver as VA
-    backend.
-
--   For non-x86 devices, VAAPI display can instantiate, through DRM,
-    with no PCI bus. This enables the usage of libva-v4l2-request
-    driver.
-
--   Added support for XDG-shell protocol as wl_shell replacement which
-    is currently deprecated. This change add as dependency
-    wayland-protocol.
-
--   GstVaapiFilter, GstVaapiWindow, and GstVaapiDecoder classes now
-    inherit from GstObject, gaining all the GStreamer’s instrumentation
-    support.
-
--   The metadata now specifies the plugin as Hardware class.
-
--   H264 decoder is more stable with problematic streams.
-
--   In H265 decoder added support for profiles main-422-10 (P010_10LE),
-    main-444 (AYUV) and main-444-10 (Y410)
-
--   JPEG decoder handles dynamic resolution changes.
-
--   More specification adherence in H264 and H265 encoders.
-
+-   this section will be filled in in due course
 
 GStreamer OMX
 
--   Add support of NV16 format to video encoders input.
-
--   Video decoders now handle the ALLOCATION query to tell upstream
-    about the number of buffers they require. Video encoders will also
-    use this query to adjust their number of allocated buffers
-    preventing starvation when using dynamic buffer mode.
-
--   The OMX_PERFORMANCE debug category has been renamed to OMX_API_TRACE
-    and can now be used to track a widder variety of interactions
-    between OMX and GStreamer.
-
--   Video encoders will now detect frame rate only changes and will
-    inform OMX about it rather than doing a full format reset.
-
--   Various Zynq UltraScale+ specific improvements:
-    -   Video encoders are now able to import dmabuf from upstream.
-    -   Support for HEVC range extension profiles and more AVC profiles.
-    -   We can now request video encoders to generate an IDR using the
-        force key unit event.
-
+-   this section will be filled in in due course
 
 GStreamer Editing Services and NLE
 
--   Added a gesdemux element, it is an auto pluggable element that
-    allows decoding edit list like files supported by GES
-
--   Added gessrc which wraps a GESTimeline as a standard source element
-    (implementing the ges protocol handler)
-
--   Added basic support for videorate::rate property potentially
-    allowing changing playback speed
-
--   Layer priority is now fully automatic and they should be moved with
-    the new ges_timeline_move_layer method, ges_layer_set_priority is
-    now deprecated.
-
--   Added a ges_timeline_element_get_layer_priority so we can simply get
-    all information about GESTimelineElement position in the timeline
-
--   GESVideoSource now auto orientates the images if it is defined in a
-    meta (overridable).
-
--   Added some PyGObject overrides to make the API more pythonic
-
--   The threading model has been made more explicit with safe guard to
-    make sure not thread safe APIs are not used from the wrong threads.
-    It is also now possible to properly handle in what thread the API
-    should be used.
-
--   Optimized GESClip and GESTrackElement creation
-
--   Added a way to compile out the old, unused and deprecated
-    GESPitiviFormatter
-
--   Re implemented the timeline editing API making it faster and making
-    the code much more maintainable
-
--   Simplified usage of nlecomposition outside GES by removing quirks in
-    it API usage and removing the need to treat it specially from an
-    application perspective.
-
--   ges-launch-1.0:
-
-    -   Added support to add titles to the timeline
-    -   Enhance the help auto generating it from the code
-
--   Deprecate ges_timeline_load_from_uri as loading the timeline should
-    be done through a project now
-
--   MANY leaks have been plugged and the unit testsuite is now “leak
-    free”
-
+-   this section will be filled in in due course
 
 GStreamer validate
 
--   Added an action type to verify the checksum of the sink last-sample
-
--   Added an include keyword to validate scenarios
-
--   Added the notion of variable in scenarios, with the set-vars keyword
-
--   Started adding support for “performance” like tests by allowing to
-    define the number of dropped buffers or the minimum buffer frequency
-    on a specific pad
-
--   Added a validateflow plugin which allows defining the data flow to
-    be seen on a particular pad and verifying that following runs match
-    the expectations
-
--   Added support for appsrc based test definition so we can instrument
-    the data pushed into the pipeline from scenarios
-
--   Added a mockdecryptor allowing adding tests with on encrypted files,
-    the element will potentially be instrumented with a validate
-    scenario
-
--   gst-validate-launcher:
-
-    -   Cleaned up output
-
-    -   Changed the default for “muting” tests as user doesn’t expect
-        hundreds of windows to show up when running the testsuite
-
-    -   Fixed the outputted xunit files to be compatible with GitLab
-
-    -   Added support to run tests on media files in push mode (using
-        pushfile://)
-
-    -   Added support for running inside gst-build
-
-    -   Added support for running ssim tests on rendered files
-
-    -   Added a way to simply define tests on pipelines through a simple
-        .json file
-
-    -   Added a python app to easily run python testsuite reusing all
-        the launcher features
-
-    -   Added flatpak knowledge so we can print backtrace even when
-        running from within flatpak
-
-    -   Added a way to automatically generated “known issues”
-        suppressions lines
-
-    -   Added a way to rerun tests to check if they are flaky and added
-        a way to tolerate tests known to be flaky
-
-    -   Add a way to output html log files
-
+-   this section will be filled in in due course
 
 GStreamer Python Bindings
 
--   add binding for gst_pad_set_caps()
-
--   pygobject dependency requirement was bumped to >= 3.8
-
--   new audiotestsrc, audioplot, and mixer plugin examples, and a
-    dynamic pipeline example
-
+-   this section will be filled in in due course
 
 GStreamer C# Bindings
 
--   bindings for the GstWebRTC library
-
-
-GStreamer Rust Bindings
-
-The GStreamer Rust bindings are now officially part of the GStreamer
-project and are also maintained in the GStreamer GitLab.
-
-The releases will generally not be synchronized with the releases of
-other GStreamer parts due to dependencies on other projects.
-
-Also unlike the other GStreamer libraries, the bindings will not commit
-to full API stability but instead will follow the approach that is
-generally taken by Rust projects, e.g.:
-
-1)  0.12.X will be completely API compatible with all other 0.12.Y
-    versions.
-2)  0.12.X+1 will contain bugfixes and compatible new feature additions.
-3)  0.13.0 will _not_ be backwards compatible with 0.12.X but projects
-    will be able to stay at 0.12.X without any problems as long as they
-    don’t need newer features.
-
-The current stable release is 0.12.2 and the next release series will be
-0.13, probably around March 2019.
-
-At this point the bindings cover most of GStreamer core (except for most
-notably GstAllocator and GstMemory), and most parts of the app, audio,
-base, check, editing-services, gl, net. pbutils, player, rtsp,
-rtsp-server, sdp, video and webrtc libraries.
-
-Also included is support for creating subclasses of the following types
-and writing GStreamer plugins:
-
--   gst::Element
--   gst::Bin and gst::Pipeline
--   gst::URIHandler and gst::ChildProxy
--   gst::Pad, gst::GhostPad
--   gst_base::Aggregator and gst_base::AggregatorPad
--   gst_base::BaseSrc and gst_base::BaseSink
--   gst_base::BaseTransform
-
-Changes to 0.12.X since 0.12.0
-
-Fixed
-
--   PTP clock constructor actually creates a PTP instead of NTP clock
-
-Added
-
--   Bindings for GStreamer Editing Services
--   Bindings for GStreamer Check testing library
--   Bindings for the encoding profile API (encodebin)
-
--   VideoFrame, VideoInfo, AudioInfo, StructureRef implements Send and
-    Sync now
--   VideoFrame has a function to get the raw FFI pointer
--   From impls from the Error/Success enums to the combined enums like
-    FlowReturn
--   Bin-to-dot file functions were added to the Bin trait
--   gst_base::Adapter implements SendUnique now
--   More complete bindings for the gst_video::VideoOverlay interface,
-    especially
-    gst_video::is_video_overlay_prepare_window_handle_message()
-
-Changed
-
--   All references were updated from GitHub to freedesktop.org GitLab
--   Fix various links in the README.md
--   Link to the correct location for the documentation
--   Remove GitLab badge as that only works with gitlab.com currently
-
-Changes in git master for 0.13
-
-Fixed
-
--   gst::tag::Album is the album tag now instead of artist sortname
-
-Added
-
--   Subclassing infrastructure was moved directly into the bindings,
-    making the gst-plugin crate deprecated. This involves many API
-    changes but generally cleans up code and makes it more flexible.
-    Take a look at the gst-plugins-rs crate for various examples.
-
--   Bindings for CapsFeatures and Meta
--   Bindings for
-    ParentBufferMeta,VideoMetaandVideoOverlayCompositionMeta`
--   Bindings for VideoOverlayComposition and VideoOverlayRectangle
--   Bindings for VideoTimeCode
-
--   UniqueFlowCombiner and UniqueAdapter wrappers that make use of the
-    Rust compile-time mutability checks and expose more API in a safe
-    way, and as a side-effect implement Sync and Send now
-
--   More complete bindings for Allocation Query
--   pbutils functions for codec descriptions
--   TagList::iter() for iterating over all tags while getting a single
-    value per tag. The old ::iter_tag_list() function was renamed to
-    ::iter_generic() and still provides access to each value for a tag
--   Bus::iter() and Bus::iter_timed() iterators around the corresponding
-    ::pop\*() functions
-
--   serde serialization of Value can also handle Buffer now
-
--   Extensive comments to all examples with explanations
--   Transmuxing example showing how to use typefind, multiqueue and
-    dynamic pads
--   basic-tutorial-12 was ported and added
-
-Changed
-
--   Rust 1.31 is the minimum supported Rust version now
--   Update to latest gir code generator and glib bindings
-
--   Functions returning e.g. gst::FlowReturn or other “combined” enums
-    were changed to return split enums like
-    Result<gst::FlowSuccess, gst::FlowError> to allow usage of the
-    standard Rust error handling.
-
--   MiniObject subclasses are now newtype wrappers around the underlying
-    GstRc<FooRef> wrapper. This does not change the API in any breaking
-    way for the current usages, but allows MiniObjects to also be
-    implemented in other crates and makes sure rustdoc places the
-    documentation in the right places.
-
--   BinExt extension trait was renamed to GstBinExt to prevent conflicts
-    with gtk::Bin if both are imported
-
--   Buffer::from_slice() can’t possible return None
-
--   Various clippy warnings
-
-
-GStreamer Rust Plugins
-
-Like the GStreamer Rust bindings, the Rust plugins are now officially
-part of the GStreamer project and are also maintained in the GStreamer
-GitLab.
-
-In the 0.3.x versions this contained infrastructure for writing
-GStreamer plugins in Rust, and a set of plugins.
-
-In git master that infrastructure was moved to the GLib and GStreamer
-bindings directly, together with many other improvements that were made
-possible by this, so the gst-plugins-rs repository only contains
-GStreamer elements now.
-
-Elements included are:
-
--   Tutorials plugin: identity, rgb2gray and sinesrc with extensive
-    comments
-
--   rsaudioecho, a port of the audiofx element
-
--   rsfilesrc, rsfilesink
-
--   rsflvdemux, a FLV demuxer. Not feature-equivalent with flvdemux yet
-
--   threadshare plugin: ts-appsrc, ts-proxysrc/sink, ts-queue, ts-udpsrc
-    and ts-tcpclientsrc elements that use a fixed number of threads and
-    share them between instances. For more background about these
-    elements see Sebastian’s talk “When adding more threads adds more
-    problems - Thread-sharing between elements in GStreamer” at the
-    GStreamer Conference 2017.
-
--   rshttpsrc, a HTTP source around the hyper/reqwest Rust libraries.
-    Not feature-equivalent with souphttpsrc yet.
-
--   togglerecord, an element that allows to start/stop recording at any
-    time and keeps all audio/video streams in sync.
-
--   mccparse and mccenc, parsers and encoders for the MCC closed caption
-    file format.
+-   this section will be filled in in due course
+
+GStreamer Rust Bindings and Rust Plugins
+
+The GStreamer Rust bindings are released separately with a different
+release cadence that’s tied to gtk-rs, but the latest release has
+already been updated for the upcoming new GStreamer 1.20 API.
+
+gst-plugins-rs, the module containing GStreamer plugins written in Rust,
+has also seen lots of activity with many new elements and plugins.
+
+What follows is a list of elements and plugins available in
+gst-plugins-rs, so people don’t miss out on all those potentially useful
+elements that have no C equivalent.
+
+-   FIXME: add new elements
+
+Rust audio plugins
+
+-   audiornnoise: New element for audio denoising which implements the
+    noise removal algorithm of the Xiph RNNoise library, in Rust
+-   rsaudioecho: Port of the audioecho element from gst-plugins-good
+    rsaudioloudnorm: Live audio loudness normalization element based on
+    the FFmpeg af_loudnorm filter
+-   claxondec: FLAC lossless audio codec decoder element based on the
+    pure-Rust claxon implementation
+-   csoundfilter: Audio filter that can use any filter defined via the
+    Csound audio programming language
+-   lewtondec: Vorbis audio decoder element based on the pure-Rust
+    lewton implementation
+
+Rust video plugins
+
+-   cdgdec/cdgparse: Decoder and parser for the CD+G video codec based
+    on a pure-Rust CD+G implementation, used for example by karaoke CDs
+-   cea608overlay: CEA-608 Closed Captions overlay element
+-   cea608tott: CEA-608 Closed Captions to timed-text (e.g. VTT or SRT
+    subtitles) converter
+-   tttocea608: CEA-608 Closed Captions from timed-text converter
+-   mccenc/mccparse: MacCaption Closed Caption format encoder and parser
+-   sccenc/sccparse: Scenarist Closed Caption format encoder and parser
+-   dav1dec: AV1 video decoder based on the dav1d decoder implementation
+    by the VLC project
+-   rav1enc: AV1 video encoder based on the fast and pure-Rust rav1e
+    encoder implementation
+-   rsflvdemux: Alternative to the flvdemux FLV demuxer element from
+    gst-plugins-good, not feature-equivalent yet
+-   rsgifenc/rspngenc: GIF/PNG encoder elements based on the pure-Rust
+    implementations by the image-rs project
+
+Rust text plugins
+
+-   textwrap: Element for line-wrapping timed text (e.g. subtitles) for
+    better screen-fitting, including hyphenation support for some
+    languages
+
+Rust network plugins
+
+-   reqwesthttpsrc: HTTP(S) source element based on the Rust
+    reqwest/hyper HTTP implementations and almost feature-equivalent
+    with the main GStreamer HTTP source souphttpsrc
+-   s3src/s3sink: Source/sink element for the Amazon S3 cloud storage
+-   awstranscriber: Live audio to timed text transcription element using
+    the Amazon AWS Transcribe API
+
+Generic Rust plugins
+
+-   sodiumencrypter/sodiumdecrypter: Encryption/decryption element based
+    on libsodium/NaCl
+-   togglerecord: Recording element that allows to pause/resume
+    recordings easily and considers keyframe boundaries
+-   fallbackswitch/fallbacksrc: Elements for handling potentially
+    failing (network) sources, restarting them on errors/timeout and
+    showing a fallback stream instead
+-   threadshare: Set of elements that provide alternatives for various
+    existing GStreamer elements but allow to share the streaming threads
+    between each other to reduce the number of threads
+-   rsfilesrc/rsfilesink: File source/sink elements as replacements for
+    the existing filesrc/filesink elements
 
-Changes to 0.3.X since 0.3.0
-
--   All references were updated from GitHub to freedesktop.org GitLab
--   Fix various links in the README.md
--   Link to the correct location for the documentation
-
-Changes in git master for 0.4
-
--   togglerecord: Switch to parking_lot crate for mutexes/condition
-    variables for lower overhead
--   Merge threadshare plugin here
--   New closedcaption plugin with mccparse and mccenc elements
--   New identity element for the tutorials plugin
-
--   Register plugins statically in tests instead of relying on the
-    plugin loader to find the shared library in a specific place
-
--   Update to the latest API changes in the GLib and GStreamer bindings
--   Update to the latest versions of all crates
+Build and Dependencies
 
+-   this section will be filled in in due course
 
-Build and Dependencies
+gst-build
 
--   The MESON BUILD SYSTEM BUILD IS NOW FEATURE-COMPLETE (*) and it is
-    now the recommended build system on all platforms and also used by
-    Cerbero to build GStreamer on all platforms. The Autotools build is
-    scheduled to be removed in the next cycle. Developers who currently
-    use gst-uninstalled should move to gst-build. The build option
-    naming has been cleaned up and made consistent and there are now
-    feature options to enable/disable plugins and various other features
-    on a case-by-case basis. (*) with the exception of plugin docs which
-    will be handled differently in future
-
--   Symbol export in libraries is now controlled via explicit exports
-    using symbol visibility or export defines where supported, to ensure
-    consistency across all platforms. This also allows libraries to have
-    exports that vary based on detected platform features and configure
-    options as is the case with the GStreamer OpenGL integration library
-    for example. A few symbols that had been exported by accident in
-    earlier versions may no longer be exported. These symbols will not
-    have had declarations in any public header files then though and
-    would not have been usable.
-
--   The GStreamer FFmpeg wrapper plugin (gst-libav) now depends on
-    FFmpeg 4.x and uses the new FFmpeg 4.x API and stopped relying on
-    ancient API that was removed with the FFmpeg 4.x release. This means
-    that it is no longer possible to build this module against an older
-    system-provided FFmpeg 3.x version. Use the internal FFmpeg 4.x copy
-    instead if you build using autotools, or use gst-libav 1.14.x
-    instead which targets the FFmpeg 3.x API and _should_ work fine in
-    combination with a newer GStreamer. It’s difficult for us to support
-    both old and new FFmpeg APIs at the same time, apologies for any
-    inconvenience caused.
-
--   Hardware-accelerated Nvidia video encoder/decoder plugins nvdec and
-    nvenc can be built against CUDA Toolkit versions 9 and 10.0 now. The
-    dynlink interface has been dropped since it’s deprecated in 10.0.
-
--   The (optional) OpenCV requirement has been bumped to >= 3.0.0 and
-    the plugin can also be built against OpenCV 4.x now.
-
--   New sctp plugin based on usrsctp (for WebRTC data channels)
+-   this section will be filled in in due course
 
 Cerbero
 
@@ -1173,741 +198,102 @@ Cerbero is a meta build system used to build GStreamer plus dependencies
 on platforms where dependencies are not readily available, such as
 Windows, Android, iOS and macOS.
 
-Cerbero has seen a number of improvements:
-
--   Cerbero has been ported to Python 3 and requires Python 3.5 or newer
-    now
-
--   Source tarballs are now protected by checksums in the recipes to
-    guard against download errors and malicious takeover of projects or
-    websites. In addition, downloads are only allowed via secure
-    transports now and plain HTTP, FTP and git:// transports are not
-    allowed anymore.
+General improvements
 
--   There is now a new fetch-bootstrap command which downloads sources
-    required for bootstrapping, with an optional --build-tools-only
-    argument to match the bootstrap --build-tools-only command.
+-   this section will be filled in in due course
 
--   The bootstrap, build, package and bundle-source commands gained a
-    new --offline switch that ensures that only sources from the cache
-    are used and never downloaded via the network. This is useful in
-    combination with the fetch and fetch-bootstrap commands that acquire
-    sources ahead of time before any build steps are executed. This
-    allows more control over the sources used and when sources are
-    updated, and is particularly useful for build environments that
-    don’t have network access.
+macOS / iOS
 
--   bootstrap --assume-yes will automatically say ‘yes’ to any
-    interactive prompts during the bootstrap stage, such as those from
-    apt-get or yum.
+-   this section will be filled in in due course
 
--   bootstrap --system-only will only bootstrap the system without build
-    tools.
-
--   Manifest support: The build manifest can be used in continuous
-    integration (CI) systems to fixate the Git revision of certain
-    projects so that all builds of a pipeline are on the same reference.
-    This is used in GStreamer’s gitlab CI for example. It can also be
-    used in order to re-produce a specific build. To set a manifest, you
-    can set manifest = 'my_manifest.xml' in your configuration file, or
-    use the --manifest command line option. The command line option will
-    take precedence over anything specific in the configuration file.
+Windows
 
--   The new build-deps command can be used to build only the
-    dependencies of a recipe, without the recipe itself.
+-   this section will be filled in in due course
 
--   new --list-variants command to list available variants
+Windows MSI installer
 
--   variants can now be set on the command line via the -v option as a
-    comma-separated list. This overrides any variants set in any
-    configuration files.
+-   this section will be filled in in due course
 
--   new qt5, intelmsdk and nvidia variants for enabling Qt5 and hardware
-    codec support. See the Enabling Optional Features with Variants
-    section in the Cerbero documentation for more details how to enable
-    and use these variants.
+Linux
 
--   When building on Windows, Cerbero can now build GStreamer recipes
-    and core dependencies such as glib with Visual Studio. This is
-    controlled by the visualstudio variant. Visual Studio 2015, 2017,
-    and 2019 are supported. Currently, only 64-bit x86 is supported due
-    to a known bug which will be fixed for the next release.
+-   this section will be filled in in due course
 
--   A new -t / --timestamp command line switch makes commands print
-    timestamps
+Android
 
+-   this section will be filled in in due course
 
 Platform-specific changes and improvements
 
 Android
 
--   toolchain: update compiler to clang and NDKr18. NDK r18 removed the
-    armv5 target and only has Android platforms that target at least
-    armv7 so the armv5 target is not useful anymore.
-
--   The way that GIO modules are named has changed due to upstream GLib
-    natively adding support for loading static GIO modules. This means
-    that any GStreamer application using gnutls for SSL/TLS on the
-    Android or iOS platforms (or any other setup using static libraries)
-    will fail to link looking for the g_io_module_gnutls_load_static()
-    function. The new function name is now
-    g_io_gnutls_load(gpointer data). data can be NULL for a static
-    library. Look at this commit for the necessary change in the
-    examples.
-
--   various build issues on Android have been fixed.
+-   this section will be filled in in due course
 
 macOS and iOS
 
--   various build issues on iOS have been fixed.
+-   this section will be filled in in due course
 
--   the minimum required iOS version is now 9.0. The difference in
-    adoption between 8.0 and 9.0 is 0.1% and the bump to 9.0 fixes some
-    build issues.
+Windows
 
--   The way that GIO modules are named has changed due to upstream GLib
-    natively adding support for loading static GIO modules. This means
-    that any GStreamer application using gnutls for SSL/TLS on the
-    Android or iOS platforms (or any other setup using static libraries)
-    will fail to link looking for the g_io_module_gnutls_load_static()
-    function. The new function name is now
-    g_io_gnutls_load(gpointer data). data can be NULL for a static
-    library. Look at this commit for the necessary change in the
-    examples.
+-   this section will be filled in in due course
 
-Windows
+Linux
 
--   The webrtcdsp element is shipped again as part of the Windows binary
-    packages, the build system issue has been resolved.
+-   this section will be filled in in due course
 
--   ‘Inconsistent DLL linkage’ warnings when building with MSVC have
-    been fixed
+Documentation improvements
 
--   Hardware-accelerated Nvidia video encoder/decoder plugins nvdec and
-    nvenc build on Windows now, also with MSVC and using Meson.
+-   this section will be filled in in due course
 
--   The ksvideosrc camera capture plugin supports 16-bit grayscale video
-    now
+Possibly Breaking Changes
 
--   The wasapisrc audio capture element implements loopback recording
-    from another output device or sink
+-   this section will be filled in in due course
+-   MPEG-TS SCTE-35 API changes (FIXME: flesh out)
+-   gst_parse_launch() and friends now error out on non-existing
+    properties on top-level bins where they would silently fail and
+    ignore those before.
 
--   wasapisink recover from low buffer levels in shared mode and some
-    exclusive mode fixes
+Known Issues
+
+-   this section will be filled in in due course
 
--   dshowsrc now implements the GstDeviceMonitor interface
+-   There are a couple of known WebRTC-related regressions/blockers:
 
+    -   webrtc: DTLS setup with Chrome is broken
+    -   webrtcbin: First keyframe is usually lost
 
 Contributors
 
-Aaron Boxer, Aleix Conchillo Flaqué, Alessandro Decina, Alexandru Băluț,
-Alex Ashley, Alexey Chernov, Alicia Boya García, Amit Pandya, Andoni
-Morales Alastruey, Andreas Frisch, Andre McCurdy, Andy Green, Anthony
-Violo, Antoine Jacoutot, Antonio Ospite, Arun Raghavan, Aurelien Jarno,
-Aurélien Zanelli, ayaka, Bananahemic, Bastian Köcher, Branko Subasic,
-Brendan Shanks, Carlos Rafael Giani, Charlie Turner, Christoph Reiter,
-Corentin Noël, Daeseok Youn, Damian Vicino, Dan Kegel, Daniel Drake,
-Daniel Klamt, Danilo Spinella, Dardo D Kleiner, David Ing, David
-Svensson Fors, Devarsh Thakkar, Dimitrios Katsaros, Edward Hervey,
-Emilio Pozuelo Monfort, Enrique Ocaña González, Erlend Eriksen, Ezequiel
-Garcia, Fabien Dessenne, Fabrizio Gennari, Florent Thiéry, Francisco
-Velazquez, Freyr666, Garima Gaur, Gary Bisson, George Kiagiadakis, Georg
-Lippitsch, Georg Ottinger, Geunsik Lim, Göran Jönsson, Guillaume
-Desmottes, H1Gdev, Haihao Xiang, Haihua Hu, Harshad Khedkar, Havard
-Graff, He Junyan, Hoonhee Lee, Hosang Lee, Hyunjun Ko, Ilya Smelykh,
-Ingo Randolf, Iñigo Huguet, Jakub Adam, James Stevenson, Jan Alexander
-Steffens, Jan Schmidt, Jerome Laheurte, Jimmy Ohn, Joakim Johansson,
-Jochen Henneberg, Johan Bjäreholt, John-Mark Bell, John Bassett, John
-Nikolaides, Jonathan Karlsson, Jonny Lamb, Jordan Petridis, Josep Torra,
-Joshua M. Doe, Jos van Egmond, Juan Navarro, Julian Bouzas, Jun Xie,
-Junyan He, Justin Kim, Kai Kang, Kim Tae Soo, Kirill Marinushkin, Kyrylo
-Polezhaiev, Lars Petter Endresen, Linus Svensson, Louis-Francis
-Ratté-Boulianne, Lucas Stach, Luis de Bethencourt, Luz Paz, Lyon Wang,
-Maciej Wolny, Marc-André Lureau, Marc Leeman, Marco Trevisan (Treviño),
-Marcos Kintschner, Marian Mihailescu, Marinus Schraal, Mark Nauwelaerts,
-Marouen Ghodhbane, Martin Kelly, Matej Knopp, Mathieu Duponchelle,
-Matteo Valdina, Matthew Waters, Matthias Fend, memeka, Michael Drake,
-Michael Gruner, Michael Olbrich, Michael Tretter, Miguel Paris, Mike
-Wey, Mikhail Fludkov, Naveen Cherukuri, Nicola Murino, Nicolas Dufresne,
-Niels De Graef, Nirbheek Chauhan, Norbert Wesp, Ognyan Tonchev, Olivier
-Crête, Omar Akkila, Pat DeSantis, Patricia Muscalu, Patrick Radizi,
-Patrik Nilsson, Paul Kocialkowski, Per Forlin, Peter Körner, Peter
-Seiderer, Petr Kulhavy, Philippe Normand, Philippe Renon, Philipp Zabel,
-Pierre Labastie, Piotr Drąg, Roland Jon, Roman Sivriver, Roman Shpuntov,
-Rosen Penev, Russel Winder, Sam Gigliotti, Santiago Carot-Nemesio,
-Sean-Der, Sebastian Dröge, Seungha Yang, Shi Yan, Sjoerd Simons, Snir
-Sheriber, Song Bing, Soon, Thean Siew, Sreerenj Balachandran, Stefan
-Ringel, Stephane Cerveau, Stian Selnes, Suhas Nayak, Takeshi Sato,
-Thiago Santos, Thibault Saunier, Thomas Bluemel, Tianhao Liu,
-Tim-Philipp Müller, Tobias Ronge, Tomasz Andrzejak, Tomislav Tustonić,
-U. Artie Eoff, Ulf Olsson, Varunkumar Allagadapa, Víctor Guzmán, Víctor
-Manuel Jáquez Leal, Vincenzo Bono, Vineeth T M, Vivia Nikolaidou, Wang
-Fei, wangzq, Whoopie, Wim Taymans, Wind Yuan, Wonchul Lee, Xabier
-Rodriguez Calvar, Xavier Claessens, Haihao Xiang, Yacine Bandou,
-Yeongjin Jeong, Yuji Kuwabara, Zeeshan Ali,
+-   this section will be filled in in due course
 
 … and many others who have contributed bug reports, translations, sent
 suggestions or helped testing.
 
+Stable 1.20 branch
 
-Stable 1.16 branch
-
-After the 1.16.0 release there will be several 1.16.x bug-fix releases
+After the 1.20.0 release there will be several 1.20.x bug-fix releases
 which will contain bug fixes which have been deemed suitable for a
 stable branch, but no new features or intrusive changes will be added to
-a bug-fix release usually. The 1.16.x bug-fix releases will be made from
-the git 1.16 branch, which is a stable branch.
-
-1.16.0
-
-1.16.0 was released on 19 April 2019.
-
-1.16.1
-
-The first 1.16 bug-fix release (1.16.1) was released on 23 September
-2019.
-
-This release only contains bugfixes and it _should_ be safe to update
-from 1.16.0.
-
-Highlighted bugfixes in 1.16.1
-
--   GStreamer-vaapi: fix green frames and decoding artefacts in some
-    cases
--   OpenGL: fix wayland event source burning CPU in certain
-    circumstances
--   Memory leak fixes and memory footprint improvements
--   Performance improvements
--   Stability and security fixes
--   Fix enum for GST_MESSAGE_DEVICE_CHANGED which is technically an API
-    break, but this is only used internally in GStreamer and duplicated
-    another message enum
--   hls: Make crypto dependency optional when hls-crypto is auto
--   player: fix switching back and forth between forward and reverse
-    playback
--   decklinkaudiosink: Drop late buffers
--   openh264enc: Fix compilation with openh264 v2.0
--   wasapisrc: fix segtotal value being always 2
--   android: Fix gnutls issue causing a FORTIFY crash on Android Q
--   windows: Fix two crashes due to cross-CRT free when using MSVC
-
-gstreamer core
-
--   device: gst_device_create_element() is transfer floating, not
-    transfer full
--   filesink, fdsink: respect IOV_MAX for the writev iovec array
-    (Solaris)
--   miniobject: free qdata array when the last qdata is removed (reduces
-    memory footprint)
--   bin: Fix minor race when adding to a bin
--   aggregator: Actually handle NEED_DATA return from update_src_caps()
--   aggregator: Ensure that the source pad is created as a
-    GstAggregatorPad if no type is given in the pad template
--   latency: fix custom event leaks
--   registry: Use plugin directory from the build system for
-    relocateable Windows builds
--   message: fix up enum value for GST_MESSAGE_DEVICE_CHANGED
--   info: Fix deadlock in gst_ring_buffer_logger_log()
--   downloadbuffer: Check for flush after seek
--   identity: Non-live upstream have no max latency
--   identity: Fix the ts-offset property getter
--   aggregator: Make parsing of explicit sink pad names more robust
--   bufferpool: Fix the buffer size reset code
--   fakesink, fakesrc, identity: sync gst_buffer_get_flags_string() with
-    new flags
--   multiqueue: never unref queries we do not own
--   concat: Reset last_stop on FLUSH_STOP too
--   aggregator: fix flow-return boolean return type mismatch
--   gstpad: Handle probes that reset the data field
--   gst: Add support for g_autoptr(GstPromise)
--   gst-inspect: fix unused-const-variable error in windows
--   base: Include gstbitwriter.h in the single-include header
--   Add various Since: 1.16 markers
--   GST_MESSAGE_DEVICE_CHANGED duplicates GST_MESSAGE_REDIRECT
--   Targetting wrong meson version
--   meson: Make get_flex_version.py script executable
--   meson: Link to objects instead of static helper library
--   meson: set correct install path for gdb helper
--   meson: fix warning about configure_file() install kwarg
-
-gst-plugins-base
-
--   video-info: parse field-order for all interleaved formats
--   tests: fix up valgrind suppressions for glibc getaddrinfo leaks
--   meson: Reenable NEON support (in audio resampler)
--   audio-resampler: Update NEON to handle remainders not multiples of 4
--   eglimage: Fix memory leak
--   audiodecoder: Set output caps with negotiated caps to avoid critical
-    info printed
--   video-frame: Take TFF flag from the video info if it was set in
-    there
--   glcolorconvert: Fix external-oes shader
--   video-anc: Fix ADF detection when trying to extract data from vanc
--   gl/wayland: fix wayland event source burning CPU
--   configure: add used attribute in order to make NEON detection
-    working with -flto.
--   audioaggregator: Return a valid rate range from caps query if
-    downstream supports a whole range
--   rtspconnection: data-offset increase not set
--   rtpsconnection: Fix number of n_vectors
--   video-color: Add compile-time assert for ColorimetryInfo enum
--   audiodecoder: Fix leak on failed audio gaps
--   glupload: Keep track of cached EGLImage texture format
--   playsink: Set ts-offset to text sink.
--   meson.build: use join_paths() on prefix
--   compositor: copy frames as-is when possible
--   compositor: Skip background when a pad obscures it completely
--   rtspconnection: Start CSeq at 1 (some servers don’t cope well with
-    seqnum 0)
--   viv-fb: fix build break for GST_GL_API
--   gl/tests: fix shader creation tests part 2
--   gl/tests: fix shader creation tests
--   wayland: set the event queue also for the xdg_wm_base object
--   video: Added GI annotation for gstvideoaffinetransformationmeta
-    apply_matrix
--   compositor: Remove unneeded left shift for ARGB/AYUV SOURCE operator
--   Colorimetry fixes
--   alsasrc: Don’t use driver timestamp if it’s zero
--   gloverlaycompositor: fix crash if buffer doesn’t have video meta
--   meson: Don’t try to find gio-unix on Windows
--   glshader: fix default external-oes shaders
--   subparse: fix pushing WebVTT cue with no newline at the end
--   meson: Missing “android” choice in gl_winsys
--   video test: Keep BE test inline with LE test
--   id3tag: Correctly validate the year from v1 tags before passing to
-    GstDateTime
--   gl/wayland: Don’t prefix wl_shell struct field
--   eglimage: Add compatibility define for DRM_FORMAT_NV24
--   Add various Since: 1.16 markers
--   video-anc: Handle SD formats correctly
--   Docs: add GL_CFLAGS to GTK_DOC_CFLAGS
--   GL: using vaapi and showing on glimagesink on wayland loads one core
-    for 100% on 1.16
--   GL: external-oes shader places precision qualifier before #extension
-    (was: androidmedia amcviddec fail after 1.15.90 1.16.0 update)
-
-gst-plugins-good
-
--   alpha: Fix one_over_kc calculation on arm/aarch64
--   souphttpsrc: Fix incompatible type build warning
--   rtpjitterbuffer: limit max-dropout-time to maxint32
--   rtpjitterbuffer: Clear clock master before unreffing
--   qtdemux: Use empty-array safe way to cleanup GPtrArray
--   v4l2: Fix type compatibility issue with glibc 2.30
--   valgrind: suppress Cond error coming from gnutls and Ignore leaks
-    caused by shout/sethostent
--   rtpfunnel: forward correct segment when switching pad
--   gtkglsink: fix crash when widget is resized after element
-    destruction
--   jpegdec: Don’t dereference NULL input state if we have no caps in
-    TIME segments
--   rtp: opuspay: fix memory leak in gst_rtp_opus_pay_setcaps
--   v4l2videodec: return right type for drain.
--   rtpssrcdemux: Avoid taking streamlock out-of-band
--   Support v4l2src buffer orphaning
--   splitmuxsink: Only set running time on finalizing sink element when
-    in async-finalize mode
--   rtpsession: Always keep at least one NACK on early RTCP
--   rtspsrc: do not try to send EOS with invalid seqnum
--   rtpsession: Call on-new-ssrc earlier
--   rtprawdepay: Don’t get rid of the buffer pool on FLUSH_STOP
--   rtpbin: Free storage when freeing session
--   scaletempo: Advertise interleaved layout in caps templates
--   Support v4l2src buffer orphaning
-
-gst-plugins-bad
-
--   hls: Make crypto dependency optional when hls-crypto is auto
--   player: fix switching back and forth between forward and reverse
-    playback
--   decklinkaudiosink: Drop late buffers
--   srt: Add stats property, include sender-side statistics and fix a
-    crash
--   dshowsrcwrapper: fix regression on device selection
--   tsdemux: Limit the maximum PES payload size
--   wayland: Define libdrm_dep in meson.build to fix meson configure
-    error when kms is disabled
--   sctp: Fix crash on free() when using the MSVC binaries
--   webrtc: Fix signals documentation
--   h264parse: don’t critical on VUI parameters > 2^31
--   rtmp: Fix crash inside free() with MSVC on Windows
--   iqa: fix leak of map_meta.data
--   d3dvideosink: Fix crash on WinProc handler
--   amc: Fix crash when a sync_meta survives its sink
--   pitch: Fix race between putSamples() and setting soundtouch
-    parameters
--   webrtc: fix type of max-retransmits, make it work
--   mxfdemux: Also allow picture essence element type 0x05 for VC-3
--   wasapi: fix symbol redefinition build error
--   decklinkvideosrc: Retrieve mode of the ancillary data from the frame
--   decklinkaudiosrc/decklinkvideosrc: Do nothing in
-    BaseSrc::negotiate() and…
--   adaptivedemux: do not retry downloads during shutdown.
--   webrtcbin: fix GInetAddress leak
--   dtls: fix dtls connection object leak
--   siren: fix a global buffer overflow spotted by asan
--   kmssink: Fix implicit declaration build error
--   Fix -Werror=return-type error in configure.
--   aiff: Fix infinite loop in header parsing.
--   nvdec: Fix possible frame drop on EOS
--   srtserversrc: yields malformed rtp payloads
--   srtsink: Fix crash in case no URI
--   dtlsagent: Fix leaked dtlscertificate
--   meson: bluez: Early terminate configure on Windows
--   decklink: Correctly ensure >=16 byte alignment for the buffers we
-    allocate
--   webrtcbin: fix DTLS when receivebin is set to DROP
--   zbar: Include running-time, stream-time and duration in the messages
--   uvch264src: Make sure we set our segment
--   avwait: Allow start and end timecode to be set back to NULL
--   avwait: Don’t print warnings for every buffer passed
--   hls/meson: fix dependency logic
--   Waylandsink gnome shell workaround
--   avwait: Allow setting start timecode after end timecode; protect
-    propeties with mutex
--   wayland/wlbuffer: just return if used_by_compositor is true when
-    attach
--   proxy: Set SOURCE flag on the source and SINK flag on the sink
--   ivfparse: Check the data size against IVF_FRAME_HEADER_SIZE
--   webrtc: Add various Since markers to new types after 1.14.0
--   msdk: fix the typo in debug category
--   dtlsagent: Do not overwrite openssl locking callbacks
--   meson: Fix typo in gsm header file name
--   srt: handle races in state change
--   webrtc: Add g_autoptr() support for public types
--   openh264enc: Fix compilation with openh264 v2.0
--   meson: Allow CUDA_PATH fallback on linux
--   meson: fix build with opencv=enabled and opencv4. Fixes #964
--   meson: Add support for the colormanagement plugin
--   autotools: gstsctp: set LDFLAGS
--   nvenc/nvdec: Add NVIDIA SDK headers to noinst_HEADERS
--   h264parse: Fix typo when setting multiview mode and flags
--   Add various Since: 1.16 markers
--   opencv: allow compilation against 4.1.x
--   Backport of some minor srt commits without MR into 1.16
--   meson: fix build with opencv=enabled and opencv4
--   wasapisrc: fix segtotal value being always 2 due to an unused
-    variable
--   meson: colormanagement missing
--   androidmedia amcviddec fail after 1.15.90 1.16.0 update
-
-gst-plugins-ugly
-
--   meson: Always require the gmodule dependency
-
-gst-libav
-
--   docs: don’t include the type hierarchy, fixing build with gtk-doc
-    1.30
--   avvidenc: Correctly signal interlaced input to ffmpeg when the input
-    caps are interlaced
--   autotools: add bcrypt to win32 libs
--   gstav: Use libavcodec util function for version check
--   API documentation fails to build with gtk-doc 1.30
-
-gst-rtsp-server
-
--   rtsp-client: RTP Info must exist in PLAY response
--   onvif-media: fix “void function returning a value” compiler warning
--   Add various Since: 1.16 markers
-
-gstreamer-vaapi
-
--   fix egl context leak and display creation race
--   pluginutil: Remove Mesa from drivers white list
--   Classify vaapidecodebin as a hardware decoder
--   Fix two leak
--   vaapivideomemory: demote error message to info
--   encoder: vp8,vp9: reset frame_counter when input frame’s format
-    changes
--   encoder: mpeg2: No packed header for SPS and PPS
--   decoder: vp9: clear parser pointer after release
--   encoder: Fixes deadlock in change state function
--   encoder: h265: reset num_ref_idx_l1_active_minus1 when low delay B.
--   encoder: not call ensure_num_slices inside g_assert()
--   encoder: continue if roi meta is NULL
--   decoder: vp9: Set chroma_ ype by VP9 bit_depth
--   vaapipostproc: don’t do any color conversion when GL_TEXTURE_UPLOAD
--   libs: surface: fix double free when dmabuf export fails
--   h264 colors and artifacts upon upgrade to GStreamer Core Library
-    version 1.15.90
-
-gst-editing-services
-
--   element: Properly handle the fact that pasting can return NULL
--   Add various missing Since markers
--   launch: Fix caps restriction short names
--   python: Avoid warning about using deprecated methods
--   video-transition: When using non crossfade effect use ‘over’
-    operations
--   meson: Generate a pkgconfig file for the GES plugin
-
-gst-devtools
-
--   launcher: testsuites: skip systemclock stress tests
--   validate: fix build on macOS
-
-gst-build
-
--   Update win flex bison binaries
--   Update the flexmeson windows binary version
--   Don’t allow people to run meson inside the uninstalled env
-
-Cerbero build tool and packaging changes in 1.16.1
-
--   cerbero: Add enums for Fedora 30, Fedora 31 and Debian bullseye
--   gnutls.recipe: Fix crash when running on Android Q
--   recipes: Upgrade openssl to 1.1.1c
--   Fix some typos
--   add support for vs build tools 2019, fixes #183
--   android: Adjust gstreamer-1.0.mk for NDK r20
--   Fix license enums
--   bootstrap: Fix dnf usage on CentOS
--   Make _add_system_libs reentrant
--   meson.recipe: Fix setting of bitcode compiler options
--   cerbero: support Ubuntu disco dingo
--   cerbero: Set utf-8 to execution character set also on MSVC
--   git: simplify the reset of the source branch.
--   FORTIFY: %n not allowed on Android Q
--   Fails to build if there’s no license file for the given license
-    (GPL/LGPL without Plus, Proprietary, …)
-
-Contributors to 1.16.1
-
-Aaron Boxer, Adam Duskett, Alicia Boya García, Andoni Morales Alastruey,
-Antonio Ospite, Arun Raghavan, Askar Safin, A. Wilcox, Charlie Turner,
-Christoph Reiter, Damian Hobson-Garcia, Daniel Klamt, Danny Smith, David
-Gunzinger, David Ing, David Svensson Fors, Doug Nazar, Edward Hervey,
-Eike Hein, Fabrice Bellet, Fernando Herrrera, Georg Lippitsch, Göran
-Jönsson, Guillaume Desmottes, Haihao Xiang, Haihua Hu, Håvard Graff, Hou
-Qi, Ignacio Casal Quinteiro, Ilya Smelykh, Jan Schmidt, Javier Celaya,
-Jim Mason, Jonas Larsson, Jordan Petridis, Jose Antonio Santos Cadenas,
-Juan Navarro, Knut Andre Tidemann, Kristofer Björkström, Lucas Stach,
-Marco Felsch, Marcos Kintschner, Mark Nauwelaerts, Martin Liska, Martin
-Theriault, Mathieu Duponchelle, Matthew Waters, Michael Olbrich, Mike
-Gorse, Nicola Murino, Nicolas Dufresne, Niels De Graef, Niklas
-Hambüchen, Nirbheek Chauhan, Olivier Crête, Philippe Normand, Ross
-Burton, Sebastian Dröge, Seungha Yang, Song Bing, Thiago Santos,
-Thibault Saunier, Thomas Coldrick, Tim-Philipp Müller, Víctor Manuel
-Jáquez Leal, Vivia Nikolaidou, Xavier Claessens, Yeongjin Jeong,
-
-… and many others who have contributed bug reports, translations, sent
-suggestions or helped testing. Thank you all!
-
-List of merge requests and issues fixed in 1.16.1
-
--   List of Merge Requests applied in 1.16
--   List of Issues fixed in 1.16.1
-
-1.16.2
-
-The second 1.16 bug-fix release (1.16.2) was released on 03 December
-2019.
-
-This release only contains bugfixes and it _should_ be safe to update
-from 1.16.1.
-
-Highlighted bugfixes in 1.16.2
-
--   Interlaced video scaling fixes
--   CineForm video support in AVI
--   audioresample: avoid glitches due to rounding errors after changing
-    rate
--   Command line tool output printing improvements on Windows
--   various performance improvements, memory leak fixes and security
-    fixes
--   VP9 decoding fixes
--   avfvideosrc: Explicitly request video permission on macOS 10.14+
--   wasapi: bug fixes and stability improvements
--   webrtc-audio-processing: fix segmentation fault on 32-bit windows
--   tsdemux: improved handling of certain discontinuities
--   vaapi h265 decoder: wait for I-frame before trying to decode
-
-gstreamer
-
--   gst-launch: Fix ugly stdout on Windows
--   tee: Make sure to actually deactivate pads that are released
--   bin: Drop need-context messages without source instead of crashing
--   gst: Don’t pass miniobjects to GST_DEBUG_OBJECT() and similar macros
--   tracers: Don’t leak temporary GstStructure
-
-gst-plugins-base
-
--   xvimagepool: Update size, stride, and offset with allocated XvImage
--   video-converter: Fix RGB-XYZ-RGB conversion
--   audiorate: Update next_offset on rate change
--   audioringbuffer: Reset reorder flag before check
--   audio-buffer: Don’t fail to map buffers with zero samples
--   videorate: Fix max-duplication-time handling
--   gl/gbm: ensure we call the resize callback before attempting to draw
--   video-converter: Various fixes for interlaced scaling
--   gstrtspconnection: messages_bytes not decreased
--   check: Don’t use real audio devices for tests
--   riff: add CineForm mapping
--   glfilters: Don’t use static variables for storing per-element state
--   glupload: Add VideoMetas and GLSyncMeta to the raw uploaded buffers
--   streamsynchronizer: avoid pad release race during logging.
--   gst-play: Use gst_print* to avoid broken stdout string on Windows
-
-gst-plugins-good
-
--   vp9dec: Fix broken 4:4:4 8bits decoding
--   rtpsession: add locking for clear-pt-map
--   rtpL16depay: don’t crash if data is not modulo channels*width
--   wavparse: Fix push mode ignoring audio with a size smaller than
-    segment buffer
--   wavparse: Fix push mode ignoring last audio payload chunk
--   aacparse: fix wrong offset of the channel number in adts header
--   jpegdec: Fix incorrect logic in EOI tag detection
--   videocrop: Also update the coordinate when in-place
--   jpegdec: don’t overwrite the last valid line
--   vpx: Error out if enabled and no features found
--   v4l2videodec: ensure pool exists before orphaning it
--   v4l2videoenc: fix type conversion errors
--   v4l2bufferpool: Queue number of allocated buffers to capture
--   v4l2object: fix mpegversion number typo
--   v4l2object: Work around bad TRY_FMT colorimetry implementations
-
-gst-plugins-bad
-
--   avfvideosrc: Explicitly request video permission on macOS 10.14+
--   wasapi: Various fixes and a workaround for a specific driver bug
--   wasapi: Move to CoInitializeEx for COM initialization
--   wasapi: Fix runtime/build warnings
--   waylandsink: Commit the parent after creating subsurface
--   msdkdec: fix surface leak in msdkdec_handle_frame
--   tsmux: Fix copying of buffer region
--   tsdemux: Handle continuity mismatch in more cases
--   tsdemux: Always issue a DTS even when it’s equal to PTS
--   openexr: Fix build with OpenEXR 2.4 (and also OpenEXR 2.2 on Ubuntu
-    18.04)
--   ccextractor: Always forward all sticky events to the caption pad
--   pnmdec: Return early on ::finish() if we have no actual data to
-    parse
--   ass: avoid infinite unref loop with bad data
--   fluidsynth: add sf3 to soundfont search path
--   webrtcdsp/webrtcechoprobe segmentation fault on windows (1.16.0 x86)
-
-gst-libav
-
--   avvidenc: Fix error propagation
--   avdemux: Fix segmentation fault if long_name is NULL
--   avviddec: Fix huge leak caused by circular reference
--   avviddec: Enforce allocate new AVFrame per input frame
--   avdec_mpeg2video (and probably more): Huge memory leak in git master
-
-gst-rtsp-server
-
--   rtsp-media: Use lock in gst_rtsp_media_is_receive_only
--   rtsp-client: RTP Info when completed_sender
--   rtsp-client: fix location uri-format by getting uri directly from
-    context instead
-
-gstreamer-vaapi
-
--   meson build: halt configuration if no renderer API
--   libs: decoder: h265: skip all pictures prior the first I-frame
--   libs: window: x11: Avoid usage of deprecated API
-
-gst-editing-services
-
--   Initialize debug categories before usage
-
-gst-build
-
--   gst-env: Use locally built GStreamer utility programs
-
-Cerbero build tool and packaging changes in 1.16.2
-
-General
-
--   openssl: Update to 1.1.1d
--   Updated ffmpeg, expat, flac, freetype, croco, ogg, xml2, mpg123,
-    openjpeg, opus, pixman, speex, tiff recipes
--   Fix setting of git credentials in local source repos
-
-Windows
-
--   webrtc-audio-processing: fix segmentation fault on 32-bit windows
-    with webrtcdsp/webrtcechoprobe elemens
--   vpx plugin has no features when built with Visual Studio 2019
--   libvpx: Add support for Visual Studio 2019
--   mingw-runtime.recipe: Correctly package pkg-config in the MSI
--   GIO doesn’t load any modules on Windows with MSVC, which breaks TLS
-    support since glib-networking’s giognutls module isn’t loaded
--   Make the instructions for running Cerbero the same on all platforms
-
-macOS + iOS
-
--   Add support for macOS 10.15 Catalina
--   Updates for Xcode 11
--   macos/ios: expose objc++ compilers in env variables
--   srt.recipe: Fix crash in constructor on iOS
--   osx-framework.recipe: Dynamically generate the list of libraries and
-    ship pkg-config
--   macos: add -mmacosx-version-min for framework
--   gstreamer-1.0-osx-framework.recipe contains an outdated hard-coded
-    list of libraries
--   We need to ship pkg-config with macOS
-
-Linux
-
--   Fix filesprovider.find_shlib_regex when a lib_suffix is used in the
-    cerbero config file
-
-Contributors to 1.16.2
-
-Adam Nilsson, Amr Mahdi, Angus Ao, Charlie Turner, Edward Hervey, Fabian
-Greffrath, Fuwei Tang, Havard Graff, Hu Qian, James Cowgill, Jan
-Alexander Steffens (heftig), Jeffy Chen, Jeremy Lempereur, Joakim
-Johansson, Jochen Henneberg, Julien Isorce, Kevin Joly, Kristofer
-Bjorkstrom, Kyrylo Polezhaiev, Matthew Waters, Michael Olbrich, Muhammet
-Ilendemli, Nicolas Dufresne, Nirbheek Chauhan, Pablo Marcos Oltra, Roman
-Shpuntov, Ruben Gonzalez, Scott Kanowitz, Sebastian Dröge, Seungha Yang,
-Thibault Saunier, Tim-Philipp Müller, Víctor Manuel Jáquez Leal, Vivia
-Nikolaidou,
-
-… and many others who have contributed bug reports, translations, sent
-suggestions or helped testing. Thank you all!
-
-List of merge requests and issues fixed in 1.16.2
-
--   List of Merge Requests applied in 1.16
--   List of Issues fixed in 1.16.2
-
-
-Known Issues
-
--   possibly breaking/incompatible changes to properties of wrapped
-    FFmpeg decoders and encoders (see above).
+a bug-fix release usually. The 1.20.x bug-fix releases will be made from
+the git 1.20 branch, which will be a stable branch.
 
--   The way that GIO modules are named has changed due to upstream GLib
-    natively adding support for loading static GIO modules. This means
-    that any GStreamer application using gnutls for SSL/TLS on the
-    Android or iOS platforms (or any other setup using static libraries)
-    will fail to link looking for the g_io_module_gnutls_load_static()
-    function. The new function name is now
-    g_io_gnutls_load(gpointer data). See Android/iOS sections above for
-    further details.
+1.20.0
 
+1.20.0 is scheduled to be released around October/November 2021.
 
-Schedule for 1.18
+Schedule for 1.22
 
-Our next major feature release will be 1.18, and 1.17 will be the
-unstable development version leading up to the stable 1.18 release. The
-development of 1.17/1.18 will happen in the git master branch.
+Our next major feature release will be 1.22, and 1.21 will be the
+unstable development version leading up to the stable 1.22 release. The
+development of 1.21/1.22 will happen in the git main branch.
 
-The plan for the 1.18 development cycle is yet to be confirmed, but it
-is now expected that feature freeze will take place in December 2019,
-with the first 1.18 stable release ready in late January or February.
+The plan for the 1.22 development cycle is yet to be confirmed.
 
-1.18 will be backwards-compatible to the stable 1.16, 1.14, 1.12, 1.10,
-1.8, 1.6, 1.4, 1.2 and 1.0 release series.
+1.22 will be backwards-compatible to the stable 1.20, 1.18, 1.16, 1.14,
+1.12, 1.10, 1.8, 1.6, 1.4, 1.2 and 1.0 release series.
 
 ------------------------------------------------------------------------
 
-_These release notes have been prepared by Tim-Philipp Müller with_
-_contributions from Sebastian Dröge, Guillaume Desmottes, Matthew
-Waters, _ _Thibault Saunier, and Víctor Manuel Jáquez Leal._
+These release notes have been prepared by Tim-Philipp Müller with
+contributions from …
 
-_License: CC BY-SA 4.0_
+License: CC BY-SA 4.0
diff --git a/README b/README
index 08b2e1b..c95e53e 100644 (file)
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-GStreamer 1.16.x stable series
+GStreamer 1.19.x development series
 
 WHAT IT IS
 ----------
@@ -9,17 +9,22 @@ WHERE TO START
 --------------
 
 We have a website at
-http://gstreamer.freedesktop.org/
 
-You should start by going through our FAQ at
-http://gstreamer.freedesktop.org/data/doc/gstreamer/head/faq/html/
+  https://gstreamer.freedesktop.org
 
-There is more documentation; go to
-http://gstreamer.freedesktop.org/documentation
+Our documentation, including tutorials, API reference and FAQ can be found at
 
-You can subscribe to our mailing lists; see the website for details.
+  https://gstreamer.freedesktop.org/documentation/
 
-We track bugs in GNOME's bugzilla; see the website for details.
+You can subscribe to our mailing lists:
+
+  https://lists.freedesktop.org/mailman/listinfo/gstreamer-announce
+
+  https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
+
+We track bugs, feature requests and merge requests (patches) in GitLab at
+
+  https://gitlab.freedesktop.org/gstreamer/
 
 You can join us on IRC - #gstreamer on irc.freenode.org
 
@@ -137,12 +142,11 @@ PLATFORMS
 ---------
 
 - Linux is of course fully supported
-- FreeBSD is reported to work; other BSDs should work too
-- Solaris is reported to work; a specific sunaudiosink plugin has been written
-- MacOSX works, binary 1.x packages can be built using the cerbero build tool
+- FreeBSD is reported to work; other BSDs should work too; same for Solaris
+- MacOS works, binary 1.x packages can be built using the cerbero build tool
 - Windows works; binary 1.x packages can be built using the cerbero build tool
   - MSys/MinGW builds
-  - Microsoft Visual Studio builds are not yet available or supported
+  - Microsoft Visual Studio builds are also available and supported
 - Android works, binary 1.x packages can be built using the cerbero build tool
 - iOS works
 
@@ -151,36 +155,49 @@ INSTALLING FROM PACKAGES
 
 You should always prefer installing from packages first.  GStreamer is
 well-maintained for a number of distributions, including Fedora, Debian,
-Ubuntu, Mandrake, Gentoo, ...
+Ubuntu, Mandrake, Arch Linux, Gentoo, ...
 
 Only in cases where you:
-- want to hack on GStreamer
-- want to verify that a bug has been fixed
-- do not have a sane distribution
+
+ - want to hack on GStreamer
+ - want to verify that a bug has been fixed
+ - do not have a sane distribution
+
 should you choose to build from source tarballs or git.
 
 Find more information about the various packages at
-http://gstreamer.freedesktop.org/download/
+
+  https://gstreamer.freedesktop.org/download/
 
 COMPILING FROM SOURCE TARBALLS
 ------------------------------
 
-- again, make sure that you really need to install from source !
+- again, make sure that you really need to install from source!
   If GStreamer is one of your first projects ever that you build from source,
   consider taking on an easier project.
 
-- check output of ./configure --help to see if any options apply to you
+- you need a recent version of Meson installed, see
+
+    http://mesonbuild.com/Getting-meson.html
+
+  and
+
+    https://gitlab.freedesktop.org/gstreamer/gst-build/blob/master/README.md
+
 - run
-  ./configure
-  make
+
+    meson build
+    ninja -C build
 
   to build GStreamer.
+
 - if you want to install it (not required, but what you usually want to do), run
-  make install
+
+    ninja -C build install
 
 - try out a simple test:
-  gst-launch -v fakesrc num_buffers=5 ! fakesink
-  (If you didn't install GStreamer, prefix gst-launch with tools/)
+  gst-launch-1.0 -v fakesrc num_buffers=5 ! fakesink
+  (If you didn't install GStreamer, run `./build/tools/gst-launch-1.0`)
 
   If it outputs a bunch of messages from fakesrc and fakesink, everything is
   ok.
@@ -196,39 +213,19 @@ COMPILING FROM SOURCE TARBALLS
 COMPILING FROM GIT
 ------------------
 
-When building from git sources, you will need to run autogen.sh to generate
-the build system files.
-
-You will need a set of additional tools typical for building from git,
-including:
-- autoconf
-- automake
-- libtool
-
-autogen.sh will check for recent enough versions and complain if you don't have
-them.  You can also specify specific versions of automake and autoconf with
---with-automake and --with-autoconf
-
-Check autogen.sh options by running autogen.sh --help
-
-autogen.sh can pass on arguments to configure
-
-When you have done this once, you can use autoregen.sh to re-autogen with
-the last passed options as a handy shortcut.  Use it.
-
-After the autogen.sh stage, you can follow the directions listed in
-"COMPILING FROM SOURCE"
+You can build an uninstalled GStreamer from git for development or testing
+purposes without affecting your system installation.
 
-You can also run your whole git stack uninstalled in your home directory,
-so that you can quickly test changes without affecting your system setup or
-interfering with GStreamer installed from packages.  Many GStreamer developers
-use an uninstalled setup for their work.
+Get started with:
 
-There is a 'create-uninstalled-setup.sh' script in
+    git clone https://gitlab.freedesktop.org/gstreamer/gst-build
+    meson build
+    ninja -C build
+    ninja -C build uninstalled
 
-  http://cgit.freedesktop.org/gstreamer/gstreamer/tree/scripts/
+For more information, see the `gst-build` module and its documentation:
 
-to easily create an uninstalled setup from scratch.
+  https://gitlab.freedesktop.org/gstreamer/gst-build/blob/master/README.md
 
 
 PLUG-IN DEPENDENCIES AND LICENSES
diff --git a/RELEASE b/RELEASE
index 7f9c1b3..5afe9d7 100644 (file)
--- a/RELEASE
+++ b/RELEASE
@@ -1,15 +1,15 @@
-This is GStreamer core 1.16.2.
+This is GStreamer core 1.19.2.
 
-The GStreamer team is pleased to announce another bug-fix release in the
-stable 1.x API series of your favourite cross-platform multimedia framework!
+GStreamer 1.19 is the development branch leading up to the next major
+stable version which will be 1.20.
 
-The 1.16 release series adds new features on top of the 1.14 series and is
+The 1.19 development series adds new features on top of the 1.18 series and is
 part of the API and ABI-stable 1.x release series of the GStreamer multimedia
 framework.
 
 Full release notes will one day be found at:
 
-  https://gstreamer.freedesktop.org/releases/1.16/
+  https://gstreamer.freedesktop.org/releases/1.20/
 
 Binaries for Android, iOS, Mac OS X and Windows will usually be provided
 shortly after the release.
diff --git a/TODO b/TODO
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/autogen.sh b/autogen.sh
deleted file mode 100755 (executable)
index e2e6f74..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-#!/bin/sh
-#
-# gstreamer autogen.sh
-#
-# Run this to generate all the initial makefiles, etc.
-#
-# This file has been generated from common/autogen.sh.in via common/update-autogen
-
-
-test -n "$srcdir" || srcdir=`dirname "$0"`
-test -n "$srcdir" || srcdir=.
-
-olddir=`pwd`
-cd "$srcdir"
-
-package=gstreamer
-srcfile=gstreamer.doap
-
-# Make sure we have common
-if test ! -f common/gst-autogen.sh;
-then
-  echo "+ Setting up common submodule"
-  git submodule init
-fi
-git submodule update
-
-# source helper functions
-if test ! -f common/gst-autogen.sh;
-then
-  echo There is something wrong with your source tree.
-  echo You are missing common/gst-autogen.sh
-  exit 1
-fi
-. common/gst-autogen.sh
-
-# install pre-commit hook for doing clean commits
-if test ! \( -x .git/hooks/pre-commit -a -L .git/hooks/pre-commit \);
-then
-    rm -f .git/hooks/pre-commit
-    if ! ln -s ../../common/hooks/pre-commit.hook .git/hooks/pre-commit 2> /dev/null
-    then
-        echo "Failed to create commit hook symlink, copying instead ..."
-        cp common/hooks/pre-commit.hook .git/hooks/pre-commit
-    fi
-fi
-
-# GNU gettext automake support doesn't get along with git.
-# https://bugzilla.gnome.org/show_bug.cgi?id=661128
-if test -d po ; then
-  touch -t 200001010000 po/gstreamer-1.0.pot
-fi
-
-CONFIGURE_DEF_OPT='--enable-maintainer-mode --enable-gtk-doc'
-
-if test "x$package" = "xgstreamer"; then
-  CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --enable-failing-tests --enable-poisoning"
-elif test "x$package" = "xgst-plugins-bad"; then
-  CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-player-tests"
-fi
-
-autogen_options $@
-
-printf "+ check for build tools"
-if test -z "$NOCHECK"; then
-  echo
-
-  printf "  checking for autoreconf ... "
-  echo
-  which "autoreconf" 2>/dev/null || {
-    echo "not found! Please install the autoconf package."
-    exit 1
-  }
-
-  printf "  checking for pkg-config ... "
-  echo
-  which "pkg-config" 2>/dev/null || {
-    echo "not found! Please install pkg-config."
-    exit 1
-  }
-else
-  echo ": skipped version checks"
-fi
-
-# if no arguments specified then this will be printed
-if test -z "$*" && test -z "$NOCONFIGURE"; then
-  echo "+ checking for autogen.sh options"
-  echo "  This autogen script will automatically run ./configure as:"
-  echo "  ./configure $CONFIGURE_DEF_OPT"
-  echo "  To pass any additional options, please specify them on the $0"
-  echo "  command line."
-fi
-
-toplevel_check $srcfile
-
-# autopoint
-if test -d po && grep ^AM_GNU_GETTEXT_VERSION configure.ac >/dev/null ; then
-  tool_run "autopoint" "--force"
-fi
-
-# aclocal
-if test -f acinclude.m4; then rm acinclude.m4; fi
-
-autoreconf --force --install || exit 1
-
-test -n "$NOCONFIGURE" && {
-  echo "+ skipping configure stage for package $package, as requested."
-  echo "+ autogen.sh done."
-  exit 0
-}
-
-cd "$olddir"
-
-echo "+ running configure ... "
-test ! -z "$CONFIGURE_DEF_OPT" && echo "  default flags:  $CONFIGURE_DEF_OPT"
-test ! -z "$CONFIGURE_EXT_OPT" && echo "  external flags: $CONFIGURE_EXT_OPT"
-echo
-
-echo "$srcdir/configure" $CONFIGURE_DEF_OPT $CONFIGURE_EXT_OPT
-"$srcdir/configure" $CONFIGURE_DEF_OPT $CONFIGURE_EXT_OPT || {
-        echo "  configure failed"
-        exit 1
-}
-
-echo "Now type 'make' to compile $package."
diff --git a/common b/common
deleted file mode 160000 (submodule)
index 59cb678..0000000
--- a/common
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 59cb678164719ff59dcf6c8b93df4617a1075d11
diff --git a/configure.ac b/configure.ac
deleted file mode 100644 (file)
index 712536b..0000000
+++ /dev/null
@@ -1,1239 +0,0 @@
-AC_PREREQ([2.69])
-
-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
-dnl
-AC_INIT([GStreamer],[1.16.2],[http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer],[gstreamer])
-AG_GST_INIT
-
-dnl initialize automake (we require GNU make)
-AM_INIT_AUTOMAKE([-Wno-portability 1.14 no-dist-gzip dist-xz tar-ustar subdir-objects])
-
-dnl define PACKAGE_VERSION_* variables
-AS_VERSION
-
-dnl check if this is a release version
-AS_NANO(GST_GIT="no", GST_GIT="yes")
-
-dnl can autoconf find the source ?
-AC_CONFIG_SRCDIR([gst/gst.c])
-
-dnl define the output header for config
-AC_CONFIG_HEADERS([config.h])
-
-dnl AM_MAINTAINER_MODE only provides the option to configure to enable it
-AM_MAINTAINER_MODE([enable])
-
-dnl sets host_* variables
-AC_CANONICAL_HOST
-
-dnl use pretty build output by default
-AM_SILENT_RULES([yes])
-
-dnl GStreamer versioning, this is mostly informational
-GST_VERSION_MAJOR=$PACKAGE_VERSION_MAJOR
-GST_VERSION_MINOR=$PACKAGE_VERSION_MINOR
-GST_VERSION_MICRO=$PACKAGE_VERSION_MICRO
-GST_VERSION_NANO=$PACKAGE_VERSION_NANO
-AC_SUBST(GST_VERSION_MAJOR)
-AC_SUBST(GST_VERSION_MINOR)
-AC_SUBST(GST_VERSION_MICRO)
-AC_SUBST(GST_VERSION_NANO)
-
-dnl our libraries and install dirs use GST_API_VERSION in the filename
-dnl to allow side-by-side installation of different API versions
-GST_API_VERSION=1.0
-AC_SUBST(GST_API_VERSION)
-AC_DEFINE_UNQUOTED(GST_API_VERSION, "$GST_API_VERSION",
-  [GStreamer API Version])
-
-dnl CURRENT, REVISION, AGE
-dnl - library source changed -> increment REVISION
-dnl - interfaces added/removed/changed -> increment CURRENT, REVISION = 0
-dnl - interfaces added -> increment AGE
-dnl - interfaces removed -> AGE = 0
-dnl
-dnl Keep CURRENT as MINOR * 100 + MICRO
-dnl Ex : 1.0.0 => 0
-dnl      1.0.3 => 3
-dnl      1.1.0 => 100
-dnl      1.2.5 => 205
-dnl      1.10.9 (who knows) => 1009
-dnl
-dnl sets GST_LT_LDFLAGS
-AS_LIBTOOL(GST, 1602, 0, 1602)
-
-dnl *** autotools stuff ****
-
-dnl allow for different autotools
-AS_AUTOTOOLS_ALTERNATE
-
-dnl Add parameters for aclocal (keep in sync with Makefile.am)
-AC_SUBST(ACLOCAL_AMFLAGS, "-I m4 -I common/m4")
-
-dnl set up gettext
-dnl the version check needs to stay here because autopoint greps for it
-AM_GNU_GETTEXT_VERSION([0.17])
-AM_GNU_GETTEXT([external])
-AG_GST_GETTEXT([gstreamer-$GST_API_VERSION])
-
-dnl *** check for arguments to configure ***
-
-AG_GST_ARG_DISABLE_FATAL_WARNINGS
-AG_GST_ARG_ENABLE_EXTRA_CHECKS
-
-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(GST_TRACER_HOOKS,[tracing subsystem hooks])
-AM_CONDITIONAL(GST_DISABLE_GST_TRACER_HOOKS, test "x$GST_DISABLE_GST_TRACER_HOOKS" = "xyes")
-if test "x$GST_DISABLE_GST_TRACER_HOOKS" = xyes; then
-  AC_DEFINE(GST_DISABLE_GST_TRACER_HOOKS, 1,
-    [Define if tracing subsystem hooks is disabled])
-fi
-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
-  AC_DEFINE(GST_DISABLE_PARSE, 1,
-    [Define if pipeline parsing code is disabled])
-fi
-AG_GST_CHECK_SUBSYSTEM_DISABLE(OPTION_PARSING,[option parsing when gst_init])
-AM_CONDITIONAL(GST_DISABLE_OPTION_PARSING, test "x$GST_DISABLE_OPTION_PARSING" = "xyes")
-if test "x$GST_DISABLE_OPTION_PARSING" = xyes; then
-  AC_DEFINE(GST_DISABLE_OPTION_PARSING, 1,
-    [Define if option parsing is disabled])
-fi
-AG_GST_CHECK_SUBSYSTEM_DISABLE(REGISTRY,[plugin registry])
-AM_CONDITIONAL(GST_DISABLE_REGISTRY, test "x$GST_DISABLE_REGISTRY" = "xyes")
-dnl define a substitution to use in docs/gst/gstreamer.types
-if test "x$GST_DISABLE_REGISTRY" = "xyes"
-then
-  GST_REGISTRY_DOC_TYPES="%"
-else
-  GST_REGISTRY_DOC_TYPES=
-fi
-AC_SUBST(GST_REGISTRY_DOC_TYPES)
-AG_GST_CHECK_SUBSYSTEM_DISABLE(PLUGIN,[plugin])
-AM_CONDITIONAL(GST_DISABLE_PLUGIN, test "x$GST_DISABLE_PLUGIN" = "xyes")
-
-GST_DISABLE_CAST_CHECKS_DEFINE=0
-AC_SUBST(GST_DISABLE_CAST_CHECKS_DEFINE)
-
-GST_DISABLE_GLIB_ASSERTS_DEFINE=0
-AC_SUBST(GST_DISABLE_GLIB_ASSERTS_DEFINE)
-
-GST_DISABLE_GLIB_CHECKS_DEFINE=0
-AC_SUBST(GST_DISABLE_GLIB_CHECKS_DEFINE)
-
-
-AG_GST_ARG_DEBUG
-AG_GST_ARG_PROFILING
-AG_GST_ARG_VALGRIND
-AG_GST_ARG_GCOV
-
-AG_GST_ARG_EXAMPLES
-
-AG_GST_ARG_WITH_PKG_CONFIG_PATH
-AG_GST_ARG_WITH_PACKAGE_NAME
-AG_GST_ARG_WITH_PACKAGE_ORIGIN
-
-AG_GST_PKG_CONFIG_PATH
-
-AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO([$PACKAGE_VERSION_NANO],
-  ["${srcdir}/gstreamer.doap"],
-  [$PACKAGE_VERSION_MAJOR.$PACKAGE_VERSION_MINOR.$PACKAGE_VERSION_MICRO])
-
-# We only use this when building with MSVC, which is only done with the
-# alternate Meson build system files
-GSTCONFIG_BUILT_WITH_MSVC=0
-AC_SUBST(GSTCONFIG_BUILT_WITH_MSVC)
-
-dnl check for bash completion
-AC_ARG_WITH([bash-completion-dir],
-    AS_HELP_STRING([--with-bash-completion-dir[=PATH]],
-        [Install the bash auto-completion script in this directory. @<:@default=no@:>@]),
-    [],
-    [with_bash_completion_dir=no])
-
-if test "x$with_bash_completion_dir" = "xyes"
-then
-    extra_args=
-
-    if test "x$prefix" != "xNONE"
-    then
-        extra_args="--define-variable=prefix=\"$prefix\""
-    fi
-
-    PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0],
-        [
-          BASH_COMPLETION_DIR="`eval pkg-config $extra_args --variable=completionsdir bash-completion`"
-          BASH_HELPERS_DIR="`eval pkg-config $extra_args --variable=helpersdir bash-completion`"
-        ],
-        [
-          BASH_COMPLETION_DIR="$datadir/bash-completion/completions"
-          BASH_HELPERS_DIR="$datadir/bash-completion/helpers"
-        ])
-else
-    BASH_COMPLETION_DIR="$with_bash_completion_dir/completions"
-    BASH_HELPERS_DIR="$with_bash_completion_dir/helpers"
-fi
-
-AC_SUBST([BASH_COMPLETION_DIR])
-AC_SUBST([BASH_HELPERS_DIR])
-AM_CONDITIONAL([ENABLE_BASH_COMPLETION],[test "x$with_bash_completion_dir" != "xno"])
-
-dnl If only building static libraries, define GST_STATIC_COMPILATION. This is
-dnl needed only on Windows, but it doesn't hurt to have it everywhere.
-if test x$enable_static = xyes -a x$enable_shared = xno; then
-  GST_OBJ_STATIC_CFLAGS="-DGST_STATIC_COMPILATION"
-fi
-
-dnl building of tests
-AC_ARG_ENABLE(tests,
-  AS_HELP_STRING([--disable-tests],[disable building test apps]),
-  [
-    case "${enableval}" in
-      yes) BUILD_TESTS=yes ;;
-      no)  BUILD_TESTS=no ;;
-      *)   AC_MSG_ERROR(bad value ${enableval} for --disable-tests) ;;
-    esac
-  ],
-[BUILD_TESTS=yes]) dnl Default value
-AM_CONDITIONAL(BUILD_TESTS,         test "x$BUILD_TESTS" = "xyes")
-
-dnl tests known to fail
-AC_ARG_ENABLE(failing-tests,
-  AS_HELP_STRING([--disable-failing-tests],[disable building tests known to fail]),
-  [
-    case "${enableval}" in
-      yes) BUILD_FAILING_TESTS=yes ;;
-      no)  BUILD_FAILING_TESTS=no ;;
-      *)   AC_MSG_ERROR(bad value ${enableval} for --disable-failing-tests) ;;
-    esac
-  ],
-  [BUILD_FAILING_TESTS=no]) dnl Default value
-AM_CONDITIONAL(BUILD_FAILING_TESTS, test "x$BUILD_FAILING_TESTS" = "xyes")
-if test x$BUILD_FAILING_TESTS = xyes; then
-  AC_MSG_WARN([building tests known to fail, use --disable-failing-tests to disable])
-else
-  AC_MSG_WARN([Sissy ! By asking to not build the tests known to fail, you hereby waive your right to customer support.  If you do not agree with this EULA, please press Ctrl-C before the next line is printed.  By allowing the next line to be printed, you expressly acknowledge your acceptance of this EULA.])
-fi
-
-dnl building of benchmarks
-AC_ARG_ENABLE(benchmarks,
-  AS_HELP_STRING([--disable-benchmarks],[disable building benchmarks apps]),
-  [
-    case "${enableval}" in
-      yes) BUILD_BENCHMARKS=yes ;;
-      no)  BUILD_BENCHMARKS=no ;;
-      *)   AC_MSG_ERROR(bad value ${enableval} for --disable-benchmarks) ;;
-    esac
-  ],
-[BUILD_BENCHMARKS=yes]) dnl Default value
-AM_CONDITIONAL(BUILD_BENCHMARKS, test "x$BUILD_BENCHMARKS" = "xyes")
-
-dnl building of tools
-AC_ARG_ENABLE(tools,
-  AS_HELP_STRING([--disable-tools],[disable building tools]),
-  [
-    case "${enableval}" in
-      yes) BUILD_TOOLS=yes ;;
-      no)  BUILD_TOOLS=no ;;
-      *)   AC_MSG_ERROR(bad value ${enableval} for --disable-tools) ;;
-    esac
-  ],
-[BUILD_TOOLS=yes]) dnl Default value
-AM_CONDITIONAL(BUILD_TOOLS, test "x$BUILD_TOOLS" = "xyes")
-
-dnl poison destroyed objects
-AC_ARG_ENABLE(poisoning,
-  AS_HELP_STRING([--enable-poisoning],[enable poisoning of deallocated objects]),
-  [
-    case "${enableval}" in
-      yes) USE_POISONING=yes ;;
-      no)  USE_POISONING=no ;;
-      *)   AC_MSG_ERROR(bad value ${enableval} for --enable-poisoning) ;;
-    esac
-  ],
-  [USE_POISONING=$GST_GIT]) dnl Default value
-if test "x$USE_POISONING" = xyes; then
-  AC_DEFINE(USE_POISONING, 1,
-    [Define if we should poison deallocated memory])
-fi
-
-dnl PTP support parts
-AC_MSG_CHECKING([whether PTP support can be enabled])
-case "$host_os" in
-  *android*)
-    dnl Can't run on Android because of permissions
-    HAVE_PTP=no
-    ;;
-  mingw*|pw32*|cygwin*)
-    dnl Not ported to Windows yet
-    HAVE_PTP=no
-    ;;
-  darwin*)
-    dnl Can't run on iOS because of permissions
-    AC_CHECK_HEADER(MobileCoreServices/MobileCoreServices.h, HAVE_PTP="no", HAVE_PTP="yes", [-])
-    ;;
-  linux*|darwin*|solaris*|netbsd*|freebsd*|openbsd*|kfreebsd*|dragonfly*|gnu*)
-    HAVE_PTP=yes
-    ;;
-  *)
-    HAVE_PTP=no
-    ;;
-esac
-AC_MSG_RESULT([$HAVE_PTP])
-
-dnl user/group to change to in gst-ptp-helper
-AC_ARG_WITH([ptp-helper-setuid-user],
-  AS_HELP_STRING([--with-ptp-helper-setuid-user],[User to switch to when installing gst-ptp-helper setuid root]),
-  [
-    if test "x$withval" != "x"
-    then
-      AC_DEFINE_UNQUOTED(HAVE_PTP_HELPER_SETUID_USER, "$withval", [PTP helper setuid user])
-    fi
-  ], []
-)
-
-dnl group/group to change to in gst-ptp-helper
-AC_ARG_WITH([ptp-helper-setuid-group],
-  AS_HELP_STRING([--with-ptp-helper-setuid-group],[Group to switch to when installing gst-ptp-helper setuid root]),
-  [
-    if test "x$withval" != "x"
-    then
-      AC_DEFINE_UNQUOTED(HAVE_PTP_HELPER_SETUID_GROUP, "$withval", [PTP helper setuid group])
-    fi
-  ], []
-)
-
-AC_ARG_WITH(
-  ptp-helper-permissions,
-  AC_HELP_STRING(
-    [--with-ptp-helper-permissions],
-    [how to gain PTP permissions (none, setuid-root, capabilities, auto)]),
-    [],
-    [with_ptp_helper_permissions=auto])
-
-gst_ptp_have_cap=no
-AG_GST_CHECK_LIBHEADER(CAP, cap,
-                       cap_init, ,
-                       sys/capability.h,
-                       CAP_LIBS="-lcap"
-                       AC_SUBST(CAP_LIBS)
-                       gst_ptp_have_cap=yes)
-
-AC_PATH_PROG([SETCAP], [setcap], [no], [$PATH:/usr/bin:/bin:/usr/sbin:/sbin])
-
-if test "x$HAVE_PTP" = "xyes"; then
-AC_DEFINE(HAVE_PTP, 1, [PTP support available])
-
-AC_MSG_CHECKING([for SIOCGIFCONF, SIOCGIFFLAGS and SIOCGIFHWADDR])
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
-    [[
-        #include <sys/ioctl.h>
-        #include <net/if.h>
-    ]],
-    [[
-        struct ifreq ifr;
-        struct ifconf ifc;
-        ioctl(0, SIOCGIFCONF, &ifc);
-        ioctl(0, SIOCGIFFLAGS, &ifr);
-        ioctl(0, SIOCGIFHWADDR, &ifr);
-        int dummy = ifr.ifr_hwaddr.sa_data[0];
-    ]])], [
-        AC_MSG_RESULT(yes)
-        AC_DEFINE(HAVE_SIOCGIFCONF_SIOCGIFFLAGS_SIOCGIFHWADDR, 1, [SIOCGIFCONF, SIOCGIFFLAGS and SIOCGIFHWADDR is available])
-    ], [
-        AC_MSG_RESULT(no)
-])
-
-AC_MSG_CHECKING([for getifaddrs() and AF_LINK])
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
-    [[
-        #include <ifaddrs.h>
-        #include <net/if.h>
-        #include <net/if_dl.h>
-    ]],
-    [[
-        struct ifaddrs *ifaddr;
-        getifaddrs(&ifaddr);
-        int dummy = (ifaddr->ifa_flags & IFF_LOOPBACK) && ifaddr->ifa_addr->sa_family != AF_LINK;
-    ]])], [
-        AC_MSG_RESULT(yes)
-        AC_DEFINE(HAVE_GETIFADDRS_AF_LINK, 1, [getifaddrs() and AF_LINK is available])
-    ], [
-        AC_MSG_RESULT(no)
-    ])
-
-AC_MSG_CHECKING([how to install gst-ptp-helper])
-if test "x$with_ptp_helper_permissions" = "xauto"; then
-    if test "x$gst_ptp_have_cap" = "xyes" -a "x$SETCAP" != "xno"; then
-        with_ptp_helper_permissions="capabilities"
-    else
-        with_ptp_helper_permissions="setuid-root"
-    fi
-fi
-AC_MSG_RESULT([$with_ptp_helper_permissions])
-
-case "$with_ptp_helper_permissions" in
-  none)
-    ;;
-  setuid-root)
-     AC_DEFINE(HAVE_PTP_HELPER_SETUID, 1,
-        [Use setuid-root for permissions in PTP helper])
-    ;;
-  capabilities)
-     AC_DEFINE(HAVE_PTP_HELPER_CAPABILITIES, 1,
-        [Use capabilities for permissions in PTP helper])
-    ;;
-  *)
-    AC_MSG_ERROR(Invalid parameter [$with_ptp_helper_permissions])
-    ;;
-esac
-
-fi
-
-AM_CONDITIONAL(HAVE_PTP, test "x$HAVE_PTP" = "xyes")
-AM_CONDITIONAL(HAVE_PTP_HELPER_SETUID, test "x$with_ptp_helper_permissions" = "xsetuid-root")
-AM_CONDITIONAL(HAVE_PTP_HELPER_CAPABILITIES, test "x$with_ptp_helper_permissions" = "xcapabilities")
-
-dnl *** checks for platform ***
-
-dnl * hardware/architecture *
-
-dnl common/m4/gst-arch.m4
-dnl check CPU type
-AG_GST_ARCH
-
-dnl check for platform specific settings
-AG_GST_PLATFORM
-
-dnl * software *
-
-dnl check for large file support
-dnl affected plugins must include config.h
-AC_SYS_LARGEFILE
-
-dnl *** checks for programs ***
-
-dnl find a compiler
-AC_PROG_CC
-AC_PROG_CC_STDC
-
-dnl check if the compiler supports '-c' and '-o' options
-AM_PROG_CC_C_O
-
-dnl find an assembler
-AM_PROG_AS
-
-dnl determine if c++ is available on this system
-AC_PROG_CXX
-dnl CXX may be set to some default even if no c++ compiler is available
-dnl (thanks autotools!), so just try to compile some c++ code to make sure
-AC_LANG_PUSH([C++])
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ class Foo { int bar; };]], [[]])],[working_cxx=yes],[working_cxx=no])
-AC_LANG_POP([C++])
-AC_MSG_NOTICE([working c++ compiler found: $working_cxx])
-AM_CONDITIONAL(HAVE_CXX, test "x$working_cxx" = "xyes")
-
-dnl Perl is used in building documentation and in the version checks
-AC_PATH_PROG(PERL_PATH, perl, no)
-if test x$PERL_PATH = xno; then
-  AC_MSG_ERROR(Could not find perl)
-fi
-
-dnl we require flex and bison for building the parser
-if test "x$GST_DISABLE_PARSE" != xyes; then
-  AG_GST_BISON_CHECK
-  AG_GST_FLEX_CHECK
-fi
-
-AC_PATH_PROG(VALGRIND_PATH, valgrind, no)
-AM_CONDITIONAL(HAVE_VALGRIND, test ! "x$VALGRIND_PATH" = "xno")
-
-dnl check for gobject-introspection
-GOBJECT_INTROSPECTION_CHECK([1.31.1])
-
-dnl check for documentation tools
-GTK_DOC_CHECK([1.12])
-AG_GST_PLUGIN_DOCS([1.12])
-
-dnl *** checks for libraries ***
-
-dnl check for libm, for sin()
-LT_LIB_M
-AC_SUBST(LIBM)
-
-dnl *** checks for header files ***
-
-dnl check if we have ANSI C header files
-AC_HEADER_STDC
-
-dnl Check for ucontext.h
-AC_CHECK_HEADERS([ucontext.h], [], [], [AC_INCLUDES_DEFAULT])
-
-dnl Check for sys/socket.h
-AC_CHECK_HEADERS([sys/socket.h], [HAVE_SYS_SOCKET_H=yes], [HAVE_SYS_SOCKET_H=no], [AC_INCLUDES_DEFAULT])
-AM_CONDITIONAL(HAVE_SYS_SOCKET_H, test "x$HAVE_SYS_SOCKET_H" = "xyes")
-
-dnl check for sys/times.h for tests/examples/adapter/
-AC_CHECK_HEADERS([sys/times.h], [HAVE_SYS_TIMES_H=yes], [HAVE_SYS_TIME_H=no], [AC_INCLUDES_DEFAULT])
-AC_CHECK_HEADERS([unistd.h], [HAVE_UNISTD_H=yes], [HAVE_UNISTD_H=no], [AC_INCLUDES_DEFAULT])
-AM_CONDITIONAL(HAVE_SYS_TIMES_H_AND_UNISTD_H, test "x$HAVE_SYS_TIMES_H" = "xyes" -a "x$HAVE_UNISTD_H" = "xyes")
-
-dnl Check for process.h for getpid() on win32
-AC_CHECK_HEADERS([process.h], [], [], [AC_INCLUDES_DEFAULT])
-
-dnl Check for sys/utsname.h for uname
-AC_CHECK_HEADERS([sys/utsname.h], [], [], [AC_INCLUDES_DEFAULT])
-
-dnl Check for stdio_ext.f for __fbufsize
-AC_CHECK_HEADERS([stdio_ext.h], [], [], [AC_INCLUDES_DEFAULT])
-
-dnl check for pthreads
-dnl without arguments AX_PTHREAD() will do AC_DEFINE(HAVE_PTHREAD)
-dnl which later checks use in their test code
-AX_PTHREAD()
-AM_CONDITIONAL(HAVE_PTHREAD, test "x$ax_pthread_ok" = "xyes")
-
-dnl check for sys/prctl for setting thread name on Linux
-AC_CHECK_HEADERS([sys/prctl.h], [], [], [AC_INCLUDES_DEFAULT])
-
-dnl check for pthread_setname_np(const char*)
-dnl which is present on OS X 10.6, iOS 3.2 and above
-AC_MSG_CHECKING(for pthread_setname_np(const char*))
-AC_LINK_IFELSE(
-    [AC_LANG_PROGRAM(
-        [#include <pthread.h>],
-        [pthread_setname_np("example")])],
-    [AC_MSG_RESULT(yes)
-     AC_DEFINE(HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID,1,
-        [Have function pthread_setname_np(const char*)])],
-    [AC_MSG_RESULT(no)])
-
-dnl check for sys/uio.h for writev()
-AC_CHECK_HEADERS([sys/uio.h], [], [], [AC_INCLUDES_DEFAULT])
-
-dnl Check for valgrind.h
-dnl separate from HAVE_VALGRIND because you can have the program, but not
-dnl the dev package
-AC_CHECK_HEADERS([valgrind/valgrind.h], [], [], [AC_INCLUDES_DEFAULT])
-
-dnl used in gst/gstpoll.c
-AC_CHECK_HEADERS([winsock2.h], [HAVE_WINSOCK2_H=yes], [HAVE_WINSOCK2_H=no], [AC_INCLUDES_DEFAULT])
-AM_CONDITIONAL(HAVE_WINSOCK2_H, test "x$HAVE_WINSOCK2_H" = "xyes")
-if test "x$HAVE_WINSOCK2_H" = "xyes"; then
-  WIN32_LIBS="-lws2_32"
-  AC_SUBST(WIN32_LIBS)
-fi
-
-dnl check for GMP/GSL, used by the gst_util_uint64_scale unit test only
-if test "x$BUILD_TESTS" = "xyes"; then
-  AG_GST_CHECK_LIBHEADER(GMP, gmp,
-                         __gmpz_init_set_d, ,
-                         gmp.h,
-                         GMP_LIBS="-lgmp"
-                         AC_SUBST(GMP_LIBS)
-                         AC_DEFINE(HAVE_GMP, [1],[Have GMP library]))
-  AG_GST_CHECK_LIBHEADER(GSL, gsl,
-                         gsl_rng_uniform_int, -lgslcblas,
-                         gsl/gsl_rng.h,
-                         GSL_LIBS="-lgsl -lgslcblas"
-                         AC_SUBST(GSL_LIBS)
-                         AC_DEFINE(HAVE_GSL, [1],[Have GSL library]))
-fi
-
-dnl *** checks for types/defines ***
-
-dnl *** checks for structures ***
-
-dnl *** checks for compiler characteristics ***
-
-dnl check if the compiler supports __uint128_t (gcc)
-dnl Actually check for 128-bit division, since that's what we use
-dnl uint128_t for.
-AC_CACHE_CHECK(for __uint128_t, gst_cv_uint128_t,
-    AC_LINK_IFELSE([AC_LANG_PROGRAM([[ ]], [[
-      static __uint128_t v1 = 100;
-      static __uint128_t v2 = 10;
-      static __uint128_t u;
-      u = v1 / v2;
-    ]])],[
-      gst_cv_uint128_t=yes
-    ],[
-      gst_cv_uint128_t=no
-    ])
-)
-if test x$gst_cv_uint128_t = xyes; then
-  AC_DEFINE(HAVE_UINT128_T, 1, [Have __uint128_t type])
-fi
-
-dnl *** checking for tm_gmtoff ***
-AC_MSG_CHECKING([for tm_gmtoff])
-AC_RUN_IFELSE([AC_LANG_SOURCE([[
-       #include <time.h>
-       int main(void) {
-         struct tm t;
-         t.tm_gmtoff = 0;
-         exit(0);
-       }]])],
-  [have_tm_gmtoff=yes
-   AC_DEFINE(HAVE_TM_GMTOFF,1,[Have tm_gmtoff field in struct tm])],
-  [have_tm_gmtoff=no],
-  [have_tm_gmtoff="no (cross compiling)"])
-AC_MSG_RESULT($have_tm_gmtoff)
-
-
-dnl *** checks for library functions ***
-
-AC_CHECK_FUNCS([strcasestr])
-
-AC_CHECK_FUNCS([gmtime_r])
-AC_CHECK_FUNCS([localtime_r])
-AC_CHECK_FUNCS([sigaction])
-AC_CHECK_FUNCS([getrusage])
-AM_CONDITIONAL(HAVE_GETRUSAGE, test "x$ac_cv_func_getrusage" = "xyes")
-AC_CHECK_HEADERS([sys/resource.h])
-
-dnl check for fseeko()
-AC_FUNC_FSEEKO
-dnl check for ftello()
-AC_CHECK_FUNCS([ftello])
-
-AC_CHECK_FUNCS([fgetpos])
-AC_CHECK_FUNCS([fsetpos])
-
-dnl check for poll(), ppoll() and pselect()
-AC_CHECK_HEADERS([sys/poll.h], [], [], [AC_INCLUDES_DEFAULT])
-AC_CHECK_HEADERS([poll.h], [], [], [AC_INCLUDES_DEFAULT])
-AC_CHECK_FUNCS([poll])
-AC_CHECK_FUNCS([ppoll])
-AC_CHECK_FUNCS([pselect])
-
-dnl check for socketpair()
-AC_CHECK_FUNC(socketpair, [], [
-  AC_CHECK_LIB(socket, socketpair, [
-    SOCKET_LIBS="-lsocket"
-    AC_SUBST(SOCKET_LIBS)
-  ])
-])
-
-dnl ****************************************
-dnl *** GLib POLL* compatibility defines ***
-dnl ****************************************
-
-AC_MSG_CHECKING([for broken poll])
-AC_RUN_IFELSE([AC_LANG_SOURCE([[
-       #include <stdlib.h>
-       #include <fcntl.h>
-       #ifdef HAVE_SYS_POLL_H
-       #include <sys/poll.h>
-       #endif
-       #ifdef HAVE_POLL_H
-       #include <poll.h>
-       #endif
-       int main(void) {
-         struct pollfd fds[1];
-         int fd;
-         fd = open("/dev/null", 1);
-         fds[0].fd = fd;
-         fds[0].events = POLLIN;
-         fds[0].revents = 0;
-         if (poll(fds, 1, 0) < 0 || (fds[0].revents & POLLNVAL) != 0) {
-               exit(1);  /* Does not work for devices -- fail */
-         }
-         exit(0);
-       }]])],
-  [broken_poll=no],
-  [broken_poll=yes
-   AC_DEFINE(BROKEN_POLL,1,[poll doesn't work on devices])],
-  [broken_poll="no (cross compiling)"])
-AC_MSG_RESULT($broken_poll)
-
-dnl check for getpagesize()
-AC_CHECK_FUNCS([getpagesize])
-
-dnl Check for POSIX timers
-CLOCK_GETTIME_FOUND="no"
-AC_CHECK_FUNC(clock_gettime, [CLOCK_GETTIME_FOUND="yes"], [
-  AC_CHECK_LIB(rt, clock_gettime, [
-    CLOCK_GETTIME_FOUND="yes"
-    LIBS="$LIBS -lrt"
-  ], [
-    AC_CHECK_LIB(pthread, clock_gettime, [
-      CLOCK_GETTIME_FOUND="yes"
-      LIBS="$LIBS -lpthread"
-    ])
-  ])
-])
-
-# With XCode 8, clock_gettime will be incorrectly detected as being available
-# regardless of what version of OS X you target because the symbol is available
-# in the .tbd file as a weak symbol.
-# See: https://bugzilla.gnome.org/show_bug.cgi?id=772451
-#
-# We cannot simply do AC_CHECK_FUNCS with -Wl,-no_weak_imports because the
-# autoconf check does its own prototype declaration that doesn't trigger that
-# compiler flag.
-#
-# It's only starting from macOS 10.12 and iOS 10.0 that clock_gettime is
-# actually available, so we can unconditionally disable it for older versions.
-case "$host_os" in
-  darwin*)
-    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
-#include <AvailabilityMacros.h>
-#include <TargetConditionals.h>
-#if defined(TARGET_OS_MAC)
-#  if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12
-#    error "Not compiling for OS X 10.12 or later"
-#  endif
-#else
-#  if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0
-#    error "Not compiling for iOS 10.0 or later"
-#  endif
-#endif
-    ]])], [], [
-    if test "$CLOCK_GETTIME_FOUND" = "yes"; then
-      AC_MSG_NOTICE([Disabling incorrectly detected clock_gettime on OS X])
-    fi
-    CLOCK_GETTIME_FOUND="no"
-    ])
-    ;;
-esac
-
-if test "$CLOCK_GETTIME_FOUND" = "yes"; then
-  AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Have clock_gettime])
-fi
-
-AC_CACHE_CHECK(for posix timers, gst_cv_posix_timers,
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#include <time.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-    ]], [[
-#if !defined(_POSIX_TIMERS) || _POSIX_TIMERS < 0 || !defined(CLOCK_REALTIME)
-#error Either _POSIX_TIMERS or CLOCK_REALTIME not defined
-#endif
-    ]])],[
-      gst_cv_posix_timers=yes
-    ],[
-      gst_cv_posix_timers=no
-    ])
-)
-
-if test "$gst_cv_posix_timers" = "yes"; then
-  AC_DEFINE(HAVE_POSIX_TIMERS,1,[Have posix timers])
-  GST_HAVE_POSIX_TIMERS_DEFINE="#define GST_HAVE_POSIX_TIMERS 1"
-else
-  GST_HAVE_POSIX_TIMERS_DEFINE="#define GST_HAVE_POSIX_TIMERS 0"
-fi
-AC_SUBST(GST_HAVE_POSIX_TIMERS_DEFINE)
-AM_CONDITIONAL(GST_HAVE_POSIX_TIMERS, test "$gst_cv_posix_timers" = "yes")
-
-AC_CACHE_CHECK(for monotonic clock, gst_cv_monotonic_clock,
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#include <time.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-    ]], [[
-#if !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK < 0 || !defined(CLOCK_MONOTONIC)
-#error Either _POSIX_MONOTONIC_CLOCK or CLOCK_MONOTONIC not defined
-#endif
-    ]])],[
-      gst_cv_monotonic_clock=yes
-    ],[
-      gst_cv_monotonic_clock=no
-    ])
-)
-
-if test "$gst_cv_monotonic_clock" = "yes"; then
-  AC_DEFINE(HAVE_MONOTONIC_CLOCK,1,[Have a monotonic clock])
-  GST_HAVE_MONOTONIC_CLOCK_DEFINE="#define GST_HAVE_MONOTONIC_CLOCK 1"
-else
-  GST_HAVE_MONOTONIC_CLOCK_DEFINE="#define GST_HAVE_MONOTONIC_CLOCK 0"
-fi
-AC_SUBST(GST_HAVE_MONOTONIC_CLOCK_DEFINE)
-AM_CONDITIONAL(GST_HAVE_MONOTONIC_CLOCK, test "$gst_cv_monotonic_clock" = "yes")
-
-dnl Check for a way to display the function name in debug output
-AG_GST_CHECK_FUNCTION
-
-dnl test if we have dladdr(); we use it for debugging; see gst/gstinfo.c
-save_cflags="$CFLAGS"
-CFLAGS="$CFLAGS -D_GNU_SOURCE"
-AC_CHECK_LIB(dl, dladdr,
-   AC_DEFINE(HAVE_DLADDR, 1, [Defined if we have dladdr ()])
-   LIBS="$LIBS -ldl")
-CFLAGS="$save_cflags"
-
-dnl Check printf stuff
-if test "x${GST_DISABLE_GST_DEBUG}" != "xyes"; then
-  AC_TYPE_LONG_LONG_INT
-  AC_TYPE_UNSIGNED_LONG_LONG_INT
-
-  if test x$ac_cv_type_long_long_int$ac_cv_type_unsigned_long_long_int = xyesyes; then
-    AC_DEFINE([HAVE_LONG_LONG], [1], [Define to 1 if the system has the type long long])
-  fi
-
-  dnl /usr/share/aclocal/inttypes_h.m4 - ships with gettext apparently
-  gl_AC_HEADER_INTTYPES_H
-
-  dnl /usr/share/aclocal/stdint_h.m4 - ships with gettext apparently
-  gl_AC_HEADER_STDINT_H
-
-  AC_CHECK_TYPES(ptrdiff_t)
-
-  AC_TYPE_INTMAX_T
-  AC_TYPE_SIZE_T
-fi
-
-dnl *** checks for dependency libraries ***
-
-dnl GLib
-GLIB_REQ=2.40.0
-AG_GST_GLIB_CHECK([$GLIB_REQ])
-
-dnl Check for documentation xrefs
-GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`"
-AC_SUBST(GLIB_PREFIX)
-
-dnl GTK is optional and only used in examples
-HAVE_GTK=no
-GTK_REQ=3.10
-if test "x$BUILD_EXAMPLES" = "xyes"; then
-  PKG_CHECK_MODULES(GTK, gtk+-3.0 >= $GTK_REQ, HAVE_GTK=yes, HAVE_GTK=no)
-  AC_SUBST(GTK_LIBS)
-  AC_SUBST(GTK_CFLAGS)
-fi
-AM_CONDITIONAL(HAVE_GTK, test "x$HAVE_GTK" = "xyes")
-
-dnl libunwind is optionally used by the leaks tracer
-AC_ARG_WITH([unwind],[AS_HELP_STRING([--with-unwind=yes|no|auto],[use libunwind])],
-            [], [with_unwind=auto])
-if [ test "x${with_unwind}" != "xno" ]; then
-  PKG_CHECK_MODULES(UNWIND, [libunwind],
-      [
-        HAVE_UNWIND=yes
-        AC_DEFINE(HAVE_UNWIND, 1, [libunwind available])
-        UNWIND_REQUIRE=libunwind
-        AC_SUBST(UNWIND_REQUIRE)
-      ],
-      [
-        HAVE_UNWIND=no
-        if [ test "x${with_unwind}" = "xyes" ]; then
-          AC_MSG_ERROR([could not find libunwind])
-        fi
-      ])
-else
-  HAVE_UNWIND=no
-fi
-
-dnl libdw is optionally used to add source lines and numbers to backtraces
-AC_ARG_WITH([dw],[AS_HELP_STRING([--with-dw=yes|no|auto],[use libdw])],
-            [], [with_dw=auto])
-if [ test "x${with_dw}" != "xno" ]; then
-  PKG_CHECK_MODULES(DW, [libdw],
-      [
-        HAVE_DW=yes
-        AC_DEFINE(HAVE_DW, 1, [libdw available])
-        DW_REQUIRE=libdw
-        AC_SUBST(DW_REQUIRE)
-      ],
-      [
-        HAVE_DW=no
-        if [ test "x${with_dw}" = "xyes" ]; then
-          AC_MSG_ERROR([could not find libdw])
-        fi
-      ])
-else
-  HAVE_DW=no
-fi
-
-dnl Check for backtrace() from libc
-AC_CHECK_FUNC(backtrace, [
-  AC_CHECK_HEADERS([execinfo.h], [
-    AC_DEFINE(HAVE_BACKTRACE,1,[Have backtrace])
-  ], [], [])
-])
-
-dnl building of unit test libraries
-AC_ARG_ENABLE(check,
-  AS_HELP_STRING([--disable-check],[disable building unit test libraries]),
-  [
-    case "${enableval}" in
-      yes) BUILD_CHECK=yes ;;
-      no)  BUILD_CHECK=no ;;
-      *)   AC_MSG_ERROR(bad value ${enableval} for --disable-check) ;;
-    esac
-  ], [
-    dnl Default value
-    case $host_os in
-      mingw* | msvc* | mks*) BUILD_CHECK=no ;;
-      *) BUILD_CHECK=yes ;;
-    esac
-])
-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 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(MEMORY_ALIGNMENT, 32, [Memory alignment to use])
-    else
-      case "${withval}" in
-        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(MEMORY_ALIGNMENT_MALLOC, 1, [Memory alignment by malloc default])
-  ]
-)
-
-dnl Symbol visibility
-VISIBILITY_CFLAGS=""
-AS_COMPILER_FLAG([-fvisibility=hidden], [
-  VISIBILITY_CFLAGS="-fvisibility=hidden"
-  AC_DEFINE(GST_API_EXPORT, [extern __attribute__ ((visibility ("default")))], [public symbol export define])
-], [
-  VISIBILITY_CFLAGS=""
-  AC_DEFINE(GST_API_EXPORT, [extern], [public symbol export define])
-])
-AC_SUBST(VISIBILITY_CFLAGS)
-
-dnl Check for -Bsymbolic-functions linker flag used to avoid
-dnl intra-library PLT jumps, if available.
-AC_ARG_ENABLE(Bsymbolic,
-              [AS_HELP_STRING([--disable-Bsymbolic],[avoid linking with -Bsymbolic])],,
-              [SAVED_LDFLAGS="${LDFLAGS}" SAVED_LIBS="${LIBS}"
-               AC_MSG_CHECKING([for -Bsymbolic-functions linker flag])
-               LDFLAGS=-Wl,-Bsymbolic-functions
-               LIBS=
-               AC_TRY_LINK([], [return 0],
-                           AC_MSG_RESULT(yes)
-                           enable_Bsymbolic=yes,
-                           AC_MSG_RESULT(no)
-                           enable_Bsymbolic=no)
-               LDFLAGS="${SAVED_LDFLAGS}" LIBS="${SAVED_LIBS}"])
-
-dnl Check for dlog
-AC_ARG_ENABLE(dlog, AC_HELP_STRING([--enable-dlog], [using dlog]),
-[
- case "${enableval}" in
-         yes) USE_DLOG=yes ;;
-         no)  USE_DLOG=no ;;
-         *)   AC_MSG_ERROR(bad value ${enableval} for --enable-dlog) ;;
- esac
-],[USE_DLOG=no])
-
-if test "x$USE_DLOG" = "xyes"; then
-        PKG_CHECK_MODULES(DLOG, dlog)
-        AC_SUBST(DLOG_CFLAGS)
-        AC_SUBST(DLOG_LIBS)
-fi
-AM_CONDITIONAL(USE_DLOG, test "x$USE_DLOG" = "xyes")
-dnl end
-
-dnl Check for tv-profile
-AC_ARG_ENABLE(tv-profile, AC_HELP_STRING([--enable-tv-profile], [using tv-profile]),
-[
- case "${enableval}" in
-         yes) HAVE_TV_PROFILE="-DTIZEN_PROFILE_TV -DTIZEN_FEATURE_TRUSTZONE" IS_TV_PROFILE=yes ;;
-         no)  HAVE_TV_PROFILE= ;;
-         *)   AC_MSG_ERROR(bad value ${enableval} for --enable-tv-profile) IS_TV_PROFILE=no ;;
- esac
-],[HAVE_TV_PROFILE=])
-AC_SUBST(HAVE_TV_PROFILE)
-AM_CONDITIONAL([IS_TV_PROFILE], [test "x$IS_TV_PROFILE" = "xyes"])
-dnl end
-
-dnl *** set variables based on configure arguments
-
-dnl set license and copyright notice
-GST_LICENSE="LGPL"
-AC_DEFINE_UNQUOTED(GST_LICENSE, "$GST_LICENSE", [GStreamer license])
-AC_SUBST(GST_LICENSE)
-
-dnl define LIBDIR, GST_DATADIR so we can inform people where we live
-AS_AC_EXPAND(LIBDIR, $libdir)
-AC_DEFINE_UNQUOTED(LIBDIR, "$LIBDIR", [library dir])
-AS_AC_EXPAND(DATADIR, $datadir)
-AC_DEFINE_UNQUOTED(GST_DATADIR, "$DATADIR", [data dir])
-
-dnl set location of plugin directory
-AG_GST_SET_PLUGINDIR
-
-dnl make sure it doesn't complain about unused variables if debugging is disabled
-NO_WARNINGS=""
-if test "x${GST_DISABLE_GST_DEBUG}" = "xyes"; then
-  NO_WARNINGS="-Wno-unused"
-fi
-
-dnl define an ERROR_CFLAGS Makefile variable
-AG_GST_SET_ERROR_CFLAGS($FATAL_WARNINGS, [-Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wundef -Wwrite-strings -Wformat-nonliteral -Wformat-security -Wold-style-definition -Winit-self -Wmissing-include-dirs -Waddress -Waggregate-return -Wno-multichar -Wnested-externs $NO_WARNINGS])
-
-dnl special warning flags for gst/printf
-AS_COMPILER_FLAG([-Wno-format-nonliteral], [PRINTF_CFLAGS="-Wno-format-nonliteral"])
-AC_SUBST(PRINTF_CFLAGS)
-
-dnl disable strict aliasing
-AS_COMPILER_FLAG([-fno-strict-aliasing], [EXTRA_CFLAGS="-fno-strict-aliasing"])
-AC_SUBST(EXTRA_CFLAGS)
-
-dnl define correct level for debugging messages
-AG_GST_SET_LEVEL_DEFAULT($GST_GIT)
-
-dnl *** finalize CFLAGS, LDFLAGS, LIBS
-
-dnl Overview:
-dnl GST_OPTION_CFLAGS:  common cflags for profiling, debugging, errors, ...
-dnl GST_ALL_*:          vars shared by all built objects
-dnl GST_LIB_LDFLAGS:    additional linker flags for all libraries
-dnl GST_OBJ_*:          additional vars to link to the core library
-dnl                    include GST_ALL_*
-dnl GST_LT_LDFLAGS:    library versioning of our libraries
-dnl GST_PLUGIN_LDFLAGS: flags to be used for all plugins
-
-dnl GST_OPTION_CFLAGS
-if test "x$USE_DEBUG" = xyes; then
-   PROFILE_CFLAGS="-g"
-fi
-AC_SUBST(PROFILE_CFLAGS)
-
-# GST_DISABLE_DEPRECATED: hide the visibility of deprecated
-# functionality from the API that gstreamer uses
-# GST_REMOVE_DEPRECATED: don't compile deprecated functionality (breaks ABI)
-if test "x$PACKAGE_VERSION_NANO" = "x1"; then
-  dnl Define _only_ when compiling from git (not for pre-releases or releases)
-  DEPRECATED_CFLAGS="-DGST_DISABLE_DEPRECATED"
-else
-  DEPRECATED_CFLAGS=""
-fi
-AC_SUBST(DEPRECATED_CFLAGS)
-
-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"
-GST_OPTION_CXXFLAGS="$GST_OPTION_CXXFLAGS"
-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 - 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
-dnl       from LibXML except for in the core library
-GST_ALL_CXXFLAGS="-I\$(top_srcdir)/libs -I\$(top_srcdir) -I\$(top_builddir)/libs -I\$(top_builddir) $GLIB_CFLAGS \$(GLIB_EXTRA_CFLAGS) $EXTRA_CFLAGS \$(GST_OPTION_CXXFLAGS) \$(ERROR_CXXFLAGS)"
-GST_ALL_CFLAGS="-I\$(top_srcdir)/libs -I\$(top_srcdir) -I\$(top_builddir)/libs -I\$(top_builddir) $GLIB_CFLAGS \$(GLIB_EXTRA_CFLAGS) $EXTRA_CFLAGS \$(GST_OPTION_CFLAGS) \$(ERROR_CFLAGS) \$(VISIBILITY_CFLAGS)"
-
-dnl FIXME: check if LTLIBINTL is needed everywhere
-dnl I presume it is given that it contains the symbols that _() stuff maps to
-GST_ALL_LIBS="$GLIB_LIBS $LTLIBINTL \$(GCOV_LIBS)"
-
-dnl LDFLAGS really should only contain flags, not libs - they get added before
-dnl whatevertarget_LIBS and -L flags here affect the rest of the linking
-GST_ALL_LDFLAGS="-no-undefined"
-if test "x${enable_Bsymbolic}" = "xyes"; then
-  GST_ALL_LDFLAGS="$GST_ALL_LDFLAGS -Wl,-Bsymbolic-functions"
-fi
-
-AC_SUBST(GST_ALL_CFLAGS)
-AC_SUBST(GST_ALL_CXXFLAGS)
-AC_SUBST(GST_ALL_LIBS)
-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=""
-AC_SUBST(GST_LIB_LDFLAGS)
-
-dnl GST_OBJ_*
-dnl default vars for all internal objects built on libgstreamer
-dnl includes GST_ALL_*
-GST_OBJ_CFLAGS="\$(GST_ALL_CFLAGS) $GST_OBJ_STATIC_CFLAGS"
-GST_OBJ_CXXFLAGS="\$(GST_ALL_CXXFLAGS) $GST_OBJ_STATIC_CFLAGS"
-GST_OBJ_LIBS="\$(top_builddir)/gst/libgstreamer-$GST_API_VERSION.la \$(GST_ALL_LIBS)"
-AC_SUBST(GST_OBJ_CFLAGS)
-AC_SUBST(GST_OBJ_CXXFLAGS)
-AC_SUBST(GST_OBJ_LIBS)
-
-dnl GST_PLUGIN_LDFLAGS
-dnl LDFLAGS for plugins; includes GST_ALL_LDFLAGS
-GST_PLUGIN_LDFLAGS="-module -avoid-version $GST_ALL_LDFLAGS"
-AC_SUBST(GST_PLUGIN_LDFLAGS, "$GST_PLUGIN_LDFLAGS")
-
-dnl plugin scanner locations
-AS_AC_EXPAND(GST_PLUGIN_SCANNER_INSTALLED,${libexecdir}/gstreamer-$GST_API_VERSION/gst-plugin-scanner)
-AC_DEFINE_UNQUOTED(GST_PLUGIN_SCANNER_INSTALLED,
-    "$GST_PLUGIN_SCANNER_INSTALLED", [location of the installed gst-plugin-scanner])
-AC_SUBST(GST_PLUGIN_SCANNER_INSTALLED)
-
-case "${libexecdir}" in
-  *libexec)
-    GST_PLUGIN_SCANNER_SUBDIR="libexec";;
-  *lib)
-    GST_PLUGIN_SCANNER_SUBDIR="lib";;
-  *)
-    GST_PLUGIN_SCANNER_SUBDIR=`basename ${libexecdir}`;
-    if test -z "$GST_PLUGIN_SCANNER_SUBDIR"; then
-      AC_MSG_WARN([Couldn't determined libexecdir suffix, using "lib"])
-      GST_PLUGIN_SCANNER_SUBDIR="lib";
-    fi
-    ;;
-esac
-AC_DEFINE_UNQUOTED(GST_PLUGIN_SCANNER_SUBDIR,
-    "$GST_PLUGIN_SCANNER_SUBDIR", [libexecdir path component, used to find plugin-scanner on relocatable builds on windows])
-
-case "${libdir}" in
-  *lib64)
-    GST_PLUGIN_SUBDIR="lib64";;
-  *lib32)
-    GST_PLUGIN_SUBDIR="lib32";;
-  *lib)
-    GST_PLUGIN_SUBDIR="lib";;
-  *)
-    GST_PLUGIN_SUBDIR=`basename ${libdir}`;
-    if test -z "$GST_PLUGIN_SUBDIR"; then
-      AC_MSG_WARN([Couldn't determined libdir suffix, using "lib"])
-      GST_PLUGIN_SUBDIR="lib";
-    fi
-    ;;
-esac
-AC_DEFINE_UNQUOTED(GST_PLUGIN_SUBDIR,
-    "$GST_PLUGIN_SUBDIR", [plugin directory path component, used to find plugins on relocatable builds on windows])
-
-dnl completion helper locations
-AS_AC_EXPAND(GST_COMPLETION_HELPER_INSTALLED,${libexecdir}/gstreamer-$GST_API_VERSION/gst-completion-helper)
-AC_DEFINE_UNQUOTED(GST_COMPLETION_HELPER_INSTALLED,
-    "$GST_COMPLETION_HELPER_INSTALLED", [location of the installed gst-completion-helper])
-AC_SUBST(GST_COMPLETION_HELPER_INSTALLED)
-
-dnl ptp helper locations
-AS_AC_EXPAND(GST_PTP_HELPER_INSTALLED,${libexecdir}/gstreamer-$GST_API_VERSION/gst-ptp-helper)
-AC_DEFINE_UNQUOTED(GST_PTP_HELPER_INSTALLED,
-    "$GST_PTP_HELPER_INSTALLED", [location of the installed gst-ptp-helper])
-AC_SUBST(GST_PTP_HELPER_INSTALLED)
-
-dnl things for our internal libcheck (must be called even if building
-dnl libcheck is disabled because it defines conditionals)
-AG_GST_CHECK_CHECKS
-
-AC_CONFIG_FILES(
-Makefile
-data/Makefile
-data/bash-completion/helpers/gst
-gst/Makefile
-gst/gstconfig.h
-gst/gstversion.h
-libs/gst/helpers/libgstreamer-gdb.py
-gst/parse/Makefile
-gst/printf/Makefile
-libs/Makefile
-libs/gst/Makefile
-libs/gst/base/Makefile
-libs/gst/check/Makefile
-libs/gst/check/libcheck/Makefile
-libs/gst/check/internal-check.h:libs/gst/check/libcheck/check.h.in
-libs/gst/controller/Makefile
-libs/gst/helpers/Makefile
-libs/gst/net/Makefile
-plugins/Makefile
-plugins/elements/Makefile
-plugins/tracers/Makefile
-po/Makefile.in
-tests/Makefile
-tests/benchmarks/Makefile
-tests/check/Makefile
-tests/misc/Makefile
-tests/examples/Makefile
-tests/examples/adapter/Makefile
-tests/examples/controller/Makefile
-tests/examples/stepping/Makefile
-tests/examples/helloworld/Makefile
-tests/examples/memory/Makefile
-tests/examples/netclock/Makefile
-tests/examples/ptp/Makefile
-tests/examples/streamiddemux/Makefile
-tests/examples/streams/Makefile
-tools/Makefile
-common/Makefile
-common/m4/Makefile
-docs/Makefile
-docs/gst/Makefile
-docs/gst/gstreamer.types
-docs/libs/Makefile
-docs/plugins/Makefile
-docs/version.entities
-m4/Makefile
-pkgconfig/Makefile
-stamp.h
-pkgconfig/gstreamer.pc
-pkgconfig/gstreamer-uninstalled.pc
-pkgconfig/gstreamer-base.pc
-pkgconfig/gstreamer-base-uninstalled.pc
-pkgconfig/gstreamer-check.pc
-pkgconfig/gstreamer-check-uninstalled.pc
-pkgconfig/gstreamer-controller.pc
-pkgconfig/gstreamer-controller-uninstalled.pc
-pkgconfig/gstreamer-net.pc
-pkgconfig/gstreamer-net-uninstalled.pc
-)
-
-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_GST_TRACER_HOOKS}" = "xno"; then enable_gst_tracer_hooks="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_PLUGIN}" = "xno"; then enable_plugin="yes"; fi
-if test "x${GST_DISABLE_REGISTRY}" = "xno"; then enable_registry="yes"; fi
-
-echo "
-
-Configuration
-       Version                    : ${VERSION}
-       Source code location       : ${srcdir}
-       Prefix                     : ${prefix}
-       Compiler                   : ${CC}
-       Package name               : ${GST_PACKAGE_NAME}
-       Package origin             : ${GST_PACKAGE_ORIGIN}
-
-       API Documentation          : ${enable_gtk_doc}
-
-       Debug logging              : ${enable_gst_debug}
-       Tracing subsystem hooks    : ${enable_gst_tracer_hooks}
-       Command-line parser        : ${enable_parse}
-       Option parsing in gst_init : ${enable_option_parsing}
-       Plugin registry            : ${enable_registry}
-       Plugin support             : ${enable_plugin}
-       Static plugins             : ${enable_static_plugins}
-       Unit testing support       : ${BUILD_CHECK}
-       PTP clock support          : ${HAVE_PTP}
-       libunwind support          : ${HAVE_UNWIND}
-       libdw support              : ${HAVE_DW}
-
-       Debug                      : ${USE_DEBUG}
-       Profiling                  : ${USE_PROFILING}
-
-       Building benchmarks        : ${BUILD_BENCHMARKS}
-       Building examples          : ${BUILD_EXAMPLES}
-       Building test apps         : ${BUILD_TESTS}
-       Building tests that fail   : ${BUILD_FAILING_TESTS}
-       Building tools             : ${BUILD_TOOLS}
-"
diff --git a/data/Makefile.am b/data/Makefile.am
deleted file mode 100644 (file)
index 16214fc..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-if ENABLE_BASH_COMPLETION
-bashhelpersdir = $(BASH_HELPERS_DIR)
-dist_bashhelpers_DATA = bash-completion/helpers/gst
-bashcompletiondir = $(BASH_COMPLETION_DIR)
-dist_bashcompletion_DATA = bash-completion/completions/gst-inspect-1.0 \
-                          bash-completion/completions/gst-launch-1.0
-endif
index 667e503..25391ae 100644 (file)
@@ -20,7 +20,7 @@
 
 _GST_HELPERDIR="${BASH_SOURCE[0]%/*}/../helpers"
 
-if [[ ! -d "$_GST_HELPERDIR"  ]]; then
+if [[ ! -f $_GST_HELPERDIR/gst ]]; then
        _GST_HELPERDIR="$(pkg-config --variable=bashhelpersdir gstreamer-1.0)"
 else
        _GST_HELPERDIR=`cd "$_GST_HELPERDIR"; pwd`
index 80ad34c..b678c86 100644 (file)
@@ -20,7 +20,7 @@
 
 _GST_HELPERDIR="${BASH_SOURCE[0]%/*}/../helpers"
 
-if [[ ! -d "$_GST_HELPERDIR" ]]; then
+if [[ ! -f $_GST_HELPERDIR/gst ]]; then
        _GST_HELPERDIR="$(pkg-config --variable=bashhelpersdir gstreamer-1.0)"
 else
        _GST_HELPERDIR=`cd "$_GST_HELPERDIR"; pwd`
diff --git a/data/bash-completion/helpers/.gitignore b/data/bash-completion/helpers/.gitignore
deleted file mode 100644 (file)
index 446b11b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-gst
index 42cfb26..03a50eb 100644 (file)
@@ -23,7 +23,7 @@ if [[ ! -x "$_GST_HELPER" ]]
 then
         helper="$(pkg-config --variable=helpersdir gstreamer-@GST_API_VERSION@)/gst-completion-helper"
 
-        if [ -x "$helper" ]
+        if [ -x "$helper" ]
         then
           _GST_HELPER=$helper
         fi
diff --git a/docs/.gitignore b/docs/.gitignore
deleted file mode 100644 (file)
index 9ab7439..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-Makefile
-Makefile.in
-*.o
-*.lo
-*.la
-.deps
-.libs
-version.entities
-tmpl/
diff --git a/docs/Makefile.am b/docs/Makefile.am
deleted file mode 100644 (file)
index 4772ebc..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-if ENABLE_GTK_DOC
-if ENABLE_PLUGIN_DOCS
-PLUGIN_DOCS_DIRS = plugins
-else
-PLUGIN_DOCS_DIRS =
-endif
-else
-PLUGIN_DOCS_DIRS = plugins
-endif
-
-BUILT_SOURCES = version.entities
-
-SUBDIRS = gst libs $(PLUGIN_DOCS_DIRS)
-DIST_SUBDIRS = gst libs plugins
-
-EXTRA_DIST = version.entities.in list-ulink.xsl
-
-upload:
-       @if test "x$(SUBDIRS)" != x; then for a in $(SUBDIRS); do cd $$a; make upload; cd ..; done; fi
-
-libs: gst
-
-include $(top_srcdir)/common/parallel-subdirs.mak
index a7b46fe..cb8fcfa 100644 (file)
 GStreamer documentation notes
 
-IMPORTANT
-=========
-
-Please make sure you've read and understood everything in this file
-before you try changing documentation.
-
-Some of the docbook-related bits in this README might be out of date now that
-quite a bit of the documentation has moved into the gst-docs repository.
-
 OVERVIEW
 ========
 
-GStreamer has two sets of documentation that we maintain:
-* API references, using gtk-doc (gstreamer, gstreamer-libs)
+Our documentation uses hotdoc, you should usually refer to the
+[hotdoc documentation](http://hotdoc.github.io/).
+
+GStreamer has two sets of documentation but both are controlled and aggregated in
+the `gst-docs` module:
+
+* API references, using hotdoc (gstreamer, gstreamer-libs) - maintained
+  in each GStreamer modules repository
 * FAQ / Application Development Manual / Plugin Writer's Guide / Tutorials -
   these are maintained in markdown format and live in the gst-docs repository.
 
-DOCBOOK NOTES
-=============
+To build the full documentation you should make sure to have `hotdoc` installed and
+build [gst-build](https://cgit.freedesktop.org/gstreamer/gst-build/) configuring it with:
 
-OK, I've grown so tired of having to coax the docs to build every time I
-get round to it that I've decided to note down some of the things that
-are important to know.
+```
+meson -Ddoc=enabled build/
+```
 
-OVERVIEW
---------
-* Our documentation should all be Docbook/XML.  No SGML.
-* The source for the documentation is:
-  - one or more .xml files, with the main one being gstreamer-(whatever).xml
-  - image files
-    - in .svg
-    - in .png (and maybe others)
-* We want to generate docs in HTML, PS and PDF
-* We want to use xml to to generate these
-
-CONVENTIONS
------------
-We stick to some simple conventions for writing docbook documentation.
-* id names:
-  - all id's start with chapter-, part-, section-, or misc-
-  - verify this is the case by looking at the generated file names in html/
-  - sections should also include the chapter name;
-    for example in a chapter called chapter-example, a section would be
-    called section-example-hello-world
-
-HOW IMAGES ARE HANDLED
-----------------------
-* the format of images used is:
-  - PNG for html
-  - EPS for ps
-  - PDF for pdf
-
-* images may need to be converted from their source format to the end format
-
-* a file called image.entities is generated that provides two entities:
-  &image; and &IMAGE;
-  &image; is the file extension (png, ps, pdf)
-* all generated images will be put in images/
-
-HOW THE BUILD WORKS FOR EACH FORMAT
------------------------------------
-* HTML:
-  - xmlto html gstreamer-whatever.xml should produce the html docs.
-  - We do this in the html subdir of the doc builddir.
-  - images are copied to (builddir)/html/images
-  - PNGS should be set to all of the png's referenced for html, both
-    already there and auto-generated
-
-* PS :
-  - images are converted to .ps files in EPS format.  Generated images are
-    put in images/
-  - xmlto ps gstreamer-whatever.xml generates the ps file
-
-* PDF :
-  There are two ways:
-  - ps2pdf is the easiest
-  - we specify ps, PS as the image type, but using xmlto the build will fail
-    because it uses ps2pdf internally and it fails to generate the images
-    By hand-generating .pdf images before xmlto we can make the build succeed.
-    (This is why image-pdf has file ext pdf but type EPS; this tricks xmlto in
-     doing the right thing)
-    xmlto pdf gstreamer-whatever.xml generates pdf (but seems to fail on the
-    FAQ, so for now we use ps2pdf)
+And building the documentation:
+
+```
+ninja -C build/ subprojects/gst-docs/GStreamer-doc`, this will result in two documentation sets:
+```
+
+This will generate two outputs:
+
+  - the html in `build/subprojects/gst-docs/GStreamer-doc/html`
+  - the [devhelp](https://wiki.gnome.org/Apps/Devhelp) in `build/subprojects/gst-docs/GStreamer-doc/devhelp`
 
 HOW THE BUILD SYSTEM IS SET UP
 ------------------------------
-* make all should build html, ps, and pdf
-* html is built in a subdir, with the png/ps images copied there
-* ps and pdf are built in the current dir, in one file
+Hotdoc build targets are generated for each documentation 'components' (ie. hotdoc
+subprojects). This includes libraries documentation and one target per GStreamer plugin.
+
+One can build a specific documentation target by explicitly building the target,
+for example to build the GStreamer core library documentation (adapt the paths if you
+are using `gst-build`):
+
+    ninja docs/libgstreamer-doc
+
+Then the documentation will be available in `docs/libgstreamer-doc/html/`.
 
 SPELL CHECKING
 --------------
-* with aspell
-  * aspell -b -c --mode=sgml --lang=en <file>.xml
-    unfortunately the curses-ui of aspell (0.50.5) has problems with the xml tags
 
+FILL ME.
 
-GTK-DOC NOTES
+HOTDOC NOTES
 =============
 
 * files under revision control:
-  - Makefile.am
-  - gstreamer-sections.txt
-    describes which symbols later appear on one api-doc page
-    configure which symbols are shown/invisible/private
-  - gstreamer.types
-    the types file lists all get_type() functions that register the GObject types
-  - gstreamer-docs.sgml
-    defines the overall structure of the api documentation
-  - tmpl/
-    - only add the file to CVS if you have at least filled the short description
-      (filename corresponds to the <FILE> tag in the sections file)
-    - document as much as possible in the source (*.c files)
+  - sitemap.txt: defines the overall structure of the documentation
+  - gst_plugins_cache.json: Automatically generated information about plugins
 
 * what to do when adding a new piece of API:
-  - add both an entity and use the entity in gstreamer-docs.sgml
-  - add a new <SECTION> to gstreamer-sections.txt in the correct alphabetical
-    position related to the other sections (so that it is easier to locate)
-  - add all documented symbols to gstreamer-sections.txt in the proper section
-    (default),<SUBSECTION Standard>,<SUBSECTION Private>
-  - document at least the Short_Description in tmpl/.sgml
-  - document symbols where they are defined, so that when one changes the
-    definition, the chaces are good that docs are updated.
-    - document functions, signals in the .c files
-    - document structs, typedefs, enums in the .h files
-
-* checklist:
-  - make sure *-sections.txt has a <TITLE> set for each <FILE>
-  - add only *one* <TITLE> to each file, when you have multiple classes in one
-    source-file, create one <FILE> section for each class
-  - the <TITLE> *must* be named like the type of the GType, when it gets
-    registered (otherwise gtkdoc introspection fails)
-  - for clarity name the <FILE> like the <TITLE>, but all lowercase
+  - Just let hotdoc generate the documentation and decide where to put it
+  - Make sure to add a `SECTION` documentation section in the file where
+    the documentation should land (hotdoc will use that to create its
+    "smart index" and list symbols from other files that should land
+    on that page in that section.
+  - document functions, signals in the .c files
+  - document structs, typedefs, enums in the .h files
 
 * what to do when trying to improve the docs
   - compare the output of
     grep "_get_type" gstreamer-sections.txt | sort
     with the types in XXX.types to detect entries that
     are maybe missing
-  - gtk docs does not warns about empty member docs!, run
+  - hotdoc does not warns about empty member docs!, run
     find . -name "*.[c,h]" -exec egrep -Hn "^ +\* +@.*: *$" {} \;
     in the project root to find them
-  - gtk docs does not warns about empty Returns: docs!, run
+  - hotdoc does not warns about empty Returns: docs!, run
     find . -name "*.[c,h]" -exec egrep -Hn "^ +\* +@Returns: *$" {} \;
     in the project root to find them
 
-* what happens during a gtk-doc build ?
-  - Scan step:
-    - based on a $(MODULE).types file:
-      - gtkdoc-scangobj creates a gtkdoc-scan binary
-        - using CC, LD, CFLAGS, LDFLAGS env var
-        - using --type-init-func and --module parameters
-        - gtkdoc-scan creates
-          - $MODULE.signals.new
-          - $MODULE.hierarchy.new
-          - $MODULE.interfaces.new
-          - $MODULE.prerequisites.new
-          - $MODULE.args.new
-        - generated source and objects get deleted
-        - gtkdoc-scangobj merges changes into the original files
-    - gtkdoc-scan
-      - extracts decls of functions, macros, enums, structs, unions from headers
-      - generates
-        - $MODULE-decl.txt
-        - $MODULE-decl-list.txt
-      - $MODULE-decl-list.txt then should get copied to $MODULE-sections.txt
-    - scan-build.stamp gets created
-  
-  - Template generation step:
-    - gtkdoc-mktmpl --module=$MODULE
-      - reads in tmpl/*.sgml
-      - moves them to tmpl/*.sgml.bak
-      - recreates tmpl/*.sgml according to $MODULE-sections.txt
-      - moves unused stuff to $MODULE-unused.txt
-    - tmpl-build.stamp gets generated
-
-* Possible errors and how to fix them
-  - Warning: multiple "IDs" for constraint linkend: gst-tag-register.
-    - check if gst_tag_register is listed more than once in -sections.txt
-
-STYLE GUIDE FOR GTK-DOC
+* what happens during a hotdoc build ?
+  - Read the GIR and scan the sources files for the docstrings and
+    generate the documentation laying out pages the way they are documented.
+  - The meson build definition is set in a way that makes it so all plugins
+    in `plugins_doc` are introspected and documented
+
+STYLE GUIDE FOR HOTDOC
 =======================
 - this is in addition to gtk-doc's style-guide.txt
 
-- when documenting signals, use "the #Gst..." for the object receiving the
-  signal; no trailing dot, and no "that received the signal"
 - function/macro descriptions are descriptive, not imperative
   ie, it uses the third person verb
 - synopsis and description should have most-used/application functions at the
@@ -201,165 +103,38 @@ STYLE GUIDE FOR GTK-DOC
     "Caller owns returned value" for other types (iterators, ..)
   - we do this because, in contrast with GLib/GTK, we are more explicit
     about threadsafety and related issues
-- link to signals from the description like this:
-  * The <link linkend="GstBin-element-added">element-added</link> signal
 
 WEBSITE DOCUMENTATION
 =====================
 
-Updating the online documentation is pretty simple.
-Make sure that you
-a) have a working freedesktop.org account
-b) $HOME/.ssh/config set up so that it has the right User for the Host
-   (for example, I have:
-Host freedesktop.org
-  User thomasvs
-c) verify this works by doing ssh freedesktop.org and being logged in without
-   a password prompt
-d) have verified your changes build documentation locally.
-
-Then, after updating any of the docs, run "make upload" from that directory.
-Or, run "make upload" from this (docs) directory.
+Updating the online documentation is done from with the `gst-docs` repository
 
 DOCUMENTING ELEMENTS
 ====================
-As of september 2005 we have some system to document plugins and elements
-in the various plugin packages.
-
-- in a submodule, docs go in docs/plugins
-- template can be copied from gst-plugins-base
-- to add plugins documentation:
-  - create docs/plugins
-  - create Makefile.am and friends, add to configure.ac
-  - create docs/version.entities.in, add to configure.ac
-  - in docs/plugins:
-    - create $(module)-plugins.types with #include <gst/gst.h>
-    - run make
-    - edit the -docs.sgml
-    - add to cvs:
-      cvs add *-plugins-docs.sgml *-plugins.args *-plugins.hierarchy *-plugins.interfaces *-plugins.prerequisites *-plugins.signals *-plugins.types inspect-build.stamp inspect.stamp scanobj-build.stamp
-      cvs add inspect
-      cvs add inspect/*.xml
-    - Additional types can be added to the documentation by placing them in
-      the .types file like this:
-        type:GstPlayBaseBin
-      This is useful for documenting plugin-private types that implement
-      signals or properties. The GType is looked up by name after all the
-      element classes have been printed - so this is only useful for types
-      that are created as a consequence of loading plugins and registering
-      the element(s).
+A hotdoc plugin is provided by GStreamer to document GStreamer plugins.
 
 - to add a plugin to be documented:
-  - make sure inspect/ has generated a inspect/plugin-xxx.xml file for it.
-    - if it has not, make sure you have pygst installed and run 'make update'.
-      and add it to CVS.
-  - add an xi:include in -docs.sgml in the Plugins chapter for that plugin
-
+  - make sure the plugin is added to the `plugins_doc` variable in meson
 - to add an element to be documented:
-  - add an xi:include in the Elements chapter for the element
-    in the main -docs.sgml
-  - add a section for it in -sections.txt with
-      <SECTION>
-      <FILE>element-(element)</FILE>
-      <TITLE>(element)</TITLE>
-      GstXxx
-      <SUBSECTION Standard>
-      GstXxxClass
-      GST_XXX
-      GST_XXX_CLASS
-      GST_IS_XXX
-      GST_IS_XXX_CLASS
-      GST_TYPE_XXX
-      gst_xxx_get_type
-      </SECTION>
   - add a gtk-doc section to the source code like:
 /**
  * SECTION:element-multifdsink
 
-  and fill it with documentation about the element, preferably inside
-  a <refsect2> docbook container.
+  and fill it with documentation about the element
   - add an example:
-    - either a few pipelines, inside <programlisting>
-    - or a piece of code:
-      - create an example program (element)-example.c in the plugin dir
-      - add the full path (starting with $(top_srcdir)) for this example
-        to the EXAMPLE_CFILES variable in Makefile.am
-      - add an xinclude of a file named "element-(element)-example.xml"
-        to the docbook documentation piece in the element source code
-  - add the header to EXTRA_HFILES in Makefile.am to be able to document
-    signals and args; in that case, the object struct needs to be in
-    -sections.txt outside of the Standard Subsection (which is annoying,
-    but ...)
-    (FIXME: are we sure we can both do the xinclude from the tmpl/ sgml,
-     as well as an override from the source itself ? maybe we should just
-     make sure the xinclude is in the source itself instead ?)
-  - if the plugin has no public header, don't add the c-file, add entries to the
-    -overrides.txt file (see playbin docs in plugins-base).
-  - to rebuild the docs, do:
-    make clean
-    make update
-    make
-  - examples will only show up using gtk-doc 1.4 or later - it relies on
-    merging stuff from .sgml with inline docs.  We might want to change
-    this to only get stuff from the source.
-  - you need to commit resulting files to git:
-    - changes to *.signals and *.args
-    - new files for your plugin created in inspect/
-  - if you get this warning:
-    " Documentation in template xxx for ./tmpl/element-yyy:Short_Description
-      being overridden by inline comments"
-    per-default the description from the GST_ELEMENT_DETAILS is put to the
-    Short_Description. This warning mean you have a different one in the section
-    docs as "@short_description:".
-
-- the plugin-doc-list on the gstreamer homepage is updated along with other
-  web site updates.
-
-- maintainer tricks:
-  - in gst-plugins-foo/docs/plugins/, run
-        make check-inspected-versions
-    to show plugins whose inspect information is not up-to-date (which is
-    usually either because they have been moved to a different module or
-    because they are not built on the maintainer's machine for some reason).
-    Whether it really makes sense to update the version number is debatable
-    (after all, the inspected information may be outdated and things may have
-    changed, in which case it would be bad to change the version number)
-  - find files that have docs
-    for file in `find . -name "*.c" -exec grep -l " * SECTION:element-" {} \; | sort`; do if [ -e ${file/.c/.h} ]; then echo ${file/.c/.h}; else echo "no header for $file"; fi; done
-    for file in `find . -name "*.cc" -exec grep -l " * SECTION:element-" {} \; | sort`; do if [ -e ${file/.cc/.h} ]; then echo ${file/.cc/.h}; else echo "no header for $file"; fi; done
-    - add those .h files to EXTRA_HFILES in Makefile.am
-  - update gst-plugins-xxx-docs.sgml
-    cd docs/plugins
-    ls -1 xml/plugin-*.xml | sort | sed -e "s/\(.*\)/    \<xi:include href=\"\1\" \/\>/"
-    ls -1 xml/element-*.xml | grep -v -- "-details.xml" | sort | sed -e "s/\(.*\)/    \<xi:include href=\"\1\" \/\>/"
-    - maybe we can generate these lists after "make update" and just xi:include
-      them in gst-plugins-xxx-docs.sgml. They should be committed to the vcs.
-
-- possible errors:
-  - "multiple constraints for linkend ID":
-    check if each section in -sections.txt actually starts and ends with
-    <SECTION> and </SECTION>
-  - if a plugin does not show up:
-    - check inspect/plugin-xxx.xml and tmpl/elements-
-
-RANDOM THINGS I'VE LEARNED
-==========================
-
-* for clean builddir != srcdir separation, I wanted to use xmlto --searchpath
-  so the source xml could find the built entity file.
-  But xmlto --searchpath is (right now) for TeX input, not xml input.
-  xsltproc has a --path option (that xmlto doesn't use yet), but it
-  resolves single files to $(specified_path)/$(srcdir)/$(file)
-  For now, we need to hack around it by copying xml to the build dir.
+    - either a few pipelines, inside a codeblock
+    - or a piece of code inside a codeblock or in `tests/examples/(pluginname)`
+  - to build the doc for a plugin, do:
+    `ninja docs/(pluginname)-doc`
 
 
 DEVHELP INTEGRATION
 -------------------
 Check https://wiki.gnome.org/Apps/Devhelp
 It's a really nice development app allowing you to look up API stuff
-from various gtk-doc'd libraries.  GStreamer is one of these ;)
+from various hotdoc/gtk-doc'd libraries.  GStreamer is one of these ;)
 
-gtk-doc generates both html API docs and the matching .devhelp(2) books.
+hotdoc generates both html API docs and the matching .devhelp(2) books.
 
 IMAGES
 ------
diff --git a/docs/gst-hotdoc-plugins-scanner.c b/docs/gst-hotdoc-plugins-scanner.c
new file mode 100644 (file)
index 0000000..f530f86
--- /dev/null
@@ -0,0 +1,962 @@
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <glib/gprintf.h>
+#include <gst/gst.h>
+#include <gio/gio.h>
+#include "gst/gst-i18n-app.h"
+
+static GRegex *cleanup_caps_field = NULL;
+static void _add_object_details (GString * json, GString * other_types,
+    GHashTable * seen_other_types, GObject * object, GType gtype,
+    GType inst_type);
+
+static gchar *
+json_strescape (const gchar * str)
+{
+  const gchar *p;
+  const gchar *end;
+  GString *output;
+  gsize len;
+
+  if (!str)
+    return g_strdup ("NULL");
+
+  len = strlen (str);
+  end = str + len;
+  output = g_string_sized_new (len);
+
+  for (p = str; p < end; p++) {
+    if (*p == '\\' || *p == '"') {
+      g_string_append_c (output, '\\');
+      g_string_append_c (output, *p);
+    } else if (*p == '%') {
+      g_string_append_c (output, '%');
+      g_string_append_c (output, *p);
+    } else if ((*p > 0 && *p < 0x1f) || *p == 0x7f) {
+      switch (*p) {
+        case '\b':
+          g_string_append (output, "\\b");
+          break;
+        case '\f':
+          g_string_append (output, "\\f");
+          break;
+        case '\n':
+          g_string_append (output, "\\n");
+          break;
+        case '\r':
+          g_string_append (output, "\\r");
+          break;
+        case '\t':
+          g_string_append (output, "\\t");
+          break;
+        default:
+          g_string_append_printf (output, "\\u00%02x", (guint) * p);
+          break;
+      }
+    } else {
+      g_string_append_c (output, *p);
+    }
+  }
+
+  return g_string_free (output, FALSE);
+}
+
+static gchar *
+flags_to_string (GFlagsValue * values, guint flags)
+{
+  GString *s = NULL;
+  guint flags_left, i;
+
+  /* first look for an exact match and count the number of values */
+  for (i = 0; values[i].value_name != NULL; ++i) {
+    if (values[i].value == flags)
+      return g_strdup (values[i].value_nick);
+  }
+
+  s = g_string_new (NULL);
+
+  /* we assume the values are sorted from lowest to highest value */
+  flags_left = flags;
+  while (i > 0) {
+    --i;
+    if (values[i].value != 0
+        && (flags_left & values[i].value) == values[i].value) {
+      if (s->len > 0)
+        g_string_append_c (s, '+');
+      g_string_append (s, values[i].value_nick);
+      flags_left -= values[i].value;
+      if (flags_left == 0)
+        break;
+    }
+  }
+
+  if (s->len == 0)
+    g_string_assign (s, "(none)");
+
+  return g_string_free (s, FALSE);
+}
+
+static void
+_serialize_flags_default (GString * json, GType gtype, GValue * value)
+{
+  GFlagsValue *values = G_FLAGS_CLASS (g_type_class_ref (gtype))->values;
+  gchar *cur;
+
+  cur = flags_to_string (values, g_value_get_flags (value));
+  g_string_append_printf (json, ",\"default\": \"%s\"", cur);
+  g_free (cur);
+}
+
+static void
+_serialize_flags (GString * json, GType gtype)
+{
+  GFlagsValue *values = G_FLAGS_CLASS (g_type_class_ref (gtype))->values;
+
+  g_string_append_printf (json, "%s\"%s\": { "
+      "\"kind\": \"flags\"," "\"values\": [", json->len ? "," : "",
+      g_type_name (gtype));
+
+  while (values[0].value_name) {
+    gchar *value_name = json_strescape (values[0].value_name);
+    gchar *value_nick = json_strescape (values[0].value_nick);
+
+    g_string_append_printf (json, "{\"name\": \"%s\","
+        "\"value\": \"0x%08x\","
+        "\"desc\": \"%s\"}", value_nick, values[0].value, value_name);
+    ++values;
+
+    if (values[0].value_name)
+      g_string_append_c (json, ',');
+
+    g_free (value_name);
+    g_free (value_nick);
+  }
+
+  g_string_append (json, "]}");
+}
+
+static void
+_serialize_enum_default (GString * json, GType gtype, GValue * value)
+{
+  GEnumValue *values;
+  guint j = 0;
+  gint enum_value;
+  gchar *value_nick = g_strdup ("");
+
+  values = G_ENUM_CLASS (g_type_class_ref (gtype))->values;
+
+  enum_value = g_value_get_enum (value);
+  while (values[j].value_name) {
+    if (values[j].value == enum_value) {
+      g_free (value_nick);
+      value_nick = json_strescape (values[j].value_nick);
+      break;
+    }
+
+    j++;
+  }
+  g_string_append_printf (json, ",\"default\": \"%s (%d)\"", value_nick,
+      enum_value);;
+  g_free (value_nick);
+}
+
+static void
+_serialize_enum (GString * json, GType gtype, GstPluginAPIFlags api_flags)
+{
+  GEnumValue *values;
+  guint j = 0;
+
+  values = G_ENUM_CLASS (g_type_class_ref (gtype))->values;
+
+  g_string_append_printf (json, "%s\"%s\": { "
+      "\"kind\": \"enum\"", json->len ? "," : "", g_type_name (gtype));
+
+  if (api_flags & GST_PLUGIN_API_FLAG_IGNORE_ENUM_MEMBERS) {
+    g_string_append (json, ",\"ignore-enum-members\": true}");
+  } else {
+    g_string_append (json, ",\"values\": [");
+
+    while (values[j].value_name) {
+      gchar *value_name = json_strescape (values[j].value_name);
+      gchar *value_nick = json_strescape (values[j].value_nick);
+
+      g_string_append_printf (json, "{\"name\": \"%s\","
+          "\"value\": \"%d\","
+          "\"desc\": \"%s\"}", value_nick, values[j].value, value_name);
+      j++;
+      if (values[j].value_name)
+        g_string_append_c (json, ',');
+
+      g_free (value_name);
+      g_free (value_nick);
+    }
+
+    g_string_append (json, "]}");
+  }
+}
+
+/* @inst_type is used when serializing base classes in the hierarchy:
+ * we don't instantiate the base class, which may very well be abstract,
+ * but instantiate the final type (@inst_type), and use @type to determine
+ * what properties / signals / etc.. we are actually interested in.
+ */
+static void
+_serialize_object (GString * json, GHashTable * seen_other_types, GType gtype,
+    GType inst_type)
+{
+  GObject *tmpobj;
+  GString *other_types = NULL;
+
+  g_string_append_printf (json, "%s\"%s\": { "
+      "\"kind\": \"%s\"", json->len ? "," : "", g_type_name (gtype),
+      G_TYPE_IS_INTERFACE (gtype) ? "interface" : "object");
+
+  other_types = g_string_new ("");
+  g_string_append_c (json, ',');
+  tmpobj = g_object_new (inst_type, NULL);
+  _add_object_details (json, other_types, seen_other_types, tmpobj, gtype,
+      inst_type);
+  gst_object_unref (tmpobj);
+
+  g_string_append_c (json, '}');
+
+  if (other_types && other_types->len) {
+    g_string_append_printf (json, ",%s", other_types->str);
+  }
+  g_string_free (other_types, TRUE);
+}
+
+static void
+_add_signals (GString * json, GString * other_types,
+    GHashTable * seen_other_types, GObject * object, GType type)
+{
+  gboolean opened = FALSE;
+  guint *signals = NULL;
+  guint nsignals;
+  gint i = 0, j;
+  GstPluginAPIFlags api_flags;
+
+  signals = g_signal_list_ids (type, &nsignals);
+  for (i = 0; i < nsignals; i++) {
+    GSignalQuery query = { 0, };
+
+    g_signal_query (signals[i], &query);
+    g_string_append_printf (json,
+        "%s\"%s\" : {", opened ? "," : ",\"signals\": {", query.signal_name);
+
+    opened = TRUE;
+
+    g_string_append (json, "\"args\": [");
+    for (j = 0; j < query.n_params; j++) {
+      gchar *arg_name = g_strdup_printf ("arg%u", j);
+      if (j) {
+        g_string_append_c (json, ',');
+      }
+
+      g_string_append_printf (json, "{ \"name\": \"%s\","
+          "\"type\": \"%s\" }", arg_name, g_type_name (query.param_types[j]));
+
+      if (!g_hash_table_contains (seen_other_types,
+              g_type_name (query.param_types[j])) &&
+          gst_type_is_plugin_api (query.param_types[j], &api_flags)) {
+        g_hash_table_insert (seen_other_types,
+            (gpointer) g_type_name (query.param_types[j]), NULL);
+
+        if (g_type_is_a (query.param_types[j], G_TYPE_ENUM)) {
+          _serialize_enum (other_types, query.param_types[j], api_flags);
+        } else if (g_type_is_a (query.param_types[j], G_TYPE_FLAGS)) {
+          _serialize_flags (other_types, query.param_types[j]);
+        } else if (g_type_is_a (query.param_types[j], G_TYPE_OBJECT)) {
+          _serialize_object (other_types, seen_other_types,
+              query.param_types[j], query.param_types[j]);
+        }
+      }
+    }
+    g_string_append_c (json, ']');
+
+    if (g_type_name (query.return_type) &&
+        !g_hash_table_contains (seen_other_types,
+            g_type_name (query.return_type)) &&
+        gst_type_is_plugin_api (query.return_type, &api_flags)) {
+      g_hash_table_insert (seen_other_types,
+          (gpointer) g_type_name (query.return_type), NULL);
+      if (g_type_is_a (query.return_type, G_TYPE_ENUM)) {
+        _serialize_enum (other_types, query.return_type, api_flags);
+      } else if (g_type_is_a (query.return_type, G_TYPE_FLAGS)) {
+        _serialize_flags (other_types, query.return_type);
+      } else if (g_type_is_a (query.return_type, G_TYPE_OBJECT)) {
+        _serialize_object (other_types, seen_other_types, query.return_type,
+            query.return_type);
+      }
+    }
+
+    g_string_append_printf (json,
+        ",\"return-type\": \"%s\"", g_type_name (query.return_type));
+
+    if (query.signal_flags & G_SIGNAL_RUN_FIRST)
+      g_string_append (json, ",\"when\": \"first\"");
+    else if (query.signal_flags & G_SIGNAL_RUN_LAST)
+      g_string_append (json, ",\"when\": \"last\"");
+    else if (query.signal_flags & G_SIGNAL_RUN_CLEANUP)
+      g_string_append (json, ",\"when\": \"cleanup\"");
+
+    if (query.signal_flags & G_SIGNAL_NO_RECURSE)
+      g_string_append (json, ",\"no-recurse\": true");
+
+    if (query.signal_flags & G_SIGNAL_DETAILED)
+      g_string_append (json, ",\"detailed\": true");
+
+    if (query.signal_flags & G_SIGNAL_ACTION)
+      g_string_append (json, ",\"action\": true");
+
+    if (query.signal_flags & G_SIGNAL_NO_HOOKS)
+      g_string_append (json, ",\"no-hooks\": true");
+
+    g_string_append_c (json, '}');
+
+    opened = TRUE;
+  }
+  g_free (signals);
+
+  if (opened)
+    g_string_append (json, "}");
+}
+
+static void
+_add_properties (GString * json, GString * other_types,
+    GHashTable * seen_other_types, GObject * object, GObjectClass * klass,
+    GType type)
+{
+  gchar *tmpstr;
+  guint i, n_props;
+  gboolean opened = FALSE;
+  GParamSpec **specs, *spec;
+  GstPluginAPIFlags api_flags;
+
+  specs = g_object_class_list_properties (klass, &n_props);
+
+  for (i = 0; i < n_props; i++) {
+    GValue value = { 0, };
+    const gchar *mutable_str = NULL;
+    spec = specs[i];
+
+    if (spec->owner_type != type)
+      continue;
+
+    g_value_init (&value, spec->value_type);
+    if (object && ! !(spec->flags & G_PARAM_READABLE) &&
+        !(spec->flags & GST_PARAM_DOC_SHOW_DEFAULT)) {
+      g_object_get_property (G_OBJECT (object), spec->name, &value);
+    } else {
+      /* if we can't read the property value, assume it's set to the default
+       * (which might not be entirely true for sub-classes, but that's an
+       * unlikely corner-case anyway) */
+      g_param_value_set_default (spec, &value);
+    }
+
+    if (!opened)
+      g_string_append (json, ",\"properties\": {");
+
+    if ((spec->flags & GST_PARAM_MUTABLE_PLAYING)) {
+      mutable_str = "\"playing\"";
+    } else if ((spec->flags & GST_PARAM_MUTABLE_PAUSED)) {
+      mutable_str = "\"paused\"";
+    } else if ((spec->flags & GST_PARAM_MUTABLE_READY)) {
+      mutable_str = "\"ready\"";
+    } else {
+      mutable_str = "\"null\"";
+    }
+
+    tmpstr = json_strescape (g_param_spec_get_blurb (spec));
+    g_string_append_printf (json,
+        "%s"
+        "\"%s\": {"
+        "\"construct-only\": %s,"
+        "\"construct\": %s,"
+        "\"readable\": %s,"
+        "\"writable\": %s,"
+        "\"blurb\": \"%s\","
+        "\"controllable\": %s,"
+        "\"conditionally-available\": %s,"
+        "\"mutable\": %s,"
+        "\"type\": \"%s\"",
+        opened ? "," : "",
+        spec->name,
+        spec->flags & G_PARAM_CONSTRUCT_ONLY ? "true" : "false",
+        spec->flags & G_PARAM_CONSTRUCT ? "true" : "false",
+        spec->flags & G_PARAM_READABLE ? "true" : "false",
+        spec->flags & G_PARAM_WRITABLE ? "true" : "false", tmpstr,
+        spec->flags & GST_PARAM_CONTROLLABLE ? "true" : "false",
+        spec->flags & GST_PARAM_CONDITIONALLY_AVAILABLE ? "true" : "false",
+        mutable_str, g_type_name (G_PARAM_SPEC_VALUE_TYPE (spec)));
+    g_free (tmpstr);
+
+    if (!g_hash_table_contains (seen_other_types,
+            g_type_name (spec->value_type))
+        && gst_type_is_plugin_api (spec->value_type, &api_flags)) {
+      g_hash_table_insert (seen_other_types,
+          (gpointer) g_type_name (spec->value_type), NULL);
+      if (G_IS_PARAM_SPEC_ENUM (spec)) {
+        _serialize_enum (other_types, spec->value_type, api_flags);
+      } else if (G_IS_PARAM_SPEC_FLAGS (spec)) {
+        _serialize_flags (other_types, spec->value_type);
+      } else if (G_IS_PARAM_SPEC_OBJECT (spec)) {
+        _serialize_object (other_types, seen_other_types, spec->value_type,
+            spec->value_type);
+      }
+    }
+
+    switch (G_VALUE_TYPE (&value)) {
+      case G_TYPE_STRING:
+      {
+        const char *string_val = g_value_get_string (&value);
+        gchar *tmpstr = json_strescape (string_val);
+
+        g_string_append_printf (json, ",\"default\": \"%s\"", tmpstr);;
+        g_free (tmpstr);
+        break;
+      }
+      case G_TYPE_BOOLEAN:
+      {
+        gboolean bool_val = g_value_get_boolean (&value);
+
+        g_string_append_printf (json, ",\"default\": \"%s\"",
+            bool_val ? "true" : "false");
+        break;
+      }
+      case G_TYPE_ULONG:
+      {
+        GParamSpecULong *pulong = G_PARAM_SPEC_ULONG (spec);
+
+        g_string_append_printf (json,
+            ",\"default\": \"%lu\""
+            ",\"min\": \"%lu\""
+            ",\"max\": \"%lu\"",
+            g_value_get_ulong (&value), pulong->minimum, pulong->maximum);
+
+        GST_ERROR_OBJECT (object,
+            "property '%s' of type ulong: consider changing to " "uint/uint64",
+            g_param_spec_get_name (spec));
+        break;
+      }
+      case G_TYPE_LONG:
+      {
+        GParamSpecLong *plong = G_PARAM_SPEC_LONG (spec);
+
+        g_string_append_printf (json,
+            ",\"default\": \"%ld\""
+            ",\"min\": \"%ld\""
+            ",\"max\": \"%ld\"",
+            g_value_get_long (&value), plong->minimum, plong->maximum);
+
+        GST_ERROR_OBJECT (object,
+            "property '%s' of type long: consider changing to " "int/int64",
+            g_param_spec_get_name (spec));
+        break;
+      }
+      case G_TYPE_UINT:
+      {
+        GParamSpecUInt *puint = G_PARAM_SPEC_UINT (spec);
+
+        g_string_append_printf (json,
+            ",\"default\": \"%d\""
+            ",\"min\": \"%d\""
+            ",\"max\": \"%d\"",
+            g_value_get_uint (&value), puint->minimum, puint->maximum);
+        break;
+      }
+      case G_TYPE_INT:
+      {
+        GParamSpecInt *pint = G_PARAM_SPEC_INT (spec);
+
+        g_string_append_printf (json,
+            ",\"default\": \"%d\""
+            ",\"min\": \"%d\""
+            ",\"max\": \"%d\"",
+            g_value_get_int (&value), pint->minimum, pint->maximum);
+        break;
+      }
+      case G_TYPE_UINT64:
+      {
+        GParamSpecUInt64 *puint64 = G_PARAM_SPEC_UINT64 (spec);
+
+        g_string_append_printf (json,
+            ",\"default\": \"%" G_GUINT64_FORMAT
+            "\",\"min\": \"%" G_GUINT64_FORMAT
+            "\",\"max\": \"%" G_GUINT64_FORMAT "\"",
+            g_value_get_uint64 (&value), puint64->minimum, puint64->maximum);
+        break;
+      }
+      case G_TYPE_INT64:
+      {
+        GParamSpecInt64 *pint64 = G_PARAM_SPEC_INT64 (spec);
+
+        g_string_append_printf (json,
+            ",\"default\": \"%" G_GUINT64_FORMAT
+            "\",\"min\": \"%" G_GINT64_FORMAT
+            "\",\"max\": \"%" G_GINT64_FORMAT "\"",
+            g_value_get_int64 (&value), pint64->minimum, pint64->maximum);
+        break;
+      }
+      case G_TYPE_FLOAT:
+      {
+        GParamSpecFloat *pfloat = G_PARAM_SPEC_FLOAT (spec);
+
+        g_string_append_printf (json,
+            ",\"default\": \"%g\""
+            ",\"min\": \"%g\""
+            ",\"max\": \"%g\"",
+            g_value_get_float (&value), pfloat->minimum, pfloat->maximum);
+        break;
+      }
+      case G_TYPE_DOUBLE:
+      {
+        GParamSpecDouble *pdouble = G_PARAM_SPEC_DOUBLE (spec);
+
+        g_string_append_printf (json,
+            ",\"default\": \"%g\""
+            ",\"min\": \"%g\""
+            ",\"max\": \"%g\"",
+            g_value_get_double (&value), pdouble->minimum, pdouble->maximum);
+        break;
+      }
+      case G_TYPE_CHAR:
+      case G_TYPE_UCHAR:
+        GST_ERROR_OBJECT (object,
+            "property '%s' of type char: consider changing to " "int/string",
+            g_param_spec_get_name (spec));
+        /* fall through */
+      default:
+        if (spec->value_type == GST_TYPE_CAPS) {
+          const GstCaps *caps = gst_value_get_caps (&value);
+
+          if (caps) {
+            gchar *capsstr = gst_caps_to_string (caps);
+            gchar *tmpcapsstr = json_strescape (capsstr);
+
+            g_string_append_printf (json, ",\"default\": \"%s\"", tmpcapsstr);
+            g_free (capsstr);
+            g_free (tmpcapsstr);
+          }
+        } else if (G_IS_PARAM_SPEC_BOXED (spec)) {
+          if (spec->value_type == GST_TYPE_STRUCTURE) {
+            const GstStructure *s = gst_value_get_structure (&value);
+            if (s) {
+              gchar *str = gst_structure_to_string (s);
+              gchar *tmpstr = json_strescape (str);
+
+              g_string_append_printf (json, ",\"default\": \"%s\"", tmpstr);
+              g_free (str);
+              g_free (tmpstr);
+            }
+          }
+        } else if (GST_IS_PARAM_SPEC_FRACTION (spec)) {
+          GstParamSpecFraction *pfraction = GST_PARAM_SPEC_FRACTION (spec);
+
+          g_string_append_printf (json,
+              ",\"default\": \"%d/%d\""
+              ",\"min\": \"%d/%d\""
+              ",\"max\": \"%d/%d\"",
+              gst_value_get_fraction_numerator (&value),
+              gst_value_get_fraction_denominator (&value),
+              pfraction->min_num, pfraction->min_den,
+              pfraction->max_num, pfraction->max_den);
+        } else if (G_IS_PARAM_SPEC_ENUM (spec)) {
+          _serialize_enum_default (json, spec->value_type, &value);
+        } else if (G_IS_PARAM_SPEC_FLAGS (spec)) {
+          _serialize_flags_default (json, spec->value_type, &value);
+        }
+        break;
+    }
+
+    g_string_append_c (json, '}');
+
+
+    opened = TRUE;
+  }
+
+  if (opened)
+    g_string_append (json, "}");
+
+}
+
+static gboolean
+print_field (GQuark field, const GValue * value, GString * jcaps)
+{
+  gchar *tmp, *str = gst_value_serialize (value);
+
+  if (!g_strcmp0 (g_quark_to_string (field), "format") ||
+      !g_strcmp0 (g_quark_to_string (field), "rate")) {
+    if (!cleanup_caps_field)
+      cleanup_caps_field = g_regex_new ("\\(string\\)|\\(rate\\)", 0, 0, NULL);
+
+    tmp = str;
+    str = g_regex_replace (cleanup_caps_field, str, -1, 0, "", 0, NULL);;
+    g_free (tmp);
+  }
+
+  g_string_append_printf (jcaps, "%15s: %s\n", g_quark_to_string (field), str);
+  g_free (str);
+  return TRUE;
+}
+
+static gchar *
+_build_caps (const GstCaps * caps)
+{
+  guint i;
+  gchar *res;
+  GString *jcaps = g_string_new (NULL);
+
+  if (gst_caps_is_any (caps)) {
+    g_string_append (jcaps, "ANY");
+    return g_string_free (jcaps, FALSE);
+  }
+
+  if (gst_caps_is_empty (caps)) {
+    g_string_append (jcaps, "EMPTY");
+    return g_string_free (jcaps, FALSE);
+  }
+
+  for (i = 0; i < gst_caps_get_size (caps); i++) {
+    GstStructure *structure = gst_caps_get_structure (caps, i);
+    GstCapsFeatures *features = gst_caps_get_features (caps, i);
+
+    if (features && (gst_caps_features_is_any (features) ||
+            !gst_caps_features_is_equal (features,
+                GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY))) {
+      gchar *features_string = gst_caps_features_to_string (features);
+
+      g_string_append_printf (jcaps, "%s%s(%s):\n",
+          i ? "\n" : "", gst_structure_get_name (structure), features_string);
+      g_free (features_string);
+    } else {
+      g_string_append_printf (jcaps, "%s:\n",
+          gst_structure_get_name (structure));
+    }
+    gst_structure_foreach (structure, (GstStructureForeachFunc) print_field,
+        jcaps);
+  }
+
+  res = json_strescape (jcaps->str);
+  g_string_free (jcaps, TRUE);
+
+  return res;
+}
+
+static void
+_add_element_pad_templates (GString * json, GString * other_types,
+    GHashTable * seen_other_types, GstElement * element,
+    GstElementFactory * factory)
+{
+  gboolean opened = FALSE;
+  const GList *pads;
+  GstStaticPadTemplate *padtemplate;
+  GRegex *re = g_regex_new ("%", 0, 0, NULL);
+  GstPluginAPIFlags api_flags;
+
+  pads = gst_element_factory_get_static_pad_templates (factory);
+  while (pads) {
+    GstCaps *documentation_caps;
+    gchar *name, *caps;
+    GType pad_type;
+    GstPadTemplate *tmpl;
+    padtemplate = (GstStaticPadTemplate *) (pads->data);
+    pads = g_list_next (pads);
+
+    tmpl = gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (element),
+        padtemplate->name_template);
+
+    name = g_regex_replace (re, padtemplate->name_template,
+        -1, 0, "%%", 0, NULL);;
+    documentation_caps = gst_pad_template_get_documentation_caps (tmpl);
+    caps = _build_caps (documentation_caps);
+    gst_caps_replace (&documentation_caps, NULL);
+    g_string_append_printf (json, "%s"
+        "\"%s\": {"
+        "\"caps\": \"%s\","
+        "\"direction\": \"%s\","
+        "\"presence\": \"%s\"",
+        opened ? "," : ",\"pad-templates\": {",
+        name, caps,
+        padtemplate->direction ==
+        GST_PAD_SRC ? "src" : padtemplate->direction ==
+        GST_PAD_SINK ? "sink" : "unknown",
+        padtemplate->presence ==
+        GST_PAD_ALWAYS ? "always" : padtemplate->presence ==
+        GST_PAD_SOMETIMES ? "sometimes" : padtemplate->presence ==
+        GST_PAD_REQUEST ? "request" : "unknown");
+    opened = TRUE;
+    g_free (name);
+
+    pad_type = GST_PAD_TEMPLATE_GTYPE (tmpl);
+    if (pad_type != G_TYPE_NONE && pad_type != GST_TYPE_PAD) {
+      g_string_append_printf (json, ", \"type\": \"%s\"",
+          g_type_name (pad_type));
+
+      if (!g_hash_table_contains (seen_other_types, g_type_name (pad_type))
+          && gst_type_is_plugin_api (pad_type, &api_flags)) {
+        g_hash_table_insert (seen_other_types,
+            (gpointer) g_type_name (pad_type), NULL);
+        _serialize_object (other_types, seen_other_types, pad_type, pad_type);
+      }
+    }
+    g_string_append_c (json, '}');
+  }
+  if (opened)
+    g_string_append_c (json, '}');
+
+  g_regex_unref (re);
+}
+
+static const char *
+get_rank_name (char *s, gint rank)
+{
+  static const int ranks[4] = {
+    GST_RANK_NONE, GST_RANK_MARGINAL, GST_RANK_SECONDARY, GST_RANK_PRIMARY
+  };
+  static const char *rank_names[4] = { "none", "marginal", "secondary",
+    "primary"
+  };
+  int i;
+  int best_i;
+
+  best_i = 0;
+  for (i = 0; i < 4; i++) {
+    if (rank == ranks[i])
+      return rank_names[i];
+    if (abs (rank - ranks[i]) < abs (rank - ranks[best_i])) {
+      best_i = i;
+    }
+  }
+
+  sprintf (s, "%s %c %d", rank_names[best_i],
+      (rank - ranks[best_i] > 0) ? '+' : '-', abs (ranks[best_i] - rank));
+
+  return s;
+}
+
+static void
+_add_factory_details (GString * json, GstElementFactory * factory)
+{
+  gchar **keys, **k;
+  gboolean f = TRUE;
+
+  keys = gst_element_factory_get_metadata_keys (factory);
+  if (keys != NULL) {
+    for (k = keys; *k != NULL; ++k) {
+      gchar *val;
+      gchar *key = *k;
+
+      val = json_strescape (gst_element_factory_get_metadata (factory, key));
+      g_string_append_printf (json, "%s\"%s\": \"%s\"", f ? "" : ",", key, val);
+      f = FALSE;
+      g_free (val);
+    }
+    g_strfreev (keys);
+    g_string_append (json, ",");
+  }
+}
+
+static void
+_add_object_details (GString * json, GString * other_types,
+    GHashTable * seen_other_types, GObject * object, GType type,
+    GType inst_type)
+{
+  GType *interfaces;
+  guint n_interfaces;
+  GType ptype = type;
+
+  g_string_append (json, "\"hierarchy\": [");
+
+  for (;; ptype = g_type_parent (ptype)) {
+    g_string_append_printf (json, "\"%s\"%c", g_type_name (ptype),
+        ((ptype == G_TYPE_OBJECT || ptype == G_TYPE_INTERFACE) ? ' ' : ','));
+
+    if (!g_hash_table_contains (seen_other_types, g_type_name (ptype))
+        && gst_type_is_plugin_api (ptype, NULL)) {
+      g_hash_table_insert (seen_other_types, (gpointer) g_type_name (ptype),
+          NULL);
+      _serialize_object (other_types, seen_other_types, ptype, inst_type);
+    }
+
+    if (ptype == G_TYPE_OBJECT || ptype == G_TYPE_INTERFACE)
+      break;
+  }
+  g_string_append (json, "]");
+
+  interfaces = g_type_interfaces (type, &n_interfaces);
+  if (n_interfaces) {
+    GType *iface;
+
+    g_string_append (json, ",\"interfaces\": [");
+    for (iface = interfaces; *iface; iface++, n_interfaces--) {
+      g_string_append_printf (json, "\"%s\"%c", g_type_name (*iface),
+          n_interfaces > 1 ? ',' : ' ');
+
+      if (!g_hash_table_contains (seen_other_types, g_type_name (*iface))
+          && gst_type_is_plugin_api (*iface, NULL)) {
+        g_hash_table_insert (seen_other_types, (gpointer) g_type_name (*iface),
+            NULL);
+        _serialize_object (other_types, seen_other_types, *iface, inst_type);
+      }
+    }
+
+    g_string_append (json, "]");
+    g_free (interfaces);
+  }
+
+  _add_properties (json, other_types, seen_other_types, object,
+      G_OBJECT_GET_CLASS (object), type);
+  _add_signals (json, other_types, seen_other_types, object, type);
+}
+
+static void
+_add_element_details (GString * json, GString * other_types,
+    GHashTable * seen_other_types, GstPluginFeature * feature)
+{
+  GstElement *element =
+      gst_element_factory_create (GST_ELEMENT_FACTORY (feature), NULL);
+  char s[20];
+
+  g_assert (element);
+
+  g_string_append_printf (json,
+      "\"%s\": {"
+      "\"rank\":\"%s\",",
+      GST_OBJECT_NAME (feature),
+      get_rank_name (s, gst_plugin_feature_get_rank (feature)));
+
+  _add_factory_details (json, GST_ELEMENT_FACTORY (feature));
+  _add_object_details (json, other_types, seen_other_types, G_OBJECT (element),
+      G_OBJECT_TYPE (element), G_OBJECT_TYPE (element));
+
+  _add_element_pad_templates (json, other_types, seen_other_types, element,
+      GST_ELEMENT_FACTORY (feature));
+
+  g_string_append (json, "}");
+}
+
+int
+main (int argc, char *argv[])
+{
+  gchar *libfile;
+  GError *error = NULL;
+  GString *json;
+  GString *other_types;
+  GHashTable *seen_other_types;
+  GstPlugin *plugin;
+  gboolean f = TRUE;
+  GList *features, *tmp;
+  gint i;
+  gboolean first = TRUE;
+  GError *err = NULL;
+
+  g_assert (argc >= 3);
+
+  setlocale (LC_ALL, "");
+  setlocale (LC_NUMERIC, "C");
+
+#ifdef ENABLE_NLS
+  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+  textdomain (GETTEXT_PACKAGE);
+#endif
+
+  gst_init (NULL, NULL);
+
+  json = g_string_new ("{");
+  for (i = 2; i < argc; i++) {
+    gchar *basename, **splitext, *filename;
+    libfile = argv[i];
+    plugin = gst_plugin_load_file (libfile, &error);
+    if (!plugin) {
+      g_printerr ("%s could not be loaded as a GstPlugin: %s", libfile,
+          error->message ? error->message : "no known reasons");
+      g_clear_error (&error);
+
+      continue;
+    }
+
+    other_types = g_string_new ("");
+    seen_other_types = g_hash_table_new (g_str_hash, g_str_equal);
+
+    basename = g_filename_display_basename (libfile);
+    splitext = g_strsplit (basename, ".", 2);
+    filename =
+        g_str_has_prefix (splitext[0], "lib") ? &splitext[0][3] : splitext[0];
+    g_string_append_printf (json,
+        "%s\"%s\": {"
+        "\"description\":\"%s\","
+        "\"filename\":\"%s\","
+        "\"source\":\"%s\","
+        "\"package\":\"%s\","
+        "\"license\":\"%s\","
+        "\"url\":\"%s\","
+        "\"elements\":{",
+        first ? "" : ",",
+        gst_plugin_get_name (plugin),
+        gst_plugin_get_description (plugin),
+        filename,
+        gst_plugin_get_source (plugin),
+        gst_plugin_get_package (plugin),
+        gst_plugin_get_license (plugin), gst_plugin_get_origin (plugin));
+    g_free (basename);
+    g_strfreev (splitext);
+    first = FALSE;
+
+    features =
+        gst_registry_get_feature_list_by_plugin (gst_registry_get (),
+        gst_plugin_get_name (plugin));
+
+    f = TRUE;
+    for (tmp = features; tmp; tmp = tmp->next) {
+      GstPluginFeature *feature = tmp->data;
+      if (GST_IS_ELEMENT_FACTORY (feature)) {
+        if (!f)
+          g_string_append_printf (json, ",");
+        _add_element_details (json, other_types, seen_other_types, feature);
+        f = FALSE;
+      }
+    }
+
+    g_string_append (json, "}, \"tracers\": {");
+    gst_plugin_feature_list_free (features);
+
+    f = TRUE;
+    features =
+        gst_registry_get_feature_list_by_plugin (gst_registry_get (),
+        gst_plugin_get_name (plugin));
+    for (tmp = features; tmp; tmp = tmp->next) {
+      GstPluginFeature *feature = tmp->data;
+
+      if (GST_IS_TRACER_FACTORY (feature)) {
+        if (!f)
+          g_string_append_printf (json, ",");
+        g_string_append_printf (json, "\"%s\": {}", GST_OBJECT_NAME (feature));
+        f = FALSE;
+      }
+    }
+    g_string_append_printf (json, "}, \"other-types\": {%s}}",
+        other_types->str);
+    gst_plugin_feature_list_free (features);
+
+    g_hash_table_unref (seen_other_types);
+    g_string_free (other_types, TRUE);
+  }
+
+  g_string_append_c (json, '}');
+  if (!g_file_set_contents (argv[1], json->str, -1, &err)) {
+    g_printerr ("Could not set json to %s: %s", argv[1], err->message);
+    g_clear_error (&err);
+
+    return -1;
+  }
+  g_string_free (json, TRUE);
+
+  return 0;
+}
diff --git a/docs/gst-plugins-doc-cache-generator.py b/docs/gst-plugins-doc-cache-generator.py
new file mode 100755 (executable)
index 0000000..c1283e7
--- /dev/null
@@ -0,0 +1,135 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2018 Thibault Saunier <tsaunier@igalia.com>
+#
+# This library is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation; either version 2.1 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 Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library.  If not, see <http://www.gnu.org/licenses/>.
+
+import argparse
+import json
+import os
+import sys
+import re
+import subprocess
+import tempfile
+
+from collections import OrderedDict
+try:
+    from collections.abc import Mapping
+except ImportError:  # python <3.3
+    from collections import Mapping
+
+
+# Marks values in the json file as "unstable" so that they are
+# not updated automatically, this aims at making the cache file
+# stable and handle corner cases were we can't automatically
+# make it happen. For properties, the best way is to use th
+# GST_PARAM_DOC_SHOW_DEFAULT flag.
+UNSTABLE_VALUE = "unstable-values"
+
+
+
+def dict_recursive_update(d, u):
+    modified = False
+    unstable_values = d.get(UNSTABLE_VALUE, [])
+    if not isinstance(unstable_values, list):
+        unstable_values = [unstable_values]
+    for k, v in u.items():
+        if isinstance(v, Mapping):
+            r = d.get(k, {})
+            modified |= dict_recursive_update(r, v)
+            d[k] = r
+        elif k not in unstable_values:
+            modified = True
+            if k == "package":
+                d[k] = re.sub(" git$| source release$| prerelease$", "", v)
+            else:
+                d[k] = u[k]
+    return modified
+
+
+def test_unstable_values():
+    current_cache = { "v1": "yes", "unstable-values": "v1"}
+    new_cache = { "v1": "no" }
+
+    assert(dict_recursive_update(current_cache, new_cache) == False)
+
+    new_cache = { "v1": "no", "unstable-values": "v2" }
+    assert(dict_recursive_update(current_cache, new_cache) == True)
+
+    current_cache = { "v1": "yes", "v2": "yay", "unstable-values": "v1",}
+    new_cache = { "v1": "no" }
+    assert(dict_recursive_update(current_cache, new_cache) == False)
+
+    current_cache = { "v1": "yes", "v2": "yay", "unstable-values": "v2"}
+    new_cache = { "v1": "no", "v2": "unstable" }
+    assert (dict_recursive_update(current_cache, new_cache) == True)
+    assert (current_cache == { "v1": "no", "v2": "yay", "unstable-values": "v2" })
+
+if __name__ == "__main__":
+    cache_filename = sys.argv[1]
+    output_filename = sys.argv[2]
+    build_root = os.environ.get('MESON_BUILD_ROOT', '')
+
+    subenv = os.environ.copy()
+    cache = {}
+    try:
+        with open(cache_filename, newline='\n', encoding='utf8') as f:
+            cache = json.load(f)
+    except FileNotFoundError:
+        pass
+
+    out = output_filename + '.tmp'
+    cmd = [os.path.join(os.path.dirname(os.path.realpath(__file__)), 'gst-hotdoc-plugins-scanner'), out]
+    gst_plugins_paths = []
+    for plugin_path in sys.argv[3:]:
+        cmd.append(plugin_path)
+        gst_plugins_paths.append(os.path.dirname(plugin_path))
+
+    try:
+        with open(os.path.join(build_root, 'GstPluginsPath.json'), newline='\n', encoding='utf8') as f:
+            plugin_paths = os.pathsep.join(json.load(f))
+    except FileNotFoundError:
+        plugin_paths = ""
+
+    if plugin_paths:
+        subenv['GST_PLUGIN_PATH'] = subenv.get('GST_PLUGIN_PATH', '') + ':' + plugin_paths
+
+    # Hide stderr unless an actual error happens as we have cases where we get g_warnings
+    # and other issues because plugins are being built while `gst_init` is called
+    stderrlogfile = output_filename + '.stderr'
+    with open(stderrlogfile, 'w', encoding='utf8') as log:
+        try:
+            data = subprocess.check_output(cmd, env=subenv, stderr=log, encoding='utf8', universal_newlines=True)
+        except subprocess.CalledProcessError as e:
+            log.flush()
+            with open(stderrlogfile, 'r', encoding='utf8') as f:
+                print(f.read(), file=sys.stderr)
+            raise
+
+    with open(out, 'r', newline='\n', encoding='utf8') as jfile:
+        try:
+            plugins = json.load(jfile, object_pairs_hook=OrderedDict)
+        except json.decoder.JSONDecodeError:
+            print("Could not decode:\n%s" % jfile.read(), file=sys.stderr)
+            raise
+
+    modified = dict_recursive_update(cache, plugins)
+
+    with open(output_filename, 'w', newline='\n', encoding='utf8') as f:
+        json.dump(cache, f, indent=4, sort_keys=True, ensure_ascii=False)
+
+    if modified:
+        with open(cache_filename, 'w', newline='\n', encoding='utf8') as f:
+            json.dump(cache, f, indent=4, sort_keys=True, ensure_ascii=False)
diff --git a/docs/gst/.gitignore b/docs/gst/.gitignore
deleted file mode 100644 (file)
index 605ca2e..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-Makefile
-Makefile.in
-gstreamer-decl-list.txt
-gstreamer-decl.txt
-gstreamer-undocumented.txt
-gstreamer-unused.txt
-gstreamer-undeclared.txt
-
-gstreamer.args
-gstreamer.hierarchy
-gstreamer.interfaces
-gstreamer.prerequisites
-gstreamer.signals
-
-html
-sgml
-tmpl
-*.stamp
-
-doc-registry.xml
-
-gstreamer.html
-gstreamer-presed-scan.c
-gstreamer-scan.c
-gstreamer-scan
-tmpl.stamp
-tmpl-build.stamp
-sgml.stamp
-sgml-build.stamp
-scan-build.stamp
-html.stamp
-html-build.stamp
-*.tgz
-*.tex
-*.log
-*.aux
-*.dvi
-*.ps
-*.bak
-gtkdoc-fixxref
-xml
-
-gst-universe.svg
-
-gstreamer.types
-gstreamer-scan.gcno
diff --git a/docs/gst/Makefile.am b/docs/gst/Makefile.am
deleted file mode 100644 (file)
index af93687..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-# The name of the module, e.g. 'glib'.
-# DOC_MODULE=gstreamer-@GST_API_VERSION@
-DOC_MODULE=gstreamer
-
-# don't want $(DOC_MODULE)-scan.c to be built with -Werror
-ERROR_CFLAGS=
-
-BUILT_SOURCES=gstreamer.types
-
-# for upload-doc.mak
-DOC=gstreamer
-FORMATS=html
-html: html-build.stamp
-include $(top_srcdir)/common/upload-doc.mak
-
-# The top-level SGML file. Change it if you want.
-DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
-
-# The files containing the source code. Relative to $(top_srcdir).
-# gtk-doc will search all .c & .h files beneath here for inline comments
-# documenting functions and macros.
-DOC_SOURCE_DIR = $(top_srcdir)/gst
-
-# Extra options to supply to gtkdoc-scan.
-SCAN_OPTIONS=--deprecated-guards="GST_DISABLE_DEPRECATED" \
-  --ignore-decorators='GST_API'
-
-# Extra options to supply to gtkdoc-mkdb.
-MKDB_OPTIONS=--sgml-mode --output-format=xml --ignore-files=parse
-
-# Extra options to supply to gtkdoc-fixref.
-FIXXREF_OPTIONS=--extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html
-
-# Used for dependencies.
-HFILE_GLOB=$(top_srcdir)/gst/*.h
-CFILE_GLOB=$(top_srcdir)/gst/*.c
-
-# Header files to ignore when scanning. Use base file name, no paths
-IGNORE_HFILES= \
-       gettext.h \
-       glib-compat-private.h \
-       glib-compat.h \
-       gst-i18n-app.h \
-       gst-i18n-lib.h \
-       gst_private.h \
-       gstelementdetails.h \
-       gstmacros.h \
-       gstmarshal.h \
-       math-compat.h \
-       \
-       grammar.tab.h \
-       grammar.tab.pre.h \
-  parse_lex.h \
-       types.h \
-       \
-       gst-printf.h \
-       printf-args.h \
-       printf-extension.h \
-       printf-parse.h \
-       vasnprintf.h
-
-gst-universe.svg: gst-universe.dot
-       -dot -Tsvg $< | sed 's/\(font-size:[0-9]*\.[0-9]*\);/\1px;/g' >$@
-
-# Images to copy into HTML directory.
-HTML_IMAGES =
-
-# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
-content_files = building.xml running.xml gst-universe.svg
-
-# Other files to distribute.
-extra_files = gst-universe.dot
-
-# CFLAGS and LDFLAGS for compiling scan program. Only needed if your app/lib
-# contains GtkObjects/GObjects and you want to document signals and properties.
-GTKDOC_CFLAGS = $(GST_OBJ_CFLAGS) -DGST_USE_UNSTABLE_API
-GTKDOC_LIBS = $(GST_OBJ_LIBS) \
-       $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la \
-       $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \
-       $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \
-       $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la
-
-GTKDOC_EXTRA_ENVIRONMENT= \
-    GST_PLUGIN_SCANNER_1_0=$(top_builddir)/libs/gst/helpers/gst-plugin-scanner
-
-# If you need to override some of the declarations, place them in this file
-# and uncomment this line.
-DOC_OVERRIDES = $(DOC_MODULE)-overrides.txt
-
-include $(top_srcdir)/common/gtk-doc.mak
-
-# gtk-doc.mak defines CLEANFILES
-CLEANFILES += gst-universe.svg
-
diff --git a/docs/gst/building.md b/docs/gst/building.md
new file mode 100644 (file)
index 0000000..c1239e5
--- /dev/null
@@ -0,0 +1,44 @@
+---
+title: Building GStreamer and GStreamer Applications
+short-description: How to build the GStreamer framework and applications using it.
+...
+
+# Building GStreamer on UNIX
+
+On UNIX, GStreamer uses the standard GNU build system, using autoconf
+for package configuration and resolving portability issues, automake for
+building makefiles that comply with the GNU Coding Standards, and
+libtool for building shared libraries on multiple platforms. The normal
+sequence for compiling and installing the GStreamer library is thus:
+`./configure` `make` `make install`
+
+The standard options provided by GNU autoconf may be passed to the
+`configure` script. Please see the autoconf documentation or run
+`./configure --help` for information about the standard options.
+
+In addition there are several options to activate or deactivate
+features. E.g. passing `--disable-gst-debug` to `configure` will turn
+the debugging subsystem into a non-functional stub and remove all macro
+based invocations from within the library (and anything compiled against
+the library afterwards.)
+
+If library size matters and one builds in a controlled environment, it
+is also possible to totally remove subsystem code. This is intentionally
+not offered as a configure option as it causes an ABI break. Code built
+against a version of GStreamer without these modifications needs to be
+recompiled.
+`make CFLAGS="-DGST_REMOVE_DEPRECATED -DGST_REMOVE_DISABLED"`
+
+-   `GST_REMOVE_DEPRECATED` - Omit deprecated functions from the
+    library.
+
+-   `GST_REMOVE_DISABLED` - Omit stubs for disabled subsystems from the
+    library.
+
+# Building GStreamer Applications
+
+Applications and libraries can use `pkg-config` to get all the needed
+compiler and linker flags to build against GStreamer. Please note that
+GStreamer is split into several libraries itself.
+`pkg-config --list-all | grep gstreamer` will list the available
+libraries.
diff --git a/docs/gst/building.xml b/docs/gst/building.xml
deleted file mode 100644 (file)
index a7f8fc5..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
-               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
-<!ENTITY % version-entities SYSTEM "version.entities">
-%version-entities;
-<!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
-]>
-<refentry id="gst-building" revision="25 mar 2009">
-<refmeta>
-<refentrytitle>Building GStreamer and GStreamer Applications</refentrytitle>
-<manvolnum>3</manvolnum>
-<refmiscinfo>GStreamer Core</refmiscinfo>
-</refmeta>
-
-<refnamediv>
-<refname>Building GStreamer and GStreamer Applications</refname>
-<refpurpose>
-How to build the GStreamer framework and applications using it.
-</refpurpose>
-</refnamediv>
-
-<refsect1>
-<title>Building GStreamer on UNIX</title>
-
-  <!-- this has been borrowed from the glib docs -->
-  <para>
-    On UNIX, GStreamer uses the standard GNU build system,
-    using <application>autoconf</application> for package
-    configuration and resolving portability issues,
-    <application>automake</application> for building makefiles
-    that comply with the GNU Coding Standards, and
-    <application>libtool</application> for building shared
-    libraries on multiple platforms.  The normal sequence for
-    compiling and installing the GStreamer library is thus:
-
-    <literallayout>
-      <userinput>./configure</userinput>
-      <userinput>make</userinput>
-      <userinput>make install</userinput>
-    </literallayout>
-  </para>
-
-  <para>
-    The standard options provided by <application>GNU
-    autoconf</application> may be passed to the
-    <command>configure</command> script.  Please see the
-    <application>autoconf</application> documentation or run
-    <command>./configure --help</command> for information about
-    the standard options.
-  </para>
-
-  <para>
-    In addition there are several options to activate or deactivate features.
-    E.g. passing <option>--disable-gst-debug</option> to <command>configure</command>
-    will turn the debugging subsystem into a non-functional stub and remove all
-    macro based invocations from within the library (and anything compiled
-    against the library afterwards.)
-  </para>
-  <para>
-    If library size matters and one builds in a controlled environment, it is
-    also possible to totally remove subsystem code. This is intentionally not
-    offered as a configure option as it causes an ABI break. Code built against
-    a version of GStreamer without these modifications needs to be recompiled.
-
-    <literallayout>
-      <userinput>make CFLAGS="-DGST_REMOVE_DEPRECATED -DGST_REMOVE_DISABLED"</userinput>
-    </literallayout>
-
-    <itemizedlist>
-      <listitem>
-        <para>
-          <symbol>GST_REMOVE_DEPRECATED</symbol> - Omit deprecated functions
-          from the library.
-        </para>
-      </listitem>
-      <listitem>
-        <para>
-          <symbol>GST_REMOVE_DISABLED</symbol> - Omit stubs for disabled
-          subsystems from the library.
-        </para>
-      </listitem>
-    </itemizedlist>
-  </para>
-
-</refsect1>
-
-<refsect1>
-<title>Building GStreamer Applications</title>
-
-<para>
-Applications and libraries can use <command>pkg-config</command> to get all the
-needed compiler and linker flags to build against GStreamer. Please note that
-GStreamer is split into several libraries itself.
-<command>pkg-config --list-all | grep gstreamer</command> will list the
-available libraries.
-</para>
-
-</refsect1>
-
-</refentry>
diff --git a/docs/gst/gi-index.md b/docs/gst/gi-index.md
new file mode 100644 (file)
index 0000000..5d0b7e9
--- /dev/null
@@ -0,0 +1,6 @@
+# Core Library
+
+libgstreamer-{{ gst_api_version.md }}.so provides all the core GStreamer
+services, including initialization, plugin management and types, as well
+as the object hierarchy that defines elements and bins, along with some
+more specialized elements.
diff --git a/docs/gst/gst-universe.dot b/docs/gst/gst-universe.dot
deleted file mode 100644 (file)
index 46f6b5c..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/* dot -Tpng gst-universe.dot -ogst-universe.png
- *
- * other layouts:
- * circo -Tpng gst-universe.dot -ogst-universe.circo.png
- * neato -Tpng gst-universe.dot -ogst-universe.neato.png
- *
- * todo:
- * - add urls to api docs
- * - use color
- */
-digraph pipeline {
-  node [style="filled", shape="box", fillcolor="#eeeeee", fontsize="9px", fontname="Bitstream Vera Sans", target="_top"];
-  edge [labelfontsize="7px", fontsize="7px", labelfontname="Bitstream Vera Sans", fontname="Bitstream Vera Sans"];
-  labelloc=t;
-  nodesep=0.25;
-
-  /*
-  fontname="Bitstream Vera Sans";
-  fontsize="10px";
-  label="GStreamer Universe";
-  */
-  
-  /* objects */
-  application [color=black, fillcolor="#ffdddd"];
-  bin [href="GstBin.html", color=black, fillcolor="#ccccff"];
-  bus [href="GstBus.html"];
-  buffer [href="gstreamer-GstBuffer.html", color=black, fillcolor="#ddffdd"];
-  caps [href="gstreamer-GstCaps.html"];
-  clock [href="GstClock.html"];
-  element [href="GstElement.html", color=black, fillcolor="#ccccff"];
-  element_factory [href="GstElementFactory.html", label="element factory"];
-  event [href="gstreamer-GstEvent.html", color=black, fillcolor="#ddffdd"];
-  message [href="gstreamer-GstMessage.html", color=black, fillcolor="#ddffdd"];
-  pad [href="GstPad.html", color=black, fillcolor="#ccccff"];
-  pad_template [href="GstPadTemplate.html", label="pad template"];
-  pipeline [href="GstPipeline.html", color=black, fillcolor="#ccccff"];
-  plugin [href="GstPlugin.html"];
-  plugin_feature [href="GstPluginFeature.html", label="plugin feature"];
-  query [href="gstreamer-GstQuery.html", color=black, fillcolor="#ddffdd"];
-  registry [href="GstRegistry.html"];
-  structure [href="gstreamer-GstStructure.html"];
-  
-  /* relations */
-  bin -> element [label="is-a"];
-  pipeline -> bin [label="is-a"];
-  pipeline -> bus [label="has 1"];
-  pipeline -> clock [label="has 1"];
-  element -> pad_template [label="has n"];
-  element -> pad [label="has n"];
-  element -> clock [label="may provide"];
-  pad -> caps [label="has n"];
-  pad_template -> caps [label="has n"];
-  buffer -> caps [label="has n"];
-  caps -> structure [label="has n"];
-  bin -> element [label="has n"];
-    
-  pad -> pad_template [label="is created from"];
-  element -> element_factory [label="is created from"];
-    
-  element -> query [label="answers"];
-  element -> event [label="send & receive"];
-  element -> buffer [label="send & receive"];
-  element -> message [label="send"];
-  bus -> message [label="receive"];
-    
-  registry -> plugin [label="has n"];
-  plugin -> plugin_feature [label="has n"];
-  element_factory -> plugin_feature [label="is-a"];
-    
-  application -> pipeline [label="has"];
-  application -> bus [label="listen on"];
-  application -> query [label="send"];
-  application -> event [label="send"];
-}
diff --git a/docs/gst/gstreamer-docs.sgml b/docs/gst/gstreamer-docs.sgml
deleted file mode 100644 (file)
index c2f6511..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
-               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
-<!ENTITY % version-entities SYSTEM "version.entities">
-%version-entities;
-<!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
-<!ENTITY hash "#">
-]>
-<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
-  <bookinfo>
-    <title>GStreamer &GST_API_VERSION; Core Reference Manual</title>
-    <releaseinfo>
-      for GStreamer Core &GST_API_VERSION; (&GST_VERSION;)
-      The latest version of this documentation can be found on-line at
-      <ulink role="online-location" url="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/">http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/</ulink>.
-    </releaseinfo>
-  </bookinfo>
-
-  <chapter id="gstreamer">
-
-    <title>GStreamer Overview</title>
-    <para>
-GStreamer is a streaming media framework.
-It uses graphs of elements which operate on data.
-The functionality to process media is provided by plug-ins which provide
-features like elements, typefinding, and so on.
-This allows new functionality to be added simply by installing new plug-ins.
-    </para>
-
-    <para>
-GStreamer is cross-platform and works on most UNIX-like platforms as well as
-Windows.  It is released under the GNU Library General Public License
-(GNU LGPL).
-    </para>
-
-    <mediaobject>
-      <imageobject>
-        <imagedata fileref="gst-universe.svg" format="SVG"/>
-      </imageobject>
-      <caption>
-        <para>Relation between gstreamer core objects.</para>
-      </caption>
-    </mediaobject>
-
-    <xi:include href="building.xml" />
-    <xi:include href="running.xml" />
-  </chapter>
-
-  <chapter id="libgstreamer">
-    <title>GStreamer Core Library</title>
-
-    <para>
-      libgstreamer-&GST_API_VERSION;.so provides all the core GStreamer services,
-      including initialization, plugin management and types,
-      as well as the object hierarchy that defines elements and bins,
-      along with some more specialized elements.
-    </para>
-
-    <xi:include href="xml/gst.xml" />
-    <xi:include href="xml/gstallocator.xml" />
-    <xi:include href="xml/gstatomicqueue.xml" />
-    <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/gstcapsfeatures.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/gstcontext.xml" />
-    <xi:include href="xml/gstcontrolbinding.xml" />
-    <xi:include href="xml/gstcontrolsource.xml" />
-    <xi:include href="xml/gstdatetime.xml" />
-    <xi:include href="xml/gstdynamictypefactory.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/gstformat.xml" />
-    <xi:include href="xml/gstghostpad.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" />
-    <xi:include href="xml/gstpadtemplate.xml" />
-    <xi:include href="xml/gstparamspec.xml" />
-    <xi:include href="xml/gstparse.xml" />
-    <xi:include href="xml/gstpipeline.xml" />
-    <xi:include href="xml/gstplugin.xml" />
-    <xi:include href="xml/gstpluginfeature.xml" />
-    <xi:include href="xml/gstpoll.xml" />
-    <xi:include href="xml/gstpreset.xml" />
-    <xi:include href="xml/gstpromise.xml" />
-    <xi:include href="xml/gstprotection.xml" />
-    <xi:include href="xml/gstquery.xml" />
-    <xi:include href="xml/gstregistry.xml" />
-    <xi:include href="xml/gstsegment.xml" />
-    <xi:include href="xml/gststreams.xml" />
-    <xi:include href="xml/gststreamcollection.xml" />
-    <xi:include href="xml/gststructure.xml" />
-    <xi:include href="xml/gstsystemclock.xml" />
-    <xi:include href="xml/gsttaglist.xml" />
-    <xi:include href="xml/gsttagsetter.xml" />
-    <xi:include href="xml/gsttask.xml" />
-    <xi:include href="xml/gsttaskpool.xml" />
-    <xi:include href="xml/gsttoc.xml" />
-    <xi:include href="xml/gsttocsetter.xml" />
-    <xi:include href="xml/gsttypefind.xml" />
-    <xi:include href="xml/gsttypefindfactory.xml" />
-    <xi:include href="xml/gsturi.xml" />
-    <xi:include href="xml/gsturihandler.xml" />
-    <xi:include href="xml/gstutils.xml" />
-    <xi:include href="xml/gstvalue.xml" />
-    <xi:include href="xml/gstversion.xml" />
-
-  </chapter>
-
-  <chapter id="gstreamer-device-probing">
-    <title>GStreamer Device Discovery and Device Probing</title>
-    <xi:include href="xml/gstdevicemonitor.xml" />
-    <xi:include href="xml/gstdevice.xml" />
-    <xi:include href="xml/gstdeviceprovider.xml" />
-    <xi:include href="xml/gstdeviceproviderfactory.xml" />
-  </chapter>
-
-  <chapter id="gstreamer-support">
-    <title>GStreamer Core Support</title>
-    <para>
-      Theses modules support the gstreamer core and plugin development.
-      Application developers will rarely need to know about it.
-    </para>
-
-    <xi:include href="xml/gstinfo.xml" />
-    <xi:include href="xml/gsttracer.xml" />
-    <xi:include href="xml/gsttracerfactory.xml" />
-    <xi:include href="xml/gsttracerrecord.xml" />
-
-  </chapter>
-
-  <chapter id="gstreamer-hierarchy">
-    <title>Object Hierarchy</title>
-    <xi:include href="xml/tree_index.sgml"/>
-  </chapter>
-
-  <index>
-    <title>API Index</title>
-    <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
-  </index>
-  <index role="deprecated">
-    <title>Index of deprecated API</title>
-    <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.14</title>
-    <xi:include href="xml/api-index-1.14.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.12</title>
-    <xi:include href="xml/api-index-1.12.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.10</title>
-    <xi:include href="xml/api-index-1.10.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.8</title>
-    <xi:include href="xml/api-index-1.8.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.6</title>
-    <xi:include href="xml/api-index-1.6.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.4</title>
-    <xi:include href="xml/api-index-1.4.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.2.3</title>
-    <xi:include href="xml/api-index-1.2.3.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.2</title>
-    <xi:include href="xml/api-index-1.2.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.0.10</title>
-    <xi:include href="xml/api-index-1.0.10.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.0.5</title>
-    <xi:include href="xml/api-index-1.0.5.xml"><xi:fallback /></xi:include>
-  </index>
-
-  <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
-
-</book>
diff --git a/docs/gst/gstreamer-overrides.txt b/docs/gst/gstreamer-overrides.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt
deleted file mode 100644 (file)
index 1af775a..0000000
+++ /dev/null
@@ -1,4014 +0,0 @@
-# GStreamer API reference sections
-
-# please add sections in alphabetical order using the following template
-# leave two empty lines between sections
-# <SECTION>
-# <FILE>gstxxx</FILE>
-# <TITLE>GstXxx</TITLE>
-# typedefs
-# macros
-# constructor
-# methods
-# <SUBSECTION Standard>
-# <SUBSECTION Private>
-# </SECTION>
-
-<INCLUDE>gst/gst.h</INCLUDE>
-
-
-<SECTION>
-<FILE>gst</FILE>
-<TITLE>Gst</TITLE>
-gst_init
-gst_init_check
-gst_init_get_option_group
-gst_is_initialized
-gst_deinit
-gst_version
-gst_version_string
-gst_segtrap_is_enabled
-gst_segtrap_set_enabled
-gst_registry_fork_is_enabled
-gst_registry_fork_set_enabled
-gst_update_registry
-gst_get_main_executable_path
-<SUBSECTION Private>
-GST_QUARK
-GstQuarkId
-GstPluginLoader
-GstPluginLoaderFuncs
-</SECTION>
-
-<SECTION>
-<FILE>gstatomicqueue</FILE>
-<TITLE>GstAtomicQueue</TITLE>
-GstAtomicQueue
-gst_atomic_queue_new
-
-gst_atomic_queue_ref
-gst_atomic_queue_unref
-
-gst_atomic_queue_push
-gst_atomic_queue_peek
-gst_atomic_queue_pop
-
-gst_atomic_queue_length
-
-<SUBSECTION Standard>
-GST_TYPE_ATOMIC_QUEUE
-gst_atomic_queue_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstbin</FILE>
-<TITLE>GstBin</TITLE>
-GstBin
-GstBinClass
-
-gst_bin_new
-gst_bin_add
-gst_bin_remove
-
-gst_bin_get_by_name
-gst_bin_get_by_name_recurse_up
-gst_bin_get_by_interface
-
-gst_bin_iterate_elements
-gst_bin_iterate_recurse
-gst_bin_iterate_sinks
-gst_bin_iterate_sorted
-gst_bin_iterate_sources
-gst_bin_iterate_all_by_interface
-
-gst_bin_recalculate_latency
-
-gst_bin_get_suppressed_flags
-gst_bin_set_suppressed_flags
-
-<SUBSECTION>
-gst_bin_add_many
-gst_bin_remove_many
-gst_bin_find_unlinked_pad
-gst_bin_sync_children_states
-
-<SUBSECTION>
-GstBinFlags
-
-GST_BIN_IS_NO_RESYNC
-
-GST_BIN_CHILDREN
-GST_BIN_CHILDREN_COOKIE
-GST_BIN_NUMCHILDREN
-
-<SUBSECTION Standard>
-GST_BIN
-GST_IS_BIN
-GST_TYPE_BIN
-GST_BIN_CLASS
-GST_IS_BIN_CLASS
-GST_BIN_GET_CLASS
-GST_TYPE_BIN_FLAGS
-GST_BIN_CAST
-<SUBSECTION Private>
-gst_bin_get_type
-gst_bin_flags_get_type
-GstBinPrivate
-</SECTION>
-
-
-<SECTION>
-<FILE>gstbus</FILE>
-<TITLE>GstBus</TITLE>
-GstBus
-GstBusFlags
-GstBusSyncReply
-GstBusFunc
-GstBusSyncHandler
-gst_bus_new
-gst_bus_post
-gst_bus_have_pending
-gst_bus_peek
-gst_bus_pop
-gst_bus_pop_filtered
-gst_bus_timed_pop
-gst_bus_timed_pop_filtered
-gst_bus_set_flushing
-gst_bus_set_sync_handler
-gst_bus_sync_signal_handler
-gst_bus_get_pollfd
-gst_bus_create_watch
-gst_bus_add_watch_full
-gst_bus_add_watch
-gst_bus_remove_watch
-gst_bus_disable_sync_message_emission
-gst_bus_enable_sync_message_emission
-gst_bus_async_signal_func
-gst_bus_add_signal_watch
-gst_bus_add_signal_watch_full
-gst_bus_remove_signal_watch
-gst_bus_poll
-<SUBSECTION Standard>
-GstBusClass
-GST_BUS
-GST_IS_BUS
-GST_TYPE_BUS
-GST_BUS_CLASS
-GST_IS_BUS_CLASS
-GST_BUS_GET_CLASS
-GST_TYPE_BUS_FLAGS
-GST_TYPE_BUS_SYNC_REPLY
-GST_BUS_CAST
-<SUBSECTION Private>
-gst_bus_get_type
-gst_bus_flags_get_type
-gst_bus_sync_reply_get_type
-GstBusPrivate
-</SECTION>
-
-
-<SECTION>
-<FILE>gstbuffer</FILE>
-<TITLE>GstBuffer</TITLE>
-GstBuffer
-GstBufferFlags
-GST_BUFFER_FLAGS
-GST_BUFFER_FLAG_IS_SET
-GST_BUFFER_FLAG_SET
-GST_BUFFER_FLAG_UNSET
-
-GST_BUFFER_PTS
-GST_BUFFER_DTS
-GST_BUFFER_DTS_OR_PTS
-GST_BUFFER_DURATION
-GST_BUFFER_OFFSET
-GST_BUFFER_OFFSET_END
-GST_BUFFER_OFFSET_NONE
-GST_BUFFER_DURATION_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
-
-gst_buffer_new
-gst_buffer_new_allocate
-gst_buffer_new_wrapped
-gst_buffer_new_wrapped_bytes
-gst_buffer_new_wrapped_full
-
-gst_buffer_ref
-gst_buffer_unref
-
-gst_buffer_get_sizes
-gst_buffer_get_size
-gst_buffer_get_sizes_range
-gst_buffer_resize_range
-gst_buffer_resize
-gst_buffer_set_size
-gst_buffer_get_max_memory
-
-gst_buffer_peek_memory
-
-gst_buffer_n_memory
-gst_buffer_insert_memory
-gst_buffer_replace_memory_range
-gst_buffer_get_memory_range
-gst_buffer_remove_memory_range
-gst_buffer_find_memory
-
-gst_buffer_prepend_memory
-gst_buffer_append_memory
-gst_buffer_replace_memory
-gst_buffer_replace_all_memory
-gst_buffer_get_memory
-gst_buffer_get_all_memory
-gst_buffer_remove_memory
-gst_buffer_remove_all_memory
-
-gst_buffer_is_all_memory_writable
-gst_buffer_is_memory_range_writable
-
-gst_buffer_map
-gst_buffer_map_range
-gst_buffer_unmap
-
-gst_buffer_memcmp
-gst_buffer_extract
-gst_buffer_extract_dup
-gst_buffer_fill
-gst_buffer_memset
-
-GstBufferCopyFlags
-GST_BUFFER_COPY_METADATA
-GST_BUFFER_COPY_ALL
-gst_buffer_copy
-gst_buffer_copy_into
-gst_buffer_copy_region
-gst_buffer_copy_deep
-
-gst_buffer_is_writable
-gst_buffer_make_writable
-gst_buffer_replace
-
-gst_buffer_append
-gst_buffer_append_region
-
-gst_buffer_get_meta
-gst_buffer_get_n_meta
-gst_buffer_add_meta
-gst_buffer_remove_meta
-gst_buffer_iterate_meta
-gst_buffer_iterate_meta_filtered
-GstBufferForeachMetaFunc
-gst_buffer_foreach_meta
-
-GstParentBufferMeta
-gst_buffer_add_parent_buffer_meta
-gst_buffer_get_parent_buffer_meta
-
-GstReferenceTimestampMeta
-gst_buffer_add_reference_timestamp_meta
-gst_buffer_get_reference_timestamp_meta
-
-gst_buffer_get_flags
-gst_buffer_set_flags
-gst_buffer_unset_flags
-gst_buffer_has_flags
-
-<SUBSECTION Standard>
-GstBufferClass
-GST_BUFFER
-GST_IS_BUFFER
-GST_TYPE_BUFFER
-GST_TYPE_BUFFER_FLAGS
-GST_TYPE_BUFFER_COPY_FLAGS
-GST_BUFFER_CAST
-GST_PARENT_BUFFER_META_INFO
-GST_PARENT_BUFFER_META_API_TYPE
-GST_TYPE_PARENT_BUFFER_META_API_TYPE
-gst_parent_buffer_meta_get_info
-GST_REFERENCE_TIMESTAMP_META_INFO
-GST_REFERENCE_TIMESTAMP_META_API_TYPE
-gst_reference_timestamp_meta_get_info
-<SUBSECTION Private>
-gst_buffer_get_type
-gst_buffer_flags_get_type
-gst_buffer_copy_flags_get_type
-gst_parent_buffer_meta_api_get_type
-gst_reference_timestamp_meta_api_get_type
-GST_BUFFER_TIMESTAMP
-GST_BUFFER_TIMESTAMP_IS_VALID
-</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
-GstMetaTransformFunction
-GstMetaTransformCopy
-GST_META_TRANSFORM_IS_COPY
-gst_meta_api_type_register
-gst_meta_api_type_has_tag
-gst_meta_api_type_get_tags
-GST_META_TAG_MEMORY
-GST_META_TAG_MEMORY_STR
-gst_meta_register
-gst_meta_get_info
-gst_meta_get_seqnum
-gst_meta_compare_seqnum
-<SUBSECTION Standard>
-GST_META_CAST
-<SUBSECTION Private>
-GST_TYPE_META_FLAGS
-gst_meta_flags_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstbufferpool</FILE>
-<TITLE>GstBufferPool</TITLE>
-GstBufferPool
-GstBufferPoolClass
-GST_BUFFER_POOL_IS_FLUSHING
-gst_buffer_pool_new
-
-gst_buffer_pool_config_get_params
-gst_buffer_pool_config_set_params
-gst_buffer_pool_config_validate_params
-gst_buffer_pool_config_get_allocator
-gst_buffer_pool_config_set_allocator
-
-gst_buffer_pool_config_n_options
-gst_buffer_pool_config_add_option
-gst_buffer_pool_config_get_option
-gst_buffer_pool_config_has_option
-
-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_set_flushing
-
-GstBufferPoolAcquireFlags
-GstBufferPoolAcquireParams
-gst_buffer_pool_acquire_buffer
-gst_buffer_pool_release_buffer
-<SUBSECTION Standard>
-GST_BUFFER_POOL_CLASS
-GST_BUFFER_POOL_CAST
-GST_BUFFER_POOL
-GST_IS_BUFFER_POOL
-GST_TYPE_BUFFER_POOL
-GST_TYPE_BUFFER_POOL_ACQUIRE_FLAGS
-gst_buffer_pool_acquire_flags_get_type
-GST_IS_BUFFER_POOL_CLASS
-GST_BUFFER_POOL_GET_CLASS
-<SUBSECTION Private>
-gst_buffer_pool_get_type
-GstBufferPoolPrivate
-</SECTION>
-
-<SECTION>
-<FILE>gstbufferlist</FILE>
-<TITLE>GstBufferList</TITLE>
-GstBufferList
-
-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_clear_buffer_list
-gst_buffer_list_copy
-gst_buffer_list_copy_deep
-gst_buffer_list_is_writable
-gst_buffer_list_make_writable
-gst_buffer_list_replace
-gst_buffer_list_take
-
-GstBufferListFunc
-gst_buffer_list_foreach
-gst_buffer_list_get
-gst_buffer_list_get_writable
-
-gst_buffer_list_calculate_size
-
-<SUBSECTION Standard>
-GST_BUFFER_LIST
-GST_IS_BUFFER_LIST
-GST_TYPE_BUFFER_LIST
-GST_BUFFER_LIST_CAST
-<SUBSECTION Private>
-gst_buffer_list_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstcaps</FILE>
-<TITLE>GstCaps</TITLE>
-GstCaps
-GstStaticCaps
-GstCapsIntersectMode
-
-GstCapsFlags
-GST_CAPS_ANY
-GST_CAPS_NONE
-GST_CAPS_REFCOUNT
-GST_CAPS_REFCOUNT_VALUE
-GST_STATIC_CAPS_ANY
-GST_STATIC_CAPS_NONE
-GST_CAPS_IS_SIMPLE
-GST_STATIC_CAPS
-GST_CAPS_FLAGS
-GST_CAPS_FLAG_IS_SET
-GST_CAPS_FLAG_SET
-GST_CAPS_FLAG_UNSET
-
-GstCapsForeachFunc
-GstCapsMapFunc
-GstCapsFilterMapFunc
-
-gst_caps_new_empty
-gst_caps_new_empty_simple
-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
-gst_caps_append_structure_full
-gst_caps_remove_structure
-gst_caps_steal_structure
-gst_caps_merge_structure
-gst_caps_merge_structure_full
-gst_caps_get_size
-gst_caps_get_structure
-gst_caps_get_features
-gst_caps_set_features
-gst_caps_set_features_simple
-gst_caps_set_value
-gst_caps_set_simple
-gst_caps_set_simple_valist
-gst_caps_foreach
-gst_caps_map_in_place
-gst_caps_filter_and_map_in_place
-gst_caps_is_any
-gst_caps_is_empty
-gst_caps_is_fixed
-gst_caps_is_equal
-gst_caps_is_equal_fixed
-gst_caps_is_strictly_equal
-gst_caps_is_always_compatible
-gst_caps_is_subset
-gst_caps_is_subset_structure
-gst_caps_is_subset_structure_full
-gst_caps_can_intersect
-gst_caps_intersect
-gst_caps_intersect_full
-gst_caps_normalize
-gst_caps_simplify
-gst_caps_replace
-gst_caps_take
-gst_caps_to_string
-gst_caps_from_string
-gst_caps_subtract
-gst_caps_make_writable
-gst_caps_truncate
-gst_caps_fixate
-gst_caps_ref
-gst_caps_unref
-gst_clear_caps
-<SUBSECTION Standard>
-GST_CAPS
-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
-gst_caps_intersect_mode_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstcapsfeatures</FILE>
-<TITLE>GstCapsFeatures</TITLE>
-GstCapsFeatures
-GST_CAPS_FEATURES_ANY
-GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY
-GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY
-gst_caps_features_new
-gst_caps_features_new_empty
-gst_caps_features_new_any
-gst_caps_features_new_id
-gst_caps_features_new_id_valist
-gst_caps_features_new_valist
-
-gst_caps_features_copy
-gst_caps_features_free
-
-gst_caps_features_from_string
-gst_caps_features_to_string
-
-gst_caps_features_set_parent_refcount
-
-gst_caps_features_is_equal
-gst_caps_features_is_any
-
-gst_caps_features_contains
-gst_caps_features_contains_id
-
-gst_caps_features_get_size
-
-gst_caps_features_get_nth
-gst_caps_features_get_nth_id
-
-gst_caps_features_add
-gst_caps_features_add_id
-gst_caps_features_remove
-gst_caps_features_remove_id
-<SUBSECTION Standard>
-GST_CAPS_FEATURES
-GST_CAPS_FEATURES_CAST
-GST_IS_CAPS_FEATURES
-GST_TYPE_CAPS_FEATURES
-gst_is_caps_features
-<SUBSECTION Private>
-gst_caps_features_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstsample</FILE>
-<TITLE>GstSample</TITLE>
-GstSample
-gst_sample_get_buffer
-gst_sample_get_buffer_list
-gst_sample_get_caps
-gst_sample_get_info
-gst_sample_get_segment
-gst_sample_set_buffer
-gst_sample_set_buffer_list
-gst_sample_set_caps
-gst_sample_set_segment
-gst_sample_set_info
-gst_sample_new
-gst_sample_ref
-gst_sample_unref
-gst_sample_copy
-gst_sample_is_writable
-gst_sample_make_writable
-<SUBSECTION Standard>
-GST_IS_SAMPLE
-GST_SAMPLE
-GST_TYPE_SAMPLE
-gst_sample_get_type
-GST_SAMPLE_CAST
-</SECTION>
-
-<SECTION>
-<FILE>gstchildproxy</FILE>
-<TITLE>GstChildProxy</TITLE>
-GstChildProxy
-GstChildProxyInterface
-gst_child_proxy_get_children_count
-gst_child_proxy_get_child_by_name
-gst_child_proxy_get_child_by_index
-gst_child_proxy_lookup
-gst_child_proxy_get_property
-gst_child_proxy_get_valist
-gst_child_proxy_get
-gst_child_proxy_set_property
-gst_child_proxy_set_valist
-gst_child_proxy_set
-gst_child_proxy_child_added
-gst_child_proxy_child_removed
-<SUBSECTION Standard>
-GST_CHILD_PROXY
-GST_IS_CHILD_PROXY
-GST_CHILD_PROXY_GET_INTERFACE
-GST_TYPE_CHILD_PROXY
-<SUBSECTION Private>
-gst_child_proxy_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstclock</FILE>
-<TITLE>GstClock</TITLE>
-GstClock
-GstClockClass
-GstClockTime
-GstClockTimeDiff
-GstClockID
-GST_CLOCK_TIME_NONE
-GST_CLOCK_TIME_IS_VALID
-GST_CLOCK_STIME_NONE
-GST_CLOCK_STIME_IS_VALID
-GST_SECOND
-GST_MSECOND
-GST_USECOND
-GST_NSECOND
-GST_TIME_AS_SECONDS
-GST_TIME_AS_MSECONDS
-GST_TIME_AS_USECONDS
-GST_TIME_AS_NSECONDS
-GST_CLOCK_DIFF
-GST_TIMEVAL_TO_TIME
-GST_TIME_TO_TIMEVAL
-GST_TIMESPEC_TO_TIME
-GST_TIME_TO_TIMESPEC
-GstClockEntry
-GstClockCallback
-GstClockEntryType
-GST_CLOCK_ENTRY
-GST_CLOCK_ENTRY_CLOCK
-GST_CLOCK_ENTRY_TYPE
-GST_CLOCK_ENTRY_TIME
-GST_CLOCK_ENTRY_INTERVAL
-GST_CLOCK_ENTRY_STATUS
-GstClockReturn
-GstClockFlags
-GST_CLOCK_FLAGS
-gst_clock_add_observation
-gst_clock_add_observation_unapplied
-gst_clock_set_master
-gst_clock_get_master
-gst_clock_set_resolution
-gst_clock_get_resolution
-gst_clock_get_time
-gst_clock_new_single_shot_id
-gst_clock_new_periodic_id
-gst_clock_single_shot_id_reinit
-gst_clock_periodic_id_reinit
-gst_clock_get_internal_time
-gst_clock_adjust_unlocked
-gst_clock_unadjust_unlocked
-gst_clock_adjust_with_calibration
-gst_clock_unadjust_with_calibration
-gst_clock_get_calibration
-gst_clock_set_calibration
-gst_clock_get_timeout
-gst_clock_set_timeout
-gst_clock_wait_for_sync
-gst_clock_is_synced
-gst_clock_set_synced
-gst_clock_id_get_time
-gst_clock_id_get_clock
-gst_clock_id_uses_clock
-gst_clock_id_wait
-gst_clock_id_wait_async
-gst_clock_id_unschedule
-gst_clock_id_compare_func
-gst_clock_id_ref
-gst_clock_id_unref
-<SUBSECTION Standard>
-GST_CLOCK
-GST_IS_CLOCK
-GST_TYPE_CLOCK
-GST_CLOCK_CLASS
-GST_IS_CLOCK_CLASS
-GST_CLOCK_GET_CLASS
-GST_CLOCK_CAST
-GST_TYPE_CLOCK_ENTRY_TYPE
-GST_TYPE_CLOCK_FLAGS
-GST_TYPE_CLOCK_RETURN
-GST_TYPE_CLOCK_TIME
-<SUBSECTION Private>
-GstClockPrivate
-GST_CLOCK_SLAVE_LOCK
-GST_CLOCK_SLAVE_UNLOCK
-gst_clock_get_type
-gst_clock_entry_type_get_type
-gst_clock_flags_get_type
-gst_clock_return_get_type
-</SECTION>
-
-
-<SECTION>
-<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
-gst_pad_get_caps_reffed
-gst_pad_peer_get_caps_reffed
-gst_pad_set_caps
-gst_buffer_new_and_alloc
-GST_BUFFER_TIMESTAMP
-GST_BUFFER_TIMESTAMP_IS_VALID
-GST_MESSAGE_DURATION
-gst_message_new_duration
-gst_message_parse_duration
-gst_adapter_prev_timestamp
-<SUBSECTION Private>
-</SECTION>
-
-
-<SECTION>
-<FILE>gstconfig</FILE>
-<TITLE>GstConfig</TITLE>
-GST_DISABLE_GST_DEBUG
-GST_DISABLE_PARSE
-GST_DISABLE_REGISTRY
-GST_DISABLE_PLUGIN
-<SUBSECTION Private>
-GST_HAVE_GLIB_2_8
-GST_EXPORT
-GST_PLUGIN_EXPORT
-GST_PADDING
-GST_PADDING_LARGE
-GST_PADDING_INIT
-</SECTION>
-
-<SECTION>
-<FILE>gstcontext</FILE>
-<TITLE>GstContext</TITLE>
-GstContext
-gst_context_new
-gst_context_ref
-gst_context_unref
-gst_context_copy
-gst_context_get_context_type
-gst_context_has_context_type
-gst_context_is_persistent
-gst_context_get_structure
-gst_context_writable_structure
-gst_context_make_writable
-gst_context_is_writable
-gst_context_replace
-<SUBSECTION Standard>
-GST_CONTEXT
-GST_CONTEXT_CAST
-GST_IS_CONTEXT
-GST_TYPE_CONTEXT
-<SUBSECTION Private>
-gst_context_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstcontrolbinding</FILE>
-<TITLE>GstControlBinding</TITLE>
-GstControlBinding
-GstControlBindingClass
-gst_control_binding_sync_values
-gst_control_binding_get_value
-gst_control_binding_get_value_array
-gst_control_binding_get_g_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
-GST_CONTROL_BINDING_PSPEC
-<SUBSECTION Private>
-GstControlBindingConvert
-GstControlBindingPrivate
-gst_control_binding_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstcontrolsource</FILE>
-<TITLE>GstControlSource</TITLE>
-GstValueArray
-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>gstdynamictypefactory</FILE>
-<TITLE>GstDynamicTypeFactory</TITLE>
-GstDynamicTypeFactory
-gst_dynamic_type_factory_load
-gst_dynamic_type_register
-<SUBSECTION Standard>
-GstDynamicTypeFactoryClass
-GST_TYPE_DYNAMIC_TYPE_FACTORY
-GST_DYNAMIC_TYPE_FACTORY
-GST_DYNAMIC_TYPE_CLASS
-GST_IS_DYNAMIC_TYPE_FACTORY
-GST_IS_DYNAMIC_TYPE_FACTORY_CLASS
-GST_DYNAMIC_TYPE_FACTORY_CAST
-<SUBSECTION Private>
-gst_dynamic_type_factory_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstelement</FILE>
-<TITLE>GstElement</TITLE>
-GstElement
-GstElementClass
-GstElementFlags
-GstState
-GstStateChange
-GstStateChangeReturn
-
-GST_STATE
-GST_STATE_GET_NEXT
-GST_STATE_NEXT
-GST_STATE_PENDING
-GST_STATE_RETURN
-GST_STATE_TARGET
-GST_STATE_TRANSITION
-GST_STATE_TRANSITION_CURRENT
-GST_STATE_TRANSITION_NEXT
-
-GST_STATE_GET_LOCK
-GST_STATE_GET_COND
-
-GST_ELEMENT_NAME
-GST_ELEMENT_PARENT
-GST_ELEMENT_BUS
-GST_ELEMENT_CLOCK
-GST_ELEMENT_PADS
-GST_ELEMENT_START_TIME
-GST_ELEMENT_ERROR
-GST_ELEMENT_ERROR_WITH_DETAILS
-GST_ELEMENT_FLOW_ERROR
-GST_ELEMENT_WARNING
-GST_ELEMENT_WARNING_WITH_DETAILS
-GST_ELEMENT_INFO
-GST_ELEMENT_INFO_WITH_DETAILS
-GST_ELEMENT_IS_LOCKED_STATE
-
-<SUBSECTION element-metadata>
-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_add_static_pad_template
-gst_element_class_add_static_pad_template_with_gtype
-gst_element_class_get_pad_template
-gst_element_class_get_pad_template_list
-gst_element_class_set_metadata
-gst_element_class_set_static_metadata
-gst_element_class_add_metadata
-gst_element_class_add_static_metadata
-
-<SUBSECTION element-pads>
-gst_element_add_pad
-gst_element_create_all_pads
-gst_element_get_compatible_pad
-gst_element_get_compatible_pad_template
-gst_element_get_request_pad
-gst_element_get_static_pad
-gst_element_request_pad
-gst_element_no_more_pads
-gst_element_release_request_pad
-gst_element_remove_pad
-gst_element_iterate_pads
-gst_element_iterate_sink_pads
-gst_element_iterate_src_pads
-GstElementForeachPadFunc
-gst_element_foreach_pad
-gst_element_foreach_sink_pad
-gst_element_foreach_src_pad
-
-<SUBSECTION element-linking>
-gst_element_link
-gst_element_unlink
-gst_element_link_many
-gst_element_unlink_many
-gst_element_link_pads
-gst_element_link_pads_full
-gst_element_unlink_pads
-gst_element_link_pads_filtered
-gst_element_link_filtered
-
-<SUBSECTION element-properties>
-gst_element_class_get_metadata
-gst_element_get_metadata
-gst_element_set_base_time
-gst_element_get_base_time
-gst_element_set_start_time
-gst_element_get_start_time
-gst_element_set_bus
-gst_element_get_bus
-gst_element_set_context
-gst_element_get_context
-gst_element_get_context_unlocked
-gst_element_get_contexts
-gst_element_get_factory
-gst_element_set_name
-gst_element_get_name
-gst_element_set_parent
-gst_element_get_parent
-gst_element_get_pad_template
-gst_element_get_pad_template_list
-
-<SUBSECTION element-clocks>
-gst_element_set_clock
-gst_element_get_clock
-gst_element_provide_clock
-
-<SUBSECTION element-states>
-gst_element_set_state
-gst_element_get_state
-gst_element_set_locked_state
-gst_element_is_locked_state
-gst_element_abort_state
-gst_element_continue_state
-gst_element_lost_state
-gst_element_state_get_name
-gst_element_state_change_return_get_name
-gst_element_sync_state_with_parent
-gst_element_change_state
-gst_state_change_get_name
-
-<SUBSECTION element-messages>
-gst_element_message_full
-gst_element_message_full_with_details
-gst_make_element_message_details
-gst_element_post_message
-
-<SUBSECTION element-query>
-gst_element_query
-gst_element_query_convert
-gst_element_query_position
-gst_element_query_duration
-
-<SUBSECTION element-event>
-gst_element_send_event
-gst_element_seek_simple
-gst_element_seek
-
-<SUBSECTION element-property-notifications>
-gst_element_add_property_notify_watch
-gst_element_add_property_deep_notify_watch
-gst_element_remove_property_notify_watch
-
-<SUBSECTION element-call-async>
-GstElementCallAsyncFunc
-gst_element_call_async
-
-<SUBSECTION Standard>
-GST_ELEMENT
-GST_IS_ELEMENT
-GST_ELEMENT_CLASS
-GST_IS_ELEMENT_CLASS
-GST_ELEMENT_GET_CLASS
-GST_TYPE_ELEMENT
-GST_TYPE_ELEMENT_FLAGS
-GST_ELEMENT_CAST
-GST_TYPE_STATE
-GST_TYPE_STATE_CHANGE
-GST_TYPE_STATE_CHANGE_RETURN
-<SUBSECTION Private>
-GST_STATE_LOCK
-GST_STATE_TRYLOCK
-GST_STATE_UNLOCK
-GST_STATE_UNLOCK_FULL
-GST_STATE_LOCK_FULL
-GST_STATE_WAIT
-GST_STATE_WAIT_UNTIL
-GST_STATE_SIGNAL
-GST_STATE_BROADCAST
-
-GST_ELEMENT_MESSAGE_MAKE_DETAILS
-
-gst_element_get_type
-gst_element_flags_get_type
-gst_state_get_type
-gst_state_change_get_type
-gst_state_change_return_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstelementfactory</FILE>
-<TITLE>GstElementFactory</TITLE>
-GstElementFactory
-gst_element_register
-gst_element_factory_find
-gst_element_factory_get_element_type
-gst_element_factory_get_metadata
-gst_element_factory_get_metadata_keys
-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_all_caps
-gst_element_factory_can_src_all_caps
-gst_element_factory_can_sink_any_caps
-gst_element_factory_can_src_any_caps
-gst_element_factory_get_static_pad_templates
-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_DECRYPTOR
-GST_ELEMENT_FACTORY_TYPE_DEMUXER
-GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER
-GST_ELEMENT_FACTORY_TYPE_ENCODER
-GST_ELEMENT_FACTORY_TYPE_ENCRYPTOR
-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_list_filter
-gst_element_factory_list_get_elements
-gst_element_factory_list_is_type
-<SUBSECTION Standard>
-GstElementFactoryClass
-GST_ELEMENT_FACTORY
-GST_ELEMENT_FACTORY_CAST
-GST_IS_ELEMENT_FACTORY
-GST_ELEMENT_FACTORY_CLASS
-GST_IS_ELEMENT_FACTORY_CLASS
-GST_TYPE_ELEMENT_FACTORY
-<SUBSECTION Private>
-gst_element_factory_get_type
-GST_ELEMENT_FACTORY_KLASS_DECODER
-GST_ELEMENT_FACTORY_KLASS_DECRYPTOR
-GST_ELEMENT_FACTORY_KLASS_DEMUXER
-GST_ELEMENT_FACTORY_KLASS_DEPAYLOADER
-GST_ELEMENT_FACTORY_KLASS_ENCODER
-GST_ELEMENT_FACTORY_KLASS_ENCRYPTOR
-GST_ELEMENT_FACTORY_KLASS_FORMATTER
-GST_ELEMENT_FACTORY_KLASS_HARDWARE
-GST_ELEMENT_FACTORY_KLASS_MEDIA_AUDIO
-GST_ELEMENT_FACTORY_KLASS_MEDIA_IMAGE
-GST_ELEMENT_FACTORY_KLASS_MEDIA_METADATA
-GST_ELEMENT_FACTORY_KLASS_MEDIA_SUBTITLE
-GST_ELEMENT_FACTORY_KLASS_MEDIA_VIDEO
-GST_ELEMENT_FACTORY_KLASS_MUXER
-GST_ELEMENT_FACTORY_KLASS_PARSER
-GST_ELEMENT_FACTORY_KLASS_PAYLOADER
-GST_ELEMENT_FACTORY_KLASS_SINK
-GST_ELEMENT_FACTORY_KLASS_SRC
-</SECTION>
-
-
-<SECTION>
-<FILE>gsterror</FILE>
-<TITLE>GstGError</TITLE>
-GstCoreError
-GstLibraryError
-GstResourceError
-GstStreamError
-GST_CORE_ERROR
-GST_LIBRARY_ERROR
-GST_RESOURCE_ERROR
-GST_STREAM_ERROR
-GST_ERROR_SYSTEM
-gst_error_get_message
-<SUBSECTION Standard>
-GST_TYPE_CORE_ERROR
-GST_TYPE_LIBRARY_ERROR
-GST_TYPE_RESOURCE_ERROR
-GST_TYPE_STREAM_ERROR
-<SUBSECTION Private>
-gst_core_error_get_type
-gst_library_error_get_type
-gst_resource_error_get_type
-gst_stream_error_get_type
-gst_core_error_quark
-gst_library_error_quark
-gst_resource_error_quark
-gst_stream_error_quark
-</SECTION>
-
-
-<SECTION>
-<FILE>gstevent</FILE>
-<TITLE>GstEvent</TITLE>
-GstEvent
-
-GstEventTypeFlags
-GST_EVENT_TYPE_BOTH
-GST_EVENT_MAKE_TYPE
-
-GstEventType
-
-GST_EVENT_TYPE
-GST_EVENT_TYPE_NAME
-GST_EVENT_TIMESTAMP
-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
-gst_event_type_to_quark
-
-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
-gst_event_has_name
-
-gst_event_get_seqnum
-gst_event_set_seqnum
-
-gst_event_get_running_time_offset
-gst_event_set_running_time_offset
-
-gst_event_new_flush_start
-gst_event_new_flush_stop
-gst_event_parse_flush_stop
-
-gst_event_new_eos
-
-gst_event_new_gap
-gst_event_parse_gap
-
-gst_event_new_stream_start
-gst_event_parse_stream_start
-GstStreamFlags
-gst_event_set_stream_flags
-gst_event_parse_stream_flags
-gst_event_set_group_id
-gst_event_parse_group_id
-
-gst_event_set_stream
-gst_event_parse_stream
-
-gst_event_new_segment
-gst_event_parse_segment
-gst_event_copy_segment
-
-gst_event_new_tag
-gst_event_parse_tag
-
-gst_event_new_buffer_size
-gst_event_parse_buffer_size
-
-GstQOSType
-gst_event_new_qos
-gst_event_parse_qos
-
-GstSeekType
-GstSeekFlags
-gst_event_new_seek
-gst_event_parse_seek
-gst_event_set_seek_trickmode_interval
-gst_event_parse_seek_trickmode_interval
-
-gst_event_new_navigation
-
-gst_event_new_latency
-gst_event_parse_latency
-
-gst_event_new_step
-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
-
-gst_event_new_toc
-gst_event_parse_toc
-
-gst_event_new_toc_select
-gst_event_parse_toc_select
-
-gst_event_new_segment_done
-gst_event_parse_segment_done
-
-gst_event_new_protection
-gst_event_parse_protection
-
-gst_event_new_select_streams
-gst_event_parse_select_streams
-
-gst_event_new_stream_collection
-gst_event_parse_stream_collection
-
-gst_event_new_stream_group_done
-gst_event_parse_stream_group_done
-<SUBSECTION Standard>
-GstEventClass
-GST_EVENT
-GST_EVENT_CAST
-GST_IS_EVENT
-GST_IS_EVENT_CLASS
-GST_EVENT_CLASS
-GST_EVENT_GET_CLASS
-GST_TYPE_EVENT
-GST_TYPE_EVENT_TYPE
-GST_TYPE_SEEK_TYPE
-GST_TYPE_SEEK_FLAGS
-GST_TYPE_QOS_TYPE
-GST_TYPE_EVENT_TYPE_FLAGS
-GST_TYPE_STREAM_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
-gst_seek_type_get_type
-gst_seek_flags_get_type
-gst_qos_type_get_type
-gst_event_type_flags_get_type
-gst_stream_flags_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstformat</FILE>
-<TITLE>GstFormat</TITLE>
-GstFormat
-GST_FORMAT_PERCENT_MAX
-GST_FORMAT_PERCENT_SCALE
-GstFormatDefinition
-
-gst_format_get_name
-gst_format_to_quark
-gst_format_register
-gst_format_get_by_nick
-gst_formats_contains
-gst_format_get_details
-gst_format_iterate_definitions
-<SUBSECTION Standard>
-GST_TYPE_FORMAT
-<SUBSECTION Private>
-gst_format_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstghostpad</FILE>
-<TITLE>GstGhostPad</TITLE>
-GstProxyPad
-GstGhostPad
-
-gst_ghost_pad_new
-gst_ghost_pad_new_no_target
-gst_ghost_pad_new_from_template
-gst_ghost_pad_new_no_target_from_template
-
-gst_ghost_pad_set_target
-gst_ghost_pad_get_target
-
-gst_ghost_pad_construct
-
-gst_ghost_pad_activate_mode_default
-
-gst_ghost_pad_internal_activate_mode_default
-
-gst_proxy_pad_get_internal
-
-gst_proxy_pad_iterate_internal_links_default
-gst_proxy_pad_chain_default
-gst_proxy_pad_chain_list_default
-gst_proxy_pad_getrange_default
-<SUBSECTION Standard>
-GstGhostPadClass
-GST_GHOST_PAD
-GST_IS_GHOST_PAD
-GST_GHOST_PAD_CLASS
-GST_IS_GHOST_PAD_CLASS
-GST_TYPE_GHOST_PAD
-GST_GHOST_PAD_CAST
-<SUBSECTION Private>
-GST_IS_PROXY_PAD
-GST_IS_PROXY_PAD_CLASS
-GST_PROXY_PAD
-GST_PROXY_PAD_CLASS
-GST_TYPE_PROXY_PAD
-GstGhostPadPrivate
-GstProxyPadClass
-GstProxyPadPrivate
-gst_proxy_pad_get_type
-gst_ghost_pad_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstinfo</FILE>
-<TITLE>GstInfo</TITLE>
-GstDebugLevel
-GST_LEVEL_DEFAULT
-GST_LEVEL_MAX
-GstDebugColorFlags
-GstDebugColorMode
-GstDebugCategory
-GstDebugGraphDetails
-GST_STR_NULL
-GST_DEBUG_PAD_NAME
-GST_FUNCTION
-GstLogFunction
-GstStackTraceFlags
-gst_debug_log
-gst_debug_log_valist
-gst_debug_message_get
-gst_debug_log_default
-gst_debug_level_get_name
-gst_debug_add_log_function
-gst_debug_remove_log_function
-gst_debug_remove_log_function_by_data
-gst_debug_add_ring_buffer_logger
-gst_debug_remove_ring_buffer_logger
-gst_debug_ring_buffer_logger_get_logs
-gst_debug_set_active
-gst_debug_is_active
-gst_debug_set_colored
-gst_debug_set_color_mode
-gst_debug_set_color_mode_from_string
-gst_debug_is_colored
-gst_debug_get_color_mode
-gst_debug_set_default_threshold
-gst_debug_set_threshold_from_string
-gst_debug_get_default_threshold
-gst_debug_set_threshold_for_name
-gst_debug_unset_threshold_for_name
-GST_DEBUG_CATEGORY
-GST_DEBUG_CATEGORY_EXTERN
-GST_DEBUG_CATEGORY_STATIC
-GST_DEBUG_CATEGORY_INIT
-GST_DEBUG_CATEGORY_GET
-gst_debug_category_free
-gst_debug_category_set_threshold
-gst_debug_category_reset_threshold
-gst_debug_category_get_threshold
-gst_debug_category_get_name
-gst_debug_category_get_color
-gst_debug_category_get_description
-gst_debug_get_all_categories
-gst_debug_construct_term_color
-gst_debug_construct_win_color
-GST_CAT_LEVEL_LOG
-GST_CAT_ERROR_OBJECT
-GST_CAT_WARNING_OBJECT
-GST_CAT_INFO_OBJECT
-GST_CAT_DEBUG_OBJECT
-GST_CAT_LOG_OBJECT
-GST_CAT_FIXME_OBJECT
-GST_CAT_TRACE_OBJECT
-GST_CAT_MEMDUMP_OBJECT
-GST_CAT_DEFAULT
-GST_CAT_ERROR
-GST_CAT_WARNING
-GST_CAT_INFO
-GST_CAT_DEBUG
-GST_CAT_LOG
-GST_CAT_FIXME
-GST_CAT_TRACE
-GST_CAT_MEMDUMP
-GST_ERROR_OBJECT
-GST_WARNING_OBJECT
-GST_INFO_OBJECT
-GST_DEBUG_OBJECT
-GST_LOG_OBJECT
-GST_FIXME_OBJECT
-GST_TRACE_OBJECT
-GST_MEMDUMP_OBJECT
-GST_ERROR
-GST_WARNING
-GST_INFO
-GST_DEBUG
-GST_LOG
-GST_FIXME
-GST_TRACE
-GST_MEMDUMP
-GST_DEBUG_REGISTER_FUNCPTR
-GST_DEBUG_FUNCPTR
-GST_DEBUG_FUNCPTR_NAME
-GST_DEBUG_BIN_TO_DOT_FILE
-GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS
-gst_debug_print_stack_trace
-gst_debug_get_stack_trace
-GST_TIME_FORMAT
-GST_TIME_ARGS
-GST_STIME_FORMAT
-GST_STIME_ARGS
-GST_PTR_FORMAT
-GST_SEGMENT_FORMAT
-gst_debug_bin_to_dot_data
-gst_debug_bin_to_dot_file
-gst_debug_bin_to_dot_file_with_ts
-gst_info_vasprintf
-gst_info_strdup_vprintf
-gst_info_strdup_printf
-gst_print
-gst_println
-gst_printerr
-gst_printerrln
-<SUBSECTION Standard>
-GST_TYPE_DEBUG_COLOR_FLAGS
-GST_TYPE_DEBUG_COLOR_MODE
-GST_TYPE_DEBUG_LEVEL
-GST_TYPE_DEBUG_GRAPH_DETAILS
-GST_TYPE_STACK_TRACE_FLAGS
-<SUBSECTION Private>
-GST_DEBUG_FG_MASK
-GST_DEBUG_BG_MASK
-GST_DEBUG_FORMAT_MASK
-GstDebugFuncPtr
-GstDebugMessage
-gst_debug_color_flags_get_type
-gst_debug_color_mode_get_type
-gst_debug_level_get_type
-gst_debug_graph_details_get_type
-GST_CAT_LEVEL_LOG_valist
-gst_stack_trace_flags_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstiterator</FILE>
-<TITLE>GstIterator</TITLE>
-GstIterator
-
-GstIteratorItem
-GstIteratorResult
-
-GstIteratorCopyFunction
-GstIteratorNextFunction
-GstIteratorItemFunction
-GstIteratorResyncFunction
-GstIteratorFreeFunction
-GstIteratorForeachFunction
-GstIteratorFoldFunction
-
-GST_ITERATOR
-GST_ITERATOR_LOCK
-GST_ITERATOR_COOKIE
-GST_ITERATOR_ORIG_COOKIE
-
-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_push
-gst_iterator_filter
-gst_iterator_fold
-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>gstallocator</FILE>
-<TITLE>GstAllocator</TITLE>
-gst_memory_alignment
-
-GstAllocator
-GstAllocatorClass
-GstAllocatorFlags
-GstAllocationParams
-
-GST_ALLOCATOR_SYSMEM
-gst_allocator_find
-gst_allocator_register
-gst_allocator_set_default
-
-gst_allocation_params_init
-gst_allocation_params_copy
-gst_allocation_params_free
-
-gst_allocator_alloc
-gst_allocator_free
-
-gst_memory_new_wrapped
-
-<SUBSECTION Standard>
-GST_ALLOCATOR
-GST_ALLOCATOR_CAST
-GST_ALLOCATOR_CLASS
-GST_ALLOCATOR_GET_CLASS
-GST_IS_ALLOCATOR
-GST_IS_ALLOCATOR_CLASS
-<SUBSECTION Private>
-GST_TYPE_ALLOCATOR_FLAGS
-GstAllocatorPrivate
-GST_TYPE_ALLOCATION_PARAMS
-gst_allocation_params_get_type
-GST_TYPE_ALLOCATOR
-gst_allocator_get_type
-gst_allocator_flags_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstmemory</FILE>
-<TITLE>GstMemory</TITLE>
-
-GstMemoryFlags
-GST_MEMORY_FLAGS
-GST_MEMORY_FLAG_IS_SET
-GST_MEMORY_FLAG_UNSET
-GST_MEMORY_IS_READONLY
-GST_MEMORY_IS_NO_SHARE
-GST_MEMORY_IS_ZERO_PADDED
-GST_MEMORY_IS_ZERO_PREFIXED
-GST_MEMORY_IS_PHYSICALLY_CONTIGUOUS
-GST_MEMORY_IS_NOT_MAPPABLE
-
-GstMemory
-
-GstMapFlags
-GST_MAP_READWRITE
-
-GstMapInfo
-GST_MAP_INFO_INIT
-
-GstMemoryMapFunction
-GstMemoryMapFullFunction
-GstMemoryUnmapFunction
-GstMemoryUnmapFullFunction
-GstMemoryCopyFunction
-GstMemoryShareFunction
-GstMemoryIsSpanFunction
-
-gst_memory_init
-
-gst_memory_is_type
-
-gst_memory_ref
-gst_memory_unref
-
-gst_memory_get_sizes
-gst_memory_resize
-
-gst_memory_lock
-gst_memory_unlock
-gst_memory_is_writable
-gst_memory_make_writable
-
-gst_memory_make_mapped
-gst_memory_map
-gst_memory_unmap
-
-gst_memory_copy
-gst_memory_share
-
-gst_memory_is_span
-<SUBSECTION Standard>
-GST_TYPE_MEMORY
-gst_memory_get_type
-GST_MEMORY_CAST
-GST_TYPE_LOCK_FLAGS
-gst_lock_flags_get_type
-GST_TYPE_MAP_FLAGS
-gst_map_flags_get_type
-GST_TYPE_MEMORY_FLAGS
-gst_memory_flags_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstmessage</FILE>
-<TITLE>GstMessage</TITLE>
-GstMessage
-GstMessageType
-GST_MESSAGE_SRC
-GST_MESSAGE_SRC_NAME
-GST_MESSAGE_TIMESTAMP
-GST_MESSAGE_SEQNUM
-GST_MESSAGE_TYPE
-GST_MESSAGE_TYPE_IS_EXTENDED
-GST_MESSAGE_TYPE_NAME
-gst_message_type_to_quark
-gst_message_type_get_name
-gst_message_ref
-gst_message_unref
-gst_clear_message
-gst_message_copy
-gst_message_get_structure
-gst_message_writable_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_take
-
-gst_message_new_eos
-gst_message_new_error
-gst_message_new_error_with_details
-gst_message_parse_error
-gst_message_parse_error_details
-gst_message_new_warning
-gst_message_new_warning_with_details
-gst_message_parse_warning
-gst_message_parse_warning_details
-gst_message_new_info
-gst_message_new_info_with_details
-gst_message_parse_info
-gst_message_parse_info_details
-gst_message_new_tag
-gst_message_parse_tag
-gst_message_new_buffering
-gst_message_parse_buffering
-gst_message_set_buffering_stats
-gst_message_parse_buffering_stats
-gst_message_new_state_changed
-gst_message_parse_state_changed
-gst_message_new_state_dirty
-gst_message_new_step_done
-gst_message_parse_step_done
-gst_message_new_clock_provide
-gst_message_parse_clock_provide
-gst_message_new_clock_lost
-gst_message_parse_clock_lost
-gst_message_new_new_clock
-gst_message_parse_new_clock
-gst_message_new_application
-gst_message_new_element
-gst_message_new_custom
-gst_message_new_segment_start
-gst_message_parse_segment_start
-gst_message_new_segment_done
-gst_message_parse_segment_done
-gst_message_new_duration_changed
-gst_message_new_latency
-gst_message_new_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
-gst_message_set_qos_values
-gst_message_set_qos_stats
-gst_message_parse_qos
-gst_message_parse_qos_values
-gst_message_parse_qos_stats
-gst_message_new_toc
-gst_message_parse_toc
-gst_message_new_reset_time
-gst_message_parse_reset_time
-
-gst_message_new_stream_start
-gst_message_set_group_id
-gst_message_parse_group_id
-
-gst_message_new_stream_collection
-gst_message_parse_stream_collection
-GstStructureChangeType
-gst_message_new_structure_change
-gst_message_parse_structure_change
-gst_message_new_request_state
-gst_message_parse_request_state
-
-GstStreamStatusType
-gst_message_new_stream_status
-gst_message_parse_stream_status
-gst_message_set_stream_status_object
-gst_message_get_stream_status_object
-
-GstProgressType
-gst_message_new_progress
-gst_message_parse_progress
-
-gst_message_new_need_context
-gst_message_parse_context_type
-gst_message_new_have_context
-gst_message_parse_have_context
-
-gst_message_new_device_added
-gst_message_new_device_removed
-gst_message_new_device_changed
-gst_message_parse_device_added
-gst_message_parse_device_removed
-gst_message_parse_device_changed
-
-gst_message_new_property_notify
-gst_message_parse_property_notify
-
-gst_message_new_streams_selected
-gst_message_parse_streams_selected
-gst_message_streams_selected_add
-gst_message_streams_selected_get_size
-gst_message_streams_selected_get_stream
-
-gst_message_new_redirect
-gst_message_add_redirect_entry
-gst_message_parse_redirect_entry
-gst_message_get_num_redirect_entries
-
-<SUBSECTION Standard>
-GstMessageClass
-GST_MESSAGE
-GST_MESSAGE_CAST
-GST_IS_MESSAGE
-GST_TYPE_MESSAGE
-GST_MESSAGE_CLASS
-GST_IS_MESSAGE_CLASS
-GST_MESSAGE_GET_CLASS
-GST_TYPE_MESSAGE_TYPE
-GST_TYPE_STRUCTURE_CHANGE_TYPE
-GST_TYPE_STREAM_STATUS_TYPE
-GST_TYPE_PROGRESS_TYPE
-<SUBSECTION Private>
-gst_message_get_type
-gst_message_type_get_type
-gst_structure_change_type_get_type
-gst_stream_status_type_get_type
-gst_progress_type_get_type
-GST_MESSAGE_GET_COND
-GST_MESSAGE_GET_LOCK
-GST_MESSAGE_LOCK
-GST_MESSAGE_SIGNAL
-GST_MESSAGE_UNLOCK
-GST_MESSAGE_WAIT
-</SECTION>
-
-
-<SECTION>
-<FILE>gstminiobject</FILE>
-<TITLE>GstMiniObject</TITLE>
-GstMiniObject
-GstMiniObjectCopyFunction
-GstMiniObjectDisposeFunction
-GstMiniObjectFreeFunction
-GstMiniObjectNotify
-
-GST_MINI_OBJECT_TYPE
-
-GstMiniObjectFlags
-GST_MINI_OBJECT_FLAGS
-GST_MINI_OBJECT_FLAG_IS_SET
-GST_MINI_OBJECT_FLAG_SET
-GST_MINI_OBJECT_FLAG_UNSET
-GST_MINI_OBJECT_IS_LOCKABLE
-
-GstLockFlags
-GST_LOCK_FLAG_READWRITE
-
-GST_MINI_OBJECT_REFCOUNT
-GST_MINI_OBJECT_REFCOUNT_VALUE
-
-GST_DEFINE_MINI_OBJECT_TYPE
-gst_mini_object_init
-
-gst_mini_object_ref
-gst_mini_object_unref
-gst_clear_mini_object
-
-gst_mini_object_weak_ref
-gst_mini_object_weak_unref
-
-gst_mini_object_lock
-gst_mini_object_unlock
-gst_mini_object_is_writable
-gst_mini_object_make_writable
-
-gst_mini_object_add_parent
-gst_mini_object_remove_parent
-
-gst_mini_object_copy
-
-gst_mini_object_set_qdata
-gst_mini_object_get_qdata
-gst_mini_object_steal_qdata
-
-gst_mini_object_replace
-gst_mini_object_take
-gst_mini_object_steal
-
-<SUBSECTION Standard>
-GST_MINI_OBJECT
-GST_IS_MINI_OBJECT_TYPE
-GST_TYPE_MINI_OBJECT_FLAGS
-GST_MINI_OBJECT_CAST
-GST_MINI_OBJECT_CONST_CAST
-
-<SUBSECTION Private>
-gst_mini_object_flags_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstobject</FILE>
-<TITLE>GstObject</TITLE>
-GstObject
-GstObjectClass
-GstObjectFlags
-GST_OBJECT_FLAGS
-GST_OBJECT_FLAG_IS_SET
-GST_OBJECT_FLAG_SET
-GST_OBJECT_FLAG_UNSET
-GST_OBJECT_NAME
-GST_OBJECT_PARENT
-GST_OBJECT_REFCOUNT
-GST_OBJECT_REFCOUNT_VALUE
-GST_OBJECT_LOCK
-GST_OBJECT_TRYLOCK
-GST_OBJECT_UNLOCK
-GST_OBJECT_GET_LOCK
-
-gst_object_set_name
-gst_object_get_name
-gst_object_set_parent
-gst_object_get_parent
-gst_object_has_as_parent
-gst_object_unparent
-gst_object_default_deep_notify
-gst_object_default_error
-gst_object_check_uniqueness
-gst_object_has_as_ancestor
-gst_object_has_ancestor
-gst_object_ref
-gst_object_unref
-gst_clear_object
-gst_object_ref_sink
-gst_object_replace
-gst_object_get_path_string
-
-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_g_value_array
-gst_object_get_control_rate
-gst_object_set_control_rate
-
-<SUBSECTION Standard>
-GST_OBJECT
-GST_IS_OBJECT
-GST_OBJECT_CLASS
-GST_IS_OBJECT_CLASS
-GST_OBJECT_GET_CLASS
-GST_TYPE_OBJECT
-GST_TYPE_OBJECT_FLAGS
-GST_OBJECT_CAST
-GST_OBJECT_CLASS_CAST
-<SUBSECTION Private>
-gst_object_get_type
-gst_object_flags_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstpad</FILE>
-<TITLE>GstPad</TITLE>
-GstPad
-
-GstPadDirection
-GstPadFlags
-GstPadLinkReturn
-gst_pad_link_get_name
-GST_PAD_LINK_FAILED
-GST_PAD_LINK_SUCCESSFUL
-GstPadLinkCheck
-GstFlowReturn
-gst_flow_get_name
-gst_flow_to_quark
-GstPadMode
-gst_pad_mode_get_name
-gst_pad_store_sticky_event
-
-<SUBSECTION Application>
-gst_pad_get_name
-gst_pad_get_direction
-gst_pad_get_parent
-gst_pad_get_parent_element
-gst_pad_get_pad_template
-
-gst_pad_link
-gst_pad_link_full
-gst_pad_link_maybe_ghosting
-gst_pad_link_maybe_ghosting_full
-gst_pad_unlink
-gst_pad_is_linked
-gst_pad_can_link
-
-gst_pad_get_allowed_caps
-gst_pad_get_current_caps
-gst_pad_get_pad_template_caps
-
-gst_pad_get_peer
-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_get_last_flow_return
-
-<SUBSECTION probes>
-GstPadProbeReturn
-GstPadProbeType
-
-GstPadProbeInfo
-GST_PAD_PROBE_INFO_TYPE
-GST_PAD_PROBE_INFO_ID
-GST_PAD_PROBE_INFO_DATA
-
-GST_PAD_PROBE_INFO_BUFFER
-GST_PAD_PROBE_INFO_BUFFER_LIST
-GST_PAD_PROBE_INFO_EVENT
-GST_PAD_PROBE_INFO_QUERY
-
-gst_pad_probe_info_get_buffer
-gst_pad_probe_info_get_buffer_list
-gst_pad_probe_info_get_event
-gst_pad_probe_info_get_query
-
-GST_PAD_PROBE_INFO_OFFSET
-GST_PAD_PROBE_INFO_SIZE
-
-GST_PAD_PROBE_INFO_FLOW_RETURN
-
-GstPadProbeCallback
-gst_pad_add_probe
-gst_pad_remove_probe
-
-gst_pad_is_blocked
-gst_pad_is_blocking
-
-<SUBSECTION offset>
-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_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_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_event_full_function
-gst_pad_set_event_full_function_full
-GstPadEventFullFunction
-
-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_proxy_query_caps
-gst_pad_proxy_query_accept_caps
-
-gst_pad_set_activate_function
-gst_pad_set_activate_function_full
-GstPadActivateFunction
-
-gst_pad_set_activatemode_function
-gst_pad_set_activatemode_function_full
-GstPadActivateModeFunction
-
-gst_pad_needs_reconfigure
-gst_pad_check_reconfigure
-gst_pad_mark_reconfigure
-
-gst_pad_push
-gst_pad_push_event
-gst_pad_push_list
-gst_pad_pull_range
-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_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_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_element_private
-gst_pad_get_element_private
-
-gst_pad_create_stream_id
-gst_pad_create_stream_id_printf
-gst_pad_create_stream_id_printf_valist
-
-gst_pad_get_stream_id
-gst_pad_get_stream
-
-GstPadForwardFunction
-gst_pad_forward
-<SUBSECTION Core>
-gst_pad_chain
-gst_pad_chain_list
-
-gst_pad_start_task
-gst_pad_pause_task
-gst_pad_stop_task
-gst_pad_get_task_state
-
-gst_pad_set_active
-
-GST_PAD_GET_STREAM_LOCK
-GST_PAD_STREAM_LOCK
-GST_PAD_STREAM_TRYLOCK
-GST_PAD_STREAM_UNLOCK
-
-GST_PAD_NAME
-GST_PAD_PARENT
-GST_PAD_ELEMENT_PRIVATE
-GST_PAD_PAD_TEMPLATE
-GST_PAD_DIRECTION
-GST_PAD_LAST_FLOW_RETURN
-
-GST_PAD_TASK
-GST_PAD_MODE
-GST_PAD_ACTIVATEFUNC
-GST_PAD_ACTIVATEMODEFUNC
-GST_PAD_CHAINFUNC
-GST_PAD_CHAINLISTFUNC
-GST_PAD_EVENTFUNC
-GST_PAD_EVENTFULLFUNC
-GST_PAD_GETRANGEFUNC
-GST_PAD_QUERYFUNC
-GST_PAD_ITERINTLINKFUNC
-GST_PAD_PEER
-GST_PAD_LINKFUNC
-GST_PAD_UNLINKFUNC
-
-GST_PAD_IS_LINKED
-GST_PAD_IS_SRC
-GST_PAD_IS_SINK
-GST_PAD_IS_ACTIVE
-GST_PAD_IS_BLOCKED
-GST_PAD_IS_BLOCKING
-GST_PAD_IS_FLUSHING
-GST_PAD_SET_FLUSHING
-GST_PAD_UNSET_FLUSHING
-GST_PAD_IS_EOS
-GST_PAD_NEEDS_RECONFIGURE
-GST_PAD_HAS_PENDING_EVENTS
-GST_PAD_IS_FIXED_CAPS
-GST_PAD_NEEDS_PARENT
-GST_PAD_IS_PROXY_CAPS
-GST_PAD_SET_PROXY_CAPS
-GST_PAD_UNSET_PROXY_CAPS
-GST_PAD_IS_PROXY_ALLOCATION
-GST_PAD_SET_PROXY_ALLOCATION
-GST_PAD_UNSET_PROXY_ALLOCATION
-GST_PAD_SET_PROXY_SCHEDULING
-GST_PAD_UNSET_PROXY_SCHEDULING
-GST_PAD_IS_PROXY_SCHEDULING
-GST_PAD_IS_ACCEPT_INTERSECT
-GST_PAD_SET_ACCEPT_INTERSECT
-GST_PAD_UNSET_ACCEPT_INTERSECT
-GST_PAD_IS_ACCEPT_TEMPLATE
-GST_PAD_SET_ACCEPT_TEMPLATE
-GST_PAD_UNSET_ACCEPT_TEMPLATE
-
-<SUBSECTION Standard>
-GstPadClass
-GstPadPrivate
-GST_PAD
-GST_IS_PAD
-GST_PAD_CLASS
-GST_IS_PAD_CLASS
-GST_TYPE_PAD
-GST_TYPE_PAD_DIRECTION
-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_PAD_PROBE_RETURN
-GST_TYPE_PAD_PROBE_TYPE
-
-<SUBSECTION Private>
-gst_pad_get_type
-gst_pad_direction_get_type
-gst_pad_flags_get_type
-gst_pad_link_return_get_type
-gst_pad_link_check_get_type
-gst_pad_presence_get_type
-gst_flow_return_get_type
-gst_pad_mode_get_type
-gst_pad_probe_return_get_type
-gst_pad_probe_type_get_type
-
-GST_PAD_IS_IN_GETCAPS
-GST_PAD_MODE_ACTIVATE
-GST_PAD_BLOCK_BROADCAST
-GST_PAD_BLOCK_GET_COND
-GST_PAD_BLOCK_SIGNAL
-GST_PAD_BLOCK_WAIT
-GST_PAD_CAST
-GST_PAD_DO_BUFFER_SIGNALS
-GST_PAD_DO_EVENT_SIGNALS
-GST_PAD_IS_IN_SETCAPS
-
-GST_PAD_QUERYTYPEFUNC
-</SECTION>
-
-
-<SECTION>
-<FILE>gstpadtemplate</FILE>
-<TITLE>GstPadTemplate</TITLE>
-GstStaticPadTemplate
-GST_STATIC_PAD_TEMPLATE
-gst_static_pad_template_get
-gst_static_pad_template_get_caps
-GstPadTemplate
-GstPadTemplateFlags
-GstPadPresence
-GST_PAD_TEMPLATE_NAME_TEMPLATE
-GST_PAD_TEMPLATE_DIRECTION
-GST_PAD_TEMPLATE_PRESENCE
-GST_PAD_TEMPLATE_CAPS
-GST_PAD_TEMPLATE_IS_FIXED
-GST_PAD_TEMPLATE_GTYPE
-gst_pad_template_new
-gst_pad_template_new_with_gtype
-gst_pad_template_new_from_static_pad_template_with_gtype
-gst_pad_template_get_caps
-
-<SUBSECTION Standard>
-GstPadTemplateClass
-GST_PAD_TEMPLATE
-GST_IS_PAD_TEMPLATE
-GST_PAD_TEMPLATE_CLASS
-GST_IS_PAD_TEMPLATE_CLASS
-GST_TYPE_PAD_TEMPLATE
-GST_TYPE_PAD_TEMPLATE_FLAGS
-GST_TYPE_STATIC_CAPS
-GST_TYPE_STATIC_PAD_TEMPLATE
-
-<SUBSECTION Private>
-gst_pad_template_get_type
-gst_pad_template_flags_get_type
-gst_pad_template_pad_created
-gst_static_pad_template_get_type
-gst_static_caps_get_type
-
-</SECTION>
-
-
-<SECTION>
-<FILE>gstparamspec</FILE>
-<TITLE>GstParamSpec</TITLE>
-
-GST_PARAM_CONTROLLABLE
-GST_PARAM_USER_SHIFT
-GST_PARAM_MUTABLE_PAUSED
-GST_PARAM_MUTABLE_PLAYING
-GST_PARAM_MUTABLE_READY
-
-<SUBSECTION paramspecfraction>
-GstParamSpecFraction
-gst_param_spec_fraction
-
-<SUBSECTION paramspecarray>
-GstParamSpecArray
-gst_param_spec_array
-
-
-<SUBSECTION Standard>
-GST_IS_PARAM_SPEC_FRACTION
-GST_PARAM_SPEC_FRACTION
-GST_TYPE_PARAM_FRACTION
-gst_param_spec_fraction_get_type
-
-GST_IS_PARAM_SPEC_ARRAY_LIST
-GST_PARAM_SPEC_ARRAY_LIST
-GST_TYPE_PARAM_ARRAY_LIST
-gst_param_spec_array_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstparse</FILE>
-<TITLE>GstParse</TITLE>
-gst_parse_error_quark
-GST_PARSE_ERROR
-GstParseError
-GstParseContext
-GstParseFlags
-gst_parse_launch
-gst_parse_launch_full
-gst_parse_launchv
-gst_parse_launchv_full
-gst_parse_bin_from_description
-gst_parse_bin_from_description_full
-<SUBSECTION>
-gst_parse_context_new
-gst_parse_context_copy
-gst_parse_context_free
-gst_parse_context_get_missing_elements
-<SUBSECTION Standard>
-GST_TYPE_PARSE_ERROR
-GST_TYPE_PARSE_FLAGS
-GST_TYPE_PARSE_CONTEXT
-<SUBSECTION Private>
-gst_parse_context_get_type
-gst_parse_error_get_type
-gst_parse_flags_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstpipeline</FILE>
-<TITLE>GstPipeline</TITLE>
-GstPipeline
-GstPipelineFlags
-
-gst_pipeline_new
-
-gst_pipeline_get_bus
-
-gst_pipeline_set_clock
-gst_pipeline_get_pipeline_clock
-gst_pipeline_get_clock
-
-gst_pipeline_use_clock
-gst_pipeline_auto_clock
-
-gst_pipeline_set_auto_flush_bus
-gst_pipeline_get_auto_flush_bus
-
-gst_pipeline_set_delay
-gst_pipeline_get_delay
-
-gst_pipeline_set_latency
-gst_pipeline_get_latency
-
-<SUBSECTION Standard>
-GstPipelineClass
-GST_PIPELINE
-GST_IS_PIPELINE
-GST_PIPELINE_CLASS
-GST_IS_PIPELINE_CLASS
-GST_PIPELINE_GET_CLASS
-GST_TYPE_PIPELINE
-GST_TYPE_PIPELINE_FLAGS
-GST_PIPELINE_CAST
-<SUBSECTION Private>
-GstPipelinePrivate
-gst_pipeline_get_type
-gst_pipeline_flags_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstplugin</FILE>
-<TITLE>GstPlugin</TITLE>
-gst_plugin_error_quark
-GST_PLUGIN_ERROR
-GstPluginError
-GstPlugin
-GstPluginDesc
-GstPluginInitFunc
-GstPluginInitFullFunc
-GST_PLUGIN_DEFINE
-GST_PLUGIN_STATIC_DECLARE
-GST_PLUGIN_STATIC_REGISTER
-GST_LICENSE_UNKNOWN
-GstPluginFilter
-gst_plugin_get_name
-gst_plugin_get_description
-gst_plugin_get_filename
-gst_plugin_get_license
-gst_plugin_get_package
-gst_plugin_get_origin
-gst_plugin_get_source
-gst_plugin_get_version
-gst_plugin_get_release_date_string
-gst_plugin_is_loaded
-gst_plugin_get_cache_data
-gst_plugin_set_cache_data
-gst_plugin_load_file
-gst_plugin_load
-gst_plugin_load_by_name
-gst_plugin_list_free
-gst_plugin_register_static
-gst_plugin_register_static_full
-<SUBSECTION>
-GstPluginFlags
-GstPluginDependencyFlags
-gst_plugin_add_dependency
-gst_plugin_add_dependency_simple
-<SUBSECTION Standard>
-GstPluginClass
-GST_PLUGIN
-GST_PLUGIN_CAST
-GST_PLUGIN_CLASS
-GST_PLUGIN_GET_CLASS
-GST_TYPE_PLUGIN
-GST_TYPE_PLUGIN_ERROR
-GST_IS_PLUGIN
-GST_IS_PLUGIN_CLASS
-GST_TYPE_PLUGIN_FLAGS
-GST_TYPE_PLUGIN_DEPENDENCY_FLAGS
-GstPluginPrivate
-gst_plugin_dependency_flags_get_type
-<SUBSECTION Private>
-gst_plugin_get_type
-<SUBSECTION Private>
-gst_plugin_error_get_type
-gst_plugin_flags_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstpluginfeature</FILE>
-<TITLE>GstPluginFeature</TITLE>
-GstPluginFeature
-GstPluginFeatureFilter
-GstRank
-
-gst_plugin_feature_set_rank
-gst_plugin_feature_set_name
-gst_plugin_feature_get_rank
-gst_plugin_feature_get_name
-gst_plugin_feature_get_plugin
-gst_plugin_feature_get_plugin_name
-gst_plugin_feature_load
-gst_plugin_feature_list_copy
-gst_plugin_feature_list_free
-GST_PLUGIN_FEATURE_LIST_DEBUG
-gst_plugin_feature_check_version
-gst_plugin_feature_rank_compare_func
-<SUBSECTION Standard>
-GstPluginFeatureClass
-GST_PLUGIN_FEATURE
-GST_PLUGIN_FEATURE_CAST
-GST_IS_PLUGIN_FEATURE
-GST_PLUGIN_FEATURE_CLASS
-GST_IS_PLUGIN_FEATURE_CLASS
-GST_PLUGIN_FEATURE_GET_CLASS
-GST_TYPE_PLUGIN_FEATURE
-GST_TYPE_RANK
-<SUBSECTION Private>
-gst_plugin_feature_get_type
-gst_plugin_feature_list_debug
-gst_rank_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstpoll</FILE>
-<TITLE>GstPoll</TITLE>
-GstPoll
-GstPollFD
-GST_POLL_FD_INIT
-gst_poll_add_fd
-gst_poll_fd_can_read
-gst_poll_fd_can_write
-gst_poll_fd_ctl_read
-gst_poll_fd_ctl_write
-gst_poll_fd_has_closed
-gst_poll_fd_has_error
-gst_poll_fd_ignored
-gst_poll_fd_init
-gst_poll_free
-gst_poll_new
-gst_poll_new_timer
-gst_poll_get_read_gpollfd
-gst_poll_remove_fd
-gst_poll_restart
-gst_poll_set_controllable
-gst_poll_set_flushing
-gst_poll_wait
-gst_poll_read_control
-gst_poll_write_control
-</SECTION>
-
-<SECTION>
-<FILE>gstpreset</FILE>
-<TITLE>GstPreset</TITLE>
-GstPreset
-GstPresetInterface
-gst_preset_get_preset_names
-gst_preset_get_property_names
-gst_preset_load_preset
-gst_preset_save_preset
-gst_preset_rename_preset
-gst_preset_delete_preset
-gst_preset_set_meta
-gst_preset_get_meta
-gst_preset_set_app_dir
-gst_preset_get_app_dir
-gst_preset_is_editable
-<SUBSECTION Standard>
-GST_PRESET
-GST_IS_PRESET
-GST_TYPE_PRESET
-GST_PRESET_GET_INTERFACE
-gst_preset_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstprotection</FILE>
-<TITLE>GstProtectionMeta</TITLE>
-GstProtectionMeta
-gst_buffer_add_protection_meta
-gst_buffer_get_protection_meta
-gst_protection_select_system
-gst_protection_filter_systems_by_available_decryptors
-GST_PROTECTION_SYSTEM_ID_CAPS_FIELD
-GST_PROTECTION_UNSPECIFIED_SYSTEM_ID
-<SUBSECTION Standard>
-GST_PROTECTION_META_API_TYPE
-GST_PROTECTION_META_INFO
-gst_protection_meta_get_info
-gst_protection_meta_api_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstquery</FILE>
-<TITLE>GstQuery</TITLE>
-GstQuery
-
-GstQueryTypeFlags
-GST_QUERY_TYPE_BOTH
-GST_QUERY_MAKE_TYPE
-
-GstQueryType
-
-GST_QUERY_TYPE
-GST_QUERY_TYPE_NAME
-
-GST_QUERY_IS_UPSTREAM
-GST_QUERY_IS_DOWNSTREAM
-GST_QUERY_IS_SERIALIZED
-
-gst_query_type_get_flags
-gst_query_type_get_name
-gst_query_type_to_quark
-
-gst_query_ref
-gst_query_unref
-gst_clear_query
-gst_query_copy
-gst_query_make_writable
-gst_query_is_writable
-gst_query_replace
-gst_query_take
-gst_query_writable_structure
-
-gst_query_new_custom
-gst_query_get_structure
-
-gst_query_new_convert
-gst_query_set_convert
-gst_query_parse_convert
-
-gst_query_new_position
-gst_query_set_position
-gst_query_parse_position
-
-gst_query_new_duration
-gst_query_set_duration
-gst_query_parse_duration
-
-gst_query_new_latency
-gst_query_parse_latency
-gst_query_set_latency
-
-gst_query_new_seeking
-gst_query_set_seeking
-gst_query_parse_seeking
-
-gst_query_new_formats
-gst_query_set_formats
-gst_query_set_formatsv
-gst_query_parse_n_formats
-gst_query_parse_nth_format
-
-gst_query_new_segment
-gst_query_set_segment
-gst_query_parse_segment
-
-gst_query_new_caps
-gst_query_parse_caps
-gst_query_set_caps_result
-gst_query_parse_caps_result
-
-gst_query_new_accept_caps
-gst_query_parse_accept_caps
-gst_query_set_accept_caps_result
-gst_query_parse_accept_caps_result
-
-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_query_add_buffering_range
-gst_query_get_n_buffering_ranges
-gst_query_parse_nth_buffering_range
-
-gst_query_new_uri
-gst_query_parse_uri
-gst_query_set_uri
-gst_query_parse_uri_redirection
-gst_query_set_uri_redirection
-gst_query_parse_uri_redirection_permanent
-gst_query_set_uri_redirection_permanent
-
-gst_query_new_allocation
-gst_query_parse_allocation
-
-gst_query_add_allocation_pool
-gst_query_get_n_allocation_pools
-gst_query_parse_nth_allocation_pool
-gst_query_set_nth_allocation_pool
-gst_query_remove_nth_allocation_pool
-
-gst_query_add_allocation_param
-gst_query_get_n_allocation_params
-gst_query_parse_nth_allocation_param
-gst_query_set_nth_allocation_param
-gst_query_remove_nth_allocation_param
-
-gst_query_add_allocation_meta
-gst_query_get_n_allocation_metas
-gst_query_parse_nth_allocation_meta
-gst_query_remove_nth_allocation_meta
-gst_query_find_allocation_meta
-
-GstSchedulingFlags
-gst_query_new_scheduling
-gst_query_parse_scheduling
-gst_query_set_scheduling
-gst_query_add_scheduling_mode
-gst_query_get_n_scheduling_modes
-gst_query_parse_nth_scheduling_mode
-gst_query_has_scheduling_mode
-gst_query_has_scheduling_mode_with_flags
-
-gst_query_new_drain
-
-gst_query_new_context
-gst_query_set_context
-gst_query_parse_context
-gst_query_parse_context_type
-
-gst_query_new_bitrate
-gst_query_set_bitrate
-gst_query_parse_bitrate
-<SUBSECTION Standard>
-GstQueryClass
-GST_QUERY
-GST_QUERY_CAST
-GST_IS_QUERY
-GST_QUERY_CLASS
-GST_IS_QUERY_CLASS
-GST_TYPE_QUERY
-GST_TYPE_QUERY_TYPE
-GST_QUERY_GET_CLASS
-GST_TYPE_QUERY_TYPE_FLAGS
-gst_query_type_flags_get_type
-GST_TYPE_BUFFERING_MODE
-gst_buffering_mode_get_type
-GST_TYPE_SCHEDULING_FLAGS
-gst_scheduling_flags_get_type
-<SUBSECTION Private>
-GST_QUERY_NUM_SHIFT
-gst_query_get_type
-gst_query_type_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstregistry</FILE>
-<TITLE>GstRegistry</TITLE>
-GstRegistry
-gst_registry_get
-gst_registry_get_feature_list
-gst_registry_get_feature_list_cookie
-gst_registry_get_feature_list_by_plugin
-gst_registry_get_plugin_list
-gst_registry_add_plugin
-gst_registry_remove_plugin
-gst_registry_plugin_filter
-gst_registry_feature_filter
-gst_registry_find_plugin
-gst_registry_find_feature
-gst_registry_lookup_feature
-gst_registry_add_path
-gst_registry_get_path_list
-gst_registry_scan_path
-gst_registry_lookup
-gst_registry_remove_feature
-gst_registry_add_feature
-gst_registry_check_feature_version
-<SUBSECTION Standard>
-GstRegistryClass
-GST_REGISTRY
-GST_IS_REGISTRY
-GST_REGISTRY_CLASS
-GST_IS_REGISTRY_CLASS
-GST_REGISTRY_GET_CLASS
-GST_TYPE_REGISTRY
-<SUBSECTION Private>
-GST_MAGIC_BINARY_REGISTRY_LEN
-GST_MAGIC_BINARY_REGISTRY_STR
-GST_MAGIC_BINARY_VERSION_STR
-GST_MAGIC_BINARY_VERSION_LEN
-gst_registry_get_type
-GstRegistryPrivate
-</SECTION>
-
-
-<SECTION>
-<FILE>gstpromise</FILE>
-<TITLE>GstPromise</TITLE>
-GstPromiseResult
-GstPromiseChangeFunc
-GstPromise
-gst_promise_new
-gst_promise_new_with_change_func
-gst_promise_ref
-gst_promise_unref
-gst_promise_wait
-gst_promise_reply
-gst_promise_interrupt
-gst_promise_expire
-gst_promise_get_reply
-<SUBSECTION Standard>
-GST_PROMISE
-GST_TYPE_PROMISE
-gst_promise_get_type
-GST_TYPE_PROMISE_RESULT
-gst_promise_result_get_type
-</SECTION>
-
-
-<SECTION>
-<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_do_seek
-gst_segment_position_from_stream_time
-gst_segment_position_from_stream_time_full
-gst_segment_to_running_time
-gst_segment_to_running_time_full
-gst_segment_to_stream_time
-gst_segment_to_stream_time_full
-gst_segment_position_from_running_time
-gst_segment_position_from_running_time_full
-gst_segment_to_position
-gst_segment_set_running_time
-gst_segment_copy_into
-gst_segment_offset_running_time
-gst_segment_is_equal
-<SUBSECTION Standard>
-GST_TYPE_SEGMENT
-GST_TYPE_SEGMENT_FLAGS
-gst_segment_get_type
-gst_segment_flags_get_type
-<SUBSECTION Private>
-</SECTION>
-
-<SECTION>
-<FILE>gststreams</FILE>
-<TITLE>GstStream</TITLE>
-GstStream
-GstStreamClass
-GstStreamType
-gst_stream_new
-gst_stream_get_caps
-gst_stream_get_stream_flags
-gst_stream_get_stream_id
-gst_stream_get_stream_type
-gst_stream_get_tags
-gst_stream_set_caps
-gst_stream_set_stream_flags
-gst_stream_set_stream_type
-gst_stream_set_tags
-gst_stream_type_get_name
-<SUBSECTION Standard>
-GST_IS_STREAM
-GST_IS_STREAM_CLASS
-GST_STREAM
-GST_STREAM_CAST
-GST_STREAM_CLASS
-GST_STREAM_GET_CLASS
-GST_TYPE_STREAM
-GST_TYPE_STREAM_TYPE
-gst_stream_get_type
-gst_stream_type_get_type
-<SUBSECTION Private>
-GstStreamPrivate
-</SECTION>
-
-<SECTION>
-<FILE>gststreamcollection</FILE>
-<TITLE>GstStreamCollection</TITLE>
-GstStreamCollection
-GstStreamCollectionClass
-gst_stream_collection_new
-gst_stream_collection_add_stream
-gst_stream_collection_get_upstream_id
-gst_stream_collection_get_size
-gst_stream_collection_get_stream
-<SUBSECTION Standard>
-gst_stream_collection_get_type
-GST_IS_STREAM_COLLECTION
-GST_IS_STREAM_COLLECTION_CLASS
-GST_STREAM_COLLECTION
-GST_STREAM_COLLECTION_CAST
-GST_STREAM_COLLECTION_CLASS
-GST_STREAM_COLLECTION_GET_CLASS
-GST_TYPE_STREAM_COLLECTION
-<SUBSECTION Private>
-GstStreamCollectionPrivate
-</SECTION>
-
-<SECTION>
-<FILE>gststructure</FILE>
-<TITLE>GstStructure</TITLE>
-GstStructure
-GstStructureForeachFunc
-GstStructureMapFunc
-GstStructureFilterMapFunc
-gst_structure_new_empty
-gst_structure_new_id_empty
-gst_structure_new
-gst_structure_new_valist
-gst_structure_new_id
-gst_structure_new_from_string
-gst_structure_copy
-gst_structure_free
-gst_structure_get_name
-gst_structure_has_name
-gst_structure_set_name
-gst_structure_get_name_id
-gst_structure_id_get
-gst_structure_id_get_valist
-gst_structure_id_get_value
-gst_structure_id_set_value
-gst_structure_id_take_value
-gst_structure_get
-gst_structure_get_valist
-gst_structure_get_value
-gst_structure_set_value
-gst_structure_set_array
-gst_structure_set_list
-gst_structure_take_value
-gst_structure_set
-gst_structure_set_valist
-gst_structure_id_set
-gst_structure_id_set_valist
-gst_structure_remove_field
-gst_structure_remove_fields
-gst_structure_remove_fields_valist
-gst_structure_remove_all_fields
-gst_structure_get_field_type
-gst_structure_n_fields
-gst_structure_has_field
-gst_structure_has_field_typed
-gst_structure_is_equal
-gst_structure_is_subset
-gst_structure_can_intersect
-gst_structure_intersect
-gst_structure_id_has_field
-gst_structure_id_has_field_typed
-gst_structure_get_boolean
-gst_structure_get_int
-gst_structure_get_uint
-gst_structure_get_int64
-gst_structure_get_uint64
-gst_structure_get_double
-gst_structure_get_string
-gst_structure_get_date
-gst_structure_get_date_time
-gst_structure_get_clock_time
-gst_structure_get_enum
-gst_structure_get_fraction
-gst_structure_get_array
-gst_structure_get_list
-gst_structure_foreach
-gst_structure_map_in_place
-gst_structure_filter_and_map_in_place
-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
-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>
-gst_structure_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstsystemclock</FILE>
-<TITLE>GstSystemClock</TITLE>
-GstClockType
-GstSystemClock
-gst_system_clock_obtain
-gst_system_clock_set_default
-<SUBSECTION Standard>
-GstSystemClockClass
-GstSystemClockPrivate
-GST_SYSTEM_CLOCK
-GST_IS_SYSTEM_CLOCK
-gst_system_clock_get_type
-GST_SYSTEM_CLOCK_CLASS
-GST_IS_SYSTEM_CLOCK_CLASS
-GST_SYSTEM_CLOCK_GET_CLASS
-GST_TYPE_SYSTEM_CLOCK
-GST_SYSTEM_CLOCK_CAST
-GST_TYPE_CLOCK_TYPE
-gst_clock_type_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gsttaglist</FILE>
-<TITLE>GstTagList</TITLE>
-GstTagList
-GstTagMergeMode
-GstTagFlag
-GstTagForeachFunc
-GstTagMergeFunc
-
-GstTagScope
-
-GST_TAG_TITLE
-GST_TAG_TITLE_SORTNAME
-GST_TAG_ARTIST
-GST_TAG_ARTIST_SORTNAME
-GST_TAG_ALBUM
-GST_TAG_ALBUM_SORTNAME
-GST_TAG_ALBUM_ARTIST
-GST_TAG_ALBUM_ARTIST_SORTNAME
-GST_TAG_DATE
-GST_TAG_DATE_TIME
-GST_TAG_GENRE
-GST_TAG_COMMENT
-GST_TAG_EXTENDED_COMMENT
-GST_TAG_TRACK_NUMBER
-GST_TAG_TRACK_COUNT
-GST_TAG_ALBUM_VOLUME_NUMBER
-GST_TAG_ALBUM_VOLUME_COUNT
-GST_TAG_LOCATION
-GST_TAG_HOMEPAGE
-GST_TAG_DESCRIPTION
-GST_TAG_VERSION
-GST_TAG_ISRC
-GST_TAG_ORGANIZATION
-GST_TAG_COPYRIGHT
-GST_TAG_COPYRIGHT_URI
-GST_TAG_ENCODED_BY
-GST_TAG_COMPOSER
-GST_TAG_CONDUCTOR
-GST_TAG_CONTACT
-GST_TAG_LICENSE
-GST_TAG_LICENSE_URI
-GST_TAG_PERFORMER
-GST_TAG_DURATION
-GST_TAG_CODEC
-GST_TAG_VIDEO_CODEC
-GST_TAG_AUDIO_CODEC
-GST_TAG_SUBTITLE_CODEC
-GST_TAG_CONTAINER_FORMAT
-GST_TAG_BITRATE
-GST_TAG_NOMINAL_BITRATE
-GST_TAG_MINIMUM_BITRATE
-GST_TAG_MAXIMUM_BITRATE
-GST_TAG_SERIAL
-GST_TAG_ENCODER
-GST_TAG_ENCODER_VERSION
-GST_TAG_TRACK_GAIN
-GST_TAG_TRACK_PEAK
-GST_TAG_ALBUM_GAIN
-GST_TAG_ALBUM_PEAK
-GST_TAG_REFERENCE_LEVEL
-GST_TAG_LANGUAGE_CODE
-GST_TAG_LANGUAGE_NAME
-GST_TAG_IMAGE
-GST_TAG_PREVIEW_IMAGE
-GST_TAG_ATTACHMENT
-GST_TAG_BEATS_PER_MINUTE
-GST_TAG_KEYWORDS
-GST_TAG_GEO_LOCATION_NAME
-GST_TAG_GEO_LOCATION_LATITUDE
-GST_TAG_GEO_LOCATION_LONGITUDE
-GST_TAG_GEO_LOCATION_ELEVATION
-GST_TAG_GEO_LOCATION_CITY
-GST_TAG_GEO_LOCATION_COUNTRY
-GST_TAG_GEO_LOCATION_SUBLOCATION
-GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR
-GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION
-GST_TAG_GEO_LOCATION_MOVEMENT_SPEED
-GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION
-GST_TAG_SHOW_NAME
-GST_TAG_SHOW_SORTNAME
-GST_TAG_SHOW_EPISODE_NUMBER
-GST_TAG_SHOW_SEASON_NUMBER
-GST_TAG_LYRICS
-GST_TAG_COMPOSER_SORTNAME
-GST_TAG_GROUPING
-GST_TAG_USER_RATING
-GST_TAG_DEVICE_MANUFACTURER
-GST_TAG_DEVICE_MODEL
-GST_TAG_APPLICATION_NAME
-GST_TAG_APPLICATION_DATA
-GST_TAG_IMAGE_ORIENTATION
-GST_TAG_PUBLISHER
-GST_TAG_INTERPRETED_BY
-GST_TAG_MIDI_BASE_NOTE
-GST_TAG_PRIVATE_DATA
-
-gst_tag_register
-gst_tag_register_static
-gst_tag_merge_use_first
-gst_tag_merge_strings_with_comma
-gst_tag_exists
-gst_tag_get_type
-gst_tag_get_nick
-gst_tag_get_description
-gst_tag_get_flag
-gst_tag_is_fixed
-gst_tag_list_new
-gst_tag_list_new_empty
-gst_tag_list_new_valist
-gst_tag_list_new_from_string
-gst_tag_list_free
-gst_tag_list_get_scope
-gst_tag_list_set_scope
-gst_tag_list_to_string
-gst_tag_list_is_empty
-gst_tag_list_is_equal
-gst_tag_list_copy
-gst_tag_list_ref
-gst_tag_list_unref
-gst_clear_tag_list
-gst_tag_list_is_writable
-gst_tag_list_make_writable
-gst_tag_list_replace
-gst_tag_list_take
-gst_tag_list_insert
-gst_tag_list_merge
-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
-gst_tag_list_add_valist
-gst_tag_list_add_valist_values
-gst_tag_list_remove_tag
-gst_tag_list_foreach
-gst_tag_list_get_value_index
-gst_tag_list_copy_value
-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_int64
-gst_tag_list_get_int64_index
-gst_tag_list_get_uint64
-gst_tag_list_get_uint64_index
-gst_tag_list_get_float
-gst_tag_list_get_float_index
-gst_tag_list_get_double
-gst_tag_list_get_double_index
-gst_tag_list_get_string
-gst_tag_list_get_string_index
-gst_tag_list_peek_string_index
-gst_tag_list_get_pointer
-gst_tag_list_get_pointer_index
-gst_tag_list_get_date
-gst_tag_list_get_date_index
-gst_tag_list_get_date_time
-gst_tag_list_get_date_time_index
-gst_tag_list_get_sample
-gst_tag_list_get_sample_index
-<SUBSECTION Standard>
-GST_TAG_LIST
-GST_IS_TAG_LIST
-GST_TAG_FLAG_IS_VALID
-GST_TAG_MODE_IS_VALID
-GST_TYPE_TAG_LIST
-GST_TYPE_TAG_FLAG
-GST_TYPE_TAG_MERGE_MODE
-GST_TYPE_TAG_SCOPE
-<SUBSECTION Private>
-gst_tag_list_get_type
-gst_tag_flag_get_type
-gst_tag_merge_mode_get_type
-gst_tag_scope_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gsttagsetter</FILE>
-<TITLE>GstTagSetter</TITLE>
-GstTagSetter
-GstTagSetterInterface
-gst_tag_setter_reset_tags
-gst_tag_setter_merge_tags
-gst_tag_setter_add_tags
-gst_tag_setter_add_tag_value
-gst_tag_setter_add_tag_values
-gst_tag_setter_add_tag_valist
-gst_tag_setter_add_tag_valist_values
-gst_tag_setter_get_tag_list
-gst_tag_setter_set_tag_merge_mode
-gst_tag_setter_get_tag_merge_mode
-<SUBSECTION Standard>
-GST_TAG_SETTER
-GST_IS_TAG_SETTER
-GST_TAG_SETTER_GET_INTERFACE
-GST_TYPE_TAG_SETTER
-<SUBSECTION Private>
-gst_tag_setter_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gsttaskpool</FILE>
-<TITLE>GstTaskPool</TITLE>
-GstTaskPool
-GstTaskPoolClass
-GstTaskPoolFunction
-gst_task_pool_new
-gst_task_pool_prepare
-gst_task_pool_push
-gst_task_pool_join
-gst_task_pool_cleanup
-<SUBSECTION Standard>
-GST_IS_TASK_POOL
-GST_IS_TASK_POOL_CLASS
-GST_TASK_POOL
-GST_TASK_POOL_CAST
-GST_TASK_POOL_CLASS
-GST_TASK_POOL_GET_CLASS
-GST_TYPE_TASK_POOL
-<SUBSECTION Private>
-gst_task_pool_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gsttask</FILE>
-<TITLE>GstTask</TITLE>
-GstTask
-GstTaskFunction
-GstTaskState
-
-GST_TASK_BROADCAST
-GST_TASK_GET_COND
-GST_TASK_GET_LOCK
-GST_TASK_SIGNAL
-GST_TASK_STATE
-GST_TASK_WAIT
-
-gst_task_new
-gst_task_set_lock
-
-gst_task_set_pool
-gst_task_get_pool
-
-GstTaskThreadFunc
-gst_task_set_enter_callback
-gst_task_set_leave_callback
-
-gst_task_get_state
-gst_task_set_state
-gst_task_pause
-gst_task_start
-gst_task_stop
-gst_task_join
-
-gst_task_cleanup_all
-
-<SUBSECTION Standard>
-GstTaskClass
-GstTaskPrivate
-GST_TASK
-GST_IS_TASK
-GST_TYPE_TASK
-GST_TASK_CLASS
-GST_IS_TASK_CLASS
-GST_TASK_GET_CLASS
-GST_TASK_CAST
-GST_TYPE_TASK_STATE
-<SUBSECTION Private>
-gst_task_get_type
-gst_task_state_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gsttoc</FILE>
-<TITLE>GstToc</TITLE>
-GstToc
-GstTocScope
-GstTocEntry
-GstTocEntryType
-GstTocLoopType
-gst_toc_new
-gst_toc_ref
-gst_toc_unref
-gst_toc_copy
-gst_toc_make_writable
-gst_toc_get_scope
-gst_toc_get_entries
-gst_toc_append_entry
-gst_toc_get_tags
-gst_toc_merge_tags
-gst_toc_set_tags
-gst_toc_dump
-gst_toc_entry_new
-gst_toc_entry_ref
-gst_toc_entry_unref
-gst_toc_entry_copy
-gst_toc_entry_make_writable
-gst_toc_find_entry
-gst_toc_entry_get_toc
-gst_toc_entry_get_uid
-gst_toc_entry_get_parent
-gst_toc_entry_get_sub_entries
-gst_toc_entry_append_sub_entry
-gst_toc_entry_get_loop
-gst_toc_entry_set_loop
-gst_toc_entry_get_start_stop_times
-gst_toc_entry_set_start_stop_times
-gst_toc_entry_get_tags
-gst_toc_entry_merge_tags
-gst_toc_entry_set_tags
-gst_toc_entry_type_get_nick
-gst_toc_entry_get_entry_type
-gst_toc_entry_is_alternative
-gst_toc_entry_is_sequence
-GST_TOC_ENTRY_TYPE_IS_ALTERNATIVE
-GST_TOC_ENTRY_TYPE_IS_SEQUENCE
-GST_TOC_REPEAT_COUNT_INFINITE
-<SUBSECTION Standard>
-GST_TYPE_TOC
-GST_TYPE_TOC_ENTRY
-GST_TYPE_TOC_ENTRY_TYPE
-GST_TYPE_TOC_LOOP_TYPE
-GST_TYPE_TOC_SCOPE
-<SUBSECTION Private>
-gst_toc_get_type
-gst_toc_entry_get_type
-gst_toc_entry_type_get_type
-gst_toc_loop_type_get_type
-gst_toc_scope_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gsttracer</FILE>
-<TITLE>GstTracer</TITLE>
-GstTracer
-gst_tracer_register
-gst_tracing_register_hook
-
-GstTracerHookBinAddPost
-GstTracerHookBinAddPre
-GstTracerHookBinRemovePost
-GstTracerHookBinRemovePre
-GstTracerHookElementAddPad
-GstTracerHookElementChangeStatePost
-GstTracerHookElementChangeStatePre
-GstTracerHookElementNew
-GstTracerHookElementPostMessagePost
-GstTracerHookElementPostMessagePre
-GstTracerHookElementQueryPost
-GstTracerHookElementQueryPre
-GstTracerHookElementRemovePad
-GstTracerHookMiniObjectCreated
-GstTracerHookMiniObjectDestroyed
-GstTracerHookMiniObjectReffed
-GstTracerHookMiniObjectUnreffed
-GstTracerHookObjectCreated
-GstTracerHookObjectDestroyed
-GstTracerHookObjectReffed
-GstTracerHookObjectUnreffed
-GstTracerHookPadLinkPost
-GstTracerHookPadLinkPre
-GstTracerHookPadPullRangePost
-GstTracerHookPadPullRangePre
-GstTracerHookPadPushEventPost
-GstTracerHookPadPushEventPre
-GstTracerHookPadPushListPost
-GstTracerHookPadPushListPre
-GstTracerHookPadPushPost
-GstTracerHookPadPushPre
-GstTracerHookPadQueryPost
-GstTracerHookPadQueryPre
-GstTracerHookPadUnlinkPost
-GstTracerHookPadUnlinkPre
-<SUBSECTION Standard>
-GST_TRACER
-GST_IS_TRACER
-GST_TYPE_TRACER
-GST_TRACER_CLASS
-GST_IS_TRACER_CLASS
-GST_TRACER_GET_CLASS
-GST_TRACER_CAST
-<SUBSECTION Private>
-GST_TRACER_ARGS
-GST_TRACER_DISPATCH
-GST_TRACER_IS_ENABLED
-GST_TRACER_QUARK
-GST_TRACER_TS
-GST_TRACER_BIN_ADD_POST
-GST_TRACER_BIN_ADD_PRE
-GST_TRACER_BIN_REMOVE_POST
-GST_TRACER_BIN_REMOVE_PRE
-GST_TRACER_ELEMENT_ADD_PAD
-GST_TRACER_ELEMENT_CHANGE_STATE_POST
-GST_TRACER_ELEMENT_CHANGE_STATE_PRE
-GST_TRACER_ELEMENT_NEW
-GST_TRACER_ELEMENT_POST_MESSAGE_POST
-GST_TRACER_ELEMENT_POST_MESSAGE_PRE
-GST_TRACER_ELEMENT_QUERY_POST
-GST_TRACER_ELEMENT_QUERY_PRE
-GST_TRACER_ELEMENT_REMOVE_PAD
-GST_TRACER_MINI_OBJECT_CREATED
-GST_TRACER_MINI_OBJECT_DESTROYED
-GST_TRACER_MINI_OBJECT_REFFED
-GST_TRACER_MINI_OBJECT_UNREFFED
-GST_TRACER_OBJECT_CREATED
-GST_TRACER_OBJECT_DESTROYED
-GST_TRACER_OBJECT_REFFED
-GST_TRACER_OBJECT_UNREFFED
-GST_TRACER_PAD_LINK_POST
-GST_TRACER_PAD_LINK_PRE
-GST_TRACER_PAD_PULL_RANGE_POST
-GST_TRACER_PAD_PULL_RANGE_PRE
-GST_TRACER_PAD_PUSH_EVENT_POST
-GST_TRACER_PAD_PUSH_EVENT_PRE
-GST_TRACER_PAD_PUSH_LIST_POST
-GST_TRACER_PAD_PUSH_LIST_PRE
-GST_TRACER_PAD_PUSH_POST
-GST_TRACER_PAD_PUSH_PRE
-GST_TRACER_PAD_QUERY_POST
-GST_TRACER_PAD_QUERY_PRE
-GST_TRACER_PAD_UNLINK_POST
-GST_TRACER_PAD_UNLINK_PRE
-GstTracerHook
-GstTracerQuarkId
-gst_tracer_get_type
-GstTracerPrivate
-</SECTION>
-
-
-<SECTION>
-<FILE>gsttracerfactory</FILE>
-<TITLE>GstTracerFactory</TITLE>
-GstTracerFactory
-gst_tracer_factory_get_list
-gst_tracer_factory_get_tracer_type
-<SUBSECTION Standard>
-GstTracerFactoryClass
-GST_TRACER_FACTORY
-GST_IS_TRACER_FACTORY
-GST_TRACER_FACTORY_CLASS
-GST_IS_TRACER_FACTORY_CLASS
-GST_TRACER_FACTORY_GET_CLASS
-GST_TRACER_FACTORY_CAST
-GST_TYPE_TRACER_FACTORY
-<SUBSECTION Private>
-gst_tracer_factory_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gsttracerrecord</FILE>
-<TITLE>GstTracerRecord</TITLE>
-GstTracerRecord
-GstTracerValueFlags
-GstTracerValueScope
-gst_tracer_record_new
-gst_tracer_record_log
-<SUBSECTION Standard>
-GstTracerRecordClass
-GST_TRACER_RECORD
-GST_IS_TRACER_RECORD
-GST_TRACER_RECORD_CLASS
-GST_IS_TRACER_RECORD_CLASS
-GST_TRACER_RECORD_GET_CLASS
-GST_TRACER_RECORD_CAST
-GST_TYPE_TRACER_RECORD
-GST_TYPE_TRACER_VALUE_FLAGS
-GST_TYPE_TRACER_VALUE_SCOPE
-<SUBSECTION Private>
-gst_tracer_record_get_type
-gst_tracer_value_flags_get_type
-gst_tracer_value_scope_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gsttocsetter</FILE>
-<TITLE>GstTocSetter</TITLE>
-GstTocSetter
-GstTocSetterInterface
-gst_toc_setter_set_toc
-gst_toc_setter_get_toc
-gst_toc_setter_reset
-<SUBSECTION Standard>
-GST_IS_TOC_SETTER
-GST_TOC_SETTER
-GST_TOC_SETTER_GET_IFACE
-GST_TYPE_TOC_SETTER
-<SUBSECTION Private>
-gst_toc_setter_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gsttypefind</FILE>
-<TITLE>GstTypeFind</TITLE>
-GstTypeFind
-GstTypeFindFunction
-GstTypeFindProbability
-gst_type_find_peek
-gst_type_find_suggest
-gst_type_find_suggest_simple
-gst_type_find_get_length
-gst_type_find_register
-<SUBSECTION Standard>
-GST_TYPE_TYPE_FIND_PROBABILITY
-<SUBSECTION Private>
-gst_type_find_probability_get_type
-gst_type_find_get_type
-GST_TYPE_TYPE_FIND
-</SECTION>
-
-
-<SECTION>
-<FILE>gsttypefindfactory</FILE>
-<TITLE>GstTypeFindFactory</TITLE>
-GstTypeFindFactory
-gst_type_find_factory_get_list
-gst_type_find_factory_get_extensions
-gst_type_find_factory_get_caps
-gst_type_find_factory_has_function
-gst_type_find_factory_call_function
-<SUBSECTION Standard>
-GstTypeFindFactoryClass
-GST_TYPE_FIND_FACTORY
-GST_IS_TYPE_FIND_FACTORY
-GST_TYPE_FIND_FACTORY_CLASS
-GST_IS_TYPE_FIND_FACTORY_CLASS
-GST_TYPE_FIND_FACTORY_GET_CLASS
-GST_TYPE_TYPE_FIND_FACTORY
-<SUBSECTION Private>
-gst_type_find_factory_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gsturihandler</FILE>
-<TITLE>GstUriHandler</TITLE>
-GstURIHandler
-GstURIHandlerInterface
-GstURIType
-GstURIError
-gst_uri_error_quark
-GST_URI_TYPE_IS_VALID
-GST_URI_NO_PORT
-gst_uri_protocol_is_valid
-gst_uri_protocol_is_supported
-gst_uri_is_valid
-gst_uri_has_protocol
-gst_uri_get_protocol
-gst_uri_get_location
-gst_uri_construct
-gst_filename_to_uri
-gst_element_make_from_uri
-gst_uri_handler_get_uri_type
-gst_uri_handler_get_protocols
-gst_uri_handler_get_uri
-gst_uri_handler_set_uri
-<SUBSECTION Standard>
-GST_URI_HANDLER
-GST_IS_URI_HANDLER
-GST_URI_HANDLER_GET_INTERFACE
-GST_TYPE_URI_HANDLER
-GST_TYPE_URI_TYPE
-gst_uri_error_get_type
-GST_TYPE_URI_ERROR
-GST_URI_ERROR
-<SUBSECTION Private>
-gst_uri_handler_get_type
-gst_uri_type_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gsturi</FILE>
-<TITLE>GstUri</TITLE>
-GST_URI_CAST
-GST_URI_CONST_CAST
-GstUri
-gst_uri_new
-gst_uri_new_with_base
-gst_uri_from_string
-gst_uri_from_string_with_base
-gst_uri_copy
-gst_uri_equal
-gst_uri_join
-gst_uri_join_strings
-gst_uri_is_writable
-gst_uri_make_writable
-gst_uri_to_string
-gst_uri_ref
-gst_uri_unref
-gst_uri_is_normalized
-gst_uri_normalize
-gst_uri_get_scheme
-gst_uri_set_scheme
-gst_uri_get_userinfo
-gst_uri_set_userinfo
-gst_uri_get_host
-gst_uri_set_host
-gst_uri_get_port
-gst_uri_set_port
-gst_uri_get_path
-gst_uri_set_path
-gst_uri_get_path_string
-gst_uri_set_path_string
-gst_uri_get_path_segments
-gst_uri_set_path_segments
-gst_uri_append_path
-gst_uri_append_path_segment
-gst_uri_get_query_string
-gst_uri_set_query_string
-gst_uri_get_query_table
-gst_uri_set_query_table
-gst_uri_get_query_value
-gst_uri_set_query_value
-gst_uri_remove_query_key
-gst_uri_query_has_key
-gst_uri_get_query_keys
-gst_uri_get_fragment
-gst_uri_set_fragment
-gst_uri_get_media_fragment_table
-<SUBSECTION Standard>
-GST_IS_URI
-GST_TYPE_URI
-GST_URI
-gst_uri_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstutils</FILE>
-<TITLE>GstUtils</TITLE>
-GST_CALL_PARENT
-GST_CALL_PARENT_WITH_DEFAULT
-GST_READ_UINT8
-GST_READ_UINT16_LE
-GST_READ_UINT16_BE
-GST_READ_UINT24_LE
-GST_READ_UINT24_BE
-GST_READ_UINT32_LE
-GST_READ_UINT32_BE
-GST_READ_UINT64_LE
-GST_READ_UINT64_BE
-GST_READ_FLOAT_LE
-GST_READ_FLOAT_BE
-GST_READ_DOUBLE_LE
-GST_READ_DOUBLE_BE
-GST_WRITE_UINT8
-GST_WRITE_UINT16_LE
-GST_WRITE_UINT16_BE
-GST_WRITE_UINT24_LE
-GST_WRITE_UINT24_BE
-GST_WRITE_UINT32_LE
-GST_WRITE_UINT32_BE
-GST_WRITE_UINT64_LE
-GST_WRITE_UINT64_BE
-GST_WRITE_FLOAT_LE
-GST_WRITE_FLOAT_BE
-GST_WRITE_DOUBLE_LE
-GST_WRITE_DOUBLE_BE
-GST_ROUND_UP_2
-GST_ROUND_UP_4
-GST_ROUND_UP_8
-GST_ROUND_UP_16
-GST_ROUND_UP_32
-GST_ROUND_UP_64
-GST_ROUND_UP_128
-GST_ROUND_UP_N
-GST_ROUND_DOWN_2
-GST_ROUND_DOWN_4
-GST_ROUND_DOWN_8
-GST_ROUND_DOWN_16
-GST_ROUND_DOWN_32
-GST_ROUND_DOWN_64
-GST_ROUND_DOWN_128
-GST_ROUND_DOWN_N
-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_SEQNUM_INVALID
-GST_GROUP_ID_INVALID
-
-gst_guint64_to_gdouble
-gst_gdouble_to_guint64
-gst_util_dump_buffer
-gst_util_dump_mem
-gst_util_uint64_scale
-gst_util_uint64_scale_round
-gst_util_uint64_scale_ceil
-gst_util_uint64_scale_int
-gst_util_uint64_scale_int_round
-gst_util_uint64_scale_int_ceil
-gst_util_greatest_common_divisor
-gst_util_greatest_common_divisor_int64
-gst_util_fraction_to_double
-gst_util_double_to_fraction
-gst_util_fraction_multiply
-gst_util_fraction_add
-gst_util_fraction_compare
-gst_util_seqnum_next
-gst_util_seqnum_compare
-gst_util_group_id_next
-gst_util_set_object_arg
-gst_util_set_value_from_string
-gst_util_set_object_array
-gst_util_get_object_array
-gst_util_get_timestamp
-GstSearchMode
-gst_util_array_binary_search
-<SUBSECTION Private>
-GST_HAVE_UNALIGNED_ACCESS
-gst_util_guint64_to_gdouble
-gst_util_gdouble_to_guint64
-GST_TYPE_SEARCH_MODE
-gst_search_mode_get_type
-gst_calculate_linear_regression
-</SECTION>
-
-<SECTION>
-<FILE>gstdatetime</FILE>
-<TITLE>GstDateTime</TITLE>
-GstDateTime
-GST_TYPE_DATE_TIME
-gst_date_time_get_day
-gst_date_time_get_month
-gst_date_time_get_hour
-gst_date_time_get_microsecond
-gst_date_time_get_minute
-gst_date_time_get_time_zone_offset
-gst_date_time_get_second
-gst_date_time_get_year
-gst_date_time_new
-gst_date_time_new_ymd
-gst_date_time_new_ym
-gst_date_time_new_y
-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_date_time_has_day
-gst_date_time_has_month
-gst_date_time_has_second
-gst_date_time_has_time
-gst_date_time_has_year
-
-
-gst_date_time_new_from_iso8601_string
-gst_date_time_to_iso8601_string
-
-gst_date_time_new_from_g_date_time
-gst_date_time_to_g_date_time
-</SECTION>
-
-<SECTION>
-<FILE>gstvalue</FILE>
-<TITLE>GstValue</TITLE>
-
-<SUBSECTION fourcc>
-GST_MAKE_FOURCC
-GST_STR_FOURCC
-GST_FOURCC_FORMAT
-GST_FOURCC_ARGS
-
-<SUBSECTION intrange>
-GST_VALUE_HOLDS_INT_RANGE
-GST_TYPE_INT_RANGE
-gst_value_set_int_range
-gst_value_get_int_range_min
-gst_value_get_int_range_max
-gst_value_set_int_range_step
-gst_value_get_int_range_step
-
-<SUBSECTION bitmask>
-GST_VALUE_HOLDS_BITMASK
-GST_TYPE_BITMASK
-gst_value_set_bitmask
-gst_value_get_bitmask
-
-<SUBSECTION flagset>
-GST_VALUE_HOLDS_FLAG_SET
-GST_TYPE_FLAG_SET
-gst_structure_get_flagset
-gst_value_get_flagset_flags
-gst_value_get_flagset_mask
-gst_value_set_flagset
-GST_FLAG_SET_MASK_EXACT
-
-<SUBSECTION int64range>
-GST_VALUE_HOLDS_INT64_RANGE
-GST_TYPE_INT64_RANGE
-gst_value_set_int64_range
-gst_value_get_int64_range_min
-gst_value_get_int64_range_max
-gst_value_set_int64_range_step
-gst_value_get_int64_range_step
-
-<SUBSECTION doublerange>
-GST_VALUE_HOLDS_DOUBLE_RANGE
-GST_TYPE_DOUBLE_RANGE
-gst_value_set_double_range
-gst_value_get_double_range_min
-gst_value_get_double_range_max
-
-<SUBSECTION valuelist>
-GST_VALUE_HOLDS_LIST
-GST_TYPE_LIST
-GST_VALUE_HOLDS_ARRAY
-GST_TYPE_ARRAY
-gst_value_list_append_value
-gst_value_list_append_and_take_value
-gst_value_list_prepend_value
-gst_value_list_concat
-gst_value_list_merge
-gst_value_list_get_size
-gst_value_list_get_value
-
-<SUBSECTION fraction>
-GST_VALUE_HOLDS_FRACTION
-GST_TYPE_FRACTION
-gst_value_set_fraction
-gst_value_get_fraction_numerator
-gst_value_get_fraction_denominator
-gst_value_fraction_multiply
-gst_value_fraction_subtract
-
-<SUBSECTION fractionrange>
-GST_VALUE_HOLDS_FRACTION_RANGE
-GST_TYPE_FRACTION_RANGE
-gst_value_set_fraction_range
-gst_value_get_fraction_range_min
-gst_value_get_fraction_range_max
-gst_value_set_fraction_range_full
-
-<SUBSECTION datetime>
-GST_VALUE_HOLDS_DATE_TIME
-
-<SUBSECTION caps>
-GST_VALUE_HOLDS_CAPS
-gst_value_set_caps
-gst_value_get_caps
-
-<SUBSECTION capsfeature>
-GST_VALUE_HOLDS_CAPS_FEATURES
-gst_value_set_caps_features
-gst_value_get_caps_features
-
-<SUBSECTION structure>
-GST_VALUE_HOLDS_STRUCTURE
-gst_value_set_structure
-gst_value_get_structure
-
-<SUBSECTION buffer>
-GST_VALUE_HOLDS_BUFFER
-gst_value_get_buffer
-gst_value_set_buffer
-gst_value_take_buffer
-
-<SUBSECTION sample>
-GST_VALUE_HOLDS_SAMPLE
-gst_value_get_sample
-gst_value_set_sample
-gst_value_take_sample
-
-<SUBSECTION>
-GST_VALUE_LESS_THAN
-GST_VALUE_EQUAL
-GST_VALUE_GREATER_THAN
-GST_VALUE_UNORDERED
-
-GstValueCompareFunc
-GstValueSerializeFunc
-GstValueDeserializeFunc
-GstValueTable
-
-gst_value_is_fixed
-gst_value_register
-gst_value_init_and_copy
-gst_value_serialize
-gst_value_deserialize
-gst_value_compare
-gst_value_can_compare
-gst_value_union
-gst_value_can_union
-gst_value_subtract
-gst_value_can_subtract
-gst_value_intersect
-gst_value_can_intersect
-gst_value_is_subset
-gst_value_array_append_value
-gst_value_array_append_and_take_value
-gst_value_array_get_size
-gst_value_array_get_value
-gst_value_array_prepend_value
-gst_value_fixate
-
-gst_flagset_register
-
-<SUBSECTION Standard>
-GST_TYPE_G_THREAD
-<SUBSECTION Private>
-gst_date_get_type
-gst_date_time_get_type
-gst_double_range_get_type
-gst_fraction_get_type
-gst_fraction_range_get_type
-gst_g_thread_get_type
-gst_int_range_get_type
-gst_int64_range_get_type
-gst_value_array_get_type
-gst_value_list_get_type
-gst_bitmask_get_type
-gst_flagset_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstversion</FILE>
-<TITLE>GstVersion</TITLE>
-GST_VERSION_MAJOR
-GST_VERSION_MINOR
-GST_VERSION_MICRO
-GST_VERSION_NANO
-GST_CHECK_VERSION
-</SECTION>
-
-<SECTION>
-<FILE>gstdevice</FILE>
-<TITLE>GstDevice</TITLE>
-
-GstDevice
-GstDeviceClass
-
-gst_device_create_element
-gst_device_get_caps
-gst_device_get_device_class
-gst_device_get_display_name
-gst_device_has_classes
-gst_device_has_classesv
-gst_device_reconfigure_element
-gst_device_get_properties
-
-<SUBSECTION Standard>
-GST_DEVICE
-GST_DEVICE_CAST
-GST_DEVICE_CLASS
-GST_DEVICE_GET_CLASS
-GST_IS_DEVICE
-GST_IS_DEVICE_CLASS
-GST_TYPE_DEVICE
-gst_device_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstdeviceprovider</FILE>
-<TITLE>GstDeviceProvider</TITLE>
-GstDeviceProvider
-GstDeviceProviderClass
-gst_device_provider_can_monitor
-gst_device_provider_class_add_metadata
-gst_device_provider_class_add_static_metadata
-gst_device_provider_class_get_metadata
-gst_device_provider_class_set_metadata
-gst_device_provider_class_set_static_metadata
-gst_device_provider_device_add
-gst_device_provider_device_remove
-gst_device_provider_device_changed
-gst_device_provider_get_bus
-gst_device_provider_get_devices
-gst_device_provider_get_factory
-gst_device_provider_get_metadata
-gst_device_provider_register
-gst_device_provider_start
-gst_device_provider_stop
-
-<SUBSECTION Standard>
-GstDevicePrivate
-GST_DEVICE_PROVIDER
-GST_DEVICE_PROVIDER_CAST
-GST_DEVICE_PROVIDER_CLASS
-GST_DEVICE_PROVIDER_GET_CLASS
-GST_IS_DEVICE_PROVIDER
-GST_IS_DEVICE_PROVIDER_CLASS
-GST_TYPE_DEVICE_PROVIDER
-gst_device_provider_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstdeviceproviderfactory</FILE>
-<TITLE>GstDeviceProviderFactory</TITLE>
-GstDeviceProviderFactory
-GstDeviceProviderFactoryClass
-gst_device_provider_factory_find
-gst_device_provider_factory_get
-gst_device_provider_factory_get_by_name
-gst_device_provider_factory_get_device_provider_type
-gst_device_provider_factory_get_metadata
-gst_device_provider_factory_get_metadata_keys
-gst_device_provider_factory_has_classes
-gst_device_provider_factory_has_classesv
-gst_device_provider_factory_list_get_device_providers
-
-<SUBSECTION Standard>
-GstDeviceProviderPrivate
-GST_DEVICE_PROVIDER_FACTORY
-GST_DEVICE_PROVIDER_FACTORY_CAST
-GST_DEVICE_PROVIDER_FACTORY_CLASS
-GST_TYPE_DEVICE_PROVIDER_FACTORY
-GST_IS_DEVICE_PROVIDER_FACTORY
-GST_IS_DEVICE_PROVIDER_FACTORY_CLASS
-gst_device_provider_factory_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstdevicemonitor</FILE>
-<TITLE>GstDeviceMonitor</TITLE>
-GstDeviceMonitor
-GstDeviceMonitorClass
-gst_device_monitor_new
-gst_device_monitor_get_bus
-gst_device_monitor_add_filter
-gst_device_monitor_remove_filter
-gst_device_monitor_start
-gst_device_monitor_stop
-gst_device_monitor_get_devices
-gst_device_monitor_get_providers
-gst_device_monitor_get_show_all_devices
-gst_device_monitor_set_show_all_devices
-gst_device_provider_get_hidden_providers
-gst_device_provider_hide_provider
-gst_device_provider_unhide_provider
-
-<SUBSECTION Standard>
-GstDeviceMonitorPrivate
-GST_DEVICE_MONITOR
-GST_DEVICE_MONITOR_CAST
-GST_DEVICE_MONITOR_CLASS
-GST_DEVICE_MONITOR_GET_CLASS
-GST_IS_DEVICE_MONITOR
-GST_IS_DEVICE_MONITOR_CLASS
-GST_TYPE_DEVICE_MONITOR
-gst_device_monitor_get_type
-</SECTION>
-
diff --git a/docs/gst/gstreamer.types.in b/docs/gst/gstreamer.types.in
deleted file mode 100644 (file)
index 02895b6..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-% add a _get_type for every GObject whose properties and signals you want
-% documented
-% add the relevant includes to be able to call those _get_type functions
-
-% adding a get_type here will:
-% - change output file name from gstreamer-(whatever).html to (whatever).html
-% - document properties and signals
-
-#include <gst/gst.h>
-#include <gst/gsttracer.h>
-#include <gst/gsttracerrecord.h>
-
-gst_bin_get_type
-gst_buffer_pool_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_object_get_type
-gst_pad_get_type
-gst_pad_template_get_type
-gst_pipeline_get_type
-gst_plugin_feature_get_type
-gst_preset_get_type
-gst_promise_get_type
-gst_registry_get_type
-gst_system_clock_get_type
-gst_tag_setter_get_type
-gst_task_get_type
-gst_tracer_get_type
-gst_tracer_factory_get_type
-gst_tracer_record_get_type
-gst_type_find_factory_get_type
-gst_uri_handler_get_type
-
-gst_buffer_get_type
-gst_buffer_list_get_type
-gst_caps_get_type
-gst_context_get_type
-gst_event_get_type
-gst_memory_get_type
-gst_message_get_type
-gst_query_get_type
-gst_sample_get_type
-gst_tag_list_get_type
-gst_toc_get_type
-gst_toc_entry_get_type
diff --git a/docs/gst/index.md b/docs/gst/index.md
new file mode 100644 (file)
index 0000000..5d0b7e9
--- /dev/null
@@ -0,0 +1,6 @@
+# Core Library
+
+libgstreamer-{{ gst_api_version.md }}.so provides all the core GStreamer
+services, including initialization, plugin management and types, as well
+as the object hierarchy that defines elements and bins, along with some
+more specialized elements.
diff --git a/docs/gst/meson.build b/docs/gst/meson.build
deleted file mode 100644 (file)
index d412bd3..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-types = configure_file(input : 'gstreamer.types.in',
-  output : 'gstreamer.types',
-  copy: true)
-
-gnome.gtkdoc('gstreamer',
-  main_sgml : 'gstreamer-docs.sgml',
-  src_dir : '@0@/../../gst'.format(meson.current_source_dir()),
-  scan_args : ['--deprecated-guards=GST_DISABLE_DEPRECATED',
-            '--ignore-decorators=GST_API',
-            '--ignore-headers=gettext.h glib-compat-private.h glib-compat.h gst-i18n-app.h gst-i18n-lib.h gst_private.h gstelementdetails.h gstmacros.h grammar.tab.h grammar.tab.pre.h math-compat.h types.h'
-            ],
-  scanobjs_args : ['--type-init-func="gst_init(NULL,NULL)"'],
-  gobject_typesfile : types,
-  dependencies : [gst_dep],
-  content_files: ['building.xml', 'running.xml', version_entities],
-  install : true)
diff --git a/docs/gst/overview.md b/docs/gst/overview.md
new file mode 100644 (file)
index 0000000..5db57da
--- /dev/null
@@ -0,0 +1,14 @@
+---
+title: GStreamer Overview
+short-description: A simple overview of the GStreamer framework
+...
+
+# GStreamer Overview
+
+GStreamer is a streaming media framework. It uses graphs of elements which operate on data. The functionality to process media is provided by plug-ins which provide features like elements, typefinding, and so on. This allows new functionality to be added simply by installing new plug-ins.
+
+GStreamer is cross-platform and works on most UNIX-like platforms as well as Windows. It is released under the GNU Library General Public License (GNU LGPL).
+
+Relation between gstreamer core objects:
+
+![GStreamer universe](images/gst-universe.svg)
\ No newline at end of file
diff --git a/docs/gst/running.md b/docs/gst/running.md
new file mode 100644 (file)
index 0000000..df5f4eb
--- /dev/null
@@ -0,0 +1,331 @@
+---
+title: Running GStreamer Applications
+short-description: How to run and debug your GStreamer application
+...
+
+# Running and debugging GStreamer Applications
+
+## Environment variables
+
+GStreamer inspects a few of environment variables in addition to
+standard variables like LANG, PATH or HOME.
+
+**`GST_PLUGIN_SYSTEM_PATH`, `GST_PLUGIN_SYSTEM_PATH_1_0`.**
+
+This environment variable can be set to a colon-separated list of paths
+(or semicolon-separated list on Windows). If this variable is not set,
+GStreamer will fill in this list for you with
+
+-   plug-ins in the user's home directory, or rather the user's "data
+    home" directory according to the xdg base dir specification.
+    Usually this will be a directory called `plugins` inside the
+    `.local/share/gstreamer-GST_API_VERSION` directory in the user's
+    home directory by default, though this search path may change if the
+    XDG_DATA_HOME environment variable is set.
+
+-   plug-ins installed system-wide. On this system, they are stored in
+    ``.
+
+GStreamer will scan these paths for GStreamer plug-ins. These plug-ins
+will be loaded after the plug-ins in the `GST_PLUGIN_PATH` variable
+below. The paths are scanned in the given order. This allows a user to
+override system-installed plug-ins with his own versions.
+
+The `GST_PLUGIN_SYSTEM_PATH_1_0` variant is useful if both the old
+GStreamer 0.10 version and the new GStreamer 1.0 version need to be
+pointed to new plugin paths. The latter will use the _1_0 variant over
+the non-versioned one if it is set.
+
+Setting this variable to an empty string will cause GStreamer not to
+scan any system paths at all for plug-ins. This can be useful if you're
+running uninstalled (for development purposes) or while running
+testsuites.
+
+**`GST_PLUGIN_PATH`, `GST_PLUGIN_PATH_1_0`.**
+
+This environment variable can be set to a colon-separated list of paths
+(or a semicolon-separated list on Windows). GStreamer will scan these
+paths for GStreamer plug-ins. These plug-ins will be loaded in addition
+to, and before, the plug-ins in the system paths.
+
+The GST_PLUGIN_PATH_1_0 variant is useful if both the old GStreamer
+0.10 version and the new GStreamer 1.0 version need to be pointed to new
+plugin paths. The latter will use the `_1_0` variant over the
+non-versioned one if it is set.
+
+**`GST_DEBUG`.**
+
+If GStreamer has been configured with `--enable-gst-debug=yes`, this
+variable can be set to a list of debug options, which cause GStreamer to
+print out different types of debugging information to stderr.
+
+The variable takes a comma-separated list of `category_name:level`
+pairs to set specific levels for the individual categories. The level
+value ranges from 0 (nothing) to 9 (MEMDUMP).
+
+1 - `ERROR`
+
+:   Logs all fatal errors. These are errors that do not allow the core
+    or elements to perform the requested action. The application can
+    still recover if programmed to handle the conditions that triggered
+    the error.
+
+2 - `WARNING`
+
+:   Logs all warnings. Typically these are non-fatal, but user-visible
+    problems are expected to happen.
+
+3 - `FIXME`
+
+:   Logs all fixme messages. Fixme messages are messages that indicate
+    that something in the executed code path is not fully implemented or
+    handled yet. The purpose of this message is to make it easier to
+    spot incomplete/unfinished pieces of code when reading the debug
+    log.
+
+4 - `INFO`
+
+:   Logs all informational messages. These are typically used for events
+    in the system that only happen once, or are important and rare
+    enough to be logged at this level.
+
+5 - `DEBUG`
+
+:   Logs all debug messages. These are general debug messages for events
+    that happen only a limited number of times during an object's
+    lifetime; these include setup, teardown, change of parameters, ...
+
+6 - `LOG`
+
+:   Logs all log messages. These are messages for events that happen
+    repeatedly during an object's lifetime; these include streaming and
+    steady-state conditions.
+
+7 - `TRACE`
+
+:   Logs all trace messages. These messages for events that happen
+    repeatedly during an object's lifetime such as the ref/unref
+    cycles.
+
+9 - `MEMDUMP`
+
+:   Log all memory dump messages. Memory dump messages are used to log
+    (small) chunks of data as memory dumps in the log. They will be
+    displayed as hexdump with ASCII characters.
+
+The category_name can contain "`*"` as a wildcard.
+
+For example, setting `GST_DEBUG` to `GST_AUTOPLUG:6,GST_ELEMENT_*:4`,
+will cause the `GST_AUTOPLUG` category to be logged at full `LOG` level,
+while all categories starting with `GST_ELEMENT_` will be logged at
+`INFO` level.
+
+To get all possible debug output, set `GST_DEBUG` to `*:9`. For debugging
+purposes a `*:6` debug log is usually the most useful, as it contains
+all important information, but hides a lot of noise such as refs/unrefs.
+For bug reporting purposes, a `*:6` log is also what will be requested
+usually. It's often also worth running with `*:3` to see if there are
+any non-fatal errors or warnings that might be related to the problem at
+hand.
+
+Since GStreamer 1.2 it is also possible to specify debug levels by name,
+e.g. `GST_DEBUG=*:WARNING,*audio*:LOG`
+
+**`GST_DEBUG_NO_COLOR`.**
+
+Set this environment variable to any value ("1" typically) to switch
+off colouring in `GST_DEBUG` output. This has the same effect as
+specifying the `--gst-debug-no-color` or `--gst-debug-color-mode`=off
+command line option to well-behaved GStreamer applications (ie. those
+that pass command-line options correctly to GStreamer). This is
+particularly useful to reduce the size of debug output and also allows
+for the output to be compressed much better than with colours turned on.
+
+Has the same effect as setting `GST_DEBUG_COLOR_MODE` environment
+variable to "off".
+
+**`GST_DEBUG_COLOR_MODE`.**
+
+Set this environment variable to change log colouring in `GST_DEBUG` output.
+Possible values:
+
+`on`: Enables debug log output coloring. Uses default coloring method for
+current platform. This is the default.
+
+`off`: Disables debug log output coloring. This has the same effect as
+specifying the `--gst-debug-color-mode=off` command line option to well-behaved
+GStreamer applications (ie. those that pass command-line options correctly to
+GStreamer). This is particularly useful to reduce the size of debug output and
+also allows for the output to be compressed much better than with colours turned
+on. Has the same effect as setting `GST_DEBUG_NO_COLOR` environment variable to
+any value.
+
+`auto`: Same as `on`.
+
+`disable`: Same as `off`.
+
+`unix`: Enables debug log output coloring and forces the use of UNIX termial
+codes for coloring, even if this method is not normally used on current
+platform. This has the same effect as specifying the
+`--gst-debug-color-mode=unix` command line option to well-behaved GStreamer
+applications (ie. those that pass command-line options correctly to GStreamer).
+This is particularly useful to dump debug output into a file on non-UNIX
+platforms to be sent to developers who have viewers that support UNIX terminal
+codes.
+
+**`GST_DEBUG_OPTIONS`.**
+
+This environment variable can be used to tweak the behaviour of the
+debugging system. Currently the only options supported are
+"pretty-tags" and "full-tags". In "pretty-tags" mode (the
+default), taglists in the debug log will be serialized so that only the
+first few and last few bytes of a buffer-type tag will be serialized
+into the log, to avoid dumping hundreds of lines of useless output into
+the log in case of large image tags and the like.
+
+**`GST_DEBUG_DUMP_DOT_DIR`.**
+
+Set this environment variable to a path to turn on all
+`GST_DEBUG_BIN_TO_DOT_FILE` or `GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS` calls and
+have the dot files in that location.
+
+This will only work if the application in question makes these calls in
+strategic places (like when the pipeline state changes or an error
+occurs). `gst-launch-1,0` is one such application.
+
+When `gst-launch-1.0` changes state through NULL to PLAYING
+and back to NULL, a dot file is generated on each state change. To have
+`gst-launch-1.0` write a snapshot of the pipeline state,
+send a SIGHUP to the `gst-launch-1.0` process.
+
+These .dot files can then be turned into images using the 'dot'
+utility from the graphviz set of tools, like this:
+`dot foo.dot -Tsvg -o foo.svg` or `dot foo.dot -Tpng -o foo.png` or
+`dot foo.dot -Tjpg -o foo.jpg`.
+
+There is also a utility called `xdot` which allows you to view the dot
+file directly without converting it first.
+
+**`GST_REGISTRY`, `GST_REGISTRY_1_0`.**
+
+Set this environment variable to make GStreamer use a different file for
+the plugin cache / registry than the default one. This is useful when
+operating in a separate environment which should not affect the default
+cache in the user's home directory.
+
+**`GST_REGISTRY_FORK`.**
+
+Set this environment variable to "no" to prevent GStreamer from
+forking on startup in order to update the plugin registry. This is
+useful for debugging purposes, but should not be used under normal
+circumstances, since it means that plugins may be loaded into memory
+even if they are not needed by the application.
+
+**`GST_REGISTRY_UPDATE`.**
+
+Set this environment variable to "no" to prevent GStreamer from
+updating the plugin registry. This is useful for embedded device which
+is not updating the plugins frequently, it will save time when doing
+`gst_init()`.
+
+**`GST_TRACE`.**
+
+Enable memory allocation tracing. Most GStreamer objects have support
+for tracing the number of unfreed objects and their memory pointers.
+
+The variable takes a comma-separated list of tracing options to enable.
+
+live
+
+:   Counts all live objects and dumps an overview of the number of
+    unfreed objects at program exit.
+
+mem-live
+
+:   Keep track of the unfreed memory pointers and dump an overview of
+    all unfreed memory at program exit. Together with a level 9 debug
+    log this can be used to follow the lifecycle of leaked objects in
+    order to track down where they are leaked. This can be useful for
+    debugging memory leaks in situations where tools such as valgrind
+    are not available, or not an option.
+
+Use `all` to enable all tracing flags.
+
+**`GST_DEBUG_FILE`.**
+
+Set this variable to a file path to redirect all GStreamer debug
+messages to this file. If left unset, debug messages with be output unto
+the standard error.
+
+**`ORC_CODE`.**
+
+Useful Orc environment variable. Set `ORC_CODE=debug` to enable debuggers
+such as gdb to create useful backtraces from Orc-generated code. Set
+`ORC_CODE=backup` or `ORC_CODE=emulate` if you suspect Orc's SIMD code
+generator is producing incorrect code (Quite a few important GStreamer
+plugins like videotestsrc, audioconvert or audioresample use Orc). One
+can also combine flags like `ORC_CODE=backup,debug`.
+
+**`G_DEBUG`.**
+
+Useful GLib environment variable. Set `G_DEBUG=fatal_warnings` to make
+GStreamer programs abort when a critical warning such as an assertion
+failure occurs. This is useful if you want to find out which part of the
+code caused that warning to be triggered and under what circumstances.
+Simply set `G_DEBUG` as mentioned above and run the program in gdb (or
+let it core dump). Then get a stack trace in the usual way.
+
+**`G_SLICE`.**
+
+Useful GLib environment variable. Set `G_SLICE=always-malloc` when
+running GStreamer programs in valgrind, or debugging memory leaks with
+other tools. See the GLib API reference for more details.
+
+**`GST_TAG_ENCODING`.**
+
+Try this character encoding first for tag-related strings where the
+encoding is not defined and which are not UTF-8 already. By default the
+current locale will be tried (if not UTF-8).
+
+**`GST_TAG_ID3_ENCODING`.**
+
+Try this character encoding first for ID3 tag-related strings where the
+encoding is not defined and which are not UTF-8 already. By default the
+current locale will be tried (if not UTF-8).
+
+**`GST_TAG_ID3V1_ENCODING`.**
+
+Try this character encoding first for ID3v1 tag-related strings where
+the encoding does not look like UTF-8.
+
+**`GST_GL_WINDOW`.**
+
+Influences the window system to use by the GStreamer OpenGL library.
+Common values are 'x11', 'wayland', 'win32' or 'cocoa'.
+
+**`GST_GL_PLATFORM`.**
+
+Influences the OpenGL platform to use by the GStreamer OpenGL library.
+Common values are 'egl', 'glx', 'wgl' or 'cgl'.
+
+**`GST_GL_API`.**
+
+Influences the OpenGL API requested by the OpenGL platform. Common
+values are 'opengl' or 'gles2'.
+
+**`GST_PLUGIN_FEATURE_RANK`. (Since: 1.18)**
+
+This environment variable can be used to adjust rank of each plugin feature.
+
+The variable takes a comma-separated list of `plugin_feature:rank`
+pairs to set specific ranks for the individual plugin features.
+The rank can be an arbitrary numerical value or one of pre-defined rank values
+from `NONE`(0) to `PRIMARY`(256) in case-insensitive manner.
+In addition to the pre-defined rank values, `MAX` is an acceptable value to set
+higher rank than the rank of other existing plugin features.
+
+Example: `GST_PLUGIN_FEATURE_RANK=foo:PRIMARY,bar:primary,foobar:128`
+
+As a result of the above example,
+the `foo` and` bar` plugin feature rank values are `PRIMARY`(256)
+and `SECONDARY`(128) rank value will be assigned to `foobar`.
diff --git a/docs/gst/running.xml b/docs/gst/running.xml
deleted file mode 100644 (file)
index 9e4b3ef..0000000
+++ /dev/null
@@ -1,559 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
-               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
-<!ENTITY % version-entities SYSTEM "version.entities">
-%version-entities;
-<!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
-]>
-<refentry id="gst-running" revision="08 Oct 2005">
-<refmeta>
-<refentrytitle>Running GStreamer Applications</refentrytitle>
-<manvolnum>3</manvolnum>
-<refmiscinfo>GStreamer Core</refmiscinfo>
-</refmeta>
-
-<refnamediv>
-<refname>Running GStreamer Applications</refname>
-<refpurpose>
-How to run and debug your GStreamer application
-</refpurpose>
-</refnamediv>
-
-<refsect1>
-<title>Running and debugging GStreamer Applications</title>
-
-<refsect2>
-<title>Environment variables</title>
-
-<para> 
-GStreamer inspects a few of environment variables in addition to standard
-variables like <envar>LANG</envar>, <envar>PATH</envar> or <envar>HOME</envar>. 
-</para>
-
-<formalpara id="GST_PLUGIN_SYSTEM_PATH">
-  <title><envar>GST_PLUGIN_SYSTEM_PATH</envar>,
-         <envar>GST_PLUGIN_SYSTEM_PATH_1_0</envar></title>
-
-  <para>
-
-This environment variable can be set to a colon-separated list of paths (or
-semicolon-separated list on Windows).
-If this variable is not set, GStreamer will fill in this list for you
-with
-<itemizedlist>
-  <listitem>
-    <para>
-plug-ins in the user's home directory, or rather the user's "data home"
-directory according to the xdg base dir specification. Usually this will be
-a directory called
-<filename>plugins</filename> inside the
-<filename>.local/share/gstreamer-&GST_API_VERSION;</filename> directory in
-the user's home directory by default, though this search path may change if
-the XDG_DATA_HOME environment variable is set.
-    </para>
-  </listitem>
-  <listitem>
-    <para>
-plug-ins installed system-wide.  On this system, they are stored in
-<filename>&GST_PLUGINS_DIR;</filename>.
-    </para>
-
-</listitem>
-</itemizedlist>
-   </para>
-
-    <para>
-GStreamer will scan these paths for GStreamer plug-ins.  These plug-ins will
-be loaded after the plug-ins in the GST_PLUGIN_PATH variable below.
-
-The paths are scanned in the given order.  This allows a user to override
-system-installed plug-ins with his own versions.
-   </para>
-  <para>
-The GST_PLUGIN_SYSTEM_PATH_1_0 variant is useful if both the old GStreamer 0.10
-version and the new GStreamer 1.0 version need to be pointed to new plugin
-paths. The latter will use the _1_0 variant over the non-versioned one if
-it is set.
-  </para>
-
-    <para>
-Setting this variable to an empty string will cause GStreamer not to scan any
-system paths at all for plug-ins.  This can be useful if you're running
-uninstalled (for development purposes) or while running testsuites.
-   </para>
-
-</formalpara>
-
-<formalpara id="GST_PLUGIN_PATH">
-  <title><envar>GST_PLUGIN_PATH</envar>, <envar>GST_PLUGIN_PATH_1_0</envar></title>
-
-  <para>
-This environment variable can be set to a colon-separated list of paths (or a
-semicolon-separated list on Windows).
-GStreamer will scan these paths for GStreamer plug-ins.  These plug-ins will
-be loaded in addition to, and before, the plug-ins in the system paths.
-  </para>
-  <para>
-The GST_PLUGIN_PATH_1_0 variant is useful if both the old GStreamer 0.10
-version and the new GStreamer 1.0 version need to be pointed to new plugin
-paths. The latter will use the _1_0 variant over the non-versioned one if
-it is set.
-  </para>
-</formalpara>
-
-<formalpara id="GST_DEBUG">
-  <title><envar>GST_DEBUG</envar></title>
-
-  <para>
-If GStreamer has been configured with <option>--enable-gst-debug=yes</option>,
-this variable can be set to a list of debug options, which cause GStreamer
-to print out different types of debugging information to stderr.
-  </para>
-  <para>
-The variable takes a comma-separated list of "category_name:level" pairs
-to set specific levels for the individual categories.
-The level value ranges from 0 (nothing) to 9 (MEMDUMP).
-    <variablelist>
-
-      <varlistentry>
-        <term>1 - <option>ERROR</option></term>
-        <listitem>
-<para>
-Logs all fatal errors.  These are errors that do not allow the core or elements
-to perform the requested action.  The application can still recover if
-programmed to handle the conditions that triggered the error.
-</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>2 - <option>WARNING</option></term>
-        <listitem>
-<para>
-Logs all warnings.  Typically these are non-fatal, but user-visible problems
-are expected to happen.
-</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>3 - <option>FIXME</option></term>
-        <listitem>
-<para>
-Logs all fixme messages. Fixme messages are messages that indicate that something
-in the executed code path is not fully implemented or handled yet.  The purpose
-of this message is to make it easier to spot incomplete/unfinished pieces of
-code when reading the debug log.
-</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>4 - <option>INFO</option></term>
-        <listitem>
-<para>
-Logs all informational messages.  These are typically used for events in
-the system that only happen once, or are important and rare enough to be
-logged at this level.
-</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>5 - <option>DEBUG</option></term>
-        <listitem>
-<para>
-Logs all debug messages.  These are general debug messages for events
-that happen only a limited number of times during an object's lifetime;
-these include setup, teardown, change of parameters, ...
-</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>6 - <option>LOG</option></term>
-        <listitem>
-<para>
-Logs all log messages.  These are messages for events
-that happen repeatedly during an object's lifetime;
-these include streaming and steady-state conditions.
-</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>7 - <option>TRACE</option></term>
-        <listitem>
-<para>
-Logs all trace messages.  These messages for events
-that happen repeatedly during an object's lifetime such as the
-ref/unref cycles.
-</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>9 - <option>MEMDUMP</option></term>
-        <listitem>
-<para>
-Log all memory dump messages. Memory dump messages are used to log
-(small) chunks of data as memory dumps in the log. They will be displayed
-as hexdump with ASCII characters.
-</para>
-        </listitem>
-      </varlistentry>
-    </variablelist>
-
- The category_name can contain "<option>*"</option> as a wildcard.
-  </para>
-
-  <para>
-For example, setting <envar>GST_DEBUG</envar> to
-<option>GST_AUTOPLUG:6,GST_ELEMENT_*:4</option>, will cause the
-<option>GST_AUTOPLUG</option> category to be logged at full
-<option>LOG</option> level, while all categories starting with
-<option>GST_ELEMENT_</option> will be logged at <option>INFO</option> level.
-  </para>
-
-  <para>
-To get all possible debug output, set
-<envar>GST_DEBUG</envar>
-to <option>*:9</option>. For debugging purposes a <option>*:6</option> debug
-log is usually the most useful, as it contains all important information, but
-hides a lot of noise such as refs/unrefs. For bug reporting purposes, a
-<option>*:6</option> log is also what will be requested usually. It's often
-also worth running with <option>*:3</option> to see if there are any
-non-fatal errors or warnings that might be related to the problem at hand.
-  </para>
-
-  <para>
-Since GStreamer 1.2 it is also possible to specify debug levels by name,
-e.g. GST_DEBUG=*:WARNING,*audio*:LOG
-  </para>
-
-</formalpara>
-
-<formalpara id="GST_DEBUG_NO_COLOR">
-  <title><envar>GST_DEBUG_NO_COLOR</envar></title>
-
-  <para>
-Set this environment variable to any value ("1" typically) to switch off
-colouring in GST_DEBUG output. This has the same effect as specifying the
-<option>--gst-debug-no-color</option> or
-<option>--gst-debug-color-mode</option>=off command line option to
-well-behaved GStreamer applications (ie. those that pass command-line
-options correctly to GStreamer).
-This is particularly useful to reduce the size of debug output and also allows
-for the output to be compressed much better than with colours turned on.
-  </para>
-  <para>
-Has the same effect as setting GST_DEBUG_COLOR_MODE environment variable to
-"off".
-  </para>
-
-</formalpara>
-
-<formalpara id="GST_DEBUG_COLOR_MODE">
-  <title><envar>GST_DEBUG_COLOR_MODE</envar></title>
-
-  <para>
-Set this environment variable to change log colouring in GST_DEBUG output.
-Possible values:
-    <variablelist>
-
-      <varlistentry>
-        <term><option>on</option></term>
-        <listitem>
-          <para>
-Enables debug log output coloring. Uses default coloring method for current
-platform. This is the default.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>off</option></term>
-        <listitem>
-          <para>
-Disables debug log output coloring. This has the same effect as specifying the
-<option>--gst-debug-color-mode</option>=off command line option to
-well-behaved GStreamer applications (ie. those that pass command-line
-options correctly to GStreamer).
-This is particularly useful to reduce the size of debug output and also allows
-for the output to be compressed much better than with colours turned on.
-          </para>
-          <para>
-Has the same effect as setting GST_DEBUG_NO_COLOR environment variable to
-any value.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>auto</option></term>
-        <listitem>
-          <para>
-Same as <option>on</option>.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>disable</option></term>
-        <listitem>
-          <para>
-Same as <option>off</option>.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>unix</option></term>
-        <listitem>
-          <para>
-Enables debug log output coloring and forces the use of UNIX termial codes
-for coloring, even if this method is not normally used on current platform.
-This has the same effect as specifying the
-<option>--gst-debug-color-mode</option>=unix command line option to
-well-behaved GStreamer applications (ie. those that pass command-line options
-correctly to GStreamer).
-This is particularly useful to dump debug output into a file on non-UNIX
-platforms to be sent to developers who have viewers that support UNIX terminal
-codes.
-          </para>
-        </listitem>
-      </varlistentry>
-
-    </variablelist>
-  </para>
-
-</formalpara>
-
-<formalpara id="GST_DEBUG_OPTIONS">
-  <title><envar>GST_DEBUG_OPTIONS</envar></title>
-
-  <para>
-This environment variable can be used to tweak the behaviour of the debugging
-system. Currently the only options supported are "pretty-tags" and "full-tags".
-In "pretty-tags" mode (the default), taglists in the debug log will be
-serialized so that only the first few and last few bytes of a buffer-type tag
-will be serialized into the log, to avoid dumping hundreds of lines of useless
-output into the log in case of large image tags and the like.
-  </para>
-
-</formalpara>
-
-<formalpara id="GST_DEBUG_DUMP_DOT_DIR">
-  <title><envar>GST_DEBUG_DUMP_DOT_DIR</envar></title>
-
-  <para>
-Set this environment variable to a path to turn on all
-#GST_DEBUG_BIN_TO_DOT_FILE or #GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS calls
-and have the dot files in that location.
-  </para>
-  <para>
-This will only work if the application in question makes these calls in
-strategic places (like when the pipeline state changes or an error occurs).
-gst-launch-&GST_API_VERSION; is one such application.
-  </para>
-  <para>
-When gst-launch-&GST_API_VERSION; changes state through NULL to PLAYING
-and back to NULL, a dot file is generated on each state change. To have
-gst-launch-&GST_API_VERSION; write a snapshot of the pipeline state, send
-a SIGHUP to the gst-launch-&GST_API_VERSION; process.
-  </para>
-  <para>
-These .dot files can then be turned into images using the 'dot' utility
-from the graphviz set of tools, like this:
-  <command>dot foo.dot -Tsvg -o foo.svg</command> or
-  <command>dot foo.dot -Tpng -o foo.png</command> or
-  <command>dot foo.dot -Tjpg -o foo.jpg</command>.
-  </para>
-  <para>
-There is also a utility called <command>xdot</command> which allows you to
-view the dot file directly without converting it first.
-  </para>
-
-
-</formalpara>
-
-<formalpara id="GST_REGISTRY">
-  <title><envar>GST_REGISTRY</envar>, <envar>GST_REGISTRY_1_0</envar></title>
-
-  <para>
-Set this environment variable to make GStreamer use a different file for the
-plugin cache / registry than the default one. This is useful when operating
-in a separate environment which should not affect the default cache in the
-user's home directory.
-  </para>
-
-</formalpara>
-
-<formalpara id="GST_REGISTRY_FORK">
-  <title><envar>GST_REGISTRY_FORK</envar></title>
-
-  <para>
-Set this environment variable to "no" to prevent GStreamer from forking on
-startup in order to update the plugin registry. This is useful for debugging
-purposes, but should not be used under normal circumstances, since it means
-that plugins may be loaded into memory even if they are not needed by the
-application.
-  </para>
-
-</formalpara>
-
-<formalpara id="GST_REGISTRY_UPDATE">
-  <title><envar>GST_REGISTRY_UPDATE</envar></title>
-
-  <para>
-Set this environment variable to "no" to prevent GStreamer from updating the
-plugin registry. This is useful for embedded device which is not updating the
-plugins frequently, it will save time when doing gst_init().
-  </para>
-
-</formalpara>
-
-<formalpara id="GST_TRACE">
-  <title><envar>GST_TRACE</envar></title>
-
-  <para>
-    Enable memory allocation tracing. Most GStreamer objects have support for
-    tracing the number of unfreed objects and their memory pointers.
-  </para>
-  <para>
-The variable takes a comma-separated list of tracing options to enable.
-    <variablelist>
-
-      <varlistentry>
-        <term>live</term>
-        <listitem>
-<para>
-  Counts all live objects and dumps an overview of the number of unfreed
-  objects at program exit.
-</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>mem-live</term>
-        <listitem>
-<para>
-  Keep track of the unfreed memory pointers and dump an overview of all unfreed
-  memory at program exit. Together with a level 9 debug log this can be used to
-  follow the lifecycle of leaked objects in order to track down where they are
-  leaked. This can be useful for debugging memory leaks in situations where
-  tools such as valgrind are not available, or not an option.
-</para>
-        </listitem>
-      </varlistentry>
-    </variablelist>
-
- Use <option>all</option> to enable all tracing flags.
-  </para>
-</formalpara>
-
-<formalpara id="GST_DEBUG_FILE">
-  <title><envar>GST_DEBUG_FILE</envar></title>
-
-  <para>
-  Set this variable to a file path to redirect all GStreamer debug
-  messages to this file. If left unset, debug messages with be output
-  unto the standard error.
-  </para>
-
-</formalpara>
-
-<formalpara id="ORC_CODE">
-  <title><envar>ORC_CODE</envar></title>
-
-  <para>
-Useful Orc environment variable. Set ORC_CODE=debug to enable debuggers
-such as gdb to create useful backtraces from Orc-generated code.  Set
-ORC_CODE=backup or ORC_CODE=emulate if you suspect Orc's SIMD code
-generator is producing incorrect code (Quite a few important
-GStreamer plugins like videotestsrc, audioconvert or audioresample use Orc).
-One can also combine flags like ORC_CODE=backup,debug.
-  </para>
-
-</formalpara>
-
-<formalpara id="G_DEBUG">
-  <title><envar>G_DEBUG</envar></title>
-
-  <para>
-Useful GLib environment variable. Set G_DEBUG=fatal_warnings to make
-GStreamer programs abort when a critical warning such as an assertion failure
-occurs. This is useful if you want to find out which part of the code caused
-that warning to be triggered and under what circumstances. Simply set G_DEBUG
-as mentioned above and run the program in gdb (or let it core dump). Then get
-a stack trace in the usual way.
-  </para>
-
-</formalpara>
-
-<formalpara id="G_SLICE">
-  <title><envar>G_SLICE</envar></title>
-
-  <para>
-Useful GLib environment variable. Set G_SLICE=always-malloc when running
-GStreamer programs in valgrind, or debugging memory leaks with other tools.
-See the GLib API reference for more details.
-  </para>
-
-</formalpara>
-
-<formalpara id="GST_TAG_ENCODING">
-  <title><envar>GST_TAG_ENCODING</envar></title>
-  <para>
-Try this character encoding first for tag-related strings where the encoding
-is not defined and which are not UTF-8 already. By default the current locale
-will be tried (if not UTF-8).
-  </para>
-</formalpara>
-
-<formalpara id="GST_TAG_ID3_ENCODING">
-  <title><envar>GST_TAG_ID3_ENCODING</envar></title>
-  <para>
-Try this character encoding first for ID3 tag-related strings where the
-encoding is not defined and which are not UTF-8 already. By default the current
-locale will be tried (if not UTF-8).
-  </para>
-</formalpara>
-
-<formalpara id="GST_TAG_ID3V1_ENCODING">
-  <title><envar>GST_TAG_ID3V1_ENCODING</envar></title>
-  <para>
-Try this character encoding first for ID3v1 tag-related strings where the
-encoding does not look like UTF-8.
-  </para>
-</formalpara>
-
-<formalpara id="GST_GL_WINDOW">
-  <title><envar>GST_GL_WINDOW</envar></title>
-  <para>
-Influences the window system to use by the GStreamer OpenGL library.
-Common values are 'x11', 'wayland', 'win32' or 'cocoa'.
-  </para>
-</formalpara>
-
-<formalpara id="GST_GL_PLATFORM">
-  <title><envar>GST_GL_PLATFORM</envar></title>
-  <para>
-Influences the OpenGL platform to use by the GStreamer OpenGL library.
-Common values are 'egl', 'glx', 'wgl' or 'cgl'.
-  </para>
-</formalpara>
-
-<formalpara id="GST_GL_API">
-  <title><envar>GST_GL_API</envar></title>
-  <para>
-Influences the OpenGL API requested by the OpenGL platform.
-Common values are 'opengl' or 'gles2'.
-  </para>
-</formalpara>
-
-</refsect2>
-
-</refsect1>
-
-</refentry>
diff --git a/docs/gst/sitemap.txt b/docs/gst/sitemap.txt
new file mode 100644 (file)
index 0000000..39558a3
--- /dev/null
@@ -0,0 +1,3 @@
+gi-index
+       running.md
+       gst.h
diff --git a/docs/images/gdp-header.svg b/docs/images/gdp-header.svg
deleted file mode 100644 (file)
index 9b88231..0000000
+++ /dev/null
@@ -1,906 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://web.resource.org/cc/"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="640px"
-   height="480px"
-   id="svg1307"
-   sodipodi:version="0.32"
-   inkscape:version="0.43"
-   sodipodi:docbase="/home/thomas"
-   sodipodi:docname="gdp.svg">
-  <defs
-     id="defs1309" />
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="1"
-     inkscape:cx="262.80469"
-     inkscape:cy="202.78641"
-     inkscape:current-layer="layer1"
-     inkscape:document-units="px"
-     showgrid="true"
-     showguides="false"
-     inkscape:grid-points="true"
-     fill="#eeeeec"
-     inkscape:window-width="1024"
-     inkscape:window-height="697"
-     inkscape:window-x="0"
-     inkscape:window-y="25" />
-  <metadata
-     id="metadata1312">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     id="layer1"
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer">
-    <g
-       id="g4859">
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094246e-15"
-         y="1"
-         x="1"
-         height="58.000019"
-         width="158"
-         id="rect3104"
-         style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094246e-15"
-         y="0"
-         x="10"
-         height="20"
-         width="80"
-         id="rect3979"
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <text
-         sodipodi:linespacing="100%"
-         id="text4855"
-         y="14.473633"
-         x="8.8222656"
-         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         xml:space="preserve"><tspan
-           y="14.473633"
-           x="8.8222656"
-           id="tspan4857"
-           sodipodi:role="line">Version</tspan></text>
-    </g>
-    <g
-       id="g4865"
-       transform="translate(160,0)">
-      <rect
-         style="opacity:1;color:#000000;fill:#edd400;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000048;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect4867"
-         width="78.000015"
-         height="58.000019"
-         x="1"
-         y="1"
-         rx="2.109425e-15"
-         ry="2.1094244e-15" />
-      <rect
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect4869"
-         width="80"
-         height="20"
-         x="10"
-         y="0"
-         rx="2.1094246e-15"
-         ry="2.1094244e-15" />
-      <text
-         xml:space="preserve"
-         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         x="8.8222656"
-         y="14.473633"
-         id="text4871"
-         sodipodi:linespacing="100%"><tspan
-           sodipodi:role="line"
-           id="tspan4873"
-           x="8.8222656"
-           y="14.473633">Flags</tspan></text>
-    </g>
-    <g
-       transform="translate(240,0)"
-       id="g4885">
-      <rect
-         ry="2.1094244e-15"
-         rx="2.109425e-15"
-         y="1"
-         x="1"
-         height="58.000019"
-         width="78.000015"
-         id="rect4887"
-         style="opacity:1;color:#000000;fill:#888a85;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000048;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094246e-15"
-         y="0"
-         x="10"
-         height="20"
-         width="80"
-         id="rect4889"
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-    </g>
-    <g
-       id="g4905"
-       transform="translate(320,0)">
-      <rect
-         style="opacity:1;color:#000000;fill:#c4a000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect4907"
-         width="158"
-         height="58.000019"
-         x="1"
-         y="1"
-         rx="2.1094246e-15"
-         ry="2.1094244e-15" />
-      <rect
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect4909"
-         width="80"
-         height="20"
-         x="10"
-         y="0"
-         rx="2.1094246e-15"
-         ry="2.1094244e-15" />
-      <text
-         xml:space="preserve"
-         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         x="8.8222656"
-         y="14.473633"
-         id="text4911"
-         sodipodi:linespacing="100%"><tspan
-           sodipodi:role="line"
-           id="tspan4913"
-           x="8.8222656"
-           y="14.473633">Payload type</tspan></text>
-    </g>
-    <g
-       id="g4915"
-       transform="translate(480,0)">
-      <rect
-         style="opacity:1;color:#000000;fill:#cee14b;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect4917"
-         width="158"
-         height="58.000019"
-         x="1"
-         y="1"
-         rx="2.1094246e-15"
-         ry="2.1094244e-15" />
-      <rect
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect4919"
-         width="80"
-         height="20"
-         x="10"
-         y="0"
-         rx="2.1094246e-15"
-         ry="2.1094244e-15" />
-      <text
-         xml:space="preserve"
-         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         x="8.8222656"
-         y="14.473633"
-         id="text4921"
-         sodipodi:linespacing="100%"><tspan
-           sodipodi:role="line"
-           id="tspan4923"
-           x="8.8222656"
-           y="14.473633">Payload length</tspan></text>
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094246e-15"
-         y="421"
-         x="1"
-         height="58.000019"
-         width="158"
-         id="rect5196"
-         style="opacity:1;color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-    </g>
-    <g
-       id="g4942"
-       transform="translate(0,60)">
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094246e-15"
-         y="1"
-         x="1"
-         height="58.000019"
-         width="158"
-         id="rect4944"
-         style="opacity:1;color:#000000;fill:#cee14b;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094246e-15"
-         y="0"
-         x="10"
-         height="20"
-         width="80"
-         id="rect4946"
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-    </g>
-    <g
-       transform="translate(160,60)"
-       id="g4952">
-      <rect
-         style="opacity:1;color:#000000;fill:#9db029;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000048;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect4954"
-         width="478.00006"
-         height="58.000019"
-         x="1"
-         y="1"
-         rx="2.1094246e-15"
-         ry="2.1094244e-15" />
-      <rect
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect4956"
-         width="80"
-         height="20"
-         x="10"
-         y="0"
-         rx="2.1094246e-15"
-         ry="2.1094244e-15" />
-      <text
-         xml:space="preserve"
-         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         x="8.8222656"
-         y="14.473633"
-         id="text4958"
-         sodipodi:linespacing="100%"><tspan
-           sodipodi:role="line"
-           id="tspan4960"
-           x="8.8222656"
-           y="14.473633">Timestamp</tspan></text>
-    </g>
-    <g
-       transform="translate(160,120)"
-       id="g4962">
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094244e-15"
-         y="1"
-         x="1"
-         height="58.000019"
-         width="477.99994"
-         id="rect4964"
-         style="opacity:1;color:#000000;fill:#fcaf3e;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094246e-15"
-         y="0"
-         x="10"
-         height="20"
-         width="80"
-         id="rect4966"
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <text
-         sodipodi:linespacing="100%"
-         id="text4968"
-         y="14.473633"
-         x="8.8222656"
-         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         xml:space="preserve"><tspan
-           y="14.473633"
-           x="8.8222656"
-           id="tspan4970"
-           sodipodi:role="line">Duration</tspan></text>
-    </g>
-    <g
-       id="g4972"
-       transform="translate(0,180)">
-      <rect
-         style="opacity:1;color:#000000;fill:#fcaf3e;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect4974"
-         width="158"
-         height="58.000019"
-         x="1"
-         y="1"
-         rx="2.1094246e-15"
-         ry="2.1094244e-15" />
-      <rect
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect4976"
-         width="80"
-         height="20"
-         x="10"
-         y="0"
-         rx="2.1094246e-15"
-         ry="2.1094244e-15" />
-    </g>
-    <g
-       id="g4982"
-       transform="translate(160,180)">
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094246e-15"
-         y="1"
-         x="1"
-         height="58.000019"
-         width="478.00006"
-         id="rect4984"
-         style="opacity:1;color:#000000;fill:#f57900;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000048;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094246e-15"
-         y="0"
-         x="10"
-         height="20"
-         width="80"
-         id="rect4986"
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <text
-         sodipodi:linespacing="100%"
-         id="text4988"
-         y="14.473633"
-         x="8.8222656"
-         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         xml:space="preserve"><tspan
-           y="14.473633"
-           x="8.8222656"
-           id="tspan4990"
-           sodipodi:role="line">Offset</tspan></text>
-    </g>
-    <g
-       id="g4992"
-       transform="translate(160,240)">
-      <rect
-         style="opacity:1;color:#000000;fill:#ce5c00;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect4994"
-         width="477.99994"
-         height="58.000019"
-         x="1"
-         y="1"
-         rx="2.1094244e-15"
-         ry="2.1094244e-15" />
-      <rect
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect4996"
-         width="80"
-         height="20"
-         x="10"
-         y="0"
-         rx="2.1094246e-15"
-         ry="2.1094244e-15" />
-      <text
-         xml:space="preserve"
-         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         x="8.8222656"
-         y="14.473633"
-         id="text4998"
-         sodipodi:linespacing="100%"><tspan
-           sodipodi:role="line"
-           id="tspan5000"
-           x="8.8222656"
-           y="14.473633">Offset end</tspan></text>
-    </g>
-    <g
-       id="g5002"
-       transform="matrix(0.333333,0,0,1,0,120)">
-      <rect
-         ry="2.1094244e-15"
-         rx="6.3282746e-15"
-         y="1"
-         x="1"
-         height="58.000019"
-         width="478.00006"
-         id="rect5004"
-         style="opacity:1;color:#000000;fill:#9db029;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.46410275;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         ry="2.1094244e-15"
-         rx="6.3282746e-15"
-         y="0"
-         x="10"
-         height="20"
-         width="80"
-         id="rect5006"
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-    </g>
-    <g
-       transform="matrix(0.333333,0,0,1,0,240)"
-       id="g5012">
-      <rect
-         style="opacity:1;color:#000000;fill:#f57900;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.46410275;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect5014"
-         width="478.00006"
-         height="58.000019"
-         x="1"
-         y="1"
-         rx="6.3282746e-15"
-         ry="2.1094244e-15" />
-      <rect
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect5016"
-         width="80"
-         height="20"
-         x="10"
-         y="0"
-         rx="6.3282746e-15"
-         ry="2.1094244e-15" />
-    </g>
-    <g
-       transform="matrix(0.333333,0,0,1,0,300)"
-       id="g5022">
-      <rect
-         ry="2.1094244e-15"
-         rx="6.3282725e-15"
-         y="1"
-         x="1"
-         height="58.000019"
-         width="477.99994"
-         id="rect5024"
-         style="opacity:1;color:#000000;fill:#ce5c00;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.46410179;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         ry="2.1094244e-15"
-         rx="6.3282729e-15"
-         y="0"
-         x="10"
-         height="20"
-         width="80"
-         id="rect5026"
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-    </g>
-    <g
-       transform="translate(160,300)"
-       id="g5032">
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094246e-15"
-         y="1"
-         x="1"
-         height="58.000019"
-         width="158"
-         id="rect5034"
-         style="opacity:1;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094246e-15"
-         y="0"
-         x="10"
-         height="20"
-         width="80"
-         id="rect5036"
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <text
-         sodipodi:linespacing="100%"
-         id="text5038"
-         y="14.473633"
-         x="8.8222656"
-         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         xml:space="preserve"><tspan
-           y="14.473633"
-           x="8.8222656"
-           id="tspan5040"
-           sodipodi:role="line">Buffer flags</tspan></text>
-    </g>
-    <g
-       id="g5048"
-       transform="translate(320,300)">
-      <rect
-         style="opacity:1;color:#000000;fill:#888a85;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect5050"
-         width="317.99997"
-         height="58.000019"
-         x="1"
-         y="1"
-         rx="2.1094244e-15"
-         ry="2.1094244e-15" />
-      <rect
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect5052"
-         width="80"
-         height="20"
-         x="10"
-         y="0"
-         rx="2.1094246e-15"
-         ry="2.1094244e-15" />
-      <text
-         xml:space="preserve"
-         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         x="8.8222656"
-         y="14.473633"
-         id="text5054"
-         sodipodi:linespacing="100%"><tspan
-           sodipodi:role="line"
-           id="tspan5056"
-           x="8.8222656"
-           y="14.473633">ABI</tspan></text>
-    </g>
-    <g
-       transform="translate(0,360)"
-       id="g5058">
-      <rect
-         ry="2.1094244e-15"
-         rx="2.109424e-15"
-         y="1"
-         x="1"
-         height="58.000019"
-         width="637.99982"
-         id="rect5060"
-         style="opacity:1;color:#000000;fill:#888a85;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094246e-15"
-         y="0"
-         x="10"
-         height="20"
-         width="80"
-         id="rect5062"
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <text
-         sodipodi:linespacing="100%"
-         id="text5064"
-         y="14.473633"
-         x="8.8222656"
-         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         xml:space="preserve"><tspan
-           y="14.473633"
-           x="8.8222656"
-           id="tspan5066"
-           sodipodi:role="line">ABI</tspan></text>
-    </g>
-    <g
-       transform="translate(0,420)"
-       id="g5068">
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094227e-15"
-         y="1"
-         x="1"
-         height="58.000019"
-         width="157.99988"
-         id="rect5070"
-         style="opacity:1;color:#000000;fill:#888a85;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.99999952;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094246e-15"
-         y="0"
-         x="10"
-         height="20"
-         width="80"
-         id="rect5072"
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <text
-         sodipodi:linespacing="100%"
-         id="text5074"
-         y="14.473633"
-         x="8.8222656"
-         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         xml:space="preserve"><tspan
-           y="14.473633"
-           x="8.8222656"
-           id="tspan5076"
-           sodipodi:role="line">ABI</tspan></text>
-    </g>
-    <g
-       id="g5080"
-       transform="translate(160,420)">
-      <rect
-         style="opacity:1;color:#000000;fill:#3465a4;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect5082"
-         width="158"
-         height="58.000019"
-         x="1"
-         y="1"
-         rx="2.1094246e-15"
-         ry="2.1094244e-15" />
-      <rect
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         id="rect5084"
-         width="80"
-         height="20"
-         x="10"
-         y="0"
-         rx="2.1094246e-15"
-         ry="2.1094244e-15" />
-      <text
-         xml:space="preserve"
-         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         x="8.8222656"
-         y="14.473633"
-         id="text5086"
-         sodipodi:linespacing="100%"><tspan
-           sodipodi:role="line"
-           id="tspan5088"
-           x="8.8222656"
-           y="14.473633">CRC header</tspan></text>
-    </g>
-    <g
-       transform="translate(320,420)"
-       id="g5090">
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094246e-15"
-         y="1"
-         x="1"
-         height="58.000019"
-         width="158"
-         id="rect5092"
-         style="opacity:1;color:#000000;fill:#204a87;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         ry="2.1094244e-15"
-         rx="2.1094246e-15"
-         y="0"
-         x="10"
-         height="20"
-         width="80"
-         id="rect5094"
-         style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <text
-         sodipodi:linespacing="100%"
-         id="text5096"
-         y="14.473633"
-         x="8.8222656"
-         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         xml:space="preserve"><tspan
-           y="14.473633"
-           x="8.8222656"
-           id="tspan5098"
-           sodipodi:role="line">CRC payload</tspan></text>
-    </g>
-    <path
-       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-       d="M 81,0.5 L 81,479.5"
-       id="path5104" />
-    <use
-       x="0"
-       y="0"
-       xlink:href="#path5104"
-       id="use5106"
-       transform="translate(-0.5,0)"
-       width="640"
-       height="480" />
-    <use
-       x="0"
-       y="0"
-       xlink:href="#use5106"
-       id="use5108"
-       transform="translate(80,0)"
-       width="640"
-       height="480" />
-    <use
-       x="0"
-       y="0"
-       xlink:href="#use5106"
-       id="use5112" />
-    <use
-       x="0"
-       y="0"
-       xlink:href="#use5112"
-       id="use5114"
-       transform="translate(400,0)"
-       width="640"
-       height="480" />
-    <use
-       x="0"
-       y="0"
-       xlink:href="#use5114"
-       id="use5116"
-       width="640"
-       height="480"
-       transform="translate(-80,0)" />
-    <use
-       x="0"
-       y="0"
-       xlink:href="#use5116"
-       id="use5118"
-       width="640"
-       height="480"
-       transform="translate(-80,0)" />
-    <use
-       x="0"
-       y="0"
-       xlink:href="#use5118"
-       id="use5120"
-       width="640"
-       height="480"
-       transform="translate(-80,0)" />
-    <use
-       id="use5126"
-       xlink:href="#use5106"
-       y="0"
-       x="0"
-       transform="matrix(1,0,0,0.87474,480,6.248e-2)"
-       width="640"
-       height="480" />
-    <g
-       id="g5145">
-      <path
-         id="path5128"
-         d="M 170.5,42.5 L 170.5,59.5"
-         style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-      <use
-         transform="translate(10,0)"
-         height="480"
-         width="640"
-         id="use5130"
-         xlink:href="#path5128"
-         y="0"
-         x="0" />
-      <use
-         height="480"
-         width="640"
-         transform="translate(10,0)"
-         id="use5132"
-         xlink:href="#use5130"
-         y="0"
-         x="0" />
-      <use
-         height="480"
-         width="640"
-         transform="translate(10,0)"
-         id="use5134"
-         xlink:href="#use5132"
-         y="0"
-         x="0" />
-      <use
-         height="480"
-         width="640"
-         transform="translate(10,0)"
-         id="use5136"
-         xlink:href="#use5134"
-         y="0"
-         x="0" />
-      <use
-         height="480"
-         width="640"
-         transform="translate(10,0)"
-         id="use5138"
-         xlink:href="#use5136"
-         y="0"
-         x="0" />
-      <use
-         height="480"
-         width="640"
-         transform="translate(10,0)"
-         id="use5140"
-         xlink:href="#use5138"
-         y="0"
-         x="0" />
-    </g>
-    <g
-       id="g5154"
-       transform="translate(0,300)">
-      <path
-         style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-         d="M 170.5,42.5 L 170.5,59.5"
-         id="path5156" />
-      <use
-         x="0"
-         y="0"
-         xlink:href="#path5128"
-         id="use5158"
-         width="640"
-         height="480"
-         transform="translate(10,0)" />
-      <use
-         x="0"
-         y="0"
-         xlink:href="#use5130"
-         id="use5160"
-         transform="translate(10,0)"
-         width="640"
-         height="480" />
-      <use
-         x="0"
-         y="0"
-         xlink:href="#use5132"
-         id="use5162"
-         transform="translate(10,0)"
-         width="640"
-         height="480" />
-      <use
-         x="0"
-         y="0"
-         xlink:href="#use5134"
-         id="use5164"
-         transform="translate(10,0)"
-         width="640"
-         height="480" />
-      <use
-         x="0"
-         y="0"
-         xlink:href="#use5136"
-         id="use5166"
-         transform="translate(10,0)"
-         width="640"
-         height="480" />
-      <use
-         x="0"
-         y="0"
-         xlink:href="#use5138"
-         id="use5168"
-         transform="translate(10,0)"
-         width="640"
-         height="480" />
-    </g>
-    <g
-       transform="translate(80,300)"
-       id="g5170">
-      <path
-         id="path5172"
-         d="M 170.5,42.5 L 170.5,59.5"
-         style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-      <use
-         transform="translate(10,0)"
-         height="480"
-         width="640"
-         id="use5174"
-         xlink:href="#path5128"
-         y="0"
-         x="0" />
-      <use
-         height="480"
-         width="640"
-         transform="translate(10,0)"
-         id="use5176"
-         xlink:href="#use5130"
-         y="0"
-         x="0" />
-      <use
-         height="480"
-         width="640"
-         transform="translate(10,0)"
-         id="use5178"
-         xlink:href="#use5132"
-         y="0"
-         x="0" />
-      <use
-         height="480"
-         width="640"
-         transform="translate(10,0)"
-         id="use5180"
-         xlink:href="#use5134"
-         y="0"
-         x="0" />
-      <use
-         height="480"
-         width="640"
-         transform="translate(10,0)"
-         id="use5182"
-         xlink:href="#use5136"
-         y="0"
-         x="0" />
-      <use
-         height="480"
-         width="640"
-         transform="translate(10,0)"
-         id="use5184"
-         xlink:href="#use5138"
-         y="0"
-         x="0" />
-    </g>
-    <text
-       xml:space="preserve"
-       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
-       x="501"
-       y="451"
-       id="text5186"
-       sodipodi:linespacing="100%"><tspan
-         sodipodi:role="line"
-         id="tspan5188"
-         x="501"
-         y="451">GStreamer</tspan><tspan
-         sodipodi:role="line"
-         x="501"
-         y="471"
-         id="tspan5192">Data Protocol</tspan></text>
-  </g>
-</svg>
diff --git a/docs/images/gst-universe.svg b/docs/images/gst-universe.svg
new file mode 100644 (file)
index 0000000..dec85ea
--- /dev/null
@@ -0,0 +1,354 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.40.1 (20161225.0304)
+ -->
+<!-- Title: pipeline Pages: 1 -->
+<svg width="707pt" height="632pt"
+ viewBox="0.00 0.00 707.00 632.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 628)">
+<title>pipeline</title>
+<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-628 703,-628 703,4 -4,4"/>
+<!-- application -->
+<g id="node1" class="node">
+<title>application</title>
+<polygon fill="#ffdddd" stroke="#000000" points="577,-624 511,-624 511,-588 577,-588 577,-624"/>
+<text text-anchor="middle" x="544" y="-603.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">application</text>
+</g>
+<!-- bus -->
+<g id="node3" class="node">
+<title>bus</title>
+<g id="a_node3"><a xlink:href="GstBus.html" xlink:title="bus" target="_top">
+<polygon fill="#eeeeee" stroke="#000000" points="122,-464 68,-464 68,-428 122,-428 122,-464"/>
+<text text-anchor="middle" x="95" y="-443.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">bus</text>
+</a>
+</g>
+</g>
+<!-- application&#45;&gt;bus -->
+<g id="edge24" class="edge">
+<title>application&#45;&gt;bus</title>
+<path fill="none" stroke="#000000" d="M510.9115,-603.0792C430.1757,-595.561 225.2233,-574.007 164,-544 132.3738,-528.4992 123.8974,-520.3344 106,-490 103.0991,-485.0833 100.9591,-479.4225 99.3816,-473.8334"/>
+<polygon fill="#000000" stroke="#000000" points="102.776,-472.9771 97.1069,-464.0266 95.957,-474.5588 102.776,-472.9771"/>
+<text text-anchor="middle" x="180" y="-524.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">listen on</text>
+</g>
+<!-- event -->
+<g id="node9" class="node">
+<title>event</title>
+<g id="a_node9"><a xlink:href="gstreamer-GstEvent.html" xlink:title="event" target="_top">
+<polygon fill="#ddffdd" stroke="#000000" points="585,-304 531,-304 531,-268 585,-268 585,-304"/>
+<text text-anchor="middle" x="558" y="-283.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">event</text>
+</a>
+</g>
+</g>
+<!-- application&#45;&gt;event -->
+<g id="edge26" class="edge">
+<title>application&#45;&gt;event</title>
+<path fill="none" stroke="#000000" d="M577.281,-590.2893C600.3723,-576.8307 627,-555.0196 627,-526 627,-526 627,-526 627,-366 627,-345.4784 625.4135,-338.3413 613,-322 607.7902,-315.1417 600.8722,-309.1985 593.7059,-304.2267"/>
+<polygon fill="#000000" stroke="#000000" points="595.5792,-301.2702 585.2668,-298.84 591.8129,-307.1707 595.5792,-301.2702"/>
+<text text-anchor="middle" x="636" y="-444.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">send</text>
+</g>
+<!-- pipeline -->
+<g id="node13" class="node">
+<title>pipeline</title>
+<g id="a_node13"><a xlink:href="GstPipeline.html" xlink:title="pipeline" target="_top">
+<polygon fill="#ccccff" stroke="#000000" points="259,-544 205,-544 205,-508 259,-508 259,-544"/>
+<text text-anchor="middle" x="232" y="-523.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">pipeline</text>
+</a>
+</g>
+</g>
+<!-- application&#45;&gt;pipeline -->
+<g id="edge23" class="edge">
+<title>application&#45;&gt;pipeline</title>
+<path fill="none" stroke="#000000" d="M510.9059,-597.5143C452.3458,-582.4989 330.8592,-551.3485 269.3763,-535.5837"/>
+<polygon fill="#000000" stroke="#000000" points="269.8879,-532.1017 259.3319,-533.0082 268.1492,-538.8823 269.8879,-532.1017"/>
+<text text-anchor="middle" x="404.5" y="-564.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">has</text>
+</g>
+<!-- query -->
+<g id="node16" class="node">
+<title>query</title>
+<g id="a_node16"><a xlink:href="gstreamer-GstQuery.html" xlink:title="query" target="_top">
+<polygon fill="#ddffdd" stroke="#000000" points="677,-304 623,-304 623,-268 677,-268 677,-304"/>
+<text text-anchor="middle" x="650" y="-283.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">query</text>
+</a>
+</g>
+</g>
+<!-- application&#45;&gt;query -->
+<g id="edge25" class="edge">
+<title>application&#45;&gt;query</title>
+<path fill="none" stroke="#000000" d="M577.1639,-601.3855C617.7094,-593.6598 681,-573.9247 681,-526 681,-526 681,-526 681,-366 681,-347.6719 673.8382,-328.4806 666.3992,-313.4901"/>
+<polygon fill="#000000" stroke="#000000" points="669.3088,-311.5046 661.5433,-304.2972 663.1192,-314.7742 669.3088,-311.5046"/>
+<text text-anchor="middle" x="690" y="-444.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">send</text>
+</g>
+<!-- bin -->
+<g id="node2" class="node">
+<title>bin</title>
+<g id="a_node2"><a xlink:href="GstBin.html" xlink:title="bin" target="_top">
+<polygon fill="#ccccff" stroke="#000000" points="343,-464 289,-464 289,-428 343,-428 343,-464"/>
+<text text-anchor="middle" x="316" y="-443.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">bin</text>
+</a>
+</g>
+</g>
+<!-- element -->
+<g id="node7" class="node">
+<title>element</title>
+<g id="a_node7"><a xlink:href="GstElement.html" xlink:title="element" target="_top">
+<polygon fill="#ccccff" stroke="#000000" points="379,-384 325,-384 325,-348 379,-348 379,-384"/>
+<text text-anchor="middle" x="352" y="-363.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">element</text>
+</a>
+</g>
+</g>
+<!-- bin&#45;&gt;element -->
+<g id="edge1" class="edge">
+<title>bin&#45;&gt;element</title>
+<path fill="none" stroke="#000000" d="M313.4728,-427.8198C313.0652,-419.637 313.6319,-410.0331 317,-402 318.4683,-398.498 320.4504,-395.1455 322.7289,-391.9929"/>
+<polygon fill="#000000" stroke="#000000" points="325.5616,-394.0618 329.3031,-384.1495 320.1969,-389.5651 325.5616,-394.0618"/>
+<text text-anchor="middle" x="323.5" y="-404.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">is&#45;a</text>
+</g>
+<!-- bin&#45;&gt;element -->
+<g id="edge12" class="edge">
+<title>bin&#45;&gt;element</title>
+<path fill="none" stroke="#000000" d="M324.169,-427.8468C328.7718,-417.6183 334.6118,-404.6405 339.7523,-393.217"/>
+<polygon fill="#000000" stroke="#000000" points="342.9514,-394.6369 343.8634,-384.0814 336.5679,-391.7643 342.9514,-394.6369"/>
+<text text-anchor="middle" x="346" y="-404.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">has n</text>
+</g>
+<!-- message -->
+<g id="node10" class="node">
+<title>message</title>
+<g id="a_node10"><a xlink:href="gstreamer-GstMessage.html" xlink:title="message" target="_top">
+<polygon fill="#ddffdd" stroke="#000000" points="128,-304 72,-304 72,-268 128,-268 128,-304"/>
+<text text-anchor="middle" x="100" y="-283.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">message</text>
+</a>
+</g>
+</g>
+<!-- bus&#45;&gt;message -->
+<g id="edge19" class="edge">
+<title>bus&#45;&gt;message</title>
+<path fill="none" stroke="#000000" d="M95.5638,-427.957C96.4266,-400.3487 98.082,-347.3746 99.1086,-314.5255"/>
+<polygon fill="#000000" stroke="#000000" points="102.6164,-314.327 99.4305,-304.2226 95.6198,-314.1083 102.6164,-314.327"/>
+<text text-anchor="middle" x="111.5" y="-364.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">receive</text>
+</g>
+<!-- buffer -->
+<g id="node4" class="node">
+<title>buffer</title>
+<g id="a_node4"><a xlink:href="gstreamer-GstBuffer.html" xlink:title="buffer" target="_top">
+<polygon fill="#ddffdd" stroke="#000000" points="521,-250 467,-250 467,-214 521,-214 521,-250"/>
+<text text-anchor="middle" x="494" y="-229.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">buffer</text>
+</a>
+</g>
+</g>
+<!-- caps -->
+<g id="node5" class="node">
+<title>caps</title>
+<g id="a_node5"><a xlink:href="gstreamer-GstCaps.html" xlink:title="caps" target="_top">
+<polygon fill="#eeeeee" stroke="#000000" points="472,-116 418,-116 418,-80 472,-80 472,-116"/>
+<text text-anchor="middle" x="445" y="-95.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">caps</text>
+</a>
+</g>
+</g>
+<!-- buffer&#45;&gt;caps -->
+<g id="edge10" class="edge">
+<title>buffer&#45;&gt;caps</title>
+<path fill="none" stroke="#000000" d="M487.8971,-213.8918C482.9336,-199.2961 475.6823,-178.2673 469,-160 464.7467,-148.3727 463.4659,-145.5473 459,-134 457.9568,-131.3027 456.8678,-128.4926 455.7781,-125.6842"/>
+<polygon fill="#000000" stroke="#000000" points="459.0195,-124.3625 452.1353,-116.309 452.4947,-126.8978 459.0195,-124.3625"/>
+<text text-anchor="middle" x="492" y="-176.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">has n</text>
+</g>
+<!-- structure -->
+<g id="node18" class="node">
+<title>structure</title>
+<g id="a_node18"><a xlink:href="gstreamer-GstStructure.html" xlink:title="structure" target="_top">
+<polygon fill="#eeeeee" stroke="#000000" points="474.5,-36 415.5,-36 415.5,0 474.5,0 474.5,-36"/>
+<text text-anchor="middle" x="445" y="-15.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">structure</text>
+</a>
+</g>
+</g>
+<!-- caps&#45;&gt;structure -->
+<g id="edge11" class="edge">
+<title>caps&#45;&gt;structure</title>
+<path fill="none" stroke="#000000" d="M445,-79.8468C445,-69.9251 445,-57.4167 445,-46.2492"/>
+<polygon fill="#000000" stroke="#000000" points="448.5001,-46.0814 445,-36.0814 441.5001,-46.0814 448.5001,-46.0814"/>
+<text text-anchor="middle" x="455" y="-56.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">has n</text>
+</g>
+<!-- clock -->
+<g id="node6" class="node">
+<title>clock</title>
+<g id="a_node6"><a xlink:href="GstClock.html" xlink:title="clock" target="_top">
+<polygon fill="#eeeeee" stroke="#000000" points="200,-304 146,-304 146,-268 200,-268 200,-304"/>
+<text text-anchor="middle" x="173" y="-283.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">clock</text>
+</a>
+</g>
+</g>
+<!-- element&#45;&gt;buffer -->
+<g id="edge17" class="edge">
+<title>element&#45;&gt;buffer</title>
+<path fill="none" stroke="#000000" d="M379.0052,-348.1841C387.6581,-342.4256 397.2602,-335.9827 406,-330 422.585,-318.647 428.7615,-318.1851 443,-304 456.442,-290.6085 468.8159,-273.3197 478.0084,-259.0402"/>
+<polygon fill="#000000" stroke="#000000" points="481.227,-260.4951 483.569,-250.1624 475.2946,-256.7794 481.227,-260.4951"/>
+<text text-anchor="middle" x="446" y="-324.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">send &amp; receive</text>
+</g>
+<!-- element&#45;&gt;clock -->
+<g id="edge7" class="edge">
+<title>element&#45;&gt;clock</title>
+<path fill="none" stroke="#000000" d="M324.9778,-361.1851C299.2847,-355.9049 260.0596,-345.9868 229,-330 218.9195,-324.8114 208.8758,-317.6948 200.1358,-310.6969"/>
+<polygon fill="#000000" stroke="#000000" points="202.1225,-307.7968 192.197,-304.0908 197.6451,-313.1776 202.1225,-307.7968"/>
+<text text-anchor="middle" x="251.5" y="-324.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">may provide</text>
+</g>
+<!-- element_factory -->
+<g id="node8" class="node">
+<title>element_factory</title>
+<g id="a_node8"><a xlink:href="GstElementFactory.html" xlink:title="element factory" target="_top">
+<polygon fill="#eeeeee" stroke="#000000" points="306,-304 218,-304 218,-268 306,-268 306,-304"/>
+<text text-anchor="middle" x="262" y="-283.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">element factory</text>
+</a>
+</g>
+</g>
+<!-- element&#45;&gt;element_factory -->
+<g id="edge14" class="edge">
+<title>element&#45;&gt;element_factory</title>
+<path fill="none" stroke="#000000" d="M324.8244,-356.6294C310.9201,-350.7366 294.5406,-341.9588 283,-330 278.4484,-325.2835 274.729,-319.3944 271.7547,-313.4736"/>
+<polygon fill="#000000" stroke="#000000" points="274.9408,-312.0246 267.6816,-304.3075 268.5439,-314.8672 274.9408,-312.0246"/>
+<text text-anchor="middle" x="310.5" y="-324.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">is created from</text>
+</g>
+<!-- element&#45;&gt;event -->
+<g id="edge16" class="edge">
+<title>element&#45;&gt;event</title>
+<path fill="none" stroke="#000000" d="M379.0347,-360.7461C406.0174,-355.003 448.3405,-344.6282 483,-330 496.4301,-324.3318 510.3994,-316.6794 522.5904,-309.3462"/>
+<polygon fill="#000000" stroke="#000000" points="524.4387,-312.3185 531.1199,-304.0958 520.7692,-306.3573 524.4387,-312.3185"/>
+<text text-anchor="middle" x="526" y="-324.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">send &amp; receive</text>
+</g>
+<!-- element&#45;&gt;message -->
+<g id="edge18" class="edge">
+<title>element&#45;&gt;message</title>
+<path fill="none" stroke="#000000" d="M324.9822,-361.5785C293.1497,-355.9741 238.9085,-345.1811 194,-330 170.198,-321.9538 163.449,-316.9228 137.4211,-304.2336"/>
+<polygon fill="#000000" stroke="#000000" points="138.777,-301.0021 128.2471,-299.8311 135.7484,-307.3131 138.777,-301.0021"/>
+<text text-anchor="middle" x="203" y="-324.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">send</text>
+</g>
+<!-- pad -->
+<g id="node11" class="node">
+<title>pad</title>
+<g id="a_node11"><a xlink:href="GstPad.html" xlink:title="pad" target="_top">
+<polygon fill="#ccccff" stroke="#000000" points="434,-304 380,-304 380,-268 434,-268 434,-304"/>
+<text text-anchor="middle" x="407" y="-283.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">pad</text>
+</a>
+</g>
+</g>
+<!-- element&#45;&gt;pad -->
+<g id="edge6" class="edge">
+<title>element&#45;&gt;pad</title>
+<path fill="none" stroke="#000000" d="M364.4804,-347.8468C371.6531,-337.4137 380.7923,-324.1203 388.7582,-312.5335"/>
+<polygon fill="#000000" stroke="#000000" points="391.7879,-314.3047 394.569,-304.0814 386.0196,-310.339 391.7879,-314.3047"/>
+<text text-anchor="middle" x="392" y="-324.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">has n</text>
+</g>
+<!-- pad_template -->
+<g id="node12" class="node">
+<title>pad_template</title>
+<g id="a_node12"><a xlink:href="GstPadTemplate.html" xlink:title="pad template" target="_top">
+<polygon fill="#eeeeee" stroke="#000000" points="408.5,-196 331.5,-196 331.5,-160 408.5,-160 408.5,-196"/>
+<text text-anchor="middle" x="370" y="-175.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">pad template</text>
+</a>
+</g>
+</g>
+<!-- element&#45;&gt;pad_template -->
+<g id="edge5" class="edge">
+<title>element&#45;&gt;pad_template</title>
+<path fill="none" stroke="#000000" d="M351.6297,-347.8244C351.397,-335.4673 351.1189,-318.748 351,-304 350.871,-288.0005 349.3386,-283.9135 351,-268 353.1835,-247.0865 358.1473,-223.877 362.4537,-206.266"/>
+<polygon fill="#000000" stroke="#000000" points="365.9671,-206.6471 365.0193,-196.0948 359.1797,-204.935 365.9671,-206.6471"/>
+<text text-anchor="middle" x="361" y="-284.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">has n</text>
+</g>
+<!-- element&#45;&gt;query -->
+<g id="edge15" class="edge">
+<title>element&#45;&gt;query</title>
+<path fill="none" stroke="#000000" d="M379.0863,-363.5768C418.8478,-359.5008 495.0155,-349.7102 557,-330 576.3889,-323.8346 596.9357,-314.4447 613.7714,-305.9205"/>
+<polygon fill="#000000" stroke="#000000" points="615.4351,-309.0005 622.7118,-301.2998 612.2211,-302.7819 615.4351,-309.0005"/>
+<text text-anchor="middle" x="594" y="-324.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">answers</text>
+</g>
+<!-- plugin_feature -->
+<g id="node15" class="node">
+<title>plugin_feature</title>
+<g id="a_node15"><a xlink:href="GstPluginFeature.html" xlink:title="plugin feature" target="_top">
+<polygon fill="#eeeeee" stroke="#000000" points="161,-196 81,-196 81,-160 161,-160 161,-196"/>
+<text text-anchor="middle" x="121" y="-175.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">plugin feature</text>
+</a>
+</g>
+</g>
+<!-- element_factory&#45;&gt;plugin_feature -->
+<g id="edge22" class="edge">
+<title>element_factory&#45;&gt;plugin_feature</title>
+<path fill="none" stroke="#000000" d="M238.3998,-267.9232C214.9138,-249.9339 178.719,-222.2103 152.7282,-202.3024"/>
+<polygon fill="#000000" stroke="#000000" points="154.7443,-199.438 144.6772,-196.1357 150.4877,-204.9951 154.7443,-199.438"/>
+<text text-anchor="middle" x="219.5" y="-230.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">is&#45;a</text>
+</g>
+<!-- pad&#45;&gt;caps -->
+<g id="edge8" class="edge">
+<title>pad&#45;&gt;caps</title>
+<path fill="none" stroke="#000000" d="M421.5944,-267.8888C425.2714,-262.4333 428.7961,-256.2319 431,-250 438.8006,-227.9426 442.5008,-164.0023 444.0459,-126.4479"/>
+<polygon fill="#000000" stroke="#000000" points="447.5545,-126.2911 444.4424,-116.1637 440.5597,-126.0214 447.5545,-126.2911"/>
+<text text-anchor="middle" x="453" y="-176.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">has n</text>
+</g>
+<!-- pad&#45;&gt;pad_template -->
+<g id="edge13" class="edge">
+<title>pad&#45;&gt;pad_template</title>
+<path fill="none" stroke="#000000" d="M387.4506,-267.737C382.9375,-262.4616 378.679,-256.3893 376,-250 370.2976,-236.3999 368.5674,-220.1056 368.3637,-206.4602"/>
+<polygon fill="#000000" stroke="#000000" points="371.8665,-206.2262 368.4808,-196.1869 364.8669,-206.1464 371.8665,-206.2262"/>
+<text text-anchor="middle" x="403.5" y="-230.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">is created from</text>
+</g>
+<!-- pad_template&#45;&gt;caps -->
+<g id="edge9" class="edge">
+<title>pad_template&#45;&gt;caps</title>
+<path fill="none" stroke="#000000" d="M386.7291,-159.9921C394.1513,-152.0167 402.9991,-142.5287 411,-134 414.1284,-130.6653 417.4244,-127.1622 420.6835,-123.7048"/>
+<polygon fill="#000000" stroke="#000000" points="423.3614,-125.9667 427.6795,-116.2917 418.2705,-121.1622 423.3614,-125.9667"/>
+<text text-anchor="middle" x="421" y="-136.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">has n</text>
+</g>
+<!-- pipeline&#45;&gt;bin -->
+<g id="edge2" class="edge">
+<title>pipeline&#45;&gt;bin</title>
+<path fill="none" stroke="#000000" d="M251.0609,-507.8468C262.4452,-497.0045 277.0731,-483.0732 289.5625,-471.1785"/>
+<polygon fill="#000000" stroke="#000000" points="292.1869,-473.5125 297.0145,-464.0814 287.3593,-468.4435 292.1869,-473.5125"/>
+<text text-anchor="middle" x="283.5" y="-484.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">is&#45;a</text>
+</g>
+<!-- pipeline&#45;&gt;bus -->
+<g id="edge3" class="edge">
+<title>pipeline&#45;&gt;bus</title>
+<path fill="none" stroke="#000000" d="M204.6065,-523.7303C178.9936,-520.2926 141.0367,-511.6598 116,-490 110.959,-485.6389 107.0322,-479.7973 104.0111,-473.7986"/>
+<polygon fill="#000000" stroke="#000000" points="107.1483,-472.2343 99.9793,-464.4332 100.7188,-475.0022 107.1483,-472.2343"/>
+<text text-anchor="middle" x="126" y="-484.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">has 1</text>
+</g>
+<!-- pipeline&#45;&gt;clock -->
+<g id="edge4" class="edge">
+<title>pipeline&#45;&gt;clock</title>
+<path fill="none" stroke="#000000" d="M224.1619,-507.8066C209.9486,-473.7131 180.4285,-397.5454 170,-330 169.2231,-324.968 169.0522,-319.5812 169.225,-314.3635"/>
+<polygon fill="#000000" stroke="#000000" points="172.7398,-314.2874 169.9782,-304.0589 165.7584,-313.7771 172.7398,-314.2874"/>
+<text text-anchor="middle" x="199" y="-404.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">has 1</text>
+</g>
+<!-- plugin -->
+<g id="node14" class="node">
+<title>plugin</title>
+<g id="a_node14"><a xlink:href="GstPlugin.html" xlink:title="plugin" target="_top">
+<polygon fill="#eeeeee" stroke="#000000" points="54,-304 0,-304 0,-268 54,-268 54,-304"/>
+<text text-anchor="middle" x="27" y="-283.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">plugin</text>
+</a>
+</g>
+</g>
+<!-- plugin&#45;&gt;plugin_feature -->
+<g id="edge21" class="edge">
+<title>plugin&#45;&gt;plugin_feature</title>
+<path fill="none" stroke="#000000" d="M42.9458,-267.6793C58.2302,-250.1185 81.4452,-223.4459 98.5869,-203.7512"/>
+<polygon fill="#000000" stroke="#000000" points="101.3645,-205.8911 105.2897,-196.0502 96.0843,-201.2954 101.3645,-205.8911"/>
+<text text-anchor="middle" x="98" y="-230.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">has n</text>
+</g>
+<!-- registry -->
+<g id="node17" class="node">
+<title>registry</title>
+<g id="a_node17"><a xlink:href="GstRegistry.html" xlink:title="registry" target="_top">
+<polygon fill="#eeeeee" stroke="#000000" points="54,-384 0,-384 0,-348 54,-348 54,-384"/>
+<text text-anchor="middle" x="27" y="-363.8" font-family="Bitstream Vera Sans" font-size="9.00" fill="#000000">registry</text>
+</a>
+</g>
+</g>
+<!-- registry&#45;&gt;plugin -->
+<g id="edge20" class="edge">
+<title>registry&#45;&gt;plugin</title>
+<path fill="none" stroke="#000000" d="M27,-347.8468C27,-337.9251 27,-325.4167 27,-314.2492"/>
+<polygon fill="#000000" stroke="#000000" points="30.5001,-314.0814 27,-304.0814 23.5001,-314.0814 30.5001,-314.0814"/>
+<text text-anchor="middle" x="37" y="-324.4" font-family="Bitstream Vera Sans" font-size="7.00" fill="#000000">has n</text>
+</g>
+</g>
+</svg>
diff --git a/docs/index.md b/docs/index.md
new file mode 100644 (file)
index 0000000..8240c79
--- /dev/null
@@ -0,0 +1,336 @@
+---
+short-description:  GStreamer core API reference.
+...
+
+# GStreamer Core
+
+GStreamer is a streaming media framework. It uses graphs of elements
+which operate on data. The functionality to process media is provided by
+plug-ins which provide features like elements, typefinding, and so on.
+This allows new functionality to be added simply by installing new
+plug-ins.
+
+GStreamer is cross-platform and works on most UNIX-like platforms as
+well as Windows. It is released under the GNU Library General Public
+License (GNU LGPL).
+
+![ Relation between gstreamer core objects. ]
+
+  [ Relation between gstreamer core objects. ]: images/gst-universe.svg
+
+## Building on UNIX
+
+On UNIX, GStreamer uses the standard GNU build system, using autoconf
+for package configuration and resolving portability issues, automake for
+building makefiles that comply with the GNU Coding Standards, and
+libtool for building shared libraries on multiple platforms. The normal
+sequence for compiling and installing the GStreamer library is thus:
+`./configure` `make` `make install`
+
+The standard options provided by GNU autoconf may be passed to the
+`configure` script. Please see the autoconf documentation or run
+`./configure --help` for information about the standard options.
+
+In addition there are several options to activate or deactivate
+features. E.g. passing `--disable-gst-debug` to `configure` will turn
+the debugging subsystem into a non-functional stub and remove all macro
+based invocations from within the library (and anything compiled against
+the library afterwards.)
+
+If library size matters and one builds in a controlled environment, it
+is also possible to totally remove subsystem code. This is intentionally
+not offered as a configure option as it causes an ABI break. Code built
+against a version of GStreamer without these modifications needs to be
+recompiled.
+
+`make CFLAGS="-DGST_REMOVE_DEPRECATED -DGST_REMOVE_DISABLED"`
+
+-   `GST_REMOVE_DEPRECATED` - Omit deprecated functions from the
+    library.
+
+-   `GST_REMOVE_DISABLED` - Omit stubs for disabled subsystems from the
+    library.
+
+## Building GStreamer Applications
+
+Applications and libraries can use `pkg-config` to get all the needed
+compiler and linker flags to build against GStreamer. Please note that
+GStreamer is split into several libraries itself.
+`pkg-config --list-all | grep gstreamer` will list the available
+libraries.
+
+## Running and debugging GStreamer Applications
+
+### Environment variables
+
+GStreamer inspects a few of environment variables in addition to
+standard variables like LANG, PATH or HOME.
+
+**GST_PLUGIN_SYSTEM_PATH, GST_PLUGIN_SYSTEM_PATH_1_0.**
+
+This environment variable can be set to a colon-separated list of paths
+(or semicolon-separated list on Windows). If this variable is not set,
+GStreamer will fill in this list for you with
+
+-   plug-ins in the user's home directory, or rather the user's "data
+    home" directory according to the xdg base dir specification. Usually
+    this will be a directory called `plugins` inside the
+    `.local/share/gstreamer-GST_API_VERSION` directory in the user's
+    home directory by default, though this search path may change if the
+    XDG_DATA_HOME environment variable is set.
+
+-   plug-ins installed system-wide. On this system, they are stored in
+    `GST_PLUGINS_DIR`.
+
+GStreamer will scan these paths for GStreamer plug-ins. These plug-ins
+will be loaded after the plug-ins in the GST_PLUGIN_PATH variable
+below. The paths are scanned in the given order. This allows a user to
+override system-installed plug-ins with his own versions.
+
+The GST_PLUGIN_SYSTEM_PATH_1_0 variant is useful if both the old
+GStreamer 0.10 version and the new GStreamer 1.0 version need to be
+pointed to new plugin paths. The latter will use the _1_0 variant over
+the non-versioned one if it is set.
+
+Setting this variable to an empty string will cause GStreamer not to
+scan any system paths at all for plug-ins. This can be useful if you're
+running uninstalled (for development purposes) or while running
+testsuites.
+
+**GST_PLUGIN_PATH, GST_PLUGIN_PATH_1_0.**
+
+This environment variable can be set to a colon-separated list of paths
+(or a semicolon-separated list on Windows). GStreamer will scan these
+paths for GStreamer plug-ins. These plug-ins will be loaded in addition
+to, and before, the plug-ins in the system paths.
+
+The GST_PLUGIN_PATH_1_0 variant is useful if both the old GStreamer
+0.10 version and the new GStreamer 1.0 version need to be pointed to new
+plugin paths. The latter will use the _1_0 variant over the
+non-versioned one if it is set.
+
+**GST_DEBUG.**
+
+If GStreamer has been configured with `--enable-gst-debug=yes`, this
+variable can be set to a list of debug options, which cause GStreamer to
+print out different types of debugging information to stderr.
+
+The variable takes a comma-separated list of "category_name:level"
+pairs to set specific levels for the individual categories. The level
+value ranges from 0 (nothing) to 9 (MEMDUMP).
+
+* 1 - `ERROR`: Logs all fatal errors. These are errors that do not allow the core
+    or elements to perform the requested action. The application can
+    still recover if programmed to handle the conditions that triggered
+    the error.
+* 2 - `WARNING`: Logs all warnings. Typically these are non-fatal, but user-visible
+    problems are expected to happen.
+* 3 - `FIXME`: Logs all fixme messages. Fixme messages are messages that indicate
+    that something in the executed code path is not fully implemented or
+    handled yet. The purpose of this message is to make it easier to
+    spot incomplete/unfinished pieces of code when reading the debug
+    log.
+* 4 - `INFO`: Logs all informational messages. These are typically used for events
+    in the system that only happen once, or are important and rare
+    enough to be logged at this level.
+* 5 - `DEBUG`: Logs all debug messages. These are general debug messages for events
+    that happen only a limited number of times during an object's
+    lifetime; these include setup, teardown, change of parameters, ...
+* 6 - `LOG`: Logs all log messages. These are messages for events that happen
+    repeatedly during an object's lifetime; these include streaming and
+    steady-state conditions.
+* 7 - `TRACE`: Logs all trace messages. These messages for events that happen
+    repeatedly during an object's lifetime such as the ref/unref cycles.
+* 9 - `MEMDUMP`: Log all memory dump messages. Memory dump messages are used to log
+    (small) chunks of data as memory dumps in the log. They will be
+    displayed as hexdump with ASCII characters.
+
+The category_name can contain "`*"` as a wildcard.
+
+For example, setting GST_DEBUG to `GST_AUTOPLUG:6,GST_ELEMENT_*:4`,
+will cause the `GST_AUTOPLUG` category to be logged at full `LOG` level,
+while all categories starting with `GST_ELEMENT_` will be logged at
+`INFO` level.
+
+To get all possible debug output, set GST_DEBUG to `*:9`. For debugging
+purposes a `*:6` debug log is usually the most useful, as it contains
+all important information, but hides a lot of noise such as refs/unrefs.
+For bug reporting purposes, a `*:6` log is also what will be requested
+usually. It's often also worth running with `*:3` to see if there are
+any non-fatal errors or warnings that might be related to the problem at
+hand.
+
+Since GStreamer 1.2 it is also possible to specify debug levels by name,
+e.g. GST_DEBUG=*:WARNING,*audio*:LOG
+
+**GST_DEBUG_NO_COLOR.**
+
+Set this environment variable to any value ("1" typically) to switch off
+colouring in GST_DEBUG output. This has the same effect as specifying
+the `--gst-debug-no-color` or `--gst-debug-color-mode`=off command line
+option to well-behaved GStreamer applications (ie. those that pass
+command-line options correctly to GStreamer). This is particularly
+useful to reduce the size of debug output and also allows for the output
+to be compressed much better than with colours turned on.
+
+Has the same effect as setting GST_DEBUG_COLOR_MODE environment
+variable to "off".
+
+**GST_DEBUG_COLOR_MODE.**
+
+Set this environment variable to change log colouring in GST_DEBUG
+output. Possible values:
+
+* `on`: Enables debug log output coloring. Uses default coloring method for
+  current platform. This is the default.
+* `off`: Disables debug log output coloring. This has the same effect as
+  specifying the `--gst-debug-color-mode`=off command line option to
+  well-behaved GStreamer applications (ie. those that pass
+  command-line options correctly to GStreamer). This is particularly
+  useful to reduce the size of debug output and also allows for the
+  output to be compressed much better than with colours turned on.
+
+  Has the same effect as setting GST_DEBUG_NO_COLOR environment
+  variable to any value.
+* `auto`: Same as `on`.
+* `disable`: Same as `off`.
+* `unix`: Enables debug log output coloring and forces the use of UNIX termial
+  codes for coloring, even if this method is not normally used on
+  current platform. This has the same effect as specifying the
+  `--gst-debug-color-mode`=unix command line option to well-behaved
+  GStreamer applications (ie. those that pass command-line options
+  correctly to GStreamer). This is particularly useful to dump debug
+  output into a file on non-UNIX platforms to be sent to developers
+  who have viewers that support UNIX terminal codes.
+
+**GST_DEBUG_OPTIONS.**
+
+This environment variable can be used to tweak the behaviour of the
+debugging system. Currently the only options supported are "pretty-tags"
+and "full-tags". In "pretty-tags" mode (the default), taglists in the
+debug log will be serialized so that only the first few and last few
+bytes of a buffer-type tag will be serialized into the log, to avoid
+dumping hundreds of lines of useless output into the log in case of
+large image tags and the like.
+
+**GST_DEBUG_DUMP_DOT_DIR.**
+
+Set this environment variable to a path to turn on all
+#GST_DEBUG_BIN_TO_DOT_FILE or
+#GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS calls and have the dot files
+in that location.
+
+This will only work if the application in question makes these calls in
+strategic places (like when the pipeline state changes or an error
+occurs). gst-launch-GST_API_VERSION is one such application.
+
+These .dot files can then be turned into images using the 'dot' utility
+from the graphviz set of tools, like this:
+`dot foo.dot -Tsvg -o foo.svg` or `dot foo.dot -Tpng -o foo.png` or
+`dot foo.dot -Tjpg -o foo.jpg`.
+
+There is also a utility called `xdot` which allows you to view the dot
+file directly without converting it first.
+
+**GST_REGISTRY, GST_REGISTRY_1_0.**
+
+Set this environment variable to make GStreamer use a different file for
+the plugin cache / registry than the default one. This is useful when
+operating in a separate environment which should not affect the default
+cache in the user's home directory.
+
+**GST_REGISTRY_FORK.**
+
+Set this environment variable to "no" to prevent GStreamer from forking
+on startup in order to update the plugin registry. This is useful for
+debugging purposes, but should not be used under normal circumstances,
+since it means that plugins may be loaded into memory even if they are
+not needed by the application.
+
+**GST_REGISTRY_UPDATE.**
+
+Set this environment variable to "no" to prevent GStreamer from updating
+the plugin registry. This is useful for embedded device which is not
+updating the plugins frequently, it will save time when doing
+gst_init().
+
+**GST_TRACE.**
+
+Enable memory allocation tracing. Most GStreamer objects have support
+for tracing the number of unfreed objects and their memory pointers.
+
+The variable takes a comma-separated list of tracing options to enable.
+
+* live: Counts all live objects and dumps an overview of the number of
+    unfreed objects at program exit.
+
+* mem-live: Keep track of the unfreed memory pointers and dump an overview of
+    all unfreed memory at program exit. Together with a level 9 debug
+    log this can be used to follow the lifecycle of leaked objects in
+    order to track down where they are leaked. This can be useful for
+    debugging memory leaks in situations where tools such as valgrind
+    are not available, or not an option.
+
+Use `all` to enable all tracing flags.
+
+**GST_DEBUG_FILE.**
+
+Set this variable to a file path to redirect all GStreamer debug
+messages to this file. If left unset, debug messages with be output unto
+the standard error.
+
+**ORC_CODE.**
+
+Useful Orc environment variable. Set ORC_CODE=debug to enable debuggers
+such as gdb to create useful backtraces from Orc-generated code. Set
+ORC_CODE=backup or ORC_CODE=emulate if you suspect Orc's SIMD code
+generator is producing incorrect code (Quite a few important GStreamer
+plugins like videotestsrc, audioconvert or audioresample use Orc). One
+can also combine flags like ORC_CODE=backup,debug.
+
+**G_DEBUG.**
+
+Useful GLib environment variable. Set G_DEBUG=fatal_warnings to make
+GStreamer programs abort when a critical warning such as an assertion
+failure occurs. This is useful if you want to find out which part of the
+code caused that warning to be triggered and under what circumstances.
+Simply set G_DEBUG as mentioned above and run the program in gdb (or
+let it core dump). Then get a stack trace in the usual way.
+
+**G_SLICE.**
+
+Useful GLib environment variable. Set G_SLICE=always-malloc when
+running GStreamer programs in valgrind, or debugging memory leaks with
+other tools. See the GLib API reference for more details.
+
+**GST_TAG_ENCODING.**
+
+Try this character encoding first for tag-related strings where the
+encoding is not defined and which are not UTF-8 already. By default the
+current locale will be tried (if not UTF-8).
+
+**GST_TAG_ID3_ENCODING.**
+
+Try this character encoding first for ID3 tag-related strings where the
+encoding is not defined and which are not UTF-8 already. By default the
+current locale will be tried (if not UTF-8).
+
+**GST_TAG_ID3V1_ENCODING.**
+
+Try this character encoding first for ID3v1 tag-related strings where
+the encoding does not look like UTF-8.
+
+**GST_GL_WINDOW.**
+
+Influences the window system to use by the GStreamer OpenGL library.
+Common values are 'x11', 'wayland', 'win32' or 'cocoa'.
+
+**GST_GL_PLATFORM.**
+
+Influences the OpenGL platform to use by the GStreamer OpenGL library.
+Common values are 'egl', 'glx', 'wgl' or 'cgl'.
+
+**GST_GL_API.**
+
+Influences the OpenGL API requested by the OpenGL platform. Common
+values are 'opengl' or 'gles2'.
diff --git a/docs/libs/.gitignore b/docs/libs/.gitignore
deleted file mode 100644 (file)
index 8701351..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-*.bak
-*.stamp
-html
-xml
-doc-registry.xml
-Makefile
-Makefile.in
-gstreamer-libs-decl.txt
-gstreamer-libs-decl-list.txt
-gstreamer-libs-presed-scan.c
-gstreamer-libs-undocumented.txt
-gstreamer-libs-unused.txt
-gstreamer-libs-undeclared.txt
-gstreamer-libs.args
-gstreamer-libs.hierarchy
-gstreamer-libs.interfaces
-gstreamer-libs.prerequisites
-gstreamer-libs.signals
-gstreamer-libs-scan.gcno
diff --git a/docs/libs/Makefile.am b/docs/libs/Makefile.am
deleted file mode 100644 (file)
index 0fc1756..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-# The name of the module, e.g. 'glib'.
-#DOC_MODULE=gstreamer-libs-@GST_API_VERSION@
-DOC_MODULE=gstreamer-libs
-
-# don't want $(DOC_MODULE)-scan.c to be built with -Werror
-ERROR_CFLAGS=
-
-# for upload-doc.mak
-DOC=gstreamer-libs
-FORMATS=html
-html: html-build.stamp
-include $(top_srcdir)/common/upload-doc.mak
-
-# The top-level SGML file. Change it if you want.
-DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
-
-# The directory containing the source code.
-# gtk-doc will search all .c & .h files beneath here for inline comments
-# documenting functions and macros.
-DOC_SOURCE_DIR=$(top_srcdir)/libs/gst
-
-# Extra options to supply to gtkdoc-scan.
-SCAN_OPTIONS=--deprecated-guards="GST_DISABLE_DEPRECATED" \
-  --ignore-decorators="GST_API|GST_BASE_API|GST_CHECK_API|GST_CONTROLLER_API|GST_NET_API"
-
-# Extra options to supply to gtkdoc-mkdb.
-MKDB_OPTIONS=--sgml-mode --output-format=xml --ignore-files="$(IGNORE_HFILES)"
-
-# Extra options to supply to gtkdoc-fixref.
-FIXXREF_OPTIONS=--extra-dir=$(top_builddir)/docs/gst/html \
-       --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \
-       --extra-dir=$(datadir)/gtk-doc/html
-
-# Used for dependencies.
-HFILE_GLOB=$(top_srcdir)/libs/gst/*/*.h
-CFILE_GLOB=$(top_srcdir)/libs/gst/*/*.c
-
-# Extra options to pass to gtkdoc-scanobj or gtkdoc-scangobj.
-SCANOBJ_OPTIONS=--type-init-func="gst_init(&argc,&argv)"
-
-CHECK_HFILES=$(wildcard $(top_srcdir)/libs/gst/check/libcheck/*.h)
-CHECK_HFILES+=$(wildcard $(top_srcdir)/libs/gst/check/libcheck/libcompat/*.h)
-
-# Header files to ignore when scanning.
-IGNORE_HFILES = \
-       $(CHECK_HFILES) \
-       check/libcheck internal-check.h \
-       gstinterpolationcontrolsourceprivate.h \
-       gstlfocontrolsourceprivate.h \
-       gstgetbits_inl.h \
-       gstindex.h \
-       dp-private.h \
-       gstntppacket.h
-
-# Images to copy into HTML directory.
-HTML_IMAGES = gdp-header.png
-
-# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
-content_files =
-
-# Other files to distribute.
-extra_files =
-
-# CFLAGS and LDFLAGS for compiling scan program. Only needed if your app/lib
-# contains GtkObjects/GObjects and you want to document signals and properties.
-GTKDOC_CFLAGS = -I$(top_builddir) -I$(top_builddir)/libs $(GST_OBJ_CFLAGS)
-GTKDOC_LIBS = \
-       $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \
-       $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \
-       $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \
-       $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \
-       $(GST_OBJ_LIBS)
-
-GTKDOC_EXTRA_ENVIRONMENT= \
-    GST_PLUGIN_SCANNER_1_0=$(top_builddir)/libs/gst/helpers/gst-plugin-scanner
-
-# If you need to override some of the declarations, place them in this file
-# and uncomment this line.
-DOC_OVERRIDES = $(DOC_MODULE)-overrides.txt
-
-include $(top_srcdir)/common/gtk-doc.mak
diff --git a/docs/libs/base/index.md b/docs/libs/base/index.md
new file mode 100644 (file)
index 0000000..055131a
--- /dev/null
@@ -0,0 +1,3 @@
+# Base and Utility classes
+
+`gstreamer-base` provides some base classes to be extended by elements and utility classes that are most useful for plugin developers.
diff --git a/docs/libs/base/sitemap.txt b/docs/libs/base/sitemap.txt
new file mode 100644 (file)
index 0000000..bc77407
--- /dev/null
@@ -0,0 +1,4 @@
+gi-index
+        gstbitreader.h
+        gstbytereader.h
+        gstbytewriter.h
diff --git a/docs/libs/check/index.md b/docs/libs/check/index.md
new file mode 100644 (file)
index 0000000..ee80e22
--- /dev/null
@@ -0,0 +1,3 @@
+# Check Unit Testing
+
+`gstreamer-check` provides functionality for writing unit tests that use the check framework.
diff --git a/docs/libs/check/sitemap.txt b/docs/libs/check/sitemap.txt
new file mode 100644 (file)
index 0000000..1aeae9b
--- /dev/null
@@ -0,0 +1,2 @@
+gi-index
+       gstcheck.h
diff --git a/docs/libs/controller/index.md b/docs/libs/controller/index.md
new file mode 100644 (file)
index 0000000..808bcb6
--- /dev/null
@@ -0,0 +1,3 @@
+# Dynamic Parameter Control
+
+`gstreamer-controller` provides functionality to animate element properties over time.
diff --git a/docs/libs/controller/sitemap.txt b/docs/libs/controller/sitemap.txt
new file mode 100644 (file)
index 0000000..4f91fcd
--- /dev/null
@@ -0,0 +1 @@
+gi-index
diff --git a/docs/libs/gstreamer-libs-docs.sgml b/docs/libs/gstreamer-libs-docs.sgml
deleted file mode 100644 (file)
index 620db5b..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-               "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
-<!ENTITY % version-entities SYSTEM "version.entities">
-%version-entities;
-<!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
-<!ENTITY hash "#">
-]>
-<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
-  <bookinfo>
-    <title>GStreamer &GST_API_VERSION; Library Reference Manual</title>
-    <releaseinfo>
-      for GStreamer Library &GST_API_VERSION; (&GST_VERSION;)
-      The latest version of this documentation can be found on-line at
-      <ulink role="online-location" url="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-libs/html/">http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-libs/html/</ulink>.
-    </releaseinfo>
-  </bookinfo>
-  <part id="gstreamer-libs">
-    <title>GStreamer Libraries</title>
-
-    <para>
-      To ease the creation of plugins, a library system was created. The most common
-      functions for a plugin can be found in a library.
-    </para>
-    <para>
-      GStreamer provides some standard libraries you can use to create plugins.
-    </para>
-
-    <chapter id="gstreamer-base">
-      <title>GStreamer Base and Utility Classes</title>
-      <para>
-        libgstbase-&GST_API_VERSION;.so provides some base classes to be extended
-        by elements and utility classes that are most useful for plugin developers.
-      </para>
-
-      <xi:include href="xml/gstaggregator.xml" />
-      <xi:include href="xml/gstaggregatorpad.xml" />
-
-      <xi:include href="xml/gstbaseparse.xml" />
-      <xi:include href="xml/gstbasesrc.xml" />
-      <xi:include href="xml/gstbasesink.xml" />
-      <xi:include href="xml/gstbasetransform.xml" />
-      <xi:include href="xml/gstpushsrc.xml" />
-
-      <xi:include href="xml/gstadapter.xml" />
-      <xi:include href="xml/gstbitreader.xml" />
-      <xi:include href="xml/gstbitwriter.xml" />
-      <xi:include href="xml/gstbytereader.xml" />
-      <xi:include href="xml/gstbytewriter.xml" />
-      <xi:include href="xml/gstcollectpads.xml" />
-      <xi:include href="xml/gstflowcombiner.xml" />
-      <xi:include href="xml/gsttypefindhelper.xml" />
-      <xi:include href="xml/gstdataqueue.xml" />
-      <xi:include href="xml/gstqueuearray.xml" />
-    </chapter>
-
-    <chapter id="gstreamer-control">
-      <title>GStreamer Dynamic Parameter Control</title>
-      <para>
-        libgstcontroller-&GST_API_VERSION;.so provides functionality to animate
-        element properties over time.
-      </para>
-
-                       <xi:include href="xml/gstargbcontrolbinding.xml" />
-                       <xi:include href="xml/gstdirectcontrolbinding.xml" />
-                       <xi:include href="xml/gstproxycontrolbinding.xml" />
-
-      <xi:include href="xml/gsttimedvaluecontrolsource.xml" />
-      <xi:include href="xml/gstinterpolationcontrolsource.xml" />
-      <xi:include href="xml/gstlfocontrolsource.xml" />
-      <xi:include href="xml/gsttriggercontrolsource.xml" />
-    </chapter>
-
-    <chapter id="gstreamer-net">
-      <title>GStreamer Network Classes</title>
-      <para>
-        libgstnet-&GST_API_VERSION;.so provides network elements and objects.
-      </para>
-
-      <xi:include href="xml/gstnetaddressmeta.xml" />
-      <xi:include href="xml/gstnetclientclock.xml" />
-      <xi:include href="xml/gstnetcontrolmessagemeta.xml" />
-      <xi:include href="xml/gstnettimepacket.xml" />
-      <xi:include href="xml/gstnettimeprovider.xml" />
-      <xi:include href="xml/gstptpclock.xml" />
-    </chapter>
-
-    <chapter id="gstreamer-check">
-      <title>GStreamer Check Unit Testing</title>
-      <para>
-        libgstcheck-&GST_API_VERSION;.so provides functionality for writing
-        unit tests that use the check framework.
-      </para>
-
-      <xi:include href="xml/gstcheck.xml" />
-      <xi:include href="xml/gstcheckbufferstraw.xml" />
-      <xi:include href="xml/gstcheckconsistencychecker.xml" />
-      <xi:include href="xml/gstharness.xml" />
-      <xi:include href="xml/gsttestclock.xml" />
-    </chapter>
-  </part>
-
-  <chapter id="gstreamer-hierarchy">
-    <title>Object Hierarchy</title>
-    <xi:include href="xml/tree_index.sgml"/>
-  </chapter>
-
-  <index>
-    <title>API Index</title>
-    <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
-  </index>
-  <index role="deprecated">
-    <title>Index of deprecated API</title>
-    <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.14</title>
-    <xi:include href="xml/api-index-1.14.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.12.1</title>
-    <xi:include href="xml/api-index-1.12.1.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.12</title>
-    <xi:include href="xml/api-index-1.12.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.10</title>
-    <xi:include href="xml/api-index-1.10.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.8</title>
-    <xi:include href="xml/api-index-1.8.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.6</title>
-    <xi:include href="xml/api-index-1.6.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.4</title>
-    <xi:include href="xml/api-index-1.4.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.2</title>
-    <xi:include href="xml/api-index-1.2.xml"><xi:fallback /></xi:include>
-  </index>
-  <index>
-    <title>Index of new API in 1.0.1</title>
-    <xi:include href="xml/api-index-1.0.1.xml"><xi:fallback /></xi:include>
-  </index>
-
-  <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
-
-</book>
diff --git a/docs/libs/gstreamer-libs-overrides.txt b/docs/libs/gstreamer-libs-overrides.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/docs/libs/gstreamer-libs-sections.txt b/docs/libs/gstreamer-libs-sections.txt
deleted file mode 100644 (file)
index fccc689..0000000
+++ /dev/null
@@ -1,1440 +0,0 @@
-# GStreamer Libraries API reference sections
-
-## please add sections in alphabetical order using the following template
-# leave two empty lines between sections
-# <SECTION>
-# <FILE>gstxxx</FILE>
-# <TITLE>GstXxx</TITLE>
-# typedefs
-# macros
-# constructor
-# methods
-# <SUBSECTION Standard>
-# <SUBSECTION Private>
-# </SECTION>
-
-# control binding classes
-
-<SECTION>
-<FILE>gstargbcontrolbinding</FILE>
-<TITLE>GstARGBControlBinding</TITLE>
-<INCLUDE>gst/controller/controller.h</INCLUDE>
-gst_argb_control_binding_new
-<SUBSECTION Standard>
-GstARGBControlBinding
-GstARGBControlBindingClass
-GST_ARGB_CONTROL_BINDING
-GST_ARGB_CONTROL_BINDING_CLASS
-GST_ARGB_CONTROL_BINDING_GET_CLASS
-GST_IS_ARGB_CONTROL_BINDING
-GST_IS_ARGB_CONTROL_BINDING_CLASS
-GST_TYPE_ARGB_CONTROL_BINDING
-gst_argb_control_binding_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstdirectcontrolbinding</FILE>
-<TITLE>GstDirectControlBinding</TITLE>
-<INCLUDE>gst/controller/controller.h</INCLUDE>
-gst_direct_control_binding_new
-gst_direct_control_binding_new_absolute
-<SUBSECTION Standard>
-GstDirectControlBindingConvertValue
-GstDirectControlBindingConvertGValue
-GstDirectControlBinding
-GstDirectControlBindingClass
-GST_DIRECT_CONTROL_BINDING
-GST_DIRECT_CONTROL_BINDING_CLASS
-GST_DIRECT_CONTROL_BINDING_GET_CLASS
-GST_IS_DIRECT_CONTROL_BINDING
-GST_IS_DIRECT_CONTROL_BINDING_CLASS
-GST_TYPE_DIRECT_CONTROL_BINDING
-gst_direct_control_binding_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstproxycontrolbinding</FILE>
-<TITLE>GstProxyControlBinding</TITLE>
-<INCLUDE>gst/controller/controller.h</INCLUDE>
-gst_proxy_control_binding_new
-<SUBSECTION Standard>
-GstProxyControlBinding
-GstProxyControlBindingClass
-GST_PROXY_CONTROL_BINDING
-GST_PROXY_CONTROL_BINDING_CLASS
-GST_PROXY_CONTROL_BINDING_GET_CLASS
-GST_IS_PROXY_CONTROL_BINDING
-GST_IS_PROXY_CONTROL_BINDING_CLASS
-GST_TYPE_PROXY_CONTROL_BINDING
-gst_proxy_control_binding_get_type
-</SECTION>
-
-# control source classes
-
-<SECTION>
-<FILE>gsttimedvaluecontrolsource</FILE>
-<TITLE>GstTimedValueControlSource</TITLE>
-<INCLUDE>gst/controller/controller.h</INCLUDE>
-GstTimedValueControlSource
-GstControlPoint
-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_invalidate_cache
-gst_control_point_copy
-gst_control_point_free
-<SUBSECTION Standard>
-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
-GST_TIMED_VALUE_CONTROL_SOURCE_LOCK
-GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK
-<SUBSECTION Private>
-gst_timed_value_control_source_get_type
-gst_control_point_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstinterpolationcontrolsource</FILE>
-<TITLE>GstInterpolationControlSource</TITLE>
-<INCLUDE>gst/controller/controller.h</INCLUDE>
-GstInterpolationControlSource
-GstInterpolationMode
-gst_interpolation_control_source_new
-<SUBSECTION Standard>
-GstInterpolationControlSourceClass
-GstInterpolationControlSourcePrivate
-GST_INTERPOLATION_CONTROL_SOURCE
-GST_IS_INTERPOLATION_CONTROL_SOURCE
-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>
-<FILE>gstlfocontrolsource</FILE>
-<TITLE>GstLFOControlSource</TITLE>
-<INCLUDE>gst/controller/controller.h</INCLUDE>
-GstLFOControlSource
-GstLFOWaveform
-gst_lfo_control_source_new
-<SUBSECTION Standard>
-GstLFOControlSourceClass
-GstLFOControlSourcePrivate
-GST_IS_LFO_CONTROL_SOURCE
-GST_IS_LFO_CONTROL_SOURCE_CLASS
-GST_LFO_CONTROL_SOURCE
-GST_LFO_CONTROL_SOURCE_CLASS
-GST_LFO_CONTROL_SOURCE_GET_CLASS
-GST_TYPE_LFO_CONTROL_SOURCE
-GST_TYPE_LFO_WAVEFORM
-<SUBSECTION Private>
-gst_lfo_control_source_get_type
-gst_lfo_waveform_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gsttriggercontrolsource</FILE>
-<TITLE>GstTriggerControlSource</TITLE>
-<INCLUDE>gst/controller/controller.h</INCLUDE>
-GstTriggerControlSource
-gst_trigger_control_source_new
-GST_TYPE_TRIGGER_WAVEFORM
-<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
-
-<SECTION>
-<FILE>gstadapter</FILE>
-<TITLE>GstAdapter</TITLE>
-<INCLUDE>gst/base/base.h</INCLUDE>
-GstAdapter
-gst_adapter_new
-gst_adapter_clear
-gst_adapter_push
-gst_adapter_map
-gst_adapter_unmap
-gst_adapter_copy
-gst_adapter_copy_bytes
-gst_adapter_flush
-gst_adapter_available
-gst_adapter_available_fast
-gst_adapter_take
-gst_adapter_take_buffer
-gst_adapter_get_buffer
-gst_adapter_take_buffer_fast
-gst_adapter_get_buffer_fast
-gst_adapter_take_list
-gst_adapter_get_list
-gst_adapter_take_buffer_list
-gst_adapter_get_buffer_list
-gst_adapter_prev_pts
-gst_adapter_prev_dts
-gst_adapter_prev_pts_at_offset
-gst_adapter_prev_dts_at_offset
-gst_adapter_prev_offset
-gst_adapter_pts_at_discont
-gst_adapter_dts_at_discont
-gst_adapter_offset_at_discont
-gst_adapter_distance_from_discont
-gst_adapter_masked_scan_uint32
-gst_adapter_masked_scan_uint32_peek
-<SUBSECTION Standard>
-GstAdapterClass
-GstAdapterPrivate
-GST_ADAPTER
-GST_IS_ADAPTER
-GST_TYPE_ADAPTER
-GST_ADAPTER_CLASS
-GST_IS_ADAPTER_CLASS
-GST_ADAPTER_GET_CLASS
-<SUBSECTION Private>
-gst_adapter_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstaggregator</FILE>
-<TITLE>GstAggregator</TITLE>
-<INCLUDE>gst/base/base.h</INCLUDE>
-GstAggregator
-GstAggregatorClass
-GST_AGGREGATOR_FLOW_NEED_DATA
-GST_AGGREGATOR_SRC_PAD
-gst_aggregator_finish_buffer
-gst_aggregator_set_src_caps
-gst_aggregator_get_latency
-gst_aggregator_set_latency
-gst_aggregator_get_buffer_pool
-gst_aggregator_get_allocator
-gst_aggregator_simple_get_next_time
-<SUBSECTION Standard>
-GST_IS_AGGREGATOR
-GST_IS_AGGREGATOR_CLASS
-GST_TYPE_AGGREGATOR
-GST_AGGREGATOR
-GST_AGGREGATOR_CAST
-GST_AGGREGATOR_CLASS
-GST_AGGREGATOR_GET_CLASS
-gst_aggregator_get_type
-GstAggregatorPrivate
-</SECTION>
-
-<SECTION>
-<FILE>gstaggregatorpad</FILE>
-<TITLE>GstAggregatorPad</TITLE>
-GstAggregatorPad
-GstAggregatorPadClass
-gst_aggregator_pad_pop_buffer
-gst_aggregator_pad_peek_buffer
-gst_aggregator_pad_drop_buffer
-gst_aggregator_pad_is_eos
-gst_aggregator_pad_has_buffer
-<SUBSECTION Standard>
-GST_IS_AGGREGATOR_PAD
-GST_IS_AGGREGATOR_PAD_CLASS
-GST_TYPE_AGGREGATOR_PAD
-GstAggregatorPadPrivate
-GST_AGGREGATOR_PAD
-GST_AGGREGATOR_PAD_CAST
-GST_AGGREGATOR_PAD_CLASS
-GST_AGGREGATOR_PAD_GET_CLASS
-gst_aggregator_pad_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstbaseparse</FILE>
-<TITLE>GstBaseParse</TITLE>
-<INCLUDE>gst/base/base.h</INCLUDE>
-GstBaseParse
-GstBaseParseClass
-
-gst_base_parse_merge_tags
-gst_base_parse_set_duration
-gst_base_parse_set_average_bitrate
-gst_base_parse_set_min_frame_size
-gst_base_parse_set_passthrough
-gst_base_parse_set_syncable
-gst_base_parse_set_has_timing_info
-gst_base_parse_drain
-gst_base_parse_set_frame_rate
-gst_base_parse_set_latency
-gst_base_parse_set_infer_ts
-gst_base_parse_set_pts_interpolation
-gst_base_parse_set_ts_at_offset
-gst_base_parse_convert_default
-gst_base_parse_add_index_entry
-
-GstBaseParseFrame
-GstBaseParseFrameFlags
-gst_base_parse_frame_new
-gst_base_parse_frame_init
-gst_base_parse_frame_copy
-gst_base_parse_frame_free
-
-gst_base_parse_push_frame
-gst_base_parse_finish_frame
-
-GST_BASE_PARSE_DRAINING
-GST_BASE_PARSE_FLAG_DRAINING
-GST_BASE_PARSE_FLAG_LOST_SYNC
-GST_BASE_PARSE_FLOW_DROPPED
-GST_BASE_PARSE_LOST_SYNC
-GST_BASE_PARSE_SINK_PAD
-GST_BASE_PARSE_SRC_PAD
-<SUBSECTION Standard>
-GstBaseParsePrivate
-GST_BASE_PARSE
-GST_BASE_PARSE_CAST
-GST_IS_BASE_PARSE
-GST_TYPE_BASE_PARSE
-GST_BASE_PARSE_CLASS
-GST_IS_BASE_PARSE_CLASS
-GST_BASE_PARSE_GET_CLASS
-<SUBSECTION Private>
-gst_base_parse_get_type
-gst_base_parse_frame_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstbasesrc</FILE>
-<TITLE>GstBaseSrc</TITLE>
-<INCLUDE>gst/base/base.h</INCLUDE>
-GstBaseSrc
-GstBaseSrcClass
-GstBaseSrcFlags
-
-gst_base_src_wait_playing
-gst_base_src_start_wait
-gst_base_src_start_complete
-gst_base_src_is_live
-gst_base_src_set_live
-gst_base_src_set_format
-gst_base_src_query_latency
-gst_base_src_get_blocksize
-gst_base_src_set_blocksize
-gst_base_src_get_do_timestamp
-gst_base_src_set_do_timestamp
-gst_base_src_set_dynamic_size
-gst_base_src_set_automatic_eos
-gst_base_src_new_seamless_segment
-gst_base_src_set_caps
-gst_base_src_get_allocator
-gst_base_src_get_buffer_pool
-gst_base_src_is_async
-gst_base_src_set_async
-gst_base_src_submit_buffer_list
-
-GST_BASE_SRC_PAD
-GST_BASE_SRC_IS_STARTED
-GST_BASE_SRC_IS_STARTING
-<SUBSECTION Standard>
-GstBaseSrcPrivate
-GST_BASE_SRC
-GST_BASE_SRC_CAST
-GST_IS_BASE_SRC
-GST_TYPE_BASE_SRC
-GST_BASE_SRC_CLASS
-GST_IS_BASE_SRC_CLASS
-GST_BASE_SRC_GET_CLASS
-<SUBSECTION Private>
-gst_base_src_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstbasesink</FILE>
-<TITLE>GstBaseSink</TITLE>
-<INCLUDE>gst/base/base.h</INCLUDE>
-GstBaseSink
-GstBaseSinkClass
-
-gst_base_sink_query_latency
-gst_base_sink_get_latency
-gst_base_sink_do_preroll
-gst_base_sink_wait
-gst_base_sink_wait_preroll
-gst_base_sink_wait_clock
-gst_base_sink_set_sync
-gst_base_sink_get_sync
-gst_base_sink_set_max_lateness
-gst_base_sink_get_max_lateness
-gst_base_sink_set_qos_enabled
-gst_base_sink_is_qos_enabled
-gst_base_sink_set_async_enabled
-gst_base_sink_is_async_enabled
-gst_base_sink_set_ts_offset
-gst_base_sink_get_ts_offset
-gst_base_sink_set_render_delay
-gst_base_sink_get_render_delay
-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_set_max_bitrate
-gst_base_sink_get_max_bitrate
-gst_base_sink_set_last_sample_enabled
-gst_base_sink_is_last_sample_enabled
-gst_base_sink_get_drop_out_of_segment
-gst_base_sink_set_drop_out_of_segment
-
-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_TRYLOCK
-GST_BASE_SINK_PREROLL_UNLOCK
-GST_BASE_SINK_PREROLL_WAIT
-GST_BASE_SINK_PREROLL_WAIT_UNTIL
-
-<SUBSECTION Standard>
-GST_BASE_SINK
-GST_BASE_SINK_CAST
-GST_IS_BASE_SINK
-GST_TYPE_BASE_SINK
-GST_BASE_SINK_CLASS
-GST_IS_BASE_SINK_CLASS
-GST_BASE_SINK_GET_CLASS
-<SUBSECTION Private>
-GstBaseSinkPrivate
-gst_base_sink_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstbasetransform</FILE>
-<TITLE>GstBaseTransform</TITLE>
-<INCLUDE>gst/base/base.h</INCLUDE>
-GstBaseTransform
-GstBaseTransformClass
-
-gst_base_transform_is_passthrough
-gst_base_transform_set_passthrough
-gst_base_transform_set_prefer_passthrough
-gst_base_transform_is_in_place
-gst_base_transform_set_in_place
-gst_base_transform_is_qos_enabled
-gst_base_transform_set_qos_enabled
-gst_base_transform_update_qos
-gst_base_transform_set_gap_aware
-gst_base_transform_get_allocator
-gst_base_transform_get_buffer_pool
-gst_base_transform_reconfigure_sink
-gst_base_transform_reconfigure_src
-gst_base_transform_update_src_caps
-
-GST_BASE_TRANSFORM_SINK_NAME
-GST_BASE_TRANSFORM_SRC_NAME
-GST_BASE_TRANSFORM_SINK_PAD
-GST_BASE_TRANSFORM_SRC_PAD
-
-GST_BASE_TRANSFORM_FLOW_DROPPED
-
-<SUBSECTION Standard>
-GST_BASE_TRANSFORM
-GST_IS_BASE_TRANSFORM
-GST_TYPE_BASE_TRANSFORM
-GST_BASE_TRANSFORM_CLASS
-GST_IS_BASE_TRANSFORM_CLASS
-GST_BASE_TRANSFORM_GET_CLASS
-GST_BASE_TRANSFORM_CAST
-<SUBSECTION Private>
-GstBaseTransformPrivate
-gst_base_transform_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstbitreader</FILE>
-<TITLE>GstBitReader</TITLE>
-<INCLUDE>gst/base/base.h</INCLUDE>
-GstBitReader
-
-GST_BIT_READER_INIT
-
-gst_bit_reader_new
-gst_bit_reader_free
-
-gst_bit_reader_init
-
-gst_bit_reader_get_pos
-gst_bit_reader_get_remaining
-gst_bit_reader_set_pos
-gst_bit_reader_get_size
-gst_bit_reader_skip
-gst_bit_reader_skip_to_byte
-
-gst_bit_reader_get_bits_uint16
-gst_bit_reader_get_bits_uint32
-gst_bit_reader_get_bits_uint64
-gst_bit_reader_get_bits_uint8
-
-gst_bit_reader_peek_bits_uint16
-gst_bit_reader_peek_bits_uint32
-gst_bit_reader_peek_bits_uint64
-gst_bit_reader_peek_bits_uint8
-
-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
-
-<SUBSECTION Private>
-GST_BIT_READER
-</SECTION>
-
-<SECTION>
-<FILE>gstbitwriter</FILE>
-<TITLE>GstBitWriter</TITLE>
-<INCLUDE>gst/base/base.h</INCLUDE>
-GstBitWriter
-
-gst_bit_writer_new
-gst_bit_writer_new_with_size
-gst_bit_writer_new_with_data
-
-gst_bit_writer_free
-gst_bit_writer_free_and_get_buffer
-gst_bit_writer_free_and_get_data
-
-gst_bit_writer_init
-gst_bit_writer_init_with_size
-gst_bit_writer_init_with_data
-
-gst_bit_writer_reset
-gst_bit_writer_reset_and_get_buffer
-gst_bit_writer_reset_and_get_data
-
-gst_bit_writer_set_pos
-
-gst_bit_writer_get_size
-gst_bit_writer_get_data
-gst_bit_writer_get_remaining
-
-gst_bit_writer_get_size_unchecked
-gst_bit_writer_get_data_unchecked
-gst_bit_writer_set_pos_unchecked
-gst_bit_writer_get_remaining_unchecked
-
-gst_bit_writer_put_bits_uint16
-gst_bit_writer_put_bits_uint32
-gst_bit_writer_put_bits_uint64
-gst_bit_writer_put_bits_uint8
-gst_bit_writer_put_bytes
-
-gst_bit_writer_put_bits_uint16_unchecked
-gst_bit_writer_put_bits_uint32_unchecked
-gst_bit_writer_put_bits_uint64_unchecked
-gst_bit_writer_put_bits_uint8_unchecked
-gst_bit_writer_put_bytes_unchecked
-
-gst_bit_writer_align_bytes
-gst_bit_writer_align_bytes_unchecked
-
-<SUBSECTION Standard>
-GST_BIT_WRITER_BIT_SIZE
-GST_BIT_WRITER_DATA
-
-<SUBSECTION Private>
-GST_BIT_WRITER
-</SECTION>
-
-<SECTION>
-<FILE>gstbytereader</FILE>
-<TITLE>GstByteReader</TITLE>
-<INCLUDE>gst/base/base.h</INCLUDE>
-GstByteReader
-
-GST_BYTE_READER_INIT
-
-gst_byte_reader_new
-gst_byte_reader_free
-
-gst_byte_reader_init
-
-gst_byte_reader_peek_sub_reader
-gst_byte_reader_get_sub_reader
-
-gst_byte_reader_get_pos
-gst_byte_reader_get_remaining
-gst_byte_reader_set_pos
-gst_byte_reader_get_size
-gst_byte_reader_skip
-
-gst_byte_reader_get_int8
-gst_byte_reader_get_int16_be
-gst_byte_reader_get_int16_le
-gst_byte_reader_get_int24_be
-gst_byte_reader_get_int24_le
-gst_byte_reader_get_int32_be
-gst_byte_reader_get_int32_le
-gst_byte_reader_get_int64_be
-gst_byte_reader_get_int64_le
-
-gst_byte_reader_get_uint8
-gst_byte_reader_get_uint16_be
-gst_byte_reader_get_uint16_le
-gst_byte_reader_get_uint24_be
-gst_byte_reader_get_uint24_le
-gst_byte_reader_get_uint32_be
-gst_byte_reader_get_uint32_le
-gst_byte_reader_get_uint64_be
-gst_byte_reader_get_uint64_le
-
-gst_byte_reader_peek_int8
-gst_byte_reader_peek_int16_be
-gst_byte_reader_peek_int16_le
-gst_byte_reader_peek_int24_be
-gst_byte_reader_peek_int24_le
-gst_byte_reader_peek_int32_be
-gst_byte_reader_peek_int32_le
-gst_byte_reader_peek_int64_be
-gst_byte_reader_peek_int64_le
-
-gst_byte_reader_peek_uint8
-gst_byte_reader_peek_uint16_be
-gst_byte_reader_peek_uint16_le
-gst_byte_reader_peek_uint24_be
-gst_byte_reader_peek_uint24_le
-gst_byte_reader_peek_uint32_be
-gst_byte_reader_peek_uint32_le
-gst_byte_reader_peek_uint64_be
-gst_byte_reader_peek_uint64_le
-
-
-gst_byte_reader_get_float32_le
-gst_byte_reader_get_float32_be
-gst_byte_reader_get_float64_le
-gst_byte_reader_get_float64_be
-
-gst_byte_reader_peek_float32_le
-gst_byte_reader_peek_float32_be
-gst_byte_reader_peek_float64_le
-gst_byte_reader_peek_float64_be
-
-gst_byte_reader_get_data
-gst_byte_reader_dup_data
-gst_byte_reader_peek_data
-
-gst_byte_reader_masked_scan_uint32
-gst_byte_reader_masked_scan_uint32_peek
-
-gst_byte_reader_get_string
-gst_byte_reader_get_string_utf8
-
-gst_byte_reader_peek_string
-gst_byte_reader_peek_string_utf8
-
-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_skip_unchecked
-
-gst_byte_reader_get_int8_unchecked
-gst_byte_reader_get_int16_be_unchecked
-gst_byte_reader_get_int16_le_unchecked
-gst_byte_reader_get_int24_be_unchecked
-gst_byte_reader_get_int24_le_unchecked
-gst_byte_reader_get_int32_be_unchecked
-gst_byte_reader_get_int32_le_unchecked
-gst_byte_reader_get_int64_be_unchecked
-gst_byte_reader_get_int64_le_unchecked
-
-gst_byte_reader_get_uint8_unchecked
-gst_byte_reader_get_uint16_be_unchecked
-gst_byte_reader_get_uint16_le_unchecked
-gst_byte_reader_get_uint24_be_unchecked
-gst_byte_reader_get_uint24_le_unchecked
-gst_byte_reader_get_uint32_be_unchecked
-gst_byte_reader_get_uint32_le_unchecked
-gst_byte_reader_get_uint64_be_unchecked
-gst_byte_reader_get_uint64_le_unchecked
-
-gst_byte_reader_peek_int8_unchecked
-gst_byte_reader_peek_int16_be_unchecked
-gst_byte_reader_peek_int16_le_unchecked
-gst_byte_reader_peek_int24_be_unchecked
-gst_byte_reader_peek_int24_le_unchecked
-gst_byte_reader_peek_int32_be_unchecked
-gst_byte_reader_peek_int32_le_unchecked
-gst_byte_reader_peek_int64_be_unchecked
-gst_byte_reader_peek_int64_le_unchecked
-
-gst_byte_reader_peek_uint8_unchecked
-gst_byte_reader_peek_uint16_be_unchecked
-gst_byte_reader_peek_uint16_le_unchecked
-gst_byte_reader_peek_uint24_be_unchecked
-gst_byte_reader_peek_uint24_le_unchecked
-gst_byte_reader_peek_uint32_be_unchecked
-gst_byte_reader_peek_uint32_le_unchecked
-gst_byte_reader_peek_uint64_be_unchecked
-gst_byte_reader_peek_uint64_le_unchecked
-
-gst_byte_reader_get_float32_le_unchecked
-gst_byte_reader_get_float32_be_unchecked
-gst_byte_reader_get_float64_le_unchecked
-gst_byte_reader_get_float64_be_unchecked
-
-gst_byte_reader_peek_float32_le_unchecked
-gst_byte_reader_peek_float32_be_unchecked
-gst_byte_reader_peek_float64_le_unchecked
-gst_byte_reader_peek_float64_be_unchecked
-
-gst_byte_reader_dup_data_unchecked
-gst_byte_reader_get_data_unchecked
-gst_byte_reader_peek_data_unchecked
-
-<SUBSECTION Private>
-GST_BYTE_READER
-# seems to be a header parsing bug
-g_memdup
-</SECTION>
-
-<SECTION>
-<FILE>gstbytewriter</FILE>
-<TITLE>GstByteWriter</TITLE>
-<INCLUDE>gst/base/base.h</INCLUDE>
-GstByteWriter
-
-gst_byte_writer_new
-gst_byte_writer_new_with_data
-gst_byte_writer_new_with_size
-
-gst_byte_writer_init
-gst_byte_writer_init_with_data
-gst_byte_writer_init_with_size
-
-gst_byte_writer_free
-gst_byte_writer_free_and_get_buffer
-gst_byte_writer_free_and_get_data
-
-gst_byte_writer_reset
-gst_byte_writer_reset_and_get_data
-gst_byte_writer_reset_and_get_buffer
-
-gst_byte_writer_get_pos
-gst_byte_writer_set_pos
-gst_byte_writer_get_remaining
-gst_byte_writer_get_size
-gst_byte_writer_ensure_free_space
-
-gst_byte_writer_put_int8
-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_uint8
-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_float32_be
-gst_byte_writer_put_float32_le
-gst_byte_writer_put_float64_be
-gst_byte_writer_put_float64_le
-
-gst_byte_writer_put_string
-gst_byte_writer_put_string_utf16
-gst_byte_writer_put_string_utf32
-gst_byte_writer_put_string_utf8
-
-gst_byte_writer_put_data
-gst_byte_writer_fill
-
-gst_byte_writer_put_buffer
-gst_byte_writer_put_buffer_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_int24_le_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
-<SUBSECTION Private>
-GST_BYTE_WRITER
-</SECTION>
-
-<SECTION>
-<FILE>gstcollectpads</FILE>
-<TITLE>GstCollectPads</TITLE>
-<INCLUDE>gst/base/base.h</INCLUDE>
-GstCollectPads
-GstCollectData
-
-GstCollectDataDestroyNotify
-GstCollectPadsBufferFunction
-GstCollectPadsClipFunction
-GstCollectPadsCompareFunction
-GstCollectPadsEventFunction
-GstCollectPadsFlushFunction
-GstCollectPadsQueryFunction
-GstCollectPadsFunction
-GstCollectPadsStateFlags
-
-GST_COLLECT_PADS_STATE
-GST_COLLECT_PADS_STATE_IS_SET
-GST_COLLECT_PADS_STATE_SET
-GST_COLLECT_PADS_STATE_UNSET
-
-GST_COLLECT_PADS_GET_STREAM_LOCK
-GST_COLLECT_PADS_STREAM_LOCK
-GST_COLLECT_PADS_STREAM_UNLOCK
-
-GST_COLLECT_PADS_DTS
-GST_COLLECT_PADS_DTS_IS_VALID
-
-gst_collect_pads_new
-
-gst_collect_pads_add_pad
-gst_collect_pads_remove_pad
-
-gst_collect_pads_start
-gst_collect_pads_stop
-
-gst_collect_pads_available
-
-gst_collect_pads_flush
-gst_collect_pads_peek
-gst_collect_pads_pop
-
-gst_collect_pads_read_buffer
-gst_collect_pads_take_buffer
-
-gst_collect_pads_clip_running_time
-
-gst_collect_pads_query_default
-
-gst_collect_pads_event_default
-gst_collect_pads_src_event_default
-
-gst_collect_pads_set_buffer_function
-gst_collect_pads_set_clip_function
-gst_collect_pads_set_compare_function
-gst_collect_pads_set_event_function
-gst_collect_pads_set_flush_function
-gst_collect_pads_set_query_function
-gst_collect_pads_set_flushing
-gst_collect_pads_set_function
-gst_collect_pads_set_waiting
-<SUBSECTION Standard>
-GstCollectPadsClass
-GstCollectPadsPrivate
-GstCollectDataPrivate
-GST_COLLECT_PADS
-GST_COLLECT_PADS_CLASS
-GST_TYPE_COLLECT_PADS
-GST_IS_COLLECT_PADS
-GST_IS_COLLECT_PADS_CLASS
-GST_COLLECT_PADS_GET_CLASS
-gst_collect_pads_get_type
-<SUBSECTION Private>
-</SECTION>
-
-<SECTION>
-<FILE>gstflowcombiner</FILE>
-<TITLE>GstFlowCombiner</TITLE>
-<INCLUDE>gst/base/base.h</INCLUDE>
-GstFlowCombiner
-gst_flow_combiner_new
-gst_flow_combiner_free
-gst_flow_combiner_ref
-gst_flow_combiner_unref
-gst_flow_combiner_update_flow
-gst_flow_combiner_add_pad
-gst_flow_combiner_remove_pad
-gst_flow_combiner_clear
-gst_flow_combiner_reset
-gst_flow_combiner_update_pad_flow
-<SUBSECTION Standard>
-GST_TYPE_FLOW_COMBINER
-<SUBSECTION Private>
-gst_flow_combiner_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstpushsrc</FILE>
-<TITLE>GstPushSrc</TITLE>
-<INCLUDE>gst/base/base.h</INCLUDE>
-GstPushSrc
-GstPushSrcClass
-<SUBSECTION Standard>
-GST_PUSH_SRC
-GST_IS_PUSH_SRC
-GST_TYPE_PUSH_SRC
-GST_PUSH_SRC_CLASS
-GST_IS_PUSH_SRC_CLASS
-GST_PUSH_SRC_GET_CLASS
-<SUBSECTION Private>
-gst_push_src_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gsttypefindhelper</FILE>
-<TITLE>GstTypeFindHelper</TITLE>
-<INCLUDE>gst/base/base.h</INCLUDE>
-gst_type_find_helper
-gst_type_find_helper_for_buffer
-gst_type_find_helper_for_buffer_with_extension
-gst_type_find_helper_for_extension
-gst_type_find_helper_for_data
-gst_type_find_helper_for_data_with_extension
-GstTypeFindHelperGetRangeFunction
-gst_type_find_helper_get_range
-<SUBSECTION Private>
-</SECTION>
-
-<SECTION>
-<FILE>gstdataqueue</FILE>
-<TITLE>GstDataQueue</TITLE>
-<INCLUDE>gst/base/base.h</INCLUDE>
-GstDataQueue
-GstDataQueueSize
-GstDataQueueCheckFullFunction
-GstDataQueueItem
-GstDataQueueEmptyCallback
-GstDataQueueFullCallback
-gst_data_queue_new
-gst_data_queue_push
-gst_data_queue_push_force
-gst_data_queue_pop
-gst_data_queue_peek
-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
-GstDataQueuePrivate
-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>
-
-<SECTION>
-<FILE>gstqueuearray</FILE>
-<TITLE>GstQueueArray</TITLE>
-<INCLUDE>gst/base/base.h</INCLUDE>
-GstQueueArray
-gst_queue_array_new
-gst_queue_array_free
-gst_queue_array_set_clear_func
-gst_queue_array_clear
-gst_queue_array_get_length
-gst_queue_array_pop_head
-gst_queue_array_peek_head
-gst_queue_array_peek_nth
-gst_queue_array_push_tail
-gst_queue_array_pop_tail
-gst_queue_array_peek_tail
-gst_queue_array_is_empty
-gst_queue_array_drop_element
-gst_queue_array_find
-gst_queue_array_new_for_struct
-gst_queue_array_push_tail_struct
-gst_queue_array_peek_head_struct
-gst_queue_array_peek_nth_struct
-gst_queue_array_pop_head_struct
-gst_queue_array_peek_tail_struct
-gst_queue_array_pop_tail_struct
-gst_queue_array_drop_struct
-</SECTION>
-
-# net
-
-<SECTION>
-<FILE>gstnetaddressmeta</FILE>
-<TITLE>GstNetAddressMeta</TITLE>
-<INCLUDE>gst/net/net.h</INCLUDE>
-GstNetAddressMeta
-gst_buffer_add_net_address_meta
-gst_buffer_get_net_address_meta
-gst_net_address_meta_get_info
-<SUBSECTION Standard>
-GST_NET_ADDRESS_META_API_TYPE
-GST_NET_ADDRESS_META_INFO
-<SUBSECTION Private>
-gst_net_address_meta_api_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstnetcontrolmessagemeta</FILE>
-<TITLE>GstNetControlMessageMeta</TITLE>
-<INCLUDE>gst/net/net.h</INCLUDE>
-GstNetControlMessageMeta
-gst_buffer_add_net_control_message_meta
-gst_buffer_get_net_control_message_meta
-gst_net_control_message_meta_get_info
-<SUBSECTION Standard>
-GST_NET_CONTROL_MESSAGE_META_API_TYPE
-GST_NET_CONTROL_MESSAGE_META_INFO
-<SUBSECTION Private>
-gst_net_control_message_meta_api_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstnetclientclock</FILE>
-<TITLE>GstNetClientClock</TITLE>
-<INCLUDE>gst/net/net.h</INCLUDE>
-GstNetClientClock
-GstNtpClock
-gst_net_client_clock_new
-gst_ntp_clock_new
-<SUBSECTION Standard>
-GstNetClientClockClass
-GstNetClientClockPrivate
-GST_NET_CLIENT_CLOCK
-GST_IS_NET_CLIENT_CLOCK
-GST_TYPE_NET_CLIENT_CLOCK
-GST_NET_CLIENT_CLOCK_CLASS
-GST_IS_NET_CLIENT_CLOCK_CLASS
-GstNtpClockClass
-GST_NTP_CLOCK
-GST_IS_NTP_CLOCK
-GST_TYPE_NTP_CLOCK
-GST_NTP_CLOCK_CLASS
-GST_IS_NTP_CLOCK_CLASS
-<SUBSECTION Private>
-gst_net_client_clock_get_type
-gst_ntp_clock_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstnettimepacket</FILE>
-<TITLE>GstNetTimePacket</TITLE>
-<INCLUDE>gst/net/net.h</INCLUDE>
-GstNetTimePacket
-GST_NET_TIME_PACKET_SIZE
-gst_net_time_packet_new
-gst_net_time_packet_copy
-gst_net_time_packet_free
-gst_net_time_packet_receive
-gst_net_time_packet_send
-gst_net_time_packet_serialize
-<SUBSECTION Standard>
-<SUBSECTION Private>
-gst_net_time_packet_get_type
-socklen_t
-</SECTION>
-
-
-<SECTION>
-<FILE>gstnettimeprovider</FILE>
-<TITLE>GstNetTimeProvider</TITLE>
-<INCLUDE>gst/net/net.h</INCLUDE>
-GstNetTimeProvider
-gst_net_time_provider_new
-<SUBSECTION Standard>
-GstNetTimeProviderClass
-GstNetTimeProviderPrivate
-GST_NET_TIME_PROVIDER
-GST_IS_NET_TIME_PROVIDER
-GST_TYPE_NET_TIME_PROVIDER
-GST_NET_TIME_PROVIDER_CLASS
-GST_IS_NET_TIME_PROVIDER_CLASS
-<SUBSECTION Private>
-gst_net_time_provider_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstptpclock</FILE>
-<TITLE>GstPtpClock</TITLE>
-<INCLUDE>gst/net/net.h</INCLUDE>
-GST_PTP_CLOCK_ID_NONE
-
-gst_ptp_init
-gst_ptp_deinit
-gst_ptp_is_initialized
-gst_ptp_is_supported
-
-GstPtpClock
-gst_ptp_clock_new
-
-GstPtpStatisticsCallback
-gst_ptp_statistics_callback_add
-gst_ptp_statistics_callback_remove
-
-GST_PTP_STATISTICS_BEST_MASTER_CLOCK_SELECTED
-GST_PTP_STATISTICS_NEW_DOMAIN_FOUND
-GST_PTP_STATISTICS_PATH_DELAY_MEASURED
-GST_PTP_STATISTICS_TIME_UPDATED
-<SUBSECTION Standard>
-GstPtpClockClass
-GstPtpClockPrivate
-GST_PTP_CLOCK
-GST_IS_PTP_CLOCK
-GST_TYPE_PTP_CLOCK
-GST_PTP_CLOCK_CLASS
-GST_IS_PTP_CLOCK_CLASS
-<SUBSECTION Private>
-gst_ptp_clock_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstcheck</FILE>
-<TITLE>GstCheck</TITLE>
-<INCLUDE>gst/check/check.h</INCLUDE>
-GST_START_TEST
-GST_END_TEST
-
-ASSERT_BUFFER_REFCOUNT
-ASSERT_CAPS_REFCOUNT
-ASSERT_CRITICAL
-ASSERT_WARNING
-ASSERT_MINI_OBJECT_REFCOUNT
-ASSERT_OBJECT_REFCOUNT
-ASSERT_OBJECT_REFCOUNT_BETWEEN
-ASSERT_SET_STATE
-
-fail_unless_equals_int
-fail_unless_equals_float
-fail_unless_equals_string
-fail_unless_equals_uint64
-fail_unless_equals_int64
-fail_unless_equals_int_hex
-fail_unless_equals_int64_hex
-fail_unless_equals_uint64_hex
-fail_unless_equals_pointer
-
-fail_unless_message_error
-
-assert_equals_int
-assert_equals_float
-assert_equals_string
-assert_equals_uint64
-assert_equals_int64
-assert_equals_int_hex
-assert_equals_int64_hex
-assert_equals_uint64_hex
-assert_equals_pointer
-assert_message_error
-
-gst_check_init
-gst_check_message_error
-gst_check_setup_element
-gst_check_setup_sink_pad
-gst_check_setup_src_pad
-gst_check_setup_sink_pad_by_name
-gst_check_setup_src_pad_by_name
-gst_check_teardown_pad_by_name
-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
-gst_check_run_suite
-gst_check_setup_events
-gst_check_setup_events_with_stream_id
-gst_check_setup_sink_pad_by_name_from_template
-gst_check_setup_sink_pad_from_template
-gst_check_setup_src_pad_by_name_from_template
-gst_check_setup_src_pad_from_template
-gst_check_objects_destroyed_on_unref
-gst_check_object_destroyed_on_unref
-
-<SUBSECTION log-filter>
-GstCheckLogFilter
-GstCheckLogFilterFunc
-gst_check_add_log_filter
-gst_check_clear_log_filter
-gst_check_remove_log_filter
-
-
-<SUBSECTION Private>
-MAIN_INIT
-MAIN_START_THREADS
-MAIN_START_THREAD_FUNCTION
-MAIN_START_THREAD_FUNCTIONS
-MAIN_STOP_THREADS
-MAIN_SYNCHRONIZE
-THREAD_START
-THREAD_STARTED
-THREAD_SWITCH
-THREAD_SYNCHRONIZE
-THREAD_TEST_RUNNING
-
-sync_cond
-mutex
-GST_CAT_DEFAULT
-thread_list
-start_cond
-GST_CHECK_MAIN
-
-gst_check_chain_func
-gst_check_abi_list
-tcase_skip_broken_loop_test
-tcase_skip_broken_test
-
-buffers
-check_cond
-check_mutex
-
-END_TEST
-START_TEST
-</SECTION>
-
-<SECTION>
-<FILE>gstcheckbufferstraw</FILE>
-<TITLE>GstBufferStraw</TITLE>
-<INCLUDE>gst/check/check.h</INCLUDE>
-gst_buffer_straw_start_pipeline
-gst_buffer_straw_get_buffer
-gst_buffer_straw_stop_pipeline
-</SECTION>
-
-<SECTION>
-<FILE>gstcheckconsistencychecker</FILE>
-<TITLE>GstStreamConsistency</TITLE>
-<INCLUDE>gst/check/check.h</INCLUDE>
-GstStreamConsistency
-gst_consistency_checker_new
-gst_consistency_checker_reset
-gst_consistency_checker_free
-gst_consistency_checker_add_pad
-</SECTION>
-
-<SECTION>
-<FILE>gstharness</FILE>
-<TITLE>GstHarness</TITLE>
-<INCLUDE>gst/check/check.h</INCLUDE>
-GstHarness
-
-gst_harness_new_empty
-gst_harness_new_full
-gst_harness_new_with_element
-gst_harness_new_with_padnames
-gst_harness_new_with_templates
-gst_harness_new
-gst_harness_new_parse
-gst_harness_add_element_full
-gst_harness_add_parse
-gst_harness_teardown
-
-gst_harness_add_element_src_pad
-gst_harness_add_element_sink_pad
-
-gst_harness_set_src_caps
-gst_harness_set_sink_caps
-gst_harness_set_caps
-gst_harness_set_src_caps_str
-gst_harness_set_sink_caps_str
-gst_harness_set_caps_str
-
-gst_harness_use_systemclock
-gst_harness_use_testclock
-gst_harness_get_testclock
-gst_harness_set_time
-gst_harness_wait_for_clock_id_waits
-gst_harness_crank_single_clock_wait
-gst_harness_crank_multiple_clock_waits
-
-gst_harness_play
-gst_harness_set_blocking_push_mode
-gst_harness_set_forwarding
-
-gst_harness_create_buffer
-gst_harness_push
-gst_harness_pull
-gst_harness_try_pull
-gst_harness_push_and_pull
-gst_harness_buffers_received
-gst_harness_buffers_in_queue
-gst_harness_set_drop_buffers
-gst_harness_dump_to_file
-gst_harness_take_all_data
-gst_harness_take_all_data_as_buffer
-gst_harness_take_all_data_as_bytes
-gst_harness_get_last_pushed_timestamp
-
-gst_harness_push_event
-gst_harness_pull_event
-gst_harness_try_pull_event
-gst_harness_events_received
-gst_harness_events_in_queue
-
-gst_harness_push_upstream_event
-gst_harness_pull_upstream_event
-gst_harness_try_pull_upstream_event
-gst_harness_upstream_events_received
-gst_harness_upstream_events_in_queue
-
-gst_harness_query_latency
-gst_harness_set_upstream_latency
-
-gst_harness_set_propose_allocator
-gst_harness_get_allocator
-
-gst_harness_add_propose_allocation_meta
-
-gst_harness_add_src
-gst_harness_add_src_harness
-gst_harness_add_src_parse
-gst_harness_push_from_src
-gst_harness_src_crank_and_push_many
-gst_harness_src_push_event
-
-gst_harness_add_sink
-gst_harness_add_sink_harness
-gst_harness_add_sink_parse
-gst_harness_push_to_sink
-gst_harness_sink_push_many
-
-gst_harness_find_element
-gst_harness_set
-gst_harness_get
-gst_harness_add_probe
-
-GstHarnessThread
-
-gst_harness_stress_thread_stop
-gst_harness_stress_custom_start
-
-gst_harness_stress_statechange_start
-gst_harness_stress_statechange_start_full
-
-gst_harness_stress_push_buffer_start
-gst_harness_stress_push_buffer_start_full
-
-GstHarnessPrepareBufferFunc
-gst_harness_stress_push_buffer_with_cb_start
-gst_harness_stress_push_buffer_with_cb_start_full
-
-gst_harness_stress_push_event_start
-gst_harness_stress_push_event_start_full
-
-GstHarnessPrepareEventFunc
-gst_harness_stress_push_event_with_cb_start
-gst_harness_stress_push_event_with_cb_start_full
-
-gst_harness_stress_send_upstream_event_start
-gst_harness_stress_push_upstream_event_start_full
-
-gst_harness_stress_send_upstream_event_with_cb_start
-gst_harness_stress_push_upstream_event_with_cb_start_full
-
-gst_harness_stress_property_start
-gst_harness_stress_property_start_full
-
-gst_harness_stress_requestpad_start
-gst_harness_stress_requestpad_start_full
-<SUBSECTION Standard>
-GstHarnessPrivate
-</SECTION>
-
-<SECTION>
-<FILE>gsttestclock</FILE>
-<TITLE>GstTestClock</TITLE>
-<INCLUDE>gst/check/check.h</INCLUDE>
-GstTestClock
-GstTestClockClass
-gst_test_clock_new
-gst_test_clock_new_with_start_time
-gst_test_clock_set_time
-gst_test_clock_advance_time
-gst_test_clock_peek_id_count
-gst_test_clock_has_id
-gst_test_clock_peek_next_pending_id
-gst_test_clock_wait_for_next_pending_id
-gst_test_clock_wait_for_pending_id_count
-gst_test_clock_process_next_clock_id
-gst_test_clock_get_next_entry_time
-gst_test_clock_wait_for_multiple_pending_ids
-gst_test_clock_id_list_get_latest_time
-gst_test_clock_timed_wait_for_multiple_pending_ids
-gst_test_clock_process_id_list
-gst_test_clock_crank
-<SUBSECTION Standard>
-GST_TEST_CLOCK
-GST_IS_TEST_CLOCK
-GST_TYPE_TEST_CLOCK
-GST_TEST_CLOCK_CLASS
-GST_IS_TEST_CLOCK_CLASS
-GST_TEST_CLOCK_GET_CLASS
-GST_TEST_CLOCK_CAST
-<SUBSECTION Private>
-GstTestClockPrivate
-gst_test_clock_get_type
-</SECTION>
diff --git a/docs/libs/gstreamer-libs.types b/docs/libs/gstreamer-libs.types
deleted file mode 100644 (file)
index c68cf9e..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#include <gst/gst.h>
-
-% base classes
-
-#include <gst/base/gstadapter.h>
-#include <gst/base/gstaggregator.h>
-#include <gst/base/gstbaseparse.h>
-#include <gst/base/gstbasesrc.h>
-#include <gst/base/gstbasesink.h>
-#include <gst/base/gstbasetransform.h>
-#include <gst/base/gstcollectpads.h>
-#include <gst/base/gstpushsrc.h>
-
-gst_adapter_get_type
-gst_aggregator_get_type
-gst_aggregator_pad_get_type
-gst_base_parse_get_type
-gst_base_src_get_type
-gst_base_sink_get_type
-gst_base_transform_get_type
-gst_collect_pads_get_type
-gst_push_src_get_type
-
-% controller
-
-#include <gst/controller/gstargbcontrolbinding.h>
-#include <gst/controller/gstdirectcontrolbinding.h>
-#include <gst/controller/gsttimedvaluecontrolsource.h>
-#include <gst/controller/gstinterpolationcontrolsource.h>
-#include <gst/controller/gstlfocontrolsource.h>
-#include <gst/controller/gsttriggercontrolsource.h>
-
-gst_argb_control_binding_get_type
-gst_direct_control_binding_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
-
-#include <gst/net/net.h>
-
-gst_net_client_clock_get_type
-gst_net_time_provider_get_type
-gst_ntp_clock_get_type
-gst_ptp_clock_get_type
-
-% check
-
-#include <gst/check/gsttestclock.h>
-
-gst_test_clock_get_type
diff --git a/docs/libs/index.md b/docs/libs/index.md
new file mode 100644 (file)
index 0000000..c51c1e8
--- /dev/null
@@ -0,0 +1 @@
+# GStreamer core libraries API
diff --git a/docs/libs/meson.build b/docs/libs/meson.build
deleted file mode 100644 (file)
index f46be82..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-types = configure_file(input : 'gstreamer-libs.types',
-  output : 'gstreamer-libs.types',
-  copy: true)
-
-gnome.gtkdoc('gstreamer-libs',
-  main_sgml : 'gstreamer-libs-docs.sgml',
-  src_dir : '@0@/../../libs/gst'.format(meson.current_source_dir()),
-  scan_args : ['--deprecated-guards=GST_DISABLE_DEPRECATED',
-            '--ignore-decorators=GST_API|GST_BASE_API|GST_CHECK_API|GST_CONTROLLER_API|GST_NET_API',
-            '--ignore-headers=gettext.h glib-compat-private.h glib-compat.h gst-i18n-app.h gst-i18n-lib.h gst_private.h gstelementdetails.h gstmacros.h grammar.tab.h grammar.tab.pre.h math-compat.h types.h'
-            ],
-  scanobjs_args : ['--type-init-func="gst_init(NULL,NULL)"'],
-  gobject_typesfile : types,
-  content_files : [version_entities],
-  dependencies : [gst_base_dep, gst_check_dep,  gst_controller_dep, gst_net_dep],
-  install : true)
diff --git a/docs/libs/net/index.md b/docs/libs/net/index.md
new file mode 100644 (file)
index 0000000..3e1b04e
--- /dev/null
@@ -0,0 +1,3 @@
+# Network Classes
+
+`gstreamer-net-1.0` provides network elements and objects.
diff --git a/docs/libs/net/sitemap.txt b/docs/libs/net/sitemap.txt
new file mode 100644 (file)
index 0000000..4f91fcd
--- /dev/null
@@ -0,0 +1 @@
+gi-index
diff --git a/docs/list-ulink.xsl b/docs/list-ulink.xsl
deleted file mode 100644 (file)
index 969b5b7..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version='1.0'?>
-<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
-  <xsl:output method='text'/>
-  <xsl:template xmlns:xi='http://www.w3.org/2003/XInclude' match='ulink'>
-    <xsl:value-of select='@url'/><xsl:text>&#xa;</xsl:text>
-  </xsl:template>
-  <xsl:template match='text()|@*'/>
-</xsl:stylesheet>
index 6b6a479..e1aecb5 100644 (file)
-docconf = configuration_data()
+build_hotdoc = false
+if meson.is_cross_build()
+    if get_option('doc').enabled()
+        error('Documentation enabled but building the doc while cross building is not supported yet.')
+    endif
+
+    message('Documentation not built as building it while cross building is not supported yet.')
+    subdir_done()
+endif
+
+hotdoc_plugin_scanner = executable('gst-hotdoc-plugins-scanner',
+  'gst-hotdoc-plugins-scanner.c',
+  c_args : gst_c_args,
+  include_directories : [configinc],
+  dependencies : [gobject_dep, gmodule_dep, glib_dep, gio_dep, gst_dep],
+  install_dir : helpers_install_dir,
+  link_with: [printf_lib],
+  install: true,
+)
+
+configure_file(
+    input: 'gst-plugins-doc-cache-generator.py',
+    output: 'gst-plugins-doc-cache-generator',
+    install_dir: helpers_install_dir,
+    copy: true
+)
+
+plugins_cache_generator = find_program(join_paths(meson.current_build_dir(), 'gst-plugins-doc-cache-generator'))
+plugins_cache = join_paths(meson.current_source_dir(), 'plugins', 'gst_plugins_cache.json')
+plugins_doc_dep = custom_target('build-doc-cache',
+    command: [plugins_cache_generator, plugins_cache, '@OUTPUT@', '@INPUT@'],
+    input: plugins,
+    output: 'gst_plugins_cache.json',
+    depends: [hotdoc_plugin_scanner],
+    build_always_stale: true,
+)
+
+hotdoc_p = find_program('hotdoc', required: get_option('doc'))
+if not hotdoc_p.found()
+    message('Hotdoc not found, not building the documentation')
+    subdir_done()
+endif
+
+hotdoc_req = '>= 0.11.0'
+hotdoc_version = run_command(hotdoc_p, '--version').stdout()
+if not hotdoc_version.version_compare(hotdoc_req)
+    if get_option('doc').enabled()
+        error('Hotdoc version @0@ not found, got @1@'.format(hotdoc_req, hotdoc_version))
+    else
+        message('Hotdoc version @0@ not found, got @1@'.format(hotdoc_req, hotdoc_version))
+        subdir_done()
+    endif
+endif
+
+hotdoc = import('hotdoc')
+required_hotdoc_extensions = ['gi-extension', 'gst-extension']
+foreach extension: required_hotdoc_extensions
+    if not hotdoc.has_extensions(extension)
+        if get_option('doc').enabled()
+            error('Documentation enabled but @0@ missing'.format(extension))
+        endif
+
+        message('@0@ extension not found, not building documentation'.format(extension))
+        subdir_done()
+    endif
+endforeach
+
 
+if not build_gir
+    if get_option('doc').enabled()
+        error('Documentation enabled but introspection not built.')
+    endif
+
+    message('Introspection not built, can\'t build the documentation')
+    subdir_done()
+endif
+
+all_plugins_paths = []
+foreach l: plugins
+    all_plugins_paths += l.full_path()
+endforeach
+
+build_hotdoc = true
+docconf = configuration_data()
 docconf.set('GST_API_VERSION', apiversion)
-docconf.set('PACKAGE_VERSION', gst_version)
-docconf.set('PLUGINDIR', '@0@/lib/gstreamer-1.0'.format(get_option('prefix')))
 
-version_entities = configure_file(input : 'version.entities.in',
-  output : 'version.entities',
-  configuration : docconf)
+version_entities = configure_file(input : 'version.in',
+    output : 'gst_api_version.md',
+    configuration : docconf)
+
+gst_excludes = []
+foreach h: ['gettext.h', 'glib-compat-private.h', 'glib-compat.h',
+            'gst-i18n-app.h', 'gst-i18n-lib.h', 'gst_private.h',
+            'gstelementdetails.h', 'gstmacros.h', 'gstmarshal.h',
+            'math-compat.h', 'parse/grammar.tab.h',
+            '../libs/gst/base/gstindex.h',
+            '../libs/gst/base/gstindex.c',
+            '../libs/gst/check/internal-check.h',
+            'parser/grammar.tab.pre.h', 'parse/parse_lex.h', 'types.h',
+            'gst-printf.h', 'printf-args.h', 'printf-extension.h',
+            'printf-parse.h', 'vasnprintf.h', 'gstregistrybinary.c',
+            'gstregistrybinary.h', 'gstpluginloader.h', 'gstpluginloader.c']
+    gst_excludes += [join_paths(meson.current_source_dir(), '..', 'gst', h)]
+endforeach
+
+libs_doc = [hotdoc.generate_doc('gstreamer',
+    project_version: apiversion,
+    gi_c_sources: '../gst/*.[hc]',
+    gi_sources: [gst_gir[0].full_path()],
+    gi_c_source_filters: gst_excludes,
+    sitemap: 'gst/sitemap.txt',
+    index: 'gst/index.md',
+    gi_index: 'gst/gi-index.md',
+    gi_smart_index: true,
+    gi_c_source_roots: [join_paths(meson.current_source_dir(), '../gst/'), ],
+    dependencies: [gst_dep, glib_dep, gobject_dep, gmodule_dep, hotdoc_plugin_scanner],
+    extra_assets: [join_paths(meson.current_source_dir(), 'images')],
+)]
+
+libs = [
+  ['base', gst_base_gir, gst_base_dep],
+  ['controller', gst_controller_gir, gst_controller_dep,],
+  ['net', gst_net_gir, gst_net_dep],
+  ['check', gst_check_gir, gst_check_dep],
+]
+
+foreach lib: libs
+  name = lib[0]
+  gir = lib[1]
+  deps = [lib[2], gir]
+  libs_doc += [hotdoc.generate_doc(name,
+      project_version: apiversion,
+      gi_c_sources: ['../libs/gst/' + name + '/*.[hc]'],
+      gi_c_source_filters: gst_excludes,
+      gi_sources: gir[0].full_path(),
+      gi_c_source_roots: [join_paths(meson.current_source_dir(), '../libs/gst/' + name), ],
+      sitemap: join_paths('libs', name, 'sitemap.txt'),
+      index: join_paths('libs/', name, 'index.md'),
+      gi_index: join_paths('libs/', name, 'index.md'),
+      gi_smart_index: true,
+      gi_order_generated_subpages: true,
+      dependencies: deps + [hotdoc_plugin_scanner],
+      install: false,
+  )]
+endforeach
+
+plugins_doc = [
+    hotdoc.generate_doc('coreelements',
+        project_version: apiversion,
+        sitemap: 'plugins/sitemap.txt',
+        index: 'plugins/index.md',
+        gst_index: 'plugins/index.md',
+        gst_smart_index: true,
+        gst_c_sources: ['../plugins/elements/*.c', '../plugins/elements/*.h'],
+        dependencies: [plugins_doc_dep],
+        gst_cache_file: plugins_cache,
+        gst_plugin_name: 'coreelements',
+    ),
+    hotdoc.generate_doc('coretracers',
+        project_version: apiversion,
+        sitemap: 'plugins/sitemap.txt',
+        index: 'plugins/blank.md',
+        gst_index: 'plugins/blank.md',
+        gst_smart_index: true,
+        gst_c_sources: ['../plugins/tracers/*.c', '../plugins/tracers/*.h'],
+        dependencies: [plugins_doc_dep],
+        gst_cache_file: plugins_cache,
+        gst_plugin_name: 'coretracers',
+    )
 
-subdir('gst')
-subdir('libs')
+]
diff --git a/docs/plugins/.gitignore b/docs/plugins/.gitignore
deleted file mode 100644 (file)
index 9272d59..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-gstreamer-plugins-decl-list.txt
-gstreamer-plugins-decl.txt
-gstreamer-plugins-overrides.txt
-gstreamer-plugins-undocumented.txt
-gstreamer-plugins.args.new
-gstreamer-plugins.signals.new
-gstreamer-plugins-unused.txt
-gstreamer-plugins-undeclared.txt
-html
-html-build.stamp
-html.stamp
-scan-build.stamp
-sgml-build.stamp
-sgml.stamp
-tmpl
-tmpl-build.stamp
-tmpl.stamp
-xml
-inspect-registry.*
-gstreamer-plugins*.bak
diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am
deleted file mode 100644 (file)
index 8f41089..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-GST_DOC_SCANOBJ = $(top_srcdir)/common/gstdoc-scangobj
-
-## Process this file with automake to produce Makefile.in
-
-# The name of the module, e.g. 'glib'.
-#DOC_MODULE=gst-plugins-libs-@GST_API_VERSION@
-MODULE=gstreamer
-DOC_MODULE=$(MODULE)-plugins
-
-# for upload-doc.mak
-DOC=$(MODULE)-plugins
-FORMATS=html
-html: html-build.stamp
-include $(top_srcdir)/common/upload-doc.mak
-
-# Extra environment needed for Core only...
-INSPECT_EXTRA_ENVIRONMENT= \
-    GST_PLUGIN_SCANNER_1_0=$(top_builddir)/libs/gst/helpers/gst-plugin-scanner
-
-# The top-level SGML file. Change it if you want.
-DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
-
-# The directory containing the source code.
-# gtk-doc will search all .c & .h files beneath here for inline comments
-# documenting functions and macros.
-DOC_SOURCE_DIR = $(top_srcdir)/plugins/elements $(top_srcdir)/plugins/tracers
-
-# Extra options to supply to gtkdoc-scan.
-SCAN_OPTIONS=
-
-# Extra options to supply to gtkdoc-mkdb.
-MKDB_OPTIONS=--sgml-mode
-
-# Extra options to supply to gtkdoc-fixref.
-FIXXREF_OPTIONS=--extra-dir=$(top_builddir)/docs/gst/html \
-       --extra-dir=$(top_builddir)/docs/libs/html \
-       --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \
-       --extra-dir=$(datadir)/gtk-doc/html
-
-# Used for dependencies.
-HFILE_GLOB=$(top_srcdir)/plugins/elements/*.h $(top_srcdir)/plugins/tracers/*.h
-CFILE_GLOB=$(top_srcdir)/plugins/elements/*.c $(top_srcdir)/plugins/tracers/*.c
-
-# Header files to ignore when scanning.
-IGNORE_HFILES =
-IGNORE_CFILES =
-
-# we add all .h files of elements that have signals/args we want
-# sadly this also pulls in the private methods - maybe we should
-# move those around in the source ?
-# also, we should add some stuff here conditionally based on whether
-# or not the plugin will actually build
-# but I'm not sure about that - it might be this Just Works given that
-# the registry won't have the element
-
-EXTRA_HFILES = \
-       $(top_srcdir)/plugins/elements/gstcapsfilter.h \
-       $(top_srcdir)/plugins/elements/gstdataurisrc.h \
-       $(top_srcdir)/plugins/elements/gstdownloadbuffer.h \
-       $(top_srcdir)/plugins/elements/gstfakesrc.h \
-       $(top_srcdir)/plugins/elements/gstfakesink.h \
-       $(top_srcdir)/plugins/elements/gstfdsink.h \
-       $(top_srcdir)/plugins/elements/gstfdsrc.h \
-       $(top_srcdir)/plugins/elements/gstfilesrc.h \
-       $(top_srcdir)/plugins/elements/gstfilesink.h \
-       $(top_srcdir)/plugins/elements/gstidentity.h \
-       $(top_srcdir)/plugins/elements/gstinputselector.h \
-       $(top_srcdir)/plugins/elements/gstmultiqueue.h \
-       $(top_srcdir)/plugins/elements/gstoutputselector.h \
-       $(top_srcdir)/plugins/elements/gstqueue.h \
-       $(top_srcdir)/plugins/elements/gstqueue2.h \
-       $(top_srcdir)/plugins/elements/gsttypefindelement.h \
-       $(top_srcdir)/plugins/elements/gsttee.h \
-       $(top_srcdir)/plugins/elements/gstvalve.h
-
-# Images to copy into HTML directory.
-HTML_IMAGES =
-
-# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
-content_files =
-
-# Other files to distribute.
-extra_files =
-
-# CFLAGS and LDFLAGS for compiling scan program. Only needed if your app/lib
-# contains GtkObjects/GObjects and you want to document signals and properties.
-GTKDOC_CFLAGS = $(GST_OBJ_CFLAGS) -I$(top_builddir) -I$(top_builddir)/libs
-GTKDOC_LIBS = $(GST_OBJ_LIBS)
-
-# If you need to override some of the declarations, place them in this file
-# and uncomment this line.
-#DOC_OVERRIDES = $(DOC_MODULE)-overrides.txt
-DOC_OVERRIDES =
-
-include $(top_srcdir)/common/gtk-doc-plugins.mak
similarity index 100%
rename from docs/random/.gitignore
rename to docs/plugins/blank.md
diff --git a/docs/plugins/gst_plugins_cache.json b/docs/plugins/gst_plugins_cache.json
new file mode 100644 (file)
index 0000000..67927f5
--- /dev/null
@@ -0,0 +1,2880 @@
+{
+    "coreelements": {
+        "description": "GStreamer core elements",
+        "elements": {
+            "capsfilter": {
+                "author": "David Schleef <ds@schleef.org>",
+                "description": "Pass data without modification, limiting formats",
+                "hierarchy": [
+                    "GstCapsFilter",
+                    "GstBaseTransform",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Generic",
+                "long-name": "CapsFilter",
+                "pad-templates": {
+                    "sink": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "always"
+                    },
+                    "src": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "caps": {
+                        "blurb": "Restrict the possible allowed capabilities (NULL means ANY). Setting this property takes a reference to the supplied GstCaps object.",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "ANY",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "GstCaps",
+                        "writable": true
+                    },
+                    "caps-change-mode": {
+                        "blurb": "Filter caps change behaviour",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "immediate (0)",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "GstCapsFilterCapsChangeMode",
+                        "writable": true
+                    }
+                },
+                "rank": "none"
+            },
+            "clocksync": {
+                "author": "Jan Schmidt <jan@centricular.com>",
+                "description": "Synchronise buffers to the clock",
+                "hierarchy": [
+                    "GstClockSync",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Generic",
+                "long-name": "ClockSync",
+                "pad-templates": {
+                    "sink": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "always"
+                    },
+                    "src": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "sync": {
+                        "blurb": "Synchronize to pipeline clock",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "sync-to-first": {
+                        "blurb": "Automatically set ts-offset based on running time of the first buffer and pipeline's running time (i.e., ts-offset = \"pipeline running time\" - \"buffer running time\"). When enabled, clocksync element will update ts-offset on the first buffer per flush event or READY to PAUSED state change. This property can be useful in case that buffer timestamp does not necessarily have to be synchronized with pipeline's running time, but duration of the buffer through clocksync element needs to be synchronized with the amount of clock time go. Note that mixed use of ts-offset and this property would be racy if clocksync element is running already.",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "ts-offset": {
+                        "blurb": "Timestamp offset in nanoseconds for synchronisation, negative for earlier sync",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "9223372036854775807",
+                        "min": "-9223372036854775808",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint64",
+                        "writable": true
+                    }
+                },
+                "rank": "none"
+            },
+            "concat": {
+                "author": "Sebastian Dröge <sebastian@centricular.com>",
+                "description": "Concatenate multiple streams",
+                "hierarchy": [
+                    "GstConcat",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Generic",
+                "long-name": "Concat",
+                "pad-templates": {
+                    "sink_%%u": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "request"
+                    },
+                    "src": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "active-pad": {
+                        "blurb": "Currently active sink pad",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstPad",
+                        "writable": false
+                    },
+                    "adjust-base": {
+                        "blurb": "Adjust the base value of segments to ensure they are adjacent",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    }
+                },
+                "rank": "none"
+            },
+            "dataurisrc": {
+                "author": "Philippe Normand <pnormand@igalia.com>, Sebastian Dröge <sebastian.droege@collabora.co.uk>",
+                "description": "Handles data: uris",
+                "hierarchy": [
+                    "GstDataURISrc",
+                    "GstBaseSrc",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "interfaces": [
+                    "GstURIHandler"
+                ],
+                "klass": "Source",
+                "long-name": "data: URI source element",
+                "pad-templates": {
+                    "src": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "uri": {
+                        "blurb": "URI that should be used",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "NULL",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gchararray",
+                        "writable": true
+                    }
+                },
+                "rank": "primary"
+            },
+            "downloadbuffer": {
+                "author": "Wim Taymans <wim.taymans@gmail.com>",
+                "description": "Download Buffer element",
+                "hierarchy": [
+                    "GstDownloadBuffer",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Generic",
+                "long-name": "DownloadBuffer",
+                "pad-templates": {
+                    "sink": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "always"
+                    },
+                    "src": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "high-percent": {
+                        "blurb": "High threshold for buffering to finish. Emits GST_MESSAGE_BUFFERING with a value of 100%%",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "99",
+                        "max": "100",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
+                    "low-percent": {
+                        "blurb": "Low threshold for buffering to start. Emits GST_MESSAGE_BUFFERING with a value of 0%%",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "10",
+                        "max": "100",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
+                    "max-size-bytes": {
+                        "blurb": "Max. amount of data to buffer (bytes, 0=disable)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "2097152",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": true
+                    },
+                    "max-size-time": {
+                        "blurb": "Max. amount of data to buffer (in ns, 0=disable)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "2000000000",
+                        "max": "18446744073709551615",
+                        "min": "0",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "guint64",
+                        "writable": true
+                    },
+                    "temp-location": {
+                        "blurb": "Location to store temporary files in (Only read this property, use temp-template to configure the name template)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "NULL",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gchararray",
+                        "writable": false
+                    },
+                    "temp-remove": {
+                        "blurb": "Remove the temp-location after use",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "temp-template": {
+                        "blurb": "File template to store temporary files in, should contain directory and XXXXXX. (NULL == disabled)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "NULL",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gchararray",
+                        "writable": true
+                    }
+                },
+                "rank": "none"
+            },
+            "fakesink": {
+                "author": "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>, Mr. 'frag-me-more' Vanderwingo <wingo@fluendo.com>",
+                "description": "Black hole for data",
+                "hierarchy": [
+                    "GstFakeSink",
+                    "GstBaseSink",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Sink",
+                "long-name": "Fake Sink",
+                "pad-templates": {
+                    "sink": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "can-activate-pull": {
+                        "blurb": "Can activate in pull mode",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "can-activate-push": {
+                        "blurb": "Can activate in push mode",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "drop-out-of-segment": {
+                        "blurb": "Drop and don't render / hand off out-of-segment buffers",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "dump": {
+                        "blurb": "Dump buffer contents to stdout",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "last-message": {
+                        "blurb": "The message describing current status",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "NULL",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gchararray",
+                        "writable": false
+                    },
+                    "num-buffers": {
+                        "blurb": "Number of buffers to accept going EOS",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "-1",
+                        "max": "2147483647",
+                        "min": "-1",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
+                    "signal-handoffs": {
+                        "blurb": "Send a signal before unreffing the buffer",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "silent": {
+                        "blurb": "Don't produce last_message events",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "state-error": {
+                        "blurb": "Generate a state change error",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "none (0)",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstFakeSinkStateError",
+                        "writable": true
+                    }
+                },
+                "rank": "none",
+                "signals": {
+                    "handoff": {
+                        "args": [
+                            {
+                                "name": "arg0",
+                                "type": "GstBuffer"
+                            },
+                            {
+                                "name": "arg1",
+                                "type": "GstPad"
+                            }
+                        ],
+                        "return-type": "void",
+                        "when": "last"
+                    },
+                    "preroll-handoff": {
+                        "args": [
+                            {
+                                "name": "arg0",
+                                "type": "GstBuffer"
+                            },
+                            {
+                                "name": "arg1",
+                                "type": "GstPad"
+                            }
+                        ],
+                        "return-type": "void",
+                        "when": "last"
+                    }
+                }
+            },
+            "fakesrc": {
+                "author": "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>",
+                "description": "Push empty (no data) buffers around",
+                "hierarchy": [
+                    "GstFakeSrc",
+                    "GstBaseSrc",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Source",
+                "long-name": "Fake Source",
+                "pad-templates": {
+                    "src": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "can-activate-pull": {
+                        "blurb": "Can activate in pull mode",
+                        "conditionally-available": false,
+                        "construct": true,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "can-activate-push": {
+                        "blurb": "Can activate in push mode",
+                        "conditionally-available": false,
+                        "construct": true,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "data": {
+                        "blurb": "Data allocation method",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "allocate (1)",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstFakeSrcDataType",
+                        "writable": true
+                    },
+                    "datarate": {
+                        "blurb": "Timestamps buffers with number of bytes per second (0 = none)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "2147483647",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
+                    "dump": {
+                        "blurb": "Dump buffer contents to stdout",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "filltype": {
+                        "blurb": "How to fill the buffer, if at all",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "nothing (1)",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstFakeSrcFillType",
+                        "writable": true
+                    },
+                    "format": {
+                        "blurb": "The format of the segment events",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "bytes (2)",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstFormat",
+                        "writable": true
+                    },
+                    "is-live": {
+                        "blurb": "True if the element cannot produce data in PAUSED",
+                        "conditionally-available": false,
+                        "construct": true,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "last-message": {
+                        "blurb": "The last status message",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "NULL",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gchararray",
+                        "writable": false
+                    },
+                    "parentsize": {
+                        "blurb": "Size of parent buffer for sub-buffered allocation",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "40960",
+                        "max": "2147483647",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
+                    "pattern": {
+                        "blurb": "Set the pattern (unused)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "NULL",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gchararray",
+                        "writable": true
+                    },
+                    "signal-handoffs": {
+                        "blurb": "Send a signal before pushing the buffer",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "silent": {
+                        "blurb": "Don't produce last_message events",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "sizemax": {
+                        "blurb": "Maximum buffer size",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "4096",
+                        "max": "2147483647",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
+                    "sizemin": {
+                        "blurb": "Minimum buffer size",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "2147483647",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
+                    "sizetype": {
+                        "blurb": "How to determine buffer sizes",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "empty (1)",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstFakeSrcSizeType",
+                        "writable": true
+                    },
+                    "sync": {
+                        "blurb": "Sync to the clock to the datarate",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    }
+                },
+                "rank": "none",
+                "signals": {
+                    "handoff": {
+                        "args": [
+                            {
+                                "name": "arg0",
+                                "type": "GstBuffer"
+                            },
+                            {
+                                "name": "arg1",
+                                "type": "GstPad"
+                            }
+                        ],
+                        "return-type": "void",
+                        "when": "last"
+                    }
+                }
+            },
+            "fdsink": {
+                "author": "Erik Walthinsen <omega@cse.ogi.edu>",
+                "description": "Write data to a file descriptor",
+                "hierarchy": [
+                    "GstFdSink",
+                    "GstBaseSink",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "interfaces": [
+                    "GstURIHandler"
+                ],
+                "klass": "Sink/File",
+                "long-name": "Filedescriptor Sink",
+                "pad-templates": {
+                    "sink": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "fd": {
+                        "blurb": "An open file descriptor to write to",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "1",
+                        "max": "2147483647",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    }
+                },
+                "rank": "none"
+            },
+            "fdsrc": {
+                "author": "Erik Walthinsen <omega@cse.ogi.edu>",
+                "description": "Read from a file descriptor",
+                "hierarchy": [
+                    "GstFdSrc",
+                    "GstPushSrc",
+                    "GstBaseSrc",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "interfaces": [
+                    "GstURIHandler"
+                ],
+                "klass": "Source/File",
+                "long-name": "Filedescriptor Source",
+                "pad-templates": {
+                    "src": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "fd": {
+                        "blurb": "An open file descriptor to read from",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "-1",
+                        "max": "2147483647",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
+                    "timeout": {
+                        "blurb": "Post a message after timeout microseconds (0 = disabled)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "18446744073709551615",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint64",
+                        "writable": true
+                    }
+                },
+                "rank": "none"
+            },
+            "filesink": {
+                "author": "Thomas Vander Stichele <thomas at apestaart dot org>",
+                "description": "Write stream to a file",
+                "hierarchy": [
+                    "GstFileSink",
+                    "GstBaseSink",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "interfaces": [
+                    "GstURIHandler"
+                ],
+                "klass": "Sink/File",
+                "long-name": "File Sink",
+                "pad-templates": {
+                    "sink": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "append": {
+                        "blurb": "Append to an already existing file",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "buffer-mode": {
+                        "blurb": "The buffering mode to use",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "default (-1)",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstFileSinkBufferMode",
+                        "writable": true
+                    },
+                    "buffer-size": {
+                        "blurb": "Size of buffer in number of bytes for line or full buffer-mode",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "65536",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": true
+                    },
+                    "location": {
+                        "blurb": "Location of the file to write",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "NULL",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gchararray",
+                        "writable": true
+                    },
+                    "max-transient-error-timeout": {
+                        "blurb": "Retry up to this many ms on transient errors (currently EACCES)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "2147483647",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
+                    "o-sync": {
+                        "blurb": "Open the file with O_SYNC for enabling synchronous IO",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    }
+                },
+                "rank": "primary"
+            },
+            "filesrc": {
+                "author": "Erik Walthinsen <omega@cse.ogi.edu>",
+                "description": "Read from arbitrary point in a file",
+                "hierarchy": [
+                    "GstFileSrc",
+                    "GstBaseSrc",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "interfaces": [
+                    "GstURIHandler"
+                ],
+                "klass": "Source/File",
+                "long-name": "File Source",
+                "pad-templates": {
+                    "src": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "location": {
+                        "blurb": "Location of the file to read",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "NULL",
+                        "mutable": "ready",
+                        "readable": true,
+                        "type": "gchararray",
+                        "writable": true
+                    }
+                },
+                "rank": "primary"
+            },
+            "funnel": {
+                "author": "Olivier Crete <olivier.crete@collabora.co.uk>",
+                "description": "N-to-1 pipe fitting",
+                "hierarchy": [
+                    "GstFunnel",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Generic",
+                "long-name": "Funnel pipe fitting",
+                "pad-templates": {
+                    "sink_%%u": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "request"
+                    },
+                    "src": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "forward-sticky-events": {
+                        "blurb": "Forward sticky events on stream changes",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "ready",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    }
+                },
+                "rank": "none"
+            },
+            "identity": {
+                "author": "Erik Walthinsen <omega@cse.ogi.edu>",
+                "description": "Pass data without modification",
+                "hierarchy": [
+                    "GstIdentity",
+                    "GstBaseTransform",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Generic",
+                "long-name": "Identity",
+                "pad-templates": {
+                    "sink": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "always"
+                    },
+                    "src": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "check-imperfect-offset": {
+                        "blurb": "Send element messages if offset and offset_end do not match up",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "check-imperfect-timestamp": {
+                        "blurb": "Send element messages if timestamps and durations do not match up",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "datarate": {
+                        "blurb": "(Re)timestamps buffers with number of bytes per second (0 = inactive)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "2147483647",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
+                    "drop-allocation": {
+                        "blurb": "Don't forward allocation queries",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "drop-buffer-flags": {
+                        "blurb": "Drop buffers with the given flags",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "(none)",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstBufferFlags",
+                        "writable": true
+                    },
+                    "drop-probability": {
+                        "blurb": "The Probability a buffer is dropped",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gfloat",
+                        "writable": true
+                    },
+                    "dump": {
+                        "blurb": "Dump buffer contents to stdout",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "eos-after": {
+                        "blurb": "EOS after N buffers",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "-1",
+                        "max": "2147483647",
+                        "min": "-1",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
+                    "error-after": {
+                        "blurb": "Error after N buffers",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "-1",
+                        "max": "2147483647",
+                        "min": "-1",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
+                    "last-message": {
+                        "blurb": "last-message",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "NULL",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gchararray",
+                        "writable": false
+                    },
+                    "signal-handoffs": {
+                        "blurb": "Send a signal before pushing the buffer",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "silent": {
+                        "blurb": "silent",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "single-segment": {
+                        "blurb": "Timestamp buffers and eat segments so as to appear as one segment",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "sleep-time": {
+                        "blurb": "Microseconds to sleep between processing",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": true
+                    },
+                    "stats": {
+                        "blurb": "Statistics",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "application/x-identity-stats, num-bytes=(guint64)0, num-buffers=(guint64)0;",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstStructure",
+                        "writable": false
+                    },
+                    "sync": {
+                        "blurb": "Synchronize to pipeline clock",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "ts-offset": {
+                        "blurb": "Timestamp offset in nanoseconds for synchronisation, negative for earlier sync",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "9223372036854775807",
+                        "min": "-9223372036854775808",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint64",
+                        "writable": true
+                    }
+                },
+                "rank": "none",
+                "signals": {
+                    "handoff": {
+                        "args": [
+                            {
+                                "name": "arg0",
+                                "type": "GstBuffer"
+                            }
+                        ],
+                        "return-type": "void",
+                        "when": "last"
+                    }
+                }
+            },
+            "input-selector": {
+                "author": "Julien Moutte <julien@moutte.net>, Jan Schmidt <thaytan@mad.scientist.com>, Wim Taymans <wim.taymans@gmail.com>",
+                "description": "N-to-1 input stream selector",
+                "hierarchy": [
+                    "GstInputSelector",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Generic",
+                "long-name": "Input selector",
+                "pad-templates": {
+                    "sink_%%u": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "request",
+                        "type": "GstSelectorPad"
+                    },
+                    "src": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "active-pad": {
+                        "blurb": "The currently active sink pad",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "GstPad",
+                        "writable": true
+                    },
+                    "cache-buffers": {
+                        "blurb": "Cache buffers for active-pad",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "ready",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "n-pads": {
+                        "blurb": "The number of sink pads",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": false
+                    },
+                    "sync-mode": {
+                        "blurb": "Behavior in sync-streams mode",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "active-segment (0)",
+                        "mutable": "ready",
+                        "readable": true,
+                        "type": "GstInputSelectorSyncMode",
+                        "writable": true
+                    },
+                    "sync-streams": {
+                        "blurb": "Synchronize inactive streams to the running time of the active stream or to the current clock",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "ready",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    }
+                },
+                "rank": "none"
+            },
+            "multiqueue": {
+                "author": "Edward Hervey <edward@fluendo.com>",
+                "description": "Multiple data queue",
+                "hierarchy": [
+                    "GstMultiQueue",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Generic",
+                "long-name": "MultiQueue",
+                "pad-templates": {
+                    "sink_%%u": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "request",
+                        "type": "GstMultiQueuePad"
+                    },
+                    "src_%%u": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "sometimes",
+                        "type": "GstMultiQueuePad"
+                    }
+                },
+                "properties": {
+                    "extra-size-buffers": {
+                        "blurb": "Amount of buffers the queues can grow if one of them is empty (0=disable) (NOT IMPLEMENTED)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "5",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": true
+                    },
+                    "extra-size-bytes": {
+                        "blurb": "Amount of data the queues can grow if one of them is empty (bytes, 0=disable) (NOT IMPLEMENTED)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "10485760",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": true
+                    },
+                    "extra-size-time": {
+                        "blurb": "Amount of time the queues can grow if one of them is empty (in ns, 0=disable) (NOT IMPLEMENTED)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "3000000000",
+                        "max": "18446744073709551615",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint64",
+                        "writable": true
+                    },
+                    "high-percent": {
+                        "blurb": "High threshold for buffering to finish. Only used if use-buffering is True (Deprecated: use high-watermark instead)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "99",
+                        "max": "100",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
+                    "high-watermark": {
+                        "blurb": "High threshold for buffering to finish. Only used if use-buffering is True",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0.99",
+                        "max": "1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gdouble",
+                        "writable": true
+                    },
+                    "low-percent": {
+                        "blurb": "Low threshold for buffering to start. Only used if use-buffering is True (Deprecated: use low-watermark instead)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "1",
+                        "max": "100",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
+                    "low-watermark": {
+                        "blurb": "Low threshold for buffering to start. Only used if use-buffering is True",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0.01",
+                        "max": "1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gdouble",
+                        "writable": true
+                    },
+                    "max-size-buffers": {
+                        "blurb": "Max. number of buffers in the queue (0=disable)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "5",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": true
+                    },
+                    "max-size-bytes": {
+                        "blurb": "Max. amount of data in the queue (bytes, 0=disable)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "10485760",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": true
+                    },
+                    "max-size-time": {
+                        "blurb": "Max. amount of data in the queue (in ns, 0=disable)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "2000000000",
+                        "max": "18446744073709551615",
+                        "min": "0",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "guint64",
+                        "writable": true
+                    },
+                    "min-interleave-time": {
+                        "blurb": "Minimum extra buffering for deinterleaving (size of the queues) when use-interleave=true",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "250000000",
+                        "max": "18446744073709551615",
+                        "min": "0",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "guint64",
+                        "writable": true
+                    },
+                    "stats": {
+                        "blurb": "Multiqueue Statistics",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "application/x-gst-multi-queue-stats;",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstStructure",
+                        "writable": false
+                    },
+                    "sync-by-running-time": {
+                        "blurb": "Synchronize deactivated or not-linked streams by running time",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "unlinked-cache-time": {
+                        "blurb": "Extra buffering in time for unlinked streams (if 'sync-by-running-time')",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "250000000",
+                        "max": "18446744073709551615",
+                        "min": "0",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "guint64",
+                        "writable": true
+                    },
+                    "use-buffering": {
+                        "blurb": "Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds (0%% = low-watermark, 100%% = high-watermark)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "use-interleave": {
+                        "blurb": "Adjust time limits based on input interleave",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    }
+                },
+                "rank": "none",
+                "signals": {
+                    "overrun": {
+                        "args": [],
+                        "return-type": "void",
+                        "when": "first"
+                    },
+                    "underrun": {
+                        "args": [],
+                        "return-type": "void",
+                        "when": "first"
+                    }
+                }
+            },
+            "output-selector": {
+                "author": "Stefan Kost <stefan.kost@nokia.com>",
+                "description": "1-to-N output stream selector",
+                "hierarchy": [
+                    "GstOutputSelector",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Generic",
+                "long-name": "Output selector",
+                "pad-templates": {
+                    "sink": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "always"
+                    },
+                    "src_%%u": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "request"
+                    }
+                },
+                "properties": {
+                    "active-pad": {
+                        "blurb": "Currently active src pad",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "GstPad",
+                        "writable": true
+                    },
+                    "pad-negotiation-mode": {
+                        "blurb": "The mode to be used for pad negotiation",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "all (1)",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstOutputSelectorPadNegotiationMode",
+                        "writable": true
+                    },
+                    "resend-latest": {
+                        "blurb": "Resend latest buffer after a switch to a new pad",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    }
+                },
+                "rank": "none"
+            },
+            "queue": {
+                "author": "Erik Walthinsen <omega@cse.ogi.edu>",
+                "description": "Simple data queue",
+                "hierarchy": [
+                    "GstQueue",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Generic",
+                "long-name": "Queue",
+                "pad-templates": {
+                    "sink": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "always"
+                    },
+                    "src": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "current-level-buffers": {
+                        "blurb": "Current number of buffers in the queue",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": false
+                    },
+                    "current-level-bytes": {
+                        "blurb": "Current amount of data in the queue (bytes)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": false
+                    },
+                    "current-level-time": {
+                        "blurb": "Current amount of data in the queue (in ns)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "18446744073709551615",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint64",
+                        "writable": false
+                    },
+                    "flush-on-eos": {
+                        "blurb": "Discard all data in the queue when an EOS event is received",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "leaky": {
+                        "blurb": "Where the queue leaks, if at all",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "no (0)",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "GstQueueLeaky",
+                        "writable": true
+                    },
+                    "max-size-buffers": {
+                        "blurb": "Max. number of buffers in the queue (0=disable)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "200",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": true
+                    },
+                    "max-size-bytes": {
+                        "blurb": "Max. amount of data in the queue (bytes, 0=disable)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "10485760",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": true
+                    },
+                    "max-size-time": {
+                        "blurb": "Max. amount of data in the queue (in ns, 0=disable)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "1000000000",
+                        "max": "18446744073709551615",
+                        "min": "0",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "guint64",
+                        "writable": true
+                    },
+                    "min-threshold-buffers": {
+                        "blurb": "Min. number of buffers in the queue to allow reading (0=disable)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": true
+                    },
+                    "min-threshold-bytes": {
+                        "blurb": "Min. amount of data in the queue to allow reading (bytes, 0=disable)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": true
+                    },
+                    "min-threshold-time": {
+                        "blurb": "Min. amount of data in the queue to allow reading (in ns, 0=disable)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "18446744073709551615",
+                        "min": "0",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "guint64",
+                        "writable": true
+                    },
+                    "silent": {
+                        "blurb": "Don't emit queue signals",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    }
+                },
+                "rank": "none",
+                "signals": {
+                    "overrun": {
+                        "args": [],
+                        "return-type": "void",
+                        "when": "first"
+                    },
+                    "pushing": {
+                        "args": [],
+                        "return-type": "void",
+                        "when": "first"
+                    },
+                    "running": {
+                        "args": [],
+                        "return-type": "void",
+                        "when": "first"
+                    },
+                    "underrun": {
+                        "args": [],
+                        "return-type": "void",
+                        "when": "first"
+                    }
+                }
+            },
+            "queue2": {
+                "author": "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim.taymans@gmail.com>",
+                "description": "Simple data queue",
+                "hierarchy": [
+                    "GstQueue2",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Generic",
+                "long-name": "Queue 2",
+                "pad-templates": {
+                    "sink": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "always"
+                    },
+                    "src": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "avg-in-rate": {
+                        "blurb": "Average input data rate (bytes/s)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "9223372036854775807",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint64",
+                        "writable": false
+                    },
+                    "bitrate": {
+                        "blurb": "Conversion value between data size and time",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "18446744073709551615",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint64",
+                        "writable": false
+                    },
+                    "current-level-buffers": {
+                        "blurb": "Current number of buffers in the queue",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": false
+                    },
+                    "current-level-bytes": {
+                        "blurb": "Current amount of data in the queue (bytes)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": false
+                    },
+                    "current-level-time": {
+                        "blurb": "Current amount of data in the queue (in ns)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "18446744073709551615",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint64",
+                        "writable": false
+                    },
+                    "high-percent": {
+                        "blurb": "High threshold for buffering to finish. Only used if use-buffering is True (Deprecated: use high-watermark instead)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "99",
+                        "max": "100",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
+                    "high-watermark": {
+                        "blurb": "High threshold for buffering to finish. Only used if use-buffering is True",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0.99",
+                        "max": "1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gdouble",
+                        "writable": true
+                    },
+                    "low-percent": {
+                        "blurb": "Low threshold for buffering to start. Only used if use-buffering is True (Deprecated: use low-watermark instead)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "1",
+                        "max": "100",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
+                    "low-watermark": {
+                        "blurb": "Low threshold for buffering to start. Only used if use-buffering is True",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0.01",
+                        "max": "1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gdouble",
+                        "writable": true
+                    },
+                    "max-size-buffers": {
+                        "blurb": "Max. number of buffers in the queue (0=disable)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "100",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": true
+                    },
+                    "max-size-bytes": {
+                        "blurb": "Max. amount of data in the queue (bytes, 0=disable)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "2097152",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": true
+                    },
+                    "max-size-time": {
+                        "blurb": "Max. amount of data in the queue (in ns, 0=disable)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "2000000000",
+                        "max": "18446744073709551615",
+                        "min": "0",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "guint64",
+                        "writable": true
+                    },
+                    "ring-buffer-max-size": {
+                        "blurb": "Max. amount of data in the ring buffer (bytes, 0 = disabled)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "18446744073709551615",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint64",
+                        "writable": true
+                    },
+                    "temp-location": {
+                        "blurb": "Location to store temporary files in (Only read this property, use temp-template to configure the name template)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "NULL",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gchararray",
+                        "writable": false
+                    },
+                    "temp-remove": {
+                        "blurb": "Remove the temp-location after use",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "temp-template": {
+                        "blurb": "File template to store temporary files in, should contain directory and XXXXXX. (NULL == disabled)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "NULL",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gchararray",
+                        "writable": true
+                    },
+                    "use-bitrate-query": {
+                        "blurb": "Use a bitrate from a downstream query to estimate buffer duration if not provided",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "use-buffering": {
+                        "blurb": "Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds (0%% = low-watermark, 100%% = high-watermark)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "use-rate-estimate": {
+                        "blurb": "Estimate the bitrate of the stream to calculate time level",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "use-tags-bitrate": {
+                        "blurb": "Use a bitrate from upstream tags to estimate buffer duration if not provided",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    }
+                },
+                "rank": "none"
+            },
+            "streamiddemux": {
+                "author": "HoonHee Lee <hoonhee.lee@lge.com>",
+                "description": "1-to-N output stream by stream-id",
+                "hierarchy": [
+                    "GstStreamidDemux",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Generic",
+                "long-name": "Streamid Demux",
+                "pad-templates": {
+                    "sink": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "always"
+                    },
+                    "src_%%u": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "sometimes"
+                    }
+                },
+                "properties": {
+                    "active-pad": {
+                        "blurb": "The currently active src pad",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstPad",
+                        "writable": false
+                    }
+                },
+                "rank": "primary",
+                "signals": {}
+            },
+            "tee": {
+                "author": "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>",
+                "description": "1-to-N pipe fitting",
+                "hierarchy": [
+                    "GstTee",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Generic",
+                "long-name": "Tee pipe fitting",
+                "pad-templates": {
+                    "sink": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "always"
+                    },
+                    "src_%%u": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "request"
+                    }
+                },
+                "properties": {
+                    "alloc-pad": {
+                        "blurb": "The pad ALLOCATION queries will be proxied to (DEPRECATED, has no effect)",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstPad",
+                        "writable": true
+                    },
+                    "allow-not-linked": {
+                        "blurb": "Return GST_FLOW_OK even if there are no source pads or they are all unlinked",
+                        "conditionally-available": false,
+                        "construct": true,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "has-chain": {
+                        "blurb": "If the element can operate in push mode",
+                        "conditionally-available": false,
+                        "construct": true,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "last-message": {
+                        "blurb": "The message describing current status",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "NULL",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gchararray",
+                        "writable": false
+                    },
+                    "num-src-pads": {
+                        "blurb": "The number of source pads",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "2147483647",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": false
+                    },
+                    "pull-mode": {
+                        "blurb": "Behavior of tee in pull mode",
+                        "conditionally-available": false,
+                        "construct": true,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "never (0)",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstTeePullMode",
+                        "writable": true
+                    },
+                    "silent": {
+                        "blurb": "Don't produce last_message events",
+                        "conditionally-available": false,
+                        "construct": true,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    }
+                },
+                "rank": "none"
+            },
+            "typefind": {
+                "author": "Benjamin Otte <in7y118@public.uni-hamburg.de>",
+                "description": "Finds the media type of a stream",
+                "hierarchy": [
+                    "GstTypeFindElement",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Generic",
+                "long-name": "TypeFind",
+                "pad-templates": {
+                    "sink": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "always"
+                    },
+                    "src": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "caps": {
+                        "blurb": "detected capabilities in stream",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstCaps",
+                        "writable": false
+                    },
+                    "force-caps": {
+                        "blurb": "force caps without doing a typefind",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstCaps",
+                        "writable": true
+                    },
+                    "minimum": {
+                        "blurb": "minimum probability required to accept caps",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "1",
+                        "max": "100",
+                        "min": "1",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": true
+                    }
+                },
+                "rank": "none",
+                "signals": {
+                    "have-type": {
+                        "args": [
+                            {
+                                "name": "arg0",
+                                "type": "guint"
+                            },
+                            {
+                                "name": "arg1",
+                                "type": "GstCaps"
+                            }
+                        ],
+                        "return-type": "void",
+                        "when": "last"
+                    }
+                }
+            },
+            "valve": {
+                "author": "Olivier Crete <olivier.crete@collabora.co.uk>",
+                "description": "Drops buffers and events or lets them through",
+                "hierarchy": [
+                    "GstValve",
+                    "GstElement",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "klass": "Filter",
+                "long-name": "Valve element",
+                "pad-templates": {
+                    "sink": {
+                        "caps": "ANY",
+                        "direction": "sink",
+                        "presence": "always"
+                    },
+                    "src": {
+                        "caps": "ANY",
+                        "direction": "src",
+                        "presence": "always"
+                    }
+                },
+                "properties": {
+                    "drop": {
+                        "blurb": "Whether to drop buffers and events or let them through",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "drop-mode": {
+                        "blurb": "The drop mode to use",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "drop-all (0)",
+                        "mutable": "ready",
+                        "readable": true,
+                        "type": "GstValveDropMode",
+                        "writable": true
+                    }
+                },
+                "rank": "none"
+            }
+        },
+        "filename": "gstcoreelements",
+        "license": "LGPL",
+        "other-types": {
+            "GstCapsFilterCapsChangeMode": {
+                "kind": "enum",
+                "values": [
+                    {
+                        "desc": "Only accept the current filter caps",
+                        "name": "immediate",
+                        "value": "0"
+                    },
+                    {
+                        "desc": "Temporarily accept previous filter caps",
+                        "name": "delayed",
+                        "value": "1"
+                    }
+                ]
+            },
+            "GstFakeSinkStateError": {
+                "kind": "enum",
+                "values": [
+                    {
+                        "desc": "No state change errors",
+                        "name": "none",
+                        "value": "0"
+                    },
+                    {
+                        "desc": "Fail state change from NULL to READY",
+                        "name": "null-to-ready",
+                        "value": "1"
+                    },
+                    {
+                        "desc": "Fail state change from READY to PAUSED",
+                        "name": "ready-to-paused",
+                        "value": "2"
+                    },
+                    {
+                        "desc": "Fail state change from PAUSED to PLAYING",
+                        "name": "paused-to-playing",
+                        "value": "3"
+                    },
+                    {
+                        "desc": "Fail state change from PLAYING to PAUSED",
+                        "name": "playing-to-paused",
+                        "value": "4"
+                    },
+                    {
+                        "desc": "Fail state change from PAUSED to READY",
+                        "name": "paused-to-ready",
+                        "value": "5"
+                    },
+                    {
+                        "desc": "Fail state change from READY to NULL",
+                        "name": "ready-to-null",
+                        "value": "6"
+                    }
+                ]
+            },
+            "GstFakeSrcDataType": {
+                "kind": "enum",
+                "values": [
+                    {
+                        "desc": "Allocate data",
+                        "name": "allocate",
+                        "value": "1"
+                    },
+                    {
+                        "desc": "Subbuffer data",
+                        "name": "subbuffer",
+                        "value": "2"
+                    }
+                ]
+            },
+            "GstFakeSrcFillType": {
+                "kind": "enum",
+                "values": [
+                    {
+                        "desc": "Leave data as malloced",
+                        "name": "nothing",
+                        "value": "1"
+                    },
+                    {
+                        "desc": "Fill buffers with zeros",
+                        "name": "zero",
+                        "value": "2"
+                    },
+                    {
+                        "desc": "Fill buffers with random data",
+                        "name": "random",
+                        "value": "3"
+                    },
+                    {
+                        "desc": "Fill buffers with pattern 0x00 -> 0xff",
+                        "name": "pattern",
+                        "value": "4"
+                    },
+                    {
+                        "desc": "Fill buffers with pattern 0x00 -> 0xff that spans buffers",
+                        "name": "pattern-span",
+                        "value": "5"
+                    }
+                ]
+            },
+            "GstFakeSrcSizeType": {
+                "kind": "enum",
+                "values": [
+                    {
+                        "desc": "Send empty buffers",
+                        "name": "empty",
+                        "value": "1"
+                    },
+                    {
+                        "desc": "Fixed size buffers (sizemax sized)",
+                        "name": "fixed",
+                        "value": "2"
+                    },
+                    {
+                        "desc": "Random sized buffers (sizemin <= size <= sizemax)",
+                        "name": "random",
+                        "value": "3"
+                    }
+                ]
+            },
+            "GstFileSinkBufferMode": {
+                "kind": "enum",
+                "values": [
+                    {
+                        "desc": "Default buffering",
+                        "name": "default",
+                        "value": "-1"
+                    },
+                    {
+                        "desc": "Fully buffered",
+                        "name": "full",
+                        "value": "0"
+                    },
+                    {
+                        "desc": "Line buffered (deprecated, like full)",
+                        "name": "line",
+                        "value": "1"
+                    },
+                    {
+                        "desc": "Unbuffered",
+                        "name": "unbuffered",
+                        "value": "2"
+                    }
+                ]
+            },
+            "GstInputSelectorSyncMode": {
+                "kind": "enum",
+                "values": [
+                    {
+                        "desc": "Sync using the current active segment",
+                        "name": "active-segment",
+                        "value": "0"
+                    },
+                    {
+                        "desc": "Sync using the clock",
+                        "name": "clock",
+                        "value": "1"
+                    }
+                ]
+            },
+            "GstMultiQueuePad": {
+                "hierarchy": [
+                    "GstMultiQueuePad",
+                    "GstPad",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "kind": "object",
+                "properties": {
+                    "current-level-buffers": {
+                        "blurb": "Current level buffers",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": false
+                    },
+                    "current-level-bytes": {
+                        "blurb": "Current level bytes",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": false
+                    },
+                    "current-level-time": {
+                        "blurb": "Current level time",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "18446744073709551615",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint64",
+                        "writable": false
+                    },
+                    "group-id": {
+                        "blurb": "Group to which this pad belongs",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "-1",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "guint",
+                        "writable": true
+                    }
+                }
+            },
+            "GstOutputSelectorPadNegotiationMode": {
+                "kind": "enum",
+                "values": [
+                    {
+                        "desc": "None",
+                        "name": "none",
+                        "value": "0"
+                    },
+                    {
+                        "desc": "All",
+                        "name": "all",
+                        "value": "1"
+                    },
+                    {
+                        "desc": "Active",
+                        "name": "active",
+                        "value": "2"
+                    }
+                ]
+            },
+            "GstQueueLeaky": {
+                "kind": "enum",
+                "values": [
+                    {
+                        "desc": "Not Leaky",
+                        "name": "no",
+                        "value": "0"
+                    },
+                    {
+                        "desc": "Leaky on upstream (new buffers)",
+                        "name": "upstream",
+                        "value": "1"
+                    },
+                    {
+                        "desc": "Leaky on downstream (old buffers)",
+                        "name": "downstream",
+                        "value": "2"
+                    }
+                ]
+            },
+            "GstSelectorPad": {
+                "hierarchy": [
+                    "GstSelectorPad",
+                    "GstPad",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "kind": "object",
+                "properties": {
+                    "active": {
+                        "blurb": "If the pad is currently active",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": false
+                    },
+                    "always-ok": {
+                        "blurb": "Make an inactive pad return OK instead of NOT_LINKED",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "running-time": {
+                        "blurb": "Running time of stream on pad",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "0",
+                        "max": "9223372036854775807",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint64",
+                        "writable": false
+                    },
+                    "tags": {
+                        "blurb": "The currently active tags on the pad",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstTagList",
+                        "writable": false
+                    }
+                }
+            },
+            "GstTeePullMode": {
+                "kind": "enum",
+                "values": [
+                    {
+                        "desc": "Never activate in pull mode",
+                        "name": "never",
+                        "value": "0"
+                    },
+                    {
+                        "desc": "Only one src pad can be active in pull mode",
+                        "name": "single",
+                        "value": "1"
+                    }
+                ]
+            },
+            "GstValveDropMode": {
+                "kind": "enum",
+                "values": [
+                    {
+                        "desc": "Drop all buffers and events",
+                        "name": "drop-all",
+                        "value": "0"
+                    },
+                    {
+                        "desc": "Drop all buffers but forward sticky events",
+                        "name": "forward-sticky-events",
+                        "value": "1"
+                    },
+                    {
+                        "desc": "Convert all dropped buffers into gap events and forward sticky events",
+                        "name": "transform-to-gap",
+                        "value": "2"
+                    }
+                ]
+            }
+        },
+        "package": "GStreamer",
+        "source": "gstreamer",
+        "tracers": {},
+        "url": "Unknown package origin"
+    },
+    "coretracers": {
+        "description": "GStreamer core tracers",
+        "elements": {},
+        "filename": "gstcoretracers",
+        "license": "LGPL",
+        "other-types": {},
+        "package": "GStreamer",
+        "source": "gstreamer",
+        "tracers": {
+            "factories": {},
+            "latency": {},
+            "leaks": {},
+            "log": {},
+            "rusage": {},
+            "stats": {}
+        },
+        "url": "Unknown package origin"
+    }
+}
\ No newline at end of file
diff --git a/docs/plugins/gstreamer-plugins-docs.sgml b/docs/plugins/gstreamer-plugins-docs.sgml
deleted file mode 100644 (file)
index 6d823c9..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-               "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
-<!ENTITY % version-entities SYSTEM "version.entities">
-%version-entities;
-]>
-
-<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
-  <bookinfo>
-    <title>GStreamer Core Plugins &GST_API_VERSION; Plugins Reference Manual</title>
-    <releaseinfo>
-      for GStreamer Core Plugins &GST_API_VERSION; (&GST_VERSION;)
-      The latest version of this documentation can be found on-line at
-      <ulink role="online-location" url="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-plugins/html/">http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-plugins/html/</ulink>.
-    </releaseinfo>
-  </bookinfo>
-
-  <chapter>
-    <title>gstreamer Elements</title>
-    <xi:include href="xml/element-capsfilter.xml" />
-    <xi:include href="xml/element-concat.xml" />
-    <xi:include href="xml/element-dataurisrc.xml" />
-    <xi:include href="xml/element-downloadbuffer.xml" />
-    <xi:include href="xml/element-fakesink.xml" />
-    <xi:include href="xml/element-fakesrc.xml" />
-    <xi:include href="xml/element-fdsink.xml" />
-    <xi:include href="xml/element-fdsrc.xml" />
-    <xi:include href="xml/element-filesink.xml" />
-    <xi:include href="xml/element-filesrc.xml" />
-    <xi:include href="xml/element-funnel.xml" />
-    <xi:include href="xml/element-identity.xml" />
-    <xi:include href="xml/element-input-selector.xml" />
-    <xi:include href="xml/element-multiqueue.xml" />
-    <xi:include href="xml/element-output-selector.xml" />
-    <xi:include href="xml/element-queue2.xml" />
-    <xi:include href="xml/element-queue.xml" />
-    <xi:include href="xml/element-streamiddemux.xml" />
-    <xi:include href="xml/element-tee.xml" />
-    <xi:include href="xml/element-typefind.xml" />
-    <xi:include href="xml/element-valve.xml" />
-  </chapter>
-
-  <chapter>
-    <title>gstreamer Tracers</title>
-    <xi:include href="xml/element-latencytracer.xml" />
-    <xi:include href="xml/element-leakstracer.xml" />
-    <xi:include href="xml/element-logtracer.xml" />
-    <xi:include href="xml/element-rusagetracer.xml" />
-    <xi:include href="xml/element-statstracer.xml" />
-  </chapter>
-
-  <chapter>
-    <title>gstreamer Plugins</title>
-    <xi:include href="xml/plugin-coreelements.xml" />
-    <xi:include href="xml/plugin-coretracers.xml" />
-  </chapter>
-</book>
-
diff --git a/docs/plugins/gstreamer-plugins-sections.txt b/docs/plugins/gstreamer-plugins-sections.txt
deleted file mode 100644 (file)
index 89d4906..0000000
+++ /dev/null
@@ -1,430 +0,0 @@
-<SECTION>
-<FILE>element-capsfilter</FILE>
-<TITLE>capsfilter</TITLE>
-GstCapsFilter
-GstCapsFilterCapsChangeMode
-<SUBSECTION Standard>
-GstCapsFilterClass
-GST_CAPS_FILTER
-GST_CAPS_FILTER_CAST
-GST_IS_CAPS_FILTER
-GST_CAPS_FILTER_CLASS
-GST_IS_CAPS_FILTER_CLASS
-GST_TYPE_CAPS_FILTER
-<SUBSECTION Private>
-gst_caps_filter_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-concat</FILE>
-<TITLE>concat</TITLE>
-GstConcat
-<SUBSECTION Standard>
-GstConcatClass
-GST_CONCAT
-GST_CONCAT_CAST
-GST_IS_CONCAT
-GST_CONCAT_CLASS
-GST_IS_CONCAT_CLASS
-GST_TYPE_CONCAT
-<SUBSECTION Private>
-gst_concat_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-dataurisrc</FILE>
-<TITLE>dataurisrc</TITLE>
-GstDataURISrc
-<SUBSECTION Standard>
-GstDataURISrcClass
-GST_DATA_URI_SRC
-GST_DATA_URI_SRC_CAST
-GST_IS_DATA_URI_SRC
-GST_DATA_URI_SRC_CLASS
-GST_IS_DATA_URI_SRC_CLASS
-GST_TYPE_DATA_URI_SRC
-<SUBSECTION Private>
-gst_data_uri_src_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-downloadbuffer</FILE>
-<TITLE>downloadbuffer</TITLE>
-GstDownloadBuffer
-<SUBSECTION Standard>
-GstDownloadBufferSize
-GstDownloadBufferClass
-GST_DOWNLOAD_BUFFER
-GST_DOWNLOAD_BUFFER_CAST
-GST_IS_DOWNLOAD_BUFFER
-GST_DOWNLOAD_BUFFER_CLASS
-GST_IS_DOWNLOAD_BUFFER_CLASS
-GST_TYPE_DOWNLOAD_BUFFER
-<SUBSECTION Private>
-gst_download_buffer_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-fakesink</FILE>
-<TITLE>fakesink</TITLE>
-GstFakeSink
-GstFakeSinkStateError
-<SUBSECTION Standard>
-GstFakeSinkClass
-GST_FAKE_SINK
-GST_FAKE_SINK_CAST
-GST_IS_FAKE_SINK
-GST_FAKE_SINK_CLASS
-GST_IS_FAKE_SINK_CLASS
-GST_TYPE_FAKE_SINK
-<SUBSECTION Private>
-gst_fake_sink_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-fakesrc</FILE>
-<TITLE>fakesrc</TITLE>
-GstFakeSrc
-GstFakeSrcDataType
-GstFakeSrcFillType
-GstFakeSrcOutputType
-GstFakeSrcSizeType
-<SUBSECTION Standard>
-GstFakeSrcClass
-GST_FAKE_SRC
-GST_IS_FAKE_SRC
-GST_FAKE_SRC_CLASS
-GST_IS_FAKE_SRC_CLASS
-GST_TYPE_FAKE_SRC
-<SUBSECTION Private>
-gst_fake_src_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-fdsink</FILE>
-<TITLE>fdsink</TITLE>
-GstFdSink
-<SUBSECTION Standard>
-GstFdSinkClass
-GST_FD_SINK
-GST_FD_SINK_CAST
-GST_IS_FD_SINK
-GST_FD_SINK_CLASS
-GST_IS_FD_SINK_CLASS
-GST_TYPE_FD_SINK
-<SUBSECTION Private>
-gst_fd_sink_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-fdsrc</FILE>
-<TITLE>fdsrc</TITLE>
-GstFdSrc
-<SUBSECTION Standard>
-GstFdSrcClass
-GST_FD_SRC
-GST_IS_FD_SRC
-GST_FD_SRC_CLASS
-GST_IS_FD_SRC_CLASS
-GST_TYPE_FD_SRC
-<SUBSECTION Private>
-gst_fd_src_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-filesink</FILE>
-<TITLE>filesink</TITLE>
-GstFileSink
-GstFileSinkBufferMode
-<SUBSECTION Standard>
-GstFileSinkClass
-GST_FILE_SINK
-GST_FILE_SINK_CAST
-GST_IS_FILE_SINK
-GST_FILE_SINK_CLASS
-GST_IS_FILE_SINK_CLASS
-GST_TYPE_FILE_SINK
-GST_TYPE_FILE_SINK_BUFFER_MODE
-<SUBSECTION Private>
-gst_file_sink_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-filesrc</FILE>
-<TITLE>filesrc</TITLE>
-GstFileSrc
-<SUBSECTION Standard>
-GstFileSrcClass
-GST_FILE_SRC
-GST_FILE_SRC_CAST
-GST_IS_FILE_SRC
-GST_FILE_SRC_CLASS
-GST_IS_FILE_SRC_CLASS
-GST_TYPE_FILE_SRC
-<SUBSECTION Private>
-gst_file_src_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-funnel</FILE>
-<TITLE>funnel</TITLE>
-GstFunnel
-<SUBSECTION Standard>
-GstFunnelClass
-GST_FUNNEL
-GST_IS_FUNNEL
-GST_FUNNEL_CLASS
-GST_IS_FUNNEL_CLASS
-GST_TYPE_FUNNEL
-<SUBSECTION Private>
-gst_funnel_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-identity</FILE>
-<TITLE>identity</TITLE>
-GstIdentity
-<SUBSECTION Standard>
-GstIdentityClass
-GST_IDENTITY
-GST_IS_IDENTITY
-GST_IDENTITY_CLASS
-GST_IS_IDENTITY_CLASS
-GST_TYPE_IDENTITY
-<SUBSECTION Private>
-gst_identity_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-input-selector</FILE>
-<TITLE>input-selector</TITLE>
-GstInputSelector
-GstInputSelectorSyncMode
-<SUBSECTION Standard>
-GstInputSelectorClass
-GST_INPUT_SELECTOR
-GST_IS_INPUT_SELECTOR
-GST_INPUT_SELECTOR_CLASS
-GST_IS_INPUT_SELECTOR_CLASS
-GST_TYPE_INPUT_SELECTOR
-GST_INPUT_SELECTOR_BROADCAST
-GST_INPUT_SELECTOR_GET_COND
-GST_INPUT_SELECTOR_GET_LOCK
-GST_INPUT_SELECTOR_LOCK
-GST_INPUT_SELECTOR_UNLOCK
-GST_INPUT_SELECTOR_WAIT
-<SUBSECTION Private>
-gst_input_selector_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-latencytracer</FILE>
-<TITLE>latencytracer</TITLE>
-GstLatencyTracer
-<SUBSECTION Standard>
-GstLatencyTracerClass
-GST_LATENCY_TRACER
-GST_LATENCY_TRACER_CAST
-GST_IS_LATENCY_TRACER
-GST_LATENCY_TRACER_CLASS
-GST_IS_LATENCY_TRACER_CLASS
-GST_TYPE_LATENCY_TRACER
-<SUBSECTION Private>
-gst_latency_tracer_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-leakstracer</FILE>
-<TITLE>leakstracer</TITLE>
-GstLeaksTracer
-<SUBSECTION Standard>
-GstLeaksTracerClass
-GST_LEAKS_TRACER
-GST_LEAKS_TRACER_CAST
-GST_IS_LEAKS_TRACER
-GST_LEAKS_TRACER_CLASS
-GST_IS_LEAKS_TRACER_CLASS
-GST_TYPE_LEAKS_TRACER
-<SUBSECTION Private>
-gst_leaks_tracer_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-logtracer</FILE>
-<TITLE>logtracer</TITLE>
-GstLogTracer
-<SUBSECTION Standard>
-GstLogTracerClass
-GST_LOG_TRACER
-GST_LOG_TRACER_CAST
-GST_IS_LOG_TRACER
-GST_LOG_TRACER_CLASS
-GST_IS_LOG_TRACER_CLASS
-GST_TYPE_LOG_TRACER
-<SUBSECTION Private>
-gst_log_tracer_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-multiqueue</FILE>
-<TITLE>multiqueue</TITLE>
-GstMultiQueue
-<SUBSECTION Standard>
-GstMultiQueueClass
-GST_MULTI_QUEUE
-GST_IS_MULTI_QUEUE
-GST_MULTI_QUEUE_CLASS
-GST_IS_MULTI_QUEUE_CLASS
-GST_TYPE_MULTI_QUEUE
-<SUBSECTION Private>
-gst_multi_queue_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-output-selector</FILE>
-<TITLE>output-selector</TITLE>
-GstOutputSelector
-GstOutputSelectorPadNegotiationMode
-<SUBSECTION Standard>
-GstOutputSelectorClass
-GST_OUTPUT_SELECTOR
-GST_IS_OUTPUT_SELECTOR
-GST_OUTPUT_SELECTOR_CLASS
-GST_IS_OUTPUT_SELECTOR_CLASS
-GST_TYPE_OUTPUT_SELECTOR
-<SUBSECTION Private>
-gst_output_selector_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-queue</FILE>
-<TITLE>queue</TITLE>
-GstQueue
-GstQueueLeaky
-<SUBSECTION Standard>
-GstQueueClass
-GST_QUEUE
-GST_QUEUE_CAST
-GST_IS_QUEUE
-GST_QUEUE_CLASS
-GST_IS_QUEUE_CLASS
-GST_TYPE_QUEUE
-<SUBSECTION Private>
-GstQueueSize
-gst_queue_get_type
-GST_QUEUE_CLEAR_LEVEL
-</SECTION>
-
-<SECTION>
-<FILE>element-queue2</FILE>
-<TITLE>queue2</TITLE>
-GstQueue2
-<SUBSECTION Standard>
-GstQueue2Class
-GST_QUEUE2
-GST_QUEUE2_CAST
-GST_IS_QUEUE2
-GST_QUEUE2_CLASS
-GST_IS_QUEUE2_CLASS
-GST_TYPE_QUEUE2
-<SUBSECTION Private>
-GstQueue2Size
-GstQueue2Range
-gst_queue2_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-rusagetracer</FILE>
-<TITLE>rusagetracer</TITLE>
-GstRUsageTracer
-<SUBSECTION Standard>
-GstRUsageTracerClass
-GST_RUSAGE_TRACER
-GST_RUSAGE_TRACER_CAST
-GST_IS_RUSAGE_TRACER
-GST_RUSAGE_TRACER_CLASS
-GST_IS_RUSAGE_TRACER_CLASS
-GST_TYPE_RUSAGE_TRACER
-<SUBSECTION Private>
-gst_rusage_tracer_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-statstracer</FILE>
-<TITLE>statstracer</TITLE>
-GstStatsTracer
-<SUBSECTION Standard>
-GstStatsTracerClass
-GST_STATS_TRACER
-GST_STATS_TRACER_CAST
-GST_IS_STATS_TRACER
-GST_STATS_TRACER_CLASS
-GST_IS_STATS_TRACER_CLASS
-GST_TYPE_STATS_TRACER
-<SUBSECTION Private>
-gst_stats_tracer_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-streamiddemux</FILE>
-<TITLE>streamiddemux</TITLE>
-GstStreamidDemux
-<SUBSECTION Standard>
-GstStreamidDemuxClass
-GST_STREAMID_DEMUX
-GST_STREAMID_DEMUX_CAST
-GST_IS_STREAMID_DEMUX
-GST_STREAMID_DEMUX_CLASS
-GST_IS_STREAMID_DEMUX_CLASS
-GST_TYPE_STREAMID_DEMUX
-<SUBSECTION Private>
-gst_streamid_demux_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-tee</FILE>
-<TITLE>tee</TITLE>
-GstTee
-GstTeePullMode
-<SUBSECTION Standard>
-GstTeeClass
-GST_TEE
-GST_TEE_CAST
-GST_IS_TEE
-GST_TEE_CLASS
-GST_IS_TEE_CLASS
-GST_TYPE_TEE
-<SUBSECTION Private>
-gst_tee_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-typefind</FILE>
-<TITLE>typefind</TITLE>
-GstTypeFindElement
-<SUBSECTION Standard>
-GstTypeFindElementClass
-GST_TYPE_FIND_ELEMENT
-GST_IS_TYPE_FIND_ELEMENT
-GST_TYPE_FIND_ELEMENT_CLASS
-GST_IS_TYPE_FIND_ELEMENT_CLASS
-GST_TYPE_TYPE_FIND_ELEMENT
-<SUBSECTION Private>
-gst_type_find_element_get_type
-</SECTION>
-
-<SECTION>
-<FILE>element-valve</FILE>
-<TITLE>valve</TITLE>
-GstValve
-<SUBSECTION Standard>
-GstValveClass
-GST_VALVE
-GST_IS_VALVE
-GST_VALVE_CLASS
-GST_IS_VALVE_CLASS
-GST_TYPE_VALVE
-<SUBSECTION Private>
-gst_valve_get_type
-</SECTION>
-
diff --git a/docs/plugins/gstreamer-plugins.args b/docs/plugins/gstreamer-plugins.args
deleted file mode 100644 (file)
index a52a71d..0000000
+++ /dev/null
@@ -1,1300 +0,0 @@
-<ARG>
-<NAME>GstValve::drop</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Drop buffers and events</NICK>
-<BLURB>Whether to drop buffers and events or let them through.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstTypeFindElement::caps</NAME>
-<TYPE>GstCaps*</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>caps</NICK>
-<BLURB>detected capabilities in stream.</BLURB>
-<DEFAULT></DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstTypeFindElement::force-caps</NAME>
-<TYPE>GstCaps*</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>force caps</NICK>
-<BLURB>force caps without doing a typefind.</BLURB>
-<DEFAULT></DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstTypeFindElement::minimum</NAME>
-<TYPE>guint</TYPE>
-<RANGE>[1,100]</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>minimum</NICK>
-<BLURB>minimum probability required to accept caps.</BLURB>
-<DEFAULT>1</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstTee::alloc-pad</NAME>
-<TYPE>GstPad*</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Allocation Src Pad</NICK>
-<BLURB>The pad ALLOCATION queries will be proxied to (DEPRECATED, has no effect).</BLURB>
-<DEFAULT></DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstTee::has-chain</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rwx</FLAGS>
-<NICK>Has Chain</NICK>
-<BLURB>If the element can operate in push mode.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstTee::last-message</NAME>
-<TYPE>gchar*</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>Last Message</NICK>
-<BLURB>The message describing current status.</BLURB>
-<DEFAULT>NULL</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstTee::num-src-pads</NAME>
-<TYPE>gint</TYPE>
-<RANGE>>= 0</RANGE>
-<FLAGS>r</FLAGS>
-<NICK>Num Src Pads</NICK>
-<BLURB>The number of source pads.</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstTee::pull-mode</NAME>
-<TYPE>GstTeePullMode</TYPE>
-<RANGE></RANGE>
-<FLAGS>rwx</FLAGS>
-<NICK>Pull mode</NICK>
-<BLURB>Behavior of tee in pull mode.</BLURB>
-<DEFAULT>Never activate in pull mode</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstTee::silent</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rwx</FLAGS>
-<NICK>Silent</NICK>
-<BLURB>Don't produce last_message events.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstTee::allow-not-linked</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rwx</FLAGS>
-<NICK>Allow not linked</NICK>
-<BLURB>Return GST_FLOW_OK even if there are no source pads or they are all unlinked.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::current-level-buffers</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>Current level (buffers)</NICK>
-<BLURB>Current number of buffers in the queue.</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::current-level-bytes</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>Current level (kB)</NICK>
-<BLURB>Current amount of data in the queue (bytes).</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::current-level-time</NAME>
-<TYPE>guint64</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>Current level (ns)</NICK>
-<BLURB>Current amount of data in the queue (in ns).</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::high-percent</NAME>
-<TYPE>gint</TYPE>
-<RANGE>[0,100]</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>High percent</NICK>
-<BLURB>High threshold for buffering to finish. Only used if use-buffering is True (Deprecated: use high-watermark instead).</BLURB>
-<DEFAULT>99</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::low-percent</NAME>
-<TYPE>gint</TYPE>
-<RANGE>[0,100]</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Low percent</NICK>
-<BLURB>Low threshold for buffering to start. Only used if use-buffering is True (Deprecated: use low-watermark instead).</BLURB>
-<DEFAULT>1</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::max-size-buffers</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Max. size (buffers)</NICK>
-<BLURB>Max. number of buffers in the queue (0=disable).</BLURB>
-<DEFAULT>100</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::max-size-bytes</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Max. size (kB)</NICK>
-<BLURB>Max. amount of data in the queue (bytes, 0=disable).</BLURB>
-<DEFAULT>2097152</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::max-size-time</NAME>
-<TYPE>guint64</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Max. size (ns)</NICK>
-<BLURB>Max. amount of data in the queue (in ns, 0=disable).</BLURB>
-<DEFAULT>2000000000</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::ring-buffer-max-size</NAME>
-<TYPE>guint64</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Max. ring buffer size (bytes)</NICK>
-<BLURB>Max. amount of data in the ring buffer (bytes, 0 = disabled).</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::temp-location</NAME>
-<TYPE>gchar*</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>Temporary File Location</NICK>
-<BLURB>Location to store temporary files in (Only read this property, use temp-template to configure the name template).</BLURB>
-<DEFAULT>NULL</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::temp-remove</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Remove the Temporary File</NICK>
-<BLURB>Remove the temp-location after use.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::temp-template</NAME>
-<TYPE>gchar*</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Temporary File Template</NICK>
-<BLURB>File template to store temporary files in, should contain directory and XXXXXX. (NULL == disabled).</BLURB>
-<DEFAULT>NULL</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::use-buffering</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Use buffering</NICK>
-<BLURB>Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::use-rate-estimate</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Use Rate Estimate</NICK>
-<BLURB>Estimate the bitrate of the stream to calculate time level.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::avg-in-rate</NAME>
-<TYPE>gint64</TYPE>
-<RANGE>>= 0</RANGE>
-<FLAGS>r</FLAGS>
-<NICK>Input data rate (bytes/s)</NICK>
-<BLURB>Average input data rate (bytes/s).</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::use-tags-bitrate</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Use bitrate from tags</NICK>
-<BLURB>Use a bitrate from upstream tags to estimate buffer duration if not provided.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::high-watermark</NAME>
-<TYPE>gdouble</TYPE>
-<RANGE>[0,1]</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>High watermark</NICK>
-<BLURB>High threshold for buffering to finish. Only used if use-buffering is True.</BLURB>
-<DEFAULT>0.99</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::low-watermark</NAME>
-<TYPE>gdouble</TYPE>
-<RANGE>[0,1]</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Low watermark</NICK>
-<BLURB>Low threshold for buffering to start. Only used if use-buffering is True.</BLURB>
-<DEFAULT>0.01</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::bitrate</NAME>
-<TYPE>guint64</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>Bitrate (bits/s)</NICK>
-<BLURB>Conversion value between data size and time.</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue2::use-bitrate-query</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Use bitrate from downstream query</NICK>
-<BLURB>Use a bitrate from a downstream query to estimate buffer duration if not provided.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue::current-level-buffers</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>Current level (buffers)</NICK>
-<BLURB>Current number of buffers in the queue.</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue::current-level-bytes</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>Current level (kB)</NICK>
-<BLURB>Current amount of data in the queue (bytes).</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue::current-level-time</NAME>
-<TYPE>guint64</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>Current level (ns)</NICK>
-<BLURB>Current amount of data in the queue (in ns).</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue::flush-on-eos</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Flush on EOS</NICK>
-<BLURB>Discard all data in the queue when an EOS event is received.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue::leaky</NAME>
-<TYPE>GstQueueLeaky</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Leaky</NICK>
-<BLURB>Where the queue leaks, if at all.</BLURB>
-<DEFAULT>Not Leaky</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue::max-size-buffers</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Max. size (buffers)</NICK>
-<BLURB>Max. number of buffers in the queue (0=disable).</BLURB>
-<DEFAULT>200</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue::max-size-bytes</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Max. size (kB)</NICK>
-<BLURB>Max. amount of data in the queue (bytes, 0=disable).</BLURB>
-<DEFAULT>10485760</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue::max-size-time</NAME>
-<TYPE>guint64</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Max. size (ns)</NICK>
-<BLURB>Max. amount of data in the queue (in ns, 0=disable).</BLURB>
-<DEFAULT>1000000000</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue::min-threshold-buffers</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Min. threshold (buffers)</NICK>
-<BLURB>Min. number of buffers in the queue to allow reading (0=disable).</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue::min-threshold-bytes</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Min. threshold (kB)</NICK>
-<BLURB>Min. amount of data in the queue to allow reading (bytes, 0=disable).</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue::min-threshold-time</NAME>
-<TYPE>guint64</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Min. threshold (ns)</NICK>
-<BLURB>Min. amount of data in the queue to allow reading (in ns, 0=disable).</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstQueue::silent</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Silent</NICK>
-<BLURB>Don't emit queue signals.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstOutputSelector::active-pad</NAME>
-<TYPE>GstPad*</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Active pad</NICK>
-<BLURB>Currently active src pad.</BLURB>
-<DEFAULT></DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstOutputSelector::pad-negotiation-mode</NAME>
-<TYPE>GstOutputSelectorPadNegotiationMode</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Pad negotiation mode</NICK>
-<BLURB>The mode to be used for pad negotiation.</BLURB>
-<DEFAULT>All</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstOutputSelector::resend-latest</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Resend latest buffer</NICK>
-<BLURB>Resend latest buffer after a switch to a new pad.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstMultiQueue::extra-size-buffers</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Extra Size (buffers)</NICK>
-<BLURB>Amount of buffers the queues can grow if one of them is empty (0=disable) (NOT IMPLEMENTED).</BLURB>
-<DEFAULT>5</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstMultiQueue::extra-size-bytes</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Extra Size (kB)</NICK>
-<BLURB>Amount of data the queues can grow if one of them is empty (bytes, 0=disable) (NOT IMPLEMENTED).</BLURB>
-<DEFAULT>10485760</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstMultiQueue::extra-size-time</NAME>
-<TYPE>guint64</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Extra Size (ns)</NICK>
-<BLURB>Amount of time the queues can grow if one of them is empty (in ns, 0=disable) (NOT IMPLEMENTED).</BLURB>
-<DEFAULT>3000000000</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstMultiQueue::high-percent</NAME>
-<TYPE>gint</TYPE>
-<RANGE>[0,100]</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>High percent</NICK>
-<BLURB>High threshold for buffering to finish. Only used if use-buffering is True (Deprecated: use high-watermark instead).</BLURB>
-<DEFAULT>99</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstMultiQueue::low-percent</NAME>
-<TYPE>gint</TYPE>
-<RANGE>[0,100]</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Low percent</NICK>
-<BLURB>Low threshold for buffering to start. Only used if use-buffering is True (Deprecated: use low-watermark instead).</BLURB>
-<DEFAULT>1</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstMultiQueue::max-size-buffers</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Max. size (buffers)</NICK>
-<BLURB>Max. number of buffers in the queue (0=disable).</BLURB>
-<DEFAULT>5</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstMultiQueue::max-size-bytes</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Max. size (kB)</NICK>
-<BLURB>Max. amount of data in the queue (bytes, 0=disable).</BLURB>
-<DEFAULT>10485760</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstMultiQueue::max-size-time</NAME>
-<TYPE>guint64</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Max. size (ns)</NICK>
-<BLURB>Max. amount of data in the queue (in ns, 0=disable).</BLURB>
-<DEFAULT>2000000000</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstMultiQueue::sync-by-running-time</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Sync By Running Time</NICK>
-<BLURB>Synchronize deactivated or not-linked streams by running time.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstMultiQueue::use-buffering</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Use buffering</NICK>
-<BLURB>Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstMultiQueue::unlinked-cache-time</NAME>
-<TYPE>guint64</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Unlinked cache time (ns)</NICK>
-<BLURB>Extra buffering in time for unlinked streams (if 'sync-by-running-time').</BLURB>
-<DEFAULT>250000000</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstMultiQueue::use-interleave</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Use interleave</NICK>
-<BLURB>Adjust time limits based on input interleave.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstMultiQueue::high-watermark</NAME>
-<TYPE>gdouble</TYPE>
-<RANGE>[0,1]</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>High watermark</NICK>
-<BLURB>High threshold for buffering to finish. Only used if use-buffering is True.</BLURB>
-<DEFAULT>0.99</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstMultiQueue::low-watermark</NAME>
-<TYPE>gdouble</TYPE>
-<RANGE>[0,1]</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Low watermark</NICK>
-<BLURB>Low threshold for buffering to start. Only used if use-buffering is True.</BLURB>
-<DEFAULT>0.01</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstMultiQueue::min-interleave-time</NAME>
-<TYPE>guint64</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Minimum interleave time</NICK>
-<BLURB>Minimum extra buffering for deinterleaving (size of the queues) when use-interleave=true.</BLURB>
-<DEFAULT>250000000</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstInputSelector::active-pad</NAME>
-<TYPE>GstPad*</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Active pad</NICK>
-<BLURB>The currently active sink pad.</BLURB>
-<DEFAULT></DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstInputSelector::cache-buffers</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Cache Buffers</NICK>
-<BLURB>Cache buffers for active-pad.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstInputSelector::n-pads</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>Number of Pads</NICK>
-<BLURB>The number of sink pads.</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstInputSelector::sync-mode</NAME>
-<TYPE>GstInputSelectorSyncMode</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Sync mode</NICK>
-<BLURB>Behavior in sync-streams mode.</BLURB>
-<DEFAULT>Sync using the current active segment</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstInputSelector::sync-streams</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Sync Streams</NICK>
-<BLURB>Synchronize inactive streams to the running time of the active stream or to the current clock.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstIdentity::check-imperfect-offset</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Check for discontiguous offset</NICK>
-<BLURB>Send element messages if offset and offset_end do not match up.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstIdentity::check-imperfect-timestamp</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Check for discontiguous timestamps</NICK>
-<BLURB>Send element messages if timestamps and durations do not match up.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstIdentity::datarate</NAME>
-<TYPE>gint</TYPE>
-<RANGE>>= 0</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Datarate</NICK>
-<BLURB>(Re)timestamps buffers with number of bytes per second (0 = inactive).</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstIdentity::drop-probability</NAME>
-<TYPE>gfloat</TYPE>
-<RANGE>[0,1]</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Drop Probability</NICK>
-<BLURB>The Probability a buffer is dropped.</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstIdentity::dump</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Dump</NICK>
-<BLURB>Dump buffer contents to stdout.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstIdentity::error-after</NAME>
-<TYPE>gint</TYPE>
-<RANGE>>= G_MAXULONG</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Error After</NICK>
-<BLURB>Error after N buffers.</BLURB>
-<DEFAULT>-1</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstIdentity::last-message</NAME>
-<TYPE>gchar*</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>last-message</NICK>
-<BLURB>last-message.</BLURB>
-<DEFAULT>NULL</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstIdentity::signal-handoffs</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Signal handoffs</NICK>
-<BLURB>Send a signal before pushing the buffer.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstIdentity::silent</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>silent</NICK>
-<BLURB>silent.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstIdentity::single-segment</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Single Segment</NICK>
-<BLURB>Timestamp buffers and eat segments so as to appear as one segment.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstIdentity::sleep-time</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Sleep time</NICK>
-<BLURB>Microseconds to sleep between processing.</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstIdentity::sync</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Synchronize</NICK>
-<BLURB>Synchronize to pipeline clock.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstIdentity::drop-buffer-flags</NAME>
-<TYPE>GstBufferFlags</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Check flags to drop buffers</NICK>
-<BLURB>Drop buffers with the given flags.</BLURB>
-<DEFAULT></DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstIdentity::ts-offset</NAME>
-<TYPE>gint64</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Timestamp offset for synchronisation</NICK>
-<BLURB>Timestamp offset in nanoseconds for synchronisation, negative for earlier sync.</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstIdentity::drop-allocation</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Drop allocation query</NICK>
-<BLURB>Don't forward allocation queries.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstIdentity::eos-after</NAME>
-<TYPE>gint</TYPE>
-<RANGE>>= G_MAXULONG</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>EOS After</NICK>
-<BLURB>EOS after N buffers.</BLURB>
-<DEFAULT>-1</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFileSrc::location</NAME>
-<TYPE>gchar*</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>File Location</NICK>
-<BLURB>Location of the file to read.</BLURB>
-<DEFAULT>NULL</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFileSink::append</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Append</NICK>
-<BLURB>Append to an already existing file.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFileSink::buffer-mode</NAME>
-<TYPE>GstFileSinkBufferMode</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Buffering mode</NICK>
-<BLURB>The buffering mode to use.</BLURB>
-<DEFAULT>Default buffering</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFileSink::buffer-size</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Buffering size</NICK>
-<BLURB>Size of buffer in number of bytes for line or full buffer-mode.</BLURB>
-<DEFAULT>65536</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFileSink::location</NAME>
-<TYPE>gchar*</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>File Location</NICK>
-<BLURB>Location of the file to write.</BLURB>
-<DEFAULT>NULL</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFdSrc::fd</NAME>
-<TYPE>gint</TYPE>
-<RANGE>>= 0</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>fd</NICK>
-<BLURB>An open file descriptor to read from.</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFdSrc::timeout</NAME>
-<TYPE>guint64</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Timeout</NICK>
-<BLURB>Post a message after timeout microseconds (0 = disabled).</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFdSink::fd</NAME>
-<TYPE>gint</TYPE>
-<RANGE>>= 0</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>fd</NICK>
-<BLURB>An open file descriptor to write to.</BLURB>
-<DEFAULT>1</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::can-activate-pull</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rwx</FLAGS>
-<NICK>Can activate pull</NICK>
-<BLURB>Can activate in pull mode.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::can-activate-push</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rwx</FLAGS>
-<NICK>Can activate push</NICK>
-<BLURB>Can activate in push mode.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::data</NAME>
-<TYPE>GstFakeSrcDataType</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>data</NICK>
-<BLURB>Data allocation method.</BLURB>
-<DEFAULT>Allocate data</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::datarate</NAME>
-<TYPE>gint</TYPE>
-<RANGE>>= 0</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Datarate</NICK>
-<BLURB>Timestamps buffers with number of bytes per second (0 = none).</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::dump</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Dump</NICK>
-<BLURB>Dump buffer contents to stdout.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::filltype</NAME>
-<TYPE>GstFakeSrcFillType</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>filltype</NICK>
-<BLURB>How to fill the buffer, if at all.</BLURB>
-<DEFAULT>Fill buffers with zeros</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::format</NAME>
-<TYPE>GstFormat</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Format</NICK>
-<BLURB>The format of the segment events.</BLURB>
-<DEFAULT>GST_FORMAT_BYTES</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::is-live</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rwx</FLAGS>
-<NICK>Is this a live source</NICK>
-<BLURB>True if the element cannot produce data in PAUSED.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::last-message</NAME>
-<TYPE>gchar*</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>last-message</NICK>
-<BLURB>The last status message.</BLURB>
-<DEFAULT>NULL</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::parentsize</NAME>
-<TYPE>gint</TYPE>
-<RANGE>>= 0</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>parentsize</NICK>
-<BLURB>Size of parent buffer for sub-buffered allocation.</BLURB>
-<DEFAULT>40960</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::pattern</NAME>
-<TYPE>gchar*</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>pattern</NICK>
-<BLURB>Set the pattern (unused).</BLURB>
-<DEFAULT>NULL</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::signal-handoffs</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Signal handoffs</NICK>
-<BLURB>Send a signal before pushing the buffer.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::silent</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Silent</NICK>
-<BLURB>Don't produce last_message events.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::sizemax</NAME>
-<TYPE>gint</TYPE>
-<RANGE>>= 0</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>sizemax</NICK>
-<BLURB>Maximum buffer size.</BLURB>
-<DEFAULT>4096</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::sizemin</NAME>
-<TYPE>gint</TYPE>
-<RANGE>>= 0</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>sizemin</NICK>
-<BLURB>Minimum buffer size.</BLURB>
-<DEFAULT>0</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::sizetype</NAME>
-<TYPE>GstFakeSrcSizeType</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>sizetype</NICK>
-<BLURB>How to determine buffer sizes.</BLURB>
-<DEFAULT>Send empty buffers</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSrc::sync</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Sync</NICK>
-<BLURB>Sync to the clock to the datarate.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSink::can-activate-pull</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Can activate pull</NICK>
-<BLURB>Can activate in pull mode.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSink::can-activate-push</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Can activate push</NICK>
-<BLURB>Can activate in push mode.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSink::dump</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Dump</NICK>
-<BLURB>Dump buffer contents to stdout.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSink::last-message</NAME>
-<TYPE>gchar*</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>Last Message</NICK>
-<BLURB>The message describing current status.</BLURB>
-<DEFAULT>NULL</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSink::num-buffers</NAME>
-<TYPE>gint</TYPE>
-<RANGE>>= G_MAXULONG</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>num-buffers</NICK>
-<BLURB>Number of buffers to accept going EOS.</BLURB>
-<DEFAULT>-1</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSink::signal-handoffs</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Signal handoffs</NICK>
-<BLURB>Send a signal before unreffing the buffer.</BLURB>
-<DEFAULT>FALSE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSink::silent</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Silent</NICK>
-<BLURB>Don't produce last_message events.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSink::state-error</NAME>
-<TYPE>GstFakeSinkStateError</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>State Error</NICK>
-<BLURB>Generate a state change error.</BLURB>
-<DEFAULT>No state change errors</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFakeSink::drop-out-of-segment</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Drop out-of-segment buffers</NICK>
-<BLURB>Drop and don't render / hand off out-of-segment buffers.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstCapsFilter::caps</NAME>
-<TYPE>GstCaps*</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Filter caps</NICK>
-<BLURB>Restrict the possible allowed capabilities (NULL means ANY). Setting this property takes a reference to the supplied GstCaps object.</BLURB>
-<DEFAULT></DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstCapsFilter::caps-change-mode</NAME>
-<TYPE>GstCapsFilterCapsChangeMode</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Caps Change Mode</NICK>
-<BLURB>Filter caps change behaviour.</BLURB>
-<DEFAULT>Only accept the current filter caps</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstDownloadBuffer::high-percent</NAME>
-<TYPE>gint</TYPE>
-<RANGE>[0,100]</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>High percent</NICK>
-<BLURB>High threshold for buffering to finish. Only used if use-buffering is True.</BLURB>
-<DEFAULT>99</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstDownloadBuffer::low-percent</NAME>
-<TYPE>gint</TYPE>
-<RANGE>[0,100]</RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Low percent</NICK>
-<BLURB>Low threshold for buffering to start. Only used if use-buffering is True.</BLURB>
-<DEFAULT>10</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstDownloadBuffer::max-size-bytes</NAME>
-<TYPE>guint</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Max. size (kB)</NICK>
-<BLURB>Max. amount of data to buffer (bytes, 0=disable).</BLURB>
-<DEFAULT>2097152</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstDownloadBuffer::max-size-time</NAME>
-<TYPE>guint64</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Max. size (ns)</NICK>
-<BLURB>Max. amount of data to buffer (in ns, 0=disable).</BLURB>
-<DEFAULT>2000000000</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstDownloadBuffer::temp-location</NAME>
-<TYPE>gchar*</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>Temporary File Location</NICK>
-<BLURB>Location to store temporary files in (Only read this property, use temp-template to configure the name template).</BLURB>
-<DEFAULT>NULL</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstDownloadBuffer::temp-remove</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Remove the Temporary File</NICK>
-<BLURB>Remove the temp-location after use.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstDownloadBuffer::temp-template</NAME>
-<TYPE>gchar*</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Temporary File Template</NICK>
-<BLURB>File template to store temporary files in, should contain directory and XXXXXX. (NULL == disabled).</BLURB>
-<DEFAULT>NULL</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstStreamidDemux::active-pad</NAME>
-<TYPE>GstPad*</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>Active pad</NICK>
-<BLURB>The currently active src pad.</BLURB>
-<DEFAULT></DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstConcat::active-pad</NAME>
-<TYPE>GstPad*</TYPE>
-<RANGE></RANGE>
-<FLAGS>r</FLAGS>
-<NICK>Active pad</NICK>
-<BLURB>Currently active src pad.</BLURB>
-<DEFAULT></DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstConcat::adjust-base</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Adjust segment base</NICK>
-<BLURB>Adjust the base value of segments to ensure they are adjacent.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstFunnel::forward-sticky-events</NAME>
-<TYPE>gboolean</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>Forward sticky events</NICK>
-<BLURB>Forward sticky events on stream changes.</BLURB>
-<DEFAULT>TRUE</DEFAULT>
-</ARG>
-
-<ARG>
-<NAME>GstDataURISrc::uri</NAME>
-<TYPE>gchar*</TYPE>
-<RANGE></RANGE>
-<FLAGS>rw</FLAGS>
-<NICK>URI</NICK>
-<BLURB>URI that should be used.</BLURB>
-<DEFAULT>NULL</DEFAULT>
-</ARG>
-
diff --git a/docs/plugins/gstreamer-plugins.hierarchy b/docs/plugins/gstreamer-plugins.hierarchy
deleted file mode 100644 (file)
index 4f5311d..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-GObject
-  GInitiallyUnowned
-    GstObject
-      GstAllocator
-        GstAllocatorSysmem
-      GstBus
-      GstClock
-      GstControlBinding
-      GstControlSource
-      GstElement
-        GstBaseSink
-          GstFakeSink
-          GstFdSink
-          GstFileSink
-        GstBaseSrc
-          GstDataURISrc
-          GstFakeSrc
-          GstFileSrc
-          GstPushSrc
-            GstFdSrc
-        GstBaseTransform
-          GstCapsFilter
-          GstIdentity
-        GstBin
-          GstPipeline
-        GstConcat
-        GstDownloadBuffer
-        GstFunnel
-        GstInputSelector
-        GstMultiQueue
-        GstOutputSelector
-        GstQueue
-        GstQueue2
-        GstStreamidDemux
-        GstTee
-        GstTypeFindElement
-        GstValve
-      GstPad
-        GstMultiQueuePad
-        GstSelectorPad
-      GstPadTemplate
-      GstPlugin
-      GstPluginFeature
-        GstDeviceProviderFactory
-        GstDynamicTypeFactory
-        GstElementFactory
-        GstTracerFactory
-        GstTypeFindFactory
-      GstRegistry
-      GstTask
-      GstTaskPool
-      GstTracer
-        GstLatencyTracer
-        GstLeaksTracer
-        GstLogTracer
-        GstRUsageTracer
-        GstStatsTracer
-      GstTracerRecord
-GInterface
-  GTypePlugin
-  GstChildProxy
-  GstURIHandler
diff --git a/docs/plugins/gstreamer-plugins.interfaces b/docs/plugins/gstreamer-plugins.interfaces
deleted file mode 100644 (file)
index fde573e..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-GstBin GstChildProxy
-GstDataURISrc GstURIHandler
-GstFdSink GstURIHandler
-GstFdSrc GstURIHandler
-GstFileSink GstURIHandler
-GstFileSrc GstURIHandler
-GstPipeline GstChildProxy
diff --git a/docs/plugins/gstreamer-plugins.prerequisites b/docs/plugins/gstreamer-plugins.prerequisites
deleted file mode 100644 (file)
index a8d518a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-GstChildProxy GObject
diff --git a/docs/plugins/gstreamer-plugins.signals b/docs/plugins/gstreamer-plugins.signals
deleted file mode 100644 (file)
index a0cf066..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-<SIGNAL>
-<NAME>GstTypeFindElement::have-type</NAME>
-<RETURNS>void</RETURNS>
-<FLAGS>l</FLAGS>
-GstTypeFindElement *gsttypefindelement
-guint  arg1
-GstCaps *arg2
-</SIGNAL>
-
-<SIGNAL>
-<NAME>GstQueue::overrun</NAME>
-<RETURNS>void</RETURNS>
-<FLAGS>f</FLAGS>
-GstQueue *gstqueue
-</SIGNAL>
-
-<SIGNAL>
-<NAME>GstQueue::pushing</NAME>
-<RETURNS>void</RETURNS>
-<FLAGS>f</FLAGS>
-GstQueue *gstqueue
-</SIGNAL>
-
-<SIGNAL>
-<NAME>GstQueue::running</NAME>
-<RETURNS>void</RETURNS>
-<FLAGS>f</FLAGS>
-GstQueue *gstqueue
-</SIGNAL>
-
-<SIGNAL>
-<NAME>GstQueue::underrun</NAME>
-<RETURNS>void</RETURNS>
-<FLAGS>f</FLAGS>
-GstQueue *gstqueue
-</SIGNAL>
-
-<SIGNAL>
-<NAME>GstMultiQueue::overrun</NAME>
-<RETURNS>void</RETURNS>
-<FLAGS>f</FLAGS>
-GstMultiQueue *gstmultiqueue
-</SIGNAL>
-
-<SIGNAL>
-<NAME>GstMultiQueue::underrun</NAME>
-<RETURNS>void</RETURNS>
-<FLAGS>f</FLAGS>
-GstMultiQueue *gstmultiqueue
-</SIGNAL>
-
-<SIGNAL>
-<NAME>GstIdentity::handoff</NAME>
-<RETURNS>void</RETURNS>
-<FLAGS>l</FLAGS>
-GstIdentity *gstidentity
-GstBuffer *arg1
-</SIGNAL>
-
-<SIGNAL>
-<NAME>GstFakeSrc::handoff</NAME>
-<RETURNS>void</RETURNS>
-<FLAGS>l</FLAGS>
-GstFakeSrc *gstfakesrc
-GstBuffer *arg1
-GstPad *arg2
-</SIGNAL>
-
-<SIGNAL>
-<NAME>GstFakeSink::handoff</NAME>
-<RETURNS>void</RETURNS>
-<FLAGS>l</FLAGS>
-GstFakeSink *gstfakesink
-GstBuffer *arg1
-GstPad *arg2
-</SIGNAL>
-
-<SIGNAL>
-<NAME>GstFakeSink::preroll-handoff</NAME>
-<RETURNS>void</RETURNS>
-<FLAGS>l</FLAGS>
-GstFakeSink *gstfakesink
-GstBuffer *arg1
-GstPad *arg2
-</SIGNAL>
-
-<SIGNAL>
-<NAME>GstQueue2::overrun</NAME>
-<RETURNS>void</RETURNS>
-<FLAGS>f</FLAGS>
-GstQueue2 *gstqueue2
-</SIGNAL>
-
diff --git a/docs/plugins/gstreamer-plugins.types b/docs/plugins/gstreamer-plugins.types
deleted file mode 100644 (file)
index 9f4950e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <gst/gst.h>
diff --git a/docs/plugins/index.md b/docs/plugins/index.md
new file mode 100644 (file)
index 0000000..7849fd8
--- /dev/null
@@ -0,0 +1,5 @@
+---
+short-description: GStreamer plugin from GStreamer core
+...
+
+# Core Plugin
diff --git a/docs/plugins/inspect/plugin-coreelements.xml b/docs/plugins/inspect/plugin-coreelements.xml
deleted file mode 100644 (file)
index 1afb8df..0000000
+++ /dev/null
@@ -1,412 +0,0 @@
-<plugin>
-  <name>coreelements</name>
-  <description>GStreamer core elements</description>
-  <filename>../../plugins/elements/.libs/libgstcoreelements.so</filename>
-  <basename>libgstcoreelements.so</basename>
-  <version>1.16.2</version>
-  <license>LGPL</license>
-  <source>gstreamer</source>
-  <package>GStreamer source release</package>
-  <origin>Unknown package origin</origin>
-  <elements>
-    <element>
-      <name>capsfilter</name>
-      <longname>CapsFilter</longname>
-      <class>Generic</class>
-      <description>Pass data without modification, limiting formats</description>
-      <author>David Schleef &lt;ds@schleef.org&gt;</author>
-      <pads>
-        <caps>
-          <name>sink</name>
-          <direction>sink</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-        <caps>
-          <name>src</name>
-          <direction>source</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>concat</name>
-      <longname>Concat</longname>
-      <class>Generic</class>
-      <description>Concatenate multiple streams</description>
-      <author>Sebastian Dröge &lt;sebastian@centricular.com&gt;</author>
-      <pads>
-        <caps>
-          <name>sink_%u</name>
-          <direction>sink</direction>
-          <presence>request</presence>
-          <details>ANY</details>
-        </caps>
-        <caps>
-          <name>src</name>
-          <direction>source</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>dataurisrc</name>
-      <longname>data: URI source element</longname>
-      <class>Source</class>
-      <description>Handles data: uris</description>
-      <author>Philippe Normand &lt;pnormand@igalia.com&gt;, Sebastian Dröge &lt;sebastian.droege@collabora.co.uk&gt;</author>
-      <pads>
-        <caps>
-          <name>src</name>
-          <direction>source</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>downloadbuffer</name>
-      <longname>DownloadBuffer</longname>
-      <class>Generic</class>
-      <description>Download Buffer element</description>
-      <author>Wim Taymans &lt;wim.taymans@gmail.com&gt;</author>
-      <pads>
-        <caps>
-          <name>sink</name>
-          <direction>sink</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-        <caps>
-          <name>src</name>
-          <direction>source</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>fakesink</name>
-      <longname>Fake Sink</longname>
-      <class>Sink</class>
-      <description>Black hole for data</description>
-      <author>Erik Walthinsen &lt;omega@cse.ogi.edu&gt;, Wim Taymans &lt;wim@fluendo.com&gt;, Mr. &apos;frag-me-more&apos; Vanderwingo &lt;wingo@fluendo.com&gt;</author>
-      <pads>
-        <caps>
-          <name>sink</name>
-          <direction>sink</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>fakesrc</name>
-      <longname>Fake Source</longname>
-      <class>Source</class>
-      <description>Push empty (no data) buffers around</description>
-      <author>Erik Walthinsen &lt;omega@cse.ogi.edu&gt;, Wim Taymans &lt;wim@fluendo.com&gt;</author>
-      <pads>
-        <caps>
-          <name>src</name>
-          <direction>source</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>fdsink</name>
-      <longname>Filedescriptor Sink</longname>
-      <class>Sink/File</class>
-      <description>Write data to a file descriptor</description>
-      <author>Erik Walthinsen &lt;omega@cse.ogi.edu&gt;</author>
-      <pads>
-        <caps>
-          <name>sink</name>
-          <direction>sink</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>fdsrc</name>
-      <longname>Filedescriptor Source</longname>
-      <class>Source/File</class>
-      <description>Read from a file descriptor</description>
-      <author>Erik Walthinsen &lt;omega@cse.ogi.edu&gt;</author>
-      <pads>
-        <caps>
-          <name>src</name>
-          <direction>source</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>filesink</name>
-      <longname>File Sink</longname>
-      <class>Sink/File</class>
-      <description>Write stream to a file</description>
-      <author>Thomas Vander Stichele &lt;thomas at apestaart dot org&gt;</author>
-      <pads>
-        <caps>
-          <name>sink</name>
-          <direction>sink</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>filesrc</name>
-      <longname>File Source</longname>
-      <class>Source/File</class>
-      <description>Read from arbitrary point in a file</description>
-      <author>Erik Walthinsen &lt;omega@cse.ogi.edu&gt;</author>
-      <pads>
-        <caps>
-          <name>src</name>
-          <direction>source</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>funnel</name>
-      <longname>Funnel pipe fitting</longname>
-      <class>Generic</class>
-      <description>N-to-1 pipe fitting</description>
-      <author>Olivier Crete &lt;olivier.crete@collabora.co.uk&gt;</author>
-      <pads>
-        <caps>
-          <name>sink_%u</name>
-          <direction>sink</direction>
-          <presence>request</presence>
-          <details>ANY</details>
-        </caps>
-        <caps>
-          <name>src</name>
-          <direction>source</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>identity</name>
-      <longname>Identity</longname>
-      <class>Generic</class>
-      <description>Pass data without modification</description>
-      <author>Erik Walthinsen &lt;omega@cse.ogi.edu&gt;</author>
-      <pads>
-        <caps>
-          <name>sink</name>
-          <direction>sink</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-        <caps>
-          <name>src</name>
-          <direction>source</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>input-selector</name>
-      <longname>Input selector</longname>
-      <class>Generic</class>
-      <description>N-to-1 input stream selector</description>
-      <author>Julien Moutte &lt;julien@moutte.net&gt;, Jan Schmidt &lt;thaytan@mad.scientist.com&gt;, Wim Taymans &lt;wim.taymans@gmail.com&gt;</author>
-      <pads>
-        <caps>
-          <name>sink_%u</name>
-          <direction>sink</direction>
-          <presence>request</presence>
-          <details>ANY</details>
-        </caps>
-        <caps>
-          <name>src</name>
-          <direction>source</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>multiqueue</name>
-      <longname>MultiQueue</longname>
-      <class>Generic</class>
-      <description>Multiple data queue</description>
-      <author>Edward Hervey &lt;edward@fluendo.com&gt;</author>
-      <pads>
-        <caps>
-          <name>sink_%u</name>
-          <direction>sink</direction>
-          <presence>request</presence>
-          <details>ANY</details>
-        </caps>
-        <caps>
-          <name>src_%u</name>
-          <direction>source</direction>
-          <presence>sometimes</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>output-selector</name>
-      <longname>Output selector</longname>
-      <class>Generic</class>
-      <description>1-to-N output stream selector</description>
-      <author>Stefan Kost &lt;stefan.kost@nokia.com&gt;</author>
-      <pads>
-        <caps>
-          <name>sink</name>
-          <direction>sink</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-        <caps>
-          <name>src_%u</name>
-          <direction>source</direction>
-          <presence>request</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>queue</name>
-      <longname>Queue</longname>
-      <class>Generic</class>
-      <description>Simple data queue</description>
-      <author>Erik Walthinsen &lt;omega@cse.ogi.edu&gt;</author>
-      <pads>
-        <caps>
-          <name>sink</name>
-          <direction>sink</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-        <caps>
-          <name>src</name>
-          <direction>source</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>queue2</name>
-      <longname>Queue 2</longname>
-      <class>Generic</class>
-      <description>Simple data queue</description>
-      <author>Erik Walthinsen &lt;omega@cse.ogi.edu&gt;, Wim Taymans &lt;wim.taymans@gmail.com&gt;</author>
-      <pads>
-        <caps>
-          <name>sink</name>
-          <direction>sink</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-        <caps>
-          <name>src</name>
-          <direction>source</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>streamiddemux</name>
-      <longname>Streamid Demux</longname>
-      <class>Generic</class>
-      <description>1-to-N output stream by stream-id</description>
-      <author>HoonHee Lee &lt;hoonhee.lee@lge.com&gt;</author>
-      <pads>
-        <caps>
-          <name>sink</name>
-          <direction>sink</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-        <caps>
-          <name>src_%u</name>
-          <direction>source</direction>
-          <presence>sometimes</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>tee</name>
-      <longname>Tee pipe fitting</longname>
-      <class>Generic</class>
-      <description>1-to-N pipe fitting</description>
-      <author>Erik Walthinsen &lt;omega@cse.ogi.edu&gt;, Wim Taymans &lt;wim@fluendo.com&gt;</author>
-      <pads>
-        <caps>
-          <name>sink</name>
-          <direction>sink</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-        <caps>
-          <name>src_%u</name>
-          <direction>source</direction>
-          <presence>request</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>typefind</name>
-      <longname>TypeFind</longname>
-      <class>Generic</class>
-      <description>Finds the media type of a stream</description>
-      <author>Benjamin Otte &lt;in7y118@public.uni-hamburg.de&gt;</author>
-      <pads>
-        <caps>
-          <name>sink</name>
-          <direction>sink</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-        <caps>
-          <name>src</name>
-          <direction>source</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-    <element>
-      <name>valve</name>
-      <longname>Valve element</longname>
-      <class>Filter</class>
-      <description>Drops buffers and events or lets them through</description>
-      <author>Olivier Crete &lt;olivier.crete@collabora.co.uk&gt;</author>
-      <pads>
-        <caps>
-          <name>sink</name>
-          <direction>sink</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-        <caps>
-          <name>src</name>
-          <direction>source</direction>
-          <presence>always</presence>
-          <details>ANY</details>
-        </caps>
-      </pads>
-    </element>
-  </elements>
-</plugin>
diff --git a/docs/plugins/inspect/plugin-coretracers.xml b/docs/plugins/inspect/plugin-coretracers.xml
deleted file mode 100644 (file)
index bfd3a52..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-<plugin>
-  <name>coretracers</name>
-  <description>GStreamer core tracers</description>
-  <filename>../../plugins/tracers/.libs/libgstcoretracers.so</filename>
-  <basename>libgstcoretracers.so</basename>
-  <version>1.16.2</version>
-  <license>LGPL</license>
-  <source>gstreamer</source>
-  <package>GStreamer source release</package>
-  <origin>Unknown package origin</origin>
-  <elements>
-    <tracer>
-      <name>latency</name>
-    </tracer>
-    <tracer>
-      <name>leaks</name>
-    </tracer>
-    <tracer>
-      <name>log</name>
-    </tracer>
-    <tracer>
-      <name>rusage</name>
-    </tracer>
-    <tracer>
-      <name>stats</name>
-    </tracer>
-  </elements>
-</plugin>
\ No newline at end of file
diff --git a/docs/plugins/sitemap.txt b/docs/plugins/sitemap.txt
new file mode 100644 (file)
index 0000000..058a271
--- /dev/null
@@ -0,0 +1 @@
+gst-index
diff --git a/docs/random/API b/docs/random/API
deleted file mode 100644 (file)
index 4962b32..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-* signals should use dashes in their names, not underscores, so ::notify
-  works correctly
diff --git a/docs/random/TODO-pre-0.9 b/docs/random/TODO-pre-0.9
deleted file mode 100644 (file)
index c751518..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-TODO:
------
-
-short term core API stability
------------------------------
-
-Changes that probably impact the API, careful discussion (IRC) + design doc is required
-before changes are accepted.
-
-target release ! description
-               !
-  0.4.1        ! expose and API to query the supported seek formats/flags on
-  (done)       ! pads, something like an extra arg to gst_pad_set_convert_function
-               ! and gst_pad_set_event_function with some function to query the 
-               ! flags and formats. more ideas in docs/random/wtay/query_events
-              !  (API: medium difficulty)
-              !
-  0.4.1        ! add event for segment playback/looping and seeking (docs/random/wtay/segments)
-  (done)       !  (API: medium difficulty, plugins: HARD to very HARD)
-              !
-    ?          ! add event to adjust rate (reverse playback, slow motion, frame skipping)
-               ! (docs/random/wtay/rate_event)
-              !  (API: medium difficulty, plugins: HARD to very HARD)
-              ! 
-    ?         ! add method in the scheduler to set the entry point (frame stepping?)
-              ! (docs/random/wtay/scheduler_entry)
-              !  (API: moderatly EASY, scheduler implementation MEDIUM)
-              !
-   0.6.0       ! create a design doc for a timecache implementation, 
-   (done)      ! (docs/wtay/random/timecache)
-              !  (API: MEDIUM, needs lots of discussion, plugin implementation MEDIUM to HARD)
-              ! (done: implemented using GstIndex base class + subclasses)
-              !
-    ?         ! implement a QoS event and a policy for handling the event.
-               !  (API: kindof EASY, plugins MEDIUM to very HARD)
-              !
-   0.4.1       ! implement user defined GstFormat values, make a format factory etc..
-   (done)      !  (API: MEDIUM, plugins MEDIUM)
-              !
-    ?         ! strip the API to a bare bones minimal set of functions, leave the automatic
-               ! stuff to the app instead of forcing a policy in the core.
-              ! create a library with useful higher level function for people who don't want
-              ! to deal with the lowlevel stuff.
-              ! (HARD, need to negotiate with people :))
-              !
-    ?         ! use GMarkup to load/save objects, remove dependency on libxml2
-               ! (MEDIUM) breaks API/ABI compatibility
-              !
-              
-
-shortterm core feature enhancements
------------------------------------
-
-   0.4.1       ! Implement PAD_DISABLED. This requires simple checks in the scheduler so that
-               ! it doesn't try to pull/push data from/to a disabled pad.
-              ! When an element goes to the PAUSED state, all of its pads should be disabled. 
-              ! This should also work for ghostpads.
-               !  (API: MEDIUM to moderatly HARD, requires some scheduler understanding)
-
-
-short term usability
---------------------
-
-Writing docs is NOT boring, you learn a lot, you get insight in stuff, you help a lot
-of people, hey! you might even find YOUR book on a shelf in a bookstore!!
-
-
-    ?          ! plugin writers guide
-               ! (we have almost nothing, so any start is welcomed)
-              ! (MEDIUM)
-               !
-    ?          ! app writers guide needs to cover common tips and tricks and HOWTOs
-               ! (MEDIUM)
-
-short to midterm policy definition
-----------------------------------
-
-Policy definition is closely related to a HOWTO but sometimes needs some thinking.
-
-
-    ?          ! document thread safety guidelines, what stuff needs locking in the app, what
-               ! is done in the core.
-              ! most of this stuff is in the heads of various people but needs to be written
-              ! down so that people get more insights into the design and vision of GStreamer.
-              ! (MEDIUM, some research and discussion needed)
-              !
-    ?         ! a step by step guide to the implementation of various events in a plugin, what can you
-              ! do, when is data passing forbidden etc..
-              ! (MEDIUM, some research needed)
-              ! 
-    ?         ! figure out a policy for the NEW_MEDIA event
-              ! (MEDIUM to HARD)
-              !
-    ?          ! figure out how to better handle clock resync
-              ! (MEDIUM to HARD)
-              !
-            
-
-midterm feature enhancement
----------------------------
-   
-  0.6.0        | Define and implement a syntax in gst_parse to handle filtered pad connections.
-  (done)       | (MEDIUM)
-              |
-    ?          | Figure out a way to set properties on schedulers (and bins?) from gst_parse.
-               | (MEDIUM)
-              |
-    ?          | Make gst-inspect do inspection of plugins, schedulers, autopluggers, types.
-               | An idea would be to make -inspect output an XML representation of the objects
-              | and use XSLT to transform this into text, HTML, docbook, ...
-               | (MEDIUM to EASY)
-              |
-
-
-midterm (longterm) optimisations
---------------------------------
-
-These optimisations can be done without changing the existing API.
-
-
- (in progress) ! implement an optimal scheduler that uses chaining when possible
-               ! (HARD, requires detailed knowledge of element scheduling)
-              !
-    ?         ! alternatively optimisations to the current scheduler can be done such
-              ! as: do nothing when the pipeline structure (or chain) has not changed
-              ! (MEDIUM)
-              !
-    ?         ! GstQueue is a little mess. implement a better queue (lockfree?), refactor
-               ! queueing policy (max buffer, max time, levels etc..)
-              ! (MEDIUM to farily EASY)
-
-
-longterm feature enhancements
------------------------------
-
-Various features that are not critical yet.
-
-    ?          ! factory aliases. map a generic name like "videosink" to and actual
-               ! user configurable plugin (aasink, sdlsink, xvideosink, ...)
-              ! (MEDIUM)
-              !
-    ?          ! property proxy in compount elements. not sure if it's possible at all.
-               ! what with elements with the same property?
-              ! (MEDIUM, needs some thinking)
-               !
-    ?          ! Make _pad_select work for muxers
-               ! (MEDIUM to HARD)
-
-
-needs consensus
----------------
-
-Some stuff that needs to be figured out based on a pro/con comparison.
-
-    ?          ! can we decide on the fact that downstream events are traveling using the
-               ! scheduler? do we need to reevaluate that design decision?
-              ! (MEDIUM, needs pros vs cons document)
-
-
-benchmarks
-----------
-
-Benchmarks are always good to get acceptance in a wider comunity or to identify performance 
-problems that need fixing.
-
-    ?          ! do a latency comparison with popular other frameworks, document GStreamer
-               ! overhead.
-              ! (MEDIUM to somewhat EASY)
-              ! 
diff --git a/docs/random/autoplug1 b/docs/random/autoplug1
deleted file mode 100644 (file)
index f3f94df..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-COMPLETELY OUTDATED
--------------------
-
-
-A little explanation of the first autoplugger in GStreamer:
-
-Autoplugging is implemented in the following places:
-
- gstpipeline.c : construction of the pipeline
- gstautoplug.c : selection of the elementfactories needed for autoplugging
-
-1) pipeline setup
------------------
-
-before any autoplugging will take place, a new GstPipeline has to be created.
-The autoplugger needs to have a src element and one or more sink elements. the
-autoplugger will try to find the elements needed to connect the src element
-to the sinks.
-
-using:
-
-  gst_pipeline_add_src (GstPipeline *pipeline, GstElement *element);
-
-a source element is added to the pipeline. only one src element can be added
-for now.
-
-using:
-
-  gst_pipeline_add_sink (GstPipeline *pipeline, GstElement *element);
-
-a sink element can be added to the pipeline.
-
-2) starting autoplug
---------------------
-
-when the pipeline has been set up as above, you will call
-
-  gst_pipeline_autoplug (GstPipeline *pipeline);
-
-to start the autoplugger. this will be done in four phases
-
-ex. we are going to autoplug an mpeg1 system stream.
-
-2a) phase1: figure out the type (GstCaps) of the src element.
--------------------------------------------------------------
-
-the gsttypefind element is connected to the "src" pad of the source
-element. gst_bin_iterate is called in a loop until gsttypefind
-signals "have_type". the gst_bin_iterate is stopped and the GstCaps
-is retrieved from the gsttypefind element.
-
-gsttypefind is disconnected from the src element and removed from the 
-bin.
-
-the GstCaps of the source element is called src_caps later on.
-
-ex. all typefind functions are tried and the one in mpeg1types will
-     return a GstCaps:
-
-        video/mpeg,
-       "systemstream", GST_PROPS_BOOLEAN (TRUE),
-       "mpegversion",  GST_PROPS_INT (1),
-       NULL
-
-
-2b) phase2: create lists of factories.
----------------------------------------
-
-for each sink:
-{
-   sinkpad = take the first sinkpad of the sink (HACK)
-   call
-   
-   list[i] = gst_autoplug_caps (src_caps, sinkpad->caps);
-     
-   I++;
-}
-
-gst_autoplug_caps will figure out (based on the padtemplates)
-which elementfactories are needed to connect src_caps to sinkpad->caps
-and will return them in a list.
-
-ex. we have two sinks with following caps:
-
-        video/raw                    audio/raw
-       "...."                       "...."
-
- gst_autoplug_caps will figure out that for the first sink the following
- elements are needed:
-
-   mpeg1parse, mp1videoparse, mpeg_play
-
- for the second sink the following is needed:
-
-   mpeg1parse, mp3parse, mpg123
-
- We now have two lists of elementfactories.
-
-2c) phase3: collect common elements from the lists.
----------------------------------------------------
-
-the rationale is that from the lists we have created in phase2, there
-must be some element that is a splitter and that it has to come first (HACK)
-We try to find that element by comparing the lists until an element differs.
-
-we add the common elements to the bin and run gst_pipeline_pads_autoplug. this
-function will loop over the pads of the previous element and the one we
-just added, and tries to connect src to sink if possible. 
-
-If a connection between the two elements could not be made, a signal "new_pad"
-is connected to the element so that pad connection can occur later on when
-the pad is actually created.
-
-ex. when we compare the two lists we see that we have common element: mpeg1parse.
-
- we add this element to the bin and try to connect it to the previous element in
- the bin, the disksrc.
-
- we see that the src pad of the disksrc and the sinkpad of the mpeg1parse element
- can be connected because they are compatible. We have a pipeline like:
-
-  ---------)         (--------
-   disksrc !         ! mpeg1parse
-           src --- sink
-  ---------)         (--------
-
-
-2d) phase4: add remaining elements
-----------------------------------
-
-now we loop over all the list and try to add the remaining elements
-
-(HACK) we always use a new thread for the elements when there is a common
-element found.
-
-if a new thread is needed (either bacuase the previous element is a common
-element or the object flag of the next element is set to GST_SUGGEST_THREAD)
-we add a queue to the bin and we add a new thread. We add the elements to
-the bin and connect them using gst_pipeline_pads_autoplug.
-
-If we add a queue, we have to copy the caps of the sink element of the queue
-to the src pad of the queue (else they won't connect)
-
-we finally arrive at the sink element and we're done.
-
-ex.
-    
-     we have just found our mpeg1parse common element, so we start a thread.
-     We add a queue to the bin and a new thread, we add the elements
-     mp1videoparse and mpeg_play to the thread. We arrive at the videosink, we
-     see that the SUGGEST_THREAD flag is set, we add a queue and a thread and
-     add the videosink in the thread.
-     the same procedure happens for the audio part. We are now left with the
-     following pipeline:
-
-     We will also have set a signal "new_pad" on the mpeg1parse element because
-     the element mp1videoparse could not be connected to the element just yet.
-
-                                                 (------------------------------------)         (----------
-                                                 !thread                              !         ! thread
-                                                 ! (-------------)       (---------)  !         ! (---------)
-                                                ! !mp1videoparse!       !mpeg_play!  !         ! !videosink!
-                                   videoqueue--sink             src -- sink      src -- queue --- sink     !
-  ---------)         (-----------)               ! (-------------)       (---------)  !         ! (---------)
-   disksrc !         ! mpeg1parse!               (------------------------------------)         (-------------
-           src --- sink          !
-  ---------)         (-----------)    
-                                      queue-----  same for audio
-
-
-   then we play, create_plan happens, data is flowing and the "new_pad" signal is called
-   from mpeg1parse, gst_pipeline_pad_autoplug is called and the connection between
-   mpeg1parse and the videoqueue is made. same for audio.
-
-   voila. smame procedure for mp3/vorbis/avi/qt/mpeg2 etc...
-
-
-Problems:
----------
-
-this is obviously a very naive solution. the creation of the elements actually happens
-beforehand. MPEG2, for one, fails because there are multiple possibilities to go
-from the mpeg demuxer to audio/raw (ac3, mp3)
-
-Also any intermedia elements like mixers (subtitles) are not possible because we 
-assume that after the common elements, the streams to not converge anymore.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/random/autoplug2 b/docs/random/autoplug2
deleted file mode 100644 (file)
index f3374b6..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-
-1) The Autoplugger API
-----------------------
-
-We'll first describe how to use the autoplugger. We will provide
-a use case: autoplug an mpeg1 system stream for audio/video playback.
-
-
-a) creating an autoplugger
---------------------------
-
-Before any autoplugging can be done, you'll have to create an 
-autoplugger object. Autoplugger objects (autopluggers) are 
-provided by plugins and are created with gst_autoplugfactor_make().
-
-GStreamer has provisions for two types of autopluggers:
-
- - regular autopluggers, which act as a complex element construction
-   mechanism. They usually don't create threads and operate solely on
-   GstCaps* for the source and destination. The complex elements 
-   created by regular autopluggers have src and sink pad compatible 
-   with the requested GstCaps*.
- - renderer autopluggers, which are designed to create a complex
-   object that can be used to playback media. Renderer autoplugged
-   complex elements have no src pads, only one sink pad.
-
-We'll create a renderer autoplugger like this:
-
-!
-!  GstAutoplug *autoplug;
-!
-!  autoplug = gst_autoplugfactory_make ("staticrender");
-!
-
-
-b) finding out the source media type.
--------------------------------------
-
-Before we can start the autoplugger, we have to find out the 
-source media type. This can be done using the typefind functions 
-provided by various plugins.
-
-We will create a little pipeline to detect the media type by connecting
-a disksrc element to a typefind element. The typefind element will 
-repeatedly call all registered typefind functions with the buffer it
-receives on its sink pad. when a typefind function returns a non NULL
-GstCaps*, that caps is set to the sink pad of the typefind element and
-a signal is emitted to notify the app.
-
-Due to caps negotiation, the disksrc will have the detected GstCaps* 
-set on its src pad.
-
-We typically use a function like below to detect the type of a media stream
-on an element (typically a disksrc). The function accepts a pipeline and the
-element inside the pipeline on which the typefind should be performed (passing
-a GstPad* is probably a better option FIXME).
-
-! 
-! static GstCaps*
-! gst_play_typefind (GstBin *bin, GstElement *element)
-! {
-!   GstElement *typefind;
-!   GstCaps *caps = NULL;
-! 
-!   typefind = gst_elementfactory_make ("typefind", "typefind");
-!   g_return_val_if_fail (typefind != NULL, FALSE);
-! 
-!   gst_pad_connect (gst_element_get_pad (element, "src"),
-!                    gst_element_get_pad (typefind, "sink"));
-! 
-!   gst_bin_add (bin, typefind);
-! 
-!   gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
-! 
-!   // push a buffer... the have_type signal handler will set the found flag
-!   gst_bin_iterate (bin);
-! 
-!   gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
-! 
-!   caps = gst_pad_get_caps (gst_element_get_pad (element, "src"));
-! 
-!   gst_pad_disconnect (gst_element_get_pad (element, "src"),
-!                       gst_element_get_pad (typefind, "sink"));
-!   gst_bin_remove (bin, typefind);
-!   gst_object_unref (GST_OBJECT (typefind));
-! 
-!   return caps;
-! }
-! 
-
-Also note that the disksrc was added to the pipeline before calling this
-typefind function.
-
-When the function returns a non-NULL pointer, the media type has been 
-determined and autoplugging can commence.
-
-Assume that in our mpeg1 use case the above function returns a GstCaps* 
-like:
-
-!
-!  srccaps = GST_CAPS_NEW ("mpeg1system_typefind",
-!                          "video/mpeg",
-!                            "mpegversion",  GST_PROPS_INT (1),
-!                            "systemstream", GST_PROPS_BOOLEAN (TRUE)
-!                         );
-!
-
-
-c) Performing the autoplugging
-------------------------------
-
-Since we use the renderer API, we have to create the output elements
-that are going to be used as the final sink elements.
-
-!
-!  osssink = gst_elementfactory_make("osssink", "play_audio");
-!  videosink = gst_elementfactory_make("xvideosink", "play_video");
-!  
-  
-We then create a complex element using the following code.
-
-!
-!  new_element = gst_autoplug_to_renderers (autoplug,
-!           srccaps,
-!           videosink,
-!           osssink,
-!           NULL);
-!
-!  if (!new_element) {
-!    g_print ("could not autoplug, no suitable codecs found...\n");
-!    exit (-1);
-!  }
-!
-
-2) Autoplugging internals
--------------------------
-
-We will now describe the internals of the above gst_autoplug_to_renderers()
-function call. This code is implemented in a plugin found in:
-
-    gst/autoplug/gststaticautoplugrender.c
-
-
-
-a) phase1: create lists of factories.
----------------------------------------
-
-The autoplugger will start with executing the following piece of
-code:
-
-!
-! i = 0;
-!
-! for each sink:
-! {
-!   sinkpad = take the first sinkpad of the sink (HACK)
-!   
-!   list[i] = gst_autoplug_caps (srccaps, sinkpad->caps);
-!     
-!   i++;
-! }
-!
-
-gst_autoplug_caps will figure out (based on the padtemplates)
-which elementfactories are needed to connect srccaps to sinkpad->caps
-and will return them in a list.
-
-The element list is created by using a modified shortest path algorithm
-by Dijkstra (http://www.orie.cornell.edu/~or115/handouts/handout3/handout3.html).
-The nodes of the graph are the elementfactories and the weight of the
-arcs is based on the pad compatibility of the padtemplates of the 
-elementfactory. For incompatible elementfactories, we use a weight of 
-MAX_COST (999999) and for compatible padtemplates we use 1.
-
-ex. we have two sinks with following caps:
-
-!
-!       video/raw                   audio/raw
-!      "...."                       "...."
-!
-
-gst_autoplug_caps will figure out that for the first sink the following
-elements are needed:
-
-!
-!   mpeg1parse, mp1videoparse, mpeg_play
-!
-
-for the second sink the following is needed:
-!
-!   mpeg1parse, mad
-!
-
-Note that for the audio connection the element list "mpeg1parse, mp3parse,
-mpg123" would also connect the srccaps to the audiosink caps. Since the
-"mpeg1parse, mad" list is shorter, it it always preferred by the autoplugger.
-
-We now have two lists of elementfactories.
-
-
-b) phase2: collect common elements from the lists and add them to a bin.
-------------------------------------------------------------------------
-
-The rationale is that from the lists we have created in phase1, there
-must be some element that is a splitter and that it has to come first (HACK)
-We try to find that element by comparing the lists until an element differs.
-
-We start by creating a toplevel bin that is going to be our complex element.
-
-In our use-case we find that mpeg1parse is an element common to both lists,
-so we add it to the bin. We then try to find a good ghostpad for the resulting
-complex element. This is done by looping over the sink pads of the first common
-element and taking the pad that is compatible with the srcaps.
-
-We end up with a bin like this:
-!
-!  (----------------------)
-!  ! autoplug_bin         !
-!  !                      !
-!  !       (------------) !
-!  !       ! mpeg1parse ! !
-!  !   - sink           ! !
-!  !  /    (------------) !
-! sink                    !
-!  (----------------------)
-!
-
-
-c) phase3: add remaining elements
----------------------------------
-
-now we loop over all the list and try to add the remaining elements
-
-(HACK) we always use a new thread for the elements when there is a common
-element found.
-
-if a new thread is needed (either because the previous element is a common
-element or the object flag of the next element is set to GST_SUGGEST_THREAD)
-we add a queue to the bin and we add a new thread. We add the elements to
-the bin and connect them using gst_pipeline_pads_autoplug. 
-
-we finally arrive at the sink element and we're done.
-
-ex.
-    
-     we have just found our mpeg1parse common element, so we start a thread.
-     We add a queue to the bin and a new thread, we add the elements
-     mp1videoparse and mpeg_play to the thread. We arrive at the videosink, we
-     see that the SUGGEST_THREAD flag is set, we add a queue and a thread and
-     add the videosink in the thread.
-     the same procedure happens for the audio part. We are now left with the
-     following pipeline:
-
-     We will also have set a signal "new_pad" on the mpeg1parse element because
-     the element mp1videoparse could not be connected to the element just yet.
-
-  (---------------------------------------------------------------------------------------------)
-  !autoplug_bin                                                                                 !
-  !                                                                                             !
-  !                                   (----------------------------------------) (------------) !
-  !                                   !thread                                  ! ! thread     ! !
-  !                         (-----)   ! (-------------)   (---------)  (-----) ! ! (---------)! !
-  !                        !queue!   ! !mp1videoparse!   !mpeg_play!  !queue! ! ! !videosink!! !
-  !                         sink src-sink            src-sink      src-sink src-sink         !! !
-  !       (-----------)     (-----)   ! (-------------)   (---------)  (-----) ! ! (---------)! !
-  !       ! mpeg1parse!               (----------------------------------------) (------------) !
-  !   - sink          !                                                                         !
-  !  /    (-----------)                                                                         !
- sink                                 (----------------------------------------) (------------) !
-  !                                   !thread                                  ! ! thread     ! !
-  !                         (-----)   ! (-------------)                (-----) ! ! (---------)! !
-  !                        !queue!   ! !mad          !                !queue! ! ! !videosink!! !
-  !                         sink src-sink            src ------------ sink  src-sink         !! !
-  !                         (-----)   ! (-------------)                (-----) ! ! (---------)! !
-  !                                   (----------------------------------------) (------------) !
-  (---------------------------------------------------------------------------------------------)
-
-   The autoplugger will return the autoplug_bin. the app will then connect the 
-   disksrc to the sinkpad of the autoplugged bin.
-
-   Then we play, create_plan happens, data is flowing and the "new_pad" signal is called
-   from mpeg1parse, gst_pipeline_pad_autoplug is called and the connection between
-   mpeg1parse and the videoqueue is made. same for audio.
-
-   Et voila. same procedure for mp3/vorbis/avi/qt/mpeg2 etc...
-
diff --git a/docs/random/autotools b/docs/random/autotools
deleted file mode 100644 (file)
index 08e04fa..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-These are some notes on our autotools setup, and some things to remember.
-
-plugin Makefile.am:
-- plugindir gets defined for you, don't set it in Makefile.am 
-- plugin_LTLIBRARIES should contain the name of every plugin,
-  starting with libgst and ending in .la
-
-- put compile/link variables in the following order: CFLAGS, LIBADD, LDFLAGS
-- order _CFLAGS and _LIBADD with the highest in the stack first;
-  e.g. $(GST_PLUGINS_BASE_LIBS) $(GST_LIBS) $(MUSICBRAINZ_LIBS)
-  this makes sure that the one you're most likely to be hacking on
-  (GStreamer) has its -L flags pointing to your hacking directory,
-  and comes first on the link line.  If it were to come later and you
-  had the library installed in the same place as the dependency, it
-  would take that version instead
-- DO NOT put any libraries in _LDFLAGS.  Typically, _LDFLAGS should only
-  have $(GST_PLUGIN_LDFLAGS)
-- when using gst-plugins-base libraries, use $(GST_PLUGINS_BASE_LIBS) then
-  add -lgst(library)-$(GST_API_VERSION).  Example:
-
-libgstsdlvideosink_la_LIBADD =  $(GST_PLUGINS_BASE_LIBS) \
-                                -lgstvideo-$(GST_API_VERSION) \
-                                -lgstaudio-$(GST_API_VERSION) \
-                                -lgstinterfaces-$(GST_API_VERSION) \
-                                $(SDL_LIBS)
-
-
-- don't forget to use noinst_HEADERS if you have private headers
-
-plugin configure.ac snippet:
-  - ORDER THEM ALPHABETICALLY PLEASE
-  - wrap your check in a block like this:
-
-translit(dnm, m, l) AM_CONDITIONAL(USE_DEP, true)
-  GST_CHECK_FEATURE(DEP, [(dependency description)], (plug-in-name), [
-    (here go the checks)
-])
-  - plug-in name is the name of the *plug-in*, not the element; ie, the
-    first column when running gst-inspect
-
-  - For the checks, in the simplest case, use something like:
-    GST_PKG_CHECK_MODULES(FOO, foo-0.3 >= 0.3.2)
-    This will:
-    - do the check
-    - show a decent message if it can't find it, without failing
-    - set HAVE_FOO to yes or no
-    - set FOO_CFLAGS and FOO_LIBS
-  - if you want to make sure configure fails when this dependency is missing,
-    use:
-    GST_PKG_CHECK_MODULES(FOO, libfoo-0.3 >= 0.3.2, yes)
-
-  - if your library does not come with a .pc file, you have to roll your own
-    check
-
-pkg.m4: (last checked: version 0.20)
-  - was changed at some point to hide the error message from you, and error
-    out by default if no ACTION-IF-NOT-FOUND is given.
-  - caller is responsible for doing AC_MSG_RESULT if ACTION-IF-NOT-FOUND
-    is given
-  - for automake-1.6, AC_SUBST((PKG)_CFLAGS) and AC_SUBST((PKG)_LIBS) is not
-    done automatically.  Starting from 1.7, it is.  We require 1.7 now.
diff --git a/docs/random/bbb/streamselection b/docs/random/bbb/streamselection
deleted file mode 100644 (file)
index 234782e..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-Stream selection
-=
-
-1. Problem
-URIs (that being either a media stream or a media stream plus subtitle) can
-contain multiple streams of a type (audio, subtitle). A user has to be given
-the option of selecting one of those streams (or none altogether).
-
-2. Implementation ideas
-Stream selection, in GStreamer, has to be integrated at the player plugging
-level, which is (in the case of Totem) playbin. Playbin offers a feature to
-'mute' a stream (which means that no processing is done on that stream
-altogether, saving the decoding step). Currently, playbin will select the
-first occurrence of a stream type and mute all others. A queue is connected
-(for pre-roll) to the active stream. What is missing here is a way to change
-the active stream.
-Playbin interface - one possible interface could simply consist of a bunch of
-GObject properties: 'textstream' and 'audiostream', both integer. The number
-of available streams can be retrieved using the 'stream-info' GObject property.
-Similar to the 'nstreams' property, we could add utility GObject properties
-for getting the number of available audio/text streams ('naudiostreams' and
-'ntextstreams'). Names of these streams (like language name or so) can be
-added as an additional GObject property to streaminfo. Some container
-formats contain such names internally. Alternatively, we could allow those
-to be user-settable as well (for .sub files).
-On a set of either of these properties, playbasebin would mute the old
-selected stream (if any), unmute the newly selected stream (if any) and
-replug the preroll queue. The queue itself is disabled as well if no new
-stream was linked. Alternatively, a switch-like element is used, which
-requires no replugging. Pad disabling/enabling is then enough. This also
-makes relinking less painful. The switch-like element needs to proxy the
-active pads' caps. However, since those caps are (in practice) always the
-same across streams, caps setting will (inside the core) immediately
-return success.
-The switch-like element simply works like this:
-=
-static void
-loop_func (GstElement * element)
-{
-  GList *inpads;
-  GstPad *pad;
-  GstData *data;
-
-  for (inpads = ..; inpads != NULL; inpads = inpads->next) {
-    pad = inpads->data;
-    if (!GST_PAD_IS_USABLE (pad))
-      continue;
-
-    /* you'd also want some way to synchronize the inputs... */
-    data = gst_pad_pull (pad);
-    if (is_active_pad (pad))
-      gst_pad_push (srcpad, data);
-    else
-      gst_data_unref (data);
-  }
-}
-=
-It'd require an active-stream property itself, which (when set) takes
-care of doing renegotiation and so on. Using internal pad linkage is
-extremely useful here, and requires little code in the switch-like
-element itself. Note that there is a slight bit of duplication in the
-playbin interface and the switch-like element interface, but that's "just
-the way it is".
-The implementation of the switch-like element could initially be local to
-playbin, until it has been cleaned up and confirmed to be useful to a
-wider audience. This allows a lot of experimenting with interfaces because
-we won't be forced to maintain a stable interface.
-The current 'switch' element (gst-plugins/gst/switch/) already does a few
-of those operations, but stream synchronization, re-negotiation on stream
-changes, internal pad linkage and some other things are completely missing.
-If we're gonna use this element, it'll need a large overhaul. The choice of
-writing a new element or using an existing element as basis, and also the
-choice of whether or not to make this element local to playbin, should be
-based on technical merits and cost/effect analysis and not on personal
-pride.
-
-Notes:
-* seamless has the same switch-like element, but it's chain-based. Apart
-from scheduler considerations, this is a good idea, but limits its use
-(making either good docs and abuse-prevention [see multifilesrc] or
-private-to-playbin a prerequisite).
-* maybe text-* properties need to be renamed to subtitle-*.
-
-3. Written by
-Ronald S. Bultje <rbultje@ronald.bitfreak.net> - Jan. 2nd, 2005.
diff --git a/docs/random/bbb/subtitles b/docs/random/bbb/subtitles
deleted file mode 100644 (file)
index 6cbe204..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-Subtitles
-=========
-
-1. Problem
-GStreamer currently does not support subtitles.
-
-2. Proposed solution
-  - Elements
-  - Text-overlay
-  - Autoplugging
-  - Scheduling
-  - Stream selection
-
-The first thing we'll need is subtitle awareness. I'll focus on AVI/MKV/OGM
-here, because I know how that works. The same methods apply to DVD subtitles
-as well. The matroska demuxer (and Ogg) will need subtitle awareness. For
-AVI, this is not needed. Secondly, we'll need subtitle stream parsers (for
-all popular subtitle formats), that can deal both with parsed streams (MKV,
-OGM) as well as .sub file chunks (AVI). Sample code is available in
-gst-sandbox/textoverlay/.
-
-Secondly, we'll need a textoverlay filter that can take text and video and
-blits text on video. We have several such elements (e.g. the cairo-based
-element) in gst-plugins already. Those might need some updates to work
-exactly as expected.
-
-Thirdly, playbin will need to handle all that. We expect subtitle streams
-to end up as subimages or plain text (or xhtml text). Note that playbin
-should also allow access to the unblitted subtitle as text (if available)
-for accessibility purposes.
-
-A problem popping up is that subtitles are no continuous streams. This is
-especially noticeable in the MKV/OGM case, because there the input of data
-depends on the other streams, so we'll only notice delays inside an element
-when we've received the next data chunk. There are two possible solutions:
-using timestamped filler events or using decoupled subtitle overlay elements
-(bins, probably). The first has as a difficulty that it only works well in
-the AVI/.sub case, where we will notice discontinuities before they become
-problematic. The second is more difficult to implement, but works for both
-cases.
-A) fillers
-Imagine that two subtitles come after each other, with 10 seconds of no-data
-in between. By parsing a .sub file, we would notice immediately and we could
-send a filler event (or empty data) with a timestamp and duration in between.
-B) decoupled
-Imagine this text element:
-------------------------------
-video ----- | actual element |out
-|        /  -----------------|
-text - -                     |
-------------------------------
-where the text pad is decoupled, like a queue. When no text data is available,
-the pad will have received no data, and the element will render no subtitles.
-The actual element can be a bin here, containing another subtitle rendering
-element. Disadvantage: it requires threading, and the element itself is (in
-concept) kinda gross. The element can be embedded in playbin to hide this
-fact (i.e. not be available outside the scope of playbin).
-Whichever solution we take, it'll require effort from the implementer.
-Scheduling (process, not implementation) knowledge is assumed.
-
-Stream selection is a problem that audio has, too. We'll need a solution for
-this at the playback bin level, e.g. playbin. By muting all unused streams
-and dynamically unmuting the selected stream, this is easily solved. Note
-that synchronization needs to be checked in this case. The solution is not
-hard, but someone has to do it.
-
-3. Written by
-Ronald S. Bultje <rbultje@ronald.bitfreak.net>, Dec. 25th, 2004
-
-
-Appendix A: random IRC addition
-<Company> intersting question: would it be a good idea to have a "max-buffer-length" property?
-<Company> that way demuxewrs would now how often they'd need to generate filler events
-<Company> s/now/know/
-<BBB> hm...
-<BBB> I don't think it's good to make that variable
-<Company> dunno
-<Company> (i'm btw always looking at this from the midi perspective, too)
-<Company> (because both subtitles and midi are basically the same in this regard)
-<BBB> and do you mean 'after the stream has advanced <time> and we didn't read a new subtitle in this mkv stream, we should send a filler'?
-<Company> yeah
-<BBB> it goes for avi with large init_delay values, too
-<Company> so you don't need to send fillers every frame
-<BBB> right
-<BBB> cant' we just set that to, for example, 1s?
-<BBB> it's fairly random, but still
-<Company> that's another option, too
-<Company> though you could write all file parsers with max-delay=MAXINT
-<Company> would make them a lot easier
-<BBB> it's true that queue size, for example, depends on this value
-<BBB> e.g. if you make this 5s and set queue size to 1s, it'll hang
-<Company> right
-<BBB> whereas if you set it to 1s and queue size to 5s, you waste space
-<BBB> :)
-<BBB> you ought to set it to max-delay * (n_streams + 1)
-<BBB> or so
-<BBB> or -1
-<BBB> I forgot
-<BBB> ohwell
-<Company> if you'd use filtercaps and queue sizes in your app, you could at least work around deadlocks
-<BBB> yeah
-<Company> though ideally it should just work of course...
-<BBB> good point...
-
-
diff --git a/docs/random/buffers b/docs/random/buffers
deleted file mode 100644 (file)
index 78ac8dc..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-METADATA ON BUFFERS IS OUTDATED
--------------------------------
-
-
-Buffer mutability properties are the most important part of gst, and
-similarly are the most complex.
-
-The simple case is that a buffer is created, memory allocated, data put
-in it, and passed to the next filter.  That filter reads the data, does
-something (like creating a new buffer and decoding into it), and
-unreferences the buffer.  This causes the data to be freed and the buffer
-to be destroyed.
-
-A more complex case is when the filter modifies the data in place.  It
-does so and simply passes on the buffer to the next element.  This is just
-as easy to deal with.
-
-If the second filter adds metadata to the buffer, it just has to add the
-pointer to the list.  The next element simply traverses the list and 
diff --git a/docs/random/caps b/docs/random/caps
deleted file mode 100644 (file)
index f291b1f..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-SOME OF THE FIRST IDEAS, PRETTY OUTDATED
-----------------------------------------
-
-
-During the course of a discussion on IRC, it turned out
-that there are many possible ways to handle the capabilities.
-
-A capability is basically a set of properties attached to a 
-mimetype in order to more closely describe the mimetype. 
-Capabilities are supposed to be attached to pads so that the
-autoplugging algorithm has more specific information to connect
-compatible pads.
-
-We present 3 possible implementation for the capabilities. we need
-to pick one of them.
-
-1. static capabilities
-----------------------
-
-When an element is created, it creates its pads like:
-
-  mpg123->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
-  gst_element_add_pad (GST_ELEMENT (mpg123), mpg123->sinkpad);
-
-  mpg123->srcpad = gst_pad_new ("src", GST_PAD_SRC);
-  gst_element_add_pad (GST_ELEMENT (mpg123), mpg123->srcpad);
-
-In the static capabilities case, it will attach a GstCaps* structure
-to the pad. The GstCaps structure in the above example might look like:
-
-  static GstCapsFactory mpg123_sink_caps = {
-    "audio/mp3",
-    "layer",   GST_CAPS_INT_RANGE (1, 3),
-    "bitrate", GST_CAPS_INT_RANGE (8, 320),
-    NULL
-  };
-
-with 
-
-mpg123sinkcaps  = gst_caps_register (mpg123_sink_caps);
-
-the factory can be converted into a GstCaps* structure. The
-GstCaps* structure is attached to the pad with:
-
-gst_pad_add_caps (mpg123->sinkpad, mpg123sinkcaps);
-
-The GstElement would then have a sinkpad with the given 
-mimetype (audio/mp3) and with the capabilitities of accepting
-mpeg layer 1 to 3 and a bitrate from 8 up to 320 Kbps.
-
-Likewise, the src pad could be set up in the same way. An
-example capability factory could look like:
-
-  static GstCapsFactory mpg123_src_caps = {
-    "audio/raw",
-    "format",   GST_CAPS_BITFIELD (...),
-    "depth",    GST_CAPS_INT (16),
-    "rate",     GST_CAPS_INT_RANGE (4000, 96000),
-    "channels", GST_CAPS_INT_RANGE (1, 2),
-    NULL
-  };
-
-All GstElements would present their pads with the appropriate
-capabilities structure.
-
-The autoplugger would then proceed (once the source media type
-is known with a typefind function) in finding all the elements
-with compatible pads and connecting them into a pipeline. 
-
-All elements of the complete pipeline could then be constructed
-with one single pass. No new elements should be added to the
-pipeline because we can figure out all the possibilities using the
-pad capabilities.
-
-We call this the static case because the capabilities of the pads
-are supposed to stay the same after creating the element.
-
-While the ability to completely setup the pipeline before actually
-starting playback is an advantage regarding performance, one obvious
-problem with this setup is that the static case may be too static in
-some cases. We can illustrate this with the following setup:
-
-  ----------)             (------------
-   mpg123   !             !  audiosink
-           src          sink
-            !             !
-  ----------)             (------------
-
-The mpg123 element has its src capabilities set up as mpg123_src_caps
-in the above example.
-
-The audio renderer has its capabilities set up with the following
-factory:
-
-  static GstCapsFactory audio_sink_caps = {
-    "audio/raw",
-    "format",   GST_CAPS_BITFIELD (...),
-    "depth",    GST_CAPS_INT (16),
-    "rate",     GST_CAPS_INT_RANGE (22000, 44000),
-    "channels", GST_CAPS_INT_RANGE (1, 2),
-    NULL
-  };
-
-The static autoplugger has to be careful when connecting the mpg123
-element with the audiosink because it is theoretically possible that
-the mpg123 element outputs raw audio with a rate that cannot be
-handled by the audiosink (ex. 4000KHz). In the absence of another
-audiosink with more capabilities, the autoplugging of this simple 
-pipeline will not be possible and would fail.
-
-the autoplugging algorithm would probably select another element to
-insert between the mpg123 element and the audiosink in order to handle
-the (uncommon) case of a rate conversion (audioscaler).
-
-It is clear that this static setup might even fail or work suboptimal
-for even the common case and should therefore be considered as too 
-restrictive.
-
-
-2. dynamic capabilities
------------------------
-
-The idea of dynamic capabilities is that the capabilities are not set
-at element create time but rather while the pipeline is running.
-
-An element would still list its mime type using: 
-
-  gst_pad_add_type_id(mpg123->sinkpad, mp3type);
-
-The idea would then be that a rough draft of the pipeline would be
-built after the media type of the stream has been detected with the
-typefind functions. The rough draft would consist of laying out a
-global plan to reach the renderer(s). this plan would basically list
-the set of conversions that have to be performed. (mime-type to
-mime-type conversion).
-
-Elements that accept the src mime-type are tried by giving it a buffer.
-If the element accepts the buffer, it will set its capabilities for
-both the sink pad and the src pad. At that time other elements can be
-tried and added to the src pad, until we reach the renderer. As usual
-one has to be careful to add just the minimum amount of elements to
-reach the renderer. The global plan will help with that.
-
-Since we basically do not use the capabilities of the sink pad one has 
-to question the need for sink pad capabilities in the first place.
-
-We might also have a hard time trying different elements until we find
-a compatible one that does not cause a dead end at some point.
-
-
-3. combined setup
------------------
-
-This combined setup will minimise the effort needed to try different 
-elements encountered by option 2 while still allowing a more dynamic
-setup based on the actual media stream we are handling.
-
-The combined setup will list/add the sink capabilities at create time.
-It will only set the mime-type of its src pads.
-
-As with option2, a global plan will be built. At runtime the src pads
-will actually specify the capabilities they need for any element that
-wants to be connected to its source pads.
-
-In this case we specify the capabilities for all the sink pads of an
-element at create time. The capabilities of the src pads would only
-become available when data has been processed by the element.
-
-The autoplugger would then be able to choose an element that can handle
-the capability listed by the src pad.
-
-in our previous example:
-
-  ----------)             (------------
-   mpg123   !             !  audiosink
-           src          sink
-            !             !
-  ----------)             (------------
-                                
-the audiosink element would specify its sink pad capabilities at create
-time, while the mpg123 elements src pad would not yet have any capabilities
-set.
-
-When data is handled by the mpg123 element, a capability would be added to
-the mpg123 src pad. This capability might be:
-
-  static GstCapsFactory mpg123_src_caps = {
-    "audio/raw",
-    "format",   GST_CAPS_INT (S16),
-    "depth",    GST_CAPS_INT (16),
-    "rate",     GST_CAPS_INT (44000),
-    "channels", GST_CAPS_INT (2),
-    NULL
-  };
-
-This capability would be compatible with the audiosinks sinkpad capabilities
-and the autoplugger would therefore be able to connect the two elements.
-
-While allowing a more flexible setup with option3, compared to option1, we 
-introduce a slightly higher overhead when we need to dynamically connect 
-elements. This overhead will not be as big as option2 because we don't 
-have to 'try' elements.
-
-so:
-
-  src caps:  added at runtime to list the caps needed for an element that
-             wants to connect to this pad.
-  sink caps: the (static) capabilities that this sinkpad has. 
-
diff --git a/docs/random/caps.dia b/docs/random/caps.dia
deleted file mode 100644 (file)
index b511083..0000000
+++ /dev/null
@@ -1,1132 +0,0 @@
-<?xml version="1.0"?>
-<diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/">
-  <diagramdata>
-    <attribute name="background">
-      <color val="#ffffff"/>
-    </attribute>
-    <attribute name="paper">
-      <composite type="paper">
-        <attribute name="name">
-          <string>#A4#</string>
-        </attribute>
-        <attribute name="tmargin">
-          <real val="2.82"/>
-        </attribute>
-        <attribute name="bmargin">
-          <real val="2.82"/>
-        </attribute>
-        <attribute name="lmargin">
-          <real val="2.82"/>
-        </attribute>
-        <attribute name="rmargin">
-          <real val="2.82"/>
-        </attribute>
-        <attribute name="is_portrait">
-          <boolean val="true"/>
-        </attribute>
-        <attribute name="scaling">
-          <real val="1"/>
-        </attribute>
-        <attribute name="fitto">
-          <boolean val="false"/>
-        </attribute>
-      </composite>
-    </attribute>
-    <attribute name="grid">
-      <composite type="grid">
-        <attribute name="width_x">
-          <real val="1"/>
-        </attribute>
-        <attribute name="width_y">
-          <real val="1"/>
-        </attribute>
-        <attribute name="visible_x">
-          <int val="1"/>
-        </attribute>
-        <attribute name="visible_y">
-          <int val="1"/>
-        </attribute>
-      </composite>
-    </attribute>
-    <attribute name="guides">
-      <composite type="guides">
-        <attribute name="hguides"/>
-        <attribute name="vguides"/>
-      </composite>
-    </attribute>
-  </diagramdata>
-  <layer name="Background" visible="true">
-    <object type="UML - Class" version="0" id="O0">
-      <attribute name="obj_pos">
-        <point val="0.75,5.55"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="0.7,5.5;12.7504,9.6"/>
-      </attribute>
-      <attribute name="elem_corner">
-        <point val="0.75,5.55"/>
-      </attribute>
-      <attribute name="elem_width">
-        <real val="11.9504"/>
-      </attribute>
-      <attribute name="elem_height">
-        <real val="4"/>
-      </attribute>
-      <attribute name="name">
-        <string>#GstCaps#</string>
-      </attribute>
-      <attribute name="stereotype">
-        <string/>
-      </attribute>
-      <attribute name="abstract">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_attributes">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="visible_attributes">
-        <boolean val="true"/>
-      </attribute>
-      <attribute name="visible_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="attributes">
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#name#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#gchar *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#id#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#guint16#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#properties#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#GstProps *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <attribute name="operations"/>
-      <attribute name="template">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="templates"/>
-    </object>
-    <object type="UML - Class" version="0" id="O1">
-      <attribute name="obj_pos">
-        <point val="16.35,9.65"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="16.3,9.6;26.896,12.1"/>
-      </attribute>
-      <attribute name="elem_corner">
-        <point val="16.35,9.65"/>
-      </attribute>
-      <attribute name="elem_width">
-        <real val="10.496"/>
-      </attribute>
-      <attribute name="elem_height">
-        <real val="2.4"/>
-      </attribute>
-      <attribute name="name">
-        <string>#GstProps#</string>
-      </attribute>
-      <attribute name="stereotype">
-        <string/>
-      </attribute>
-      <attribute name="abstract">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_attributes">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="visible_attributes">
-        <boolean val="true"/>
-      </attribute>
-      <attribute name="visible_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="attributes">
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#properties#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#GList *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <attribute name="operations"/>
-      <attribute name="template">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="templates"/>
-    </object>
-    <object type="UML - Association" version="0" id="O2">
-      <attribute name="obj_pos">
-        <point val="12.7004,9.05"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="11.2504,7.6;18.4892,11.8"/>
-      </attribute>
-      <attribute name="orth_points">
-        <point val="12.7004,9.05"/>
-        <point val="14.15,9.05"/>
-        <point val="14.15,10.35"/>
-        <point val="16.35,10.35"/>
-      </attribute>
-      <attribute name="orth_orient">
-        <enum val="0"/>
-        <enum val="1"/>
-        <enum val="0"/>
-      </attribute>
-      <attribute name="name">
-        <string/>
-      </attribute>
-      <attribute name="direction">
-        <enum val="0"/>
-      </attribute>
-      <attribute name="ends">
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string>#1#</string>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="2"/>
-          </attribute>
-        </composite>
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string>#0..1#</string>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="0"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <connections>
-        <connection handle="0" to="O0" connection="13"/>
-        <connection handle="1" to="O1" connection="3"/>
-      </connections>
-    </object>
-    <object type="UML - Class" version="0" id="O3">
-      <attribute name="obj_pos">
-        <point val="14.75,13.45"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="14.7,13.4;26.2656,16.7"/>
-      </attribute>
-      <attribute name="elem_corner">
-        <point val="14.75,13.45"/>
-      </attribute>
-      <attribute name="elem_width">
-        <real val="11.4656"/>
-      </attribute>
-      <attribute name="elem_height">
-        <real val="3.2"/>
-      </attribute>
-      <attribute name="name">
-        <string>#GstPropsEntry#</string>
-      </attribute>
-      <attribute name="stereotype">
-        <string/>
-      </attribute>
-      <attribute name="abstract">
-        <boolean val="true"/>
-      </attribute>
-      <attribute name="suppress_attributes">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="visible_attributes">
-        <boolean val="true"/>
-      </attribute>
-      <attribute name="visible_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="attributes">
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#propid#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#GQuark#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#propstype#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#GstPropsId#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <attribute name="operations"/>
-      <attribute name="template">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="templates"/>
-    </object>
-    <object type="UML - Association" version="0" id="O4">
-      <attribute name="obj_pos">
-        <point val="16.35,11.55"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="11.25,10.1;17.8,15.6"/>
-      </attribute>
-      <attribute name="orth_points">
-        <point val="16.35,11.55"/>
-        <point val="12.7,11.55"/>
-        <point val="12.7,14.15"/>
-        <point val="14.75,14.15"/>
-      </attribute>
-      <attribute name="orth_orient">
-        <enum val="0"/>
-        <enum val="1"/>
-        <enum val="0"/>
-      </attribute>
-      <attribute name="name">
-        <string/>
-      </attribute>
-      <attribute name="direction">
-        <enum val="0"/>
-      </attribute>
-      <attribute name="ends">
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string>#1#</string>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="2"/>
-          </attribute>
-        </composite>
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string>#*#</string>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="0"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <connections>
-        <connection handle="0" to="O1" connection="8"/>
-        <connection handle="1" to="O3" connection="3"/>
-      </connections>
-    </object>
-    <object type="UML - Class" version="0" id="O5">
-      <attribute name="obj_pos">
-        <point val="4.45,19.05"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="4.4,19;14.996,21.5"/>
-      </attribute>
-      <attribute name="elem_corner">
-        <point val="4.45,19.05"/>
-      </attribute>
-      <attribute name="elem_width">
-        <real val="10.496"/>
-      </attribute>
-      <attribute name="elem_height">
-        <real val="2.4"/>
-      </attribute>
-      <attribute name="name">
-        <string>#boolean#</string>
-      </attribute>
-      <attribute name="stereotype">
-        <string/>
-      </attribute>
-      <attribute name="abstract">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_attributes">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="visible_attributes">
-        <boolean val="true"/>
-      </attribute>
-      <attribute name="visible_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="attributes">
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#bool_data#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#gboolean#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <attribute name="operations"/>
-      <attribute name="template">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="templates"/>
-    </object>
-    <object type="UML - Class" version="0" id="O6">
-      <attribute name="obj_pos">
-        <point val="10.55,22.4"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="10.5,22.35;21.5808,24.85"/>
-      </attribute>
-      <attribute name="elem_corner">
-        <point val="10.55,22.4"/>
-      </attribute>
-      <attribute name="elem_width">
-        <real val="10.9808"/>
-      </attribute>
-      <attribute name="elem_height">
-        <real val="2.4"/>
-      </attribute>
-      <attribute name="name">
-        <string>#fourcc#</string>
-      </attribute>
-      <attribute name="stereotype">
-        <string/>
-      </attribute>
-      <attribute name="abstract">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_attributes">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="visible_attributes">
-        <boolean val="true"/>
-      </attribute>
-      <attribute name="visible_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="attributes">
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#fourcc_data#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#guint32#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <attribute name="operations"/>
-      <attribute name="template">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="templates"/>
-    </object>
-    <object type="UML - Class" version="0" id="O7">
-      <attribute name="obj_pos">
-        <point val="16.8,19.2"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="16.75,19.15;24.922,21.65"/>
-      </attribute>
-      <attribute name="elem_corner">
-        <point val="16.8,19.2"/>
-      </attribute>
-      <attribute name="elem_width">
-        <real val="8.072"/>
-      </attribute>
-      <attribute name="elem_height">
-        <real val="2.4"/>
-      </attribute>
-      <attribute name="name">
-        <string>#int#</string>
-      </attribute>
-      <attribute name="stereotype">
-        <string/>
-      </attribute>
-      <attribute name="abstract">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_attributes">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="visible_attributes">
-        <boolean val="true"/>
-      </attribute>
-      <attribute name="visible_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="attributes">
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#int_data#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#gint#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <attribute name="operations"/>
-      <attribute name="template">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="templates"/>
-    </object>
-    <object type="UML - Class" version="0" id="O8">
-      <attribute name="obj_pos">
-        <point val="22.5,22.55"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="22.45,22.5;31.5916,25"/>
-      </attribute>
-      <attribute name="elem_corner">
-        <point val="22.5,22.55"/>
-      </attribute>
-      <attribute name="elem_width">
-        <real val="9.0416"/>
-      </attribute>
-      <attribute name="elem_height">
-        <real val="2.4"/>
-      </attribute>
-      <attribute name="name">
-        <string>#list#</string>
-      </attribute>
-      <attribute name="stereotype">
-        <string/>
-      </attribute>
-      <attribute name="abstract">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_attributes">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="visible_attributes">
-        <boolean val="true"/>
-      </attribute>
-      <attribute name="visible_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="attributes">
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#entries#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#GList *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <attribute name="operations"/>
-      <attribute name="template">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="templates"/>
-    </object>
-    <object type="UML - Class" version="0" id="O9">
-      <attribute name="obj_pos">
-        <point val="27.9,18.85"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="27.85,18.8;33.598,22.1"/>
-      </attribute>
-      <attribute name="elem_corner">
-        <point val="27.9,18.85"/>
-      </attribute>
-      <attribute name="elem_width">
-        <real val="5.648"/>
-      </attribute>
-      <attribute name="elem_height">
-        <real val="3.2"/>
-      </attribute>
-      <attribute name="name">
-        <string>#int_range#</string>
-      </attribute>
-      <attribute name="stereotype">
-        <string/>
-      </attribute>
-      <attribute name="abstract">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_attributes">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="visible_attributes">
-        <boolean val="true"/>
-      </attribute>
-      <attribute name="visible_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="attributes">
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#min#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#gint#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#max#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#gint#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <attribute name="operations"/>
-      <attribute name="template">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="templates"/>
-    </object>
-    <object type="UML - Association" version="0" id="O10">
-      <attribute name="obj_pos">
-        <point val="30.724,18.85"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="19.0328,15.2;32.174,20.45"/>
-      </attribute>
-      <attribute name="orth_points">
-        <point val="30.724,18.85"/>
-        <point val="30.724,18.25"/>
-        <point val="20.4828,18.25"/>
-        <point val="20.4828,16.65"/>
-      </attribute>
-      <attribute name="orth_orient">
-        <enum val="1"/>
-        <enum val="0"/>
-        <enum val="1"/>
-      </attribute>
-      <attribute name="name">
-        <string/>
-      </attribute>
-      <attribute name="direction">
-        <enum val="0"/>
-      </attribute>
-      <attribute name="ends">
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string/>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="0"/>
-          </attribute>
-        </composite>
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string/>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="1"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <connections>
-        <connection handle="0" to="O9" connection="1"/>
-        <connection handle="1" to="O3" connection="6"/>
-      </connections>
-    </object>
-    <object type="UML - Association" version="0" id="O11">
-      <attribute name="obj_pos">
-        <point val="20.836,19.2"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="19.0328,15.2;22.286,20.8"/>
-      </attribute>
-      <attribute name="orth_points">
-        <point val="20.836,19.2"/>
-        <point val="20.836,18.25"/>
-        <point val="20.4828,18.25"/>
-        <point val="20.4828,16.65"/>
-      </attribute>
-      <attribute name="orth_orient">
-        <enum val="1"/>
-        <enum val="0"/>
-        <enum val="1"/>
-      </attribute>
-      <attribute name="name">
-        <string/>
-      </attribute>
-      <attribute name="direction">
-        <enum val="0"/>
-      </attribute>
-      <attribute name="ends">
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string/>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="0"/>
-          </attribute>
-        </composite>
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string/>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="1"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <connections>
-        <connection handle="0" to="O7" connection="1"/>
-        <connection handle="1" to="O3" connection="6"/>
-      </connections>
-    </object>
-    <object type="UML - Association" version="0" id="O12">
-      <attribute name="obj_pos">
-        <point val="9.698,19.05"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="8.248,15.2;21.9328,20.65"/>
-      </attribute>
-      <attribute name="orth_points">
-        <point val="9.698,19.05"/>
-        <point val="9.698,18.25"/>
-        <point val="20.4828,18.25"/>
-        <point val="20.4828,16.65"/>
-      </attribute>
-      <attribute name="orth_orient">
-        <enum val="1"/>
-        <enum val="0"/>
-        <enum val="1"/>
-      </attribute>
-      <attribute name="name">
-        <string/>
-      </attribute>
-      <attribute name="direction">
-        <enum val="0"/>
-      </attribute>
-      <attribute name="ends">
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string/>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="0"/>
-          </attribute>
-        </composite>
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string/>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="1"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <connections>
-        <connection handle="0" to="O5" connection="1"/>
-        <connection handle="1" to="O3" connection="6"/>
-      </connections>
-    </object>
-    <object type="UML - Association" version="0" id="O13">
-      <attribute name="obj_pos">
-        <point val="16.0404,22.4"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="14.5904,15.2;21.9328,24"/>
-      </attribute>
-      <attribute name="orth_points">
-        <point val="16.0404,22.4"/>
-        <point val="16.0404,18.25"/>
-        <point val="20.4828,18.25"/>
-        <point val="20.4828,16.65"/>
-      </attribute>
-      <attribute name="orth_orient">
-        <enum val="1"/>
-        <enum val="0"/>
-        <enum val="1"/>
-      </attribute>
-      <attribute name="name">
-        <string/>
-      </attribute>
-      <attribute name="direction">
-        <enum val="0"/>
-      </attribute>
-      <attribute name="ends">
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string/>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="0"/>
-          </attribute>
-        </composite>
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string/>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="1"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <connections>
-        <connection handle="0" to="O6" connection="1"/>
-        <connection handle="1" to="O3" connection="6"/>
-      </connections>
-    </object>
-    <object type="UML - Association" version="0" id="O14">
-      <attribute name="obj_pos">
-        <point val="27.0208,22.55"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="19.0328,15.2;28.4708,24.15"/>
-      </attribute>
-      <attribute name="orth_points">
-        <point val="27.0208,22.55"/>
-        <point val="27.0208,18.25"/>
-        <point val="20.4828,18.25"/>
-        <point val="20.4828,16.65"/>
-      </attribute>
-      <attribute name="orth_orient">
-        <enum val="1"/>
-        <enum val="0"/>
-        <enum val="1"/>
-      </attribute>
-      <attribute name="name">
-        <string>#union#</string>
-      </attribute>
-      <attribute name="direction">
-        <enum val="0"/>
-      </attribute>
-      <attribute name="ends">
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string/>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="0"/>
-          </attribute>
-        </composite>
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string/>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="1"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <connections>
-        <connection handle="0" to="O8" connection="1"/>
-        <connection handle="1" to="O3" connection="6"/>
-      </connections>
-    </object>
-    <object type="UML - Association" version="0" id="O15">
-      <attribute name="obj_pos">
-        <point val="31.5416,24.45"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="24.7656,12.7;36.3,25.9"/>
-      </attribute>
-      <attribute name="orth_points">
-        <point val="31.5416,24.45"/>
-        <point val="34.85,24.45"/>
-        <point val="34.85,14.15"/>
-        <point val="26.2156,14.15"/>
-      </attribute>
-      <attribute name="orth_orient">
-        <enum val="0"/>
-        <enum val="1"/>
-        <enum val="0"/>
-      </attribute>
-      <attribute name="name">
-        <string/>
-      </attribute>
-      <attribute name="direction">
-        <enum val="0"/>
-      </attribute>
-      <attribute name="ends">
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string>#1#</string>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="2"/>
-          </attribute>
-        </composite>
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string>#*#</string>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="0"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <connections>
-        <connection handle="0" to="O8" connection="9"/>
-        <connection handle="1" to="O3" connection="4"/>
-      </connections>
-    </object>
-  </layer>
-</diagram>
diff --git a/docs/random/caps2 b/docs/random/caps2
deleted file mode 100644 (file)
index 3ca0a74..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-
-The new caps code uses the type name GstCaps2 and the function
-names gst_caps2_*().  Before the CAPS branch is merged, there
-will be a global change from caps2 to caps.  Since GstCaps is
-no longer defined, it no longer compiles, thus highlighting
-exactly what needs to be changed in an element.
-
-
-
-Pad Templates:
-
-Old style:
-
-  GST_PAD_TEMPLATE_FACTORY (fakesrc_src_factory,
-    "src%d",
-    GST_PAD_SRC,
-    GST_PAD_REQUEST,
-    GST_CAPS_ANY
-  );
-
-New style:
-
-  GstStaticPadTemplate fakesrc_src_template = GST_STATIC_PAD_TEMPLATE (
-    "src%d",
-    GST_PAD_SRC,
-    GST_PAD_REQUEST,
-    GST_STATIC_CAPS2_ANY
-  );
-
-The old style defined a function called fakesrc_src_factory(), which,
-when called, returns a pad template.  The new style defines a
-GstStaticPadTemplate, which can be converted to a GstPadTemplate
-by the function gst_static_pad_template_get().  The 4th argument
-is also different -- previously it would call the GST_CAPS_NEW()
-function.  Now it is a GstStaticCaps.
-
-Not every pad template can be converted to a GstStaticPadTemplate,
-particularly those which create caps from another source at runtime,
-such as videotestsrc.
-
-Caps:
-
-Old style:
-
-  GST_CAPS_NEW (
-    "sinesrc_src",
-    "audio/x-raw-int",
-      "endianness",     GST_PROPS_INT (G_BYTE_ORDER),
-      "signed",         GST_PROPS_BOOLEAN (TRUE),
-      "width",          GST_PROPS_INT (16),
-      "depth",          GST_PROPS_INT (16),
-      "rate",           GST_PROPS_INT_RANGE (8000, 48000),
-      "channels",       GST_PROPS_INT (1)
-  )
-
-New style:
-
-  GST_STATIC_CAPS2 ( "audio/x-raw-int, "
-      "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
-      "signed = (boolean) true, "
-      "width = (int) 16, "
-      "depth = (int) 16, "
-      "rate = (int) [ 8000, 48000 ], "
-      "channels = (int) 1"
-  )
-
-The old style calls a function that creates a GstCaps.  The new style
-stores a string in a GstStaticCaps2, and this string is converted to
-a caps in the function gst_static_caps2_get().
-
-Note that the old caps name is no longer used.
-
-Old style:
-
-  caps = GST_CAPS_NEW ("videotestsrc_filter",
-                       "video/x-raw-rgb",
-                       "bpp", GST_PROPS_INT(format->bitspp),
-                       "endianness", GST_PROPS_INT(endianness),
-                       "depth", GST_PROPS_INT(format->depth),
-                       "red_mask", GST_PROPS_INT(format->red_mask),
-                       "green_mask", GST_PROPS_INT(format->green_mask),
-                       "blue_mask", GST_PROPS_INT(format->blue_mask));
-
-New style:
-
-  caps = gst_caps2_new_simple("video/x-raw-rgb",
-        "bpp", G_TYPE_INT, format->bitspp,
-        "endianness", G_TYPE_INT, endianness,
-        "depth", G_TYPE_INT, format->depth,
-        "red_mask", G_TYPE_INT, format->red_mask,
-        "green_mask", G_TYPE_INT, format->green_mask,
-        "blue_mask", G_TYPE_INT, format->blue_mask);
-
-Not everything can be converted in this way, especially lists and
-ranges.
-
-
-IMPLEMENTATION
-
-Pad Capabilities (caps) are mathematical sets that represent all the
-possible stream types that a pad can use.  These general sets are
-represented by unions of simpler sets known as caps structures.  Each
-caps structure has a media type (e.g., "audio/mpeg") and a number of
-properties.  Each property has a name and a GValue.  In normal
-circumstances, the GValue will have the types int, boolean, string,
-fourcc, and double.  Simple sets are constructed by using GValues
-that are lists of other GValues, or the special types that represent
-int ranges and double ranges.
-
-A "fixed" caps represents exactly one media format.  This means that
-the caps is a union of exactly one caps structure, and each property
-in the caps structure is a simple type, i.e., no ranges or lists.
-
-There are two special caps values, "ANY" which represents the union
-of all stream types, and "EMPTY", which represents the set of no
-stream types.  The ANY caps is often used on generic elements that
-handle any type of data (e.g., filesrc and filesink).  The EMPTY
-caps is the return value of gst_caps_intersect(), when the two
-given caps do not intersect.  In many cases, using EMPTY is invalid.
-
-
-CAPS NEGOTIATION
-
-Elements provide information to the core about what stream formats
-they understand in four ways: the caps in the pad templates, the
-caps returned by a pad's getcaps function, accepting/denying
-a given caps in the pad link function, and a new fixate function.
-
-The pad template caps should be the union of caps a pad supports
-in any potential situation.  Simultaneously, these caps should be
-as specific as possible, since it is used to decide which elements
-to attempt for autoplugging, without having to load the element.
-The pad template caps are generally determined at compile time, but
-might be actually computed at run-time from other information.
-
-The getcaps() function returns the caps supported by a given 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 getcaps function 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.  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.
-
-The pad link function is the last step in negotiating caps.  The
-core calls the pad link function with a fixed caps, meaning that
-the stream format is precisely defined, with the caps having one
-structure, with no fields that are ranges or lists.
-
-There is also a new pad function "fixate", which is used to help
-choose a fixed caps from a non-fixed caps.  This is called in
-situations where normal negotiation cannot decide on a fixed caps.
-You should almost never implement a fixate function, please ask
-me if it is appropriate for your case.  Fixate functions are called
-iteratively on the pads until a fixed caps is found.  Fixate functions
-are called with a const caps, and should return a caps that is a
-strict subset of the given caps.  That is, the function should
-create a caps that is "more fixed" than previously, but does not
-have to return fixed caps.  If the fixate function can't provide
-more fixed caps, it should return NULL.
-
-
-
-Checklist for getcaps:
-
- - The getcaps function prototype no longer has the caps parameter.
-   Remove it.
-
- - The returned caps is owned by the caller.  Make sure you don't
-   keep a pointer to the caps.
- - Make sure that the getcaps function can be called safely in each
-   element state (NULL, READY, PAUSED, PLAYING), and for any element
-   configuration (properties, links, devices/files opened or not,
-   error state, etc.)
-
- - Make sure that the returned caps do not depend on the caps that
-   indicate the stream type that the pad is currently using.
-
-Checklist for pad_link:
-
- - The pad link function prototypes uses a const GstCaps *.
-
- - Pad link functions are called with fixed caps.  There's no need
-   to check for this.  This means that you can assume that the caps
-   is not ANY or EMPTY, and that there is exactly one structure in
-   the caps, and that all the fields in the structure are fixed.
-
- - Pad link functions are called with caps that are a subset of the
-   most recent return value of the pad's getcaps function.  Generally,
-   the getcaps function was called immediately prior to calling the
-   src_link function.  For 0.8, you can assume that nothing has changed
-   in your element that would cause a change to the return value of
-   getcaps.
-
- - the return value GST_PAD_LINK_OK should be used when the caps are
-   acceptable, and you've extracted all the necessary information from
-   the caps and set the element's internal state appropriately.
-
- - the return value GST_PAD_LINK_REFUSED should be used when the caps
-   are unacceptable for whatever reason.
-
- - the return value GST_PAD_LINK_DELAYED should be used when the
-   element is in a state where it can't determine whether the caps
-   are acceptable or not.  This is often used if the element needs
-   to open a device or process data before determining acceptable
-   caps.
-
- - the pad_link function must not call gst_caps_try_set_caps() on
-   the pad that was specified as a parameter.
-
- - the pad_link function may (and often should) call
-   gst_caps_try_set_caps() on pads that are not specified as the
-   pad parameter.
-Checklist for fixate:
-
- - Make sure you actually should be using a fixate function.  Fixate
-   functions are reasonable for non-fixed primary sources, such as
-   videotestsrc, v4lsrc, and osssrc.
-
- - The user_data parameter is mainly used for user-provided fixate
-   function.  It should be ignored in element fixate functions.
-
-
-
-
diff --git a/docs/random/classes.dia b/docs/random/classes.dia
deleted file mode 100644 (file)
index de4aa3e..0000000
Binary files a/docs/random/classes.dia and /dev/null differ
diff --git a/docs/random/ds/0.9-planning b/docs/random/ds/0.9-planning
deleted file mode 100644 (file)
index f9f60e9..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-
-
-
-Scheduling:
-
- - remove loop/get/chain from GstElement and add a "iterate" method.
-   The iterate method is called with the event (or events) that
-   triggered it, performs some action, and resets the events (file
-   descriptors becoming readable, semaphores, pads becoming readable
-   or writable, or a time occurs).
-
- - Add GstLoopElement, GstChainElement, etc. for compatibility.
-
- - Remove existing state handling and create 2 states, "playing" and
-   "stopped".  "playing" means that the iterate() method of the
-   element may be called, that is, the element is allowed to move
-   buffers, negotiate, etc.  "stopped" means that no gstreamer-ish
-   things happen to an element, only gobject-ish.  A separate
-   reset() method will handle the difference between READY and NULL.
-
- - Add a flag "ready" to GstElement that is under the control of the
-   element.  If the element is ready to stream, it sets this flag,
-   and the entire pipeline starts streaming.  (This is basically
-   the difference between PAUSED and PLAYING.)  For example, osssink
-   won't set the ready flag until the device is opened and there is
-   a buffer available to write to the device.
-
- - Scheduling of elements and movement of buffers will be timed by
-   clocks.  
-
-
-
-Example #1:
-
- Pipeline: sinesrc ! osssink
-
- - The application creates the pipeline and sets it to "playing".
-
- - The clock is created and set to "paused".
-
- - sinesrc.iterate() decides to watch for the event "src pad
-   negotiation" and sets the available caps on the pad.
-
- - osssink.iterate() opens device, determines available caps, and
-   sets the available caps on the pad.  Then it decides to wait for
-   "sink pad negotiation".
-
- - The scheduler realizes that the two elements are waiting for
-   negotiation, so it negotiates the link.
-
- - sinesrc.iterate() sets the "ready" flag (because it needs no more
-   preparation to stream) and decides to watch for the event "src
-   pad ready to accept buffer".
-
- - osssink.iterate() decides to watch for the event "sink pad has
-   available buffer".
-
- - The scheduler realizes that sinesrc.srcpad is now ready, so it
-   calls sinesrc.iterate()
-
- - sinesrc.iterate() creates a buffer and pushes it, and decides to
-   wait for the same event.
-
- - The scheduler realizes that osssink.sinkpad now has a buffer, so
-   it calls osssink.iterate().
-
- - osssink.iterate() is now ready to stream, so it sets the "ready"
-   flag and waits for "time 0".
-
- - The pipeline is now completely ready, so the clock may be
-   started.  A signal is fired to let the application know this
-   (and possibly change the default behavior).
-
- - The clock starts with the time 0.  The scheduler realizes this,
-   and decides to schedule osssink.
-
- - osssink.iterate() is called, and writes the buffer to the device.
-   This starts the clock counting.  (Actually, the buffer could be
-   written by the clock code, since presumably the clock is related
-   to osssink.)  iterate() then waits for "sink pad has available
-   buffer".
-
- We're now basically in streaming mode.  A streaming cycle:
-
- - osssink.iterate() decides the audio output buffer is full enough,
-   so it waits for "time X", where X is the time when the output
-   buffer will be below some threshold.
-
- - osssink.iterate() waits for "sink pad has available buffer"
-
- - sinesrc.iterate() creates and pushes a buffer, then waits for
-   "src pad ready".
-
-
- Further ideas:
-
- - osssink can set a hard deadline time, which means that if it is
-   not scheduled before that time, you'll get a skip.  Skipping
-   involves setting osssink to "not ready" and pauses the clock.
-   Then the scheduler needs to go through the same process as above
-   to start the clock.
-
- - As a shortcut, osssink can say "I need a buffer on the sinkpad
-   at time X".  This information can be passed upstream, and be used
-   in filters -- filter.sinkpad says "I need a buffer at time X-N",
-   where N is the latency of the filter.
-
-
-Example #2:
-
- Pipeline: osssrc ! osssink
- - The application creates the pipeline and sets it to "playing".
-
- - The clock is created and set to "paused".
-
- - negotiation happens roughly as in example #1, although osssrc
-   additionally opens and prepares the device.
-
- - osssrc.iterate() sets the "ready" flag (because it needs no more
-   preparation to stream) and waits for "time 0", since it presumably
-   can't wait for the file descriptor (audio input hasn't been
-   enabled on the device yet.)
-
- - osssink.iterate() decides to watch for the event "sink pad has
-   available buffer".
-
- - The scheduler realizes the deadlock and (somehow) tells osssink
-   that it can't pre-roll.  (This needs more work)  In other words,
-   osssink can't be the clock master, but only a clock slave.
-
- - osssink.iterates() agrees to start at time SOME_LATENCY, sets the
-   "ready" flag, and waits for a buffer on its sink pad.
-
- - The pipeline is now completely ready, so the clock may be
-   started.  A signal is fired to let the application know this
-   (and possibly change the default behavior).
-
- - The clock starting causes two things to happen: osssrc starts
-   the recording of data, and osssink starts the outputting of data.
-   The data being output is a chunk of silence equal to SOME_LATENCY.
-
- - osssrc.iterate() is called for "time 0", does nothing, and waits
-   on the file descriptor (via the scheduler, of course).  All waiting
-   on file descriptors should have an associated timeout.
-
- - osssrc.iterate() is called when the file descriptor is ready,
-   reads a chunk of data, and pushes the buffer.  It then waits for
-   its file descriptor to be ready.
-
- - osssink.iterate() is called
-
-
-Evil:
-
-  fakesrc ! tee ! fakesink tee0. ! never_accept_a_buffer_sink
-
-  sinesrc ! osssink videotestsrc ! ximagesink
-  
-  fakesrc ! fakesink (pausing)
-
-  sinesrc ! identity ! osssink
-
-
-
diff --git a/docs/random/ds/buffer_locking b/docs/random/ds/buffer_locking
deleted file mode 100644 (file)
index 8200a81..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-Buffers should have readlocks and writelocks to enforce
-GST_BUFFER_DONTKEEP and relax the restriction that buffers with
-multiple refcounts are read-only.
-
-
-
-Example:
-
-  videotestsrc ! ximagesink
-
-  videotestsrc requests a buffer from its src pad
-
-  ximagesink creates a buffer (refcount:1 readlock:0 writelock:0)
-
-  videotestsrc writelocks it (refcount:1 readlock:0 writelock:1)
-
-  videotestsrc writes to the buffer
-
-  videotestsrc un-writelocks it (refcount:1 readlock:0 writelock:0)
-
-  ximagesink readlocks it (refcount:1 readlock:1 writelock:0)
-
-  ximagesink writes it to the screen
-
-  ximagesink un-readlocks it (refcount:1 readlock:0 writelock:0)
-
-
-  
diff --git a/docs/random/ds/bufferpools b/docs/random/ds/bufferpools
deleted file mode 100644 (file)
index b0f211b..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-On Thu, Jan 08, 2004 at 04:10:00PM +0100, Julien MOUTTE wrote:
-> 
-> Hi David,
-> 
-> I'd like to implement bufferpools again in x[v]imagesink asap.. Could
-> you please point me to a template/doc on how to do that ?
-> 
-> The best for me would be a simple testcase showing how to use the buffer
-> free methods to replace bufferpools.
-
-
-x[v]imagesink should call gst_pad_set_bufferalloc_function() on
-their sink pads with a bufferalloc implementation.  This bufferalloc
-function is to allocate buffers that _peers_ will send _to_ that pad.
-
-A trivial version of a bufferalloc function, i.e., one that just
-allocates normal buffers:
-
-static GstBuffer *
-gst_ximagesink_sink_bufferalloc (GstPad *pad, guint64 offset, guint
-size)
-{
-  GstBuffer *buffer;
-
-  buffer = gst_buffer_new_and_alloc (size);
-  GST_DATA_FREE_FUNC (data) = gst_ximagesink_buffer_free;
-  GST_BUFFER_POOL_PRIVATE (data) = ximagesink; /* whatever */
-
-  return buffer;
-}
-
-static void
-gst_ximagesink_buffer_free (GstData *data)
-{
-  g_free (GST_BUFFER_DATA (data));
-}
-
-The hard part is going through each element, and every time it
-allocates a buffer using gst_buffer_new_and_alloc () that is then
-sent to a sink pad, the call should be replaced with
-gst_pad_alloc_buffer (sinkpad, offset, size).
-
-
-
-dave...
-
-
-
--------------------------------------------------------
-This SF.net email is sponsored by: Perforce Software.
-Perforce is the Fast Software Configuration Management System offering
-advanced branching capabilities and atomic changes on 50+ platforms.
-Free Eval! http://www.perforce.com/perforce/loadprog.html
-_______________________________________________
-gstreamer-devel mailing list
-gstreamer-devel@lists.sourceforge.net
-https://lists.sourceforge.net/lists/listinfo/gstreamer-devel
diff --git a/docs/random/ds/categories b/docs/random/ds/categories
deleted file mode 100644 (file)
index 2636f11..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-
-Element Categories:
--------------------
-
-
-Decoder:
-
-
-Encoder:
-
-
-Converter:
- A converter has one or more source pads and one or more sink pads.
- Converter pads may have different caps templates.  Converters are
- expected 
-
-
-Filter:
- A filter has one source and one sink pad.  These pads have the same
- caps and (thus) the same caps template.
-
- Filters generally do not handle events.
-
- Filters may have interfaces.
-
- Filters are generally not autoplugged unless they have interfaces.
-
-
-Source:
- A source has one source pad and no sink pads.
-
- Sources usually handle events.
-
- Sources may have interfaces.
-
- Sources are not autoplugged.
-
-Sink:
- A sink has one sink pad and no source pads.
-
- Sources usually handle events.
-
- Sources may have interfaces.
-
- Sinks are not autoplugged.
-
-
-
-Converter/Colorspace
-
diff --git a/docs/random/ds/element-checklist b/docs/random/ds/element-checklist
deleted file mode 100644 (file)
index fcac4e4..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-
-This is a list of things to check in elements.
-
-
-
-1. Add a "Element-Checklist-Version: 1" comment
-
-This comment is to indicate which items on this checklist have been
-checked, so that future checkers can skip things that you've already
-carefully checked.  This number should obviously be updated whenever
-you do additional checks.  Ideally, you should not do checks out of
-order, but using "1, also 4-6" is acceptable.
-
-
-2. Each pad should have a pad template
-
-Create and register a pad template to the element class.
-
-
-3. config.h
-
-Make sure that each .c file includes config.h (conditionally on
-HAVE_CONFIG_H).  Make sure that each .h file does _not_ include
-config.h.
-
-4. src event handling
-
-Every element having multiple sink pads or having a specific need to handle
-src events in a different manner than the default event handler should do that 
-correctly. Correctly means that :
-
-- It should not leak the event if it is handled (gst_event_unref)
-- It should call return gst_pad_event_default (pad, event) for all non handled 
-localy events. Otherwise it breaks navigation, seeking, etc...
-- it should return a TRUE/FALSE boolean if the localy handled event was handled.
-
-
-
-
-other ideas:
-
-- plugins should avoid using gst_caps_to_string() in debug statement.
-  They should use %"GST_PTR_FORMAT" instead.  Check all usage for leaks.
diff --git a/docs/random/ds/registry b/docs/random/ds/registry
deleted file mode 100644 (file)
index ff06ef6..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-
-Ideas for a new registry system:
-
-- each plugin has an associated registry XML file.  Each xml file in
-  a plugin directory is loaded to create the in-core registry.
-
-- needed for avidemux:
-
-  <Company> plugin x create some registry information that says stuff like:
-  <Company> "caps x are fourcc FOOO in avi"
-  <Company> or "caps y may be contained in id3 tagged files"
-  <Company> or "caps z is a valid format to put in an ogg container"
-
-
-
diff --git a/docs/random/ds/roadmap b/docs/random/ds/roadmap
deleted file mode 100644 (file)
index 4a54bb8..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-
-After some discussion on IRC, I think it's time to propose a
-formal plan for the next 6 months or so to the list.
-
-I think most people are in agreement that we need a period of time
-in which we can focus on improving non-core bits (like elements,
-schedulers, autopluggers, applications, etc.)  In the last cycle,
-there was a lot of time spent with a significant number of plugins
-broken, and it's realistic to assume that this could happen again
-in a 0.9 unstable series.
-
-What I propose is:
-
- - We continue to develop the 0.8.x series as HEAD, with the obvious
-   requirement that all changes be ABI/API compatible.
- - API additions are encouraged, as long as they are well-thought-out.
-
- - Significant API additions should be developed on a separate branch
-   (not HEAD) to test out any bugs.
-
-In mid-August (or so, in order to coordinate with GNOME-2.8), we have
-two options:
-
- - Continue with 0.8.x releases, obviously ABI compatible with 0.8.0.
-
- - or, remove deprecated functions, readjust the padding on structures,
-   perhaps make a few additional ABI changes [1], and quickly go to
-   0.10.0.
-
-I prefer the latter, although we don't have to decide that until
-later.  In either case, there should be no API changes that affect
-more than a bare minimum of elements or applications.
-
-A few things that we won't be able to do without a true unstable
-branch are:
-
- - using GstStructure for all GstEvents.
-
- - significant clock changes
-
- - significant scheduling changes
-
- - separation of headers into application and plugin headers
-
- - anything that requires modification of every plugin
-
-There are perils with having HEAD being the stable branch,
-specifically that bugs can creep in and accidentally cause regressions
-in releases.  I'm hoping that the introduction of media regression
-testing and also the development of new testsuites will keep this
-to a minimum.  Don't forget that accidental bugs that get into
-releases typically cause rude IRC conversations, which we really
-don't need.  Please keep the bugs (and the rudeness) to a minimum.
-
-Also, keep in mind that we will have to live with 0.8's unfixable
-bugs for an entire year.[2]
-
-
-
-dave...
-
---
-[1] I'm thinking about making GstData a subclass of GTypeInstance or
-    GObject.
-[2] But then, 0.6 was 1 year ago, and felt a lot more buggy when it
-    was released.
-
-
-
--------------------------------------------------------
-This SF.Net email is sponsored by: IBM Linux Tutorials
-Free Linux tutorial presented by Daniel Robbins, President and CEO of
-GenToo technologies. Learn everything from fundamentals to system
-administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
-_______________________________________________
-gstreamer-devel mailing list
-gstreamer-devel@lists.sourceforge.net
-https://lists.sourceforge.net/lists/listinfo/gstreamer-devel
diff --git a/docs/random/ensonic/audiobaseclasses.txt b/docs/random/ensonic/audiobaseclasses.txt
deleted file mode 100644 (file)
index e31047f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-$Id$
-
-= audio base classes =
-We have gst-plugins-base/gst-libs/gst/audio with some audio helper and base
-classes.
-
-audiofilter: for src_caps=sink_caps
-basetransform: *
-
-= new stuff =
-
-
-= todo =
-* mv gstaudiofilterexample -> gst-template
-* make more elements using the baseclass
-  * base: audiorate, audioresample, volume
-  * good: audiopanorama
-
diff --git a/docs/random/ensonic/dparams.txt b/docs/random/ensonic/dparams.txt
deleted file mode 100644 (file)
index 27dc4b7..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-$Id$
-
-* controller changes
-  * handling of G_TYPE_XXX is distributed over
-    gst-controller.c::gst_controlled_property_set_interpolation_mode()
-    gst-controller.c::gst_controlled_property_new
-    gst-interpolation.c 
-  * it would be better to put handlers for each type into a struct
-    and register it into a hashmap with the G_TYPE as the key
-  * functions in  gst-controller.c could try the key,
-    if no handler is registered the try the type_parent and so on
-
-* implement quadric/cubic interpolation
-
diff --git a/docs/random/ensonic/draft-registry-change-hooks.txt b/docs/random/ensonic/draft-registry-change-hooks.txt
deleted file mode 100644 (file)
index 102d6ce..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-Registry Change Hooks
-----------------------
-
-This document proposes a mechanism to register on registry updates.
-
-Last edited: 2009-11-09 Stefan Kost
-
-
-Current Behaviour
------------------
-
-When new plugins are installed or some are removed, the next application that
-runs rebuiilds the registry. Any application that runs later on won't know about
-it.
-
-
-Problem
--------
-
-Some usecases need to cache gstreamer capabilities. They need to know when the 
-cache needs to be rebuilt. We could either export the registry mtime as api or
-do the following.
-
-This gets more useful once we can have more plugin/element metadata in the
-registry (e.g. mime-types for demuxers and codecs, see
-http://www.rfc-editor.org/rfc/rfc4281.txt).
-
-Proposal
---------
-We add a ~/.gstreamer-0.10/registry-hooks directory. Applications can install
-scripts there. When the registry is rebuild, those scripts are run async in no
-specific order. There is no feedback channel (return values, stdout/err).
-
-
-Examples
----------
-
-gst-inspector
--------------
-it would install a script that simply deletes its cachefile.
-
-gupnp
------
-it would install a script that runs gst-inspect-0.10 --print-plugin-auto-install-info
-and post process it.
-
-totem,banshee,rythmbox
------------------------
-they could tune the "MimeType=" lists in their desktop files
-
-
-Open Items
-----------
-Should we have a gst-registry-hook script with --install/--remove/--list actions
-to manage hooks?
-
diff --git a/docs/random/ensonic/dynlink.txt b/docs/random/ensonic/dynlink.txt
deleted file mode 100644 (file)
index 16f29ea..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-$Id$
-
-Currently its only save to link/unlink elements/pad when pipeline is in READY.
-Belowe some thoughts. See http://bugzilla.gnome.org/show_bug.cgi?id=435487
-for patches.
-
-= current api =
-
-gboolean gst_element_link   (GstElement *src, GstElement *dest);
-void     gst_element_unlink (GstElement *src, GstElement *dest);
-
-gst_element_link_many, gst_element_unlink_many, gst_element_link_filtered,
-gst_element_link_pads, gst_element_unlink_pads, gst_element_link_pads_filtered
-
-GstPadLinkReturn gst_pad_link (GstPad *srcpad, GstPad *sinkpad);
-gboolean         gst_pad_unlink (GstPad *srcpad, GstPad *sinkpad);
-
-= use cases =
-
-== inserting an element ==
-
-* we have: e1 ! e4
-* we want: e1 ! e2 ! e3 ! e4
-* we want: e1 ! e2      ! e4
-
-gst_element_insert_linked(e1, e2, e3, e4); // e2 == e3 allowed
-gst_pads_insert_link (e1.src, e2.sink, e3.src, e4.sink);
-  disconnect e1.src, e1.src.peer
-  disconnect e4.sink, e4.sink.peer
-  connect e1.src, e2.sink
-  connect e3.src, e4.sink
-
-== removing an element ==
-
-* we have: e1 ! e2 ! e3
-* we want: e1 ! e3
-
-gst_element_remove_linked(e2);
-gst_pads_remove_link (e1.src, e3.sink);
-  disconnect e1.src, e1.src.peer
-  disconnect e3.sink, e3.sink.peer
-  connect e1.src, e3.sink
-
-== swapping out an elelment ==
-
-* we have: e1 ! e2 ! e6
-* we have: e1 ! e2 ! e3 ! e6
-* we want: e1 ! e4 ! e5 ! e6
-* we want: e1 ! e3      ! e6
-
-gst_element_swap_linked(e1, e4, e5, e6);
-gst_pads_insert_link (e1.src, e4.sink, e5.src, e6.sink);
-  disconnect e1.src, e1.src.peer (=e2.sink)
-  disconnect e6.sink, e6.sink.peer
-  connect e1.src, e4.sink
-  connect e5.src, e6.sink
-
-= thoughts =
-* I don't think we need api for pads
-* Should current api check for the state?
-* do we want to swapp multiple elements at once
-
-== events ==
-* tee and adder need special treatment
-  * both would need to cache an accumulated segment
-  * tee
-    * would also cache tags
-    * when linkfunc is called, it can send out the segment and the tags
-    * when all pads got unlinked it could clear the segment
-  * adder
-    * when linkfunc gets called it sends a seek-event
-
-= ideas =
-== dynlinkpoint ==
-* use cases
-  * its meant to be used with one side disconnected to allow to connect elements
-    at runtime
-  * it can be used in a pipeline to remove/insert elements at runtime
-* element with 1 source- and 1 sinkpad
-* when both connected it passes data thru
-* if src is not connected it drops received buffers
-* if sink is not connected
-  * it does not push
-  * it creates silence on pull
-* events
-  * it caches events
-    * down: newsegment, tags, buffersize
-    * up: seek (needs to be modified)
-  * when other-pad get connected it pushes events depending on direction
diff --git a/docs/random/ensonic/interfaces.txt b/docs/random/ensonic/interfaces.txt
deleted file mode 100644 (file)
index cbff582..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-$Id$
-
-* existing gstreamer interfaces
-  ./gstreamer/gst/gsttaginterface.c
-  ./gstreamer/gst/gstinterface.c
-  ./gstreamer/gst/gsturi.c
-  ./gst-plugins/gst-libs/gst/propertyprobe/propertyprobe.c
-  ./gst-plugins/gst-libs/gst/mixer/mixer.c
-  ./gst-plugins/gst-libs/gst/tuner/tuner.c
-  ./gst-plugins/gst-libs/gst/xoverlay/xoverlay.c
-  ./gst-plugins/gst-libs/gst/colorbalance/colorbalance.c
-  ./gst-plugins/gst-libs/gst/navigation/navigation.c
-* new general interfaces
-  * GST_TYPE_UI_HINT
-    - add hints to generate 'good' looking interfaces to elements
-    - API:
-      GList *get_group_list();
-      struct ui_hint_group {
-        gchar *label;
-        gachr *role;
-        GList *entries;
-      }
-      struct ui_hint_group_entry {
-        enum UiHintGroupEntryType type={PARAM,DPARAM};
-        gchar *name;
-      }
-      roles {
-        /* graphics */
-        "color_selection/rgb",
-        "color_selection/hsv",
-        "aspect_ratio",
-        /* audio */
-        "envelope/adsr",
-      }
-    - features
-      - grouping of parameters, each group has:
-        - a label: giving a title to the group
-        - a role:
-          - this can give the UI a hint about the purpose of the controls
-          - this only makes sense, if we dont make this a thousand templates
-        - a list of dparams or properties
-    - question
-      - should this be aware of instruments (voice-groups)
-        - no, instruments should auto-generate those
-  * GST_TYPE_QUALITY_VS_SPEED
-    - get the name of a property that can be used to switch between
-      - a fast version for e.g. realtime usage
-      - a slower version with higher precision that can be used for off-line
-        rendering
-* new interfaces for audio applications
-  * GST_TYPE_MULTI_VOICE
-    - control interface for elements that support multiple voices (in one output-pad)
-    - API:
-      gulong number_of_voices;
-      void add_voice();
-      void remove_last_voice();
-      gulong get_number_of_voices();
-    - features
-      - plugin will initially have one voice and that one can not be deleted
-  * GST_TYPE_MUSIC_GENERATOR
-    - add hints so that application can use a element as an instrument
-    - API:
-      // param types
-      DParam *get_note_dparam();
-      GList *get_trigger_dparams();
-      // -- or
-      DParamType get_dparam_type(DParam *);
-      dparamtype = { NOTE, TRIGGER, OTHER }
-      // voices
-      char *get_number_of_voices_property();
-      GList *get_global_param_names();
-      GList *get_voice_param_names();
-    - features
-      - find out which params to use to play notes/trigger sounds
-        - these params will not appear in a control-ui
-        - notes involve a key to frequency translation
-      - find out if the element has a number_of_voices property
-        - if yes, we can find out about the max by looking at the gparamspec
-        - setting the property, adds/removes voices
-        - if the element supports it, it needs to:
-          - register voice-dparams as e.g. note_XXX, where XXX is the voice-number
-          - run the voice-loop in the chain/loop function
-            each voice processes the same input, if at all
-            the outputs of all voices are mixed together
-
diff --git a/docs/random/ensonic/lazycaps.txt b/docs/random/ensonic/lazycaps.txt
deleted file mode 100644 (file)
index b8761bf..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-Lazy Caps
-=========
-
-The idea is to have caps where we evaluate the structures as needed. We can have
-these variants of lazy caps:
-
-- construction (e.g. from_string)
-  - need user_data (the string/string-array)
-  - need a free_func for the user_data
-  - need a get_structure_func to fill structure slots as needed
-  - we can more easily make this iterator based too
-- operations (e.g. intersect) (see [1]).
-  - need user_data (the iterator)
-  - need a free_func for the user_data
-  - need a get_structure_func to fill structure slots as needed
-
-We should add PERFORMANCE category logging to methods that cause lazy caps to be
-fully evaluated. To get maximum speed benefit we need to inspect places that 
-loop over structures of a caps and turn them into while() loops where possible.
-
-We can use GST_CAPS_FLAGS_LAZY to indicate that caps are not fully constructed.
-Once caps are fully evaluated, we can remove the flag (and call the free_func).
-
-Lazy caps might need a lock to protect multiple threads requesting a structure
-(get_structure_func).
-
-Accessors
----------
-guint gst_caps_get_size (const GstCaps *caps);
-- needs to fully evaluate the caps if iterator based :/
-
-GstStructure *gst_caps_get_structure (const GstCaps *caps, guint index);- needs to fully evaluate the caps if iterator based :/
-- needs to evaluate all entries up to index if iterator based
-- needs to only evaluate requested index if e.g. parse based
-
-gchar *gst_caps_to_string (const GstCaps * caps)
-- needs to fully evaluate the caps
-- it is used in debugging and serialisation
-
-Construction
-------------
-
-Manipulation
-------------
-void gst_caps_append (GstCaps *caps1, GstCaps *caps2);
-- use an iterator
-
-void gst_caps_merge (GstCaps *caps1, GstCaps *caps2);
-- use an iterator
-
-void gst_caps_append_structure (GstCaps *caps, GstStructure *structure);
-void gst_caps_remove_structure (GstCaps *caps, guint idx);
-void gst_caps_merge_structure (GstCaps *caps,
-- fully evaluate caps?
-
-GstCaps * gst_caps_copy_nth (const GstCaps *caps, guint nth);
-- eval structure and copy
-
-void gst_caps_truncate (GstCaps *caps);
-- eval first structure as needed and remove GST_CAPS_FLAGS_LAZY + call free_func
-
-void gst_caps_set_value (GstCaps *caps, const char *field, const GValue *value);
-void gst_caps_set_simple (GstCaps *caps, const char *field, ...);
-void gst_caps_set_simple_valist (GstCaps *caps, const char *field, va_list varargs);
-- fully evaluate caps
-
-
-Operations
-----------
-
-
-[1] https://bugzilla.gnome.org/show_bug.cgi?id=618853
diff --git a/docs/random/ensonic/logging.txt b/docs/random/ensonic/logging.txt
deleted file mode 100644 (file)
index d3ab917..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-$Id$
-
-rethink log format. current format:
-* is not easy to parse/process by commandline tools
-* cannot be easily diffed (timestamps, pid)
-
-gst_debug_log_default() is default gst-log handler.
-try new via:
-  gst_debug_remove_log_function(gst_debug_log_default)
-  gst_debug_add_log_function(func,data)
-
-== reorder fields ==
-
-format of default handler is:
-                 DEBUG (0x8134bc0 - 0:00:00.848191000)              GST_QOS( 3340) gstbasesink.c(1431):gst_base_sink_do_render_stats:<xvimagesink0> avg_render: 0:00:00.009044000
-log_level_name --^^^^^  |       |   |               |               |     | |   |  |                 | |                           | |
-thread-id --------------^^^^^^^^^   |               |               |     | |   |  |                 | |                           | |
-timestamp --------------------------^^^^^^^^^^^^^^^^^               |     | |   |  |                 | |                           | |
-log_category -------------------------------------------------------^^^^^^^ |   |  |                 | |                           | |
-process-id -----------------------------------------------------------------^^^^^  |                 | |                           | |
-file:line -------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^ |                           | |
-function ----------------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
-message -----------------------------------------------------------------------------------------------------------------------------^^^^^^^^^^^^^^^
-
-new proposed format:
-                 0:00:00.848191000  3340 0x8134bc0 DEBUG               GST_QOS gstbasesink.c:1431:gst_base_sink_do_render_stats:<xvimagesink0> avg_render: 0:00:00.009044000
-timestamp -------^^^^^^^^^^^^^^^^^ |   | |       | |   |               |     | |                | |                           | |
-process-id ------------------------^^^^^ |       | |   |               |     | |                | |                           | |
-thread-id -------------------------------^^^^^^^^^ |   |               |     | |                | |                           | |
-log_level_name ------------------------------------^^^^^               |     | |                | |                           | |
-log_category ----------------------------------------------------------^^^^^^^ |                | |                           | |
-file:line ---------------------------------------------------------------------^^^^^^^^^^^^^^^^^^ |                           | |
-function -----------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
-message ------------------------------------------------------------------------------------------------------------------------^^^^^^^^^^^^^^^
-
-something like:
-  cut -c35- | sed -e "s/0x[0-9a-f]\{7,8\}//g"
-should make logs easily 'diffable'.
-
-== color code level ==
-
-I suggedt to color-code loglevels if COLOR is allowed:
-ERROR   : red
-WARNING : yellow
-INFO    : green
-DEBUG   : turkis
-LOG     : gray
-NONE    : gray
-
-== log sources ==
-
-What about differentating between log sources:
-  core
-  elements
-  application
-
diff --git a/docs/random/ensonic/media-device-daemon.txt b/docs/random/ensonic/media-device-daemon.txt
deleted file mode 100644 (file)
index 81717f9..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-$Id$
-
-components
-================================================================================
-
-- daemon process
-  - is a gstreamer application
-  - open physical sink, src elements
-  - prepends an adder to sinks
-  - appends an tee to sources
-  - listens to dbus, to get notified by virtual-endpoints of init/finalize
-    (the dbus notify, would also be useful for gst-editor to hook on running
-     apps)
-
-- 4 new elements
-  - virtual-audiosink, virtual-videosink
-    virtual-audiosrc, virtual-videosrc
-  - virtual sinks establish a connection to the daemon
-  - they link to request_pads of the adder/tee elements
-  - on init and finalize they send a dbus-message
-
-- gui app
-  - lists instances as mixing-desk like channelstrips
-  - channelstrips would contain
-    - audio
-      - volume, panorama, 3-band eq
-    - video
-      - brightness, contrast, alpha-level
-  - user can
-    - add insert-fx
-    - route channel to targets, where targets can be real sinks or more
-      virtual-sinks (sub-groups)
-  - virtual sinks need queues to decouple application processes
-
-- interfaces
-  - expose child-elements via child-proxy
-    - then e.g. the applications volume-control could directly access the
-      channelstrip
-  - state-control (play, pause/mute)
-    - it would be useful if one app could pause/mute others
-    - think of a voip-client, if there is an incoming call, if pauses your
-      media-player, or mutes the monitoring of your recording app
diff --git a/docs/random/ensonic/plugindocs.txt b/docs/random/ensonic/plugindocs.txt
deleted file mode 100644 (file)
index 987fc68..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-Plugin Docs
-===========
-
-In contrast to normal gtk-doc workflow modules will include
-common/gtk-doc-plugins.mak. This provides an additional 'make udpate' target.
-
-the "make update" target calls
-1.) common/gstdoc-scangobj --type-init-func="gst_init(NULL,NULL)" --module=$(DOC_MODULE) --source=$(PACKAGE)
-    common/scangobj-merge.py $(DOC_MODULE)
-
-the "tmpl" target is modified to run this extra step after "gtkdoc-mktmpl":
-2.) common/mangle-tmpl.py $(srcdir)/inspect tmpl
-
-and the "sgml" target is modified to run this step before "gtkdoc-mkdb":
-3.) for a in $(srcdir)/inspect/*.xml; do \
-  xsltproc --stringparam module $(MODULE) $(top_srcdir)/common/plugins.xsl $$a > xml/`basename $$a`;
-done
-
-Details
-=======
-
-1a.) gstdoc-scangobj
--------------------
-- get types from registry instead of .types file
-- outputs inspect/plugin-<pluginname>.xml files
-- outputs signal and args files
-
-1b.) scangobj-merge.py
----------------------
-- parse, update and write .signals and .args files
-
-2.) mangle-tmpl.py
-------------------
-- read data from inspect/plugin-<pluginname>.xml
-- insert/overwrite "Short Description" and "Long Description" in tmpl/
-- the "Long Description" contains a <xi:include> for xml/element-<name>-details.xml
-
-3.) common/plugins.xsl
-----------------------
-- creates xml/plugin-<name>.xml and xml/element-<name>-details.xml
-
-
-TODO:
------
-- scangobj-merge.py -> gstdoc-scangobj
-- need a way to skip the tmpl step
-  - gtkdoc-mkdb needs a way to insert extra content
-  - maybe patch generated xml/*.xml files
-    - could common/plugins.xsl patch the files?
-      <refsect1 id="gstreamer-plugins-capsfilter.description" role="desc">
-
diff --git a/docs/random/ensonic/receipies.txt b/docs/random/ensonic/receipies.txt
deleted file mode 100644 (file)
index 0d2a0a3..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-$Id$
-
-= receipies =
-
-The idea is to collect some recommendations for common, but not so trivial
-tasks. docs/design/part-block.txt has something like that already. Ideally these
-would go to the application developer manual and there would be sample code.
-
-== initial seeking ==
-=== question ===
-How to I configure the initial playback segment?
-
-=== idea ===
-1) set pipeline to PAUSED
-2) send seek event
-3) set pipeline to PLAYING
-
-=== problems ===
-1) would preroll the pipeline only, to flush it when the seek comes
-
-
-== async state changes ==
-=== question === 
-what to do when gst_element_set_state() returns ASYNC?
-
-=== idea ===
-1) listen to the STATE_CHANGED message on the bus
-2) trigger next action
-
-=== problems ===
-This scatters logic over multiple functions (callbacks).
-
-
-== topic ==
-=== question === 
-=== idea ===
-=== problems ===
diff --git a/docs/random/eos b/docs/random/eos
deleted file mode 100644 (file)
index b4d259f..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-OUTDATED
---------
-
-
-case 1) 
-
- (--------)         (--------)         (--------)
- ! fakesrc!         !identity!         !fakesink!
- !       src ----- sink     src ---- sink       !
- (--------)         (--------)         (--------)
-
-
-
-  fakesrc detects the end of stream. It just sent the last buffer
-  and sets the srcpad to EOS with gst_pad_eos ().
-
-  gst_pad_eos() will notify the parent about the plugins attempt to
-  signal eos. the parent adds the element to its possible EOS 
-  providers.
-  
-  gst_pad_eos() will by default propagate to identy and to fakesink.
-  none of these plugins override the default behaviour so gst_pad_eos
-  returns TRUE and fakesrc signals EOS with the value TRUE.
-
-  The parent looks in the list of EOS providers and finds the faksrc
-  element that is now signaling EOS. all EOS providers are now in EOS
-  and so the bin fires EOS.
-
-
-
-case 2) 
-                                                     (---------------)
-                                                     !thread         !
- (--------)         (--------)         (--------)    !     (--------)!
- ! fakesrc!         !identity!         !  queue !    !     !fakesink!!
- !       src ----- sink     src ---- sink       src ---- sink       !!
- (--------)         (--------)         (--------)    !     (--------)!
-                                                     (---------------)
-
-
-  fakesrc detects the end of stream. It just sent the last buffer
-  and sets the srcpad to EOS with gst_pad_eos ().
-
-  gst_pad_eos() will notify the parent about the plugins attempt to
-  signal eos. the parent adds the element to its possible EOS 
-  providers.
-
-  gst_pad_eos() will by default propagate to identy and to queue.
-  queue overrides the eos handler and returns false on the eos
-  request. fakesrc signals EOS with a value of false and the parent
-  bin removes the EOS provider from its list.
-
-  after the queue has sent out the last buffer, its calls eos on its
-  src pad. queue is added to the top level bin as an eos provider and
-  the default eos handler signals EOS with a value of TRUE to the parent.
-
-  the parent sees that all the eos providers are in eos now and signals
-  EOS.
-
-
-case 3) 
-                                                     (---------------)
-                                                     !thread         !
- (--------)         (--------)         (--------)    !     (--------)!
- ! fakesrc!         !  tee   !         ! queue1 !    !     !fakesink!!
- !       src ----- sink     src ---- sink       src ---- sink       !!
- (--------)         !        !         (--------)    !     (--------)!
-                    !        !                       (---------------)
-                    !        !
-                    !        !                       (---------------)
-                    !        !                       !thread         !
-                    !        !         (--------)    !     (--------)!
-                    !        !         ! queue2 !    !     !fakesink!!
-                    !       src ---- sink       src ---- sink       !!
-                    !        !         (--------)    !     (--------)!
-                    (--------)                       (---------------)
-
-
-  fakesrc detects the end of stream. It just sent the last buffer
-  and sets the srcpad to EOS with gst_pad_eos ().
-
-  the eos handler returns false because both queues return false on the
-  eos request. the parent removes fakesrc as an EOS provider.
-
-  queue1 and queue2 were responsible for the EOS delay and so they get
-  added to the bin as possible EOS providers.
-
-  after the queues have sent out their last buffer, they calls eos on their
-  src pads.
-  the parent already has the two queues in the EOS provider list so they dont
-  get added twice.
-  the two queues perform gst_pad_eos () on their pads when the queue is empty,
-  the parent removes the EOS providers from its list, when the list is empty,
-  the parent fires EOS.
-  
-  
-case 4) 
-
-                                                     (---------------)
-                                                     !thread         !
- (--------)       (----------)         (--------)    !     (--------)!
- ! fakesrc!       !mpeg1parse!         ! queue1 !    !     !fakesink!!
- !       src -- sink        src ---- sink       src ---- sink       !!
- (--------)       !          !         (--------)    !     (--------)!
-                  !          !                       (---------------)
-                  !          !
-                  !          !                       (---------------)
-                  !          !                       !thread         !
-                  !          !         (--------)    !     (--------)!
-                  !          !         ! queue2 !    !     !fakesink!!
-                  !         src ---- sink       src ---- sink       !!
-                  !          !         (--------)    !     (--------)!
-                  (----------)                       (---------------)
-
-
-  this case differs from case3 in that one of the queues can be empty
-  while the other isn't. we assume queue1 is empty while queue2 isn't yet.
-
-  fakesrc detects the end of stream. It just sent the last buffer
-  and sets the srcpad to EOS with gst_pad_eos ().
-
-  the eos handler returns false because queue2 returns false on the
-  eos request. the parent removes fakesrc as an EOS provider.
-
-  queue2 was responsible for the EOS delay and so it gets added to the bin
-  as a possible EOS provider.
-
-  after the queue2 has sent its last buffer, it performs gst_pad_eos on its
-  src pad.
-  the parent already has the queue2 in the list of EOS providers so it does not
-  get added twice.
-  queue2 finally fires the EOS signal and the parent removes the EOS provider 
-  from its list, when the list is empty, the parent fires EOS.
-
-  
-
-case 5) 
-
- (--------)         (--------)         (--------) 
- ! disksrc!         !  mad   !         !filesink! 
- !       src ----- sink     src ---- sink       ! 
- (--------)         (--------)         (--------)
-
-
-  disksrc detects the end of stream. It just sent the last buffer
-  and sets the srcpad to EOS with gst_pad_eos ().
-
-  the eos handler returns false because mad returns false on the
-  eos request. the parent removes mad as an EOS provider.
-
-  mad was responsible for the EOS delay and so it gets added to the bin 
-  as a possible EOS provider.
-
-  After mad has sent its last buffer, it performs gst_pad_eos on its
-  src pad.
-  the parent already has mad in the list of EOS providers so it does not
-  get added twice.
-  mad finally fires the EOS signal.  This time, filesink returns false on
-  the eos request.  the parent removes mad as an EOS provider. 
-  
-  filesink was responsible for the EOS delay and gets added to the bin
-  as a possible EOS provider.
-  When filesink has written all of it's data and closed the output file,
-  it fires EOS.
-  The parent already has filesink in the list of EOS providers so it does
-  not get added twice.
-  The parent removes the EOS provider 
-  from its list, and since the list is empty, the parent fires EOS.
-
-case 6) 
-
- (--------)         (--------)         (--------) 
- !disksrc1!         !  mad1  !         ! mixer  ! 
- !       src ----- sink     src ---- sink1      !        (--------)
- (--------)         (--------)         !        !        !filesink!
-                                       !       src ---- sink      !
- (--------)         (--------)         !        !        (--------)
- !disksrc2!         !  mad2  !         !        ! 
- !       src ----- sink     src ---- sink2      ! 
- (--------)         (--------)         (--------)
-
-  In this case, we want to make sure the pipeline keeps running after one
-  of the two sources reaches eos.  Suppose in this case that disksrc1 will
-  reach eos first.
-
-  disksrc1 detects the end of stream. It sets eos, mad1 will return false,
-  and mad1 will be responsible for eos.  When mad1 had sent out the last
-  buffer, it sends out eos.
-
-  The mixer intercepts eos and returns false.  mad1 is removed from the
-  eos providers and mixer is added.
-
-  (At this point, the mixer might choose to disconnect mad1->src and
-  mixer->sink1 pads, since it's received eos on mad1->src)
-
-  mixer will not send out eos since it hasn't received eos from 
-  mad2->src.
-
-  After a while, disksrc2 will detect end of stream, and eos will finally
-  propagate to mixer.  mixer might disconnect mad->src2, and after
-  realizing all of it's sources have reached eos, it sends out the final
-  buffer and fires EOS.
-
-  At this point, filesink will return false, mixer will be removed as an
-  eos provider, and filesink will write out it's final buffer and close
-  the file on disk.  At this point, it fires eos, and since it's the last
-  eos provider, the parent can fire eos.
-
-
diff --git a/docs/random/error b/docs/random/error
deleted file mode 100644 (file)
index bccb239..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-Some notes on the error handling introduced after 0.7.3
-
-- there are four domains for errors:
-  - CORE: core GStreamer errors
-  - LIBRARY: supporting library errors
-  - RESOURCE: errors accessing resources (files, network, memory, ...)
-  - STREAM: errors in the data stream
-- Each error in GStreamer or plug-ins can be put under one of these four.
-- the enum is called Gst(Domain)Error and has GST_(DOMAIN)_ERROR_(CODE) members
-  (see GError API docs for rationale)
-- each of the enums starts with _FAILED at 1 (with FAILED being the generic
-  error if none of the others applies)
-- second in the enum is TOO_LAZY, which allows us to keep track of those errors
-  that we haven't categorized yet.  This means they really should either move
-  to another one, or a new one ought to be created.
-- each enum ends with NUM_ERRORS
-
-- elements call gst_element_error to signal an error:
-  gst_element_error (element, domain, code, message, debug);
-  With :
-  - element being the one signalling the error
-  - domain one of CORE, LIBRARY, RESOURCE, STREAM
-  - code one of the suffixes in the Gst(Domain)Error enum
-  - message is either NULL (to signal the standard error message for the
-    given domain and code), or a printf-like set with the format being
-    marked for translation.
-    The string should start with a capital and end in a period so it forms
-    a complete sentence.
-    The string can/should be shown to the user of an application.
-  - debug is either NULL or a non-translated debug string, which can be used
-    to diagnose errors after they've happened.
-    The string can be shown to the user when he asks for additional debug info.
-    A useful macro is GST_ERROR_SYSTEM, which prints out the system error
-    that explains the failure by using g_strerror.
-
-- Some example calls:
-
-      gst_element_error (src, RESOURCE, OPEN_READ,
-        (_("Could not open file \"%s\" for reading"), src->filename),
-        GST_ERROR_SYSTEM);
-
-      The message is specified since we have more information:
-          - the resource is a file 
-          - we know the file name
-
-      gst_element_error (element, CORE, NEGOTIATION, NULL, NULL);
-      This is a simple negotiation error.  The default message will be
-      signaled, telling the user that GStreamer had an internal error.
-
-      gst_element_error (ebml, RESOURCE, READ, NULL,
-                         ("Read error at position %llu (0x%llx)",
-                         pos, pos));
-
-      The plugin asked to read on the underlying resource (using bytestream),
-      but failed.  The user will get a generic read error.  The debug info
-      will contain the exact position in the stream at which the read error
-      occurred.
-
diff --git a/docs/random/example b/docs/random/example
deleted file mode 100644 (file)
index 87bf619..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-OUTDATED, methods have different names now
-------------------------------------------
-
-
-Here's a pipeline that does audio/video MPEG streams with a queue on
-either side of each decompressor, for a total of 5 threads (read/split,
-decode audio, decode video, play audio, play video):
-
-NOTES: mpegsplit is the intelligence in this pipeline, providing an IDL
-that allows one to connect things to a GUI.  
-
-Pipeline(mpegplay)
-       Thread(reader)
-               Element(:disk_async_src) [StreamerAsyncSrc]
-                       OutPad(disk1)
-               Element(:mpegsplit)
-                       InPad(disk1)
-                       OutPad(audio1)
-                       OutPad(video1)
-
-       Queue(audioQ1)
-               InPad(audio1)
-               OutPad(audio2)
-       Thread(audiodecode)
-               Element(:mpeg_audio_decode) [StreamerVideoFilter]
-                       InPad(audio2)
-                       OutPad(audio3)
-       Queue(audioQ2)
-               InPad(audio3)
-               OutPad(audio4)
-       Thread(audioplay)
-               Element(:audio_play) [StreamerAudioSink]
-                       InPad(audio4)
-
-       Queue(videoQ1)
-               InPad(video1)
-               OutPad(video2)
-       Thread(videodecode)
-               Element(:mpeg_video_decode) [StreamerVideoFilter]
-                       InPad(video2)
-                       OutPad(video3)
-       Queue(videoQ2)
-               InPad(video3)
-               OutPad(video4)
-       Thread(videoplay)
-               Element(:video_play) [StreamerVideoSink]
-                       InPad(video4)
-
-
-A simpler pipeline that just does MPEG videos:
-
-Pipeline(mpegplay)
-       Thread(reader)
-               Element(:disk_async_src) [GstAsyncSrc]
-                       OutPad(disk1)
-               Element(:mpeg_control)
-                       InPad(disk1)
-                       OutPad(video1)
-               Element(:mpeg_video_decode) [GstVideoFilter]
-                       InPad(video1)
-                       InPad(video2)
-       Queue(queue)
-               InPad(video2)
-               OutPad(video3)
-       Thread(play)
-               Element(:video_play) [GstVideoSink]
-                       InPad(video3)
-
-The code for the above looks roughly like:
-
-/* all the objects we're worried about */
-GstPipeline *mpegplay;
-GstThread *reader;
-GstSrc *disk_src;
-GstControl *mpeg_control;
-GstFilter *mpeg_video_decode;
-GstQueue *queue;
-GstThread *play;
-GstSink *video_play;
-
-/*** first we create all of the objects ***/
-
-mpegplay = gst_pipeline_new();
-reader = gst_thread_new();
-disk_src = gst_async_disk_src_new("filename.mpg");
-mpeg_control = gst_mpeg_control_new();
-mpeg_video_decode = gst_mpeg_video_decode_new();
-queue = gst_queue_new();
-play = gst_thread_new();
-video_play = gst_video_sink_new();
-
-
-/*** now we start to create the pipeline ***/
-
-/* first set up the reader thread */
-gst_bin_add(reader,disk_src);
-gst_object_connect(disk_src,"out",mpeg_control,"in");
-gst_object_connect(mpeg_control,"out",mpeg_audio_decode,"in");
-gst_bin_ghost_pad(reader,mpeg_audio_decode,"out");
-
-/* then set up the player thread */
-gst_bin_add(play,audio_play);
-gst_bin_ghost_pad(play,audio_play,"in");
-
-/* now plug them all into the main pipeline */
-gst_bin_add(mp3play,reader);
-gst_object_connect(reader,"out",queue,"in");
-gst_object_connect(queue,"out",play,"in");
diff --git a/docs/random/hierarchy b/docs/random/hierarchy
deleted file mode 100644 (file)
index a07f8b8..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-OUTDATED
---------
-
-
-Face it, the plugins/ directory hierarchy is crap. We want to propose a
-better layout for it now. Some things to consider:
-
- - Elements have a klass member in the factory that is used to
-   denote the functional type of the element. For example, the
-   mp3 encoder has a klass of Codec/Encoder/Audio
-   
- - The plugins can be grouped together by the media type they
-   operate on or by the way they work (decoder/encoder)
-   
-In GStreamer all plugins are technically filters, the only way they
-can be considered sources or sinks (input/output) elements is
-by the absence of src/sink pads. At first sight the source/filter/
-sink distinction is quite useless because most of the plugins
-will go into the filters category anyway. 
-
-We don't want to make the hierarchy too deep, yet provide a 
-clean way to ask for a mp3 decoder element..
-
-Anyway this is a rough proposal to fire off the discussions...
-
-Wim
-
-Source 
-  Disk
-    disksrc
-    fdsrc
-    multifilesrc
-  Network
-    HTTPsrc
-    RTPsrc
-  CDDA
-    cdparanoia
-  XMMS
-    ..
-  DVD
-    dvdsrc
-  Audio
-    ASLA
-    OSS
-  Capture
-    v4lsrc
-    firewire
-  
-Demuxer     
-  AVI
-  MPEG1
-  MPEG2
-  QT
-  
-Muxer
-  AVI
-  MPEG1
-  QT
-  
-Aggregator
-
-Tee
-  gsttee
-  
-Connection
-  queue
-  CORBA
-
-Parser
-  MPEG1
-  MPEG2
-  AC3
-
-Mixer
-  Audio
-    Merge
-  Video
-    Subtitles
-    Merge
-
-Filters
-  Audio
-    ladspa
-    resample
-  Video
-    colorspace
-  
-Effect
-  Audio
-    stereo
-    volume
-    delay
-    chorus
-  Video
-    median
-    smooth
-  XMMS
-
-Decoder
-  MPEG1
-  MPEG2
-  MP3
-    mpg123
-    xing
-  win32
-  AU
-  WAV
-  JPEG
-  AC3
-    ac3dec
-  RTJPEG
-  vorbis
-
-Encoder
-  MPEG1
-  MPEG2
-  MP3
-    lame
-    mpegaudio
-  win32
-  JPEG
-  AU
-  WAV
-  RTJPEG
-  Vorbis
-
-Visualisation
-  Video
-    histogram  
-  Audio
-    smoothwave
-    spectrum
-    synaesthesia
-    vumeter
-  XMMS
-
-Sink
-  Disk
-    filesink
-    multifilesink
-  Network
-    ICECASTsink
-    FTPsink
-    RTPsink
-  XMMS
-  ESD
-  Video
-    videosink
-    SDLsink
-  Audio
-    OSSsink
-    ALSAsink
-    
diff --git a/docs/random/interfaces b/docs/random/interfaces
deleted file mode 100644 (file)
index d4d473b..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-INTERFACES & ELEMENTS
----------------------
-
-1) Introduction
-===============
-Interfaces are descriptions on how to handle an object, without actually
-implementing the object. This allows for multiple objects to be instantiated
-based on this interface. Each of them can then be handled equally by an
-application.
-Glib, apparently (unchecked), has a way of creating interfaces, probably
-by means of a class struct without actually defining the object. The object,
-then, does not define a class and these two add up. Benjamin knows more
-about interfaces, I didn't study interfaces & glib too deeply, yet. I know
-them just from Java.
-Interfaces are cool! It allows for some sort of random element creation
-without needing to link to the implementation. This is similar to how
-GStreamer currently handles media plugins. GStreamer itself could be seen
-as an interface too, in that respect.
-
-2) So why do we need interfaces?
-================================
-Because GStreamer doesn't handle it all. GStreamer in itself is a media
-framework for streams of data from one element to the next. There's lots
-of things that's media-related, but not handled in this description.
-Several examples will probably clarify this: think of the Xvideo output
-plugin. We can create an overlay here (Xv-based), and we currently control
-this X-connection using glib properties. However, what property name is
-associated with what control? And does it work the same as v4lsrc's
-overlay image control?
-The same goes for a mixer, for image control, audio control, and probably
-a lot more. The general idea is simple: *this needs to be documented*.
-But properties aren't all - they simply cannot do this all. Some things
-cannot be described in a simple one-argument property thing. Of course,
-we could give a pointer to a struct as argument, but that's merely a hack
-and requires both plugin and app to know the ABI of the struct. This
-kills the whole idea of making the plugin independent of the app.
-In short: we want interfaces for this.
-
-3) How to integrate an interface in GStreamer
-=============================================
-Let us start with some starting point: an interface is associated
-with an element. It is a feature exported by that specific element,
-not by a pipeline or anything more complex. Pipelines are already
-handled just fine by GStreamer (or you wouldn't be reading all
-this).
-Obviously, a pipeline can be a fallback for an interface. Imagine
-that we're looking for an audio sink that exposes a mixer, but our
-fakesink audio output doesn't ("I wonder why"). We could then create
-a pipeline with the volume element in it to "fake" a mixer. Ideally,
-the volume element would implement a mixer interface itself.
-
-How are we going to do that in programmatic way? We currently use
-properties. Their huge advantage is that we do not need to care
-about adding new functions or whatever. Their disadvantage is that
-they're limited to one argument. Anything more complex requires
-app/plugin knowledge about the shared data, and that defeats the
-point of them: to have no dependency on each other. This could be
-solved partially by using action signals, but that makes the whole
-picture quite complex (since you use multiple methods for doing one
-simple thing). Also, they are quite slow compared to functions
-because of the table lookups. In short: it'd work, but I'm not in
-facour of it...
-OK, so an element exposes interfaces. This allows us to think of
-the idea of embedding interfaces (dynamically, of course) in the
-GstElement object. Think of an object being able to register an
-indefinate number of interfaces per object instance, and a client
-application could then enumerate interfaces and instantiate one.
-Glib gives us GInterface for this purpose. The disadvantage of
-this is that it's on a per-class basis, not a per-instance basis.
-This is a problem in case of elements where it depends on several
-properties whether it supports an interface or not. This can be
-solved by simply making one generic virtual function "supported ()"
-in a generic derived object of GInterface (GstInterface?).
-
-GstInterface is then a generic thing that is inherited by specific
-interfaces (see examples). Obviously, the client will need to know
-about the ABI/API of this struct, but that'll happen either way.
-Surely, there needs to binary linkage, but I don't consider that a
-bad thing. It does improve performance compared to action signals!
-
-So an element contains interfaces. But where are these interfaces
-described? And who creates them? I suggest that we do that just as
-we handle gstvideo and gstaudio right now (these libs do *nothing*
-useful currently, so this'd make them a lot more interesting).
-These interfaces inherit from GstInterface. The functions that
-are needed, can be provided through a class object. The element is
-then responsible for storing variables and so on. gstvideo/audio
-provides wrapper functions for the class functions. That's also how
-glib suggest us to use GInterfaces.
-
-Plugin and application then handle and retrieve interfaces as
-documented in the glib documentation, which is available at:
-http://www.gnome.org/~mathieu/gobject/main.html
-
-So the most important part left is to document the interfaces
-and make sure all elements exporting them work equally. For this,
-I'll give two examples.
-
-4) Examples
-===========
-
-/* 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.
- */
-typedef struct _GstInterfaceClass {
-  GTypeInterface parent;
-
-  /* virtual functions */
-  gboolean (* supported) (GstInterface *iface);
-} GstInterfaceClass;
-
-There would probably be a convenience function that checks
-a specific interface's implementation (glib allows for this)
-and checks for ->supported () to be set and to return TRUE:
-
-gboolean
-gst_element_implements_interface (GstElement *element,
-                                 GType       iface_type)
-{
-  if (G_TYPE_CHECK_INSTANCE_TYPE (G_OBJECT (element),
-                                 type)) {
-    GstInterface *iface;
-    GstInterfaceClass *ifclass;
-
-    iface = G_TYPE_CHECK_INSTANCE_CAST (G_OBJECT (element),
-                                       type, GstInterface)
-    ifclass = GST_INTERFACE_GET_CLASS (iface);
-
-    if (ifclass->supported != NULL &&
-        ifclass->supported (iface) == TRUE) {
-      return TRUE;
-    }
-  }
-
-  return FALSE;
-}
-
-Let's now add some functions so we can abuse this in case/check
-functions.
-
-GstInterface *
-gst_interface_cast (gpointer from,
-                   GType    type)
-{
-  GstInterface *iface;
-
-  /* check cast, give warning+fail if it's invalid */
-  if (!(iface = G_TYPE_CHECK_INSTANCE_CAST (G_OBJECT (element),
-                                           type, GstInterface))) {
-    return NULL;
-  }
-
-  /* if we're an element, take care that this interface
-   * is actually implemented */
-  if (GST_IS_ELEMENT (from)) {
-    gboolean interface_is_implemented =
-       gst_element_implements_interface (GST_ELEMENT (from),
-                                         type);
-    g_return_val_if_fail (interface_is_implemented == TRUE, NULL);
-  }
-
-  return iface;
-}
-
-gboolean
-gst_interface_check (gpointer from,
-                    GType    type)
-{
-  GstInterface *iface;
-
-  /* check cast, return FALSE if it fails, don't give a warning... */
-  if (!G_TYPE_CHECK_INSTANCE_CAST (from, type,
-                                  GstInterface)) {
-    return FALSE;
-  }
-
-  iface = G_TYPE_CHECK_INSTANCE_CAST (G_OBJECT (element),
-                                     type, GstInterface);
-
-  /* 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;
-}
-
-#define GST_INTERFACE_CHECK_INSTANCE_CAST(obj, type, cast_t) \
-  ((cast_t *) gst_interface_cast ((obj), (type))
-#define GST_INTERFACE_CHECK_INSTANCE_TYPE(obj, type) \
-  (gst_interface_check ((obj), (type))
-
-We could use this in the GST_IS_... () macros. For example, the
-macros GST_IS_MIXER () and GST_MIXER () would then look like this:
-
-/* Note that this is a non-standard macro, and with a reason! */
-#define GST_MIXER(obj) \
-  (GST_INTERFACE_CHECK_INSTANCE_CAST ((obj), \
-                                     GST_TYPE_MIXER,
-                                     GstMixer))
-#define GST_IS_MIXER(obj) \
-  (GST_INTERFACE_CHECK_INSTANCE_TYPE ((obj), \
-                                     GST_TYPE_MIXER))
-
-So the application would just tread it with the known macro, and
-everything would look extremely simple to the end user.
-
-4a) mixer
----------
-A mixer is a way of controlling volume and input/output channels.
-This doesn't mean that you control which channel is the subwoofer,
-all that is supposed to be done automatically. It is really meant
-as a way of representing system-level volumes and such. It could
-also be used to turn on/off certain outputs or inputs.
-As you've noticed, I'm not only talking about output, but also
-input. Indeed, I want both osssrc *and* osssink to export the
-same mixer interface! Or at least a very similar one. Volume
-control works the same for both. You could say that osssrc should
-enumerate the input channels (such as microphone, line-in). Of
-course, osssink should not. Or maybe it should, not sure... Maybe,
-we'd need a parent osselement which implements all mixer channels.
-And alsa* would surely implement the same interface.
-
-/* This is confusing naming... (i.e. FIXME)
- * A channel is referred to both as the number of simultaneous
- * sound streams the input can handle as well as the in-/output
- * itself
- */
-
-#define GST_MIXER_CHANNEL_INPUT  (1<<0)
-#define GST_MIXER_CHANNEL_OUTPUT (1<<1)
-#define GST_MIXER_CHANNEL_MUTE   (1<<2)
-#define GST_MIXER_CHANNEL_RECORD (1<<3)
-
-typedef struct _GstMixerChannel {
-  gchar *label;
-  gint   current_num_channels,
-         max_num_channels,
-         flags;
-} GstMixerChannel;
-
-typedef struct _GstMixerClass {
-  GTypeInterface klass;
-
-  /* virtual functions */
-  GList *  (* list_channels) (GstMixer        *mixer);
-
-  void     (* set_volume)    (GstMixer        *mixer,
-                             GstMixerChannel *channel,
-                             gint            *volumes);
-  void     (* get_volume)    (GstMixer        *mixer,
-                             GstMixerChannel *channel,
-                             gint            *volumes);
-
-  void     (* set_mute)      (GstMixer        *mixer,
-                             GstMixerChannel *channel,
-                             gboolean         mute);
-  void     (* set_record)    (GstMixer        *mixer,
-                             GstMixerChannel *channel,
-                             gboolean         record);
-} GstMixerClass;
-
-libgstmixer.la/so provides wrapper functions for each of the
-class' virtual functions. Possibly also some macros for
-GST_MIXER_CHANNEL_HAS_FLAG () or _get_channel ().
-
-The rest is done automatically, as described in the already-
-mentioned glib documentation for GInterface. This includes
-things like the base_init () function of the GstMixerClass,
-which fills all the virtual functions for the mixer, and the
-actual function implementations. The mixer, basically, operates
-as an element on its own. It gets the file descriptor from
-the interface->element (every oss... is a osscommon, etc.).
-
-4b) overlay
------------
-Overlay is used in both in- and output, too. Think of v4lsrc,
-v4l2src, v4lmjpegsrc, xvideosink - all overlays. But where do
-we position the overlay window? Control of this can be done at
-various levels: locational control (over the server, asynchronous)
-or XID control (but that makes you depend on X and limits the
-ability to broaden it over to non-X elements such as fbsink).
-
-However, simplicity *is* an issue here. Do we really care about
-overlay? In the end, users will have to link against either FB
-or X anyway, so we might want to create separate interfaces for
-both. On the other hand, we want to be general too... This is a
-decision that we need to make as early as possible in this process.
-For now, I propose making X- and FB-based interfaces.
-
-Let's assume that we take X as a basis. Then, overlay becomes as
-simple as one function. Possible extendible by providing inputs
-(like in the mixer) and norms, although that only applies to
-input-to-analog, not to-digital... Others simply return NULL.
-
-typedef struct _GstOverlayClass {
-  GTypeInterface klass;
-
-  /* virtual functions */
-  void    (* set_xwindowid) (GstOverlay        *overlay,
-                            XID                xid);
-} GstOverlayClass;
-
-That's all! It would look similar for FB & co.
-
-4c) user input
---------------
-And yes, user input could be an interface too. Even better, it
-should definitely be. And wasn't this one of our key issues for
-0.8.0?
-
-No code here. Go implement it, lazy ass!
-
-General ways of thinking: input can come from a plugin, or from
-the application (we don't have modules for joystick input et all).
-However, plugins handling input (such as dvdsrc) need to be able
-to handle each. So we get both input-to-application as well as
-input-from-application APIs.
-
-5) Status of this document
-==========================
-The interfaces are implemented, more (for metadata, framebuffer-
-overlay, video balancing (brightness), user input etc. are all
-pending.
-
-6) Copyright and blabla
-=======================
-(c) Ronald Bultje, 2003 <rbultje@ronald.bitfreak.net> under the
-terms of the GNU Free Documentation License. See http://www.gnu.org/
-for details.
-
-And no, I'm not for hire. ;).
diff --git a/docs/random/metadata b/docs/random/metadata
deleted file mode 100644 (file)
index d986555..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-OUTDATED
---------
-
-The point of the metadata is to provide some context for each buffer.  In
-the case of audio data, for instance, it would provide the samplerate, bit
-depth, and channel count.
-
-The trick is that there may be multiple types of metadata ganged onto a
-single buffer.  This is why they're going to be a GList.  This does mean
-extra overhead in all cases, but I think it's minimal.  The GList type
-uses a chunk allocater so we're not wasting too much memory or time when
-adding to the list.
-
-The trick is dealing with these structs as they pass through a pipeline,
-since they have potentially different mutability properties.  For
-instance, if you've got a mp3 decoder connected to a tee, which sends the
-buffers off to both the decoder and a spectrum analyzer (and then a
-visualization element).  The preferred setup would be where every time a
-audio/raw metadata comes down the pipe (indicating a potential change in
-audio format), the audiosink and spectrum would just save off pointers.
-
-So when exactly does this metadata go away (deallocated)?  Well, that
-means metadata has to be refcounted.  But that gets rather hairy.  OK, in
-the simple case you create a metadata struct, it comes with refcount set
-to 1.  You pass it through, it stays one, eventually someone drops the
-last reference on the buffer it's tied to, you free the metadata too.
-Easy.  What if you tee?  You could go through and for every metadata in
-the buffer, increment the refcount by the same as the buffer.  So in the
-above case (tee'd), the audiosink and spectrum would get the buffer with a
-refcount of 2, and it'd have a metadata with refcount 2.  Do they ref it
-each themselves, then unref the buffer?  Or do they remove the metadata?
-Removing the metadata would require a buffer CoW, which would suck, so
-yes, they'd just ref the metadata.
-
-But....  what if they're all in different threads?  Then we're off into
-the magical world of mutexes.  Everything with a refcount in a threaded
-world must be mutexed, else you can do atomic increment and atomic
-dec&test.  Can this be done from C easily?  Perhaps it needs to be found
-from kernel includes via autoconf?
-
-
-
-
-The goal in designing the way metadata will be defined and used is to keep
-it as simple as possible.  The basis for accomplishing this is the fact
-that in order to actually use (rather than just pass) the metadata, you
-have to know what the fields are, which means you have to have compiled in
-support for that metadata at build time.  Therefore, if you're using
-metadata, you must have build-time access to the necessary include file
-that defines it.
-
-So, given that you've got an include file, it would be nice if the whole
-thing could be contained there.  This would limit the need to be linked
-against something, or have load-time requirements as to that has to be
-loaded before you are.
-
-Given that really all metadata is is a region of memory of a given size
-with a certain signature, this isn't all that hard.  First you lay out the
-struct that defines the metadata.  Then you set up #defines that expand to
-the size of the struct in question, as well as the four-cc code that
-defines the type.
-
-The work is done by a few #defines, a la the #defines used in all Gtk
-objects.  The first is a NEW() method that allocates the memory for the
-metadata and fills in all the normal fields (type, size, utility
-functions).  Because of the way it's defined (as a #define, no less),
-you'll have to invoke it as META_NEW(meta), since it can't return()
-anything.
-
-Another #define will check to make sure a meta is indeed that type by
-verifying the type code and size.  Theoretically, meta types can overlap
-with the same fourcc code, as long as they have different sizes.  But I
-probably ought to have a global public registry so people writing things
-don't conflict.  MSFT got that right, at least.
-
-So, a hairy problem is what to do when there are utility functions
-associated with one of these things.  One option is to not bother with
-them.  This is very likely a possible solution, since metadata is supposed
-to be flat memory of a given size.  Not much to do to either free or copy
-it, is there?
index 814ee1a..a64b967 100644 (file)
@@ -1,7 +1,7 @@
 Moving around plug-ins between source modules
 ---------------------------------------------
 
-Last updated: 2013-12-13
+Last updated: 2020-05-19
 
 Contents:
   1. How to get your plug-in out of -bad and into -good or -ugly (ie. policies)
@@ -30,11 +30,11 @@ PEOPLE
   The three roles can be filled by two people, but not just one.
 
   In addition, an admin needs to perform the actual move, which involves
-  CVS surgery.
+  GIT surgery.
 
 PROCESS
 -------
-- bug in bugzilla gets filed by someone requesting a move from bad
+- Issue in gitlab gets filed by someone requesting a move from bad
   to good/ugly
   This is "requesting" the move.
 - a second person reviews the request and code, and verifies that the
@@ -66,15 +66,9 @@ CHECKLIST
     embedded systems).
 
 - The plug-in's build:
-  - should be correctly integrated with configure.ac
+  - should be correctly integrated with Meson buildsystem
   - files implementing elements should be named according to their class name,
     e.g GstBaseSink -> gstbasesink.c
-  - should list libs and cflags in stack order, with lowest in the stack first
-    (so one can link against highest in the stack somewhere else without
-     picking up everything from the somewhere else)
-    e.g. $(GST_PLUGINS_BASE_CFLAGS) \
-         $(GST_BASE_CFLAGS) \
-         $(GST_CFLAGS) $(CAIRO_CFLAGS)
 
 - The compiled plug-in:
   - should show up correct in gst-inspect output; no warnings, no unknown
@@ -191,8 +185,8 @@ For safety, it is recommended to do all this work in a temporary branch
 At this point, we have all the commits related to gst/weneedthis/ in -bad.
 
 We also need to move the other related parts in:
-* configure.ac
-* Makefile.am from intermediary directories (if needed)
+* meson.build
+* meson_options.txt
 * i18n
 * documentation
 
diff --git a/docs/random/mutability b/docs/random/mutability
deleted file mode 100644 (file)
index 74a0944..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-Mutability is the property of an object that defines whether or not you
-are allowed to modify it.  In the context of GST, that means that if you
-want to mutilate a buffer, say to do an audio effect, you may have to do
-this on a copy of the buffer, if someone else has a reference on it.
-
-The simplest sequence of events in a decoder pipeline is as follows:
-
-1) create buffer
-2) allocate and fill data region, attach to buffer
-3) pass to next element
-4) decode the data into new buffer, free original buffer
-5) pass to next element
-6) buffer gets copied to output device (sound, video, whatever)
-
-Both of these buffers are created from malloc()'d memory, are referenced
-by one and only one element at a time, and are never modified in place.
-They have no special flags, and when ref==0, they're simply free()'d.
-
-An optimization in the case of the sound card or video double buffering,
-where the output buffer actually comes from the output device.  In that
-case the element will be aware of such things.
-
-A more complex example is where the data is teed after being decoded, sent
-to an effects or visualization object.
-
-1) create buffer, fill from source
-2) hand to decoder
-3) create new buffer, decode into it, free old buffer
-4) hand to tee
-5) ref++, hand off to 
diff --git a/docs/random/negotiation b/docs/random/negotiation
deleted file mode 100644 (file)
index 76dc197..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-
-Some notes on pad negotiation
-
-
-A "pad link" is a connection between two pads.  It can be in one of
-two states, "negotiated" or "not negotiated".  Pad links are created
-by gst_pad_link().
-
-A "pad link" is created when two pads are linked using gst_pad_link().
-When initially created, the link only specifies a src pad, a sink pad,
-and optionally a filter caps provided by the application.
-
-In order to pass data through a link, the peer pads must decide on
-what data format to use.  This is called negotiation.  Pads
-describe acceptable data formats by using a combination of  pad
-template caps and (optionally) a pad->getcaps function.
-
-
-Negotiation can happen in one of two forms, directed or undirected.
-Directed negotiation happens when one element has decided (usually
-during negotiation on another pad) to ask for a specific format on
-a pad.  This happens when a pad calls gst_pad_try_set_caps().
-Undirected negotiation happens when the core decides to negotiate
-a link, either due to a state change or a specific application
-request.
-
-Steps in undirected negotiation (core view):
-
- - core checks that both pad's parent elements are in the READY or
-   higher state.
-
- - core calls gst_pad_get_caps() on each pad, intersects the two caps,
-   and intersects again with the filter caps.  If the intersection is
-   empty, then the pads have no formats in common, and the link fails.
-
- - If the intersection caps is not fixed, there are multiple possible
-   formats that the link could use.  If this is the case, fixate
-   functions are called until the caps are fixed.  The fixate functions
-   are called by priority -- src application fixate function, sink
-   application fixate function, src and sink fixate functions, and
-   the default core fixate function.  The application fixate functions
-   are implemented by the "fixate" signal on each pad.  The core
-   loops through the fixate functions until a fixed caps is decided
-   on.
-
- - Each pad may have a pad_link function, which is called with the
-   fixed caps.  The pad_link function has the option of accepting,
-   rejecting, or delaying the negotiation.
-
- - If both pads accept the caps, the link is then negotiated.
-
-Steps in directed negotiation (gst_pad_try_set_caps):
-
- - the originator is the pad that gst_pad_try_set_caps() is called
-   on.
-
- - the elements owning both pads are assumed to be in a non-NULL state
-
- - the caps argument of try_set_caps() must be fixed.
- - gst_pad_get_caps() is called on the peer pad, and intersected with
-   the originating pad's pad template caps and the filter caps.  The
-   caps argument is checked to be a subset of the intersection.  (It's
-   important that this intersection uses the pad _template_ caps.)
-
- - Fixate functions don't need to be called, since the caps are
-   already fixed.
-
- - The peer's pad_link function is called.
-
- - If the peer's pad_link function accepts the caps, the link is then
-   negotiated.
- - If the peer's pad_link function refuses the caps, and the link had
-   already been negotiated, the peer's pad_link function is called
-   with the caps of the old negotiation.
-
- - Note: the originator's pad_link function is _not_ called.  The
-   originator must take appropriate alternative steps.
-
-
-Notes about renegotiation:
-
- - same as negotiation.  Note that get_caps() functions should always
-   ignore the currently negotiated caps of a link.
-
- - if renegotiation fails, the previous negotiation is still in effect.
-   If the renegotiation fails in the last pad_link step, the pad_link
-   functions are called with the previously negotiated caps.
-
-
-Notes for sources and sinks:
-
- - sources and sinks that talk to hardware may not be able to fully
-   describe their available formats, and thus need to rely on pad_link
-   functions to test a particular format.  FIXME: currently, the core
-   completely fails negotiation if a pad_link function refuses a caps,
-   instead of attempting with an alternate caps.
-
-   Example: Assume osssink advertises rate=(int)[8000,48000], but
-   the device cannot actually handle rate=44100 (unknown to osssink).
-   Assume that the pad_link function is called with rate=44100 --
-   ideally, the pad_link function should return GST_PAD_LINK_DELAYED,
-   and future calls to getcaps should return {[8000,44099],[44101,
-   48000]}.  I don't know how to make this easy and/or work well.
-
-
-Notes for decoders/demuxers:
-
- - Decoders will typically negotiate a sink pad, receive some data,
-   determine the output format, and call try_set_caps() with the given
-   format.  If the output format is non-fixed, gst_pad_renegotiate()
-   may be used instead, in order to have the fixate functions choose
-   the optimal format.  Note that this requires communication so that
-   the pad's getcaps function returns the correct caps.
-
-Notes for converters:
-
- - Converters change one or more properties of the format of a data
-   stream.  A typical converter's getcaps function will call
-   gst_pad_get_allowed_caps() for the opposite pad in the element,
-   change one or more fields in the caps, and return the result.
-
- - getcaps function:
-
-   - call gst_pad_get_allowed_caps() on the other pad in the element
-
-   - for each possible format ("A") in the allowed caps, determine all
-     the formats ("B") that your converter could convert the original
-     format (A) to.  The union of all these formats (all the B's) is
-     the caps that should be returned.  (This is how to do it
-     _theoretically_, but an optimal implementation will probably be 
-     quite different.)
-     For example, a simple way to do this for an element that can convert
-     a given field of the caps is to remove the field(s) from the structure,
-     then intersect with the pad template.
-
-   - As an example, videoscale can convert any sized video to any other
-     sized video.  Its getcaps function iterates over each structure in
-     the caps, and replaces the width and height with the range
-     [1,MAXINT].
- - pad_link function:
-  
-   - the "otherpad" is the opposite pad in the element.
-
-   - extract fields from the caps that are relevant for your converter
-     handling the format.  Store these in _local_ variables.  (E.g,
-     things like video size, sample rate, etc.)
-
-   - If it's possible to pass buffers through without modifying them
-     (passthrough), you should call gst_try_set_caps() with the caps
-     that was specified as the parameter to the pad_link function.  If
-     this is successful, save the local variables to the element
-     structure, perform whatever other setup is necessary for your
-     element, and return GST_PAD_LINK_OK.
-
-   - Otherwise, you're not using passthrough, and may need to
-     change the caps on the otherpad to match the given format.
-
-   - If the otherpad is not negotiated (!gst_pad_is_negotiated()),
-     you shouldn't attempt to set a format on it.  It will eventually
-     be negotiated.  Save the local variables to the element structure,
-     perform whatever other setup is necessary, and return
-     GST_PAD_LINK_OK.
-
-   - At this point, the other pad is already negotiated, but won't
-     accept the passthrough format, so you should combine the existing
-     negotiated caps on the otherpad and the caps that was the pad link
-     argument.  This can either be done using existing information in the
-     element that was saved during a previous pad_link call, or you can
-     get the information from the negotiated caps
-     (gst_pad_get_negotiated_caps()).
-
-     As an example, consider the videoscale element.  Assume that
-     videoscale.src has already negotiated "video/x-raw-yuv,
-     format=(fourcc)I420, width=320, height=240", and that the sink
-     pad's link function is called with "video/x-raw-yuv,
-     format=(fourcc)YUY2, width=640, height=480".  Since it's the
-     videoscale element, we can have different width and height
-     fields on the pads, but the format must be the same.  So we'll
-     use the existing negotiated size (640x480), and the new format,
-     and call gst_pad_try_set_caps() with "video/x-raw-yuv,
-     format=(fourcc)I420, width=640, height=480".
-
-     This may seem overkill, but most of the time, you'll end up
-     calling try_set_caps() with the same caps that are currently
-     negotiated -- try_set_caps() just returns GST_PAD_LINK_OK in
-     this case.
-
-   - If gst_pad_try_set_caps() returns GST_PAD_LINK_OK, save the
-     local variables to the element structure.  In any case, return
-     the return value of gst_pad_try_set_caps().
-
-
-Notes for filters:
-
- - Filters can almost always use gst_pad_proxy_getcaps() as the
-   getcaps function.  This just returns gst_pad_get_allowed_caps()
-   on the otherpad.
- - You may be able to use gst_pad_proxy_pad_link() as the pad link
-   function, but only if you don't need to extract parameters from
-   the caps.
-
-
-Notes for encoders/muxers:
-
- - Encoders and muxers should roughly work like converters.  Many
-   converters are symmetric; encoders and muxers obvious are not,
-   thus it may make the code clearer to have separate src and sink
-   getcaps and pad_link functions.
-
- - Encoders and muxers should handle multiple negotiations until
-   the first buffer has been passed.  After this point, it's unlikely
-   that additional negotiations will happen in well-constructed
-   pipelines, but it may be wise to "lock" the caps after the
-   muxer has committed to a format.  (FIXME: it's still unclear to
-   me when the caps should get "unlocked".  Obviously at EOS or
-   PAUSED->READY transitions.  Any others?)
-
- - Locking caps can be done by adding (near the top) of the getcaps
-   function:
-
-   if (my_element->lock_caps) {
-     return gst_pad_get_negotiated_caps (pad);
-   }
-
-
-Explicit caps:
-
- - There's a hack in the core to make the code for decoder elements
-   a lot simpler.  This hack can be used only for src pads of elements
-   that get their srcpad capabilities directly from the data stream,
-   i.e., decoders, demuxers, and typefind.  This hack overrides the
-   pad's getcaps() and pad_link() function, so that they work correctly
-   in all decoder states.
-
- - To enable this hack on a pad, call gst_pad_use_explicit_caps().
-
- - To indicate that a decoder has found the format of the stream, call
-   gst_pad_set_explicit_caps(pad,caps) with the caps of the stream.
-   This caps must be fixed.
-
- - To indicate that a decoder has lost the format of the stream, i.e.,
-   there's been a NEW_MEDIA event, call gst_pad_set_explicit_caps(pad,
-   NULL).
-
- - If the explicit caps are set, the getcaps function will return that
-   caps, and the pad_link function will return GST_PAD_LINK_OK.  If
-   the explicit caps are not set, the getcaps function returns the pad
-   template caps, and the pad_link function returns GST_PAD_LINK_DELAYED.
-
-
-
-Other junk:
-
- - negotiation can happen at any time
-
- - negotiation can happen multiple times/often happens multiple times
-
- - initial negotiation can lead to strange caps
-
- - directed negotiation can happen in either direction (src to sink or
-   sink to src)
-
- - Other considerations ignored, every pad should have a getcaps function.
-
- - If a pad's getcaps function returns the same caps in every
-   circumstance, the getcaps function can be omitted.
-   
- - If you use gst_pad_use_explicit_caps(), the getcaps function must
-   be omitted.
-
- - fixate functions are a method for applications to exert influence
-   on how a format is chosen from a caps.  It's also used as a hack to
-   allow elements to do the same.  Element fixate functions are _not_
-   intended to give good results for applications -- they're intended
-   to give non-disgusting results in gst-launch.  Don't attempt to
-   make them do more than they're capable of.
-
- - Fixate functions should not be implemented on anything except source
-   and sink elements.
-
-
-
diff --git a/docs/random/omega/EOS/chain-walkthrough b/docs/random/omega/EOS/chain-walkthrough
deleted file mode 100644 (file)
index b4c28bf..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-disksrc -> mp3parse -> mpg123 -> audiosink
-
-disksrc reads last 4K chunk from disk.  Sets EOS on the buffer, pushes buffer out to peer.
-disksrc:src sets itself to EOS and chains to mp3parse.
-
- mp3parse takes the buffer and slices it up into several.
- Each buffer gets chained off to mpg123.
-
-  mpg123 decoders each frame and sends it to audiosink.
-
-   audiosink dumps the audio data to the sound card.
-
-  mpg123 returns from the chain, and returns.
-
- mp3parse returns from each of the several chains,a nd returns.
-
-disksrc:src returns from the chain, signals EOS, and sets disksrc's EOS flag
-
-At this point the pipeline state code takes over and starts to set everyone to READY
diff --git a/docs/random/omega/IDEAS b/docs/random/omega/IDEAS
deleted file mode 100644 (file)
index ef79da4..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-Plugin Registry:
-Have a web-accessible database of plugins from everywhere, including their merit values.  gstplugin.c
-and the autoplug code (should we abstract out autoplug into a special file?  I think so) can make use of
-this database via another module (gstwebregistry.c?) to look up stuff.  A copy of the registry (gzip'd
-XML) could even be cached.  System and user options would determine whether this registry is checked
-and/or updated automatically.  The registry could simply be merged with the local machine and user
-registries, with the state bit set to "don't even have it".  Autodownload/install code should be
-provided, though designed such that it's not toolkit/OS specific.
-
-Merit:
-Plugins and even type definition should carry merit values, allowing the system to determine which
-plugin or type definition is better.  This can be tied into the web registry setup, where merit values
-can be updated without requiring an update of the plugins themselves.  They can also be guaranteed
-unique if there's a range reserved for registered objects.  Unfortunately, that might get us into some
-political wars.  We could leave that up to the users via some voting system.
-
-Scheduling state:
-All the scheduling info for a Bin should be contained in a single object of some form.  This can be
-saved off and restored seamlessly at some point in the future.  This would be ideal for some autoplug
-cases, where the rest of the pipeline simply ceases to exist temporarily, and scheduling entry points
-may need to be modified until the autoplug stage is finished.
diff --git a/docs/random/omega/TODO-0.1.0 b/docs/random/omega/TODO-0.1.0
deleted file mode 100644 (file)
index f07798a..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-mandatory:
------------
-
-(done) Fix compile warnings in gst/* 
-
-Make sure all common media types work with autoplug and gstmediaplay
-
-Add interface to control the level of output, both compile- and run-time
-
-(done) Make sure the build is capable of being run without any debugging noise
-
-Make sure that the absence of any of the optional libraries will not be fatal
-
-Make sure all the old plugins don't build normally, via some configure option?
-
-Try to get more of the INFO calls worked out, removing gst_info
-
-Decide whether DEBUG should use the category system, and if so, implement it
-
-Icon for gstplay, .desktop file, etc.
-
-Build tarballs
-
-Build RPMs
-
-Figure out which docs we're going to make 'offical'
-
-UPDATE THE WEB SITE
-
-optional:
----------
-
-Fix gstreamer-launch to do named pads
-
-Need to fix EOS subsystem so -launch can play out
-
-gstreamer-launch should play out till EOS
-
-Finish LADSPA plugin to data-moving stage
-
-
-
-things to remember for the announcement:
----------------------------------------
-
-Build requirements list:
-libtool 1.3.5 or patched to "pass_all"
-optional:
-libcdparanoia
-libmp3lame
-libxaudio
-libXv
-libgdk-pixbuf
-libglade
diff --git a/docs/random/omega/TYPE_FOURCC b/docs/random/omega/TYPE_FOURCC
deleted file mode 100644 (file)
index dff7d7d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#define GST_TYPE_FOURCC(f) \
-(((f)[0]) & ((f)[1] << 8) & ((f)[2] << 16) & ((f)[3] << 24))
-
diff --git a/docs/random/omega/build/TODO b/docs/random/omega/build/TODO
deleted file mode 100644 (file)
index fe0e5be..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-Convert all the STREAMER_ version stuff to GSTREAMER_
-
-Convert all the --version-info lines to use GSTREAMER_LIBVERSION
-
-Fix all the masses of Makefile.am's that override CFLAGS
-
-Makefile.am's should use the library_la_CFLAGS and _LIBADD always
diff --git a/docs/random/omega/caps2 b/docs/random/omega/caps2
deleted file mode 100644 (file)
index 6264781..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-The elementfactory for a given element will contain some information about the capabilities of element's
-pads or potential pads.  An indication will be provided as to whether the pad always exists, always
-exists once data is present, or *might* exist once data is present (the latter case is for things like
-the MPEG system parsers, where an audio stream might or might not exist).
-
-
-First, an entirely normal example:
-----------------------------------
-
-(-----------)        (----------)        (-------------)
-! disksrc   !        ! mpg123   !        ! audiosink   !
-!         src        sink     src        sink          !
-!           !        !          !        !             !
-(-----------)        (----------)        (-------------)
-
-We start with only the disksrc.  The typefind filter is attached to the disksrc, and via typefind magic
-the properties of the disksrc are found to be:
-
-  disksrc->src->caps = {
-    "audio/mp3",
-    "layer",   GST_CAPS_INT (3),
-    "bitrate", GST_CAPS_INT (128),
-    NULL
-  };
-
-A look through the plugin registry shows that we have an element called mpg123 that has the following
-caps:
-
-  static GstCapsFactory mpg123_sink_caps = {
-    "audio/mp3",
-    "layer",   GST_CAPS_INT_RANGE (1, 3),
-    "bitrate", GST_CAPS_INT_RANGE (8, 320),
-    NULL
-  };
-
-The caps of the disksrc fit within those parameters, so we instantiate an mpg123 and attach it to the
-disksrc.  The connection succeeds negotiation and as a result the mpg123 specifies its output caps as:
-
-  mpg123->src->caps = {
-    "audio/raw",
-    "format",   GST_CAPS_BITFIELD (S16),
-    "depth",    GST_CAPS_INT (16),
-    "rate",     GST_CAPS_INT (44100),
-    "channels", GST_CAPS_INT (2),
-    NULL
-  };
-
-Again from the plugin registry we find an element audiosink that has appropriate caps:
-
-  static GstCapsFactory audiosink_src_caps = {
-    "audio/raw",
-    "format",   GST_CAPS_BITFIELD (S16,....),
-    "depth",    GST_CAPS_INT (16),
-    "rate",     GST_CAPS_INT_RANGE (4000, 96000),
-    "channels", GST_CAPS_INT_RANGE (1, 2),
-    NULL
-  };
-
-A copy of the audiosink is instantiated and attached, negotiation goes smoothly, and we're done.  No
-dataflow has occurred, no failure found, etc.  An ideal autoplug.
-
-
-Now, a slightly more convoluted example:
-----------------------------------------
-
-Start with the same graph:
-
-(-----------)        (----------)        (-------------)
-! disksrc   !        ! mpg123   !        ! audiosink   !
-!         src        sink     src        sink          !
-!           !        !          !        !             !
-(-----------)        (----------)        (-------------)
-
-Run typefind on the disksrc's output, get the same output caps:
-
-  disksrc->src->caps = {
-    "audio/mp3",
-    "layer",   GST_CAPS_INT (3),
-    "bitrate", GST_CAPS_INT (128),
-    NULL
-  };
-
-Find and attach mpg123, get the following output caps this time:
-
-  mpg123->src->caps = {
-    "audio/raw",
-    "format",   GST_CAPS_BITFIELD (S16),
-    "depth",    GST_CAPS_INT (16),
-    "rate",     GST_CAPS_INT (44100),
-    "channels", GST_CAPS_INT (1),
-    NULL
-  };
-
-Note that this time we have a mono output.  A look into the audiosink caps shows that we have a match.
-So we instantiate a copy.  Oops.  We now find that the caps for the input pad on our audiosink have
-changed:
-
-  mpg123->src->caps = {
-    "audio/raw",
-    "format",   GST_CAPS_BITFIELD (S16,...),
-    "depth",    GST_CAPS_INT (16),
-    "rate",     GST_CAPS_INT (11025, 48000),
-    "channels", GST_CAPS_INT (2),
-    NULL
-  };
-
-Whoops.  It seems that the sound card we've got in this machine (FIXME how on earth to deal with
-multiple sound cards???) doesn't support mono output *at all*.  This is a problem.  We now find that we
-have no options as far as directly matching the mpg123 to the audiosink.
-
-A look through our (fictitious) plugin registry shows at least one element that at least has audio/raw
-on both input and output (since both mpg123 and audiosink have open pads with this mime type).  A closerlook shows that its caps are:
-
-  static GstCapsFactory mono2stereo_sink_caps = {
-    "audio/raw",
-    "channels", GST_CAPS_INT (1),
-    NULL
-  };
-  static GstCapsFactory mono2stereo_src_caps = {
-    "audio/raw",
-    "channels", GST_CAPS_INT (2),
-    NULL
-  };
-
-Wow, that's a perfect match.  Instantiate, attach to mpg123, no problems.  Attach to audiosink, no
-problems.  Done.  When we start up the pipeline, we should get absolutely no callbacks from pads saying
-"help me, I've fallen and..., er, I don't like this buffer!".
-
-
-A really messy case:
---------------------
-
-Start with a disksrc, typefind it, get the following:
-
-  disksrc->src->caps = {
-    "audio/mp3",
-    "layer",   GST_CAPS_INT (3),
-    "bitrate", GST_CAPS_INT (128),
-    NULL
-  };
-
-Look through the plugin registry, find mpg123.  Instantiate it, attach it.  It spits out audio
-parameters as usual:
-
-  mpg123->src->caps = {
-    "audio/raw",
-    "format",   GST_CAPS_BITFIELD (S16),
-    "depth",    GST_CAPS_INT (16),
-    "rate",     GST_CAPS_INT (44100),
-    "channels", GST_CAPS_INT (2),
-    NULL
-  };
-
-Now we instantiate an audiosink plugin.  This time, we're sunk:
-
-  mpg123->src->caps = {
-    "audio/raw",
-    "format",   GST_CAPS_BITFIELD (S8,U8),
-    "depth",    GST_CAPS_INT (8),
-    "rate",     GST_CAPS_INT_RANGE (11025, 22050),
-    "channels", GST_CAPS_INT (1),
-    NULL
-  };
-
-ACK!  It's one of those Disney Sound Source things.  We've got a problem here that isn't obviously
-solvable.  However, there happens to be another mp3 decoder sitting around.  It's got the same
-properties as mpg123, but a lower merit value.  Let's instantiate one and attach it.  We get the
-following output pad caps:
-
-  mp3decoder->src->caps = {
-    "audio/raw",
-    "format",   GST_CAPS_BITFIELD (S8,S16),
-    "depth",    GST_CAPS_INT_RANGE (8,16),
-    "rate",     GST_CAPS_INT_RANGE (8000, 44100),
-    "channels", GST_CAPS_INT (1,2),
-    NULL
-  };
-
-Well, that matches the audiosink.  We try attaching it, and during negotiation the mp3decoder finds
-sufficient common ground with the castrated audiosink and sets its output pad to match the best of the
-options: S8 at 22050 KHz.
-
-
-
-Next to impossible scenario: DVD
---------------------------------
-
-Start with a dvdsrc.  It's output pad caps are:
-
-  static GstCapsFactory dvdsrc_src_caps = {
-    "video/mpeg",
-    "mpegversion",  GST_CAPS_INT (2),
-    "systemstream", GST_CAPS_BOOLEAN (TRUE),
-    NULL
-  };
-
-The type would be classified as incomplete via some mechanism.  This might cause the autoplug code to go
-and run the typefind function.  It would flesh the type out to the following:
-
-  dvdsrc->src->caps = {
-    "video/mpeg",
-    "mpegversion",  GST_CAPS_INT (2),
-    "systemstream", GST_CAPS_BOOLEAN (TRUE),
-    "videostreams", GST_CAPS_INT (1),
-    "audiostreams", GST_CAPS_INT (3),
-    "bitrate",      GST_CAPS_INT (40960),
-    NULL,
-  };
-
-Wow, that helped a lot.  A check through the plugin registry shows that the mpeg2parse will match those
-properties:
-
-  static GstCapsFactory mpeg2parse_sink_caps = {
-    "video/mpeg",
-    "mpegversion",  GST_CAPS_INT (2),
-    "systemstream", GST_CAPS_BOOLEAN (TRUE),
-    NULL
-  };
-
-(In retrospect, it may not be necessary to run typefind if there's match this good right away.  Only run
-typefind when there's no exact match.)
-Since there are no output pads yet, we have to actually push data through the pipeline.  The moment a
-buffer or two get to the mpeg2parse element, it promptly goes and creates an output pad, probably of the
-following caps:
-
-  mpeg2parse_video_src_caps = {
-    "video/mpeg",
-    "mpegversion",  GST_CAPS_RANGE (1,2),
-    "systemstream", GST_CAPS_BOOLEAN (FALSE),
-    NULL
-  };
-
-This seems to be a task for typefind again.  But since data is flowing, we have to be careful with the
-buffers.  (This is the case in any typefind maneuver, but more so when one really can't rewind the
-source without consequences)  The autoplug system attaches a special pseudo-element to mpeg2parse's new
-output pad, and attaches the typefind element to the end of that.  The pseudo-element takes the buffer,
-stores it, and passes a copy off to the attached element, in this case typefind.  This repeats until
-typefind has determined the type, at which point the typefind is removed, and the newly found element is
-attached instead.
-
-The pseudo-element is 'rewound' and the stored buffers flow out and into the newly attached element.
-When the cache of buffers is gone, a signal fires and the autoplug system removes the pseudo-element and
-reconnects the pipeline.
-
-In this case, the typefind function will find the following:
-
-  mpeg2parse_video_src_caps = {
-    "video/mpeg",
-    "mpegversion",  GST_CAPS_INT (2),
-    "systemstream", GST_CAPS_BOOLEAN (FALSE),
-    "bitrate",      GST_CAPS_INT (36864),
-    "width",        GST_CAPS_INT (720),
-    "height",       GST_CAPS_INT (480),
-    "framerate",    GST_CAPS_FLOAT (29.97002997),
-    "chromaformat", GST_CAPS_INT (1),          [GST_CAPS_STRING ("4:2:0") ?]
-    NULL
-  };
-
-Back to the plugin registry, we find our only choice is mpeg2dec, which has input caps of:
-
-  static GstCapsFactory mpeg2dec_sink_caps = {
-    "video/mpeg",
-    "mpegversion",  GST_CAPS_RANGE (1,2),
-    "systemstream", GST_CAPS_BOOLEAN (FALSE),
-    NULL
-  };
-
-Once again it just so happens that we really didn't need to do the typefind at all.  But it can't hurt
-unless the typefind is slow and painful, which we can guess won't be the case since the choices are
-rather limited by the fact that there's already a MIME type attached, meaning we can drastically reduce
-the number of typefind functions we try (down to one, actually).
-
-However, since we *have* run the typefind, upon attachment of the input pad of mpeg2dec, the output pad
-looks like the following:
-
-  mpeg2dec_src_caps = {
-    "video/raw",
-    "fourcc",    GST_CAPS_LIST (
-                       GST_CAPS_FOURCC ("YV12"),       [identical...]
-                       GST_CAPS_FOURCC ("IYUV"),
-                       GST_CAPS_FOURCC ("I420"),
-                 ),
-    "width",     GST_CAPS_INT (720),
-    "height",    GST_CAPS_INT (480),
-    "framerate", GST_CAPS_FLOAT (29.97002997),
-    NULL
-  };
-
-Currently only videosink supports the output of video/raw.  It claims a list of FOURCCs but nothing
-more:
-
-  static GstCapsFactory videosink_sink_caps = {
-    "video/raw",
-    "fourcc", GST_CAP_LIST ( GST_CAPS_FOURCC ("YV12"),
-               GST_CAPS_FOURCC ("IYUV"), GST_CAPS_FOURCC ("I420"),
-               GST_CAPS_FOURCC ("YUY2"), GST_CAPS_FOURCC ("UYVY"),
-               [ etc... ],
-              ),
-    NULL
-  };
-
-When instantiated, we potentially have the same problem as with the audiosink: we don't necessarily know
-which hardware output to use.  Somehow we have to solve the problem of setting some element arguments
-before we can get useful information out of them as to the properties.  In this case anyway, if the
-videosink were to find only one output possibility, it would trim the list of FOURCCs it can deal with
-to what the hardware can handle, as well as add further properties:
-
-  videosink_sink_caps = {
-    "video/raw",
-    "fourcc", GST_CAPS_LIST (GST_CAPS_FOURCC ("YV12"),
-                       GST_CAPS_FOURCC ("YUY2"),
-              ),
-    "width",  GST_CAPS_INT_RANGE (4,1020),
-    "height", GST_CAPS_INT_RANGE (4,1020),
-    NULL
-  };
-
-We can now connect the mpeg2dec output to the videosink, and we now have displaying video.
-
-. . . .
diff --git a/docs/random/omega/caps3 b/docs/random/omega/caps3
deleted file mode 100644 (file)
index 11dcf8c..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
- /* fake mp3 where bitrates 8 through 32 can't be stereo */
-static GstCapsListFactory mpg123_sink_caps = {
-  {
-    "audio/mp3",
-    "layer",    GST_CAPS_INT_RANGE (1, 3),
-    "bitrate",  GST_CAPS_INT_RANGE (32, 320),
-    "channels", GST_CAPS_INT_RANGE (1, 2),
-    "framed",   GST_CAPS_BOOLEAN (TRUE),
-    NULL
-  },
-  {
-    "audio/mp3",
-    "layer",    GST_CAPS_INT_RANGE (1, 3),
-    "bitrate",  GST_CAPS_INT_RANGE (8, 32),
-    "channels", GST_CAPS_INT_RANGE (1),
-    "framed",   GST_CAPS_BOOLEAN (TRUE),
-    NULL
-  },
-  NULL
-};
diff --git a/docs/random/omega/debug-commit b/docs/random/omega/debug-commit
deleted file mode 100644 (file)
index b1b4589..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-Changes made to the DEBUG system.  New header file gstdebug.h holds the stuff to keep it out of gst.h's
-hair.  DEBUG prints out the process id, cothread id, source filename and line number.  Two new macros
-DEBUG_ENTER and DEBUG_LEAVE are used to show the entry and exit of a given function.  This eventually
-might be used to construct call trace graphs, even taking cothreads into account.  This would be quite
-useful in visualizing the scheduling mechanism.
-
-Minor changes to various debug messages.
-
-Also sitting in gstdebug.h is a prototypical DEBUG_ENTER that's capable of performing DEBUG_LEAVE
-automatically.  It does this by utilizing a little-known GCC extension that allows one to call a
-function with the same parameters as the current function.  The macro uses this to basically call
-itself.  A boolean is used to ensure that when it calls itself it actually runs the body of the
-function.  In the meantime it prints stuff out before and after the real function, as well as
-constructing a debugging string.  This can be used eventually to provide call-wide data on the DEBUG
-lines, instead of having to replicate data on each call to DEBUG.  More research is needed into how this
-would most cleanly be fit into some other chunk of code, like GStreamer (I think of this DEBUG trick as
-a separate project, sorta).
-
-Unfortunately, the aforementioned DEBUG trick interacts quite poorly with cothreads.  Almost any time
-it's used in a function that has anything remotely to do with a cothread context (as in, it runs in
-one), a segfault results from the __builtin_apply call, which is the heart of the whole thing.  If
-someone who really knows assembly could analyze the resulting code to see what's really going on, we
-might find a way to fix either the macro or the cothreads (I'm thinking that there's something we missed
-in constructing the cothreads themselves) so this works in all cases.
-
-In the meantime, please insert both DEBUG_ENTER and DEBUG_LEAVE in your functions.  Be sure to put
-DEBUG_ENTER after your variable declarations and before any functional code, not to put the function
-name in any DEBUG strings (it's already there, trust me), and put a DEBUG_LEAVE if you care enough.
-
-Changes are going to happen in the way DEBUGs and other printouts occur, so stay tuned.
diff --git a/docs/random/omega/eos.old b/docs/random/omega/eos.old
deleted file mode 100644 (file)
index 8621d67..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-OUTDATED
---------
-
-
-What I propose for EOS condition is th following:  As is stands, EOS is a
-flag in a buffer.  However, it's also a signal from an element, which is
-odd. What I propose is that EOS become a pad thing.  Here's how it would
-work:
-
-When a source has a final buffer, it marks it as EOS.  It passes this on
-through the pad, and the pads set a 'pending' EOS state on the way
-through.  When another push or pull happens, only then does the pad signal
-EOS.  This means that EOS doesn't happen until the buffer has passed all
-the way to the end, and a request for another buffer is starting to work
-its way back.  It gets stopped almost immediately.
-
-This gets a bit messy in complex cases, haven't thought them all out.
-Assuming everything is reasonably symmetric, it should work out cleanly.
-We may have to add the ability to force buffers to pass even post EOS, but
-that sounds like a hack.
-
-
-
-Example: DVD
-============
-
-
-                                              ------------     |-------|
-                                             -| mpeg2dec |-----|       |
-             ------------------------       / ------------     |       |
-             |                video0|------/ -------------     |       |       -------------
-             |                      |       -| subtitle0 |-----| merge |-------| videosink |
-             |             subtitle0|------/ -------------     |       |       -------------
-----------   |                      |        -------------     |       |
-| dvdsrc |---| mpeg2parse  subtitle1|--------| subtitle1 |-----|       |
-----------   |                      |        -------------     |-------|
-             |                audio0|--------\ -----------     |----------|
-             |                      |         -| ac3dec0 |-----|          |
-             |                audio1|-------\  -----------     |          |    -------------
-             ------------------------        \ -----------     | switcher |----| audiosink |
-                                              -| ac3dec1 |-----|          |    -------------
-                                               -----------     |----------|
-
-When dvdsrc reads its last buffer, it sets EOS on the buffer and passes it.  The pad (probably audio1,
-since video and audio are interleaved and subtitles don't usually end up at the end of a movie) would
-set EOS pending, and pass it to mpeg2dec which would pass the EOS to the merge.  Merge would then ask
-for a buffer from subtitle1, since that's the one we're showing subtitles on right now.  It would then
-pull from the mpeg2parse.  This would cause a switch back the parser, who's next task is to go and set
-all the output pads to EOS.  It may have to accomplish this by sending a zero-byte buffer.
-
-Well, this example isn't actually very good.  I'll go ahead and implement it, and we can see what
-happens.  The current setup is so lacking that anything is better....
diff --git a/docs/random/omega/filterfactory b/docs/random/omega/filterfactory
deleted file mode 100644 (file)
index 9936306..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-A very useful feature would be a FilterFactory, i.e. some system whereby filter writers can avoid
-getting their hands messy with the details of building and operating a G[tk]Object.  A couple of
-structures and a couple of functions should do it.
diff --git a/docs/random/omega/output_policies b/docs/random/omega/output_policies
deleted file mode 100644 (file)
index 81dfc80..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-GStreamer polices for various forms of library output, including error cases.
-
-
-g_return_...
-============
-The parameters of a function are checked for validity (non-NULL, correct type, etc.) with g_return[_val]_if_fail, i.e.:
-
-gst_element_connect (GstElement *src, gchar *srcpadname,
-                     GstElement *dest, gchar *destpadname) {
-  g_return_if_fail (src != NULL);
-  g_return_if_fail (GST_IS_ELEMENT(src));
-  g_return_if_fail (srcpadname != NULL);
-  g_return_if_fail (dest != NULL);
-  g_return_if_fail (GST_IS_ELEMENT(dest));
-  g_return_if_fail (destpadname != NULL);
-
-This will inform the user of the library of any basic problems with the arguments they pass, such as a NULL pointer.
-
-
-ERROR
-=====
-The ERROR macro will be used whenever there is some other type of flaw in the data passed, at a GStreamer-specific 
-level:
-
-  srcpad = gst_element_get_pad (src, srcpadname);
-  if (srcpad == NULL) {
-    ERROR(src,"source element has no pad \"%s\"",srcpadname);
-    return;
-  }
-
-An ERROR will generally cause ceasation of the application, and ideally launch gdb.
-
-
-INFO
-====
-The INFO macro will be used to output any interesting state from the library, such as plugin loading and various events 
-of interest.  They will be separated into categories that can be individually enabled and disabled.
-
-Categories (first draft of list, unordered):
-
-cothreads                      [cothreads.c]
-gst initialization             [gst.c]
-autoplug results               [autoplug.c]
-autoplug attempts              [autoplug.c]
-bin parentage issues           [gstbin.c]
-plan generation                        [gstbin.c]
-schedule generation            [gstschedule.c]
-schedule implementation                [gstpad.c, gstbin.c, etc.]
-buffer operations              [gstbuffer.h]
-caps matching                  [gstcaps.c]
-clock stuff                    [gstclock.c]
-element pad operations         [gstelement.c]
-elementfactory operations      [gstelementfactory.c]
-pad creation/connection                [gstpad.c]
-pipeline stuff                 [gstpipeline.c]
-plugin loading                 [gstplugin.c]
-plugin loading errors          [gstplugin.c]
-properties operations          [gstprops.c]
-thread creation/management     [gstthread.c]
-type operations                        [gsttype.c]
-XML load/save                  [gstxml.c]
diff --git a/docs/random/omega/pad-negotiation b/docs/random/omega/pad-negotiation
deleted file mode 100644 (file)
index 6c12468..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-OUTDATED, EARLY IDEA
---------------------
-
-When two pads are connected, a negotiation phase is going to have to
-happen.  Ideally, the caps of the two pads will both be fully-specified,
-and match.  That's the ideal case, but may rarely happen in practice.
-
-It'll work the following way:
-
-1) gst_pad_connect(pad1,pad2) is called by something
-2) pad1's negotiate() method is called, with pad2 as argument
-3) negotiate() repeatedly calls pad2's set_caps() method
-
-At some point, the two pads will agree on a set of caps, and proceed by
-returning TRUE from negotiate(), at which point gst_pad_connect()
-finishes.  If it returns FALSE, gst_pad_connect() is forced to fail.
-
-Now, obviously the algorithm used to find matching caps can get
-complicated.  But in some cases it'll be simple.  Ideally, if there is no
-negotiate() function for pad1, there'll be a function that will go through
-the options and try to make pad1 and pad2 meet in the middle, with no
-specific knowledge of what the caps actually mean.
-
-Another detail is deciding which pads are pad1 and pad2.  In the autoplug
-case, the code will sometimes know which of the pads have the more
-specific caps.  In others, you may not.  Either you can guess, and
-possibly lose to having the slower of the two pad's negotiate() methods do
-the work, or you might be able to actually guess at which is the most
-specific set of caps:
-
-For any given typeid in the union of both pads, look at all properties
-  For each property, find the smallest range, assign this a 1.0
-    For all other instances of this property, assign relative to 1.0
-For each pad1,pad2
-  Take the assigned value of every property, and multiply together
-
-Whichever value is lower between pad1 and pad2 is most likely to be the
-most specific set of caps.  The trick is implementing the above
-efficiently, but on the surface there appear to be more than enough
-potential optimizations.
diff --git a/docs/random/omega/padtemplates b/docs/random/omega/padtemplates
deleted file mode 100644 (file)
index 6b3ce4c..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-OUTDATED
---------
-
-typedef gpointer GstCapsFactoryEntry;
-typedef GstCapsFactoryEntry GstCapsFactory[];
-typedef GstCapsFactory *GstCapsListFactory[];
-
-typedef gpointer GstPadFactoryEntry;
-typedef GstPadFactoryEntry GstPadFactory[];
-typedef GstPadFactory *GstPadListFactory[];
-
-#define GST_PADFACTORY_SRC     GINT_TO_POINTER (GST_PAD_SRC)
-#define GST_PADFACTORY_ALWAYS  GINT_TO_POINTER (GST_PAD_ALWAYS)
-
-typedef struct GstPadTemplate {
-  gchar *name_template;
-  gint direction;
-  gint presence;
-  GList *caps;
-};
-
-GstPadFactory mpg123_src_padfactory = {
-  "src"
-  GST_PADFACTORY_SRC,
-  GST_PADFACTORY_ALWAYS,
-
-  "audio/raw"
-  "samplerate", GST_PROPS_INT (44100),
-  . . .
-  NULL
-};
-
-static GstPadTemplate *srcpadtemplate;
-
-mpg123_new(GstMpg123 *mpg123) {
-  mpg123->srcpad = gst_pad_new_template("src", srcpadtemplate);
-  . . .
-}
-
-plugin_init() {
-  GstElementFactory *factory;
-
-  factory = gst_elementfactory_new("mpg123",. . .);
-  srcpadtemplate = gst_padfactory_new(mpg123_src_padfactory);
-  get_elementfactory_add_padtemplate (srcpadtemplate);
-}
diff --git a/docs/random/omega/plan-generation b/docs/random/omega/plan-generation
deleted file mode 100644 (file)
index afc9e07..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-OUTDATED
---------
-
-Plan generation happens at transition from NULL to READY (and PLAYING to READY right now, need to fix
-that).  By way of some logic in gst_bin_change_state(), gst_bin_create_plan() is only called for the
-outer Bin, usually a Pipeline.  This keeps things from getting nasty later on.
-
-A major new concept in plan generation is that of the 'manager'.  This is the element that is responsible
-for running a given element.  In general, Pipelines and Threads are the only managing-capable elements
-(have the MANAGER flag set), since they are the only ones with real scheduling authority (because they
-have a process context to play with, basically).
-
-gst_bin_set_manager() is called to set the manager element of the bin and all it's children and their
-children.  However, there's one important trick: it won't recurse into child Bins that have the MANAGER
-flag set.  This avoids some highly redundant recursion.
-
-When create_plan() is called on the outside Pipeline, the first thing it does is call
-set_manager(self,self).  As noted above, this recursion will not proceed into child Bins that have the
-MANAGER flag set.
-
-The next step is to recursively generate the plan (yes, head-recursive).  This gives child Bins the
-opportunity to generate their plan first, causing a inside-to-outside sequence.  This matches the way
-the scheduling is arranged now, where the plan for a Src/Connection outside a Bin is handled by that
-Bin, not it's parent.  But we must be very careful not to stomp on that plan in the parent Bin.
-
-Because create_plan() is called on all Bins, but we can only set up scheduling state in MANAGER bins,
-create_plan() must perform create_plan() recursion, but not do anything else *unless* the MANAGER bit is
-set.  It shouldn't even call set_manager() unless it's a MANAGER itself, because calling it otherwise
-would waste time doing the work again.  Basically, from the standpoing of setting the manager,
-create_plan() recursion starts it when the current Bin is a MANAGER, and set_manager() stops when it
-finds the next one.  create_plan()'s further recursion eventually starts the process back up again
-furtuer down the hierarchy, until everything is covered.
-
-For all MANAGER Bins, the last step is to actually create the scheduling plan.  This is still one of the
-nastiest chunks of code in the whole project, and probably will do nothing but get worse from now on (it
-got better recently, but only because I took a chainsaw to the code and broke everything...).  It will
-remain similar to what it is now, but with some definite differences.
-
-First task is now to find all the elements that we're responsible for.  This is normally a recursive
-process, because the structure is an arbitrary tree.  However, something like the following should work 
-(bin is self):
-
-  GSList *elements = NULL;
-  GList *children;
-  GSList *waiting_bins = NULL;
-  GstBin *waiting_bin;
-
-  waiting_bins = g_slist_prepend (waiting_bins,bin);
-
-  while (waiting_bins) {
-    // retrieve the top of the stack and pop it
-    waiting_bin = GST_BIN (waiting_bins->data);
-    waiting_bins = g_slist_remove (waiting_bins,waiting_bin);
-
-    // walk the list of elements, and find bins
-    children = waiting_bin->children;
-    while (children) {
-      // add it to the list of elements
-      elements = g_slist_prepend (elements, children->data);
-
-      // if it's a bin and it's not a managing bin,
-      // shove it on the list of bins to recurse into
-      if (GST_IS_BIN (children->data) && 
-          !GST_FLAG_IS_SET (GST_ELEMENT (children->data)))
-        waiting_bins = g_slist_prepend (waiting_bins,children->data);
-
-      children = g_list_next (children);
-    }
-  }
-
-The code makes the assumption that the manager of every element is the same until such time as a
-different managing parent appears in the hierarchy.  This is the result of the aforementioned nested
-recursion of create_plan() and set_manager(), but may not remain the case forever.  The above loop
-should probably be slightly re-written to work solely on whether or not the Bin in question is the
-element's manager.  This means that the child Bins are *always* recursed into, in case there's a rogue
-element inside of one of them that's supposed to be managed.
-
-At the same time all the elements managed by this bin are found (i.e. in the inner loop), we can
-determine some useful bits of information, such as testing for several cases that require the use of
-cothreads.  The availability of manager information at this point may aid significantly in this
-decision.
-
-Finally, the scheduling plan is generated, based on all the elements to be managed by the Bin (the list
-of which may span several 'generations' of Bins and elements).  Elements which have peers in child
-self-managed Bins are left alone on for the pad in that makes that connection.  This should keep the
-parent Bins from stepping all over state set up by the child Bins, by establishing clear implicit
-ownership on the pad level, based on the managing Bins' relationship to the pad.
diff --git a/docs/random/omega/sched-case b/docs/random/omega/sched-case
deleted file mode 100644 (file)
index f5ebd2d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-Case 1:
-
-
----------------------------------------------------
-| pipeline                                        |
-| ---------------                ---------------- |
-| | bin         |                | thread       | |
-| | ----------- |  ------------  | ------------ | |
-| | | fakesrc | |  | queue    |  | | fakesink | | |
-| | |     src>|-|--|<sink src>|--|-|<sink     | | |
-| | ----------- |  ------------  | ------------ | |
-| ---------------                ---------------- |
----------------------------------------------------
-
-Pipeline manages: fakesrc, queue
-Thread manages: fakesink
-Both forced to use cothreads.
-
-First thing the thread does is try to pull from the queue.  Because it's a chain function, it runs in
-_chain_wrapper, which calls gst_pad_pull().
diff --git a/docs/random/omega/sched-commit1 b/docs/random/omega/sched-commit1
deleted file mode 100644 (file)
index 4170674..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-STATUS: pushregion/pullregion is gone
--------------------------------------
-
-Changed the way things are scheduled, especially sources.  A Src used to
-have a push() function, and optionally a pushregion() to deal with async
-reads, etc.  That whole thing has gone away, in favor of providing a
-pull() function for the output (Src) pad instead, ala chain functions.  
-This makes constructing cothreaded schedules out of non-loop elements
-somewhat easier.  Basically there was always a question as to which pad
-was being dealt with.  In the pullregion case, cothread-specific data was
-used to try to pass the region struct to the right place, which is a slow
-hack.  And in general, the push function severely limited the kind of
-tricks that could be played when there's more than one output pad, such as
-a multi-out file reader with async capabilities on each pad independently.
-
-This changes the way cothread scheduling occurs.  Instead of the hack to
-deal with Src's by calling their push() function (or optionally the
-pushregion(), in certain cases), we now are working towards a general
-mechanism where pads are the only thing that are dealt with directly.
-
-An optimization was made in the process of doing this: the loopfunction
-actually run as the outer [stack] frame of the cothread is now set more
-intelligently in create_plan() based on what kind of element it is.  We
-now have:
-
-loopfunc_wrapper: used for loop-based elements, it simply calls the
-       loopfunc in a loop, paying attention to COTHREAD_STOPPING (see
-       below).  It currently does other, soon to be deprecated, stuff.
-
-pullsrc_wrapper: wraps a Src that's not loop-based (since your options
-       are now loop- or pull-based)
-
-There will be a couple more to deal with other cases, such as Connections
-and chain-based elements.  The general idea is that it's a lot more
-efficient to make the decisions once in create_plan than to keep doing
-this huge if/else chain in the wrapper.  Just choose the right wrapper up
-front.  It'll be most apparent performance-wise in the case of whichever
-element context is switched to first for each iteration, since the whole
-wrapper setup is done for every iteration.
-
-The tricky part is that there is now a bit of overloading of the function
-pointers in a pad.  The current meanings (possibly to change a bit more
-soon) are:
-
-chainfunc: as always, chainfunc pointer is mirrored between peer pads
-           (this may change, and the chain func may end up in pushfunc)
-pushfunc: SrcPad: gst_pad_pushfunc_proxy, cothread_switch to peer
-          SinkPad: none (may take over chainfunc, see below) pullfunc:
-SrcPad: Src or Connection's function to construct buffers
-          SinkPad: gst_pad_pullfunc_proxy, cothread_switch to peer
-
-There are a number of issues remaining with the scheduling, not the least
-of which is the fact that Connections are still dealt with the old way,
-with _push() functions and such.  I'm trying to figure out a way to unify
-the system so it makes sense.  Following the scheduling system is hard
-enough, trying to change it is murder.
-
-
-Another useful scheduling addition, mentioned above, is COTHREAD_STOPPING.  
-It's an element flag that's used to signal whatever code is running in
-cothread context that it should be finishing up and exiting soon.  An
-example of this is in plugins/cobin/spindentity.c.  All the loops should
-now be composed of do/while loops, rather than while(1) loops:
-
-  do {
-    buf = gst_pad_pull(spindentity->sinkpad);
-    gst_pad_push(spindentity->srcpad,buf);
-  } while (!GST_ELEMENT_IS_COTHREAD_STOPPING(element));
-
-The reason for this is that COTHREAD_STOPPING may be set before the above
-loop ever gets started.  It wouldn't do for the body of the loop to never
-once get called, that would simply stall the pipeline. Note that only the
-core library code is ever responsible for setting and unsetting this flag.  
-All elements have to do is respond to it by cleanly exiting the loop and
-the function holding it.
-
-This is needed primarily to allow iterations to occur properly.  
-Basically, there's a single entry point in the cothread scheduling loop,
-gst_bin_iterate_func() simply switches to this cothread.  If the element
-in this context is allowed to loop infinitely, nothing would even switch
-back to the context from which the iterate() was originally called.  This
-is a bit of a problem.  The solution is for there to be an implicit switch
-back to the originating context.  Now, even I'm not sure exactly how this
-works, but if the cothread that's switched to actually returns, execution
-returns back to the calling context, i.e. iterate_func().
-
-COTHREAD_STOPPING is therefore set just before switching into this
-(currently randomly chosen) context, on the assumption that it will return
-promptly after finishing its duties.  The burden of clearing the flag
-falls to the various wrapper functions provided by the Bin code, thus
-element writers don't have to worry about doing that at all (and simply
-shouldn't).
-
-
-Related changes:
-All the sources in elements/ have been changed to reflect the new system.
-
-
-FIXMEs:
-1) gstpipeline.c calls gst_src_push at some point, dunno why, it's
-commented out now.
-2) any other sources, including vcdsrc, dvdsrc, and v4lsrc will break
-badly and need to be modified to work as pull-based sources.
diff --git a/docs/random/omega/sched/chains b/docs/random/omega/sched/chains
deleted file mode 100644 (file)
index 69af945..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-A new concept in scheduling is that of chains of elements that need to be schedule separately, even in the same set of
-managed elements (which is the set of elements that the Bin in question [a pipeline or thread] is responsible for).  
-An example would by anywhere you have a non-blocking queue in place for buffering.  This kind of element might be
-useful in cases where the scheduling on a buffer level is tight enough that deadlocks might occur.
-
-The scheduler will find chains by traversing the pipeline through the list of managed elements.  A chain boundary is 
-anywhere you have a 'DECOUPLED' element.  A DECOUPLED element is one where there is no direct correlation between the 
-activities of the various pads.  A source fits this description, although the normal single-pad source is the 
-degenerate case.  A queue more properly fits the bill, since pushing a buffer at the sink pad doesn't trigger anything 
-on the src pad, and vice versa.  A multi-src async source is probably the best example, since you want to leave the 
-scheduling up to the elements connected to it.
-
-Anyway, first the simple case:
-
-fakesrc -> fakesink
-
-Both of them should probably have the DECOUPLED bit set, at least to be true to the nature of the actual fake elements.  
-These two end up being a chain, and scheduling has to be set up for the chain.  There are no cothreaded elements in the 
-chain, which means it's relatively easy.  The goal is to find a single entry into the chain, which can be called in a 
-loop to get things done.  Since the fakesrc is DECOUPLED, and we'd be messing with the source pad, it has lower 
-priority than a DECOUPLED sink pad, so the fakesrc's sink pad is the ideal entry into the chain.  This can be 
-simplified into saying that the fakesink is the entry.
-
-In the end, the code to do this boils down to:
-
-  buf = gst_pad_pull (fakesink->sinkpad);
-  gst_pad_push (fakesink->sinkpad, buf);
-
-Because of the way things are no implemented for scheduling, turning it around and making the source the entry has no
-effect as far as the efficiency.  That's because _get no longer directly calls gst_pad_push(), so we have to do it
-outside.  No big deal, it boils down to the same thing I think, modulo a cache-line of stack (i.e. one or two fewer
-this way).
-
-If we put an identity in the middle:
-
-fakesrc -> identity -> fakesink
-
-then we have the same thing, except that there's now an element that isn't DECOUPLED, so it gets higher priority.  That 
-means the identity is now the entry, and when we push the buffer into its chain function, the fakesink gets called.
-
-Now, we can make this much more complex, with the following elementary echo meta-filter:
-
-            |=====| -> delay1 -> |=====|
-            |     |              |     |
--> queue -> | tee | -> delay2 -> | mix | -> queue ->
-            |     |              |     |
-            |=====| -> delay3 -> |=====|
-
-The tee takes a buffer in and spits three out, delay shifts the timestamps around and possibly reframes things to be 
-friendly.  mix takes the three buffers and simply sums them (they're all audio).  The tee element takes one buffer in 
-and promptly spits three out, one after another.  Delay takes an element and immediately spits out a buffer (it 
-zero-pads at the beginning [the duration of the delay] for the sake of argument).  Mix in this case is chained, but 
-assumes that buffer will arrive in order.  On the last chain, it does a push of the newly mixed audio buffer.
-
-The queues are both DECOUPLED, so they have lower weight.  That leaves a bunch of other elements sitting there ripe for 
-entry.  But if we were to take delay1, what would happen?  Well we can't, since there's no _get function on the tee's 
-src pads.
-
-This just re-enforces the idea that the left-most (closest to the source, for you right-to-left people) element should 
-get to be the entry.  But what if we have multiple left-most elements?:
-
--> queue -> eq1 -> |=====|
-                   | mix | -> queue
--> queue -> eq2 -> |=====|
-
-If eq1 is the only entry, we call pull on the queue, then chain over to mix.  Mix then doesn't do anything with it, 
-since it's waiting for another buffer before doing anything.  That means we have to do the same with eq2, and have it 
-chain to mix, at which point mix will do its magic and chain out to the right-hand side.  Figure out to actually use 
-both entries is hard, because the idea at this point is that there's only a single entry to a chain.
-
-Does this mean that we should make mix a DECOUPLED element?  That would fix it to some extent, giving us three chains 
-in the above case.  Each eq chain would be driven by the eq element, pulling from the queue and pushing into the mixer.  
-The mixer -> queue chain is problematic, because there is no possibly entry.  The mixer side has no _get function 
-(since the push always happens upon the receipt of a buffer from the second sink pad), which means that those two
-pads have no possible entrance.
-
-Cothreads make this case much easier, since the mix element would drive things, forcing the eq elements to pull and 
-process buffers in order as needed.  It may be that the best option in the case where there are any multi-sinkpad 
-elements is to turn them into cothreads.
-
-
-Now, on to cothreaded cases.  The simplest possible is to turn all the elements into cothreads.  I may punt on this and 
-do just that for the moment, but there's still the question of what to do at the ends of the chain, where the DECOUPLED 
-elements are.  The easiest is to simply always make then chained, so there's never any worry about who owns the 
-cothread context for the element, simply because there never will be one.
-
-fakesrc -> queue -> @identity -> fakesink
-
-We just set it up so both ends of the queue are chained, and all is well.
diff --git a/docs/random/omega/sched/walkthrough-72 b/docs/random/omega/sched/walkthrough-72
deleted file mode 100644 (file)
index 6ea3504..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-72)
- [-pipeline---------------------------------------------------------------------------------------------]
- ! [-bin-----------------------------]                                               [-thread---------] !
- ! ! [--------]        [---------]   !     [------]      [---------]      [------]   !    [--------]  ! !
- ! ! !faksesrc!        !identity1!   !     !queue1!      !identity2!      !queue2!   !    !fakesink!  ! !
- ! ! !       src --- sink  *     src --- sink n  src -- sink     src -- sink    src --  sink       !  ! !
- ! ! [--------]        [---------]   !     [------]      [---------]      [------]   !    [--------]  ! !
- ! [---------------------------------]                                               [----------------] !
- [------------------------------------------------------------------------------------------------------]
-
-
------
-Ideally, you'd end up with the following sub-pipelines
-
-pipeline:
-fakesrc -> identity1 -> queue1
-queue1 -> identity2 -> queue2
-
-thread:
-queue2 -> fakesink
-
-
-They'd be scheduled as following:
-
-fakesrc: passive chained, pulled by identity1
-identity1: loopfunc cothreaded, ENTRY
-queue1:sink: passive chained, pushed by identity1
-
-queue1:src: _get-based iteration, ENTRY
-identity2: chained by queue1
-queue2:src: passively chained, pushed by identity2
-
-queue2:sink: passively chained, pulled by fakesink
-fakesink: loopfunc cothreaded, ENTRY
-
-
------
-Most likely, we'd end up with the following
diff --git a/docs/random/omega/sched2 b/docs/random/omega/sched2
deleted file mode 100644 (file)
index 3bac20a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-Currently, when an element wants to push or pull, they call gst_pad_*.  These functions then decide what
-to do based on the selection of pointers in the pad.  There are at least 2 options for each, plus some
-header stuff to do various checking of flags.  Unfortunately, because of the selection of pointers in
-the pad, there is at least one case where scheduling has to be tricked, by providing a pointer to a
-function with no body.
-
-What I propose is that these functions be replaced with macros that call a function pointer directly.
-The default functions (provided by GstPad) would be capable of chaining, that's about it.  When a
-schedule is formed, these get replaced with more specific functions, provided by GstBin or a subclass.
-
-In the chain case, the pad_push_func might even be replaced brute force with the chain function, since
-they have the same prototype.  In the cothreaded case, various functions would provide the ability to
-switch, deal with bufpens, etc.
diff --git a/docs/random/omega/scheduling b/docs/random/omega/scheduling
deleted file mode 100644 (file)
index 8da58f0..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-STATUS: pull on srcpads is outdated, they use _get
---------------------------------------------------
-
-0) definitions:
-
-All pads without further specifiers are assumed to belong to the element
-in question.  The pad's peer is always denoted with ->peer.  If there's
-question, pads will be prefixed with self-> and other-> as necessary.
-
-All elements in this document have at most one source and one sink pad,
-called srcpad and sinkpad. Multi-pad cases are supposed to be simple
-extrapolations except in a couple strange cases, to be covered elsewhere.
-
-
-1) loop functions:
-
-A loop function will call gst_pad_pull(sinkpad), do something, and call
-gst_pad_push(srcpad).
-
-gst_pad_pull first checks to see if there's a buffer in the pen.  If not,
-it calls that pad's pullfunc handler, passing it the peer pad.  When that
-finishes, we check again and return the buffer.  If no buffer, we squawk.
-The pullfunc handler simply causes a cothread switch to the peer pad's
-context;
-
-gst_pad_push places the buffer in the peer pad's pen, and calls the local
-pad's pushfunc.  The pushfunc simply causes a switch to the peer pad's
-context.
-
-
-2) chain functions
-
-The loopfunc constructed around a chain function starts by finding all
-sink pads.  For each sink pad, it calls gst_pad_pull.  This causes a
-switch to the peer pad's context and a buffer to appear, which is
-returned.  The pad is the handed off to the chain function, which
-presumably does some processing and calls gst_pad_push(), which causes a
-context switch to that pad's peer.
-
-
-
-3) source
-
-The loopfunc must repeatedly call the srcpad's pull
-
-
-
-
-
----------------------------------      ---------------------------------
- srcpad                                |       | sinkpad
-                               |       |
- GstPad *peer;                 | <-p-> | GstPad *peer;
-   pointer to peer pad         |       |   pointer to peer pad
-                               |       |
- funcptr *pushfunc;            | --s-> | funcptr *pushfunc;
-   causes switch to peer ctx   |       |   element uses buffer in pen,
-                               |       |
- funcptr *pullfunc;            | <-s-- | funcptr *pullfunc;
-   element puts buffer in pen, |       |   causes switch to peer ctx
-   calls gst_pad_push()                |       |
-                               |       |
- funcptr *pullregion func      | <-s-- | funcptr *pullregionfunc;
-   element puts region in pen  |       |   causes switch to peer ctx
-   calls gst_pad_push()                |       |
----------------------------------      ---------------------------------
diff --git a/docs/random/omega/testing/.gitignore b/docs/random/omega/testing/.gitignore
deleted file mode 100644 (file)
index 67c5711..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-Makefile
-Makefile.in
-*.o
-*.lo
-*.la
-.deps
-.libs
-gstobject
diff --git a/docs/random/omega/testing/Makefile b/docs/random/omega/testing/Makefile
deleted file mode 100644 (file)
index 691d5cd..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-gstobject: gstobject.c
-       libtool gcc -o gstobject gstobject.c -I../../../.. ../../../../gst/libgst.la \
-`gtk-config --cflags --libs` `xml-config --cflags --libs`
diff --git a/docs/random/omega/testing/framework b/docs/random/omega/testing/framework
deleted file mode 100644 (file)
index 4ef4519..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-Construction
-Validation
-Testing
-
-Construction will generate some state
-Validation will ensure that everything is kosher
-Tests use combinations of the above to check things
-
-##### Example:
-parent = gst_object_get_parent(object);
-
-setup:
-       create: new object
-               action: object = gst_object_new();
-               validation: object != NULL, object->parent == NULL, etc
-               [cleanup: gst_object_destroy(object);]
-       create: new parent
-               action: parent = gst_object_new();
-               validation: parent != NULL, parent->parent == NULL, etc
-               [cleanup: gst_object_destroy(parent);]
-       create: set object's parent
-               precondition: object->parent == NULL
-               action: gst_object_set_parent(object,parent);
-               validation: object->parent = parent
-preconditions:
-       nothing
-action:
-       curparent = gst_element_get_parent(object);
-validation:
-       curparent == object->parent
-       curparent == parent
-cleanup:
-       nothing
-
-
-##### Resulting code:
-
-///// setup
-// new object
-object = gst_object_new();
-ASSERT(object != NULL);
-ASSERT(object->parent == NULL);
-// new object
-parent = gst_object_new();
-ASSERT(parent != NULL);
-ASSERT(parent->parent == NULL);
-// set object parent
-ASSERT(object->parent == NULL);
-gst_object_set_parent(object,parent);
-ASSERT(object->parent != NULL);
-
-///// preconditions
-
-///// action
-curparent = gst_element_get_parent(object);
-
-///// validation
-ASSERT(object->parent == parent);
-
-///// cleanup
-gst_object_destroy(parent);
-gst_object_destroy(object);
-
-
-
-##### XML descriptions
-
-<construct name="new object">
-  <variable>
-    GstObject *object;
-  </variabls>
-  <action>
-    object = gst_object_new();
-  </action>
-  <validation>
-    <assert>
-      object != NULL
-    </assert>
-    <assert>
-      GST_IS_OBJECT(object)
-    <assert>
-      object->parent == NULL
-    </assert>
-  </validation>
-  <cleanup>
-    <validation>
-      <assert>
-        object != NULL
-      </assert>
-      <assert>
-        GST_IS_OBJECT(object)
-      </assert>
-    </validation>
-    <action>
-      gst_object_destroy(object);
-    </action>
-  </cleanup>
-</construct>
-
-<construct name="set object parent">
-  <variable>
-    GstObject *object;
-  </variable>
-  <variable>
-    GstObject *object;
-  </variable>
-  <precondition>
-    <assert>
-      object->parent == NULL
-    </assert>
-  </precondition>
-  <action>
-    gst_object_set_parent(object,parent);
-  </action>
-  <validation>
-    <assert>
-      object->parent == parent
-    </assert>
-  </validation>
-</construct>
-
-<test name="set object parent">
-  <variable>
-    GstObject *object;
-  <variable>
-  </variable>
-    GstObject *parent;
-  <variable>
-  </variable>
-    GstObject *curparent;
-  </variable>
-  <setup>
-    object = gst_object_new();
-    parent = gst_object_new();
-    gst_object_set_parent(object,parent);
-  </setup>
-  <action>
-    curparent = gst_element_get_parent(object);
-  </action>
-  <validation>
-    curparent == object->parent
-    curparent == parent
-  </validation>
-</test>
diff --git a/docs/random/omega/testing/gstobject.c b/docs/random/omega/testing/gstobject.c
deleted file mode 100644 (file)
index d188f49..0000000
+++ /dev/null
@@ -1,314 +0,0 @@
-#include <gst/gst.h>
-
-static gchar *_subject, *_category;
-static gint _testnum = 0;
-static gboolean _passed;
-static gint _total_tests = 0, _passed_tests = 0;
-static gint _random_size;
-
-void
-tabpad (gchar * str, gint width)
-{
-  int i;
-
-  for (i = 0; i < width - strlen (str); i++)
-    fprintf (stderr, " ");
-}
-
-#define TEST_SUBJECT(subject) fprintf(stderr,"Subject: %s\n",subject),_subject = subject
-#define TEST_CATEGORY(category) fprintf(stderr,"\n\nCategory: %s\n",category)
-
-#define TEST(test) fprintf(stderr,"Test %d: %s...\n",_testnum,test),_passed = TRUE
-#define ASSERT(expr) G_STMT_START{                              \
-  fprintf(stderr,"\t%s:",#expr);tabpad(#expr,50);               \
-  if (!(expr)) {                                                \
-    fprintf(stderr,"FAILED\n");                                 \
-    _passed = FALSE;                                            \
-  } else {                                                      \
-    fprintf(stderr,"passed\n");                                 \
-  }                                                             \
-}G_STMT_END;
-#define ENDTEST() G_STMT_START{                 \
-  _testnum++;                                   \
-  if (_passed) {                                \
-    fprintf(stderr,"\tpassed.\n");              \
-    _passed_tests++;                            \
-  } else {                                      \
-    fprintf(stderr,"\tFAILED.\n");              \
-  }                                             \
-  _total_tests++;                               \
-}G_STMT_END;
-
-void
-SETUP_RANDOM_SIZE (void *random, gint size)
-{
-  int i;
-
-  if (random)
-    g_free (random);
-  _random_size = size;
-  random = g_malloc (_random_size);
-  for (i = 0; i < _random_size; i++)
-    ((unsigned char *) random)[i] = i;
-}
-
-#define SETUP_RANDOM(random,type) SETUP_RANDOM_SIZE(random,sizeof(type))
-
-gboolean
-RANDOM_OK (void *random)
-{
-  int i;
-
-  for (i = 0; i < _random_size; i++) {
-    if (((unsigned char *) random)[i] != i) {
-      SETUP_RANDOM_SIZE (random, _random_size);
-      return FALSE;
-    }
-  }
-  return TRUE;
-}
-
-int
-main (int argc, char *argv[])
-{
-  GstObject *object;
-  GstObject *parent;
-  GstObject *newparent;
-  GtkObject *gtkobject;
-  GstObject *curparent;
-
-  gst_init (&argc, &argv);
-
-  TEST_SUBJECT ("GstObject");
-
-
-  TEST_CATEGORY ("Creation");
-
-  TEST ("create object");
-  /* setup */
-  /* action */
-  object = gst_object_new ();
-  /* assertions */
-  ASSERT (object != NULL);
-  ASSERT (GST_IS_OBJECT (object));
-  /* cleanup */
-  g_free (object);
-  ENDTEST ();
-
-
-  /* new category */
-  TEST_CATEGORY ("Refcounting");
-  /* category setup */
-  object = gst_object_new ();
-
-  TEST ("new object");
-  /* setup */
-  /* action */
-  /* assertions */
-  ASSERT (object->refcount == 1);
-  ASSERT (GTK_OBJECT_FLOATING (object) == TRUE);
-  /* cleanup */
-  ENDTEST ();
-
-  TEST ("increment refcount");
-  /* setup */
-  /* action */
-  gst_object_ref (object);
-  /* assertions */
-  ASSERT (object->refcount == 2);
-  ASSERT (GTK_OBJECT_FLOATING (object) == TRUE);
-  /* cleanup */
-  ENDTEST ();
-
-  TEST ("sink object");
-  /* setup */
-  /* action */
-  gst_object_sink (object);
-  /* assertions */
-  ASSERT (object->refcount == 1);
-  ASSERT (GTK_OBJECT_FLOATING (object) == FALSE);
-  /* cleanup */
-  ENDTEST ();
-
-  TEST ("increment refcount after sink");
-  /* setup */
-  /* action */
-  gst_object_ref (object);
-  /* assertions */
-  ASSERT (object->refcount == 2);
-  ASSERT (GTK_OBJECT_FLOATING (object) == FALSE);
-  /* cleanup */
-  ENDTEST ();
-
-  TEST ("decrement refcount after sink");
-  /* setup */
-  /* action */
-  gst_object_unref (object);
-  /* assertions */
-  ASSERT (object->refcount == 1);
-  ASSERT (GTK_OBJECT_FLOATING (object) == FALSE);
-  /* cleanup */
-  ENDTEST ();
-
-  /* category cleanup */
-  g_free (object);
-
-
-
-  /* new category */
-  TEST_CATEGORY ("Parentage");
-  /* category setup */
-  object = gst_object_new ();
-  parent = gst_object_new ();
-  newparent = gst_object_new ();
-  gtkobject = gtk_type_new (gtk_object_get_type ());
-  /* category assertions */
-  ASSERT (object != NULL);
-  ASSERT (object->refcount == 1);
-  ASSERT (object->parent == NULL);
-  ASSERT (parent != NULL);
-  ASSERT (newparent != NULL);
-  ASSERT (gtkobject != NULL);
-  ASSERT (!GST_IS_OBJECT (gtkobject));
-
-  TEST ("gst_object_set_parent: null object");
-  /* setup */
-  /* action */
-  gst_object_set_parent (NULL, NULL);
-  /* assertions */
-  ASSERT (object->parent == NULL);
-  /* cleanup */
-  ENDTEST ();
-
-  TEST ("gst_object_set_parent: invalid object");
-  /* setup */
-  /* action */
-  gst_object_set_parent ((GstObject *) gtkobject, NULL);
-  /* assertions */
-  ASSERT (object->parent == NULL);
-  /* cleanup */
-  ENDTEST ();
-
-  TEST ("gst_object_set_parent: null parent");
-  /* setup */
-  /* action */
-  gst_object_set_parent (object, NULL);
-  /* assertions */
-  ASSERT (object->parent == NULL);
-  /* cleanup */
-  ENDTEST ();
-
-  TEST ("gst_object_set_parent: invalid parent");
-  /* setup */
-  /* action */
-  gst_object_set_parent (object, (GstObject *) gtkobject);
-  /* assertions */
-  ASSERT (object->parent == NULL);
-  /* cleanup */
-  ENDTEST ();
-
-  TEST ("gst_object_set_parent: valid object, parent is object");
-  /* setup */
-  /* action */
-  gst_object_set_parent (object, object);
-  /* assertions */
-  ASSERT (object->parent == NULL);
-  /* cleanup */
-  ENDTEST ();
-
-  TEST ("gst_object_set_parent: valid object and parent");
-  /* setup */
-  /* action */
-  gst_object_set_parent (object, parent);
-  /* assertions */
-  ASSERT (object->parent == parent);
-  /* cleanup */
-  ENDTEST ();
-
-  TEST ("gst_object_set_parent: parent already set");
-  /* setup */
-  /* action */
-  gst_object_set_parent (object, newparent);
-  /* assertions */
-  ASSERT (object->parent != newparent);
-  ASSERT (object->parent == parent);
-  /* cleanup */
-  g_free (object);
-  ENDTEST ();
-
-
-  TEST ("gst_object_get_parent: null object");
-  /* setup */
-  /* action */
-  curparent = gst_object_get_parent (NULL);
-  /* assertions */
-  ASSERT (curparent == NULL);
-  /* cleanup */
-  ENDTEST ();
-
-  TEST ("gst_object_get_parent: invalid object");
-  /* setup */
-  /* action */
-  curparent = gst_object_get_parent ((GstObject *) gtkobject);
-  /* assertions */
-  ASSERT (curparent == NULL);
-  /* cleanup */
-  ENDTEST ();
-
-  TEST ("gst_object_get_parent: no parent");
-  /* setup */
-  object = gst_object_new ();
-  /* action */
-  curparent = gst_object_get_parent (object);
-  /* assertions */
-  ASSERT (curparent == NULL);
-  /* cleanup */
-  ENDTEST ();
-
-  TEST ("gst_object_get_parent: valid parent");
-  /* setup */
-  gst_object_set_parent (object, parent);
-  /* action */
-  curparent = gst_object_get_parent (object);
-  /* assertions */
-  ASSERT (curparent == parent);
-  /* cleanup */
-  g_free (object);
-  ENDTEST ();
-
-
-  TEST ("gst_object_unparent: null object");
-  /* setup */
-  /* action */
-  gst_object_unparent (NULL);
-  /* assertions */
-  /* NONE - FIXME! */
-  /* cleanup */
-  ENDTEST ();
-
-  TEST ("gst_object_unparent: invalid object");
-  /* setup  */
-  /* action */
-  gst_object_unparent ((GstObject *) gtkobject);
-  /* assertions */
-  /* NONE - FIXME! */
-  /* cleanup */
-  ENDTEST ();
-
-  TEST ("gst_object_unparent: no parent");
-  /* setup */
-  object = gst_object_new ();
-
-
-  /* category cleanup */
-  g_free (object);
-  g_free (parent);
-  g_free (newparent);
-  g_free (gtkobject);
-
-
-
-  fprintf (stderr, "\n\nTotal tests:\t%d\n", _total_tests);
-  fprintf (stderr, "Total passed:\t%d\n", _passed_tests);
-  fprintf (stderr, "Total FAILED:\t%d\n", _total_tests - _passed_tests);
-}
diff --git a/docs/random/omega/testing/gstobject.txt b/docs/random/omega/testing/gstobject.txt
deleted file mode 100644 (file)
index 35f0396..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-Subject: GstObject
-
-Areas to test
-=============
-
-Creation
-Refcounting
-Destruction
-Flags
-Locking
-Parentage
-Path string
-
-
-Tests
-=====
-
-Creation
---------
-Create an object
-       Does it return !NULL
-       GST_IS_OBJECT() ?
-
-Refcounting
------------
-Create new object
-       object->refcount == 1, GTK_OBJECT_FLOATING(object) == TRUE
-Increment refcount
-       object->refcount == 2
-Sink object
-       object->refcount == 1, GTK_OBJECT_FLOATING(object) == FALSE
-Increment refcount
-       object->refcount == 2
-Decrement refcount
-       object->refcount == 1
-
-Destruction
------------
-???
-
-Flags (start with new object)
------
-Create new object
-       Verify that all flags are unset
-Set a flag
-       Verify it's set
-Unset a flag
-       Verify it's not set
-
-Locking (start with new object)
--------
-Lock an object
-       Try to lock, get false
-
-Parentage (start with new object, check refcount == 1)
----------
-gst_object_set_parent: (start with new parent object)
-       Pass NULL...
-       Pass !NULL, but not Object...
-       Pass NULL parent...
-       Pass !NULL parent, but not Object...
-       Pass valid Object, and parent == object
-               object->refcount == 1
-               GTK_OBJECT_FLOATING(object) == TRUE
-               object->parent == NULL
-       Pass valid Object
-               object->refcount == 1
-               GTK_OBJECT_FLOATING(object) == FALSE
-               object->parent == parent
-               The "parent_set" signal should fire with the object and parent as args
-       Pass Object with parent already set
-               object->parent should not equal new parent
-               object->refcount == 1
-gst_object_get_parent:
-       Pass NULL...
-       Pass !NULL, not Object...
-       Pass valid object with no parent
-               Get NULL
-       Pass valid object with parent
-               Get parent pointer
-gst_object_unparent:
-       Pass NULL, with no parent
-               no effect
-       Pass !NULL, not Object, NULL parent
-               pointer not mangled
-       Pass valid object, with no parent
-               object->parent == NULL
-               object->refcount = 1
-       Pass NULL, with valid parent
-               no effect
-       Pass !NULL, not Object, with valid object as parent
-               pointer not mangled
-       Pass valid object, with valid parent
-               object->parent == NULL
-               object->refcount == 0
diff --git a/docs/random/omega/type-properties b/docs/random/omega/type-properties
deleted file mode 100644 (file)
index b216470..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-OUTDATED
---------
-
-
-A type properties system might look like following:
-
-
-1) Type definition includes the properties and their ranges:
-
-audio/mp3
-       layer:          1 - 3
-       bitrate:        8 - 320
-
-audio/raw
-       format:         bitfield (using asound.h definitions)
-       depth:          8 - 32
-       rate:           4000 - 96000
-       channels:       1 - n
-       interleave:     boolean
-
-video/raw
-       format:         32-bit FOURCC
-       bpp:            1 - 32
-       width:          1 - n
-       height:         1 - n
-       framerate:      32-bit float
-
-etc.
-
-
-2) An element can specify what subtypes it can deal with by creating a list of property tables:
-
-mpg123: audio/mp3
-       layer:          1 - 3
-       bitrate:        8 - 320
-
-osssink:
-       format:         S8, S16, etc.
-       depth:          8 - 16
-       rate:           8000 - 48000
-       channels:       1 - 2
-       interleave:     true
-
-And you could list several of these, so for instance if the card only supports 8-bit at up to 22KHz in
-mono, you can remove S8 from the above list and add a second entry:
-
-osssink:
-       format:         S8
-       depth:          8
-       rate:           8000 - 22050
-       channels:       1
-       interleave:     false (irrelevant)
-
-The obvious problem with these examples is that the rate isn't really 8000 - 48000, it's 8000, 11025,
-16000, 22050, 44100, and 48000.  However, we may be able to leave these to pad connect time.
-
-
-
-
-
-struct _type_definition {
-  char *mime_type;
-
-  ....
-
-  GData *properties;
-}
-
-gst_type_add_property_int(_type *type,gchar *propname,int min,int max) {
-  struct _type_prop_int prop_int;
-  GQuark quark = g_quark_from_string(propname);
-
-  prop_int->id = quark;
-  prop_int->min = min;
-  prop_int->max = max;
-  g_datalist_id_set_data(type->properties,quark,&prop_int);
-}
diff --git a/docs/random/phonon-gst b/docs/random/phonon-gst
deleted file mode 100644 (file)
index f5acd84..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-Phonon backend
---------------
-
- The phonon design is based around forming graphs using 3 basic components:
-
- - a source component that generates raw audio/video/subtitle data, aka
-   MediaObject. 
- - an effect component that applies effects to raw audio/video known as
-   AudioPath/VideoPath respectively. Subtitles are routed to a VideoPath
- - output components that render audio or video called AudioOutput and
-   VideoOutput.
-
-  there is also a special input object that allows for feeding raw data in the
-  pipeline and specialized sinks to retrieve audio samples and video frames from
-  the pipeline.
-
- A typical graph or a source that produces an audio and a video stream that
- need to be played. The VideoPath and AudioPath typically contain no filters
- in this case:
-
-                     +----+  +---
-                     | FX |  | ...
-                     +----+  +---
-                       V       V
-                      +-----------+      +-------------+
-                ----->| VideoPath |----->| VideoOutput |
-                |     +-----------+      +-------------+
-    +-------------+
-    | MediaObject |
-    +-------------+
-                |     +-----------+      +-------------+
-                +---->| AudioPath |----->| AudioOutput |
-                      +-----------+      +-------------+
-                       ^       ^
-                     +----+  +---
-                     | FX |  | ...
-                     +-+--+  +---
-
-   - This is very similar to a regular gstreamer playback pipeline.
-
-  A typical graph of playing and crosfading two sources:
-
-                          +--------+
-                          | volume |
-                          +--------+
-                              V  
-     +-------------+    +-----------+                    
-     | MediaObject |--->| AudioPath |\                    
-     +-------------+    +-----------+ \     +-------------+
-                                       ---->| AudioOutput |
-     +-------------+    +-----------+ /     +-------------+
-     | MediaObject |--->| AudioPath |/                    
-     +-------------+    +-----------+                    
-                              ^  
-                          +--------+
-                          | volume |
-                          +--------+
-
-  - As soon as two audio paths are connected to one sink, the input signals are
-    mixed before sending them to the sink. The mixing is typically done in the
-    audio sink by an element such as adder.
-
-  Other types of graphs are possible too:
-
-                        +-----------+                    
-                       /| AudioPath |\                    
-     +-------------+  / +-----------+ \     +-------------+
-     | MediaObject |--                 ---->| AudioOutput |
-     +-------------+  \ +-----------+ /     +-------------+
-                       \| AudioPath |/
-                        +-----------+                    
-
-  - This graph sends the same out data to 2 effect filter graphs and then mixes
-    it to an audio output. The splitting of the graph typically happens with a
-    tee element after the media object.
-
-
-Questions
----------
-
- 1) do the following chains run
-    - synchronized with a shared clock?
-
-     +-------------+    +-----------+    +-------------+                
-     | MediaObject |--->| AudioPath |--->| AudioOutput |
-     +-------------+    +-----------+    +-------------+
-
-     +-------------+    +-----------+    +-------------+                
-     | MediaObject |--->| VideoPath |--->| VideoOutput |
-     +-------------+    +-----------+    +-------------+
-
-    - no API to set both MediaObjects atomically to play so it is assumed that
-      the playback starts and follows the rate of the global clock as soon as
-      the MediaObject is set to play. This makes unconnected chains run as if
-      they were in different GstPipelines.
-
- 2) Threading:
-
-   - Can signals be emitted from any thread?
-   - what operations are permited from a signal handler?
-
- 3) Error reporting
-
-   - How does error reporting work?
-     * an audio/video device/port is busy.
-     * a fatal decoding error occurred.
-     * a media type is not supported
-
-
-General
--------
-
- - Setting up KDE and Phonon build environment
- - Testing, identifying test applications, building test cases
- - Asking questions to Phonon maintainers/designers
-
-Essential classes
------------------
-
-These classes are essential to implement a backend and should be implemented
-first. 
-
-Phonon::BackendCapabilities
-
-  Mostly exposes features in the registry like available decoders and effects.
-
-Phonon::Factory
-
-  Entry point for the GStreamer backend. Provides methods to create instances of
-  object from our backed.
-
-
-Simple playback
----------------
-
-The following classes need to be implemented in order to have simple playback
-capabilities from the backend.
-
-Phonon::AudioOutput
-
-  - Wrapper around audiosinks. Also needs provision for rate and format
-    conversions.  
-  - Mixing capabilities in the case when 2 audio paths are routed to it. 
-
- Notes:
-
-  * is the volume related to the device or to the connection to the device.
-
-Phonon::VideoWidget
-
-  - Wrapper around videosinks. Also needs provision for colorspace and size
-    conversions.  Extends QWidget and probably needs to hook into the XOverlay
-    stuff to draw in the QT widget.  Supports fullscreen mode with a switch.
-
-  - Needs mixing capabilities in the case when 2 video paths are routed to it. 
-
-Phonon::AbstractMediaProducer
-
-  - contains stream selection
-  - play/pause/stop
-  - seeking
-  - periodically performs tick callbacks.
-
-Phonon::MediaObject:
-
-  - The object that decodes the media into raw audio/video/subtitle.
-    This object will use the GStreamer decodebin element to perform the
-    typefinding and decoding.
-
-Phonon::AudioPath/Phonon::VideoPath
-
-  - Simple container for audio/video effect plugins. 
-  - Handles adding/removing of effects, making sure that the streaming is not
-    interrupted and the formats are all compatible.
-
-
-Effect support
---------------
-
-Phonon::Visualization
-
-  Connects an AudioPath to a VideoWidget and allows for selection of a
-  visualisation plugin.
-
-Phonon::AudioEffect/Phonon::VideoEffect
-
-  Base classes
-
-Phonon::VolumeFaderEffect
-
-  Allows fade-in and fade-out with a configurable curve and time. Needs
-  GstController.
-
-Phonon::BrightnessControl
-
-  Controls the brightness of video.
-
-
-Playlist support
-----------------
-
-Phonon::MediaQueue:
-
-  ?? don't know yet where this fits in.
-
-
-Capture
--------
-
-Phonon::AvCapture
-
-  Synchronized audio and video capture. 
-
-Phonon::AudioWriter
-
-  Compress audio.
-
-
-Advanced features
------------------
-Phonon::ByteStream
-
-  Feed raw data into the pipeline. Used for streaming network access.
-
- Implementation:
-
-  Possibly a specialized source element connected to a decodebin.
-
- Notes:
-
-  * Phonon::ByteStream::writeData
-   - can it block?
-
-  * Phonon::ByteStream::setStreamSeekable
-   - If called before starting the ByteStream, decodebin might operate in pull
-     based mode when supported. Else the source is activated in push mode.
-   - If called after starting ByteStream, the Phonon::ByteStream::seekStream
-     signal can be called for push-based seekable streams.
-
-  * Can the signals be emitted from a streaming thread?
-   
-
-Phonon::AudioDataOutput/Phonon::VideoDataOutput/
-
-  Receive raw audio/video data from the pipeline. Used to allow applications to
-  deal with the raw data themselves.
-
- Implementation:
-
-  Possibly a specialized sink element.
-
- Notes :
-
-  * Phonon::AudioDataOutput::dataReady
-    - can this be emitted from the streaming threads?
-
-  * Phonon::AudioDataOutput::endOfMedia 
-    - can this be emitted from the streaming threads?
-    - We need to grab this EOS message synchronously from the bus.
-    - should be emitted _before_ sending the last dataReady. This means we need
-      to cache at least one dataReady.
-
-  * Phonon::AudioDataOutput::setDataSize
-    - can this be a _suggested_ data size or does every callback need to be of
-      this size?
-
-  
diff --git a/docs/random/plugins b/docs/random/plugins
deleted file mode 100644 (file)
index ad98aa2..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-SOMEWHAT OUTDATED
------------------
-
-
-We describe how the plugin system works.
-
-Plugins
--------
-
-plugins are basically shared libraries with a plugin_init
-function.
-
-they provide the GStreamer core library with the following
-information:
-
-  - element factories
-  - type factories
-  - metadata factories?
-
-ElementFactory
---------------
-
-element factories provide the core library with elements (duh)
-
-an element factory has the following information:
-
-  - a unique name for the element factory
-  - strings describing the element (name, description, copyright,...)
-  - a description of the media types it accepts (as capabilities) 
-  - a description of the media types it outputs (as capabilities)
-
-
-TypeFactory
------------
-
-has the following properties:
-
- - a mime type
- - file extensions that may provide a hint for this type
- - a function to detect this type
- - a string to detect this type (file(1) like)
-
-
-XML registry
-------------
-
-The complete plugin tree will be exported into an XML description so
-that the definitions of the factories can be obtained without having
-to load and plugin_init the plugins.
-
-Loading of plugins
-------------------
-
-at some point, the plugin will need to be read into memory before
-any elements it provides can be used. the XML description of the
-loaded plugin will need to be updated.
-
-We will have the following methods for (implicitly) loading plugins:
-
- gst_plugin_load_all()
-
-  remove the complete XML tree and read all the plugins in the
-  paths. The plugin_init method will be called and the XML tree
-  will be rebuild in memory.
-
- gst_plugin_load (name)
-
-  The plugin will be located in the tree and if it already loaded, the
-  function returns. If it is not loaded, the XML entry is removed and
-  the plugin is loaded. The plugin_init is called so that the XML tree
-  is reconstructed.
-
- gst_elementfactory_create (factory, name);
-
-  The plugin providing the element will be located, if the plugin is
-  already loaded, an element with the given name is created.
-  if the plugin is not loaded, gst_plugin_load is called.
-  the loaded factory is located again and the element is created.
-
- The typefind function is called
-
-  When the plugin description  is read from the XML file, the typefind 
-  function is hooked up to a dummy typefind function. The dummy typefind 
-  function will locate the plugin it belongs to and call gst_plugin_load.
-  after the loading of the plugin, the real typefind function is called.
-
-
-
-
-  
-
-
diff --git a/docs/random/plugins.dia b/docs/random/plugins.dia
deleted file mode 100644 (file)
index e7c4206..0000000
+++ /dev/null
@@ -1,941 +0,0 @@
-<?xml version="1.0"?>
-<diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/">
-  <diagramdata>
-    <attribute name="background">
-      <color val="#ffffff"/>
-    </attribute>
-    <attribute name="paper">
-      <composite type="paper">
-        <attribute name="name">
-          <string>#A4#</string>
-        </attribute>
-        <attribute name="tmargin">
-          <real val="2.82"/>
-        </attribute>
-        <attribute name="bmargin">
-          <real val="2.82"/>
-        </attribute>
-        <attribute name="lmargin">
-          <real val="2.82"/>
-        </attribute>
-        <attribute name="rmargin">
-          <real val="2.82"/>
-        </attribute>
-        <attribute name="is_portrait">
-          <boolean val="true"/>
-        </attribute>
-        <attribute name="scaling">
-          <real val="1"/>
-        </attribute>
-        <attribute name="fitto">
-          <boolean val="false"/>
-        </attribute>
-      </composite>
-    </attribute>
-    <attribute name="grid">
-      <composite type="grid">
-        <attribute name="width_x">
-          <real val="1"/>
-        </attribute>
-        <attribute name="width_y">
-          <real val="1"/>
-        </attribute>
-        <attribute name="visible_x">
-          <int val="1"/>
-        </attribute>
-        <attribute name="visible_y">
-          <int val="1"/>
-        </attribute>
-      </composite>
-    </attribute>
-    <attribute name="guides">
-      <composite type="guides">
-        <attribute name="hguides"/>
-        <attribute name="vguides"/>
-      </composite>
-    </attribute>
-  </diagramdata>
-  <layer name="Background" visible="true">
-    <object type="UML - Class" version="0" id="O0">
-      <attribute name="obj_pos">
-        <point val="0.85,4.15"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="0.8,4.1;12.3656,11.4"/>
-      </attribute>
-      <attribute name="elem_corner">
-        <point val="0.85,4.15"/>
-      </attribute>
-      <attribute name="elem_width">
-        <real val="11.4656"/>
-      </attribute>
-      <attribute name="elem_height">
-        <real val="7.2"/>
-      </attribute>
-      <attribute name="name">
-        <string>#GstPlugin#</string>
-      </attribute>
-      <attribute name="stereotype">
-        <string/>
-      </attribute>
-      <attribute name="abstract">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_attributes">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="visible_attributes">
-        <boolean val="true"/>
-      </attribute>
-      <attribute name="visible_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="attributes">
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#name#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#gchar *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#longname#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#char *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#filename#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#gchar *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#loaded#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#gboolean#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#elements#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#GList *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#types#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#GList *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#autopluggers#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#GList *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <attribute name="operations"/>
-      <attribute name="template">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="templates"/>
-    </object>
-    <object type="UML - Class" version="0" id="O1">
-      <attribute name="obj_pos">
-        <point val="17,9"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="16.95,8.95;31.9092,13.85"/>
-      </attribute>
-      <attribute name="elem_corner">
-        <point val="17,9"/>
-      </attribute>
-      <attribute name="elem_width">
-        <real val="14.8592"/>
-      </attribute>
-      <attribute name="elem_height">
-        <real val="4.8"/>
-      </attribute>
-      <attribute name="name">
-        <string>#GstElementFactory#</string>
-      </attribute>
-      <attribute name="stereotype">
-        <string/>
-      </attribute>
-      <attribute name="abstract">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_attributes">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="visible_attributes">
-        <boolean val="true"/>
-      </attribute>
-      <attribute name="visible_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="attributes">
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#name#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#gchar *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#type#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#GtkType#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#details#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#GstElementDetails *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#padtemplates#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#GList *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <attribute name="operations"/>
-      <attribute name="template">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="templates"/>
-    </object>
-    <object type="UML - Association" version="0" id="O2">
-      <attribute name="obj_pos">
-        <point val="12.3156,9.25"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="10.8656,7.8;18.45,11.15"/>
-      </attribute>
-      <attribute name="orth_points">
-        <point val="12.3156,9.25"/>
-        <point val="15,9.25"/>
-        <point val="15,9.7"/>
-        <point val="17,9.7"/>
-      </attribute>
-      <attribute name="orth_orient">
-        <enum val="0"/>
-        <enum val="1"/>
-        <enum val="0"/>
-      </attribute>
-      <attribute name="name">
-        <string/>
-      </attribute>
-      <attribute name="direction">
-        <enum val="0"/>
-      </attribute>
-      <attribute name="ends">
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string>#1#</string>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="2"/>
-          </attribute>
-        </composite>
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string>#*#</string>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="0"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <connections>
-        <connection handle="0" to="O0" connection="17"/>
-        <connection handle="1" to="O1" connection="3"/>
-      </connections>
-    </object>
-    <object type="UML - Class" version="0" id="O3">
-      <attribute name="obj_pos">
-        <point val="21,2"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="20.95,1.95;34.9396,6.85"/>
-      </attribute>
-      <attribute name="elem_corner">
-        <point val="21,2"/>
-      </attribute>
-      <attribute name="elem_width">
-        <real val="13.8896"/>
-      </attribute>
-      <attribute name="elem_height">
-        <real val="4.8"/>
-      </attribute>
-      <attribute name="name">
-        <string>#GstPadTemplate#</string>
-      </attribute>
-      <attribute name="stereotype">
-        <string/>
-      </attribute>
-      <attribute name="abstract">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_attributes">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="visible_attributes">
-        <boolean val="true"/>
-      </attribute>
-      <attribute name="visible_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="attributes">
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#name_template#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#gchar *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#direction#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#GstPadDirection#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#presence#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#GstPadPresence#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#caps#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#GstCaps *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <attribute name="operations"/>
-      <attribute name="template">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="templates"/>
-    </object>
-    <object type="UML - Association" version="0" id="O4">
-      <attribute name="obj_pos">
-        <point val="31.8592,13.3"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="30.4092,1.25;38.45,14.75"/>
-      </attribute>
-      <attribute name="orth_points">
-        <point val="31.8592,13.3"/>
-        <point val="37,13.3"/>
-        <point val="37,2.7"/>
-        <point val="34.8896,2.7"/>
-      </attribute>
-      <attribute name="orth_orient">
-        <enum val="0"/>
-        <enum val="1"/>
-        <enum val="0"/>
-      </attribute>
-      <attribute name="name">
-        <string/>
-      </attribute>
-      <attribute name="direction">
-        <enum val="0"/>
-      </attribute>
-      <attribute name="ends">
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string>#1#</string>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="2"/>
-          </attribute>
-        </composite>
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string>#*#</string>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="0"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <connections>
-        <connection handle="0" to="O1" connection="15"/>
-        <connection handle="1" to="O3" connection="4"/>
-      </connections>
-    </object>
-    <object type="UML - Class" version="0" id="O5">
-      <attribute name="obj_pos">
-        <point val="17.1,14.85"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="17.05,14.8;32.494,18.9"/>
-      </attribute>
-      <attribute name="elem_corner">
-        <point val="17.1,14.85"/>
-      </attribute>
-      <attribute name="elem_width">
-        <real val="15.344"/>
-      </attribute>
-      <attribute name="elem_height">
-        <real val="4"/>
-      </attribute>
-      <attribute name="name">
-        <string>#GstTypeFactory#</string>
-      </attribute>
-      <attribute name="stereotype">
-        <string/>
-      </attribute>
-      <attribute name="abstract">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_attributes">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="visible_attributes">
-        <boolean val="true"/>
-      </attribute>
-      <attribute name="visible_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="attributes">
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#mime#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#gchar *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#exts#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#gchar *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#typefindfunc#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#GstTypeFindFunc#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <attribute name="operations"/>
-      <attribute name="template">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="templates"/>
-    </object>
-    <object type="UML - Association" version="0" id="O6">
-      <attribute name="obj_pos">
-        <point val="12.3156,10.05"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="10.8656,8.6;18.55,17"/>
-      </attribute>
-      <attribute name="orth_points">
-        <point val="12.3156,10.05"/>
-        <point val="15.7,10.05"/>
-        <point val="15.7,15.55"/>
-        <point val="17.1,15.55"/>
-      </attribute>
-      <attribute name="orth_orient">
-        <enum val="0"/>
-        <enum val="1"/>
-        <enum val="0"/>
-      </attribute>
-      <attribute name="name">
-        <string/>
-      </attribute>
-      <attribute name="direction">
-        <enum val="0"/>
-      </attribute>
-      <attribute name="ends">
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string>#1#</string>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="2"/>
-          </attribute>
-        </composite>
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string>#*#</string>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="0"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <connections>
-        <connection handle="0" to="O0" connection="19"/>
-        <connection handle="1" to="O5" connection="3"/>
-      </connections>
-    </object>
-    <object type="UML - Class" version="0" id="O7">
-      <attribute name="obj_pos">
-        <point val="17.065,19.975"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="17.015,19.925;27.5201,24.025"/>
-      </attribute>
-      <attribute name="elem_corner">
-        <point val="17.065,19.975"/>
-      </attribute>
-      <attribute name="elem_width">
-        <real val="10.4051"/>
-      </attribute>
-      <attribute name="elem_height">
-        <real val="4"/>
-      </attribute>
-      <attribute name="name">
-        <string>#GstAutoplugFactory#</string>
-      </attribute>
-      <attribute name="stereotype">
-        <string/>
-      </attribute>
-      <attribute name="abstract">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_attributes">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="suppress_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="visible_attributes">
-        <boolean val="true"/>
-      </attribute>
-      <attribute name="visible_operations">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="attributes">
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#name#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#gchar *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#longdesc#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#gchar *#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-        <composite type="umlattribute">
-          <attribute name="name">
-            <string>#type#</string>
-          </attribute>
-          <attribute name="type">
-            <string>#GtkType#</string>
-          </attribute>
-          <attribute name="value">
-            <string/>
-          </attribute>
-          <attribute name="visibility">
-            <enum val="0"/>
-          </attribute>
-          <attribute name="abstract">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="class_scope">
-            <boolean val="false"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <attribute name="operations"/>
-      <attribute name="template">
-        <boolean val="false"/>
-      </attribute>
-      <attribute name="templates"/>
-    </object>
-    <object type="UML - Association" version="0" id="O8">
-      <attribute name="obj_pos">
-        <point val="12.3156,10.85"/>
-      </attribute>
-      <attribute name="obj_bb">
-        <rectangle val="10.8656,9.4;18.515,22.125"/>
-      </attribute>
-      <attribute name="orth_points">
-        <point val="12.3156,10.85"/>
-        <point val="14.8,10.85"/>
-        <point val="14.8,20.675"/>
-        <point val="17.065,20.675"/>
-      </attribute>
-      <attribute name="orth_orient">
-        <enum val="0"/>
-        <enum val="1"/>
-        <enum val="0"/>
-      </attribute>
-      <attribute name="name">
-        <string/>
-      </attribute>
-      <attribute name="direction">
-        <enum val="0"/>
-      </attribute>
-      <attribute name="ends">
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string>#1#</string>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="2"/>
-          </attribute>
-        </composite>
-        <composite>
-          <attribute name="role">
-            <string/>
-          </attribute>
-          <attribute name="multiplicity">
-            <string>#*#</string>
-          </attribute>
-          <attribute name="arrow">
-            <boolean val="false"/>
-          </attribute>
-          <attribute name="aggregate">
-            <enum val="0"/>
-          </attribute>
-        </composite>
-      </attribute>
-      <connections>
-        <connection handle="0" to="O0" connection="21"/>
-        <connection handle="1" to="O7" connection="3"/>
-      </connections>
-    </object>
-  </layer>
-</diagram>
diff --git a/docs/random/porting-to-0.11.txt b/docs/random/porting-to-0.11.txt
deleted file mode 100644 (file)
index 66f850a..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-This guide has been renamed to porting-to-1.0.txt.
-
-The latest version can be found at:
-
-http://cgit.freedesktop.org/gstreamer/gstreamer/tree/docs/random/porting-to-1.0.txt
diff --git a/docs/random/queue b/docs/random/queue
deleted file mode 100644 (file)
index a76f235..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-            thread 1                                         thread2
-
-                                                          // the queue is empty
-                                                           while (!queue->level_buffers) {
-                                                             STATUS("queue: %s U released lock\n");
-                                                             GST_OBJECT_UNLOCK (queue);
-
-  // thread1 is scheduled and puts a lot of buffers
-  // in the queue
-
-  // thread1 has put the last buffer on the queue
-  // here. A signal is going to be emitted
-
-  tosignal = (queue->level_buffers >= 0);
-  queue->level_buffers++;
-
-  /* we can unlock now */
-  GST_OBJECT_UNLOCK (queue);
-
-  if (tosignal) {
-    g_mutex_lock (queue->emptylock);
-    g_cond_signal (queue->emptycond);
-    g_mutex_unlock (queue->emptylock);
-  }
-
-                                                             g_mutex_lock (queue->emptylock);
-                                                            // wait forever
-                                                             g_cond_wait (queue->emptycond, queue->emptylock);
-                                                             g_mutex_unlock (queue->emptylock);
-                                                             GST_OBJECT_LOCK (queue);
-                                                           }
-                                                          
-
-  // thread 1 will also wait forever because the
-  // queue is filled....
-
-
-
diff --git a/docs/random/richardb/syncmail b/docs/random/richardb/syncmail
deleted file mode 100644 (file)
index d45adf3..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-The syncmail script in CVSROOT is a modified version of the script
-taken from the sourceforge snippets page, at:
-http://sourceforge.net/snippet/detail.php?type=snippet&id=100414
diff --git a/docs/random/rtp b/docs/random/rtp
deleted file mode 100644 (file)
index 40a159b..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-RTP client subsystem proposal.
-Ramon Garcia Fernandez
-
-A brief description of the RTP protocol.
-
-The RTP protocol uses two connections: one for passing data and another for control. The control connection is used for starting, finishing, and passing statistics of lost packets. On the data connection, packets are transmitted containing the media. These packets have a 7 bit field that says what codec is the data transmitted with. This codec is variable. However data cannot change from audio to video in packets of the same connection. All the packets belong to the same logical stream, that is, for instanace, to the same speech, or to the same song. Different codecs in the same stream is used, for instance, to insert comfort noise.
-
-Each codec is packeted in a specific way in RTP packets. This is necessary to minimize the damage produced by lost packets. Therefore, packets should be arranged so that each packet can be decoded independently. If a packet is lost, that shouldn't preclude the decoding of following packets.
-
-
-Suggested implementation:
-
-Tbe implementation that I suggest contains an rtpdec element. This element has one sink pad for the data, one src pad for the decoded data, and a pair of src and sink pads for control messages. The decoded data that comes from rtpdec has no RTP dependency. It is in the format expected by the codec that it decodes it. Therefore, rtpdec must do codec specific processing of data to take into account that different codecs are stored differently in RTP.
-
-A possible pipeline is:
-
-udpcon name="data" udpcon name="control" data.src!rtpdec.datasrc  control.src!rtpdec.controlin control.sink!rtpdec.controlout rtpdec name="rtpdec" ! mp3decode ! osssink
-
-udpcon is an element (not yet written) that provides a src and a sink pad to read and write to a socket. There are two udpcon, one for reading the data socket and another for reading and writing to the control socket.
-
-To handle variable types, the following would work (the UDP part left out for clarity is identical to the one above):
-
-[udp] rtpdec ! spider ! osssink
-
-rtpdec has a property that tells it the mapping of the payload bits to mime type. This is necessary, because that mapping is not fixed. It has to be obtained at runtime through other mechanisms, such as a SDP file obtained by http or rtsp.
-
-A possible implementation of rtpdec is a bin that contains two elements: a media independent _rtpparse and a media dependent rtp-dec-mp3. Thus the pipeline would be
-
-udpsrc ! _rtpparse ! rtp-dec-mp3 ! mp3decode ! osssink
-       \________________________/
-             rtpdec bin
-
-Another possible implementation is, that rtpdec opens a plugin that contains the code to convert the codec specific packets into the input that the normal decoder for that codec expects.
-
-Ronald said that this mechanism would be complicated because it would require to duplicate the functionality of the plugin loader. It shouldn't be like that because it should use the normal plugin loader. However, this is an issue that I do not fully understand.
-
-Ronald suggested to use inheritance. Thus the user should insert a codec specific rtp element in the pipeline. Such as:
-
-udpsrc ! rtp-mp3 ! mp3decode ! osssink
-
-Reuse of RTP logic would be achieved through inheritance.
-
-This looks more logical, because inheritance reflects the fact that rtp-mp3 "is an" specialization of rtp. However, there are several issues. As stated above, it is possible in RTP to switch the encoding of the media at any time. If this happens, some state must be kept, such as statistics of packets received and sent.
-
diff --git a/docs/random/signal b/docs/random/signal
deleted file mode 100644 (file)
index 679a36c..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-Random notes on signals:
-
-* Use a BOXED (and not a POINTER) marshaller when your signal will have a 
-  GstBuffer argument:
-
-g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
-              G_STRUCT_OFFSET (GstIdentityClass, handoff), NULL, NULL,
-              gst_marshal_VOID__BOXED, G_TYPE_NONE, 1,
-              GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE);
-
-* For GstBuffers arguments, consider using G_SIGNAL_TYPE_STATIC_SCOPE as it
-  can prevent an extra copy of the buffer
diff --git a/docs/random/sources b/docs/random/sources
deleted file mode 100644 (file)
index 3e5c466..0000000
+++ /dev/null
@@ -1,324 +0,0 @@
-There are a number of different ways of coding a GstSrc.  I'll try to
-outline them and how the function here: 
-
-1a) Simple push-function based with single output
-
-
- *------*      *------
- !      !      !
- ! src  !--->--! plugin
- !      !      !      
- *------*      *------
-
-This is the style that all the existing sources use.  There is a single
-output pad, and a _push function that's global to the whole element.  The
-_push function simply constructs buffers and pushes them out the pad. 
-
-Chained (current implementation): 
-
-
-      bin               src               pad1           pad2            plugin
-       !                                              (= pad1->peer)
- gst_bin_iterate
-       !
-       ! (find entry)
-       !
-       ! gst_src_push
-       !---------------->!  
-                         ! (create buffer)
-                        !
-                         ! gst_pad_push    
-                        !---------------->! 
-                                          !
-                                          ! pad1->chainfunc (pad1->peer) 
-                                           !------------------------------->!
-                                          !                                !
-                                          :                                :
-                                                                     (more chaining)
-                                          :                                :
-                                          !<-------------------------------!
-                        !<----------------!
-      !<-----------------!
-      !
-  iteration ends
-      !
-     ---
-      -
-
-Typically this will be the/an entry into the Bin.  The Bin's iterate
-function simply calls the Src's _push function.  When the _push function
-pushes a buffer out it's pad, the chain function of the peer pad is
-called, presumably causing a push out the other side of that element, and
-eventually data gets to the other end.  The stack unrolls, and the
-iteration ends for that Src. 
-
-
-
-Cothreaded: 
-
-Again, the source would generally be an entry into the Bin.  A loopfunc
-will be constructed around it, which will simply loop calling the Src's
-_push function as in the non-cothreaded case.  When the _push function
-pushes a buffer, it finds a pushfunc attached to the pad, drops the buffer
-in the pen, and calls the pushfunc provided by the Bin.  This causes a
-switch to the next element, then the next, to the end, at which point a
-buffer pull will travel back down the chain.  The _push function gets
-context and finishes, at which point the loopfunc wrapper simply calls it
-again in the next iteration. 
-
-(current implementation): 
-
-
-      bin               cothread1         src               pad1           pad2       cothread2      plugin
-       !                 (src)                          (= pad2->peer)                (plugin)
- gst_bin_iterate
-       !
-       ! (first entry)
-       !
-       ! cothread_switch
-       !---------------->!  
-                         ! gst_src_push    
-                        !---------------->! 
-                                          ! (create buffer)
-                                          !
-                                          ! gst_pad_push (pad1) 
-                                          !
-                                           !--------------------!
-                                                               ! (fill bufpen)
-                                                               !
-                                                               ! cothread switch
-                                                               ----------------------->!
-                                                                                       ! gst_pad_pull (pad2)
-                                                                                       !
-                                                                           !<----------!
-                                                                           !
-                                                                           ! (get buffer from bufpen)
-                                                                           !
-                                                                           !---------->!
-                                                                                       ! pad2->chainfunc
-                                                                                       !------------->!
-                                                                                                      !
-                                                                                                      :
-                                                                                                      
-                                                                                                      :
-                                                                                       !<-------------!
-                                                                                       ! gst_pad_pull (pad2)
-                                                                           !<----------!
-                                                                            ! 
-                                                                           ! (bufpen empty)
-                                                               !<----------! 
-                        !<-------------------------------------! cothread switch
-       !<----------------!
-       !
-  iteration ends
-       !
-       :
-
-       :
-       !
-  next iteration
-       !
-       ! cothread_switch
-       !---------------->!  
-                         ! gst_src_push    
-                        !---------------->! 
-                                          ! (create buffer)
-                                          !
-                                          ! gst_pad_push (pad1) 
-                                          !
-                                           !--------------------!
-                                                               ! (fill bufpen)
-                                                               !
-                                                               ! cothread switch
-                                                               !---------->!
-                                                                           ! (get buffer from bufpen)
-                                                                           !
-                                                                           !---------->!
-                                                                                       ! pad2->chainfunc
-                                                                                       !------------->!
-                                                                                                      !
-                                                                                                      :
-                                                                                                      
-                                                                                                      :
-                                                                                       !<-------------!
-                                                                                       ! gst_pad_pull (pad2)
-                                                                           !<----------!
-                                                                            ! 
-                                                                           ! (bufpen empty)
-                                                               !<----------! 
-                        !<-------------------------------------! cothread switch
-       !<----------------!
-       !
-  iteration ends
-       !
-       :
-
-      
------------------------------------------------------------------------------------------------
-1b) Simple push-function based with multiple output
-
-Chained: 
-
-Similar to the single output variant, except several chains are spawned
-off, one per push, hanging off whichever pad the buffer is pushed off of. 
-The stack will grow and unwind as many times as buffers are pushed out. 
-
-(current implementation)
-
-      bin               src               pad1           pad2            plugin
-       !                                              (= pad1->peer)
- gst_bin_iterate
-       !
-       ! (find entry)
-       !
-       ! gst_src_push
-       !---------------->!  
-                         ! (create buffer)
-                        !
-                         ! gst_pad_push    
-                        !---------------->! 
-                                          !
-                                          ! pad1->chainfunc (pad1->peer) 
-                                           !------------------------------->!
-                                          !                                !
-                                          :                                :
-                                                                     (more chaining)
-                                          :                                :
-                                          !<-------------------------------!
-                        !<----------------!
-                         ! (create buffer)
-                        !
-                         ! gst_pad_push    
-                        !---------------->! 
-                                          !
-                                          ! pad1->chainfunc (pad1->peer) 
-                                           !------------------------------->!
-                                          !                                !
-                                          :                                :
-                                                                     (more chaining)
-                                          :                                :
-                                          !<-------------------------------!
-                        !<----------------!
-                        :
-                  (more pushes)
-                        :
-      !<-----------------!
-      !
-  iteration ends
-      !
-     ---
-      -
-
-
-Cothreaded: 
-
-Also similar to the single output variant.  When the pull winds its way
-back from the first push, execution returns to the Src's _push function,
-which simply goes off and pushes out another buffer, causing another
-series of context switches.  Eventually the loopfunc wrapper starts over,
-round and round we go. 
-
-
-
------------------------------------------------------------------------------------------------
-2) Pull-function based with single output
-
-Similar to a regular filter with a chain function associated with each
-pad, this kind of source doesn't provide a src-wide push function, but
-does provide pullfuncs for its pad.  A pullfunc puts a buffer in the pen
-and exits. 
-
-Chained: 
-
-      bin               src               pad1           pad2            plugin
-       !                                              (= pad1->peer)
- gst_bin_iterate
-       !
-       ! (find entry)
-       !
-       ! (find src pad
-       !  of entry element)
-       !
-       ! gst_pad_pull
-       !------------------------------------------------>!
-                                 ?                       !
-                        !<------------------------------!
-                         !  
-                         ! (create buffer)
-                        !
-                         ! gst_pad_push    
-                         !------------------------------>!
-                                                        ! (bufpen filled)
-                       (return buffer)                  !
-       !<------------------------------------------------!
-       !
-       ! gst_pad_chain
-       !------------------------------------------------------------------->!
-                                                                           !
-                                                                           :
-                                                                     (more chaining)
-                                                                           :
-       !<-------------------------------------------------------------------!
-       !
-  iteration ends
-       !
-      ---
-       -
-
-As usual, is likely to be an entry into a Bin.  The Bin iterate code must
-explicitly pull a buffer and pass it on to the peer.
-
-Cothreaded: 
-
-
-      bin               cothread1         src               pad1           pad2       cothread2      plugin
-       !                 (src)                          (= pad2->peer)                (plugin)
- gst_bin_iterate
-       !
-       ! (first entry)
-       !
-       ! cothread_switch
-       !---------------->! gst_pad_pull 
-                         !------------------------------------------------>!
-                                                   ?                       !
-                                          !<------------------------------!
-                                           !  
-                                           ! (create buffer)
-                                          !
-                                           ! gst_pad_push    
-                                           !------------------------------>!
-                                                                          ! (bufpen filled)
-                                               (return buffer)            !
-                         !<------------------------------------------------!
-                         !
-                        ! pad_chain
-                        !--------------------------------------! cothread switch
-                                                               |---------------------->!
-                                                                                       ! gst_pad_pull (pad2)
-                                                                                       !
-                                                                           !<----------!
-                                                                           !
-                                                                           ! (get buffer from bufpen)
-                                                                           !
-                                                                           !---------->!
-                                                                                       ! pad2->chainfunc
-                                                                                       !------------->!
-                                                                                                      !
-                                                                                                      :
-                                                                                                      
-                                                                                                      :
-                                                                                       !<-------------!
-                                                                                       ! gst_pad_pull (pad2)
-                                                                           !<----------!
-                                                                            ! 
-                                                                           ! (bufpen empty)
-                                                              !<-----------!
-                                                               !   cothread switch
-                                           !-------------------!   
-                         !<----------------!
-       !<----------------!                                     
-       !
-  iteration ends
-       !
-       :
-
diff --git a/docs/random/status-0.11-14-jun-2011.txt b/docs/random/status-0.11-14-jun-2011.txt
deleted file mode 100644 (file)
index b4309ac..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-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/styleguide b/docs/random/styleguide
deleted file mode 100644 (file)
index 6fadda1..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-Some notes about various stylistic issues
------------------------------------------
-
-(This file should end up as a nice web page eventually)
-
-CODING STYLE
-------------
-- No //-style comments allowed.  Never.  Reason: Forte doesn't support it.
-- Our indentation style is codified in gstreamer/tools/gst-indent
-- Don't mix tabs with spaces when writing new code.
-- use GST_*_OBJECT as much as possible so it's clear which object you're
-  logging for
-
-SUBMITTING CODE
----------------
-- new code submitted to core, plugins-base, or plugins-good needs to pass a
-  review from another committer.
-- submitting new base classes also means you look at targets for assimilation.
diff --git a/docs/random/testing/syntax b/docs/random/testing/syntax
deleted file mode 100644 (file)
index f66c126..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-The test program
-----------------
-
-We need a test program that:
-
-  - can read a file with the test specs
-  - construct a pipeline using the pipeline definition in the spec file
-    (using gst_parse_launch ())
-  - add signals to elements in the pipeline 
-  - run the pipeline for a fixed (in time/number of iterations) period
-  - record the fireing of the signals
-  - compare the signals to the expected results.
-
-
-spec file contents:
--------------------
-
-tcN: name-of-the-tescase
-tcP: pipeline of the testcase in gst_parse_launch () syntax.
-tcS: id1, element, signalname (attach to signal in an element)
-tcS: id2, element, signalname
-...
-tcI: the number of iterations on the top bin 
-tcT: a timeout value in mSecs
-tcR: id1,1,id2,1,.. (the pattern of signals triggered)
-or 
-tcR: id1==id2,... (denote an equal number of signals)
-/n
-
-
-signal trigger patterns
------------------------
-
-
-
-
-
diff --git a/docs/random/thaytan/opengl b/docs/random/thaytan/opengl
deleted file mode 100644 (file)
index a796629..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# OpenGL usage
-How to set up openGL using plugins in such a way that they can
-render to an on-screen window, or offscreen equally?
-
-eg:
-superfoo3d ! glwindow
-or
-superfoo3d ! gloffscreen ! xvideowindow
-
-This would imply that there is some mime type which connects a glwindow/gloffscreen and a GL using component sensibly. I don't see that there is any actual 
-data to send, however - the only purpose of the glwindow/gloffscreen is to 
-set up an openGL context and then 'output' it somehow one the superfoo3d has
-finished drawing each frame.
-
-In the case of glwindow, 'output' it means translate into an on-screen window,
-but for gloffscreen it means produce a video packet and go.
-
-These components really need some other 2 way communication, rather than the
-pads metaphor, I think?
-
diff --git a/docs/random/thaytan/video-overlays b/docs/random/thaytan/video-overlays
deleted file mode 100644 (file)
index af0697b..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-# Compositing and video overlays.
-We want a way to composite a video frame and an overlay frame. The video frame is as we expect, the overlay is a normal video frame + an alpha mask. In the following monologue, please consider that I mean RGB/I420/YV12/YUY2 wherever I say RGB.
-
-So we have a plugin with 2 sinks and one src:
-   +----------------+
-   |video           |
-   |           video|
-   |overlay         |
-   +----------------+
-
-What should the format for the overlay data look like?
-Ideas:
- * RGBA   - 4 byte per pixel video frame
- * RGB+A  - 3 Bytes per pixel video frame, then 1 byte per pixel overlay frame.
-            A new mime type, or a variation on video/raw? I'm not sure
- * Overlay is actually 2 sinks, one takes a RGB/YUV data the other the alpha channel.
-
-I'm not sure which approach is better, but I think it is probably neatest to 
-use RGB+A, and then have a separate plugin which has 2 sinks and converts an
-RGB/YUV stream plus an alpha stream into an RGB+A stream. The benefit of RGB+A over RGBA in this scenario, is that it is easier (correct me if I'm wrong) to optimise 2 block copies which appends an alpha frame to a RGB frame than it is to
-do the many copies required to interleave them into an RGBA stream.
-
-So, I see this producing a few new plugins:
-videooverlay - takes an RGB and an RGB+A frame from 2 sinks, does the overlay (according to some properties) and outputs a result frame in RGB or RGB+A (as negotiated) format on 1 src.
-rgb2rgba - takes 1 RGB frame and one A frame from 2 sinks and outputs RGB+A on 1 src. If the A sink is not connected, we just add a fixed alpha channel based on an object-property.
-rgb2rgba - takes an RGB+A frame and discards the RGB component.
-textoverlay - This plugin, instead of taking a video frame and overlaying text, can just output an RGB+A stream with appropriate timestamping. This prevents duplicating code to composite with an alpha mask and allows us to optimise it in one spot only.
-
diff --git a/docs/random/thomasvs/0.10 b/docs/random/thomasvs/0.10
deleted file mode 100644 (file)
index ee3e466..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-general
--------
-- write script to check for:
-  invalid // comments
-  invalid %lld
-  invalid LL for 64bit ints
-  wrong whitespacing
-  trailing space
-
-gstreamer
----------
-- reorganize tests and examples into
-  - testsuite
-    - check: unit tests
-    - examples: example code
-    - interactive: interactive tests
-- move gst/base to libs/gst/base ?
-  (but elements link against them)
-- move elements out of gst/ dir ?
-- check/gst/pipelines: currently disabled, random failures
-
-gst-plugins-base
-----------------
-- gst-libs/gst/audio:
-  - DONE: audiofilter folded in
-- gst:
-  - adder: needs docs, an example, and a test
-  - audioconvert: ok
-  - audiorate: needs docs and tests
-  - audioresample: David needs to fix this
-  - audioscale: needs to go
-  - audiotestsrc: ok
-  - ffmpegcolorspace: needs a test
-  - playback: example
-  - sine: removed, DONE
-  - subparse:
-    - works, but how do we link it so we can display it ?
-    - example ?
-    - test with different files/sources ? can be inlined
-  - tags:
-    - contained a very small code file that wasn't built, and a copy of a header
-      that was in the tag lib; removed; DONE
-  - tcp:
-    - works
-    - need tests
-    - need docs
-    - need possible porting to GNet (later)
-  - typefind:
-    - works
-    - need tests - this definitely could use it
-    - is there any way they can be documented ?
-    - should the plugin docs show a list of them ?
-  - videorate:
-    - needs tests, docs
-  - videoscale:
-    - needs tests
-      - negotiation
-      - par conversion
-      - different scale algorithms
-    - needs docs
-      - negotiation with five out of six free variables (src/sink w/h/par)
-  - videotestsrc:
-    - could use tests for all possible caps
-  - volume: OK
-- ext:
-  - alsa:
-    - needs docs; esp. params and common practices
-    - needs interactive tests; depends on having such a setup available
-  - cdparanoia:
-    - needs docs, and interactive test
-    - remains in -base until cdio is proven to be better on all counts
-  - gnomevfs:
-    - needs docs (how to use proxy, link to gnomevfs docs, explanation
-       about need for homedir to create .gnome2 dir in, ...)
-    - needs test; test could use local files and http urls
-  - libvisual
-    - needs docs (easy)
-    - needs test
-  - ogg, vorbis, theora
-    - needs docs
-    - needs test
-- sys
-  - v4l
-    - needs interactive test
-    - needs lots of docs
-  - ximage
-    - interactive test should go somewhere
-    - docs ok
-  - xvimage
-    - interactive test should go somewhere
-    - docs ok
-
-gst-plugins-good
-----------------
-
-- gst:
-  - alpha, alphacolor: document with example
-  - auparse: crashes on e.g.
-  gst-launch -v filesrc location=/usr/share/emacs/site-lisp/emacspeak/sounds/default-8k/ask-short-question.au ! auparse ! osssink
-    -> will move to bad
-  - autodetect: OK
-  - videofilter:
-    - is the lib still needed, given basetransform ?
-      yes
-    - currently installs a lib; should not install, or move to a dir, with pc
-      file, possibly in -base
-      DONE: moved to -base
-- ext:
-  - aasink: properties need looking at
-    - width, height: why are they there ? caps don't match
-    - frames-displayed: in base class ?
-    - frame-time: what's this ?
-  - cairo:
-    - cairotimeoverlay works
-    - cairotextoverlay ? pipeline ?
-  - flac:
-    - flacenc:
-gst-launch -v audiotestsrc wave=white-noise ! flacenc ! filesink location=white-noise.flac does not produce a correct file
-    - flacdec works, but
-gst-launch gnomevfssrc location=http://gstreamer.freedesktop.org/media/small/dark.441-16-s.flac ! flacdec ! autoaudiosink
-      does not
diff --git a/docs/random/thomasvs/0.4.0 b/docs/random/thomasvs/0.4.0
deleted file mode 100644 (file)
index ddbc777..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-Set of 0.4.0 proposals
-
-* module versioning
-  - we need an agreement on how we are going to version the separate modules.
-    This needs to meet some requirements :
-    a) we shouldn't be forced to release all of the modules together 
-       every time (if the plugins have been updated, and still work against
-       a previous core, then only release plugins, for example)
-       We should start treating the different modules as separate projects
-       (albeit still closely tied of course)
-    b) it should be clear for other people what packages they need to download
-    c) major API breakage needs to be clear; we don't expect really old players
-       to keep working with really new cores.
-
-   - my idea (which others seemed to agree with) would be to let the micro
-     numbers run independently.  Only when the core API has changed to the
-     point that other modules are not compatible with them anymore
-     should we upgrade the minor version.
-     We can assume/assert that modules with the same minor number will be able
-     to work with each other.
-     
-    - Example schedule : 
-      * we release 0.4.0 versions of all of the modules
-      * plugins get updated a few times : 0.4.1 and 0.4.2
-      * core gets a new scheduler, doesn't affect other modules : 0.4.1
-      * gst-player gets rapid releases due to arik's recovery: 0.4.1-0.4.5
-      * core gets a major new update re: events : 0.5.0
-      * some days later, other modules have been updated to the new core
-        and the new core starts being useful to other people as well
-       
-* release practice
-  - we should have a simple way to cut releases; something that makes
-    the necessary adaptions to the source tree
-    This could also be a simple check list of things that need to pass
-  - cvs tarballs/packages should be easily distinguishable from pre-release
-    tarballs/packages and actual released ones.
-
-    my idea here would be :
-    a) releases are named as normal
-       e.g. gstreamer-0.4.0.tar.gz
-            gstreamer-0.4.0-1.i386.rpm
-
-    b) as soon as the release is made, we are back in "cvs" mode
-       i'd use a ".1" for a fourth version number for all cvs versions
-         so as soon as we release 0.4.0, I'd add a fourth ".1" version number.
-        this one would be used during the whole of the cvs period, no
-        reason to up this manually in between
-       The packages (rpms in any case, don't know about debs) would still
-       keep the date as the revision number like they have now, in order
-       to make it easy to work with snapshots.
-
-    c) when we are ready to release this module, I would go back to maintainer
-       mode, but keep the fourth version number and increase that for each cut.
-       So we'd stop developing the module, switch to maintainer mode, up the
-       version number to
-       gstreamer-0.4.0.2.tar.gz
-       and test that.
-
-     d) when we are happy with the precuts, we drop the fourth number and make
-        a release
-
-     Summary :
-     * all "official" released versions have sane versioning with three numbers
-     * all "cvs" versions are clearly recognizable by the fourth .1
-     * all "precuts" are also recognizable
-     * no tarballs will accidentally spill pretending to be real releases ;)
-     * upgrading rpm's all through this process is easy
-        
-* build code stuff duplicated between various modules
-  - how do we integrate these ? this pertains to stuff in autogen.sh,
-    duplicate stuff in configure.ac (which should probably be moved out to
-    custom .m4 files and yanked in), and maybe testing stuff
-  
-* what possible ways are there to build gstreamer ?
-  I would like to take stock of the combinations of deps possible to build
-  gstreamer.  While most people want only glib2, I think there is merit
-  in still making glib1 work and willing to put in the effort.  I just need
-  the possibilities mapped out once and for all ;) IMO the effort going into
-  making gstreamer build without libxml is the same as making it work with
-  older glib too.  I mean, as soon as you allow variation, it isn't that hard
-  to allow for more than one variation.  The bigger step is from zero to one.
-  
-  so, what are they ?
-  - glib1 & gtk1
-  - glib1 & gtk1 & libxml
-  - glib2 & libxml2
-  
-* media suite
-  - media files on the site should be renamed to simple uniform names
-  - and split up based on size
-  - described by features/content
-
-* when to branch in CVS ?
-
-* automatic build testing
-  - tinderbox ? useful ?
-  - small build scripts
-  
-* automatic functionality testing
-  - an md5sink would be useful to do this
-  - something automated is needed; it should check if you have the plugins
-    that are needed to test other plugins
-
-* media player
-
-* packaging
-  - dependency libs should be easily available
-
diff --git a/docs/random/thomasvs/TODO b/docs/random/thomasvs/TODO
deleted file mode 100644 (file)
index fce3d74..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-GSTREAMER
----------
-- gst-i18n-lib.h is included funnily from base classes and elements
diff --git a/docs/random/thomasvs/docreview b/docs/random/thomasvs/docreview
deleted file mode 100644 (file)
index 0fced3c..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-Documentation review
-
-* gstbuffer
-- What are the flags in GstBuffer ? used anywhere ? defined how ?
-
-
-* General
-- how can we define common terms and make them cros-ref'd ?
-  e.g. timestamps in buffer, do we say everywhere that they're in nanosec ?
-
-
-* Style
-- when in doubt, try to conform to GTK+ reference docs
-  (in the gtk-doc tarball, doc/style-guide.txt)
-- GtkMisc and GtkFontSelectionDialog are example templates.
-
-- in the arg clarification, use as much cross-reffing as possible.  Do it
-  only where it is useful in the explanation text.
-
-- examples
-
-  - use active form instead of imperative describing functions; we describe
-    what the function does.
-    good : creates a new buffer.
-    bad : create new buffer
-  - use singular for enum names; this makes it more natural to reference to
-    it in the API docs
-    good : GstBufferFlag
-    bad : GstBufferFlags
-  - in arg clarification, use a period and start with a small letter.
-    Call the object you work on "a" instead of "the".  Call the other objects
-    "the".
-    If the object in question is the return value, this means you call the
-    return value "a".  If the object in question is the first argument
-    of the call, you call this argument "a" and the rest "the".
-    good : @buf: a pointer to query.
-    bad : @buf: The pointer to query
diff --git a/docs/random/thomasvs/features b/docs/random/thomasvs/features
deleted file mode 100644 (file)
index 2d52339..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-Here's a list of features in GStreamer which plug-ins can make use of.
-For each feature we will try to find a few plug-ins that show a good way
-of implementing them.
-
-seeking
-caps negotiation
-timestamps
-clock interaction
-signals
-object argument handling
-chain-based
-loop-based
-request pads
-sometimes pads
-
diff --git a/docs/random/thomasvs/guadec-4 b/docs/random/thomasvs/guadec-4
deleted file mode 100644 (file)
index f7965dd..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-Presentation ideas for GUADEC 4 (thomasvs, April 8 2002)
-
-* use gst-editor to create pipelines that make a karaoke machine
-  in different steps and using different features
-
-1) pipeline 1: play the free software song by Richard Stallman
-2) pipeline 2: do the same but add a visualization plugin
-3) create a small video using actual RMS footage
-4) pipeline 3: play this video and the song together
-5) Stallman is a bit hard to understand.  We want text.
-   pipeline 4: use the subtitle reader to overlay text 
-   maybe also do a bouncing ball overlay !
-6) Stallman can't sing. Let's pitch-shift him.
-   this will need MIDI or dynparams to control a pitch shifter
-7) It sounds better, but still not quite there.  Replace him with a festival
-   voice doing the pitch shifting.
diff --git a/docs/random/thomasvs/pthread b/docs/random/thomasvs/pthread
deleted file mode 100644 (file)
index 8047c7c..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-Some notes on use of pthreads in GStreamer
-------------------------------------------
-
-First off, pthreads are HARD.  Remember that.
-
-1) How I learned to debug glibc and pthreads and add debug code to it.
-
-You have to trick your GStreamer test app in running against a modified
-glibc.
-
-I used Red Hat 7.3, downloaded the .src.rpm, installed it, applied the
-patches included, and ran
-  ./configure --prefix=/home/thomas/cvs --with-add-ons
-  make
-  make install
-
-After quite some time this left me with recompiled libc and libpthread
-libraries in /home/thomas/cvs/lib, as well as a new ld-linux.so.2
-
-Now you need to use this new ld-linux.so ld loader to run your app,
-preferably from inside of gdb so you can tell what's going on when it
-crashes.
-
-You can use ld-linux.so.2 to call your binaries:
-  ld-linux.so.2 .libs/thread1
-to run the thread1 program with the new glibc.
-
-If this is a GStreamer app, chances are it might not find some libraries
-it needs that you could safely use from /usr/lib (like, zlib and popt).
-
-Also, you want it to run in gdb, so this is my full line:
-
-LD_LIBRARY_PATH=/usr/lib /home/thomas/cvs/lib/ld-linux.so.2 \
-  /usr/bin/gdb .libs/thread1 
-
-At this point you can start adding debug code to the pthreads implementation
-in your glibc source tree.  Just change, re-run make install, and restart
-the test app in gdb.
-
-Helpful --gst-mask is 0x00200100 to get thread info and scheduling info
-(with mem alloc from cothreads)
-
-2) What GStreamer does with pthreads.
-
-Apps create a thread with gst_thread_new.  This just allocates the GstThread
-structure without actually doing much with it.
-
-When a thread goes from NULL to READY, the gst_thread_change_state function
-creates the actual pthread.
-  - we lock the thread->lock mutex
-  - we create attributes for the pthread
-    - by default the pthread is JOINABLE
-    - we ask the thread's scheduler for a preferred stack size and location
-      (FIXME: if the scheduler doesn't return one, what do we do ?)
-    - we create the pthread with the given attributes
-      - the pthread id is stored in thread->thread_id
-      - the created pthread starts executing gst_thread_main_loop (thread)
-    - the change_state function does a g_cond_wait
-      - this means it unlocks the mutex, waits until thread->cond is set
-        (which happens in gst_thread_main_loop), 
-        then relocks the mutex and resumes execution
-
-From the point of view of the created pthread, here's what happens.
-gst_thread_main_loop (thread) gets called
-  - the thread's mutex gets locked
-  - the thread's scheduler's policy gets examined
-  - the scheduler gets set up (invokes the scheduler object's setup method)
-    FIXME: what are the prereqs of this _setup method ?
-    - basic and fast scheduler both call do_cothread_context_init
-      - basic: this calls cothread_context_init
-        - cothread_context_init
-      - fast: this calls cothread_create (NULL, 0, NULL, NULL))
-
-(FINISHME) 
-(FOLDMEBACKTOREALDOCS)
diff --git a/docs/random/thomasvs/pwg b/docs/random/thomasvs/pwg
deleted file mode 100644 (file)
index c51b767..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-Stuff for the PWG
------------------
-
-* arguments
-
-  - how to add arguments
-    - create an identifier in the enum, starting with ARG_
-      example: ARG_RATE
-    - add the property by adding a
-      g_object_class_install_property line
-      FIXME: what is name/nick/blurb in the paramspec ?
-    - if the argument is readable, a block of code for it needs to be added
-      to the _get_property function.
-
-  - default value
-    - default value should be set in _init function
-    - default value can be specified in paramspec (but I don't think this
-      is used anywhere)
-
-
-  - things to check/possible problems
-    - do you have a _get_property function ?
-    - do you have a _set_property function ?
-    - do both have a default handler that handles invalid property ID's ?
-    - are the _get/_set_property handlers assigned to the class's struct ?
-    - do you have a g_object_class_install_property line for the argument ?
-    - are there restrictions on when your parameters can change ?
-      e.g. sample rate is not something that should be changed while PLAYING,
-           so it can only be changed in the NULL state
-    - did you use ARG_ ... consistently everywhere ?
-
-
-  - my own problems:
-    - how to set defaults and make the paramspec be right for them ?
-
-
-* audio
-  - explanation of difference of width and depth
-  - guidelines on how to implement this properly
diff --git a/docs/random/thomasvs/registry b/docs/random/thomasvs/registry
deleted file mode 100644 (file)
index 5287133..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-Reviewing the registry (thomasvs, April 8 2002)
-
-* added a --gst-registry flag to the core which allows any gst app
-  to specify a different registry for loading/saving
-
-  some stuff to do this went into gstreamer/gst/gstregistry.h
-
-* What location is used for writing ? (gst-register)
-
-  - if specified (using --gst-registry) then use the specified location
-  - if not specified :
-       - it can be written in the global location, do it there
-         (which should be sysconfdir/gstreamer) and reg.xml
-       - if not writable, then try ~/.gstreamer/reg.xml
-
-* What location is used for reading ? (gst-whatever)
-
-  - if specified (using --gst-registry) then use the specified location
-  - if not specified :
-    - right now :
-      if local exists, only read local
-      if not, read global
-
-    - TODO: try reading GST_CONFIG_DIR/reg.xml first
-      then try reading ~/.gstreamer/reg.xml
-      AND replace every namespace collision with the new one
-
-* actual variables stuff (gstregistry.c)
-  - use gst_registry_write_get to get a GstRegistryWrite struct back 
-    listing the right location of dir, file and tmp file
-  - use gst_registry_read_get to get a GstRegistryRead struct back
-    listing the path of global and local file to read
-
-* gst-register signals it's going to write to the registry (causing it to
-  be unlinked before the read in post_init ()) by setting a global variable,
-  _gst_init_write_registry
diff --git a/docs/random/types b/docs/random/types
deleted file mode 100644 (file)
index eac3012..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-GstTypes exist to try to make sure data eveyrone is talking about the
-right kind of data.  They aid quite a bit in autoplugging, in fact make it
-possible.  Each well-formed type includes a function (typefind) that will
-take one or more buffers and determine whether or not it is indeed a
-stream of that type, and possible a metadata to go with it.  It may
-provide related metadata structure IDs (and must if it provides metadata
-from the typefind function).
-
-Because multiple elements and plugins are very likely to be using the same
-types, the process of creating/finding types is designed to be done with a
-single function call.  All operations on GstTypes occur via their guint16
-ID numbers, with the GstType structure "private" to the GST library.  A
-plugin wishing to use a give type would contain a static struct of type
-GstTypeFactory, which lists the MIME type, possible extensions (which may
-overlap the mime-types file), a typefind function, and any other cruft I
-decide to add.
-
-A plugin init function would take this typefactory and hand it to the
-gst_type_new() (FIXME: badly named) function, which would first search for
-that same MIME type in the current list.  If it found one, it would
-compare the two to see if the new one is "better".  Better is defined as
-having more extensions (to be merged) or a typefind function verses none.
-
-The point of returning an existing MIME type is a result of the goal of
-unifying types enough to guarantee that, for instance, all MP3 decoders
-will work interchangeably.  If MP3 decoder A says "MIME type 'audio/mpeg'
-with extensions 'mpeg3'" and decoder B says "MIME type 'audio/mpeg' with
-extensions 'mp3'", we don't want to have two types defined, possibly with
-two typefind functions. If we did, it's not obvious which of the two would
-be tried first (luck) and if both would really identify streams as mp3
-correctly in all cases.  And whichever wins, we're stuck using the
-associated decoder to play that stream.  We lose the choice between any
-valid mp3 decoder, and thus the whole point of the type system.
diff --git a/docs/random/types2 b/docs/random/types2
deleted file mode 100644 (file)
index d2515e5..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-OUTDATED
---------
-
-
-1. Introduction
----------------
-
-The type system is used to attach meaning to the bytes in a GstBuffer.
-A plugin can decide to add metadata to the GstBuffer, this metadata
-will carry an associated typeid.
-
-Types are also used by the plugins to expose the type of their pads to
-the type system.
-
-Types are essential for autoplugging. 
-
-We will explain the inner workings of the type system in this document, as
-well as the API used in the plugins.
-
-
-2. Type properties
-------------------
-
-a) identification of the type
-
-  Types are identified by one or more MIME types. 
-
-b) detection of types
-
-  The type of any given GstBuffer can be detected using
-
-    - a typefind function: a function that will inspect the bytes
-           in the buffer and return a gboolean indicating the
-          buffer is of the given type.
-
-    - a template for the bytes/bits in the data that must be
-           satisfied in order for the GstBuffer to be of the given 
-          type.
-  
-    - other properties that act more like a hint like:
-           the extension of the source filename.
-          the URI of the source.
-
-
-3. Type registration
---------------------
-
-a) the core libraries will create to types:
-
-   video/raw image/raw
-   audio/raw
-
-b) all other types will be provided by the plugins
-
-before a type can become available to other plugins, the plugin
-has to register the type. 
-
-The system will keep a directed graph of the types and the plugins
-that operate on them.
-
-example:
-
-                     video/mpeg
-                         ! 
-                    mpeg1parse
-                     /     \
-             video/mpeg1   audio/mp3 -----\
-             !        !           \        !
-        mpeg_play   mpeg2dec      mpg123   xing  ...
-              \        /              \     /                  
-              video/raw              audio/raw-----\
-             !      !                   !         !
-        videosink   SDLsink           audiosink    alsasink ...
-                       
-
-The system can find the needed plugins to convert video/mpeg to
-audio/raw using this graph.
-
-
-4. type equivalence
--------------------
-
-some types can have the same meaning for example:
-
-  audio/mp3 and audio/mpeg 
-
-or
-
-  video/raw and image/raw
-  
-
-a plugin that exposes its output type as audio/mpeg and another plugins
-with input type audio/mp3 can be connected. The system has to know about
-the equivalence of both types, even it they have a different mime type.
-
-5. type hierarchy
------------------
-
-some plugins can output a specific subset of an already existing type.
-
-example:
-
-  mp3parse inputs audio/mp3 and packs the stream into mp3 audio frames
-  with mime type: audio/mp3-frame
-
-  mpg123 only accepts audio/mp3-frame but not audio/mp3.
-
-  another mp3 decoder (libmpg123) can accept audio/mp3 (and thus also 
-  audio/mp3-frame)
-
-  it must be possible to connect both libmpg123 and mpg123 to the mp3parse
-  element.
-  it must not be possible to connect mpg123 to an element that outputs only
-  audio/mp3 but not audio/mp3-frame.
-
-
-We say that audio/mp3-frame is a more specific subset of type audio/mp3.
-
-we can create a type hierarchy:
-
-          audio/mp3
-         /        \
-  audio/mp3-frame  audio/mp3-layer12
-                     /        \
-          audio/mp3-layer1    audio/mp3-layer2
-
-
-6. multi-type pads
-------------------
-
-certain plugins might accept multiple non equivalent types in one of their
-input pads. Consequently a plugin might output non equivalent types in
-its output pad.
-
-It must therefore be possible to specify multiple types for a pad.
-
-example:
-
-  mpegdemux may be able to demux both MPEG1 and MPEG2 system streams.
-  we show the type hierarchy of the video/mpeg as follows:
-
-                          video/mpeg
-                        /        \
-               video/mpeg1         video/mpeg2 ---------------\
-              /    \                    /    \               !
-      mpeg1-system*  mpeg1-video    mpeg2-ts   mpeg2-ps*    mpeg2-video
-
-
-  the mpegdemux element might specify the type of the input pad as 
-  one of video/mpeg1-system and video/mpeg2-ts
-
-
-
-7. definition of types
-----------------------
-
-A plugin will provide the following information to the type system:
-
- - a mime type string describing the hierarchy and where the types
-   they provide are located in that hierarchy.
-
- - typefind functions for some of the types.
-
- - extensions for some of the types
-
-We will propose a syntax to define the type hierarchy
-
-a) equivalent types :
-
-   separated with a | sign
-
-   ( audio/mp3 | audio/mpeg )
-
-b) type hierarchy :
-
-   in braces:
-
-   ( audio/mp3 ( audio/mp3-frame))
-
-c) multi-type pads
-
-  ( mpegdemux ( video/mpeg1-system + video/mpeg2-ps) )
-
-  the pad will have type mpegdemux which is the parent for
-  type video/mpeg1-system or video/mpeg2-ps
-
-                  mpegdemux
-                 /       \
- video/mpeg1-system      video/mpeg2-ps
-   
-
-   
-once the type hierarchy has been registered, the typeid of each
-element can be obtained with:
-
-  guint16 gst_type_find_by_mime (gchar *mime)
-
-extra typefind functions and/or extensions can be added to the 
-typeid afterwards.
-
-
-8. type matching
-----------------
-
-The more specific typefind functions, the functions associated with
-types in the leaf nodes, are tried first.
-
-when a specific type has been found ex. video/mpeg1-system elements
-that can handle this type or one of its parents are selected:
-
-  mpegdemux:                     mpeg1parse:                    supermpegdecoder:
-
-    video/mpeg                       video/mpeg                   video/mpeg
-     !                                  !
-    mpegdemux                        video/mpeg1-system
-     !                                 
-    video/mpeg1-system         
-
-In the above case, also the super mpeg element is selected because it stated
-that it can handle all sorts of video/mpeg data. 
-
-
-example 2:
-
-   suppose the typefind functions finds an mp3 stream, following elements
-   are selected:
-
-       libmpg123              mp3parse:
-
-       audio/mp3              audio/mp3
-   mpg123 is not selected because its pad type is too specific (audio/mp3-frame):
-
-       mpg123
-
-       audio/mp3
-         !
-       audio/mp3-frame
-
-   if the typefind would find a mp3-frame type, all three objects would be selected.
-
-
-8. consideration
-----------------
-
-It is clear that clear indications have to be given to the type hierarchy,
-especially for the top nodes.
-
-The more specific an element is in its mime type specification, the more flexible 
-and extendible the plugin system can be.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-     
-
diff --git a/docs/random/types3 b/docs/random/types3
deleted file mode 100644 (file)
index 4c95860..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-SOMEWHAT OUTDATED, design still holds though
---------------------------------------------
-
-
-1. Introduction
----------------
-
-The type system is used to attach meaning to the bytes in a GstBuffer.
-A plugin can decide to add metadata to the GstBuffer, this metadata
-will carry an associated typeid.
-
-Types are also used by the plugins to expose the type of their pads to
-the type system.
-
-Types are essential for autoplugging. 
-
-We will explain the inner workings of the type system in this document, as
-well as the API used in the plugins.
-
-2. major types
---------------
-
-major types are identified with mime types and are used to denote a 
-family of types.
-
-More specific information about the type is given using properties. This
-will allow us to be very specific without creating a lot of mime types.
-
-3. API
-------
-
-Both a simple array based specification and a real API will be
-provided to build the capabilities. 
-
-In the array based approach, we basically build an array of pointers.
-Some macros will be available to specify ranges, boolean values, lists
-and id's. (not sure if this can be done)
-
-#define GST_TYPE_INT_RANGE(a, b) GST_TYPE_RANGE,(a),(b)
-#define GST_TYPE_BOOLEAN(a) GST_TYPE_BOOLEAN,(a)
-#define GST_TYPE_LIST(a...) GST_TYPE_LIST,(##a),NULL
-
-for example:
-
-  static GstTypeCapsFactory mpg123_sink_caps[] = {
-    "audio/mp3",
-    "layer",   GST_TYPE_INT_RANGE (1, 3),
-    "bitrate", GST_TYPE_INT_RANGE (8, 320),
-    "framed",  GST_TYPE_BOOLEAN (true),
-    NULL
-  };
-
-will expand to the array:
-
-  static GstTypeCapsFactory mpg123_sink_caps[] = {
-    "audio/mp3",
-    "layer",   GST_TYPE_RANGE,1,3,
-    "bitrate", GST_TYPE_RANGE,8,320,
-    "famed",   GST_TYPE_BOOLEAN,true,
-    NULL,
-  };
-
-when we register the caps factory, the strings will be converted
-into GQuarks and be stored into a GData Keyed Data List.
-
-This will result in a GstTypeCaps structure:
-
-struct _GstTypeCaps {
-  guint16 id;                 // if of the major type 
-
-  GData *properties;
-}
-
-4. example using arrays
------------------------
-
-mpg123: an mpeg audio decoder.
-
-  // a factory for the major type we use
-  static GstTypeFactory mp3factory = {
-    "audio/mp3",               // major type
-    ".mp3 .mp2 .mp1 .mpga",    // extensions
-    NULL,                      // typefind function
-  };
-
-  // capabilities of the sink pad
-  static GstTypeCapsFactory mpg123_sink_caps[] = {
-    "audio/mp3",
-    "layer",   GST_TYPE_INT_RANGE (1, 3),
-    "bitrate", GST_TYPE_INT_RANGE (8, 320),
-    "framed",  GST_TYPE_BOOLEAN (true),
-    NULL
-  };
-
-  // capabilities of the source pad
-  static GstTypeCapsFactory mpg123_src_caps[] = {
-    "audio/raw",
-    "rate",    GST_TYPE_INT_RANGE (8000, 48000),
-    "channels",        GST_TYPE_INT_RANGE (1, 2),
-    NULL
-  };
-
-  static GstTypeCaps *sinkcaps = NULL, *rawcaps = NULL;
-
-  static gst_mpg123_init (GstMpg123 *mpg123) 
-  {
-    mpg123->sinpad = gst_pad_new ("sink", GST_PAD_SINK);
-    gst_element_add_pad (GST_ELEMENT (mpg123), mpg123->sinkpad);
-    gst_pad_set_caps (mpg123->sinkpad, sinkcaps);
-
-    ...
-  }
-
-  GstPlugin *plugin_init (GModule *module)
-  {
-    ...
-    plugin = gst_plugin_new ("mpg123");
-   
-    gst_plugin_add_type_factory (plugin, mp3factory);
-  
-    ...
-    sinkcaps = gst_type_register_caps (mpg123_sink_caps, NULL);
-    rawcaps  = gst_type_register_caps (mpg123_src_caps, NULL);
-    ...
-  }
-
-mpeg2dec: an mpeg video decoder that can do mpeg1 and mpeg2.
-
-  static GstTypeFactory mpegfactory = {
-    "video/mpeg",              // major type
-    ".mpg .mpeg",              // extensions
-    NULL,                      // typefind function
-  };
-
-  static GstTypeCapsFactory mpeg2dec_sink_caps[] = {
-    "video/mpeg",
-    "mpegtype", GST_TYPE_LIST (
-                        GST_TYPE_INT(1),
-                        GST_TYPE_INT(2),
-                       ),
-    NULL
-  };
-
-  static GstTypeCapsFactory mpeg2dec_src_caps[] = {
-    "video/raw",
-    "fourcc",  GST_TYPE_LIST (
-                        GST_TYPE_INT32 (0x32315659), 
-                       GST_TYPE_INT32 (0x32...), 
-                       ),
-    "width",   GST_TYPE_INT_RANGE (16, 4096),
-    "height",  GST_TYPE_INT_RANGE (16, 4096),
-    NULL
-  };
-
-  static GstTypeCaps *sinkcaps = NULL, *rawcaps = NULL;
-
-  GstPlugin *plugin_init (GModule *module)
-  {
-    ...
-    plugin = gst_plugin_new ("mpeg2dec");
-   
-    ...
-    sinkcaps = gst_type_register_caps (mpeg2dec_sink_caps, NULL);
-    rawcaps  = gst_type_register_caps (mpeg2dec_src_caps, NULL);
-    ...
-  }
-
-
-5. capabilty compatibility
---------------------------
-
-Two pads are compatible if:
-
-- The major types are equal
-- range of the sink pad contains the range of the src pad
-
diff --git a/docs/random/use-cases-0.11.txt b/docs/random/use-cases-0.11.txt
deleted file mode 100644 (file)
index 6ba1d4d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-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/usecases b/docs/random/usecases
deleted file mode 100644 (file)
index 5fa895a..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-Use cases for audio applications
---------------------------------
-
-ANALYSIS
-========
-
-* find start and end  -x dB boundary
-
-* find overall volume for complete track (peak/RMS/average)
-
-* do level-triggered playback
-
-CUE FILES
-=========
-
-Given a long audio file and a .cue file:
-- an element should be able to read an audio input stream and a cue input
-  stream and send new-media events based on the .cue file information
-- a audiocdsink should be able to record this stream straight to disk
-
-Use cases for core functionality
---------------------------------
-
-THREADS
-=======
-
-* { sinesrc } ! { queue ! osssink }
-  - play thread
-  - pause input thread
-  - output thread should keep playing as long as queue not empty
-  - play input thread again
-  - no gaps should be heard
-
-Use cases for video applications
---------------------------------
-
-THUMBNAILING
-============
-- load file
-- figure out if it's playable
-- ask length of file
-- seek to middle
-- snapshot one frame
-- save to disk
diff --git a/docs/random/vis-transform b/docs/random/vis-transform
deleted file mode 100644 (file)
index aa80a53..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-Duh, an 'easy' way to replicate Giess's behavior:
-
-For each frame, you have to mutate it by a transform matrix.  This is
-easy, thought not cheap.  First you precalculate the transform matrix how
-you want it, based on whatever rotations or whatever you want.
-
-The data stored in each spot on the matrix tells you how to transform a
-single pixel.  The simple case is dx,dy, where both are relatively small.
-The probably ought to be a byte in any case, so you can scale the
-transform matrix on slow machines.  A more complex case is some trick
-whereby a single pixel ends up splattered in several places.  Idea below.
-
-The matrix consists of some number of 8bit arrays of the same size as the
-image.  They'd probably be line-interleaved or better to help with cache
-effects (which are VERY serious here).  Each channel represents some
-aspect of the transform. The first two would likely be dx and dy, the
-third might be a multiplier if that wasn't done statically.
-
-The idea: any number of transform sets could be applied, given available
-processing power.  Just set the static scalar or the multiplier matrices
-so you don't completely swamp the output pixels.
-
-Note that this is fastest in 8-bit, but theoretically could be applied to
-32 bit.  15 and 16 are hard, since you can't easily apply the multipliers
-unless they're 1/2^n, and even then it's significantly heavier (you'd have
-to mask the top n bits of each color out).
-
-This SCREAMS for MMX, in case you haven't figured it out yet.
-Unfortunately, MMX is only directly useful for the scalar matrix, unless
-you do a trick where all the pixels in that fit in 64 bits (8 8bit, 4
-16bit, or 2 32bit) are always moved in a group.  This is very possible,
-and might be a significant perf increase by being able to use MMX all the
-way through.  Otherwise you have to place each pixel by extracting the MMX
-stuff back into normal registers, and that just plain sucks.
-
-A pseudo-C implementation:
-
------ BEGIN -----
-gint x,y;                              /* image x and y size */
-guchar old_image[x][y];                        /* original image */
-guchar new_image[x][y];                        /* new image */
-gchar x_xform[x][y];                   /* dx matrix */
-gchar y_xform[x][y];                   /* dy matrix */
-guchar s_xform[x][y];                  /* intensity scalar matrix */
-guchar scalar;                         /* global scalar */
-
-gint i,j;                              /* indixes */
-gulong p;                              /* pixel value in question */
-guchar u,v,w;                          /* modifier variables */
-
-/* clear the new image, we don't want anything getting in the way */
-/* NOT NECESSARILY A GOOD THING, THOUGH */
-memset(new_image,0,x*y);
-
-/* loop through all the lines in the image */
-for (j=0;j<y;j++) {
-  /* loop through all the pixels in the line */
-  for (i=0;i<x;i++) {
-    p = old_image[i][j];
-    u = x_xform[i][j];
-    v = y_xform[i][j];
-    w = s_xform[i][j];
-    new_image[i+u][j+v] = (guchar)((p<<14) / (w * scalar));
-  }
-}
------ END -----
-
-Note that the above really, *REALLY* sucks performance-wise.  Throw it a
-80x60 image and it'll swamp my poor laptop.  Also note that I simply set
-the pixel value, not merge it.  That means you'd better be sure your
-transform matrix doesn't have overlapping destinations.
-
-Other notes about the above code: x_xform and y_xform are signed chars,
-which means pixels can move in all directions.  The intensity matrix is
-unsigned, with a range from 0 to 255, so is the global scalar.  Note the
-shift of 14bits (2 * 7bits), then divide by each.  That means identity for
-both scalars is at 128.  The FP range of each is thus 0.0 to 2.0.  Very
-handy.
diff --git a/docs/random/wingo/porting-plugins-to-0.9 b/docs/random/wingo/porting-plugins-to-0.9
deleted file mode 100644 (file)
index dc56f73..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
--*- outline -*-
-
-
-Some collected notes porting plugins to GStreamer 0.9.
-
-
-* General notes
-
-Consider using the base classes. There are base classes for sources,
-sinks, and "transformers", which are plugins that have the same caps on
-their source and sink sides.
-
-These base classes offer interfaces that are much more appropriate to
-the function of specific plugins than the general GstElement interface.
-
-
-* Functions that changed
-
-** gst_pad_use_explicit_caps
-** gst_pad_set_explicit_caps
-
-Not needed; just set the caps on the first buffer you push out.
-
-** gst_element_set_loop_function
-
-Use gst_pad_set_loop_function. Note that loop-based elements participate
-more in the scheduling process in 0.9, so you'll need to add hooks to
-the activate function to start up a task.
-
-refcounting:
-_get_ accessors
-GValue, GstObject, and refcounts (arrrrgh)
\ No newline at end of file
diff --git a/docs/random/wingo/threadsafe-properties b/docs/random/wingo/threadsafe-properties
deleted file mode 100644 (file)
index 7e9306f..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
--*- Mode: text -*-
-
-Sometimes it's difficult to use GStreamer in real applications where the GUI and
-the GStreamer pipeline are in different threads. You have to somehow make sure
-that the object is not modifying its properties while you get and set them. This
-document is a brief outline of a potential fix to this issue.
-
-* When is it safe to get or set properties?
-
-Well, it is only safe to do so when other threads are not accessing an object.
-So, from the main thread, it is only safe to query or modify properties on an
-object when it is not in the RUNNING state, because when it is RUNNING its
-properties are potentially changing in the thread of execution.
-
-The only place that it is safe to get or set properties while in the RUNNING
-state is from within the thread of execution. Thus, something within the
-iteration loop of the thread must check to see if there are pending property
-changes or queries. There are two places this could be done, from within
-gstthread itself and from within the scheduler. Doing it from gstthread sounds
-like a good idea because it keeps more code out of the scheduler, but is also
-bad in a way because it requires a gstthread-specific api to proxy prop_set and
-prop_get. Setting it in the scheduler sounds good because of its finer
-granularity, but might be bad because it would clutter the scheduler a bit more.
-
-I propose to go with the scheduler-based solution based on system response time
-and out of potentials for integration with gst_clock_wait.
-
-* Implementation
-
-We do want to preserve some measure of generality, however. Considering that
-more threadsafety issues could pop up in the future, it would be nice to have
-one function to call from the scheduler, in the interests of code
-simplification. This function will be present in some elements and not in
-others, and will be modified at run time, so we will make it a function pointer
-within the GstElement struct.
-
-struct _GstElement {
-  ...
-  void (*pre_run_func) (GstElement *);
-  void (*post_run_func) (GstElement *);
-}
-
-Only the managing bin of an element is allowed to set that function, because
-presumably that bin would know something about how to schedule the element.
-Then, in the scheduler, before we call chain functions and before we switch into
-loop functions:
-
-if (element->pre_run_func)
-  element->pre_run_func (element);
-
-Then, to get or set properties, we use the new functions gst_element_get or
-gst_element_set. _set would add the property name and a gvalue onto a queue
-(probably a GAsyncQueue). Then the pre_run_func would go ahead and set the
-properties. _get is a little more tricky; _set doesn't hardly block at all,
-although it's not instantaneous. With _get though, you really don't know what
-the properties are until you query them. The best thing would be to connect to
-the ::notify signal, which executes within the thread of interest. However, say
-you really want to use _get. Hmm. I think that it would have to block. On what?
-Well, probably on an element's mutex. So it seems we might need a
-post_run_func too, to unlock the mutex. We can use the GstObject lock for this.
-
-But we need a little more. How do we know whether or not just calling
-g_object_get/set is ok? I'm thinking this whole prop set/get proxy thing should
-not be abstracted away, that it should be contained in gstelement.c. There are
-more kinds of bins that need threadsafety than just gstthread (I'm thinking
-about jack here). So, we can add on a GAsyncQueue *prop_set_queue; to the
-GstElement struct, and only initialize it in certain managing bins. Then, we can
-set a flag on gstelement, GST_ELEMENT_USE_THREADSAFE_PROPERTIES. If this flag is
-set (by the managing bin), do all this complicated mess; otherwise use the
-gobject native functionality.
-
-So, this is the plan. We'll see how the implementation goes. This should make MT
-gst programming much easier.
-
-wingo.
-25 May 2002.
diff --git a/docs/random/wingo/without-factories b/docs/random/wingo/without-factories
deleted file mode 100644 (file)
index 07e3885..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
--*- outline -*-
-
-* Creating Elements Without Factories
-
-** The purpose of factories
-
-On a typical GStreamer system, there are approximately 6.022*10^23
-plugins. GStreamer knows about all of them because of the registry. The
-goal is to avoid initializing each one of them, when maybe for your
-application you only need one or two.
-
-The problem becomes, how do you create an instance of the plugin? The
-normal way to instantiate a class is via g_object_new (TYPE, ARGS...).
-In the case that the plugin isn't loaded, you don't know its type, and
-can't even get it from the type name.
-
-Element factories exist to solve this problem by associating names (like
-"sinesrc" or "identity") with certain types that are provided by the
-plugin. Then when the user asks for "sinesrc", the appropriate plugin is
-loaded, its types are initialized, and then gst_element_factory_create
-creates the object for you.
-
-** Why not factories?
-
-To review, factories (1) allow plugins to remain unloaded if not
-necessary, and (2) make it easy to create elements.
-
-If you are writing an application that has custom elements (as is the
-case with most serious applications), you will probably have the plugin
-loaded up already, and you will have access to the type of the element.
-To muck about creating a plugin for the app, registering the element
-with the plugin, and then creating it with the element factory API
-actually takes more work than the normal way.
-
-** g_object_new
-
-So you want to avoid factories. To create objects with a simple
-g_object_new call is our strategy. However, to preserve the same
-semantics as gst_element_factory_create, we need to know what else is
-needed to initialize a GStreamer element.
-
-The other things that gst_element_factory_create does are as follows:
-
-*** Sets the ->elementfactory member on the element class
-
-Note that anything trying to get the factory won't work (e.g.
-gst_element_get_factory). Thankfully this is less of a problem after the
-0.7 plugin system changes.
-
-*** Initializes the name of the element
-
-To do this ourselves, we either call gst_object_set_name, or when we
-set the "name" property when creating the object.
-
-** Summary
-
-To create a GStreamer element when you know the type, you can just use
-
-g_object_new (get_type_of_my_element (),
-              "name", the_name_you_want_possibly_null,
-              ... any other properties ...
-              NULL);
index 61edb75..b6d8dc8 100644 (file)
@@ -2,7 +2,7 @@ Autoplugger V2
 ==============
 
 The current autoplugger as described in autoplug1 has some
-serious shortcommings:
+serious shortcomings:
 
  - it is embedded in GstPipeline and cannot be used with a 
    generic interface. A lot of complexity is inside the 
index 556fbea..eb7170a 100644 (file)
@@ -54,7 +54,7 @@ EOS denial: An element can deny an EOS call by returning FALSE on the
 ---------------------
 
 EOS is currently implemented by selectively disabling scheduling of
-the chains. This procedure continues untill a bin/thread has no more
+the chains. This procedure continues until a bin/thread has no more
 chains left to schedule, at which point it will fire the EOS signal.
 
 A gboolean was added to the chain structure to indicate if this chain
index 1560dc5..361290c 100644 (file)
@@ -101,7 +101,7 @@ case 3)
 
   after the queues have sent out their last buffer, they calls eos on their
   src pads.
-  the parent already has the two queues in the EOS provider list so they dont
+  the parent already has the two queues in the EOS provider list so they don't
   get added twice.
   the two queues perform gst_pad_eos () on their pads when the queue is empty,
   the parent removes the EOS providers from its list, when the list is empty,
index cacbac4..ec4099d 100644 (file)
@@ -33,7 +33,7 @@ case 1)
   all the pads in i1 and fsk1 to EOS too. none of these elements
   override the default behaviour so gst_pad_set_eos returns TRUE.
 
-  fakesrc signals EOS.  since an element in chain1 has signales
+  fakesrc signals EOS.  since an element in chain1 has signals
   EOS, chain1 becomes EOS. All the elements in the chain are set
   to the READY state and the chain is not scheduled anymore because
   its EOS flag is on.
index c6f3a2d..cfffdea 100644 (file)
@@ -50,7 +50,7 @@ and then call the do_link function on the peer pad. The do_link function can onl
 accept or refuse the provided caps.
 
 For autopluggers it is important to know when the pad is ready to start the negotiation.
-It is also inportant to know when the negotiation failed and it must be possible to 
+It is also important to know when the negotiation failed and it must be possible to 
 restart the negotiation with another element. This functionality will be provided
 with signals.
 
index 6f209c4..1a7ce85 100644 (file)
@@ -31,9 +31,9 @@ Network Transparent elements
      in parallel with the datastream so the event path should
      use a different connection.
      
-4) GStreamer deamon
+4) GStreamer daemon
 
-   - each host has to run a deamon that listens for
+   - each host has to run a daemon that listens for
      commands and creates elements/pipelines and performs all
      operations on the real pipeline.
 
index dfa92f8..5127ff4 100644 (file)
@@ -205,7 +205,7 @@ always performed relative to 0, so if we convert track2 to bytes, we
 always get the number of bytes from track0->track2.
 
 If we want to get the number of bytes of one particular track, we have
-to substract two convert values. Look at the following figure to understand
+to subtract two convert values. Look at the following figure to understand
 this. The --- defines the region we want to convert.
 
 
@@ -240,7 +240,7 @@ stream (bitrate == byterate * 8). So, we do:
 
 ..and we get the number of bytes this plugin takes in each second.
 Again, note that this value is relative to 0, you can get an average
-of a specific period by using the same substract trick as above.
+of a specific period by using the same subtract trick as above.
 
 
 Element Properties
index 516292b..83a9f7b 100644 (file)
    -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  autoconvert:   autoconvert: Select converter based on caps
+   -bad  autoconvert:   autovideoconvert: Select color space converter based on caps
    -bad  avcsrc:        avcsrc:
 
          bluetooth:     a2dpsink: Bluetooth A2DP sink
index d4132c5..7b544f8 100644 (file)
@@ -473,7 +473,7 @@ without connections are removed from the group.
 
 It is possible that when an element still has a connection with some other
 element in the group, the group has to be split up anyway. This can happen
-in fakesrc ! indentity ! identity ! fakesink when we break the connection
+in fakesrc ! identity ! identity ! fakesink when we break the connection
 between the two identity elements. We have to be careful here in the cothread
 case that we don't take away the running cothread from under the elements.
 In the non-cothread case we can just move the elements to another new group.
diff --git a/docs/random/zaheerm/dvb-interface.txt b/docs/random/zaheerm/dvb-interface.txt
deleted file mode 100644 (file)
index 1cc479b..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-Interface:
-- type (string like caps) channels/x-mpegts-pat
-- GstStructure to describe the what the list is, name, where from etc. (how many entries you can select, if multiple tried, first one picked)
-- method to list entries (channels)
-- method to get current entries
-- method to set list of entries
-- each entry contains an id (32 bit int say), GstStructure (with additional stuff)
-
-signals to say when entry list changes
-        to say when current entry changes
-
-So for a transport stream, this interface would be exported and it could contain a list of interfaces...eg it would export PAT, and PAT list would contain interfaces in the GstStructure for the PMT.
-
-dvbsrc -> list of frequencies
-flutsdemux -> list of programs (PAT) and list of PMT streams per program
-
-get list of frequencies, select frequency
-get list of programs, select programs
-get list of streams, select streams
-
-only give program details in PAT list, when we have seen the PMT for that program.
-
-possibly another interface to select multiple list interfaces from an element. (interface selector interface)
-
---
-other option is to tag
diff --git a/docs/version.entities.in b/docs/version.entities.in
deleted file mode 100644 (file)
index be8ed4b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<!ENTITY GST_API_VERSION "@GST_API_VERSION@">
-<!ENTITY GST_VERSION "@PACKAGE_VERSION@">
-<!ENTITY GST_PLUGINS_DIR "@PLUGINDIR@">
diff --git a/docs/version.in b/docs/version.in
new file mode 100644 (file)
index 0000000..efa22cd
--- /dev/null
@@ -0,0 +1 @@
+@GST_API_VERSION@
diff --git a/gst/.gitignore b/gst/.gitignore
deleted file mode 100644 (file)
index 606da2b..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-Makefile
-Makefile.in
-*.o
-*.lo
-*.la
-.deps
-.libs
-gstversion.h
-gstmarshal.c
-gstmarshal.h
-gstenumtypes.h
-gstenumtypes.c
-gstconfig.h
-*.bb
-*.bbg
-*.da
-*.def
-*.gcno
-*.gcov
-*.gcov.out
diff --git a/gst/Makefile.am b/gst/Makefile.am
deleted file mode 100644 (file)
index 6910554..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-lib_LTLIBRARIES = libgstreamer-@GST_API_VERSION@.la
-
-if GST_DISABLE_REGISTRY
-GST_REGISTRY_SRC =
-else
-GST_REGISTRY_SRC = gstregistrybinary.c
-endif
-
-if GST_DISABLE_PARSE
-SUBDIRS_PARSE =
-GST_PARSE_LA =
-else
-SUBDIRS_PARSE = parse
-GST_PARSE_LA = parse/libgstparse.la
-endif
-
-if GST_DISABLE_PLUGIN
-GST_PLUGIN_SRC =
-else
-GST_PLUGIN_SRC = gstplugin.c
-endif
-
-if !GST_DISABLE_GST_DEBUG
-SUBDIRS_PRINTF = printf
-GST_PRINTF_LA = printf/libgstprintf.la
-else
-SUBDIRS_PRINTF =
-GST_PRINTF_LA =
-endif
-
-SUBDIRS = $(SUBDIRS_PARSE) $(SUBDIRS_PRINTF)
-
-DIST_SUBDIRS = parse printf
-
-# make variables for all generated source and header files to make the
-# distinction clear
-
-built_headers_configure = gstversion.h gstconfig.h
-built_header_make = gstenumtypes.h
-built_source_make = gstenumtypes.c
-
-EXTRA_libgstreamer_@GST_API_VERSION@_la_SOURCES = \
-       gstregistrybinary.c
-
-
-# temporarily not used
-#      glib-compat.c
-
-libgstreamer_@GST_API_VERSION@_la_SOURCES = \
-       gst.c                   \
-       gstobject.c             \
-       gstallocator.c          \
-       gstbin.c                \
-       gstbuffer.c             \
-       gstbufferlist.c         \
-       gstbufferpool.c         \
-       gstbus.c                \
-       gstcaps.c               \
-       gstcapsfeatures.c       \
-       gstchildproxy.c         \
-       gstclock.c              \
-       gstcontext.c \
-       gstcontrolbinding.c \
-       gstcontrolsource.c \
-       gstdatetime.c           \
-       gstdebugutils.c         \
-       gstdevice.c             \
-       gstdevicemonitor.c      \
-       gstdeviceprovider.c     \
-       gstdeviceproviderfactory.c \
-       gstdynamictypefactory.c \
-       gstelement.c            \
-       gstelementfactory.c     \
-       gsterror.c              \
-       gstevent.c              \
-       gstformat.c             \
-       gstghostpad.c           \
-       gstinfo.c               \
-       gstiterator.c           \
-       gstatomicqueue.c        \
-       gstmessage.c            \
-       gstmeta.c               \
-       gstmemory.c             \
-       gstminiobject.c         \
-       gstpad.c                \
-       gstpadtemplate.c        \
-       gstparamspecs.c         \
-       gstpipeline.c           \
-       gstplugin.c             \
-       gstpluginfeature.c      \
-       gstpluginloader.c       \
-       gstpoll.c               \
-       gstpreset.c             \
-       gstprotection.c         \
-       gstquark.c              \
-       gstquery.c              \
-       gstregistry.c           \
-       gstregistrychunks.c     \
-       gstpromise.c    \
-       gstsample.c             \
-       gstsegment.c            \
-       gststreamcollection.c   \
-       gststreams.c            \
-       gststructure.c          \
-       gstsystemclock.c        \
-       gsttaglist.c            \
-       gsttagsetter.c          \
-       gsttask.c               \
-       gsttaskpool.c           \
-       gsttoc.c                \
-       gsttocsetter.c          \
-       gsttracer.c             \
-       gsttracerfactory.c      \
-       gsttracerrecord.c               \
-       gsttracerutils.c                \
-       gsttypefind.c           \
-       gsttypefindfactory.c    \
-       gsturi.c                \
-       gstutils.c              \
-       gstvalue.c              \
-       gstparse.c              \
-       $(GST_REGISTRY_SRC)
-
-# do not put files in the distribution that are generated
-nodist_libgstreamer_@GST_API_VERSION@_la_SOURCES = $(built_source_make)
-
-# BUILT_SOURCES are built on make all/check/install before all other targets
-BUILT_SOURCES = \
-        $(built_headers_configure)     \
-        $(built_header_make)           \
-        $(built_source_make)
-# CLEANFILES is for files generated by make
-CLEANFILES = $(built_header_make) $(built_source_make) $(as_dll_cleanfiles) *.gcno *.gcda *.gcov *.gcov.out
-# DISTCLEANFILES is for files generated by configure
-DISTCLEANFILES = $(built_headers_configure)
-
-libgstreamer_@GST_API_VERSION@_la_CFLAGS =             \
-       -D_GNU_SOURCE                                   \
-       -DBUILDING_GST                                  \
-       -DG_LOG_DOMAIN=g_log_domain_gstreamer           \
-       -DGST_API_VERSION=\""$(GST_API_VERSION)"\"      \
-       -DGST_DISABLE_DEPRECATED                        \
-       $(VALGRIND_CFLAGS)                              \
-       $(UNWIND_CFLAGS)                                \
-       $(DW_CFLAGS)                            \
-       $(GST_ALL_CFLAGS)
-
-libgstreamer_@GST_API_VERSION@_la_LIBADD =             \
-       $(GST_PARSE_LA)                                 \
-       $(GST_PRINTF_LA)                                \
-       $(GST_ALL_LIBS)                                 \
-       $(WIN32_LIBS)                                   \
-       $(SOCKET_LIBS)                                  \
-       $(UNWIND_LIBS)                                  \
-       $(DW_LIBS)                                      \
-       $(LIBM)
-if USE_DLOG
-libgstreamer_@GST_API_VERSION@_la_CFLAGS += $(DLOG_CFLAGS)
-libgstreamer_@GST_API_VERSION@_la_LIBADD += $(DLOG_LIBS)
-libgstreamer_@GST_API_VERSION@_la_CFLAGS += -DUSE_DLOG
-endif
-
-
-libgstreamer_@GST_API_VERSION@_la_LDFLAGS =            \
-       $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
-
-libgstreamer_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst
-
-if IS_TV_PROFILE
-GST_QUERY_H = gstquery.h.tv
-else
-GST_QUERY_H = gstquery.h
-endif
-
-gst_headers =                  \
-       gst.h                   \
-       glib-compat.h           \
-       gstobject.h             \
-       gstallocator.h          \
-       gstbin.h                \
-       gstbuffer.h             \
-       gstbufferlist.h         \
-       gstbufferpool.h         \
-       gstbus.h                \
-       gstcaps.h               \
-       gstcapsfeatures.h       \
-       gstchildproxy.h         \
-       gstclock.h              \
-       gstcompat.h             \
-       gstcontext.h \
-       gstcontrolbinding.h \
-       gstcontrolsource.h \
-       gstdatetime.h           \
-       gstdebugutils.h         \
-       gstelement.h            \
-       gstelementmetadata.h    \
-       gstdevice.h             \
-       gstdeviceprovider.h     \
-       gstdeviceproviderfactory.h \
-       gstdynamictypefactory.h \
-       gstelementfactory.h     \
-       gsterror.h              \
-       gstevent.h              \
-       gstformat.h             \
-       gstghostpad.h           \
-       gstdevicemonitor.h      \
-       gstinfo.h               \
-       gstiterator.h           \
-       gstatomicqueue.h        \
-       gstmacros.h             \
-       gstmessage.h            \
-       gstmeta.h               \
-       gstmemory.h             \
-       gstminiobject.h         \
-       gstpad.h                \
-       gstpadtemplate.h        \
-       gstparamspecs.h         \
-       gstpipeline.h           \
-       gstplugin.h             \
-       gstpluginfeature.h      \
-       gstpoll.h               \
-       gstpreset.h             \
-       gstprotection.h         \
-       $(GST_QUERY_H)          \
-       gstpromise.h   \
-       gstsample.h             \
-       gstsegment.h            \
-       gststreamcollection.h   \
-       gststreams.h            \
-       gststructure.h          \
-       gstsystemclock.h        \
-       gsttaglist.h            \
-       gsttagsetter.h          \
-       gsttask.h               \
-       gsttaskpool.h           \
-       gsttoc.h                \
-       gsttocsetter.h          \
-       gsttracer.h             \
-       gsttracerfactory.h      \
-       gsttracerrecord.h               \
-       gsttypefind.h           \
-       gsttypefindfactory.h    \
-       gsturi.h                \
-       gstutils.h              \
-       gstvalue.h              \
-       gstregistry.h           \
-       gstparse.h
-
-libgstreamer_@GST_API_VERSION@include_HEADERS = $(gst_headers) math-compat.h
-
-nodist_libgstreamer_@GST_API_VERSION@include_HEADERS = \
-       $(built_headers_configure) $(built_header_make)
-
-noinst_HEADERS =               \
-       gettext.h               \
-       glib-compat-private.h   \
-       gst-i18n-lib.h          \
-       gst-i18n-app.h          \
-       gstelementmetadata.h    \
-       gstpluginloader.h       \
-       gstquark.h              \
-       gstregistrybinary.h     \
-       gstregistrychunks.h     \
-       gsttracerutils.h                \
-       gst_private.h
-
-gstenumtypes.h: $(gst_headers)
-       $(AM_V_GEN)$(GLIB_MKENUMS) \
-       --fhead "#ifndef __GST_ENUM_TYPES_H__\n#define __GST_ENUM_TYPES_H__\n\n#include <glib-object.h>\n#include <gst/gstconfig.h>\n\nG_BEGIN_DECLS\n" \
-       --fprod "\n/* enumerations from \"@filename@\" */\n" \
-       --vhead "GST_API GType @enum_name@_get_type (void);\n#define GST_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n"         \
-       --ftail "G_END_DECLS\n\n#endif /* __GST_ENUM_TYPES_H__ */" \
-       $^ > gstenumtypes.h
-
-gstenumtypes.c: $(gst_headers)
-       $(AM_V_GEN)$(GLIB_MKENUMS) \
-       --fhead "#include \"gst_private.h\"\n#include <gst/gst.h>\n#define C_ENUM(v) ((gint) v)\n#define C_FLAGS(v) ((guint) v)\n " \
-       --fprod "\n/* enumerations from \"@filename@\" */" \
-       --vhead "GType\n@enum_name@_get_type (void)\n{\n  static gsize id = 0;\n  static const G@Type@Value values[] = {"     \
-       --vprod "    { C_@TYPE@(@VALUENAME@), \"@VALUENAME@\", \"@valuenick@\" }," \
-       --vtail "    { 0, NULL, NULL }\n  };\n\n  if (g_once_init_enter (&id)) {\n    GType tmp = g_@type@_register_static (\"@EnumName@\", values);\n    g_once_init_leave (&id, tmp);\n  }\n\n  return (GType) id;\n}" \
-       $^ > gstenumtypes.c
-
-%.c.gcov: .libs/libgstreamer_@GST_API_VERSION@_la-%.gcda %.c
-       $(GCOV) -b -f -o $^ > $@.out
-
-gcov: $(libgstreamer_@GST_API_VERSION@_la_SOURCES:=.gcov)
-
-if HAVE_INTROSPECTION
-BUILT_GIRSOURCES = Gst-@GST_API_VERSION@.gir
-
-gir_headers=$(patsubst %,$(srcdir)/%, $(libgstreamer_@GST_API_VERSION@include_HEADERS))
-gir_headers+=$(patsubst %,$(builddir)/%, $(built_header_make))
-gir_headers+=$(patsubst %,$(builddir)/%, gstversion.h)
-gir_sources=$(patsubst %,$(srcdir)/%, $(libgstreamer_@GST_API_VERSION@_la_SOURCES))
-gir_sources+=$(patsubst %,$(builddir)/%, $(built_source_make))
-
-Gst-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstreamer-@GST_API_VERSION@.la
-       $(AM_V_GEN)GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_DISABLE=yes GI_SCANNER_DISABLE_CACHE=yes \
-               CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" PKG_CONFIG="$(PKG_CONFIG)" DLLTOOL="$(DLLTOOL)" \
-               $(INTROSPECTION_SCANNER) -v --namespace Gst \
-               --nsversion=@GST_API_VERSION@ \
-               --verbose \
-               --warn-all \
-               -I$(top_srcdir) \
-               -I$(top_builddir) \
-               -DIN_GOBJECT_INTROSPECTION=1 \
-               --c-include='gst/gst.h' \
-               --library=libgstreamer-@GST_API_VERSION@.la \
-               --include=GLib-2.0 \
-               --include=GObject-2.0 \
-               --include=GModule-2.0 \
-               --libtool="${LIBTOOL}" \
-               --pkg glib-2.0 \
-               --pkg gobject-2.0 \
-               --pkg gmodule-no-export-2.0 \
-               --pkg-export gstreamer-@GST_API_VERSION@ \
-               --add-init-section="$(INTROSPECTION_INIT)" \
-               --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) $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F)
-
-CLEANFILES += $(BUILT_GIRSOURCES) $(typelibs_DATA)
-endif
-
-# try to prevent packaging errors
-check-libexecdir-consistency:
-       @if test "${GST_PLUGIN_SCANNER_INSTALLED}" != "${libexecdir}/gstreamer-$(GST_API_VERSION)/gst-plugin-scanner"; then \
-         echo "*** Inconsistent libexecdir! Please use ./configure --libexecdir=/foo/bar"; \
-         echo "*** to set the libexecdir and not make libexecdir=/foo/bar or the like."; \
-         echo "*** The same goes for prefix, libdir etc."; \
-         echo "*** ${GST_PLUGIN_SCANNER_INSTALLED} != ${libexecdir}/gstreamer-$(GST_API_VERSION)/gst-plugin-scanner"; \
-         exit 1; \
-       fi
-
-all-local: check-libexecdir-consistency
index 117b385..617a50e 100644 (file)
@@ -30,11 +30,9 @@ G_BEGIN_DECLS
 /* copies */
 
 /* adaptations */
-#ifdef TIZEN_FEATURE_UPSTREAM
 #if !GLIB_CHECK_VERSION(2, 67, 4)
 #define g_memdup2(ptr,sz) ((G_LIKELY(((guint64)(sz)) < G_MAXUINT)) ? g_memdup(ptr,sz) : (g_abort(),NULL))
 #endif
-#endif /* TIZEN_FEATURE_UPSTREAM */
 
 G_END_DECLS
 
index 2f4c789..6ea42e0 100644 (file)
--- a/gst/gst.c
+++ b/gst/gst.c
  *                     graphs.
  *
  * GStreamer is a framework for constructing graphs of various filters
- * (termed elements here) that will handle streaming media.  Any discrete
- * (packetizable) media type is supported, with provisions for automatically
- * determining source type.  Formatting/framing information is provided with
- * a powerful negotiation framework.  Plugins are heavily used to provide for
- * all elements, allowing one to construct plugins outside of the GST
- * library, even released binary-only if license require (please don't).
+ * (termed elements here) that will handle streaming media.
+ *
+ * Any discrete (packetizable) media type is supported, with provisions for
+ * automatically determining source type.
+ *
+ * Formatting/framing information is provided with a powerful negotiation
+ * framework.
+ *
+ * Plugins are heavily used to provide for all elements, allowing one to
+ * construct plugins outside of the GST library, even released binary-only if
+ * license require (please don't).
+ *
  * GStreamer covers a wide range of use cases including: playback, recording,
  * editing, serving streams, voice over ip and video calls.
  *
- * The <application>GStreamer</application> library should be initialized with
- * gst_init() before it can be used. You should pass pointers to the main argc
- * and argv variables so that GStreamer can process its own command line
+ * The `GStreamer` library should be initialized with
+ * gst_init() before it can be used. You should pass pointers to the main `argc`
+ * and `argv` variables so that GStreamer can process its own command line
  * options, as shown in the following example.
  *
  * ## Initializing the gstreamer library
  *
- * |[ <!-- language="C" -->
- * int
- * main (int argc, char *argv[])
+ * ``` C
+ * int main (int argc, char *argv[])
  * {
  *   // initialize the GStreamer library
- *   gst_init (&amp;argc, &amp;argv);
+ *   gst_init (&argc, &argv);
  *   ...
  * }
- * ]|
+ * ```
  *
  * It's allowed to pass two %NULL pointers to gst_init() in case you don't want
  * to pass the command line args to GStreamer.
  *
- * You can also use GOption to initialize your own parameters as shown in
+ * You can also use #GOptionContext to initialize your own parameters as shown in
  * the next code fragment:
  *
- * ## Initializing own parameters when initializing gstreamer
- * |[ <!-- language="C" -->
+ * ## Initializing own parameters when initializing GStreamer
+ *
+ * ``` C
  * static gboolean stats = FALSE;
  * ...
  * int
  *  ctx = g_option_context_new ("[ADDITIONAL ARGUMENTS]");
  *  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, &amp;argc, &amp;argv, &amp;err)) {
- *    g_print ("Error initializing: &percnt;s\n", GST_STR_NULL (err->message));
+ *  if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
+ *    g_print ("Error initializing: %s\n", GST_STR_NULL (err->message));
  *    exit (1);
  *  }
  *  g_option_context_free (ctx);
  * ...
  * }
- * ]|
+ * ```
  *
  * Use gst_version() to query the library version at runtime or use the
  * GST_VERSION_* macros to find the version at compile time. Optionally
 
 static gboolean gst_initialized = FALSE;
 static gboolean gst_deinitialized = FALSE;
+static GMutex init_lock;
 
 GstClockTime _priv_gst_start_time;
 
@@ -390,7 +397,7 @@ gst_get_main_executable_path (void)
  * gst_init_check:
  * @argc: (inout) (allow-none): pointer to application's argc
  * @argv: (inout) (array length=argc) (allow-none): pointer to application's argv
- * @err: pointer to a #GError to which a message will be posted on error
+ * @error: pointer to a #GError to which a message will be posted on error
  *
  * Initializes the GStreamer library, setting up internal path lists,
  * registering built-in elements, and loading standard plugins.
@@ -402,9 +409,8 @@ gst_get_main_executable_path (void)
  * Returns: %TRUE if GStreamer could be initialized.
  */
 gboolean
-gst_init_check (int *argc, char **argv[], GError ** err)
+gst_init_check (int *argc, char **argv[], GError ** error)
 {
-  static GMutex init_lock;
 #ifndef GST_DISABLE_OPTION_PARSING
   GOptionGroup *group;
   GOptionContext *ctx;
@@ -424,7 +430,7 @@ gst_init_check (int *argc, char **argv[], GError ** err)
   g_option_context_set_help_enabled (ctx, FALSE);
   group = gst_init_get_option_group ();
   g_option_context_add_group (ctx, group);
-  res = g_option_context_parse (ctx, argc, argv, err);
+  res = g_option_context_parse (ctx, argc, argv, error);
   g_option_context_free (ctx);
 #else
   init_pre (NULL, NULL, NULL, NULL);
@@ -454,9 +460,9 @@ gst_init_check (int *argc, char **argv[], GError ** err)
  * <link linkend="gst-running">Running GStreamer Applications</link>
  * for how to disable automatic registry updates.
  *
- * > This function will terminate your program if it was unable to initialize
- * > GStreamer for some reason.  If you want your program to fall back,
- * use gst_init_check() instead.
+ * WARNING: This function will terminate your program if it was unable to
+ * initialize GStreamer for some reason. If you want your program to fall back,
+ * use gst_init_check() instead.
  *
  * WARNING: This function does not work in the same way as corresponding
  * functions in other glib-style libraries, such as gtk_init\(\). In
@@ -631,6 +637,24 @@ gst_register_core_elements (GstPlugin * plugin)
   return TRUE;
 }
 
+static void
+init_static_plugins (void)
+{
+  GModule *module;
+
+  /* Call gst_init_static_plugins() defined in libgstreamer-full-1.0 in the case
+   * libgstreamer is static linked with some plugins. */
+  module = g_module_open (NULL, G_MODULE_BIND_LOCAL);
+  if (module) {
+    void (*func) (void);
+    if (g_module_symbol (module, "gst_init_static_plugins",
+            (gpointer *) & func)) {
+      func ();
+    }
+    g_module_close (module);
+  }
+}
+
 /*
  * this bit handles:
  * - initialization of threads if we use them
@@ -789,6 +813,8 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
       gst_register_core_elements, VERSION, GST_LICENSE, PACKAGE,
       GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
 
+  init_static_plugins ();
+
   /*
    * Any errors happening below this point are non-fatal, we therefore mark
    * gstreamer as being initialized, since it is the case from a plugin point of
@@ -809,6 +835,10 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
       GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
   GST_INFO ("initialized GStreamer successfully");
 
+  /* Adjust initial plugin rank based on the GST_PLUGIN_FEATURE_RANK
+   * environment variable */
+  _priv_gst_plugin_feature_rank_initialize ();
+
 #ifndef GST_DISABLE_GST_DEBUG
   _priv_gst_tracing_init ();
 #endif
@@ -1016,6 +1046,7 @@ parse_one_option (gint opt, const gchar * arg, GError ** err)
   return TRUE;
 }
 
+/* *INDENT-OFF* */
 static gboolean
 parse_goption_arg (const gchar * opt,
     const gchar * arg, gpointer data, GError ** err)
@@ -1058,6 +1089,7 @@ parse_goption_arg (const gchar * opt,
   return parse_one_option (val, arg, err);
 }
 #endif
+/* *INDENT-ON* */
 
 /**
  * gst_deinit:
@@ -1077,15 +1109,18 @@ gst_deinit (void)
   GstBinClass *bin_class;
   GstClock *clock;
 
-  if (!gst_initialized)
-    return;
-
-  GST_INFO ("deinitializing GStreamer");
+  g_mutex_lock (&init_lock);
 
-  if (gst_deinitialized) {
-    GST_DEBUG ("already deinitialized");
+  if (!gst_initialized) {
+    g_mutex_unlock (&init_lock);
     return;
   }
+  if (gst_deinitialized) {
+    /* tell the user how naughty they've been */
+    g_error ("GStreamer should not be deinitialized a second time.");
+  }
+
+  GST_INFO ("deinitializing GStreamer");
   g_thread_pool_set_max_unused_threads (0);
   bin_class = (GstBinClass *) g_type_class_peek (gst_bin_get_type ());
   if (bin_class && bin_class->pool != NULL) {
@@ -1125,7 +1160,7 @@ gst_deinit (void)
 
   _priv_gst_caps_features_cleanup ();
   _priv_gst_caps_cleanup ();
-  _priv_gst_debug_cleanup ();
+  _priv_gst_meta_cleanup ();
 
   g_type_class_unref (g_type_class_peek (gst_object_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_pad_get_type ()));
@@ -1230,6 +1265,12 @@ gst_deinit (void)
 
   gst_deinitialized = TRUE;
   GST_INFO ("deinitialized GStreamer");
+  g_mutex_unlock (&init_lock);
+
+  /* Doing this as the very last step to allow the above GST_INFO() to work
+   * correctly. It's of course making the above statement a lie: for a short
+   * while we're not deinitialized yet */
+  _priv_gst_debug_cleanup ();
 }
 
 /**
index a1f2297..4423813 100644 (file)
--- a/gst/gst.h
+++ b/gst/gst.h
@@ -102,7 +102,7 @@ void                gst_init                        (int *argc, char **argv[]);
 
 GST_API
 gboolean       gst_init_check                  (int *argc, char **argv[],
-                                                GError ** err);
+                                                GError ** error);
 GST_API
 gboolean        gst_is_initialized              (void);
 
index b4567d6..739981a 100644 (file)
@@ -92,6 +92,10 @@ struct _GstPluginPrivate {
   GstStructure *cache_data;
 };
 
+/* Private function for getting plugin features directly */
+GList *
+_priv_plugin_get_features(GstRegistry *registry, GstPlugin *plugin);
+
 /* Needed by GstMeta (to access meta seq) and GstBuffer (create/free/iterate) */
 typedef struct _GstMetaItem GstMetaItem;
 struct _GstMetaItem {
@@ -112,8 +116,6 @@ G_GNUC_INTERNAL  gboolean _priv_plugin_deps_env_vars_changed (GstPlugin * plugin
 
 G_GNUC_INTERNAL  gboolean _priv_plugin_deps_files_changed (GstPlugin * plugin);
 
-G_GNUC_INTERNAL  gboolean _priv_gst_in_valgrind (void);
-
 /* init functions called from gst_init(). */
 G_GNUC_INTERNAL  void  _priv_gst_quarks_initialize (void);
 G_GNUC_INTERNAL  void  _priv_gst_mini_object_initialize (void);
@@ -137,12 +139,14 @@ G_GNUC_INTERNAL  void  _priv_gst_debug_init (void);
 G_GNUC_INTERNAL  void  _priv_gst_context_initialize (void);
 G_GNUC_INTERNAL  void  _priv_gst_toc_initialize (void);
 G_GNUC_INTERNAL  void  _priv_gst_date_time_initialize (void);
+G_GNUC_INTERNAL  void  _priv_gst_plugin_feature_rank_initialize (void);
 
 /* cleanup functions called from gst_deinit(). */
 G_GNUC_INTERNAL  void  _priv_gst_allocator_cleanup (void);
 G_GNUC_INTERNAL  void  _priv_gst_caps_features_cleanup (void);
 G_GNUC_INTERNAL  void  _priv_gst_caps_cleanup (void);
 G_GNUC_INTERNAL  void  _priv_gst_debug_cleanup (void);
+G_GNUC_INTERNAL  void  _priv_gst_meta_cleanup (void);
 
 /* called from gst_task_cleanup_all(). */
 G_GNUC_INTERNAL  void  _priv_gst_element_cleanup (void);
@@ -166,7 +170,7 @@ G_GNUC_INTERNAL const char * _priv_gst_value_gtype_to_abbr (GType type);
 
 G_GNUC_INTERNAL gboolean _priv_gst_value_parse_string (gchar * s, gchar ** end, gchar ** next, gboolean unescape);
 G_GNUC_INTERNAL gboolean _priv_gst_value_parse_simple_string (gchar * str, gchar ** end);
-G_GNUC_INTERNAL gboolean _priv_gst_value_parse_value (gchar * str, gchar ** after, GValue * value, GType default_type);
+G_GNUC_INTERNAL gboolean _priv_gst_value_parse_value (gchar * str, gchar ** after, GValue * value, GType default_type, GParamSpec *pspec);
 G_GNUC_INTERNAL gchar * _priv_gst_value_serialize_any_list (const GValue * value, const gchar * begin, const gchar * end, gboolean print_type);
 
 /* Used in GstBin for manual state handling */
@@ -179,7 +183,8 @@ G_GNUC_INTERNAL  void _priv_gst_element_state_changed (GstElement *element,
 
 G_GNUC_INTERNAL
 gboolean  priv_gst_structure_append_to_gstring (const GstStructure * structure,
-                                                GString            * s);
+                                                GString            * s,
+                                                GstSerializeFlags flags);
 G_GNUC_INTERNAL
 gboolean priv__gst_structure_append_template_to_gstring (GQuark field_id,
                                                         const GValue *value,
@@ -189,7 +194,7 @@ G_GNUC_INTERNAL
 void priv_gst_caps_features_append_to_gstring (const GstCapsFeatures * features, GString *s);
 
 G_GNUC_INTERNAL
-gboolean priv_gst_structure_parse_name (gchar * str, gchar **start, gchar ** end, gchar ** next);
+gboolean priv_gst_structure_parse_name (gchar * str, gchar **start, gchar ** end, gchar ** next, gboolean check_valid);
 G_GNUC_INTERNAL
 gboolean priv_gst_structure_parse_fields (gchar *str, gchar ** end, GstStructure *structure);
 
@@ -487,7 +492,7 @@ struct _GstDeviceProviderFactory {
 
   GType                      type;              /* unique GType the device factory or 0 if not loaded */
 
-  volatile GstDeviceProvider *provider;
+  GstDeviceProvider         *provider;
   gpointer                   metadata;
 
   gpointer _gst_reserved[GST_PADDING];
@@ -513,5 +518,16 @@ struct _GstDynamicTypeFactoryClass {
 /* privat flag used by GstBus / GstMessage */
 #define GST_MESSAGE_FLAG_ASYNC_DELIVERY (GST_MINI_OBJECT_FLAG_LAST << 0)
 
+/* private struct used by GstClock and GstSystemClock */
+struct _GstClockEntryImpl
+{
+  GstClockEntry entry;
+  GWeakRef clock;
+  GDestroyNotify destroy_entry;
+  gpointer padding[21];                 /* padding for allowing e.g. systemclock
+                                         * to add data in lieu of overridable
+                                         * virtual functions on the clock */
+};
+
 G_END_DECLS
 #endif /* __GST_PRIVATE_H__ */
index 20ced48..6b30476 100644 (file)
@@ -24,6 +24,9 @@
  * @title: GstAllocator
  * @short_description: allocate memory blocks
  * @see_also: #GstMemory
+ * @auto-sort: false
+ * @symbols:
+ * - GstAllocator
  *
  * Memory is usually created by allocators with a gst_allocator_alloc()
  * method call. When %NULL is used as the allocator, the default allocator will
@@ -140,6 +143,31 @@ G_DEFINE_BOXED_TYPE (GstAllocationParams, gst_allocation_params,
     (GBoxedFreeFunc) gst_allocation_params_free);
 
 /**
+ * gst_allocation_params_new:
+ *
+ * Create a new #GstAllocationParams on the heap.  This function is for
+ * use in GStreamer language bindings.  In your own code, you can just
+ * declare a #GstAllocationParams on the stack or in a struct, and
+ * call gst_allocation_params_init() to initialize it.
+ *
+ * You do not need to call gst_allocation_params_init() on the instance
+ * returned by this function.
+ *
+ * Returns: (transfer full) (not nullable): a new #GstAllocationParams
+ *
+ * Since: 1.20
+ */
+GstAllocationParams *
+gst_allocation_params_new (void)
+{
+  /* Call new() and then init(), rather than calling new0(), in case
+   * init() ever changes to something other than a memset(). */
+  GstAllocationParams *result = g_slice_new (GstAllocationParams);
+  gst_allocation_params_init (result);
+  return result;
+}
+
+/**
  * gst_allocation_params_init:
  * @params: a #GstAllocationParams
  *
@@ -159,10 +187,7 @@ gst_allocation_params_init (GstAllocationParams * params)
  *
  * Create a copy of @params.
  *
- * Free-function: gst_allocation_params_free
- *
- * Returns: (transfer full) (nullable): a new ##GstAllocationParams, free with
- * gst_allocation_params_free().
+ * Returns: (transfer full) (nullable): a new #GstAllocationParams.
  */
 GstAllocationParams *
 gst_allocation_params_copy (const GstAllocationParams * params)
@@ -194,8 +219,7 @@ gst_allocation_params_free (GstAllocationParams * params)
  * @name: the name of the allocator
  * @allocator: (transfer full): #GstAllocator
  *
- * Registers the memory @allocator with @name. This function takes ownership of
- * @allocator.
+ * Registers the memory @allocator with @name.
  */
 void
 gst_allocator_register (const gchar * name, GstAllocator * allocator)
@@ -221,8 +245,7 @@ gst_allocator_register (const gchar * name, GstAllocator * allocator)
  * default allocator will be returned.
  *
  * Returns: (transfer full) (nullable): a #GstAllocator or %NULL when
- * the allocator with @name was not registered. Use gst_object_unref()
- * to release the allocator after usage.
+ * the allocator with @name was not registered.
  */
 GstAllocator *
 gst_allocator_find (const gchar * name)
@@ -246,7 +269,7 @@ gst_allocator_find (const gchar * name)
  * gst_allocator_set_default:
  * @allocator: (transfer full): a #GstAllocator
  *
- * Set the default allocator. This function takes ownership of @allocator.
+ * Set the default allocator.
  */
 void
 gst_allocator_set_default (GstAllocator * allocator)
index 05565a2..0989dd8 100644 (file)
@@ -168,6 +168,9 @@ void           gst_allocator_set_default     (GstAllocator * allocator);
 /* allocation parameters */
 
 GST_API
+GstAllocationParams * gst_allocation_params_new (void) G_GNUC_MALLOC;
+
+GST_API
 void           gst_allocation_params_init    (GstAllocationParams *params);
 
 GST_API
@@ -191,9 +194,7 @@ GstMemory *    gst_memory_new_wrapped  (GstMemoryFlags flags, gpointer data, gsi
                                         gsize offset, gsize size, gpointer user_data,
                                         GDestroyNotify notify);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAllocationParams, gst_allocation_params_free)
-#endif
 
 G_END_DECLS
 
index a80089c..a69c048 100644 (file)
@@ -57,9 +57,9 @@ struct _GstAQueueMem
 {
   gint size;
   gpointer *array;
-  volatile gint head;
-  volatile gint tail_write;
-  volatile gint tail_read;
+  gint head;
+  gint tail_write;
+  gint tail_read;
   GstAQueueMem *next;
   GstAQueueMem *free;
 };
@@ -103,7 +103,7 @@ free_queue_mem (GstAQueueMem * mem)
 
 struct _GstAtomicQueue
 {
-  volatile gint refcount;
+  gint refcount;
 #ifdef LOW_MEM
   gint num_readers;
 #endif
index 8a131ab..2bf1e7d 100644 (file)
@@ -65,9 +65,7 @@ gpointer           gst_atomic_queue_peek        (GstAtomicQueue* queue);
 GST_API
 guint              gst_atomic_queue_length      (GstAtomicQueue * queue);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAtomicQueue, gst_atomic_queue_unref)
-#endif
 
 G_END_DECLS
 
index e86f0f6..43e1329 100644 (file)
@@ -19,8 +19,6 @@
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
  * Boston, MA 02110-1301, USA.
- *
- * MT safe.
  */
 
 /**
  * the bin. Likewise the #GstBin::element-removed signal is fired whenever an
  * element is removed from the bin.
  *
- * ## Notes
- *
  * A #GstBin internally intercepts every #GstMessage posted by its children and
  * implements the following default behaviour for each of them:
  *
- * * GST_MESSAGE_EOS: This message is only posted by sinks in the PLAYING
+ * * %GST_MESSAGE_EOS: This message is only posted by sinks in the PLAYING
  * state. If all sinks posted the EOS message, this bin will post and EOS
  * message upwards.
  *
- * * GST_MESSAGE_SEGMENT_START: Just collected and never forwarded upwards.
- * The messages are used to decide when all elements have completed playback
- * of their segment.
+ * * %GST_MESSAGE_SEGMENT_START: Just collected and never forwarded upwards.
+ *   The messages are used to decide when all elements have completed playback
+ *   of their segment.
+ *
+ * * %GST_MESSAGE_SEGMENT_DONE: Is posted by #GstBin when all elements that posted
+ *   a SEGMENT_START have posted a SEGMENT_DONE.
+ *
+ * * %GST_MESSAGE_DURATION_CHANGED: Is posted by an element that detected a change
+ *   in the stream duration. The duration change is posted to the
+ *   application so that it can refetch the new duration with a duration
+ *   query.
+ *
+ *   Note that these messages can be posted before the bin is prerolled, in which
+ *   case the duration query might fail.
+ *
+ *   Note also that there might be a discrepancy (due to internal buffering/queueing)
+ *   between the stream being currently displayed and the returned duration query.
+ *
+ *   Applications might want to also query for duration (and changes) by
+ *   listening to the %GST_MESSAGE_STREAM_START message, signaling the active start
+ *   of a (new) stream.
  *
- * * GST_MESSAGE_SEGMENT_DONE: Is posted by #GstBin when all elements that posted
- * a SEGMENT_START have posted a SEGMENT_DONE.
+ * * %GST_MESSAGE_CLOCK_LOST: This message is posted by an element when it
+ *   can no longer provide a clock.
  *
- * * GST_MESSAGE_DURATION_CHANGED: Is posted by an element that detected a change
- * in the stream duration. The default bin behaviour is to clear any
- * cached duration values so that the next duration query will perform
- * a full duration recalculation. The duration change is posted to the
- * application so that it can refetch the new duration with a duration
- * query. Note that these messages can be posted before the bin is
- * prerolled, in which case the duration query might fail.
+ *   The default bin behaviour is to check if the lost clock was the one provided
+ *   by the bin. If so and the bin is currently in the PLAYING state, the message
+ *   is forwarded to the bin parent.
  *
- * * GST_MESSAGE_CLOCK_LOST: This message is posted by an element when it
- * can no longer provide a clock. The default bin behaviour is to
- * check if the lost clock was the one provided by the bin. If so and
- * the bin is currently in the PLAYING state, the message is forwarded to
- * the bin parent.
- * This message is also generated when a clock provider is removed from
- * the bin. If this message is received by the application, it should
- * PAUSE the pipeline and set it back to PLAYING to force a new clock
- * distribution.
+ *   This message is also generated when a clock provider is removed from
+ *   the bin. If this message is received by the application, it should
+ *   PAUSE the pipeline and set it back to PLAYING to force a new clock
+ *   distribution.
  *
- * * GST_MESSAGE_CLOCK_PROVIDE: This message is generated when an element
- * can provide a clock. This mostly happens when a new clock
- * provider is added to the bin. The default behaviour of the bin is to
- * mark the currently selected clock as dirty, which will perform a clock
- * recalculation the next time the bin is asked to provide a clock.
- * This message is never sent tot the application but is forwarded to
- * the parent of the bin.
+ * * %GST_MESSAGE_CLOCK_PROVIDE: This message is generated when an element
+ *   can provide a clock. This mostly happens when a new clock
+ *   provider is added to the bin.
+ *
+ *   The default behaviour of the bin is to mark the currently selected clock as
+ *   dirty, which will perform a clock recalculation the next time the bin is
+ *   asked to provide a clock.
+ *
+ *   This message is never sent to the application but is forwarded to
+ *   the parent of the bin.
  *
  * * OTHERS: posted upwards.
  *
  * A #GstBin implements the following default behaviour for answering to a
  * #GstQuery:
  *
- * * GST_QUERY_DURATION:If the query has been asked before with the same format
- * and the bin is a toplevel bin (ie. has no parent),
- * use the cached previous value. If no previous value was cached, the
- * query is sent to all sink elements in the bin and the MAXIMUM of all
- * values is returned. If the bin is a toplevel bin the value is cached.
- * If no sinks are available in the bin, the query fails.
+ * * %GST_QUERY_DURATION: The bin will forward the query to all sink
+ *   elements contained within and will return the maximum value.
+ *   If no sinks are available in the bin, the query fails.
  *
- * * GST_QUERY_POSITION:The query is sent to all sink elements in the bin and the
- * MAXIMUM of all values is returned. If no sinks are available in the bin,
- * the query fails.
+ * * %GST_QUERY_POSITION: The query is sent to all sink elements in the bin and the
+ *   MAXIMUM of all values is returned. If no sinks are available in the bin,
+ *   the query fails.
  *
- * * OTHERS:the query is forwarded to all sink elements, the result
- * of the first sink that answers the query successfully is returned. If no
- * sink is in the bin, the query fails.
+ * * OTHERS: the query is forwarded to all sink elements, the result
+ *   of the first sink that answers the query successfully is returned. If no
+ *   sink is in the bin, the query fails.
  *
  * A #GstBin will by default forward any event sent to it to all sink
- * (#GST_EVENT_TYPE_DOWNSTREAM) or source (#GST_EVENT_TYPE_UPSTREAM) elements
+ * ( %GST_EVENT_TYPE_DOWNSTREAM ) or source ( %GST_EVENT_TYPE_UPSTREAM ) elements
  * depending on the event type.
+ *
  * If all the elements return %TRUE, the bin will also return %TRUE, else %FALSE
  * is returned. If no elements of the required type are in the bin, the event
  * handler will return %TRUE.
- *
  */
 
 #include "gst_private.h"
@@ -321,8 +326,7 @@ _gst_boolean_accumulator (GSignalInvocationHint * ihint,
   gboolean myboolean;
 
   myboolean = g_value_get_boolean (handler_return);
-  if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
-    g_value_set_boolean (return_accu, myboolean);
+  g_value_set_boolean (return_accu, myboolean);
 
   GST_DEBUG ("invocation %d, %d", ihint->run_type, myboolean);
 
@@ -356,7 +360,7 @@ gst_bin_class_init (GstBinClass * klass)
 
   /**
    * GstBin::element-added:
-   * @bin: the #GstBin
+   * @self: the #GstBin
    * @element: the #GstElement that was added to the bin
    *
    * Will be emitted after the element was added to the bin.
@@ -364,10 +368,10 @@ gst_bin_class_init (GstBinClass * klass)
   gst_bin_signals[ELEMENT_ADDED] =
       g_signal_new ("element-added", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_added), NULL,
-      NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
+      NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
   /**
    * GstBin::element-removed:
-   * @bin: the #GstBin
+   * @self: the #GstBin
    * @element: the #GstElement that was removed from the bin
    *
    * Will be emitted after the element was removed from the bin.
@@ -375,43 +379,41 @@ gst_bin_class_init (GstBinClass * klass)
   gst_bin_signals[ELEMENT_REMOVED] =
       g_signal_new ("element-removed", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_removed), NULL,
-      NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
+      NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
   /**
    * GstBin::deep-element-added:
-   * @bin: the #GstBin
+   * @self: the #GstBin
    * @sub_bin: the #GstBin the element was added to
    * @element: the #GstElement that was added to @sub_bin
    *
-   * Will be emitted after the element was added to sub_bin.
+   * Will be emitted after the element was added to @sub_bin.
    *
    * Since: 1.10
    */
   gst_bin_signals[DEEP_ELEMENT_ADDED] =
       g_signal_new ("deep-element-added", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, deep_element_added),
-      NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, GST_TYPE_BIN,
-      GST_TYPE_ELEMENT);
+      NULL, NULL, NULL, G_TYPE_NONE, 2, GST_TYPE_BIN, GST_TYPE_ELEMENT);
   /**
    * GstBin::deep-element-removed:
-   * @bin: the #GstBin
+   * @self: the #GstBin
    * @sub_bin: the #GstBin the element was removed from
    * @element: the #GstElement that was removed from @sub_bin
    *
-   * Will be emitted after the element was removed from sub_bin.
+   * Will be emitted after the element was removed from @sub_bin.
    *
    * Since: 1.10
    */
   gst_bin_signals[DEEP_ELEMENT_REMOVED] =
       g_signal_new ("deep-element-removed", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, deep_element_removed),
-      NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, GST_TYPE_BIN,
-      GST_TYPE_ELEMENT);
+      NULL, NULL, NULL, G_TYPE_NONE, 2, GST_TYPE_BIN, GST_TYPE_ELEMENT);
   /**
    * GstBin::do-latency:
-   * @bin: the #GstBin
+   * @self: the #GstBin
    *
    * Will be emitted when the bin needs to perform latency calculations. This
-   * signal is only emitted for toplevel bins or when async-handling is
+   * signal is only emitted for toplevel bins or when #GstBin:async-handling is
    * enabled.
    *
    * Only one signal handler is invoked. If no signals are connected, the
@@ -425,8 +427,7 @@ gst_bin_class_init (GstBinClass * klass)
   gst_bin_signals[DO_LATENCY] =
       g_signal_new ("do-latency", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstBinClass, do_latency),
-      _gst_boolean_accumulator, NULL, g_cclosure_marshal_generic,
-      G_TYPE_BOOLEAN, 0, G_TYPE_NONE);
+      _gst_boolean_accumulator, NULL, NULL, G_TYPE_BOOLEAN, 0, G_TYPE_NONE);
 
   /**
    * GstBin:message-forward:
@@ -436,8 +437,8 @@ gst_bin_class_init (GstBinClass * klass)
    * state of individual elements, for example.
    *
    * The messages are converted to an ELEMENT message with the bin as the
-   * source. The structure of the message is named 'GstBinForwarded' and contains
-   * a field named 'message' of type GST_TYPE_MESSAGE that contains the original
+   * source. The structure of the message is named `GstBinForwarded` and contains
+   * a field named `message` of type %GST_TYPE_MESSAGE that contains the original
    * forwarded message.
    */
   g_object_class_install_property (gobject_class, PROP_MESSAGE_FORWARD,
@@ -1019,11 +1020,12 @@ is_stream_start (GstBin * bin, guint32 * seqnum, gboolean * have_group_id,
   gboolean result;
   GList *walk, *msgs;
   guint tmp_group_id;
-  gboolean first = TRUE, same_group_id = TRUE;
+  gboolean first_stream_start = TRUE, first_group_id = TRUE;
+  gboolean same_group_id = TRUE;
 
-  *have_group_id = TRUE;
+  *have_group_id = FALSE;
   *group_id = 0;
-  result = TRUE;
+  result = FALSE;
   for (walk = bin->children; walk; walk = g_list_next (walk)) {
     GstElement *element;
 
@@ -1033,12 +1035,24 @@ is_stream_start (GstBin * bin, guint32 * seqnum, gboolean * have_group_id,
       if ((msgs =
               find_message (bin, GST_OBJECT_CAST (element),
                   GST_MESSAGE_STREAM_START))) {
+        /* Only initialize to TRUE if we have any stream-start messages at
+         * all, otherwise it should be FALSE. */
+        if (first_stream_start) {
+          /* If any stream-start message do not contain a group id then we
+           * will set it to FALSE below */
+          *have_group_id = TRUE;
+          /* Similarly if any sinks did not post stream-start then we will
+           * set it to FALSE afterwards */
+          result = TRUE;
+          first_stream_start = FALSE;
+        }
+
         GST_DEBUG ("sink '%s' posted STREAM_START", GST_ELEMENT_NAME (element));
         *seqnum = gst_message_get_seqnum (GST_MESSAGE_CAST (msgs->data));
         if (gst_message_parse_group_id (GST_MESSAGE_CAST (msgs->data),
                 &tmp_group_id)) {
-          if (first) {
-            first = FALSE;
+          if (first_group_id) {
+            first_group_id = FALSE;
             *group_id = tmp_group_id;
           } else {
             if (tmp_group_id != *group_id)
@@ -1110,7 +1124,7 @@ gst_bin_do_deep_add_remove (GstBin * bin, gint sig_id, const gchar * sig_name,
     do {
       ires = gst_iterator_foreach (it, bin_deep_iterator_foreach, &elements);
       if (ires != GST_ITERATOR_DONE) {
-        g_queue_foreach (&elements, (GFunc) g_object_unref, NULL);
+        g_queue_foreach (&elements, (GFunc) gst_object_unref, NULL);
         g_queue_clear (&elements);
       }
       if (ires == GST_ITERATOR_RESYNC)
@@ -1129,7 +1143,7 @@ gst_bin_do_deep_add_remove (GstBin * bin, gint sig_id, const gchar * sig_name,
               " in bin %" GST_PTR_FORMAT, sig_name, e, parent);
           g_signal_emit (bin, sig_id, 0, parent, e);
           gst_object_unref (parent);
-          g_object_unref (e);
+          gst_object_unref (e);
         }
       }
     }
@@ -1399,13 +1413,11 @@ had_parent:
  * @bin: a #GstBin
  * @flags: the #GstElementFlags to suppress
  *
- * Suppress the given flags on the bin. #GstElementFlags of a
+ * Suppresses the given flags on the bin. #GstElementFlags of a
  * child element are propagated when it is added to the bin.
  * When suppressed flags are set, those specified flags will
  * not be propagated to the bin.
  *
- * MT safe.
- *
  * Since: 1.10
  */
 void
@@ -1425,10 +1437,6 @@ gst_bin_set_suppressed_flags (GstBin * bin, GstElementFlags flags)
  * gst_bin_get_suppressed_flags:
  * @bin: a #GstBin
  *
- * Return the suppressed flags of the bin.
- *
- * MT safe.
- *
  * Returns: the bin's suppressed #GstElementFlags.
  *
  * Since: 1.10
@@ -1485,7 +1493,7 @@ gst_bin_deep_element_removed_func (GstBin * bin, GstBin * sub_bin,
 
   GST_LOG_OBJECT (parent_bin, "emitting deep-element-removed for element "
       "%" GST_PTR_FORMAT " which has just been removed from %" GST_PTR_FORMAT,
-      sub_bin, child);
+      child, sub_bin);
 
   g_signal_emit (parent_bin, gst_bin_signals[DEEP_ELEMENT_REMOVED], 0, sub_bin,
       child);
@@ -1510,8 +1518,6 @@ gst_bin_deep_element_removed_func (GstBin * bin, GstBin * sub_bin,
  * > with gst_element_set_state(), or use gst_element_sync_state_with_parent().
  * > The bin or pipeline will not take care of this for you.
  *
- * MT safe.
- *
  * Returns: %TRUE if the element could be added, %FALSE if
  * the bin does not want to accept the element.
  */
@@ -1576,7 +1582,7 @@ gst_bin_remove_func (GstBin * bin, GstElement * element)
   GstClock **provided_clock_p;
   GstElement **clock_provider_p;
   GList *walk, *next;
-  gboolean other_async, this_async, have_no_preroll;
+  gboolean other_async, this_async, have_no_preroll, removed_eos;
   GstStateChangeReturn ret;
 
   GST_DEBUG_OBJECT (bin, "element :%s", GST_ELEMENT_NAME (element));
@@ -1703,6 +1709,8 @@ gst_bin_remove_func (GstBin * bin, GstElement * element)
    * async state. */
   this_async = FALSE;
   other_async = FALSE;
+  /* If we remove an EOSed element, the bin might go EOS */
+  removed_eos = FALSE;
   for (walk = bin->messages; walk; walk = next) {
     GstMessage *message = (GstMessage *) walk->data;
     GstElement *src = GST_ELEMENT_CAST (GST_MESSAGE_SRC (message));
@@ -1736,6 +1744,10 @@ gst_bin_remove_func (GstBin * bin, GstElement * element)
           remove = TRUE;
         break;
       }
+      case GST_MESSAGE_EOS:
+        if (src == element)
+          removed_eos = TRUE;
+        break;
       default:
         break;
     }
@@ -1798,6 +1810,15 @@ no_state_recalc:
   gst_element_set_clock (element, NULL);
   GST_OBJECT_UNLOCK (bin);
 
+  /* If the element was a sink that had not posted EOS,
+   * it might have been the last one we were waiting for,
+   * so check if it's time to send EOS now */
+  if (is_sink && !removed_eos) {
+    GST_DEBUG_OBJECT (bin,
+        "Removing sink that had not EOSed. Re-checking overall EOS status");
+    bin_do_eos (bin);
+  }
+
   if (clock_message)
     gst_element_post_message (GST_ELEMENT_CAST (bin), clock_message);
 
@@ -1858,8 +1879,6 @@ not_in_bin:
  * If the element's pads are linked to other pads, the pads will be unlinked
  * before the element is removed from the bin.
  *
- * MT safe.
- *
  * Returns: %TRUE if the element could be removed, %FALSE if
  * the bin does not want to remove the element.
  */
@@ -1902,10 +1921,7 @@ no_function:
  *
  * Gets an iterator for the elements in this bin.
  *
- * MT safe.  Caller owns returned value.
- *
- * Returns: (transfer full) (nullable): a #GstIterator of #GstElement,
- * or %NULL
+ * Returns: (transfer full) (nullable): a #GstIterator of #GstElement
  */
 GstIterator *
 gst_bin_iterate_elements (GstBin * bin)
@@ -1943,10 +1959,7 @@ iterate_child_recurse (GstIterator * it, const GValue * item)
  * Gets an iterator for the elements in this bin.
  * This iterator recurses into GstBin children.
  *
- * MT safe.  Caller owns returned value.
- *
- * Returns: (transfer full) (nullable): a #GstIterator of #GstElement,
- * or %NULL
+ * Returns: (transfer full) (nullable): a #GstIterator of #GstElement
  */
 GstIterator *
 gst_bin_iterate_recurse (GstBin * bin)
@@ -2001,10 +2014,7 @@ sink_iterator_filter (const GValue * vchild, GValue * vbin)
  * Gets an iterator for all elements in the bin that have the
  * #GST_ELEMENT_FLAG_SINK flag set.
  *
- * MT safe.  Caller owns returned value.
- *
- * Returns: (transfer full) (nullable): a #GstIterator of #GstElement,
- * or %NULL
+ * Returns: (transfer full) (nullable): a #GstIterator of #GstElement
  */
 GstIterator *
 gst_bin_iterate_sinks (GstBin * bin)
@@ -2062,10 +2072,7 @@ src_iterator_filter (const GValue * vchild, GValue * vbin)
  * Gets an iterator for all elements in the bin that have the
  * #GST_ELEMENT_FLAG_SOURCE flag set.
  *
- * MT safe.  Caller owns returned value.
- *
- * Returns: (transfer full) (nullable): a #GstIterator of #GstElement,
- * or %NULL
+ * Returns: (transfer full) (nullable): a #GstIterator of #GstElement
  */
 GstIterator *
 gst_bin_iterate_sources (GstBin * bin)
@@ -2455,10 +2462,7 @@ gst_bin_sort_iterator_new (GstBin * bin)
  * This function is used internally to perform the state changes
  * of the bin elements and for clock selection.
  *
- * MT safe.  Caller owns returned value.
- *
- * Returns: (transfer full) (nullable): a #GstIterator of #GstElement,
- * or %NULL
+ * Returns: (transfer full) (nullable): a #GstIterator of #GstElement
  */
 GstIterator *
 gst_bin_iterate_sorted (GstBin * bin)
@@ -2731,13 +2735,13 @@ failed:
  * gst_bin_recalculate_latency:
  * @bin: a #GstBin
  *
- * Query @bin for the current latency using and reconfigures this latency to all the
- * elements with a LATENCY event.
+ * Queries @bin for the current latency and reconfigures this latency on all the
+ * elements using a LATENCY event.
  *
  * This method is typically called on the pipeline when a #GST_MESSAGE_LATENCY
  * is posted on the bus.
  *
- * This function simply emits the 'do-latency' signal so any custom latency
+ * This function simply emits the #GstBin::do-latency signal so any custom latency
  * calculations will be performed.
  *
  * Returns: %TRUE if the latency could be queried and reconfigured.
@@ -3678,14 +3682,6 @@ gst_bin_update_context_unlocked (GstBin * bin, GstContext * context)
  *     with the segment_done message. If there are no more segment_start
  *     messages, post segment_done message upwards.
  *
- * GST_MESSAGE_DURATION_CHANGED: clear any cached durations.
- *     Whenever someone performs a duration query on the bin, we store the
- *     result so we can answer it quicker the next time. Any element that
- *     changes its duration marks our cached values invalid.
- *     This message is also posted upwards. This is currently disabled
- *     because too many elements don't post DURATION_CHANGED messages when
- *     the duration changes.
- *
  * GST_MESSAGE_CLOCK_LOST: This message is posted by an element when it
  *     can no longer provide a clock. The default bin behaviour is to
  *     check if the lost clock was the one provided by the bin. If so and
@@ -3843,17 +3839,6 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
       }
       break;
     }
-    case GST_MESSAGE_DURATION_CHANGED:
-    {
-      /* FIXME: remove all cached durations, next time somebody asks
-       * for duration, we will recalculate. */
-#if 0
-      GST_OBJECT_LOCK (bin);
-      bin_remove_messages (bin, NULL, GST_MESSAGE_DURATION_CHANGED);
-      GST_OBJECT_UNLOCK (bin);
-#endif
-      goto forward;
-    }
     case GST_MESSAGE_CLOCK_LOST:
     {
       GstClock **provided_clock_p;
@@ -4142,15 +4127,6 @@ bin_query_duration_done (GstBin * bin, QueryFold * fold)
   gst_query_set_duration (fold->query, format, fold->max);
 
   GST_DEBUG_OBJECT (bin, "max duration %" G_GINT64_FORMAT, fold->max);
-
-  /* FIXME: re-implement duration caching */
-#if 0
-  /* 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
@@ -4318,52 +4294,7 @@ gst_bin_query (GstElement * element, GstQuery * query)
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_DURATION:
     {
-      /* FIXME: implement duration caching in GstBin again */
-#if 0
-      GList *cached;
-      GstFormat qformat;
-
-      gst_query_parse_duration (query, &qformat, NULL);
-
-      /* find cached duration query */
-      GST_OBJECT_LOCK (bin);
-      for (cached = bin->messages; cached; cached = g_list_next (cached)) {
-        GstMessage *message = (GstMessage *) cached->data;
-
-        if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DURATION_CHANGED &&
-            GST_MESSAGE_SRC (message) == GST_OBJECT_CAST (bin)) {
-          GstFormat format;
-          gint64 duration;
-
-          gst_message_parse_duration (message, &format, &duration);
-
-          /* if cached same format, copy duration in query result */
-          if (format == qformat) {
-            GST_DEBUG_OBJECT (bin, "return cached duration %" G_GINT64_FORMAT,
-                duration);
-            GST_OBJECT_UNLOCK (bin);
-
-            gst_query_set_duration (query, qformat, duration);
-            res = TRUE;
-            goto exit;
-          }
-        }
-      }
-      GST_OBJECT_UNLOCK (bin);
-#else
-#ifndef GST_DISABLE_GST_DEBUG
-      G_STMT_START {
-        /* Quieten this particularly annoying FIXME a bit: */
-        static gboolean printed_fixme = FALSE;
-        if (!printed_fixme) {
-          GST_FIXME ("implement duration caching in GstBin again");
-          printed_fixme = TRUE;
-        }
-      }
-      G_STMT_END;
-#endif
-#endif
-      /* no cached value found, iterate and collect durations */
+      /* iterate and collect durations */
       fold_func = (GstIteratorFoldFunction) bin_query_duration_fold;
       fold_init = bin_query_min_max_init;
       fold_done = bin_query_duration_done;
@@ -4468,12 +4399,8 @@ compare_name (const GValue * velement, const gchar * name)
  * Gets the element with the given name from a bin. This
  * function recurses into child bins.
  *
- * Returns %NULL if no element with the given name is found in the bin.
- *
- * MT safe.  Caller owns returned reference.
- *
  * Returns: (transfer full) (nullable): the #GstElement with the given
- * name, or %NULL
+ * name
  */
 GstElement *
 gst_bin_get_by_name (GstBin * bin, const gchar * name)
@@ -4511,13 +4438,8 @@ gst_bin_get_by_name (GstBin * bin, const gchar * name)
  * Gets the element with the given name from this bin. If the
  * element is not found, a recursion is performed on the parent bin.
  *
- * Returns %NULL if:
- * - no element with the given name is found in the bin
- *
- * MT safe.  Caller owns returned reference.
- *
  * Returns: (transfer full) (nullable): the #GstElement with the given
- * name, or %NULL
+ * name
  */
 GstElement *
 gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name)
@@ -4570,8 +4492,6 @@ compare_interface (const GValue * velement, GValue * interface)
  * all elements that implement the interface, use
  * gst_bin_iterate_all_by_interface(). This function recurses into child bins.
  *
- * MT safe.  Caller owns returned reference.
- *
  * Returns: (transfer full) (nullable): A #GstElement inside the bin
  * implementing the interface
  */
@@ -4614,13 +4534,10 @@ gst_bin_get_by_interface (GstBin * bin, GType iface)
  * Looks for all elements inside the bin that implements the given
  * interface. You can safely cast all returned elements to the given interface.
  * The function recurses inside child bins. The iterator will yield a series
- * of #GstElement that should be unreffed after use.
- *
- * MT safe.  Caller owns returned value.
+ * of #GstElement.
  *
  * Returns: (transfer full) (nullable): a #GstIterator of #GstElement
- *     for all elements in the bin implementing the given interface,
- *     or %NULL
+ *     for all elements in the bin implementing the given interface
  */
 GstIterator *
 gst_bin_iterate_all_by_interface (GstBin * bin, GType iface)
@@ -4643,3 +4560,53 @@ gst_bin_iterate_all_by_interface (GstBin * bin, GType iface)
 
   return result;
 }
+
+static gint
+compare_factory_names (const GValue * velement, GValue * factory_name_val)
+{
+  GstElement *element = g_value_get_object (velement);
+  GstElementFactory *factory = gst_element_get_factory (element);
+  const gchar *factory_name = g_value_get_string (factory_name_val);
+
+  if (factory == NULL)
+    return -1;
+
+  return g_strcmp0 (GST_OBJECT_NAME (factory), factory_name);
+}
+
+/**
+ * gst_bin_iterate_all_by_element_factory_name:
+ * @bin: a #GstBin
+ * @factory_name: (not nullable): the name of the #GstElementFactory
+ *
+ * Looks for all elements inside the bin with the given element factory name.
+ * The function recurses inside child bins. The iterator will yield a series of
+ * #GstElement.
+ *
+ * Returns: (transfer full) (nullable): a #GstIterator of #GstElement
+ *     for all elements in the bin with the given element factory name
+ *
+ * Since: 1.18
+ */
+GstIterator *
+gst_bin_iterate_all_by_element_factory_name (GstBin * bin,
+    const gchar * factory_name)
+{
+  GstIterator *children;
+  GstIterator *result;
+  GValue factory_name_val = G_VALUE_INIT;
+
+  g_return_val_if_fail (GST_IS_BIN (bin), NULL);
+  g_return_val_if_fail (factory_name && *factory_name, NULL);
+
+  g_value_init (&factory_name_val, G_TYPE_STRING);
+  g_value_set_string (&factory_name_val, factory_name);
+
+  children = gst_bin_iterate_recurse (bin);
+  result = gst_iterator_filter (children, (GCompareFunc) compare_factory_names,
+      &factory_name_val);
+
+  g_value_unset (&factory_name_val);
+
+  return result;
+}
index 3f61ed7..ed6f29d 100644 (file)
@@ -40,22 +40,41 @@ G_BEGIN_DECLS
 
 /**
  * GstBinFlags:
- * @GST_BIN_FLAG_NO_RESYNC: don't resync a state change when elements are
- *             added or linked in the bin (Since: 1.0.5)
- * @GST_BIN_FLAG_STREAMS_AWARE: Indicates whether the bin can handle elements
- *             that add/remove source pads at any point in time without
- *             first posting a no-more-pads signal (Since: 1.10)
  * @GST_BIN_FLAG_LAST: the last enum in the series of flags for bins.
  * Derived classes can use this as first value in a list of flags.
  *
  * GstBinFlags are a set of flags specific to bins. Most are set/used
- * internally. They can be checked using the GST_OBJECT_FLAG_IS_SET () macro,
- * and (un)set using GST_OBJECT_FLAG_SET () and GST_OBJECT_FLAG_UNSET ().
+ * internally. They can be checked using the GST_OBJECT_FLAG_IS_SET() macro,
+ * and (un)set using GST_OBJECT_FLAG_SET() and GST_OBJECT_FLAG_UNSET().
  */
 typedef enum {
+  /**
+   * GST_BIN_FLAG_NO_RESYNC:
+   *
+   * Don't resync a state change when elements are added or linked in the bin
+   *
+   * Since: 1.0.5
+   */
   GST_BIN_FLAG_NO_RESYNC       = (GST_ELEMENT_FLAG_LAST << 0),
+
+  /**
+   * GST_BIN_FLAG_STREAMS_AWARE:
+   *
+   * Indicates whether the bin can handle elements that add/remove source pads
+   * at any point in time without first posting a no-more-pads signal.
+   *
+   * Since: 1.10
+   */
   GST_BIN_FLAG_STREAMS_AWARE   = (GST_ELEMENT_FLAG_LAST << 1),
+
   /* padding */
+
+  /**
+   * GST_BIN_FLAG_LAST:
+   *
+   * The last enum in the series of flags for bins. Derived classes can use this
+   * as first value in a list of flags.
+   */
   GST_BIN_FLAG_LAST            = (GST_ELEMENT_FLAG_LAST << 5)
 } GstBinFlags;
 
@@ -85,7 +104,7 @@ typedef struct _GstBinPrivate GstBinPrivate;
  * GST_BIN_CHILDREN:
  * @bin: a #GstBin
  *
- * Gets the list with children in a bin.
+ * Gets the list of children in a bin.
  */
 #define GST_BIN_CHILDREN(bin)          (GST_BIN_CAST(bin)->children)
 /**
@@ -141,26 +160,18 @@ struct _GstBin {
 /**
  * GstBinClass:
  * @parent_class: bin parent class
- * @add_element: method to add an element to a bin
- * @remove_element: method to remove an element from a bin
- * @handle_message: method to handle a message from the children
- * @deep_element_added: method called when an element was added somewhere
- *     in the bin hierarchy
- * @deep_element_removed: method called when an element was removed somewhere
- *     in the bin hierarchy
  *
- * Subclasses can override the @add_element and @remove_element to
- * update the list of children in the bin.
+ * Subclasses can override #GstBinClass::add_element and #GstBinClass::remove_element
+ * to update the list of children in the bin.
  *
- * The @handle_message method can be overridden to implement custom
- * message handling.  @handle_message takes ownership of the message, just like
- * #gst_element_post_message.
+ * The #GstBinClass::handle_message method can be overridden to implement custom
+ * message handling.
  *
- * The @deep_element_added vfunc will be called when a new element has been
+ * #GstBinClass::deep_element_added will be called when a new element has been
  * added to any bin inside this bin, so it will also be called if a new child
  * was added to a sub-bin of this bin. #GstBin implementations that override
  * this message should chain up to the parent class implementation so the
- * element-added-deep signal is emitted on all parents.
+ * #GstBin::deep-element-added signal is emitted on all parents.
  */
 struct _GstBinClass {
   GstElementClass parent_class;
@@ -169,14 +180,57 @@ struct _GstBinClass {
   GThreadPool  *pool; /* deprecated */
 
   /* signals */
+
+  /**
+   * GstBinClass::element_added:
+   * @bin: the #GstBin
+   * @child: the element that was added
+   *
+   * Method called when an element was added to the bin.
+   */
   void         (*element_added)        (GstBin *bin, GstElement *child);
+
+  /**
+   * GstBinClass::element_removed:
+   * @bin: the #GstBin
+   * @child: the element that was removed
+   *
+   * Method called when an element was removed from the bin.
+   */
   void         (*element_removed)      (GstBin *bin, GstElement *child);
 
   /*< public >*/
   /* virtual methods for subclasses */
+
+  /**
+   * GstBinClass::add_element:
+   * @bin: the #GstBin
+   * @element: the element to be added
+   *
+   * Method to add an element to the bin.
+   *
+   * Returns: %TRUE if the @element was added
+   */
   gboolean     (*add_element)          (GstBin *bin, GstElement *element);
+
+  /**
+   * GstBinClass::remove_element:
+   * @bin: the #GstBin
+   * @element: the element to be removed
+   *
+   * Method to remove an element from the bin.
+   *
+   * Returns: %TRUE if the @element was removed
+   */
   gboolean     (*remove_element)       (GstBin *bin, GstElement *element);
 
+  /**
+   * GstBinClass::handle_message:
+   * @bin: the #GstBin
+   * @message: (transfer full): the message to be handled
+   *
+   * Method to handle a message from the children.
+   */
   void         (*handle_message)       (GstBin *bin, GstMessage *message);
 
   /*< private >*/
@@ -185,7 +239,25 @@ struct _GstBinClass {
 
   /*< public >*/
   /* signal */
+
+  /**
+   * GstBinClass::deep_element_added:
+   * @bin: the top level #GstBin
+   * @sub_bin: the #GstBin to which the element was added
+   * @child: the element that was added
+   *
+   * Method called when an element was added somewhere in the bin hierarchy.
+   */
   void          (*deep_element_added)   (GstBin *bin, GstBin *sub_bin, GstElement *child);
+
+  /**
+   * GstBinClass::deep_element_removed:
+   * @bin: the top level #GstBin
+   * @sub_bin: the #GstBin from which the element was removed
+   * @child: the element that was removed
+   *
+   * Method called when an element was removed somewhere in the bin hierarchy.
+   */
   void          (*deep_element_removed) (GstBin *bin, GstBin *sub_bin, GstElement *child);
 
   /*< private >*/
@@ -237,6 +309,9 @@ GstIterator*        gst_bin_iterate_sources          (GstBin *bin);
 GST_API
 GstIterator*   gst_bin_iterate_all_by_interface (GstBin *bin, GType iface);
 
+GST_API
+GstIterator*   gst_bin_iterate_all_by_element_factory_name (GstBin * bin, const gchar * factory_name);
+
 /* latency */
 
 GST_API
@@ -250,9 +325,7 @@ void            gst_bin_set_suppressed_flags (GstBin * bin, GstElementFlags flag
 GST_API
 GstElementFlags gst_bin_get_suppressed_flags (GstBin * bin);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBin, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 19a70b4..d3d0898 100644 (file)
@@ -34,7 +34,8 @@
  * 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.
- * |[<!-- language="C" -->
+ *
+ * ``` C 
  *   GstBuffer *buffer;
  *   GstMemory *memory;
  *   gint size, width, height, bpp;
@@ -44,7 +45,7 @@
  *   memory = gst_allocator_alloc (NULL, size, NULL);
  *   gst_buffer_insert_memory (buffer, -1, memory);
  *   ...
- * ]|
+ * ```
  *
  * Alternatively, use gst_buffer_new_allocate() to create a buffer with
  * preallocated data of a given size.
@@ -84,7 +85,7 @@
  *
  * 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
+ * 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
@@ -96,7 +97,7 @@
  * needed.
  *
  * Arbitrary extra metadata can be set on a buffer with gst_buffer_add_meta().
- * Metadata can be retrieved with gst_buffer_get_meta(). See also #GstMeta
+ * Metadata can be retrieved with gst_buffer_get_meta(). See also #GstMeta.
  *
  * An element should either unref the buffer or push it out on a src pad
  * using gst_pad_push() (see #GstPad).
  * using the #GstMemory of the parent buffer, and wants to prevent the parent
  * buffer from being returned to a buffer pool until the #GstMemory is available
  * for re-use. (Since: 1.6)
- *
  */
+
+#define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 #include "gst_private.h"
 
 #ifdef HAVE_UNISTD_H
 #include "gstutils.h"
 #include "gstversion.h"
 
+/* For g_memdup2 */
+#include "glib-compat-private.h"
+
 GType _gst_buffer_type = 0;
 
 /* info->size will be sizeof(FooMeta) which contains a GstMeta at the beginning
@@ -171,28 +176,31 @@ static gint64 meta_seq;         /* 0 *//* ATOMIC */
 /* TODO: use GLib's once https://gitlab.gnome.org/GNOME/glib/issues/1076 lands */
 #if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
 static inline gint64
-gst_atomic_int64_inc (volatile gint64 * atomic)
+gst_atomic_int64_inc (gint64 * atomic)
 {
   return __sync_fetch_and_add (atomic, 1);
 }
 #elif defined (G_PLATFORM_WIN32)
 #include <windows.h>
 static inline gint64
-gst_atomic_int64_inc (volatile gint64 * atomic)
+gst_atomic_int64_inc (gint64 * atomic)
 {
   return InterlockedExchangeAdd64 (atomic, 1);
 }
 #else
-#warning No 64-bit atomic int defined for this platform/toolchain!
+#define STR_TOKEN(s) #s
+#define STR(s) STR_TOKEN(s)
+#pragma message "No 64-bit atomic int defined for this " STR(TARGET_CPU) " platform/toolchain!"
+
 #define NO_64BIT_ATOMIC_INT_FOR_PLATFORM
 G_LOCK_DEFINE_STATIC (meta_seq);
 static inline gint64
-gst_atomic_int64_inc (volatile gint64 * atomic)
+gst_atomic_int64_inc (gint64 * atomic)
 {
   gint64 ret;
 
   G_LOCK (meta_seq);
-  ret = *atomic++;
+  ret = (*atomic)++;
   G_UNLOCK (meta_seq);
 
   return ret;
@@ -234,72 +242,79 @@ _is_span (GstMemory ** mem, gsize len, gsize * poffset, GstMemory ** parent)
 }
 
 static GstMemory *
-_get_merged_memory (GstBuffer * buffer, guint idx, guint length)
+_actual_merged_memory (GstBuffer * buffer, guint idx, guint length)
 {
   GstMemory **mem, *result = NULL;
-
-  GST_CAT_LOG (GST_CAT_BUFFER, "buffer %p, idx %u, length %u", buffer, idx,
-      length);
+  GstMemory *parent = NULL;
+  gsize size, poffset = 0;
 
   mem = GST_BUFFER_MEM_ARRAY (buffer);
 
-  if (G_UNLIKELY (length == 0)) {
-    result = NULL;
-  } else if (G_LIKELY (length == 1)) {
-    result = gst_memory_ref (mem[idx]);
+  size = gst_buffer_get_sizes_range (buffer, idx, length, NULL, NULL);
+
+  if (G_UNLIKELY (_is_span (mem + idx, length, &poffset, &parent))) {
+    if (!GST_MEMORY_IS_NO_SHARE (parent))
+      result = gst_memory_share (parent, poffset, size);
+    if (!result) {
+      GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy for merge %p", parent);
+      result = gst_memory_copy (parent, poffset, size);
+    }
   } else {
-    GstMemory *parent = NULL;
-    gsize size, poffset = 0;
+    gsize i, tocopy, left;
+    GstMapInfo sinfo, dinfo;
+    guint8 *ptr;
+
+    result = gst_allocator_alloc (NULL, size, NULL);
+    if (result == NULL || !gst_memory_map (result, &dinfo, GST_MAP_WRITE)) {
+      GST_CAT_ERROR (GST_CAT_BUFFER, "Failed to map memory writable");
+      if (result)
+        gst_memory_unref (result);
+      return NULL;
+    }
 
-    size = gst_buffer_get_sizes_range (buffer, idx, length, NULL, NULL);
+    ptr = dinfo.data;
+    left = size;
 
-    if (G_UNLIKELY (_is_span (mem + idx, length, &poffset, &parent))) {
-      if (!GST_MEMORY_IS_NO_SHARE (parent))
-        result = gst_memory_share (parent, poffset, size);
-      if (!result) {
-        GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy for merge %p", parent);
-        result = gst_memory_copy (parent, poffset, size);
-      }
-    } else {
-      gsize i, tocopy, left;
-      GstMapInfo sinfo, dinfo;
-      guint8 *ptr;
-
-      result = gst_allocator_alloc (NULL, size, NULL);
-      if (result == NULL || !gst_memory_map (result, &dinfo, GST_MAP_WRITE)) {
-        GST_CAT_ERROR (GST_CAT_BUFFER, "Failed to map memory writable");
-        if (result)
-          gst_memory_unref (result);
+    for (i = idx; i < (idx + length) && left > 0; i++) {
+      if (!gst_memory_map (mem[i], &sinfo, GST_MAP_READ)) {
+        GST_CAT_ERROR (GST_CAT_BUFFER,
+            "buffer %p, idx %u, length %u failed to map readable", buffer,
+            idx, length);
+        gst_memory_unmap (result, &dinfo);
+        gst_memory_unref (result);
         return NULL;
       }
-
-      ptr = dinfo.data;
-      left = size;
-
-      for (i = idx; i < (idx + length) && left > 0; i++) {
-        if (!gst_memory_map (mem[i], &sinfo, GST_MAP_READ)) {
-          GST_CAT_ERROR (GST_CAT_BUFFER,
-              "buffer %p, idx %u, length %u failed to map readable", buffer,
-              idx, length);
-          gst_memory_unmap (result, &dinfo);
-          gst_memory_unref (result);
-          return NULL;
-        }
-        tocopy = MIN (sinfo.size, left);
-        GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
-            "memcpy %" G_GSIZE_FORMAT " bytes for merge %p from memory %p",
-            tocopy, result, mem[i]);
-        memcpy (ptr, (guint8 *) sinfo.data, tocopy);
-        left -= tocopy;
-        ptr += tocopy;
-        gst_memory_unmap (mem[i], &sinfo);
-      }
-      gst_memory_unmap (result, &dinfo);
+      tocopy = MIN (sinfo.size, left);
+      GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
+          "memcpy %" G_GSIZE_FORMAT " bytes for merge %p from memory %p",
+          tocopy, result, mem[i]);
+      memcpy (ptr, (guint8 *) sinfo.data, tocopy);
+      left -= tocopy;
+      ptr += tocopy;
+      gst_memory_unmap (mem[i], &sinfo);
     }
+    gst_memory_unmap (result, &dinfo);
   }
+
   return result;
 }
 
+static inline GstMemory *
+_get_merged_memory (GstBuffer * buffer, guint idx, guint length)
+{
+  GST_CAT_LOG (GST_CAT_BUFFER, "buffer %p, idx %u, length %u", buffer, idx,
+      length);
+
+  if (G_UNLIKELY (length == 0))
+    return NULL;
+
+  if (G_LIKELY (length == 1))
+    return gst_memory_ref (GST_BUFFER_MEM_PTR (buffer, idx));
+
+  return _actual_merged_memory (buffer, idx, length);
+}
+
+
 static void
 _replace_memory (GstBuffer * buffer, guint len, guint idx, guint length,
     GstMemory * mem)
@@ -344,7 +359,7 @@ _replace_memory (GstBuffer * buffer, guint len, guint idx, guint length,
  * gst_buffer_get_flags:
  * @buffer: a #GstBuffer
  *
- * Get the #GstBufferFlags flags set on this buffer.
+ * Gets the #GstBufferFlags flags set on this buffer.
  *
  * Returns: the flags set on this buffer.
  *
@@ -357,7 +372,7 @@ gst_buffer_get_flags (GstBuffer * buffer)
 }
 
 /**
- * gst_buffer_flag_is_set:
+ * gst_buffer_has_flags:
  * @buffer: a #GstBuffer
  * @flags: the #GstBufferFlags flag to check.
  *
@@ -490,7 +505,7 @@ _priv_gst_buffer_initialize (void)
 /**
  * gst_buffer_get_max_memory:
  *
- * Get the maximum amount of memory blocks that a buffer can hold. This is a
+ * Gets the maximum amount of memory blocks that a buffer can hold. This is a
  * compile time constant that can be queried with the function.
  *
  * When more memory blocks are added, existing memory blocks will be merged
@@ -596,7 +611,7 @@ gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src,
     for (i = 0; i < len && left > 0; i++) {
       GstMemory *mem = GST_BUFFER_MEM_PTR (src, i);
 
-      bsize = gst_memory_get_sizes (mem, NULL, NULL);
+      bsize = mem->size;
 
       if (bsize <= skip) {
         /* don't copy buffer */
@@ -719,7 +734,7 @@ _gst_buffer_copy (const GstBuffer * buffer)
  * gst_buffer_copy_deep:
  * @buf: a #GstBuffer.
  *
- * Create a copy of the given buffer. This will make a newly allocated
+ * Creates a copy of the given buffer. This will make a newly allocated
  * copy of the data the source buffer contains.
  *
  * Returns: (transfer full): a new copy of @buf.
@@ -828,8 +843,6 @@ gst_buffer_init (GstBufferImpl * buffer, gsize size)
  *
  * Creates a newly allocated buffer without any data.
  *
- * MT safe.
- *
  * Returns: (transfer full): the new #GstBuffer.
  */
 GstBuffer *
@@ -860,10 +873,7 @@ gst_buffer_new (void)
  *
  * Note that when @size == 0, the buffer will not have memory associated with it.
  *
- * MT safe.
- *
- * Returns: (transfer full) (nullable): a new #GstBuffer, or %NULL if
- *     the memory couldn't be allocated.
+ * Returns: (transfer full) (nullable): a new #GstBuffer
  */
 GstBuffer *
 gst_buffer_new_allocate (GstAllocator * allocator, gsize size,
@@ -961,7 +971,7 @@ no_memory:
  * @user_data: (allow-none): user_data
  * @notify: (allow-none) (scope async) (closure user_data): called with @user_data when the memory is freed
  *
- * Allocate a new buffer that wraps the given memory. @data must point to
+ * Allocates a new buffer that wraps the given memory. @data must point to
  * @maxsize of memory, the wrapped buffer will have the region from @offset and
  * @size visible.
  *
@@ -997,9 +1007,7 @@ gst_buffer_new_wrapped_full (GstMemoryFlags flags, gpointer data,
  * @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.
+ * with g_free() and will be marked writable.
  *
  * Returns: (transfer full): a new #GstBuffer
  */
@@ -1016,8 +1024,6 @@ gst_buffer_new_wrapped (gpointer data, gsize size)
  * Creates a new #GstBuffer that wraps the given @bytes. The data inside
  * @bytes cannot be %NULL and the resulting buffer will be marked as read only.
  *
- * MT safe.
- *
  * Returns: (transfer full): a new #GstBuffer wrapping @bytes
  *
  * Since: 1.16
@@ -1037,10 +1043,29 @@ gst_buffer_new_wrapped_bytes (GBytes * bytes)
 }
 
 /**
+ * gst_buffer_new_memdup:
+ * @data: (array length=size) (element-type guint8) (transfer none): data to copy into new buffer
+ * @size: size of @data in bytes
+ *
+ * Creates a new buffer of size @size and fills it with a copy of @data.
+ *
+ * Returns: (transfer full): a new #GstBuffer
+ *
+ * Since: 1.20
+ */
+GstBuffer *
+gst_buffer_new_memdup (gconstpointer data, gsize size)
+{
+  gpointer data2 = g_memdup2 (data, size);
+
+  return gst_buffer_new_wrapped_full (0, data2, size, 0, size, data2, g_free);
+}
+
+/**
  * gst_buffer_n_memory:
  * @buffer: a #GstBuffer.
  *
- * Get the amount of memory blocks that this buffer has. This amount is never
+ * Gets the amount of memory blocks that this buffer has. This amount is never
  * larger than what gst_buffer_get_max_memory() returns.
  *
  * Returns: the number of memory blocks this buffer is made of.
@@ -1058,7 +1083,7 @@ gst_buffer_n_memory (GstBuffer * buffer)
  * @buffer: a #GstBuffer.
  * @mem: (transfer full): a #GstMemory.
  *
- * Prepend the memory block @mem to @buffer. This function takes
+ * Prepends the memory block @mem to @buffer. This function takes
  * ownership of @mem and thus doesn't increase its refcount.
  *
  * This function is identical to gst_buffer_insert_memory() with an index of 0.
@@ -1075,7 +1100,7 @@ gst_buffer_prepend_memory (GstBuffer * buffer, GstMemory * mem)
  * @buffer: a #GstBuffer.
  * @mem: (transfer full): a #GstMemory.
  *
- * Append the memory block @mem to @buffer. This function takes
+ * Appends the memory block @mem to @buffer. This function takes
  * ownership of @mem and thus doesn't increase its refcount.
  *
  * This function is identical to gst_buffer_insert_memory() with an index of -1.
@@ -1093,7 +1118,7 @@ gst_buffer_append_memory (GstBuffer * buffer, GstMemory * mem)
  * @idx: the index to add the memory at, or -1 to append it to the end
  * @mem: (transfer full): a #GstMemory.
  *
- * Insert the memory block @mem to @buffer at @idx. This function takes ownership
+ * Inserts the memory block @mem into @buffer at @idx. This function takes ownership
  * of @mem and thus doesn't increase its refcount.
  *
  * Only gst_buffer_get_max_memory() can be added to a buffer. If more memory is
@@ -1149,7 +1174,7 @@ _get_mapped (GstBuffer * buffer, guint idx, GstMapInfo * info,
  * @buffer: a #GstBuffer.
  * @idx: an index
  *
- * Get the memory block at @idx in @buffer. The memory block stays valid until
+ * Gets the memory block at @idx in @buffer. The memory block stays valid until
  * the memory block in @buffer is removed, replaced or merged, typically with
  * any call that modifies the memory in @buffer.
  *
@@ -1158,11 +1183,8 @@ _get_mapped (GstBuffer * buffer, guint idx, GstMapInfo * info,
 GstMemory *
 gst_buffer_peek_memory (GstBuffer * buffer, guint idx)
 {
-  guint len;
-
   g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
-  len = GST_BUFFER_MEM_LEN (buffer);
-  g_return_val_if_fail (idx < len, NULL);
+  g_return_val_if_fail (idx < GST_BUFFER_MEM_LEN (buffer), NULL);
 
   return GST_BUFFER_MEM_PTR (buffer, idx);
 }
@@ -1172,10 +1194,10 @@ gst_buffer_peek_memory (GstBuffer * buffer, guint idx)
  * @buffer: a #GstBuffer.
  * @idx: an index
  *
- * Get the memory block at index @idx in @buffer.
+ * Gets the memory block at index @idx in @buffer.
  *
  * Returns: (transfer full) (nullable): a #GstMemory that contains the data of the
- * memory block at @idx. Use gst_memory_unref () after usage.
+ * memory block at @idx.
  */
 GstMemory *
 gst_buffer_get_memory (GstBuffer * buffer, guint idx)
@@ -1187,11 +1209,10 @@ gst_buffer_get_memory (GstBuffer * buffer, guint idx)
  * gst_buffer_get_all_memory:
  * @buffer: a #GstBuffer.
  *
- * Get all the memory block in @buffer. The memory blocks will be merged
+ * Gets all the memory blocks in @buffer. The memory blocks will be merged
  * into one large #GstMemory.
  *
  * Returns: (transfer full) (nullable): a #GstMemory that contains the merged memory.
- * Use gst_memory_unref () after usage.
  */
 GstMemory *
 gst_buffer_get_all_memory (GstBuffer * buffer)
@@ -1205,13 +1226,13 @@ gst_buffer_get_all_memory (GstBuffer * buffer)
  * @idx: an index
  * @length: a length
  *
- * Get @length memory blocks in @buffer starting at @idx. The memory blocks will
+ * Gets @length memory blocks in @buffer starting at @idx. The memory blocks will
  * be merged into one large #GstMemory.
  *
  * If @length is -1, all memory starting from @idx is merged.
  *
  * Returns: (transfer full) (nullable): a #GstMemory that contains the merged data of @length
- *    blocks starting at @idx. Use gst_memory_unref () after usage.
+ *    blocks starting at @idx.
  */
 GstMemory *
 gst_buffer_get_memory_range (GstBuffer * buffer, guint idx, gint length)
@@ -1262,7 +1283,7 @@ gst_buffer_replace_all_memory (GstBuffer * buffer, GstMemory * mem)
  * gst_buffer_replace_memory_range:
  * @buffer: a #GstBuffer.
  * @idx: an index
- * @length: a length should not be 0
+ * @length: a length, should not be 0
  * @mem: (transfer full): a #GstMemory
  *
  * Replaces @length memory blocks in @buffer starting at @idx with @mem.
@@ -1298,7 +1319,7 @@ gst_buffer_replace_memory_range (GstBuffer * buffer, guint idx, gint length,
  * @buffer: a #GstBuffer.
  * @idx: an index
  *
- * Remove the memory block in @b at index @i.
+ * Removes the memory block in @b at index @i.
  */
 void
 gst_buffer_remove_memory (GstBuffer * buffer, guint idx)
@@ -1310,12 +1331,13 @@ gst_buffer_remove_memory (GstBuffer * buffer, guint idx)
  * gst_buffer_remove_all_memory:
  * @buffer: a #GstBuffer.
  *
- * Remove all the memory blocks in @buffer.
+ * Removes all the memory blocks in @buffer.
  */
 void
 gst_buffer_remove_all_memory (GstBuffer * buffer)
 {
-  gst_buffer_remove_memory_range (buffer, 0, -1);
+  if (GST_BUFFER_MEM_LEN (buffer))
+    gst_buffer_remove_memory_range (buffer, 0, -1);
 }
 
 /**
@@ -1324,7 +1346,7 @@ gst_buffer_remove_all_memory (GstBuffer * buffer)
  * @idx: an index
  * @length: a length
  *
- * Remove @length memory blocks in @buffer starting from @idx.
+ * Removes @length memory blocks in @buffer starting from @idx.
  *
  * @length can be -1, in which case all memory starting from @idx is removed.
  */
@@ -1357,7 +1379,7 @@ gst_buffer_remove_memory_range (GstBuffer * buffer, guint idx, gint length)
  * @length: (out): pointer to length
  * @skip: (out): pointer to skip
  *
- * Find the memory blocks that span @size bytes starting from @offset
+ * Finds the memory blocks that span @size bytes starting from @offset
  * in @buffer.
  *
  * When this function returns %TRUE, @idx will contain the index of the first
@@ -1390,7 +1412,7 @@ gst_buffer_find_memory (GstBuffer * buffer, gsize offset, gsize size,
     gsize s;
 
     mem = GST_BUFFER_MEM_PTR (buffer, i);
-    s = gst_memory_get_sizes (mem, NULL, NULL);
+    s = mem->size;
 
     if (s <= offset) {
       /* block before offset, or empty block, skip */
@@ -1425,9 +1447,9 @@ gst_buffer_find_memory (GstBuffer * buffer, gsize offset, gsize size,
  * gst_buffer_is_memory_range_writable:
  * @buffer: a #GstBuffer.
  * @idx: an index
- * @length: a length should not be 0
+ * @length: a length, should not be 0
  *
- * Check if @length memory blocks in @buffer starting from @idx are writable.
+ * Checks if @length memory blocks in @buffer starting from @idx are writable.
  *
  * @length can be -1 to check all the memory blocks after @idx.
  *
@@ -1468,7 +1490,7 @@ gst_buffer_is_memory_range_writable (GstBuffer * buffer, guint idx, gint length)
  * gst_buffer_is_all_memory_writable:
  * @buffer: a #GstBuffer.
  *
- * Check if all memory blocks in @buffer are writable.
+ * Checks if all memory blocks in @buffer are writable.
  *
  * Note that this function does not check if @buffer is writable, use
  * gst_buffer_is_writable() to check that if needed.
@@ -1489,7 +1511,7 @@ gst_buffer_is_all_memory_writable (GstBuffer * buffer)
  * @offset: (out) (allow-none): a pointer to the offset
  * @maxsize: (out) (allow-none): a pointer to the maxsize
  *
- * Get the total size of the memory blocks in @b.
+ * Gets the total size of the memory blocks in @buffer.
  *
  * 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
@@ -1509,14 +1531,23 @@ gst_buffer_get_sizes (GstBuffer * buffer, gsize * offset, gsize * maxsize)
  * gst_buffer_get_size:
  * @buffer: a #GstBuffer.
  *
- * Get the total size of the memory blocks in @buffer.
+ * Gets the total size of the memory blocks in @buffer.
  *
  * Returns: total size of the memory blocks in @buffer.
  */
 gsize
 gst_buffer_get_size (GstBuffer * buffer)
 {
-  return gst_buffer_get_sizes_range (buffer, 0, -1, NULL, NULL);
+  guint i;
+  gsize size, len;
+
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+
+  /* FAST PATH */
+  len = GST_BUFFER_MEM_LEN (buffer);
+  for (i = 0, size = 0; i < len; i++)
+    size += GST_BUFFER_MEM_PTR (buffer, i)->size;
+  return size;
 }
 
 /**
@@ -1527,7 +1558,7 @@ gst_buffer_get_size (GstBuffer * buffer)
  * @offset: (out) (allow-none): a pointer to the offset
  * @maxsize: (out) (allow-none): a pointer to the maxsize
  *
- * Get the total size of @length memory blocks stating from @idx in @buffer.
+ * Gets the total size of @length memory blocks stating from @idx in @buffer.
  *
  * When not %NULL, @offset will contain the offset of the data in the
  * memory block in @buffer at @idx and @maxsize will contain the sum of the size
@@ -1558,6 +1589,16 @@ gst_buffer_get_sizes_range (GstBuffer * buffer, guint idx, gint length,
     /* common case */
     mem = GST_BUFFER_MEM_PTR (buffer, idx);
     size = gst_memory_get_sizes (mem, offset, maxsize);
+  } else if (offset == NULL && maxsize == NULL) {
+    /* FAST PATH ! */
+    guint i, end;
+
+    size = 0;
+    end = idx + length;
+    for (i = idx; i < end; i++) {
+      mem = GST_BUFFER_MEM_PTR (buffer, i);
+      size += mem->size;
+    }
   } else {
     guint i, end;
     gsize extra, offs;
@@ -1597,7 +1638,7 @@ gst_buffer_get_sizes_range (GstBuffer * buffer, guint idx, gint length,
  * @offset: the offset adjustment
  * @size: the new size or -1 to just adjust the offset
  *
- * Set the offset and total size of the memory blocks in @buffer.
+ * Sets the offset and total size of the memory blocks in @buffer.
  */
 void
 gst_buffer_resize (GstBuffer * buffer, gssize offset, gssize size)
@@ -1610,7 +1651,7 @@ gst_buffer_resize (GstBuffer * buffer, gssize offset, gssize size)
  * @buffer: a #GstBuffer.
  * @size: the new size
  *
- * Set the total size of the memory blocks in @buffer.
+ * Sets the total size of the memory blocks in @buffer.
  */
 void
 gst_buffer_set_size (GstBuffer * buffer, gssize size)
@@ -1626,7 +1667,7 @@ gst_buffer_set_size (GstBuffer * buffer, gssize size)
  * @offset: the offset adjustment
  * @size: the new size or -1 to just adjust the offset
  *
- * Set the total size of the @length memory blocks starting at @idx in
+ * Sets the total size of the @length memory blocks starting at @idx in
  * @buffer
  *
  * Returns: %TRUE if resizing succeeded, %FALSE otherwise.
@@ -1675,7 +1716,7 @@ gst_buffer_resize_range (GstBuffer * buffer, guint idx, gint length,
     gsize left, noffs;
 
     mem = GST_BUFFER_MEM_PTR (buffer, i);
-    bsize = gst_memory_get_sizes (mem, NULL, NULL);
+    bsize = mem->size;
 
     noffs = 0;
     /* last buffer always gets resized to the remaining size */
@@ -1729,11 +1770,10 @@ gst_buffer_resize_range (GstBuffer * buffer, guint idx, gint length,
 /**
  * gst_buffer_map:
  * @buffer: a #GstBuffer.
- * @info: (out): info about the mapping
+ * @info: (out caller-allocates): info about the mapping
  * @flags: flags for the mapping
  *
- * This function fills @info with the #GstMapInfo of all merged memory
- * blocks in @buffer.
+ * Fills @info with the #GstMapInfo of all merged memory blocks in @buffer.
  *
  * @flags describe the desired access of the memory. When @flags is
  * #GST_MAP_WRITE, @buffer should be writable (as returned from
@@ -1759,10 +1799,10 @@ gst_buffer_map (GstBuffer * buffer, GstMapInfo * info, GstMapFlags flags)
  * @buffer: a #GstBuffer.
  * @idx: an index
  * @length: a length
- * @info: (out): info about the mapping
+ * @info: (out caller-allocates): info about the mapping
  * @flags: flags for the mapping
  *
- * This function fills @info with the #GstMapInfo of @length merged memory blocks
+ * Fills @info with the #GstMapInfo of @length merged memory blocks
  * starting at @idx in @buffer. When @length is -1, all memory blocks starting
  * from @idx are merged and mapped.
  *
@@ -1859,7 +1899,7 @@ cannot_map:
  * @buffer: a #GstBuffer.
  * @info: a #GstMapInfo
  *
- * Release the memory previously mapped with gst_buffer_map().
+ * Releases the memory previously mapped with gst_buffer_map().
  */
 void
 gst_buffer_unmap (GstBuffer * buffer, GstMapInfo * info)
@@ -1882,7 +1922,7 @@ gst_buffer_unmap (GstBuffer * buffer, GstMapInfo * info)
  * @src: (array length=size) (element-type guint8): the source address
  * @size: the size to fill
  *
- * Copy @size bytes from @src to @buffer at @offset.
+ * Copies @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.
@@ -1935,7 +1975,7 @@ gst_buffer_fill (GstBuffer * buffer, gsize offset, gconstpointer src,
  *     the destination address
  * @size: the size to extract
  *
- * Copy @size bytes starting from @offset in @buffer to @dest.
+ * Copies @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.
@@ -1985,7 +2025,7 @@ gst_buffer_extract (GstBuffer * buffer, gsize offset, gpointer dest, gsize size)
  * @mem: (array length=size) (element-type guint8): the memory to compare
  * @size: the size to compare
  *
- * Compare @size bytes starting from @offset in @buffer with the memory in @mem.
+ * Compares @size bytes starting from @offset in @buffer with the memory in @mem.
  *
  * Returns: 0 if the memory is equal.
  */
@@ -2038,7 +2078,7 @@ gst_buffer_memcmp (GstBuffer * buffer, gsize offset, gconstpointer mem,
  * @val: the value to set
  * @size: the size to set
  *
- * Fill @buf with @size bytes with @val starting from @offset.
+ * Fills @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.
@@ -2097,8 +2137,6 @@ gst_buffer_memset (GstBuffer * buffer, gsize offset, guint8 val, gsize size)
  * duration and offset end fields are also copied. If not they will be set
  * to #GST_CLOCK_TIME_NONE and #GST_BUFFER_OFFSET_NONE.
  *
- * MT safe.
- *
  * Returns: (transfer full): the new #GstBuffer or %NULL if the arguments were
  *     invalid.
  */
@@ -2127,7 +2165,7 @@ gst_buffer_copy_region (GstBuffer * buffer, GstBufferCopyFlags flags,
  * @buf1: (transfer full): the first source #GstBuffer to append.
  * @buf2: (transfer full): the second source #GstBuffer to append.
  *
- * Append all the memory from @buf2 to @buf1. The result buffer will contain a
+ * Appends all the memory from @buf2 to @buf1. The result buffer will contain a
  * concatenation of the memory of @buf1 and @buf2.
  *
  * Returns: (transfer full): the new #GstBuffer that contains the memory
@@ -2146,7 +2184,7 @@ gst_buffer_append (GstBuffer * buf1, GstBuffer * buf2)
  * @offset: the offset in @buf2
  * @size: the size or -1 of @buf2
  *
- * Append @size bytes at @offset from @buf2 to @buf1. The result buffer will
+ * Appends @size bytes at @offset from @buf2 to @buf1. The result buffer will
  * contain a concatenation of the memory of @buf1 and the requested region of
  * @buf2.
  *
@@ -2190,14 +2228,13 @@ gst_buffer_append_region (GstBuffer * buf1, GstBuffer * buf2, gssize offset,
  * @buffer: a #GstBuffer
  * @api: the #GType of an API
  *
- * Get the metadata for @api on buffer. When there is no such metadata, %NULL is
+ * Gets the metadata for @api on buffer. When there is no such metadata, %NULL is
  * returned. If multiple metadata with the given @api are attached to this
  * buffer only the first one is returned.  To handle multiple metadata with a
  * given API use gst_buffer_iterate_meta() or gst_buffer_foreach_meta() instead
- * and check the meta->info.api member for the API type.
+ * and check the `meta->info.api` member for the API type.
  *
- * Returns: (transfer none) (nullable): the metadata for @api on
- * @buffer.
+ * Returns: (transfer none) (nullable): the metadata for @api on @buffer.
  */
 GstMeta *
 gst_buffer_get_meta (GstBuffer * buffer, GType api)
@@ -2247,7 +2284,7 @@ gst_buffer_get_n_meta (GstBuffer * buffer, GType api_type)
  * @info: a #GstMetaInfo
  * @params: params for @info
  *
- * Add metadata for @info to @buffer using the parameters in @params.
+ * Adds metadata for @info to @buffer using the parameters in @params.
  *
  * Returns: (transfer none) (nullable): the metadata for the api in @info on @buffer.
  */
@@ -2310,7 +2347,7 @@ init_failed:
  * @buffer: a #GstBuffer
  * @meta: a #GstMeta
  *
- * Remove the metadata for @meta on @buffer.
+ * Removes the metadata for @meta on @buffer.
  *
  * Returns: %TRUE if the metadata existed and was removed, %FALSE if no such
  * metadata was on @buffer.
@@ -2364,7 +2401,7 @@ gst_buffer_remove_meta (GstBuffer * buffer, GstMeta * meta)
  * @buffer: a #GstBuffer
  * @state: (out caller-allocates): an opaque state pointer
  *
- * Retrieve the next #GstMeta after @current. If @state points
+ * Retrieves the next #GstMeta after @current. If @state points
  * to %NULL, the first metadata is returned.
  *
  * @state will be updated with an opaque state pointer
@@ -2400,7 +2437,7 @@ gst_buffer_iterate_meta (GstBuffer * buffer, gpointer * state)
  * @state: (out caller-allocates): an opaque state pointer
  * @meta_api_type: only return #GstMeta of this type
  *
- * Retrieve the next #GstMeta of type @meta_api_type after the current one
+ * Retrieves the next #GstMeta of type @meta_api_type after the current one
  * according to @state. If @state points to %NULL, the first metadata of
  * type @meta_api_type is returned.
  *
@@ -2443,10 +2480,10 @@ gst_buffer_iterate_meta_filtered (GstBuffer * buffer, gpointer * state,
  * @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.
+ * Calls @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
+ * of @func defines if this function returns or if the remaining metadata items
  * in the buffer should be skipped.
  *
  * Returns: %FALSE when @func returned %FALSE for one of the metadata.
@@ -2549,7 +2586,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_parent_buffer_meta_debug);
  * @buffer: (transfer none): a #GstBuffer
  * @ref: (transfer none): a #GstBuffer to ref
  *
- * Add a #GstParentBufferMeta to @buffer that holds a reference on
+ * Adds a #GstParentBufferMeta to @buffer that holds a reference on
  * @ref until the buffer is freed.
  *
  * Returns: (transfer none) (nullable): The #GstParentBufferMeta that was added to the buffer
@@ -2615,7 +2652,7 @@ static gboolean
 _gst_parent_buffer_meta_init (GstParentBufferMeta * parent_meta,
     gpointer params, GstBuffer * buffer)
 {
-  static volatile gsize _init;
+  static gsize _init;
 
   if (g_once_init_enter (&_init)) {
     GST_DEBUG_CATEGORY_INIT (gst_parent_buffer_meta_debug, "parentbuffermeta",
@@ -2628,10 +2665,13 @@ _gst_parent_buffer_meta_init (GstParentBufferMeta * parent_meta,
   return TRUE;
 }
 
+/**
+ * gst_parent_buffer_meta_api_get_type: (attributes doc.skip=true)
+ */
 GType
 gst_parent_buffer_meta_api_get_type (void)
 {
-  static volatile GType type = 0;
+  static GType type = 0;
   static const gchar *tags[] = { NULL };
 
   if (g_once_init_enter (&type)) {
@@ -2645,7 +2685,7 @@ gst_parent_buffer_meta_api_get_type (void)
 /**
  * gst_parent_buffer_meta_get_info:
  *
- * Get the global #GstMetaInfo describing  the #GstParentBufferMeta meta.
+ * Gets the global #GstMetaInfo describing  the #GstParentBufferMeta meta.
  *
  * Returns: (transfer none): The #GstMetaInfo
  *
@@ -2679,7 +2719,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_reference_timestamp_meta_debug);
  * @timestamp: timestamp
  * @duration: duration, or %GST_CLOCK_TIME_NONE
  *
- * Add a #GstReferenceTimestampMeta to @buffer that holds a @timestamp and
+ * Adds a #GstReferenceTimestampMeta to @buffer that holds a @timestamp and
  * optionally @duration based on a specific timestamp @reference. See the
  * documentation of #GstReferenceTimestampMeta for details.
  *
@@ -2715,7 +2755,7 @@ gst_buffer_add_reference_timestamp_meta (GstBuffer * buffer,
  * @buffer: a #GstBuffer
  * @reference: (allow-none): a reference #GstCaps
  *
- * Find the first #GstReferenceTimestampMeta on @buffer that conforms to
+ * Finds the first #GstReferenceTimestampMeta on @buffer that conforms to
  * @reference. Conformance is tested by checking if the meta's reference is a
  * subset of @reference.
  *
@@ -2781,7 +2821,7 @@ static gboolean
 _gst_reference_timestamp_meta_init (GstReferenceTimestampMeta * meta,
     gpointer params, GstBuffer * buffer)
 {
-  static volatile gsize _init;
+  static gsize _init;
 
   if (g_once_init_enter (&_init)) {
     GST_DEBUG_CATEGORY_INIT (gst_reference_timestamp_meta_debug,
@@ -2796,10 +2836,13 @@ _gst_reference_timestamp_meta_init (GstReferenceTimestampMeta * meta,
   return TRUE;
 }
 
+/**
+ * gst_reference_timestamp_meta_api_get_type: (attributes doc.skip=true)
+ */
 GType
 gst_reference_timestamp_meta_api_get_type (void)
 {
-  static volatile GType type = 0;
+  static GType type = 0;
   static const gchar *tags[] = { NULL };
 
   if (g_once_init_enter (&type)) {
@@ -2814,7 +2857,7 @@ gst_reference_timestamp_meta_api_get_type (void)
 /**
  * gst_reference_timestamp_meta_get_info:
  *
- * Get the global #GstMetaInfo describing  the #GstReferenceTimestampMeta meta.
+ * Gets the global #GstMetaInfo describing the #GstReferenceTimestampMeta meta.
  *
  * Returns: (transfer none): The #GstMetaInfo
  *
@@ -2838,3 +2881,157 @@ gst_reference_timestamp_meta_get_info (void)
 
   return meta_info;
 }
+
+/**
+ * gst_buffer_add_custom_meta:
+ * @buffer: (transfer none): a #GstBuffer
+ * @name: the registered name of the desired custom meta
+ *
+ * Creates and adds a #GstCustomMeta for the desired @name. @name must have
+ * been successfully registered with gst_meta_register_custom().
+ *
+ * Returns: (transfer none) (nullable): The #GstCustomMeta that was added to the buffer
+ *
+ * Since: 1.20
+ */
+GstCustomMeta *
+gst_buffer_add_custom_meta (GstBuffer * buffer, const gchar * name)
+{
+  GstCustomMeta *meta;
+  const GstMetaInfo *info;
+
+  g_return_val_if_fail (name != NULL, NULL);
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
+
+  info = gst_meta_get_info (name);
+
+  if (info == NULL || !gst_meta_info_is_custom (info))
+    return NULL;
+
+  meta = (GstCustomMeta *) gst_buffer_add_meta (buffer, info, NULL);
+
+  return meta;
+}
+
+/**
+ * gst_buffer_get_custom_meta:
+ * @buffer: a #GstBuffer
+ * @name: the registered name of the custom meta to retrieve.
+ *
+ * Finds the first #GstCustomMeta on @buffer for the desired @name.
+ *
+ * Returns: (transfer none) (nullable): the #GstCustomMeta
+ *
+ * Since: 1.20
+ */
+GstCustomMeta *
+gst_buffer_get_custom_meta (GstBuffer * buffer, const gchar * name)
+{
+  const GstMetaInfo *info;
+
+  g_return_val_if_fail (buffer != NULL, NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+
+  info = gst_meta_get_info (name);
+
+  if (!info)
+    return NULL;
+
+  if (!gst_meta_info_is_custom (info))
+    return NULL;
+
+  return (GstCustomMeta *) gst_buffer_get_meta (buffer, info->api);
+}
+
+/**
+ * gst_buffer_ref: (skip)
+ * @buf: a #GstBuffer.
+ *
+ * Increases the refcount of the given buffer by one.
+ *
+ * Note that the refcount affects the writability
+ * of @buf and its metadata, see gst_buffer_is_writable().
+ * It is important to note that keeping additional references to
+ * GstBuffer instances can potentially increase the number
+ * of `memcpy` operations in a pipeline.
+ *
+ * Returns: (transfer full): @buf
+ */
+GstBuffer *
+gst_buffer_ref (GstBuffer * buf)
+{
+  return (GstBuffer *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (buf));
+}
+
+/**
+ * gst_buffer_unref: (skip)
+ * @buf: (transfer full): a #GstBuffer.
+ *
+ * Decreases the refcount of the buffer. If the refcount reaches 0, the buffer
+ * with the associated metadata and memory will be freed.
+ */
+void
+gst_buffer_unref (GstBuffer * buf)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (buf));
+}
+
+/**
+ * gst_clear_buffer: (skip)
+ * @buf_ptr: a pointer to a #GstBuffer reference
+ *
+ * Clears a reference to a #GstBuffer.
+ *
+ * @buf_ptr must not be %NULL.
+ *
+ * If the reference is %NULL then this function does nothing. Otherwise, the
+ * reference count of the buffer is decreased and the pointer is set to %NULL.
+ *
+ * Since: 1.16
+ */
+void
+gst_clear_buffer (GstBuffer ** buf_ptr)
+{
+  gst_clear_mini_object ((GstMiniObject **) buf_ptr);
+}
+
+/**
+ * gst_buffer_copy: (skip)
+ * @buf: a #GstBuffer.
+ *
+ * Creates a copy of the given buffer. This will only copy the buffer's
+ * data to a newly allocated memory if needed (if the type of memory
+ * requires it), otherwise the underlying data is just referenced.
+ * Check gst_buffer_copy_deep() if you want to force the data
+ * to be copied to newly allocated memory.
+ *
+ * Returns: (transfer full): a new copy of @buf.
+ */
+GstBuffer *
+gst_buffer_copy (const GstBuffer * buf)
+{
+  return GST_BUFFER (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (buf)));
+}
+
+/**
+ * gst_buffer_replace: (skip)
+ * @obuf: (inout) (transfer full) (nullable): pointer to a pointer to
+ *     a #GstBuffer to be replaced.
+ * @nbuf: (transfer none) (allow-none): pointer to a #GstBuffer that will
+ *     replace the buffer pointed to by @obuf.
+ *
+ * Modifies a pointer to a #GstBuffer to point to a different #GstBuffer. 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
+ * 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.
+ */
+gboolean
+gst_buffer_replace (GstBuffer ** obuf, GstBuffer * nbuf)
+{
+  return gst_mini_object_replace ((GstMiniObject **) obuf,
+      (GstMiniObject *) nbuf);
+}
index c0491fb..ee352d9 100644 (file)
@@ -47,7 +47,7 @@ typedef struct _GstBufferPool GstBufferPool;
  * GST_BUFFER_FLAGS:
  * @buf: a #GstBuffer.
  *
- * A flags word containing #GstBufferFlags flags set on this buffer.
+ * Returns a flags word containing #GstBufferFlags flags set on this buffer.
  */
 #define GST_BUFFER_FLAGS(buf)                   GST_MINI_OBJECT_FLAGS(buf)
 /**
@@ -80,25 +80,27 @@ typedef struct _GstBufferPool GstBufferPool;
  * GST_BUFFER_PTS:
  * @buf: a #GstBuffer.:
  *
- * The presentation timestamp (pts) in nanoseconds (as a #GstClockTime)
+ * Gets 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_PTS(buf)                     (GST_BUFFER_CAST(buf)->pts)
 /**
  * GST_BUFFER_DTS:
- * @buf: a #GstBuffer.:
+ * @buf: a #GstBuffer.
  *
- * The decoding timestamp (dts) in nanoseconds (as a #GstClockTime)
+ * Gets 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_DTS(buf)                     (GST_BUFFER_CAST(buf)->dts)
 /**
  * GST_BUFFER_DTS_OR_PTS:
- * @buf: a #GstBuffer.:
+ * @buf: a #GstBuffer.
  *
  * Returns the buffer decoding timestamp (dts) if valid, else the buffer
  * presentation time (pts)
@@ -110,7 +112,8 @@ typedef struct _GstBufferPool GstBufferPool;
  * GST_BUFFER_DURATION:
  * @buf: a #GstBuffer.
  *
- * The duration in nanoseconds (as a #GstClockTime) of the data in the buffer.
+ * Gets the duration in nanoseconds (as a #GstClockTime) of the data in the buffer.
+ *
  * Value will be %GST_CLOCK_TIME_NONE if the duration is unknown.
  */
 #define GST_BUFFER_DURATION(buf)                (GST_BUFFER_CAST(buf)->duration)
@@ -118,14 +121,14 @@ typedef struct _GstBufferPool GstBufferPool;
  * GST_BUFFER_OFFSET:
  * @buf: a #GstBuffer.
  *
- * The offset in the source file of the beginning of this buffer.
+ * Gets the offset in the source file of the beginning of this buffer.
  */
 #define GST_BUFFER_OFFSET(buf)                  (GST_BUFFER_CAST(buf)->offset)
 /**
  * GST_BUFFER_OFFSET_END:
  * @buf: a #GstBuffer.
  *
- * The offset in the source file of the end of this buffer.
+ * Gets the offset in the source file of the end of this buffer.
  */
 #define GST_BUFFER_OFFSET_END(buf)              (GST_BUFFER_CAST(buf)->offset_end)
 
@@ -194,8 +197,8 @@ typedef struct _GstBufferPool GstBufferPool;
  *                                 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 start of a talkspurt.
+ *                                 video this is the end of a frame boundary, for audio
+ *                                 this is the start 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
@@ -207,14 +210,6 @@ typedef struct _GstBufferPool GstBufferPool;
  * @GST_BUFFER_FLAG_DELTA_UNIT:    this unit cannot be decoded independently.
  * @GST_BUFFER_FLAG_TAG_MEMORY:    this flag is set when memory of the buffer
  *                                 is added/removed
- * @GST_BUFFER_FLAG_SYNC_AFTER:    Elements which write to disk or permanent
- *                              storage should ensure the data is synced after
- *                              writing the contents of this buffer. (Since: 1.6)
- * @GST_BUFFER_FLAG_NON_DROPPABLE: This buffer is important and should not be dropped.
- *                                 This can be used to mark important buffers, e.g. to flag
- *                                 RTP packets carrying keyframes or codec setup data for RTP
- *                                 Forward Error Correction purposes, or to prevent still video
- *                                 frames from being dropped by elements due to QoS. (Since: 1.14)
  * @GST_BUFFER_FLAG_LAST:          additional media specific flags can be added starting from
  *                                 this flag.
  *
@@ -232,7 +227,29 @@ typedef enum {
   GST_BUFFER_FLAG_DROPPABLE     = (GST_MINI_OBJECT_FLAG_LAST << 8),
   GST_BUFFER_FLAG_DELTA_UNIT    = (GST_MINI_OBJECT_FLAG_LAST << 9),
   GST_BUFFER_FLAG_TAG_MEMORY    = (GST_MINI_OBJECT_FLAG_LAST << 10),
+
+  /**
+   * GST_BUFFER_FLAG_SYNC_AFTER:
+   *
+   * Elements which write to disk or permanent storage should ensure the data
+   * is synced after writing the contents of this buffer.
+   *
+   * Since: 1.6
+   */
   GST_BUFFER_FLAG_SYNC_AFTER    = (GST_MINI_OBJECT_FLAG_LAST << 11),
+
+  /**
+   * GST_BUFFER_FLAG_NON_DROPPABLE:
+   *
+   * This buffer is important and should not be dropped.
+   *
+   * This can be used to mark important buffers, e.g. to flag RTP packets
+   * carrying keyframes or codec setup data for RTP Forward Error Correction
+   * purposes, or to prevent still video frames from being dropped by elements
+   * due to QoS.
+   *
+   * Since: 1.14
+   */
   GST_BUFFER_FLAG_NON_DROPPABLE = (GST_MINI_OBJECT_FLAG_LAST << 12),
 
   GST_BUFFER_FLAG_LAST          = (GST_MINI_OBJECT_FLAG_LAST << 16)
@@ -297,9 +314,13 @@ GstBuffer * gst_buffer_new_wrapped_full    (GstMemoryFlags flags, gpointer data,
                                             GDestroyNotify notify);
 GST_API
 GstBuffer * gst_buffer_new_wrapped         (gpointer data, gsize size);
+
 GST_API
 GstBuffer * gst_buffer_new_wrapped_bytes   (GBytes * bytes);
 
+GST_API
+GstBuffer * gst_buffer_new_memdup           (gconstpointer data, gsize size);
+
 /* memory blocks */
 
 GST_API
@@ -409,54 +430,20 @@ GST_API
 gboolean       gst_buffer_unset_flags      (GstBuffer * buffer, GstBufferFlags flags);
 
 
-
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 /* refcounting */
-/**
- * gst_buffer_ref:
- * @buf: a #GstBuffer.
- *
- * Increases the refcount of the given buffer by one.
- *
- * Note that the refcount affects the writability
- * of @buf and its metadata, see gst_buffer_is_writable().
- * It is important to note that keeping additional references to
- * GstBuffer instances can potentially increase the number
- * of memcpy operations in a pipeline.
- *
- * Returns: (transfer full): @buf
- */
 static inline GstBuffer *
 gst_buffer_ref (GstBuffer * buf)
 {
   return (GstBuffer *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (buf));
 }
 
-/**
- * gst_buffer_unref:
- * @buf: (transfer full): a #GstBuffer.
- *
- * Decreases the refcount of the buffer. If the refcount reaches 0, the buffer
- * with the associated metadata and memory will be freed.
- */
 static inline void
 gst_buffer_unref (GstBuffer * buf)
 {
   gst_mini_object_unref (GST_MINI_OBJECT_CAST (buf));
 }
 
-/**
- * gst_clear_buffer: (skip)
- * @buf_ptr: a pointer to a #GstBuffer reference
- *
- * Clears a reference to a #GstBuffer.
- *
- * @buf_ptr must not be %NULL.
- *
- * If the reference is %NULL then this function does nothing. Otherwise, the
- * reference count of the buffer is decreased and the pointer is set to %NULL.
- *
- * Since: 1.16
- */
 static inline void
 gst_clear_buffer (GstBuffer ** buf_ptr)
 {
@@ -464,23 +451,24 @@ gst_clear_buffer (GstBuffer ** buf_ptr)
 }
 
 /* copy buffer */
-/**
- * gst_buffer_copy:
- * @buf: a #GstBuffer.
- *
- * Create a copy of the given buffer. This will only copy the buffer's
- * data to a newly allocated memory if needed (if the type of memory
- * requires it), otherwise the underlying data is just referenced.
- * Check gst_buffer_copy_deep() if you want to force the data
- * to be copied to newly allocated memory.
- *
- * Returns: (transfer full): a new copy of @buf.
- */
 static inline GstBuffer *
 gst_buffer_copy (const GstBuffer * buf)
 {
   return GST_BUFFER (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (buf)));
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+GstBuffer * gst_buffer_ref       (GstBuffer * buf);
+
+GST_API
+void        gst_buffer_unref     (GstBuffer * buf);
+
+GST_API
+void        gst_clear_buffer     (GstBuffer ** buf_ptr);
+
+GST_API
+GstBuffer * gst_buffer_copy      (const GstBuffer * buf);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 GST_API
 GstBuffer * gst_buffer_copy_deep (const GstBuffer * buf);
@@ -499,8 +487,6 @@ GstBuffer * gst_buffer_copy_deep (const GstBuffer * buf);
  *   merged
  * @GST_BUFFER_COPY_META: flag indicating that buffer meta should be
  *   copied
- * @GST_BUFFER_COPY_DEEP: flag indicating that memory should always be
- *   copied instead of reffed (Since: 1.2)
  *
  * A set of flags that can be provided to the gst_buffer_copy_into()
  * function to specify which items should be copied.
@@ -512,6 +498,14 @@ typedef enum {
   GST_BUFFER_COPY_META           = (1 << 2),
   GST_BUFFER_COPY_MEMORY         = (1 << 3),
   GST_BUFFER_COPY_MERGE          = (1 << 4),
+
+  /**
+   * GST_BUFFER_COPY_DEEP:
+   *
+   * flag indicating that memory should always be copied instead of reffed
+   *
+   * Since: 1.2
+   */
   GST_BUFFER_COPY_DEEP           = (1 << 5)
 } GstBufferCopyFlags;
 
@@ -576,27 +570,17 @@ gboolean        gst_buffer_copy_into            (GstBuffer *dest, GstBuffer *src
  */
 #define         gst_buffer_make_writable(buf)   GST_BUFFER_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (buf)))
 
-/**
- * gst_buffer_replace:
- * @obuf: (inout) (transfer full) (nullable): pointer to a pointer to
- *     a #GstBuffer to be replaced.
- * @nbuf: (transfer none) (allow-none): pointer to a #GstBuffer that will
- *     replace the buffer pointed to by @obuf.
- *
- * Modifies a pointer to a #GstBuffer to point to a different #GstBuffer. 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
- * 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.
- */
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 static inline gboolean
 gst_buffer_replace (GstBuffer **obuf, GstBuffer *nbuf)
 {
   return gst_mini_object_replace ((GstMiniObject **) obuf, (GstMiniObject *) nbuf);
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+gboolean        gst_buffer_replace              (GstBuffer ** obuf,
+                                                 GstBuffer * nbuf);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 /* creating a region */
 
@@ -660,6 +644,14 @@ gboolean        gst_buffer_foreach_meta         (GstBuffer *buffer,
                                                  GstBufferForeachMetaFunc func,
                                                  gpointer user_data);
 
+GST_API
+GstCustomMeta * gst_buffer_add_custom_meta      (GstBuffer *buffer,
+                                                 const gchar *name);
+
+GST_API
+GstCustomMeta * gst_buffer_get_custom_meta      (GstBuffer *buffer,
+                                                 const gchar *name);
+
 /**
  * gst_value_set_buffer:
  * @v: a #GValue to receive the data
@@ -725,7 +717,7 @@ GType gst_parent_buffer_meta_api_get_type (void);
  * gst_buffer_get_parent_buffer_meta:
  * @b: a #GstBuffer
  *
- * Find and return a #GstParentBufferMeta if one exists on the
+ * Finds and returns a #GstParentBufferMeta if one exists on the
  * buffer
  */
 #define gst_buffer_get_parent_buffer_meta(b) \
@@ -756,10 +748,10 @@ typedef struct _GstReferenceTimestampMeta GstReferenceTimestampMeta;
  * captured.
  *
  * The reference is stored as a #GstCaps in @reference. Examples of valid
- * references would be "timestamp/x-drivername-stream" for timestamps that are locally
- * generated by some driver named "drivername" when generating the stream,
- * e.g. based on a frame counter, or "timestamp/x-ntp, host=pool.ntp.org,
- * port=123" for timestamps based on a specific NTP server.
+ * references would be `timestamp/x-drivername-stream` for timestamps that are locally
+ * generated by some driver named `drivername` when generating the stream,
+ * e.g. based on a frame counter, or `timestamp/x-ntp, host=pool.ntp.org,
+ * port=123` for timestamps based on a specific NTP server.
  *
  * Since: 1.14
  */
@@ -792,13 +784,9 @@ GST_API
 GstReferenceTimestampMeta * gst_buffer_get_reference_timestamp_meta (GstBuffer * buffer,
                                                                      GstCaps   * reference);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBuffer, gst_buffer_unref)
-#endif
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBufferPool, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 2c13597..dca4335 100644 (file)
  * Buffer lists are an object containing a list of buffers.
  *
  * Buffer lists are created with gst_buffer_list_new() and filled with data
- * using gst_buffer_list_insert().
+ * using gst_buffer_list_insert().
  *
  * Buffer lists can be pushed on a srcpad with gst_pad_push_list(). This is
  * interesting when multiple buffers need to be pushed in one go because it
  * can reduce the amount of overhead for pushing each buffer individually.
  */
+#define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 #include "gst_private.h"
 
 #include "gstbuffer.h"
@@ -146,14 +147,10 @@ gst_buffer_list_init (GstBufferList * list, guint n_allocated, gsize slice_size)
  * 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.
+ * Creates a new, empty #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.
+ * Returns: (transfer full): the new #GstBufferList.
  */
 GstBufferList *
 gst_buffer_list_new_sized (guint size)
@@ -181,13 +178,9 @@ gst_buffer_list_new_sized (guint size)
 /**
  * gst_buffer_list_new:
  *
- * Creates a new, empty #GstBufferList. The caller is responsible for unreffing
- * the returned #GstBufferList.
- *
- * Free-function: gst_buffer_list_unref
+ * Creates a new, empty #GstBufferList.
  *
- * Returns: (transfer full): the new #GstBufferList. gst_buffer_list_unref()
- *     after usage.
+ * Returns: (transfer full): the new #GstBufferList.
  */
 GstBufferList *
 gst_buffer_list_new (void)
@@ -239,10 +232,10 @@ gst_buffer_list_remove_range_internal (GstBufferList * list, guint idx,
  * @func: (scope call): a #GstBufferListFunc to call
  * @user_data: (closure): user data passed to @func
  *
- * Call @func with @data for each buffer in @list.
+ * Calls @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
+ * of @func defines if this function returns or if the remaining buffers in
  * the list should be skipped.
  *
  * Returns: %TRUE when @func returned %TRUE for each buffer in @list or when
@@ -307,8 +300,11 @@ gst_buffer_list_foreach (GstBufferList * list, GstBufferListFunc func,
         gst_buffer_list_remove_range_internal (list, i, 1, !was_writable);
         --len;
       } else {
-        if (!was_writable)
+        if (!was_writable) {
+          gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (buf),
+              GST_MINI_OBJECT_CAST (list));
           gst_buffer_unref (buf);
+        }
 
         list->buffers[i] = buf_ret;
         gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (buf_ret),
@@ -337,7 +333,7 @@ gst_buffer_list_foreach (GstBufferList * list, GstBufferListFunc func,
  * @list: a #GstBufferList
  * @idx: the index
  *
- * Get the buffer at @idx.
+ * Gets the buffer at @idx.
  *
  * You must make sure that @idx does not exceed the number of
  * buffers available.
@@ -409,7 +405,7 @@ gst_buffer_list_get_writable (GstBufferList * list, guint idx)
  * @idx: the index
  * @buffer: (transfer full): a #GstBuffer
  *
- * Insert @buffer at @idx in @list. Other buffers are moved to make room for
+ * Inserts @buffer at @idx in @list. Other buffers are moved to make room for
  * this new buffer.
  *
  * A -1 value for @idx will append the buffer at the end.
@@ -436,6 +432,9 @@ gst_buffer_list_insert (GstBufferList * list, gint idx, GstBuffer * buffer)
   want_alloc = list->n_buffers + 1;
 
   if (want_alloc > list->n_allocated) {
+    if (G_UNLIKELY (list->n_allocated > (G_MAXUINT / 2)))
+      g_error ("Growing GstBufferList would result in overflow");
+
     want_alloc = MAX (GST_ROUND_UP_16 (want_alloc), list->n_allocated * 2);
 
     if (GST_BUFFER_LIST_IS_USING_DYNAMIC_ARRAY (list)) {
@@ -466,7 +465,7 @@ gst_buffer_list_insert (GstBufferList * list, gint idx, GstBuffer * buffer)
  * @idx: the index
  * @length: the amount to remove
  *
- * Remove @length buffers starting from @idx in @list. The following buffers
+ * Removes @length buffers starting from @idx in @list. The following buffers
  * are moved to close the gap.
  */
 void
@@ -484,8 +483,8 @@ gst_buffer_list_remove (GstBufferList * list, guint idx, guint length)
  * gst_buffer_list_copy_deep:
  * @list: a #GstBufferList
  *
- * Create a copy of the given buffer list. This will make a newly allocated
- * copy of the buffer that the source buffer list contains.
+ * Creates a copy of the given buffer list. This will make a newly allocated
+ * copy of the buffers that the source buffer list contains.
  *
  * Returns: (transfer full): a new copy of @list.
  *
@@ -523,10 +522,10 @@ gst_buffer_list_copy_deep (const GstBufferList * list)
  * gst_buffer_list_calculate_size:
  * @list: a #GstBufferList
  *
- * Calculates the size of the data contained in buffer list by adding the
+ * Calculates the size of the data contained in @list by adding the
  * size of all buffers.
  *
- * Returns: the size of the data contained in buffer list in bytes.
+ * Returns: the size of the data contained in @list in bytes.
  *
  * Since: 1.14
  */
@@ -547,3 +546,120 @@ gst_buffer_list_calculate_size (GstBufferList * list)
 
   return size;
 }
+
+/**
+ * gst_buffer_list_ref: (skip)
+ * @list: a #GstBufferList
+ *
+ * Increases the refcount of the given buffer list by one.
+ *
+ * Note that the refcount affects the writability of @list and its data, see
+ * gst_buffer_list_make_writable(). It is important to note that keeping
+ * additional references to GstBufferList instances can potentially increase
+ * the number of memcpy operations in a pipeline.
+ *
+ * Returns: (transfer full): @list
+ */
+GstBufferList *
+gst_buffer_list_ref (GstBufferList * list)
+{
+  return
+      GST_BUFFER_LIST_CAST (gst_mini_object_ref (GST_MINI_OBJECT_CAST (list)));
+}
+
+/**
+ * gst_buffer_list_unref: (skip)
+ * @list: (transfer full): a #GstBufferList
+ *
+ * Decreases the refcount of the buffer list. If the refcount reaches 0, the
+ * buffer list will be freed.
+ */
+void
+gst_buffer_list_unref (GstBufferList * list)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (list));
+}
+
+/**
+ * gst_clear_buffer_list: (skip)
+ * @list_ptr: a pointer to a #GstBufferList reference
+ *
+ * Clears a reference to a #GstBufferList.
+ *
+ * @list_ptr must not be %NULL.
+ *
+ * If the reference is %NULL then this function does nothing. Otherwise, the
+ * reference count of the list is decreased and the pointer is set to %NULL.
+ *
+ * Since: 1.16
+ */
+void
+gst_clear_buffer_list (GstBufferList ** list_ptr)
+{
+  gst_clear_mini_object ((GstMiniObject **) list_ptr);
+}
+
+/**
+ * gst_buffer_list_copy: (skip)
+ * @list: a #GstBufferList
+ *
+ * Creates a shallow copy of the given buffer list. This will make a newly
+ * allocated copy of the source list with copies of buffer pointers. The
+ * refcount of buffers pointed to will be increased by one.
+ *
+ * Returns: (transfer full): a new copy of @list.
+ */
+GstBufferList *
+gst_buffer_list_copy (const GstBufferList * list)
+{
+  return
+      GST_BUFFER_LIST_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST
+          (list)));
+}
+
+/**
+ * gst_buffer_list_replace:
+ * @old_list: (inout) (transfer full) (nullable): pointer to a pointer to a
+ *     #GstBufferList to be replaced.
+ * @new_list: (transfer none) (allow-none): pointer to a #GstBufferList that
+ *     will replace the buffer list pointed to by @old_list.
+ *
+ * Modifies a pointer to a #GstBufferList to point to a different
+ * #GstBufferList. 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 buffer list is unreffed, the new is reffed).
+ *
+ * Either @new_list or the #GstBufferList pointed to by @old_list may be %NULL.
+ *
+ * Returns: %TRUE if @new_list was different from @old_list
+ *
+ * Since: 1.16
+ */
+gboolean
+gst_buffer_list_replace (GstBufferList ** old_list, GstBufferList * new_list)
+{
+  return gst_mini_object_replace ((GstMiniObject **) old_list,
+      (GstMiniObject *) new_list);
+}
+
+/**
+ * gst_buffer_list_take:
+ * @old_list: (inout) (transfer full): pointer to a pointer to a #GstBufferList
+ *     to be replaced.
+ * @new_list: (transfer full) (allow-none): pointer to a #GstBufferList
+ *     that will replace the bufferlist pointed to by @old_list.
+ *
+ * Modifies a pointer to a #GstBufferList to point to a different
+ * #GstBufferList. This function is similar to gst_buffer_list_replace() except
+ * that it takes ownership of @new_list.
+ *
+ * Returns: %TRUE if @new_list was different from @old_list
+ *
+ * Since: 1.16
+ */
+gboolean
+gst_buffer_list_take (GstBufferList ** old_list, GstBufferList * new_list)
+{
+  return gst_mini_object_take ((GstMiniObject **) old_list,
+      (GstMiniObject *) new_list);
+}
index 3e2bcbc..6077717 100644 (file)
@@ -38,7 +38,7 @@ typedef struct _GstBufferList GstBufferList;
 
 /**
  * GstBufferListFunc:
- * @buffer: (out) (nullable): pointer the buffer
+ * @buffer: (out) (nullable): pointer to the buffer
  * @idx: the index of @buffer
  * @user_data: user data passed to gst_buffer_list_foreach()
  *
@@ -58,21 +58,8 @@ typedef struct _GstBufferList GstBufferList;
 typedef gboolean   (*GstBufferListFunc)   (GstBuffer **buffer, guint idx,
                                            gpointer user_data);
 
-
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 /* refcounting */
-/**
- * gst_buffer_list_ref:
- * @list: a #GstBufferList
- *
- * Increases the refcount of the given buffer list by one.
- *
- * Note that the refcount affects the writability of @list and its data, see
- * gst_buffer_list_make_writable(). It is important to note that keeping
- * additional references to GstBufferList instances can potentially increase
- * the number of memcpy operations in a pipeline.
- *
- * Returns: (transfer full): @list
- */
 static inline GstBufferList *
 gst_buffer_list_ref (GstBufferList * list)
 {
@@ -80,32 +67,12 @@ gst_buffer_list_ref (GstBufferList * list)
       list)));
 }
 
-/**
- * gst_buffer_list_unref:
- * @list: (transfer full): a #GstBufferList
- *
- * Decreases the refcount of the buffer list. If the refcount reaches 0, the
- * buffer list will be freed.
- */
 static inline void
-gst_buffer_list_unref (GstBufferList * list)
+gst_buffer_list_unref(GstBufferList* list)
 {
   gst_mini_object_unref (GST_MINI_OBJECT_CAST (list));
 }
 
-/**
- * gst_clear_buffer_list: (skip)
- * @list_ptr: a pointer to a #GstBufferList reference
- *
- * Clears a reference to a #GstBufferList.
- *
- * @list_ptr must not be %NULL.
- *
- * If the reference is %NULL then this function does nothing. Otherwise, the
- * reference count of the list is decreased and the pointer is set to %NULL.
- *
- * Since: 1.16
- */
 static inline void
 gst_clear_buffer_list (GstBufferList ** list_ptr)
 {
@@ -113,40 +80,12 @@ gst_clear_buffer_list (GstBufferList ** list_ptr)
 }
 
 /* copy */
-/**
- * gst_buffer_list_copy:
- * @list: a #GstBufferList
- *
- * Create a shallow copy of the given buffer list. This will make a newly
- * allocated copy of the source list with copies of buffer pointers. The
- * refcount of buffers pointed to will be increased by one.
- *
- * Returns: (transfer full): a new copy of @list.
- */
 static inline GstBufferList *
 gst_buffer_list_copy (const GstBufferList * list)
 {
   return GST_BUFFER_LIST_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (list)));
 }
 
-/**
- * gst_buffer_list_replace:
- * @old_list: (inout) (transfer full) (nullable): pointer to a pointer to a
- *     #GstBufferList to be replaced.
- * @new_list: (transfer none) (allow-none): pointer to a #GstBufferList that
- *     will replace the buffer list pointed to by @old_list.
- *
- * Modifies a pointer to a #GstBufferList to point to a different
- * #GstBufferList. 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 buffer list is unreffed, the new is reffed).
- *
- * Either @new_list or the #GstBufferList pointed to by @old_list may be %NULL.
- *
- * Returns: %TRUE if @new_list was different from @old_list
- *
- * Since: 1.16
- */
 static inline gboolean
 gst_buffer_list_replace (GstBufferList **old_list, GstBufferList *new_list)
 {
@@ -154,27 +93,33 @@ gst_buffer_list_replace (GstBufferList **old_list, GstBufferList *new_list)
       (GstMiniObject *) new_list);
 }
 
-/**
- * gst_buffer_list_take:
- * @old_list: (inout) (transfer full): pointer to a pointer to a #GstBufferList
- *     to be replaced.
- * @new_list: (transfer full) (allow-none): pointer to a #GstBufferList
- *     that will replace the bufferlist pointed to by @old_list.
- *
- * Modifies a pointer to a #GstBufferList to point to a different
- * #GstBufferList. This function is similar to gst_buffer_list_replace() except
- * that it takes ownership of @new_list.
- *
- * Returns: %TRUE if @new_list was different from @old_list
- *
- * Since: 1.16
- */
 static inline gboolean
 gst_buffer_list_take (GstBufferList **old_list, GstBufferList *new_list)
 {
   return gst_mini_object_take ((GstMiniObject **) old_list,
       (GstMiniObject *) new_list);
 }
+#else  /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+GstBufferList * gst_buffer_list_ref     (GstBufferList * list);
+
+GST_API
+void            gst_buffer_list_unref   (GstBufferList * list);
+
+GST_API
+void            gst_clear_buffer_list   (GstBufferList ** list_ptr);
+
+GST_API
+GstBufferList * gst_buffer_list_copy    (const GstBufferList * list);
+
+GST_API
+gboolean        gst_buffer_list_replace (GstBufferList ** old_list,
+                                         GstBufferList * new_list);
+
+GST_API
+gboolean        gst_buffer_list_take    (GstBufferList ** old_list,
+                                         GstBufferList * new_list);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 /**
  * gst_buffer_list_is_writable:
@@ -235,9 +180,7 @@ gsize                    gst_buffer_list_calculate_size        (GstBufferList *
 
 #define gst_buffer_list_add(l,b) gst_buffer_list_insert((l),-1,(b));
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBufferList, gst_buffer_list_unref)
-#endif
 
 G_END_DECLS
 
index 619860e..4d0bdf4 100644 (file)
@@ -46,7 +46,7 @@
  * gst_buffer_pool_set_config() updates the configuration in the pool. This can
  * fail when the configuration structure is not accepted.
  *
- * After the pool has been configured, it can be activated with
+ * After the pool has been configured, it can be activated with
  * gst_buffer_pool_set_active(). This will preallocate the configured resources
  * in the pool.
  *
@@ -59,9 +59,6 @@
  * The bufferpool can be deactivated again with gst_buffer_pool_set_active().
  * All further gst_buffer_pool_acquire_buffer() calls will return an error. When
  * all buffers are returned to the pool they will be freed.
- *
- * Use gst_object_unref() to release the reference to a bufferpool. If the
- * refcount of the pool reaches 0, the pool will be freed.
  */
 
 #include "gst_private.h"
@@ -477,7 +474,7 @@ do_set_flushing (GstBufferPool * pool, gboolean flushing)
  * @pool: a #GstBufferPool
  * @active: the new active state
  *
- * Control the active state of @pool. When the pool is inactive, new calls to
+ * Controls the active state of @pool. When the pool is inactive, new calls to
  * gst_buffer_pool_acquire_buffer() will return with %GST_FLOW_FLUSHING.
  *
  * Activating the bufferpool will preallocate all resources in the pool based on
@@ -572,7 +569,7 @@ stop_failed:
  * gst_buffer_pool_is_active:
  * @pool: a #GstBufferPool
  *
- * Check if @pool is active. A pool can be activated with the
+ * Checks if @pool is active. A pool can be activated with the
  * gst_buffer_pool_set_active() call.
  *
  * Returns: %TRUE when the pool is active.
@@ -633,10 +630,10 @@ wrong_config:
  * @pool: a #GstBufferPool
  * @config: (transfer full): a #GstStructure
  *
- * Set the configuration of the pool. If the pool is already configured, and
- * the configuration haven't change, this function will return %TRUE. If the
+ * Sets the configuration of the pool. If the pool is already configured, and
+ * the configuration hasn't changed, this function will return %TRUE. If the
  * pool is active, this method will return %FALSE and active configuration
- * will remain. Buffers allocated form this pool must be returned or else this
+ * will remain. Buffers allocated from 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
@@ -727,12 +724,10 @@ have_outstanding:
  * 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.
+ * Gets a copy of the current configuration of the pool. This configuration
+ * can be modified and used for the gst_buffer_pool_set_config() call.
  *
- * Returns: (transfer full): a copy of the current configuration of @pool. use
- * gst_structure_free() after usage or gst_buffer_pool_set_config().
+ * Returns: (transfer full): a copy of the current configuration of @pool.
  */
 GstStructure *
 gst_buffer_pool_get_config (GstBufferPool * pool)
@@ -754,7 +749,7 @@ 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
+ * Gets 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().
  *
@@ -792,7 +787,7 @@ invalid_result:
  * @pool: a #GstBufferPool
  * @option: an option
  *
- * Check if the bufferpool supports @option.
+ * Checks if the bufferpool supports @option.
  *
  * Returns: %TRUE if the buffer pool contains @option.
  */
@@ -817,12 +812,12 @@ gst_buffer_pool_has_option (GstBufferPool * pool, const gchar * option)
 /**
  * gst_buffer_pool_config_set_params:
  * @config: a #GstBufferPool configuration
- * @caps: caps for the buffers
+ * @caps: (nullable): caps for the buffers
  * @size: the size of each buffer, not including prefix and padding
  * @min_buffers: the minimum amount of buffers to allocate.
  * @max_buffers: the maximum amount of buffers to allocate or 0 for unlimited.
  *
- * Configure @config with the given parameters.
+ * Configures @config with the given parameters.
  */
 void
 gst_buffer_pool_config_set_params (GstStructure * config, GstCaps * caps,
@@ -842,10 +837,10 @@ gst_buffer_pool_config_set_params (GstStructure * config, GstCaps * caps,
 /**
  * gst_buffer_pool_config_set_allocator:
  * @config: a #GstBufferPool configuration
- * @allocator: (allow-none): a #GstAllocator
- * @params: (allow-none): #GstAllocationParams
+ * @allocator: (nullable): a #GstAllocator
+ * @params: (nullable): #GstAllocationParams
  *
- * Set the @allocator and @params on @config.
+ * Sets the @allocator and @params on @config.
  *
  * One of @allocator and @params can be %NULL, but not both. When @allocator
  * is %NULL, the default allocator of the pool will use the values in @param
@@ -875,10 +870,10 @@ gst_buffer_pool_config_set_allocator (GstStructure * config,
  * @config: a #GstBufferPool configuration
  * @option: an option to add
  *
- * Enabled the option in @config. This will instruct the @bufferpool to enable
+ * Enables 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().
+ * The options supported by @pool can be retrieved with gst_buffer_pool_get_options().
  */
 void
 gst_buffer_pool_config_add_option (GstStructure * config, const gchar * option)
@@ -914,7 +909,7 @@ gst_buffer_pool_config_add_option (GstStructure * config, const gchar * option)
  * gst_buffer_pool_config_n_options:
  * @config: a #GstBufferPool configuration
  *
- * Retrieve the number of values currently stored in the options array of the
+ * Retrieves the number of values currently stored in the options array of the
  * @config structure.
  *
  * Returns: the options array size as a #guint.
@@ -939,10 +934,10 @@ gst_buffer_pool_config_n_options (GstStructure * config)
  * @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
+ * Parses an available @config and gets the option at @index of the options API
  * array.
  *
- * Returns: a #gchar of the option at @index.
+ * Returns: (nullable): the option at @index.
  */
 const gchar *
 gst_buffer_pool_config_get_option (GstStructure * config, guint index)
@@ -968,7 +963,7 @@ gst_buffer_pool_config_get_option (GstStructure * config, guint index)
  * @config: a #GstBufferPool configuration
  * @option: an option
  *
- * Check if @config contains @option.
+ * Checks if @config contains @option.
  *
  * Returns: %TRUE if the options array contains @option.
  */
@@ -996,12 +991,12 @@ gst_buffer_pool_config_has_option (GstStructure * config, const gchar * option)
 /**
  * gst_buffer_pool_config_get_params:
  * @config: (transfer none): a #GstBufferPool configuration
- * @caps: (out) (transfer none) (allow-none): the caps of buffers
- * @size: (out) (allow-none): the size of each buffer, not including prefix and padding
- * @min_buffers: (out) (allow-none): the minimum amount of buffers to allocate.
- * @max_buffers: (out) (allow-none): the maximum amount of buffers to allocate or 0 for unlimited.
+ * @caps: (out) (transfer none) (optional) (nullable): the caps of buffers
+ * @size: (out) (optional): the size of each buffer, not including prefix and padding
+ * @min_buffers: (out) (optional): the minimum amount of buffers to allocate.
+ * @max_buffers: (out) (optional): the maximum amount of buffers to allocate or 0 for unlimited.
  *
- * Get the configuration values from @config.
+ * Gets the configuration values from @config.
  *
  * Returns: %TRUE if all parameters could be fetched.
  */
@@ -1024,10 +1019,10 @@ gst_buffer_pool_config_get_params (GstStructure * config, GstCaps ** caps,
 /**
  * gst_buffer_pool_config_get_allocator:
  * @config: (transfer none): a #GstBufferPool configuration
- * @allocator: (out) (allow-none) (transfer none): a #GstAllocator, or %NULL
- * @params: (out) (allow-none): #GstAllocationParams, or %NULL
+ * @allocator: (out) (optional) (nullable) (transfer none): a #GstAllocator, or %NULL
+ * @params: (out caller-allocates) (optional): #GstAllocationParams, or %NULL
  *
- * Get the @allocator and @params from @config.
+ * Gets the @allocator and @params from @config.
  *
  * Returns: %TRUE, if the values are set.
  */
@@ -1057,12 +1052,12 @@ gst_buffer_pool_config_get_allocator (GstStructure * config,
 /**
  * gst_buffer_pool_config_validate_params:
  * @config: (transfer none): a #GstBufferPool configuration
- * @caps: (transfer none): the excepted caps of buffers
+ * @caps: (nullable) (transfer none): the excepted caps of buffers
  * @size: the expected size of each buffer, not including prefix and padding
  * @min_buffers: the expected minimum amount of buffers to allocate.
  * @max_buffers: the expect maximum amount of buffers to allocate or 0 for unlimited.
  *
- * Validate that changes made to @config are still valid in the context of the
+ * Validates that changes made to @config are still valid in the context of the
  * expected parameters. This function is a helper that can be used to validate
  * changes made by a pool to a config when gst_buffer_pool_set_config()
  * returns %FALSE. This expects that @caps haven't changed and that
@@ -1223,9 +1218,21 @@ default_reset_buffer (GstBufferPool * pool, GstBuffer * buffer)
 
   /* if the memory is intact reset the size to the full size */
   if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY)) {
-    gsize offset;
-    gst_buffer_get_sizes (buffer, &offset, NULL);
-    gst_buffer_resize (buffer, -offset, pool->priv->size);
+    gsize offset, maxsize;
+    gst_buffer_get_sizes (buffer, &offset, &maxsize);
+    /* check if we can resize to at least the pool configured size.  If not,
+     * then this will fail internally in gst_buffer_resize().
+     * default_release_buffer() will drop the buffer from the pool if the
+     * sizes don't match */
+    if (maxsize >= pool->priv->size) {
+      gst_buffer_resize (buffer, -offset, pool->priv->size);
+    } else {
+      GST_WARNING_OBJECT (pool, "Buffer %p without the memory tag has "
+          "maxsize (%" G_GSIZE_FORMAT ") that is smaller than the "
+          "configured buffer pool size (%u). The buffer will be not be "
+          "reused. This is most likely a bug in this GstBufferPool subclass",
+          buffer, maxsize, pool->priv->size);
+    }
   }
 
   /* remove all metadata without the POOLED flag */
@@ -1238,11 +1245,10 @@ default_reset_buffer (GstBufferPool * pool, GstBuffer * buffer)
  * @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
+ * Acquires 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.
+ * @params can contain optional parameters to influence the allocation.
  *
  * Returns: a #GstFlowReturn such as %GST_FLOW_FLUSHING when the pool is
  * inactive.
@@ -1326,6 +1332,7 @@ not_writable:
 discard:
   {
     do_free_buffer (pool, buffer);
+    gst_poll_write_control (pool->priv->poll);
     return;
   }
 }
@@ -1335,7 +1342,7 @@ discard:
  * @pool: a #GstBufferPool
  * @buffer: (transfer full): a #GstBuffer
  *
- * Release @buffer to @pool. @buffer should have previously been allocated from
+ * Releases @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
@@ -1374,7 +1381,7 @@ gst_buffer_pool_release_buffer (GstBufferPool * pool, GstBuffer * buffer)
  * @pool: a #GstBufferPool
  * @flushing: whether to start or stop flushing
  *
- * Enable or disable the flushing state of a @pool without freeing or
+ * Enables or disables the flushing state of a @pool without freeing or
  * allocating buffers.
  *
  * Since: 1.4
index 0efd24f..18b73a0 100644 (file)
@@ -98,6 +98,8 @@ struct _GstBufferPoolAcquireParams {
 
 /**
  * GstBufferPool:
+ * @object: the parent structure
+ * @flushing: whether the pool is currently gathering back outstanding buffers
  *
  * The structure of a #GstBufferPool. Use the associated macros to access the public
  * variables.
@@ -117,58 +119,150 @@ struct _GstBufferPool {
 /**
  * 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 configured memory allocator and with the configured
- *        parameters. All metadata that is present on the allocated buffer will
- *        be marked as #GST_META_FLAG_POOLED and #GST_META_FLAG_LOCKED and will
- *        not be removed from the buffer in @reset_buffer. The buffer should
- *        have the GST_BUFFER_FLAG_TAG_MEMORY cleared.
- * @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 without the #GST_META_FLAG_POOLED flag (even
- *        the metadata with #GST_META_FLAG_LOCKED). If the
- *        #GST_BUFFER_FLAG_TAG_MEMORY was set, this function can also try to
- *        restore the memory and clear the #GST_BUFFER_FLAG_TAG_MEMORY again.
- * @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 when the #GST_BUFFER_FLAG_TAG_MEMORY
- *        is not set on the buffer. If #GST_BUFFER_FLAG_TAG_MEMORY is set, the
- *        buffer will be freed with @free_buffer.
- * @free_buffer: free a buffer. The default implementation unrefs the buffer.
- * @flush_start: enter the flushing state. (Since: 1.4)
- * @flush_stop: leave the flushign state. (Since: 1.4)
  *
- * The GstBufferPool class.
+ * The #GstBufferPool class.
  */
 struct _GstBufferPoolClass {
   GstObjectClass    object_class;
 
   /*< public >*/
+
+  /**
+   * GstBufferPoolClass::get_options:
+   * @pool: the #GstBufferPool
+   *
+   * Get a list of options supported by this pool
+   *
+   * Returns: (array zero-terminated=1) (transfer none): a %NULL terminated array
+   *          of strings.
+   */
   const gchar ** (*get_options)    (GstBufferPool *pool);
+
+  /**
+   * GstBufferPoolClass::set_config:
+   * @pool: the #GstBufferPool
+   * @config: the required configuration
+   *
+   * Apply the bufferpool configuration. The default configuration will parse
+   * the default config parameters.
+   *
+   * Returns: whether the configuration could be set.
+   */
   gboolean       (*set_config)     (GstBufferPool *pool, GstStructure *config);
 
+  /**
+   * GstBufferPoolClass::start:
+   * @pool: the #GstBufferPool
+   *
+   * Start the bufferpool. The default implementation will preallocate
+   * min-buffers buffers and put them in the queue.
+   *
+   * Returns: whether the pool could be started.
+   */
   gboolean       (*start)          (GstBufferPool *pool);
+
+  /**
+   * GstBufferPoolClass::stop:
+   * @pool: the #GstBufferPool
+   *
+   * Stop the bufferpool. the default implementation will free the
+   * preallocated buffers. This function is called when all the buffers are
+   * returned to the pool.
+   *
+   * Returns: whether the pool could be stopped.
+   */
   gboolean       (*stop)           (GstBufferPool *pool);
 
+  /**
+   * GstBufferPoolClass::acquire_buffer:
+   * @pool: the #GstBufferPool
+   * @buffer: (out): a location for a #GstBuffer
+   * @params: (transfer none) (allow-none): parameters.
+   *
+   * 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.
+   *
+   * Returns: a #GstFlowReturn such as %GST_FLOW_FLUSHING when the pool is
+   * inactive.
+   */
   GstFlowReturn  (*acquire_buffer) (GstBufferPool *pool, GstBuffer **buffer,
                                     GstBufferPoolAcquireParams *params);
+
+  /**
+   * GstBufferPoolClass::alloc_buffer:
+   * @pool: the #GstBufferPool
+   * @buffer: (out): a location for a #GstBuffer
+   * @params: (transfer none) (allow-none): parameters.
+   *
+   * Allocate a buffer. the default implementation allocates
+   * buffers from the configured memory allocator and with the configured
+   * parameters. All metadata that is present on the allocated buffer will
+   * be marked as #GST_META_FLAG_POOLED and #GST_META_FLAG_LOCKED and will
+   * not be removed from the buffer in #GstBufferPoolClass::reset_buffer.
+   * The buffer should have the #GST_BUFFER_FLAG_TAG_MEMORY cleared.
+   *
+   * Returns: a #GstFlowReturn to indicate whether the allocation was
+   * successful.
+   */
   GstFlowReturn  (*alloc_buffer)   (GstBufferPool *pool, GstBuffer **buffer,
                                     GstBufferPoolAcquireParams *params);
+
+  /**
+   * GstBufferPoolClass::reset_buffer:
+   * @pool: the #GstBufferPool
+   * @buffer: the #GstBuffer to reset
+   *
+   * Reset the buffer to its state when it was freshly allocated.
+   * The default implementation will clear the flags, timestamps and
+   * will remove the metadata without the #GST_META_FLAG_POOLED flag (even
+   * the metadata with #GST_META_FLAG_LOCKED). If the
+   * #GST_BUFFER_FLAG_TAG_MEMORY was set, this function can also try to
+   * restore the memory and clear the #GST_BUFFER_FLAG_TAG_MEMORY again.
+   */
   void           (*reset_buffer)   (GstBufferPool *pool, GstBuffer *buffer);
+
+  /**
+   * GstBufferPoolClass::release_buffer:
+   * @pool: the #GstBufferPool
+   * @buffer: the #GstBuffer to release
+   *
+   * Release a buffer back in the pool. The default implementation
+   * will put the buffer back in the queue and notify any
+   * blocking #GstBufferPoolClass::acquire_buffer calls when the
+   * #GST_BUFFER_FLAG_TAG_MEMORY is not set on the buffer.
+   * If #GST_BUFFER_FLAG_TAG_MEMORY is set, the buffer will be freed with
+   * #GstBufferPoolClass::free_buffer.
+   */
   void           (*release_buffer) (GstBufferPool *pool, GstBuffer *buffer);
+
+  /**
+   * GstBufferPoolClass::free_buffer:
+   * @pool: the #GstBufferPool
+   * @buffer: the #GstBuffer to free
+   *
+   * Free a buffer. The default implementation unrefs the buffer.
+   */
   void           (*free_buffer)    (GstBufferPool *pool, GstBuffer *buffer);
+
+  /**
+   * GstBufferPoolClass::flush_start:
+   * @pool: the #GstBufferPool
+   *
+   * Enter the flushing state.
+   *
+   * Since: 1.4
+   */
   void           (*flush_start)    (GstBufferPool *pool);
+
+  /**
+   * GstBufferPoolClass::flush_stop:
+   * @pool: the #GstBufferPool
+   *
+   * Leave the flushing state.
+   *
+   * Since: 1.4
+   */
   void           (*flush_stop)     (GstBufferPool *pool);
 
   /*< private >*/
index cddaf39..15cf16b 100644 (file)
@@ -35,7 +35,7 @@
  * is done in another thread than the application.
  *
  * The GstBus provides support for #GSource based notifications. This makes it
- * possible to handle the delivery in the glib mainloop.
+ * possible to handle the delivery in the glib #GMainLoop.
  *
  * The #GSource callback function gst_bus_async_signal_func() can be used to
  * convert all bus messages into signal emissions.
@@ -109,19 +109,45 @@ static void gst_bus_finalize (GObject * object);
 
 static guint gst_bus_signals[LAST_SIGNAL] = { 0 };
 
+typedef struct
+{
+  GstBusSyncHandler handler;
+  gpointer user_data;
+  GDestroyNotify destroy_notify;
+  gint ref_count;
+} SyncHandler;
+
+static SyncHandler *
+sync_handler_ref (SyncHandler * handler)
+{
+  g_atomic_int_inc (&handler->ref_count);
+
+  return handler;
+}
+
+static void
+sync_handler_unref (SyncHandler * handler)
+{
+  if (!g_atomic_int_dec_and_test (&handler->ref_count))
+    return;
+
+  if (handler->destroy_notify)
+    handler->destroy_notify (handler->user_data);
+
+  g_free (handler);
+}
+
 struct _GstBusPrivate
 {
   GstAtomicQueue *queue;
   GMutex queue_lock;
 
-  GstBusSyncHandler sync_handler;
-  gpointer sync_handler_data;
-  GDestroyNotify sync_handler_notify;
+  SyncHandler *sync_handler;
 
   guint num_signal_watchers;
 
   guint num_sync_message_emitters;
-  GSource *signal_watch;
+  GSource *gsource;
 
   gboolean enable_async;
   GstPoll *poll;
@@ -171,9 +197,9 @@ gst_bus_class_init (GstBusClass * klass)
   gobject_class->constructed = gst_bus_constructed;
 
   /**
-   * GstBus::enable-async:
+   * GstBus:enable-async:
    *
-   * Enable async message delivery support for bus watches,
+   * Enables async message delivery support for bus watches,
    * gst_bus_pop() and similar API. Without this only the
    * synchronous message handlers are called.
    *
@@ -188,7 +214,7 @@ gst_bus_class_init (GstBusClass * klass)
 
   /**
    * GstBus::sync-message:
-   * @bus: the object which received the signal
+   * @self: the object which received the signal
    * @message: the message that has been posted synchronously
    *
    * A message has been posted on the bus. This signal is emitted from the
@@ -201,22 +227,22 @@ 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,
-      g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
+      NULL, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
 
   /**
    * GstBus::message:
-   * @bus: the object which received the signal
+   * @self: the object which received the signal
    * @message: the message that has been posted asynchronously
    *
    * A message has been posted on the bus. This signal is emitted from a
-   * GSource added to the mainloop. this signal will only be emitted when
-   * there is a mainloop running.
+   * #GSource added to the mainloop. this signal will only be emitted when
+   * there is a #GMainLoop running.
    */
   gst_bus_signals[ASYNC_MESSAGE] =
       g_signal_new ("message", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
       G_STRUCT_OFFSET (GstBusClass, message), NULL, NULL,
-      g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
+      NULL, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
 }
 
 static void
@@ -262,8 +288,8 @@ gst_bus_finalize (GObject * object)
 {
   GstBus *bus = GST_BUS (object);
 
-  if (bus->priv->sync_handler_notify)
-    bus->priv->sync_handler_notify (bus->priv->sync_handler_data);
+  if (bus->priv->sync_handler)
+    sync_handler_unref (g_steal_pointer (&bus->priv->sync_handler));
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -294,20 +320,17 @@ gst_bus_new (void)
  * @bus: a #GstBus to post on
  * @message: (transfer full): the #GstMessage to post
  *
- * Post a message on the given bus. Ownership of the message
+ * Posts a message on the given bus. Ownership of the message
  * is taken by the bus.
  *
  * Returns: %TRUE if the message could be posted, %FALSE if the bus is flushing.
- *
- * MT safe.
  */
 gboolean
 gst_bus_post (GstBus * bus, GstMessage * message)
 {
   GstBusSyncReply reply = GST_BUS_PASS;
-  GstBusSyncHandler handler;
   gboolean emit_sync_message;
-  gpointer handler_data;
+  SyncHandler *sync_handler = NULL;
 
   g_return_val_if_fail (GST_IS_BUS (bus), FALSE);
   g_return_val_if_fail (GST_IS_MESSAGE (message), FALSE);
@@ -324,21 +347,24 @@ gst_bus_post (GstBus * bus, GstMessage * message)
   if (GST_OBJECT_FLAG_IS_SET (bus, GST_BUS_FLUSHING))
     goto is_flushing;
 
-  handler = bus->priv->sync_handler;
-  handler_data = bus->priv->sync_handler_data;
+  if (bus->priv->sync_handler)
+    sync_handler = sync_handler_ref (bus->priv->sync_handler);
   emit_sync_message = bus->priv->num_sync_message_emitters > 0;
   GST_OBJECT_UNLOCK (bus);
 
   /* first call the sync handler if it is installed */
-  if (handler)
-    reply = handler (bus, message, handler_data);
+  if (sync_handler)
+    reply = sync_handler->handler (bus, message, sync_handler->user_data);
 
   /* emit sync-message if requested to do so via
      gst_bus_enable_sync_message_emission. terrible but effective */
   if (emit_sync_message && reply != GST_BUS_DROP
-      && handler != gst_bus_sync_signal_handler)
+      && (!sync_handler
+          || sync_handler->handler != gst_bus_sync_signal_handler))
     gst_bus_sync_signal_handler (bus, message, NULL);
 
+  g_clear_pointer (&sync_handler, sync_handler_unref);
+
   /* If this is a bus without async message delivery
    * always drop the message */
   if (!bus->priv->poll)
@@ -417,13 +443,11 @@ is_flushing:
  * gst_bus_have_pending:
  * @bus: a #GstBus to check
  *
- * Check if there are pending messages on the bus that
+ * Checks if there are pending messages on the bus that
  * should be handled.
  *
  * Returns: %TRUE if there are messages on the bus to be handled, %FALSE
  * otherwise.
- *
- * MT safe.
  */
 gboolean
 gst_bus_have_pending (GstBus * bus)
@@ -443,11 +467,9 @@ gst_bus_have_pending (GstBus * bus)
  * @bus: a #GstBus
  * @flushing: whether or not to flush the bus
  *
- * If @flushing, flush out and unref any messages queued in the bus. Releases
+ * If @flushing, flushes out and unrefs any messages queued in the bus. Releases
  * references to the message origin objects. Will flush future messages until
  * gst_bus_set_flushing() sets @flushing to %FALSE.
- *
- * MT safe.
  */
 void
 gst_bus_set_flushing (GstBus * bus, gboolean flushing)
@@ -479,10 +501,10 @@ gst_bus_set_flushing (GstBus * bus, gboolean flushing)
 /**
  * gst_bus_timed_pop_filtered:
  * @bus: a #GstBus to pop from
- * @timeout: a timeout in nanoseconds, or GST_CLOCK_TIME_NONE to wait forever
- * @types: message types to take into account, GST_MESSAGE_ANY for any type
+ * @timeout: a timeout in nanoseconds, or %GST_CLOCK_TIME_NONE to wait forever
+ * @types: message types to take into account, %GST_MESSAGE_ANY for any type
  *
- * Get a message from the bus whose type matches the message type mask @types,
+ * Gets a message from the bus whose type matches the message type mask @types,
  * waiting up to the specified timeout (and discarding any messages that do not
  * match the mask provided).
  *
@@ -492,18 +514,14 @@ gst_bus_set_flushing (GstBus * bus, gboolean flushing)
  *
  * Returns: (transfer full) (nullable): a #GstMessage matching the
  *     filter in @types, or %NULL if no matching message was found on
- *     the bus until the timeout expired. The message is taken from
- *     the bus and needs to be unreffed with gst_message_unref() after
- *     usage.
- *
- * MT safe.
+ *     the bus until the timeout expired.
  */
 GstMessage *
 gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout,
     GstMessageType types)
 {
   GstMessage *message;
-  GTimeVal now, then;
+  gint64 now, then;
   gboolean first_round = TRUE;
   GstClockTime elapsed = 0;
 
@@ -563,12 +581,12 @@ gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout,
 
     else if (timeout != GST_CLOCK_TIME_NONE) {
       if (first_round) {
-        g_get_current_time (&then);
+        then = g_get_monotonic_time ();
         first_round = FALSE;
       } else {
-        g_get_current_time (&now);
+        now = g_get_monotonic_time ();
 
-        elapsed = GST_TIMEVAL_TO_TIME (now) - GST_TIMEVAL_TO_TIME (then);
+        elapsed = (now - then) * GST_USECOND;
 
         if (elapsed > timeout)
           break;
@@ -582,10 +600,10 @@ gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout,
     g_mutex_lock (&bus->priv->queue_lock);
 
     if (ret == 0) {
-      GST_INFO_OBJECT (bus, "timed out, breaking loop");
+      GST_DEBUG_OBJECT (bus, "timed out, breaking loop");
       break;
     } else {
-      GST_INFO_OBJECT (bus, "we got woken up, recheck for message");
+      GST_DEBUG_OBJECT (bus, "we got woken up, recheck for message");
     }
   }
 
@@ -602,7 +620,7 @@ beach:
  * @bus: a #GstBus to pop
  * @timeout: a timeout
  *
- * Get a message from the bus, waiting up to the specified timeout.
+ * Gets a message from the bus, waiting up to the specified timeout.
  *
  * If @timeout is 0, this function behaves like gst_bus_pop(). If @timeout is
  * #GST_CLOCK_TIME_NONE, this function will block forever until a message was
@@ -610,10 +628,7 @@ beach:
  *
  * Returns: (transfer full) (nullable): the #GstMessage that is on the
  *     bus after the specified timeout or %NULL if the bus is empty
- *     after the timeout expired.  The message is taken from the bus
- *     and needs to be unreffed with gst_message_unref() after usage.
- *
- * MT safe.
+ *     after the timeout expired.
  */
 GstMessage *
 gst_bus_timed_pop (GstBus * bus, GstClockTime timeout)
@@ -628,7 +643,7 @@ gst_bus_timed_pop (GstBus * bus, GstClockTime timeout)
  * @bus: a #GstBus to pop
  * @types: message types to take into account
  *
- * Get a message matching @type from the bus.  Will discard all messages on
+ * Gets a message matching @type from the bus.  Will discard all messages on
  * the bus that do not match @type and that have been posted before the first
  * message that does match @type.  If there is no message matching @type on
  * the bus, all messages will be discarded. It is not possible to use message
@@ -636,10 +651,7 @@ gst_bus_timed_pop (GstBus * bus, GstClockTime timeout)
  *
  * Returns: (transfer full) (nullable): the next #GstMessage matching
  *     @type that is on the bus, or %NULL if the bus is empty or there
- *     is no message matching @type. The message is taken from the bus
- *     and needs to be unreffed with gst_message_unref() after usage.
- *
- * MT safe.
+ *     is no message matching @type.
  */
 GstMessage *
 gst_bus_pop_filtered (GstBus * bus, GstMessageType types)
@@ -654,14 +666,10 @@ gst_bus_pop_filtered (GstBus * bus, GstMessageType types)
  * gst_bus_pop:
  * @bus: a #GstBus to pop
  *
- * Get a message from the bus.
+ * Gets a message from the bus.
  *
  * Returns: (transfer full) (nullable): the #GstMessage that is on the
- *     bus, or %NULL if the bus is empty. The message is taken from
- *     the bus and needs to be unreffed with gst_message_unref() after
- *     usage.
- *
- * MT safe.
+ *     bus, or %NULL if the bus is empty.
  */
 GstMessage *
 gst_bus_pop (GstBus * bus)
@@ -675,14 +683,11 @@ gst_bus_pop (GstBus * bus)
  * gst_bus_peek:
  * @bus: a #GstBus
  *
- * Peek the message on the top of the bus' queue. The message will remain
- * on the bus' message queue. A reference is returned, and needs to be unreffed
- * by the caller.
+ * Peeks the message on the top of the bus' queue. The message will remain
+ * on the bus' message queue.
  *
  * Returns: (transfer full) (nullable): the #GstMessage that is on the
  *     bus, or %NULL if the bus is empty.
- *
- * MT safe.
  */
 GstMessage *
 gst_bus_peek (GstBus * bus)
@@ -716,47 +721,31 @@ gst_bus_peek (GstBus * bus)
  * should handle messages asynchronously using the gst_bus watch and poll
  * functions.
  *
- * You cannot replace an existing sync_handler. You can pass %NULL to this
- * function, which will clear the existing handler.
+ * Before 1.16.3 it was not possible to replace an existing handler and
+ * clearing an existing handler with %NULL was not thread-safe.
  */
 void
 gst_bus_set_sync_handler (GstBus * bus, GstBusSyncHandler func,
     gpointer user_data, GDestroyNotify notify)
 {
-  GDestroyNotify old_notify;
+  SyncHandler *old_handler, *new_handler = NULL;
 
   g_return_if_fail (GST_IS_BUS (bus));
 
-  GST_OBJECT_LOCK (bus);
-  /* Assert if the user attempts to replace an existing sync_handler,
-   * other than to clear it */
-  if (func != NULL && bus->priv->sync_handler != NULL)
-    goto no_replace;
-
-  if ((old_notify = bus->priv->sync_handler_notify)) {
-    gpointer old_data = bus->priv->sync_handler_data;
-
-    bus->priv->sync_handler_data = NULL;
-    bus->priv->sync_handler_notify = NULL;
-    GST_OBJECT_UNLOCK (bus);
-
-    old_notify (old_data);
-
-    GST_OBJECT_LOCK (bus);
+  if (func) {
+    new_handler = g_new0 (SyncHandler, 1);
+    new_handler->handler = func;
+    new_handler->user_data = user_data;
+    new_handler->destroy_notify = notify;
+    new_handler->ref_count = 1;
   }
-  bus->priv->sync_handler = func;
-  bus->priv->sync_handler_data = user_data;
-  bus->priv->sync_handler_notify = notify;
-  GST_OBJECT_UNLOCK (bus);
 
-  return;
+  GST_OBJECT_LOCK (bus);
+  old_handler = g_steal_pointer (&bus->priv->sync_handler);
+  bus->priv->sync_handler = g_steal_pointer (&new_handler);
+  GST_OBJECT_UNLOCK (bus);
 
-no_replace:
-  {
-    GST_OBJECT_UNLOCK (bus);
-    g_warning ("cannot replace existing sync handler");
-    return;
-  }
+  g_clear_pointer (&old_handler, sync_handler_unref);
 }
 
 /**
@@ -793,13 +782,6 @@ typedef struct
 } GstBusSource;
 
 static gboolean
-gst_bus_source_prepare (GSource * source, gint * timeout)
-{
-  *timeout = -1;
-  return FALSE;
-}
-
-static gboolean
 gst_bus_source_check (GSource * source)
 {
   GstBusSource *bsrc = (GstBusSource *) source;
@@ -852,59 +834,102 @@ no_handler:
   }
 }
 
+#if GLIB_CHECK_VERSION(2,63,3)
 static void
-gst_bus_source_finalize (GSource * source)
+gst_bus_source_dispose (GSource * source)
 {
   GstBusSource *bsource = (GstBusSource *) source;
   GstBus *bus;
 
   bus = bsource->bus;
 
+  GST_DEBUG_OBJECT (bus, "disposing source %p", source);
+
+  GST_OBJECT_LOCK (bus);
+  if (bus->priv->gsource == source)
+    bus->priv->gsource = NULL;
+  GST_OBJECT_UNLOCK (bus);
+}
+#endif
+
+static void
+gst_bus_source_finalize (GSource * source)
+{
+  GstBusSource *bsource = (GstBusSource *) source;
+#if !GLIB_CHECK_VERSION(2,63,3)
+  GstBus *bus = bsource->bus;
+
   GST_DEBUG_OBJECT (bus, "finalize source %p", source);
 
   GST_OBJECT_LOCK (bus);
-  if (bus->priv->signal_watch == source)
-    bus->priv->signal_watch = NULL;
+  if (bus->priv->gsource == source)
+    bus->priv->gsource = NULL;
   GST_OBJECT_UNLOCK (bus);
+#endif
 
-  gst_object_unref (bsource->bus);
-  bsource->bus = NULL;
+  gst_clear_object (&bsource->bus);
 }
 
 static GSourceFuncs gst_bus_source_funcs = {
-  gst_bus_source_prepare,
+  NULL,
   gst_bus_source_check,
   gst_bus_source_dispatch,
   gst_bus_source_finalize
 };
 
+
+static GSource *
+gst_bus_create_watch_unlocked (GstBus * bus)
+{
+  GstBusSource *source;
+
+  if (bus->priv->gsource) {
+    GST_ERROR_OBJECT (bus,
+        "Tried to add new GSource while one was already there");
+    return NULL;
+  }
+
+  bus->priv->gsource = g_source_new (&gst_bus_source_funcs,
+      sizeof (GstBusSource));
+  source = (GstBusSource *) bus->priv->gsource;
+
+  g_source_set_name ((GSource *) source, "GStreamer message bus watch");
+#if GLIB_CHECK_VERSION(2,63,3)
+  g_source_set_dispose_function ((GSource *) source, gst_bus_source_dispose);
+#endif
+
+  source->bus = gst_object_ref (bus);
+  g_source_add_poll ((GSource *) source, &bus->priv->pollfd);
+
+  return (GSource *) source;
+}
+
 /**
  * gst_bus_create_watch:
  * @bus: a #GstBus to create the watch for
  *
- * Create watch for this bus. The GSource will be dispatched whenever
+ * Create watch for this bus. The #GSource will be dispatched whenever
  * a message is on the bus. After the GSource is dispatched, the
  * message is popped off the bus and unreffed.
  *
- * Returns: (transfer full) (nullable): a #GSource that can be added to a mainloop.
+ * As with other watches, there can only be one watch on the bus, including
+ * any signal watch added with #gst_bus_add_signal_watch.
+ *
+ * Returns: (transfer full) (nullable): a #GSource that can be added to a #GMainLoop.
  */
 GSource *
 gst_bus_create_watch (GstBus * bus)
 {
-  GstBusSource *source;
+  GSource *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));
-
-  g_source_set_name ((GSource *) source, "GStreamer message bus watch");
-
-  source->bus = gst_object_ref (bus);
-  g_source_add_poll ((GSource *) source, &bus->priv->pollfd);
+  GST_OBJECT_LOCK (bus);
+  source = gst_bus_create_watch_unlocked (bus);
+  GST_OBJECT_UNLOCK (bus);
 
-  return (GSource *) source;
+  return source;
 }
 
 /* must be called with the bus OBJECT LOCK */
@@ -916,13 +941,13 @@ gst_bus_add_watch_full_unlocked (GstBus * bus, gint priority,
   guint id;
   GSource *source;
 
-  if (bus->priv->signal_watch) {
+  if (bus->priv->gsource) {
     GST_ERROR_OBJECT (bus,
         "Tried to add new watch while one was already there");
     return 0;
   }
 
-  source = gst_bus_create_watch (bus);
+  source = gst_bus_create_watch_unlocked (bus);
   if (!source) {
     g_critical ("Creating bus watch failed");
     return 0;
@@ -938,7 +963,7 @@ gst_bus_add_watch_full_unlocked (GstBus * bus, gint priority,
   g_source_unref (source);
 
   if (id) {
-    bus->priv->signal_watch = source;
+    bus->priv->gsource = source;
   }
 
   GST_DEBUG_OBJECT (bus, "New source %p with id %u", source, id);
@@ -963,7 +988,7 @@ gst_bus_add_watch_full_unlocked (GstBus * bus, gint priority,
  * There can only be a single bus watch per bus, you must remove it before you
  * can set a new one.
  *
- * The bus watch will only work if a GLib main loop is being run.
+ * The bus watch will only work if a #GMainLoop is being run.
  *
  * When @func is called, the message belongs to the caller; if you want to
  * keep a copy of it, call gst_message_ref() before leaving @func.
@@ -975,8 +1000,6 @@ gst_bus_add_watch_full_unlocked (GstBus * bus, gint priority,
  * The bus watch will take its own reference to the @bus, so it is safe to unref
  * @bus using gst_object_unref() after setting the bus watch.
  *
- * MT safe.
- *
  * Returns: The event source id or 0 if @bus already got an event source.
  */
 guint
@@ -1001,7 +1024,7 @@ gst_bus_add_watch_full (GstBus * bus, gint priority,
  * @user_data: user data passed to @func.
  *
  * Adds a bus watch to the default main context with the default priority
- * (%G_PRIORITY_DEFAULT). It is also possible to use a non-default main
+ * ( %G_PRIORITY_DEFAULT ). It is also possible to use a non-default main
  * context set up using g_main_context_push_thread_default() (before
  * one had to create a bus watch source and attach it to the desired main
  * context 'manually').
@@ -1010,7 +1033,7 @@ gst_bus_add_watch_full (GstBus * bus, gint priority,
  * There can only be a single bus watch per bus, you must remove it before you
  * can set a new one.
  *
- * The bus watch will only work if a GLib main loop is being run.
+ * The bus watch will only work if a #GMainLoop is being run.
  *
  * The watch can be removed using gst_bus_remove_watch() or by returning %FALSE
  * from @func. If the watch was added to the default main context it is also
@@ -1019,8 +1042,6 @@ gst_bus_add_watch_full (GstBus * bus, gint priority,
  * The bus watch will take its own reference to the @bus, so it is safe to unref
  * @bus using gst_object_unref() after setting the bus watch.
  *
- * MT safe.
- *
  * Returns: The event source id or 0 if @bus already got an event source.
  */
 guint
@@ -1050,7 +1071,7 @@ gst_bus_remove_watch (GstBus * bus)
 
   GST_OBJECT_LOCK (bus);
 
-  if (bus->priv->signal_watch == NULL) {
+  if (bus->priv->gsource == NULL) {
     GST_ERROR_OBJECT (bus, "no bus watch was present");
     goto error;
   }
@@ -1061,8 +1082,8 @@ gst_bus_remove_watch (GstBus * bus)
     goto error;
   }
 
-  source =
-      bus->priv->signal_watch ? g_source_ref (bus->priv->signal_watch) : NULL;
+  source = g_source_ref (bus->priv->gsource);
+  bus->priv->gsource = NULL;
 
   GST_OBJECT_UNLOCK (bus);
 
@@ -1150,7 +1171,7 @@ poll_destroy_timeout (GstBusPollData * poll_data)
  * @timeout: the poll timeout, as a #GstClockTime, or #GST_CLOCK_TIME_NONE to poll
  * indefinitely.
  *
- * Poll the bus for messages. Will block while waiting for messages to come.
+ * Polls the bus for messages. Will block while waiting for messages to come.
  * You can specify a maximum time to poll with the @timeout parameter. If
  * @timeout is negative, this function will block indefinitely.
  *
@@ -1164,7 +1185,7 @@ poll_destroy_timeout (GstBusPollData * poll_data)
  * signal handler will see the same messages that this function sees -- neither
  * will steal messages from the other.
  *
- * This function will run a main loop from the default main context when
+ * This function will run a #GMainLoop from the default main context when
  * polling.
  *
  * You should never use this function, since it is pure evil. This is
@@ -1185,9 +1206,7 @@ poll_destroy_timeout (GstBusPollData * poll_data)
  * from there.
  *
  * Returns: (transfer full) (nullable): the message that was received,
- *     or %NULL if the poll timed out. The message is taken from the
- *     bus and needs to be unreffed with gst_message_unref() after
- *     usage.
+ *     or %NULL if the poll timed out.
  */
 GstMessage *
 gst_bus_poll (GstBus * bus, GstMessageType events, GstClockTime timeout)
@@ -1270,10 +1289,10 @@ gst_bus_async_signal_func (GstBus * bus, GstMessage * message, gpointer data)
  * @message: the #GstMessage received
  * @data: user data
  *
- * A helper GstBusSyncHandler that can be used to convert all synchronous
+ * A helper #GstBusSyncHandler that can be used to convert all synchronous
  * messages into signals.
  *
- * Returns: GST_BUS_PASS
+ * Returns: %GST_BUS_PASS
  */
 GstBusSyncReply
 gst_bus_sync_signal_handler (GstBus * bus, GstMessage * message, gpointer data)
@@ -1304,13 +1323,11 @@ gst_bus_sync_signal_handler (GstBus * bus, GstMessage * message, gpointer data)
  * as this function is called.
  *
  * While this function looks similar to gst_bus_add_signal_watch(), it is not
- * exactly the same -- this function enables <emphasis>synchronous</emphasis> emission of
+ * exactly the same -- this function enables *synchronous* emission of
  * signals when messages arrive; gst_bus_add_signal_watch() adds an idle callback
- * to pop messages off the bus <emphasis>asynchronously</emphasis>. The sync-message signal
+ * to pop messages off the bus *asynchronously*. The sync-message signal
  * comes from the thread of whatever object posted the message; the "message"
- * signal is marshalled to the main thread via the main loop.
- *
- * MT safe.
+ * signal is marshalled to the main thread via the #GMainLoop.
  */
 void
 gst_bus_enable_sync_message_emission (GstBus * bus)
@@ -1336,8 +1353,6 @@ gst_bus_enable_sync_message_emission (GstBus * bus)
  * "cancelled" by calling this function. In this way the semantics are exactly
  * the same as gst_object_ref() that which calls enable should also call
  * disable.
- *
- * MT safe.
  */
 void
 gst_bus_disable_sync_message_emission (GstBus * bus)
@@ -1362,7 +1377,7 @@ gst_bus_disable_sync_message_emission (GstBus * bus)
  * main context 'manually').
  *
  * After calling this statement, the bus will emit the "message" signal for each
- * message posted on the bus when the main loop is running.
+ * message posted on the bus when the #GMainLoop is running.
  *
  * This function may be called multiple times. To clean up, the caller is
  * responsible for calling gst_bus_remove_signal_watch() as many times as this
@@ -1370,8 +1385,6 @@ gst_bus_disable_sync_message_emission (GstBus * bus)
  *
  * There can only be a single bus watch per bus, you must remove any signal
  * watch before you can set another type of watch.
- *
- * MT safe.
  */
 void
 gst_bus_add_signal_watch_full (GstBus * bus, gint priority)
@@ -1384,13 +1397,13 @@ gst_bus_add_signal_watch_full (GstBus * bus, gint priority)
   if (bus->priv->num_signal_watchers > 0)
     goto done;
 
-  /* this should not fail because the counter above takes care of it */
-  g_assert (!bus->priv->signal_watch);
+  if (bus->priv->gsource)
+    goto has_gsource;
 
   gst_bus_add_watch_full_unlocked (bus, priority, gst_bus_async_signal_func,
       NULL, NULL);
 
-  if (G_UNLIKELY (!bus->priv->signal_watch))
+  if (G_UNLIKELY (!bus->priv->gsource))
     goto add_failed;
 
 done:
@@ -1407,6 +1420,12 @@ add_failed:
     GST_OBJECT_UNLOCK (bus);
     return;
   }
+has_gsource:
+  {
+    g_critical ("Bus %s already has a GSource watch", GST_OBJECT_NAME (bus));
+    GST_OBJECT_UNLOCK (bus);
+    return;
+  }
 }
 
 /**
@@ -1414,7 +1433,7 @@ add_failed:
  * @bus: a #GstBus on which you want to receive the "message" signal
  *
  * Adds a bus signal watch to the default main context with the default priority
- * (%G_PRIORITY_DEFAULT). It is also possible to use a non-default
+ * ( %G_PRIORITY_DEFAULT ). It is also possible to use a non-default
  * main context set up using g_main_context_push_thread_default() (before
  * one had to create a bus watch source and attach it to the desired main
  * context 'manually').
@@ -1425,8 +1444,6 @@ add_failed:
  * This function may be called multiple times. To clean up, the caller is
  * responsible for calling gst_bus_remove_signal_watch() as many times as this
  * function is called.
- *
- * MT safe.
  */
 void
 gst_bus_add_signal_watch (GstBus * bus)
@@ -1439,8 +1456,6 @@ gst_bus_add_signal_watch (GstBus * bus)
  * @bus: a #GstBus you previously added a signal watch to
  *
  * Removes a signal watch previously added with gst_bus_add_signal_watch().
- *
- * MT safe.
  */
 void
 gst_bus_remove_signal_watch (GstBus * bus)
@@ -1460,11 +1475,12 @@ gst_bus_remove_signal_watch (GstBus * bus)
   if (bus->priv->num_signal_watchers > 0)
     goto done;
 
-  GST_DEBUG_OBJECT (bus, "removing signal watch %u",
-      g_source_get_id (bus->priv->signal_watch));
+  GST_DEBUG_OBJECT (bus, "removing gsource %u",
+      g_source_get_id (bus->priv->gsource));
 
-  source =
-      bus->priv->signal_watch ? g_source_ref (bus->priv->signal_watch) : NULL;
+  g_assert (bus->priv->gsource);
+  source = g_source_ref (bus->priv->gsource);
+  bus->priv->gsource = NULL;
 
 done:
   GST_OBJECT_UNLOCK (bus);
index 1f14246..d8e7583 100644 (file)
@@ -78,7 +78,7 @@ typedef enum
  * into the bus. This function is mostly used internally. Only one sync handler
  * can be attached to a given bus.
  *
- * If the handler returns GST_BUS_DROP, it should unref the message, else the
+ * If the handler returns %GST_BUS_DROP, it should unref the message, else the
  * message should not be unreffed by the sync handler.
  *
  * Returns: #GstBusSyncReply stating what to do with the message
@@ -98,8 +98,8 @@ typedef GstBusSyncReply (*GstBusSyncHandler)    (GstBus * bus, GstMessage * mess
  * The message passed to the function will be unreffed after execution of this
  * function so it should not be freed in the function.
  *
- * Note that this function is used as a GSourceFunc which means that returning
- * %FALSE will remove the GSource from the mainloop.
+ * Note that this function is used as a #GSourceFunc which means that returning
+ * %FALSE will remove the #GSource from the mainloop.
  *
  * Returns: %FALSE if the event source should be removed.
  */
@@ -107,6 +107,7 @@ typedef gboolean        (*GstBusFunc)           (GstBus * bus, GstMessage * mess
 
 /**
  * GstBus:
+ * @object: the parent structure
  *
  * The opaque #GstBus data structure.
  */
@@ -120,12 +121,34 @@ struct _GstBus
   gpointer _gst_reserved[GST_PADDING];
 };
 
+/**
+ * GstBusClass:
+ * @parent_class: the parent class structure
+ *
+ * GStreamer bus class.
+ */
 struct _GstBusClass
 {
   GstObjectClass parent_class;
 
   /* signals */
+
+  /**
+   * GstBusClass::message:
+   * @bus: the #GstBus
+   * @message: the message that has been posted asynchronously
+   *
+   * A message has been posted on the bus.
+   */
   void (*message)       (GstBus *bus, GstMessage *message);
+
+  /**
+   * GstBusClass::sync_message:
+   * @bus: the #GstBus
+   * @message: the message that has been posted synchronously
+   *
+   * A message has been posted on the bus.
+   */
   void (*sync_message)  (GstBus *bus, GstMessage *message);
 
   /*< private >*/
@@ -223,9 +246,7 @@ void                    gst_bus_enable_sync_message_emission (GstBus * bus);
 GST_API
 void                    gst_bus_disable_sync_message_emission (GstBus * bus);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBus, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 9e6408d..5c23b0e 100644 (file)
@@ -35,7 +35,8 @@
  * handle or produce at runtime.
  *
  * A #GstCaps can be constructed with the following code fragment:
- * |[<!-- language="C" -->
+ *
+ * ``` C
  *   GstCaps *caps = gst_caps_new_simple ("video/x-raw",
  *      "format", G_TYPE_STRING, "I420",
  *      "framerate", GST_TYPE_FRACTION, 25, 1,
  *      "width", G_TYPE_INT, 320,
  *      "height", G_TYPE_INT, 240,
  *      NULL);
- * ]|
+ * ```
  *
- * A #GstCaps is fixed when it has no properties with ranges or lists. Use
+ * A #GstCaps is fixed when it has no fields with ranges or lists. Use
  * gst_caps_is_fixed() to test for fixed caps. Fixed caps can be used in a
  * caps event to notify downstream elements of the current media type.
  *
  * Various methods exist to work with the media types such as subtracting
  * or intersecting.
  *
- * Be aware that the current #GstCaps / #GstStructure serialization into string
- * has limited support for nested #GstCaps / #GstStructure fields. It can only
- * support one level of nesting. Using more levels will lead to unexpected
+ * Be aware that until 1.20 the #GstCaps / #GstStructure serialization into string
+ * had limited support for nested #GstCaps / #GstStructure fields. It could only
+ * support one level of nesting. Using more levels would lead to unexpected
  * behavior when using serialization features, such as gst_caps_to_string() or
  * gst_value_serialize() and their counterparts.
  */
@@ -65,6 +66,7 @@
 #include <string.h>
 #include <signal.h>
 
+#define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 #include "gst_private.h"
 #include <gst/gst.h>
 #include <gobject/gvaluecollector.h>
@@ -245,7 +247,6 @@ gst_caps_init (GstCaps * caps)
  * Creates a new #GstCaps that is empty.  That is, the returned
  * #GstCaps contains no media formats.
  * The #GstCaps is guaranteed to be writable.
- * Caller is responsible for unreffing the returned caps.
  *
  * Returns: (transfer full): the new #GstCaps
  */
@@ -289,7 +290,6 @@ gst_caps_new_any (void)
  *
  * 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
  */
@@ -316,7 +316,6 @@ gst_caps_new_empty_simple (const char *media_type)
  * Creates a new #GstCaps that contains one #GstStructure.  The
  * structure is defined by the arguments, which have the same format
  * as gst_structure_new().
- * Caller is responsible for unreffing the returned caps.
  *
  * Returns: (transfer full): the new #GstCaps
  */
@@ -399,10 +398,9 @@ G_DEFINE_POINTER_TYPE (GstStaticCaps, gst_static_caps);
  *
  * Converts a #GstStaticCaps to a #GstCaps.
  *
- * Returns: (transfer full) (nullable): a pointer to the #GstCaps. Unref
- *     after usage. Since the core holds an additional ref to the
- *     returned caps, use gst_caps_make_writable() on the returned caps
- *     to modify it.
+ * Returns: (transfer full) (nullable): a pointer to the #GstCaps. Since the
+ *     core holds an additional ref to the returned caps, use
+ *     gst_caps_make_writable() on the returned caps to modify it.
  */
 GstCaps *
 gst_static_caps_get (GstStaticCaps * static_caps)
@@ -462,7 +460,7 @@ no_string:
  * gst_static_caps_cleanup:
  * @static_caps: the #GstStaticCaps to clean
  *
- * Clean up the cached caps contained in @static_caps.
+ * Cleans up the cached caps contained in @static_caps.
  */
 void
 gst_static_caps_cleanup (GstStaticCaps * static_caps)
@@ -510,6 +508,20 @@ gst_caps_remove_and_get_structure (GstCaps * caps, guint idx)
   return s;
 }
 
+static void
+gst_caps_make_any (GstCaps * caps)
+{
+  guint i;
+  GstStructure *s;
+
+  /* empty out residual structures */
+  for (i = GST_CAPS_LEN (caps); i; i--) {
+    s = gst_caps_remove_and_get_structure (caps, 0);
+    gst_structure_free (s);
+  }
+  GST_CAPS_FLAGS (caps) |= GST_CAPS_FLAG_ANY;
+}
+
 /**
  * gst_caps_steal_structure:
  * @caps: the #GstCaps to retrieve from
@@ -554,7 +566,7 @@ gst_caps_append (GstCaps * caps1, GstCaps * caps2)
   g_return_if_fail (IS_WRITABLE (caps1));
 
   if (G_UNLIKELY (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2))) {
-    GST_CAPS_FLAGS (caps1) |= GST_CAPS_FLAG_ANY;
+    gst_caps_make_any (caps1);
     gst_caps_unref (caps2);
   } else {
     caps2 = gst_caps_make_writable (caps2);
@@ -636,6 +648,13 @@ gst_caps_append_structure (GstCaps * caps, GstStructure * structure)
   g_return_if_fail (GST_IS_CAPS (caps));
   g_return_if_fail (IS_WRITABLE (caps));
 
+  if (CAPS_IS_ANY (caps)) {
+    /* ANY caps will stay as ANY caps */
+    if (structure)
+      gst_structure_free (structure);
+    return;
+  }
+
   if (G_LIKELY (structure)) {
     gst_caps_append_structure_unchecked (caps, structure, NULL);
   }
@@ -659,6 +678,15 @@ gst_caps_append_structure_full (GstCaps * caps, GstStructure * structure,
   g_return_if_fail (GST_IS_CAPS (caps));
   g_return_if_fail (IS_WRITABLE (caps));
 
+  if (CAPS_IS_ANY (caps)) {
+    /* ANY caps will stay as ANY caps */
+    if (structure)
+      gst_structure_free (structure);
+    if (features)
+      gst_caps_features_free (features);
+    return;
+  }
+
   if (G_LIKELY (structure)) {
     gst_caps_append_structure_unchecked (caps, structure, features);
   }
@@ -669,7 +697,7 @@ gst_caps_append_structure_full (GstCaps * caps, GstStructure * structure,
  * @caps: the #GstCaps to remove from
  * @idx: Index of the structure to remove
  *
- * removes the structure with the given index from the list of structures
+ * Removes the structure with the given index from the list of structures
  * contained in @caps.
  */
 void
@@ -678,7 +706,7 @@ gst_caps_remove_structure (GstCaps * caps, guint idx)
   GstStructure *structure;
 
   g_return_if_fail (caps != NULL);
-  g_return_if_fail (idx <= gst_caps_get_size (caps));
+  g_return_if_fail (idx < gst_caps_get_size (caps));
   g_return_if_fail (IS_WRITABLE (caps));
 
   structure = gst_caps_remove_and_get_structure (caps, idx);
@@ -690,7 +718,7 @@ gst_caps_remove_structure (GstCaps * caps, guint idx)
  * @caps: (transfer full): the #GstCaps to merge into
  * @structure: (transfer full): the #GstStructure to merge
  *
- * Appends @structure to @caps if its not already expressed by @caps.
+ * Appends @structure to @caps if it is not already expressed by @caps.
  *
  * Returns: (transfer full): the merged caps.
  */
@@ -707,6 +735,12 @@ gst_caps_merge_structure (GstCaps * caps, GstStructure * structure)
   if (G_UNLIKELY (structure == NULL))
     return caps;
 
+  if (CAPS_IS_ANY (caps)) {
+    /* ANY caps will stay as ANY caps */
+    gst_structure_free (structure);
+    return caps;
+  }
+
   /* check each structure */
   for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) {
     structure1 = gst_caps_get_structure_unchecked (caps, i);
@@ -758,6 +792,14 @@ gst_caps_merge_structure_full (GstCaps * caps, GstStructure * structure,
   if (G_UNLIKELY (structure == NULL))
     return caps;
 
+  if (CAPS_IS_ANY (caps)) {
+    /* ANY caps will stay as ANY caps */
+    gst_structure_free (structure);
+    if (features)
+      gst_caps_features_free (features);
+    return caps;
+  }
+
   /* To make comparisons easier below */
   features_tmp = features ? features : GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
 
@@ -814,11 +856,10 @@ gst_caps_get_size (const GstCaps * caps)
  * @caps: a #GstCaps
  * @index: the index of the structure
  *
- * Finds the structure in @caps that has the index @index, and
- * returns it.
+ * Finds the structure in @caps at @index, and returns it.
  *
- * WARNING: This function takes a const GstCaps *, but returns a
- * non-const GstStructure *.  This is for programming convenience --
+ * WARNING: This function takes a `const GstCaps *`, but returns a
+ * non-const `GstStructure *`.  This is for programming convenience --
  * the caller should be aware that structures inside a constant
  * #GstCaps should not be modified. However, if you know the caps
  * are writable, either because you have just copied them or made
@@ -826,9 +867,6 @@ gst_caps_get_size (const GstCaps * caps)
  * structure returned in the usual way, e.g. with functions like
  * gst_structure_set().
  *
- * You do not need to free or unref the structure returned, it
- * belongs to the #GstCaps.
- *
  * Returns: (transfer none): a pointer to the #GstStructure corresponding
  *     to @index
  */
@@ -846,21 +884,17 @@ gst_caps_get_structure (const GstCaps * caps, guint index)
  * @caps: a #GstCaps
  * @index: the index of the structure
  *
- * Finds the features in @caps that has the index @index, and
- * returns it.
+ * Finds the features in @caps at @index, and returns it.
  *
- * WARNING: This function takes a const GstCaps *, but returns a
- * non-const GstCapsFeatures *.  This is for programming convenience --
- * the caller should be aware that structures inside a constant
+ * WARNING: This function takes a `const GstCaps *`, but returns a
+ * non-const `GstCapsFeatures *`.  This is for programming convenience --
+ * the caller should be aware that features inside a constant
  * #GstCaps should not be modified. However, if you know the caps
  * are writable, either because you have just copied them or made
  * them writable with gst_caps_make_writable(), you may modify the
  * features returned in the usual way, e.g. with functions like
  * gst_caps_features_add().
  *
- * You do not need to free or unref the structure returned, it
- * belongs to the #GstCaps.
- *
  * Returns: (transfer none) (nullable): a pointer to the #GstCapsFeatures
  *     corresponding to @index
  *
@@ -885,7 +919,8 @@ gst_caps_get_features (const GstCaps * caps, guint index)
     gst_caps_features_set_parent_refcount (features, &GST_CAPS_REFCOUNT (caps));
 
     storage = gst_caps_get_features_storage_unchecked (caps, index);
-    if (!g_atomic_pointer_compare_and_exchange (storage, NULL, features)) {
+    if (!g_atomic_pointer_compare_and_exchange (storage,
+            (GstCapsFeatures *) NULL, features)) {
       /* Someone did the same we just tried in the meantime */
       gst_caps_features_set_parent_refcount (features, NULL);
       gst_caps_features_free (features);
@@ -904,7 +939,7 @@ gst_caps_get_features (const GstCaps * caps, guint index)
  * @index: the index of the structure
  * @features: (allow-none) (transfer full): the #GstCapsFeatures to set
  *
- * Sets the #GstCapsFeatures @features for the structure at @index.
+ * Sets the @features for the structure at @index.
  *
  * Since: 1.2
  */
@@ -914,7 +949,7 @@ gst_caps_set_features (GstCaps * caps, guint index, GstCapsFeatures * features)
   GstCapsFeatures **storage, *old;
 
   g_return_if_fail (caps != NULL);
-  g_return_if_fail (index <= gst_caps_get_size (caps));
+  g_return_if_fail (index < gst_caps_get_size (caps));
   g_return_if_fail (IS_WRITABLE (caps));
 
   storage = gst_caps_get_features_storage_unchecked (caps, index);
@@ -936,7 +971,7 @@ gst_caps_set_features (GstCaps * caps, guint index, GstCapsFeatures * features)
  * @caps: a #GstCaps
  * @features: (allow-none) (transfer full): the #GstCapsFeatures to set
  *
- * Sets the #GstCapsFeatures @features for all the structures of @caps.
+ * Sets the @features for all the structures of @caps.
  *
  * Since: 1.16
  */
@@ -951,6 +986,13 @@ gst_caps_set_features_simple (GstCaps * caps, GstCapsFeatures * features)
 
   n = gst_caps_get_size (caps);
 
+  if (n == 0) {
+    /* features will not be set on any structure */
+    if (features)
+      gst_caps_features_free (features);
+    return;
+  }
+
   for (i = 0; i < n; i++) {
     GstCapsFeatures *f;
 
@@ -1003,13 +1045,17 @@ gst_caps_copy_nth (const GstCaps * caps, guint nth)
  * gst_caps_truncate:
  * @caps: (transfer full): the #GstCaps to truncate
  *
- * Discard all but the first structure from @caps. Useful when
+ * Discards all but the first structure from @caps. Useful when
  * fixating.
  *
  * This function takes ownership of @caps and will call gst_caps_make_writable()
  * on it if necessary, so you must not use @caps afterwards unless you keep an
  * additional reference to it with gst_caps_ref().
  *
+ * Note that it is not guaranteed that the returned caps have exactly one
+ * structure. If @caps is any or empty caps then the returned caps will be
+ * the same and contain no structure at all.
+ *
  * Returns: (transfer full): truncated caps
  */
 GstCaps *
@@ -1019,7 +1065,13 @@ gst_caps_truncate (GstCaps * caps)
 
   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
 
+  /* Nothing to truncate here */
+  if (GST_CAPS_LEN (caps) == 0)
+    return caps;
+
   i = GST_CAPS_LEN (caps) - 1;
+
+  /* Already truncated */
   if (i == 0)
     return caps;
 
@@ -1182,6 +1234,10 @@ gst_caps_is_fixed (const GstCaps * caps)
   if (GST_CAPS_LEN (caps) != 1)
     return FALSE;
 
+  /* double check not ANY, even though ANY caps should have 0 length */
+  if (CAPS_IS_ANY (caps))
+    return FALSE;
+
   features = gst_caps_get_features_unchecked (caps, 0);
   if (features && gst_caps_features_is_any (features))
     return FALSE;
@@ -1269,11 +1325,12 @@ gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
     return FALSE;
 
   for (i = GST_CAPS_LEN (subset) - 1; i >= 0; i--) {
+    s1 = gst_caps_get_structure_unchecked (subset, i);
+    f1 = gst_caps_get_features_unchecked (subset, i);
+    if (!f1)
+      f1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
+
     for (j = GST_CAPS_LEN (superset) - 1; j >= 0; j--) {
-      s1 = gst_caps_get_structure_unchecked (subset, i);
-      f1 = gst_caps_get_features_unchecked (subset, i);
-      if (!f1)
-        f1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
       s2 = gst_caps_get_structure_unchecked (superset, j);
       f2 = gst_caps_get_features_unchecked (superset, j);
       if (!f2)
@@ -1286,6 +1343,7 @@ gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
         break;
       }
     }
+
     /* If we found no superset for this subset structure
      * we return FALSE immediately */
     if (j == -1) {
@@ -1427,6 +1485,12 @@ gst_caps_is_strictly_equal (const GstCaps * caps1, const GstCaps * caps2)
   if (G_UNLIKELY (caps1 == caps2))
     return TRUE;
 
+  /* if both are ANY caps, consider them strictly equal */
+  if (CAPS_IS_ANY (caps1))
+    return (CAPS_IS_ANY (caps2));
+  else if (CAPS_IS_ANY (caps2))
+    return FALSE;
+
   if (GST_CAPS_LEN (caps1) != GST_CAPS_LEN (caps2))
     return FALSE;
 
@@ -1549,21 +1613,6 @@ gst_caps_intersect_zig_zag (GstCaps * caps1, GstCaps * caps2)
   GstCaps *dest;
   GstStructure *istruct;
 
-  /* caps are exactly the same pointers, just copy one caps */
-  if (G_UNLIKELY (caps1 == caps2))
-    return gst_caps_ref (caps1);
-
-  /* empty caps on either side, return empty */
-  if (G_UNLIKELY (CAPS_IS_EMPTY (caps1) || CAPS_IS_EMPTY (caps2)))
-    return gst_caps_ref (GST_CAPS_NONE);
-
-  /* one of the caps is any, just copy the other caps */
-  if (G_UNLIKELY (CAPS_IS_ANY (caps1)))
-    return gst_caps_ref (caps2);
-
-  if (G_UNLIKELY (CAPS_IS_ANY (caps2)))
-    return gst_caps_ref (caps1);
-
   dest = gst_caps_new_empty ();
   /* run zigzag on top line then right line, this preserves the caps order
    * much better than a simple loop.
@@ -1648,21 +1697,6 @@ gst_caps_intersect_first (GstCaps * caps1, GstCaps * caps2)
   GstCaps *dest;
   GstStructure *istruct;
 
-  /* caps are exactly the same pointers, just copy one caps */
-  if (G_UNLIKELY (caps1 == caps2))
-    return gst_caps_ref (caps1);
-
-  /* empty caps on either side, return empty */
-  if (G_UNLIKELY (CAPS_IS_EMPTY (caps1) || CAPS_IS_EMPTY (caps2)))
-    return gst_caps_ref (GST_CAPS_NONE);
-
-  /* one of the caps is any, just copy the other caps */
-  if (G_UNLIKELY (CAPS_IS_ANY (caps1)))
-    return gst_caps_ref (caps2);
-
-  if (G_UNLIKELY (CAPS_IS_ANY (caps2)))
-    return gst_caps_ref (caps1);
-
   dest = gst_caps_new_empty ();
   len1 = GST_CAPS_LEN (caps1);
   len2 = GST_CAPS_LEN (caps2);
@@ -1714,6 +1748,22 @@ gst_caps_intersect_full (GstCaps * caps1, GstCaps * caps2,
   g_return_val_if_fail (GST_IS_CAPS (caps1), NULL);
   g_return_val_if_fail (GST_IS_CAPS (caps2), NULL);
 
+  /* Common fast-path */
+  /* caps are exactly the same pointers, just copy one caps */
+  if (G_UNLIKELY (caps1 == caps2))
+    return gst_caps_ref (caps1);
+
+  /* empty caps on either side, return empty */
+  if (G_UNLIKELY (CAPS_IS_EMPTY (caps1) || CAPS_IS_EMPTY (caps2)))
+    return gst_caps_ref (GST_CAPS_NONE);
+
+  /* one of the caps is any, just copy the other caps */
+  if (G_UNLIKELY (CAPS_IS_ANY (caps1)))
+    return gst_caps_ref (caps2);
+
+  if (G_UNLIKELY (CAPS_IS_ANY (caps2)))
+    return gst_caps_ref (caps1);
+
   switch (mode) {
     case GST_CAPS_INTERSECT_FIRST:
       return gst_caps_intersect_first (caps1, caps2);
@@ -1944,7 +1994,7 @@ gst_caps_normalize_foreach (GQuark field_id, const GValue * value, gpointer ptr)
  *
  * Returns a #GstCaps that represents the same set of formats as
  * @caps, but contains no lists.  Each list is expanded into separate
- * @GstStructures.
+ * #GstStructure.
  *
  * This function takes ownership of @caps and will call gst_caps_make_writable()
  * on it so you must not use @caps afterwards unless you keep an additional
@@ -2122,6 +2172,10 @@ gst_caps_simplify (GstCaps * caps)
 
   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
 
+  /* empty/any caps are as simple as can be */
+  if (GST_CAPS_LEN (caps) == 0)
+    return caps;
+
   start = GST_CAPS_LEN (caps) - 1;
   /* one caps, already as simple as can be */
   if (start == 0)
@@ -2183,6 +2237,12 @@ gst_caps_simplify (GstCaps * caps)
  * on it so you must not use @caps afterwards unless you keep an additional
  * reference to it with gst_caps_ref().
  *
+ * Note that it is not guaranteed that the returned caps have exactly one
+ * structure. If @caps are empty caps then the returned caps will be
+ * the empty too and contain no structure at all.
+ *
+ * Calling this function with ANY caps is not allowed.
+ *
  * Returns: (transfer full): the fixated caps
  */
 GstCaps *
@@ -2192,10 +2252,20 @@ gst_caps_fixate (GstCaps * caps)
   GstCapsFeatures *f;
 
   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
+  g_return_val_if_fail (!CAPS_IS_ANY (caps), NULL);
 
   /* default fixation */
   caps = gst_caps_truncate (caps);
   caps = gst_caps_make_writable (caps);
+
+  /* need to return early here because empty caps have no structure
+   * but must return after make_writable() because the documentation
+   * specifies that it will call make_writable() on the return value
+   * and callers might assume writable caps.
+   */
+  if (CAPS_IS_EMPTY (caps))
+    return caps;
+
   s = gst_caps_get_structure (caps, 0);
   gst_structure_fixate (s);
 
@@ -2211,29 +2281,13 @@ gst_caps_fixate (GstCaps * caps)
 
 /* utility */
 
-/**
- * gst_caps_to_string:
- * @caps: a #GstCaps
- *
- * Converts @caps to a string representation.  This string representation
- * can be converted back to a #GstCaps by gst_caps_from_string().
- *
- * For debugging purposes its easier to do something like this:
- * |[<!-- language="C" -->
- * GST_LOG ("caps are %" GST_PTR_FORMAT, caps);
- * ]|
- * This prints the caps in human readable form.
- *
- * The current implementation of serialization will lead to unexpected results
- * when there are nested #GstCaps / #GstStructure deeper than one level.
- *
- * Returns: (transfer full): a newly allocated string representing @caps.
- */
-gchar *
-gst_caps_to_string (const GstCaps * caps)
+static gchar *
+caps_serialize (const GstCaps * caps, GstSerializeFlags flags)
 {
   guint i, slen, clen;
   GString *s;
+  gboolean nested_structs_brackets =
+      !(flags & GST_SERIALIZE_FLAG_BACKWARD_COMPAT);
 
   /* NOTE:  This function is potentially called by the debug system,
    * so any calls to gst_log() (and GST_DEBUG(), GST_LOG(), etc.)
@@ -2286,7 +2340,8 @@ gst_caps_to_string (const GstCaps * caps)
       priv_gst_caps_features_append_to_gstring (features, s);
       g_string_append_c (s, ')');
     }
-    priv_gst_structure_append_to_gstring (structure, s);
+    priv_gst_structure_append_to_gstring (structure, s,
+        nested_structs_brackets);
   }
   if (s->len && s->str[s->len - 1] == ';') {
     /* remove latest ';' */
@@ -2295,6 +2350,57 @@ gst_caps_to_string (const GstCaps * caps)
   return g_string_free (s, FALSE);
 }
 
+/**
+ * gst_caps_to_string:
+ * @caps: a #GstCaps
+ *
+ * Converts @caps to a string representation.  This string representation
+ * can be converted back to a #GstCaps by gst_caps_from_string().
+ *
+ * For debugging purposes its easier to do something like this:
+ *
+ * ``` C
+ * GST_LOG ("caps are %" GST_PTR_FORMAT, caps);
+ * ```
+ *
+ * This prints the caps in human readable form.
+ *
+ * The implementation of serialization up to 1.20 would lead to unexpected results
+ * when there were nested #GstCaps / #GstStructure deeper than one level.
+ *
+ * Returns: (transfer full): a newly allocated string representing @caps.
+ */
+gchar *
+gst_caps_to_string (const GstCaps * caps)
+{
+  return caps_serialize (caps, GST_SERIALIZE_FLAG_BACKWARD_COMPAT);
+}
+
+/**
+ * gst_caps_serialize:
+ * @caps: a #GstCaps
+ * @flags: a #GstSerializeFlags
+ *
+ * Converts @caps to a string representation.  This string representation can be
+ * converted back to a #GstCaps by gst_caps_from_string().
+ *
+ * This prints the caps in human readable form.
+ *
+ * This version of the caps serialization function introduces support for nested
+ * structures and caps but the resulting strings won't be parsable with
+ * GStreamer prior to 1.20 unless #GST_SERIALIZE_FLAG_BACKWARD_COMPAT is passed
+ * as @flag.
+ *
+ * Returns: (transfer full): a newly allocated string representing @caps.
+ *
+ * Since: 1.20
+ */
+gchar *
+gst_caps_serialize (const GstCaps * caps, GstSerializeFlags flags)
+{
+  return caps_serialize (caps, flags);
+}
+
 static gboolean
 gst_caps_from_string_inplace (GstCaps * caps, const gchar * string)
 {
@@ -2320,7 +2426,7 @@ gst_caps_from_string_inplace (GstCaps * caps, const gchar * string)
       break;
     }
 
-    if (!priv_gst_structure_parse_name (s, &s, &end, &next)) {
+    if (!priv_gst_structure_parse_name (s, &s, &end, &next, FALSE)) {
       g_free (copy);
       return FALSE;
     }
@@ -2399,8 +2505,8 @@ gst_caps_from_string_inplace (GstCaps * caps, const gchar * string)
  *
  * Converts @caps from a string representation.
  *
- * The current implementation of serialization will lead to unexpected results
- * when there are nested #GstCaps / #GstStructure deeper than one level.
+ * The implementation of serialization up to 1.20 would lead to unexpected results
+ * when there were nested #GstCaps / #GstStructure deeper than one level.
  *
  * Returns: (transfer full) (nullable): a newly allocated #GstCaps
  */
@@ -2592,11 +2698,105 @@ gst_caps_filter_and_map_in_place (GstCaps * caps, GstCapsFilterMapFunc func,
  * 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
+ * Returns: (transfer full): the new #GstCaps
  */
 GstCaps *(gst_caps_copy) (const GstCaps * caps)
 {
   return GST_CAPS (gst_mini_object_copy (GST_MINI_OBJECT_CAST (caps)));
 }
+
+/**
+ * gst_caps_ref: (skip)
+ * @caps: the #GstCaps to reference
+ *
+ * Adds 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.
+ */
+GstCaps *
+gst_caps_ref (GstCaps * caps)
+{
+  return (GstCaps *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (caps));
+}
+
+/**
+ * gst_caps_unref: (skip)
+ * @caps: a #GstCaps.
+ *
+ * Unrefs a #GstCaps and frees all its structures and the
+ * structures' values when the refcount reaches 0.
+ */
+void
+gst_caps_unref (GstCaps * caps)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (caps));
+}
+
+/**
+ * gst_clear_caps: (skip)
+ * @caps_ptr: a pointer to a #GstCaps reference
+ *
+ * Clears a reference to a #GstCaps.
+ *
+ * @caps_ptr must not be %NULL.
+ *
+ * If the reference is %NULL then this function does nothing. Otherwise, the
+ * reference count of the caps is decreased and the pointer is set to %NULL.
+ *
+ * Since: 1.16
+ */
+void
+gst_clear_caps (GstCaps ** caps_ptr)
+{
+  gst_clear_mini_object ((GstMiniObject **) caps_ptr);
+}
+
+/**
+ * gst_caps_replace: (skip)
+ * @old_caps: (inout) (transfer full) (nullable): 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 @old_caps.
+ *
+ * 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 @new_caps or the #GstCaps pointed to by @old_caps may be %NULL.
+ *
+ * Returns: %TRUE if @new_caps was different from @old_caps
+ */
+gboolean
+gst_caps_replace (GstCaps ** old_caps, GstCaps * new_caps)
+{
+  return gst_mini_object_replace ((GstMiniObject **) old_caps,
+      (GstMiniObject *) new_caps);
+}
+
+/**
+ * gst_caps_take: (skip)
+ * @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 @old_caps.
+ *
+ * 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
+ */
+gboolean
+gst_caps_take (GstCaps ** old_caps, GstCaps * new_caps)
+{
+  return gst_mini_object_take ((GstMiniObject **) old_caps,
+      (GstMiniObject *) new_caps);
+}
index 603422f..d031b6f 100644 (file)
@@ -55,23 +55,25 @@ typedef enum {
  *
  * Modes of caps intersection
  *
- * @GST_CAPS_INTERSECT_ZIG_ZAG tries to preserve overall order of both caps
+ * %GST_CAPS_INTERSECT_ZIG_ZAG tries to preserve overall order of both caps
  * by iterating on the caps' structures as the following matrix shows:
- * |[
+ *
+ * ```
  *          caps1
  *       +-------------
  *       | 1  2  4  7
  * caps2 | 3  5  8 10
  *       | 6  9 11 12
- * ]|
+ * ```
+ *
  * Used when there is no explicit precedence of one caps over the other. e.g.
  * tee's sink pad getcaps function, it will probe its src pad peers' for their
  * caps and intersect them with this mode.
  *
- * @GST_CAPS_INTERSECT_FIRST is useful when an element wants to preserve
+ * %GST_CAPS_INTERSECT_FIRST is useful when an element wants to preserve
  * another element's caps priority order when intersecting with its own caps.
- * Example: If caps1 is [A, B, C] and caps2 is [E, B, D, A], the result
- * would be [A, B], maintaining the first caps priority on the intersection.
+ * Example: If caps1 is `[A, B, C]` and caps2 is `[E, B, D, A]`, the result
+ * would be `[A, B]`, maintaining the first caps priority on the intersection.
  */
 typedef enum {
   GST_CAPS_INTERSECT_ZIG_ZAG            =  0,
@@ -114,8 +116,7 @@ typedef enum {
  * GST_CAPS_IS_SIMPLE:
  * @caps: the #GstCaps instance to check
  *
- * Convenience macro that checks if the number of structures in the given caps
- * is exactly one.
+ * Checks if the number of structures in the given caps is exactly one.
  */
 #define GST_CAPS_IS_SIMPLE(caps) (gst_caps_get_size(caps) == 1)
 
@@ -143,7 +144,7 @@ GST_API GstCaps * _gst_caps_none;
  * GST_CAPS_FLAGS:
  * @caps: a #GstCaps.
  *
- * A flags word containing #GstCapsFlags flags set on this caps.
+ * Gets a flags word containing #GstCapsFlags flags set on this caps.
  */
 #define GST_CAPS_FLAGS(caps)                    GST_MINI_OBJECT_FLAGS(caps)
 
@@ -152,14 +153,14 @@ GST_API GstCaps * _gst_caps_none;
  * GST_CAPS_REFCOUNT:
  * @caps: a #GstCaps
  *
- * Get access to the reference count field of the caps
+ * Gives access to the reference count field of the caps
  */
 #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.
+ * Gets the reference count value of the caps.
  */
 #define GST_CAPS_REFCOUNT_VALUE(caps)           GST_MINI_OBJECT_REFCOUNT_VALUE(caps)
 
@@ -188,59 +189,35 @@ GST_API GstCaps * _gst_caps_none;
  */
 #define GST_CAPS_FLAG_UNSET(caps,flag)         GST_MINI_OBJECT_FLAG_UNSET (caps, flag)
 
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 /* 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.
- */
 static inline GstCaps *
 gst_caps_ref (GstCaps * caps)
 {
   return (GstCaps *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (caps));
 }
 
-/**
- * gst_caps_unref:
- * @caps: a #GstCaps.
- *
- * Unref a #GstCaps and and free all its structures and the
- * structures' values when the refcount reaches 0.
- */
 static inline void
 gst_caps_unref (GstCaps * caps)
 {
   gst_mini_object_unref (GST_MINI_OBJECT_CAST (caps));
 }
 
-/**
- * gst_clear_caps: (skip)
- * @caps_ptr: a pointer to a #GstCaps reference
- *
- * Clears a reference to a #GstCaps.
- *
- * @caps_ptr must not be %NULL.
- *
- * If the reference is %NULL then this function does nothing. Otherwise, the
- * reference count of the caps is decreased and the pointer is set to %NULL.
- *
- * Since: 1.16
- */
 static inline void
 gst_clear_caps (GstCaps ** caps_ptr)
 {
   gst_clear_mini_object ((GstMiniObject **) caps_ptr);
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+GstCaps * gst_caps_ref   (GstCaps * caps);
+
+GST_API
+void      gst_caps_unref (GstCaps * caps);
+
+GST_API
+void      gst_clear_caps (GstCaps ** caps_ptr);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 /* copy caps */
 GST_API
@@ -278,46 +255,27 @@ GstCaps * gst_caps_copy (const GstCaps * 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) (nullable): 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 @old_caps.
- *
- * 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 @new_caps or the #GstCaps pointed to by @old_caps may be %NULL.
- *
- * Returns: %TRUE if @new_caps was different from @old_caps
- */
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 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 @old_caps.
- *
- * 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
- */
 static inline gboolean
 gst_caps_take (GstCaps **old_caps, GstCaps *new_caps)
 {
     return gst_mini_object_take ((GstMiniObject **) old_caps, (GstMiniObject *) new_caps);
 }
+#else  /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+gboolean  gst_caps_replace (GstCaps ** old_caps,
+                            GstCaps * new_caps);
+
+GST_API
+gboolean  gst_caps_take    (GstCaps ** old_caps,
+                            GstCaps * new_caps);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 /**
  * GstCaps:
@@ -334,7 +292,7 @@ struct _GstCaps {
  * @caps: the cached #GstCaps
  * @string: a string describing a caps
  *
- * Datastructure to initialize #GstCaps from a string description usually
+ * Data structure to initialize #GstCaps from a string description usually
  * used in conjunction with GST_STATIC_CAPS() and gst_static_caps_get() to
  * instantiate a #GstCaps.
  */
@@ -421,6 +379,9 @@ GstCaps *         gst_caps_new_full                (GstStructure  *struct1,
 GST_API
 GstCaps *         gst_caps_new_full_valist         (GstStructure  *structure,
                                                     va_list        var_args) G_GNUC_WARN_UNUSED_RESULT;
+/**
+ * gst_static_caps_get_type: (attributes doc.skip=true)
+ */
 GST_API
 GType             gst_static_caps_get_type         (void);
 
@@ -569,13 +530,13 @@ GstCaps *         gst_caps_fixate                  (GstCaps *caps) G_GNUC_WARN_U
 
 GST_API
 gchar *           gst_caps_to_string               (const GstCaps *caps) G_GNUC_MALLOC;
+GST_API
+gchar *           gst_caps_serialize               (const GstCaps *caps, GstSerializeFlags flags) G_GNUC_MALLOC;
 
 GST_API
 GstCaps *         gst_caps_from_string             (const gchar   *string) G_GNUC_WARN_UNUSED_RESULT;
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstCaps, gst_caps_unref)
-#endif
 
 G_END_DECLS
 
index 2f433a2..0911fff 100644 (file)
@@ -40,8 +40,8 @@
  *
  * Examples for caps features would be the requirement of a specific #GstMemory
  * types or the requirement of having a specific #GstMeta on the buffer. Features
- * are given as a string of the format "memory:GstMemoryTypeName" or
- * "meta:GstMetaAPIName".
+ * are given as a string of the format `memory:GstMemoryTypeName` or
+ * `meta:GstMetaAPIName`.
  *
  * Since: 1.2
  */
@@ -118,6 +118,13 @@ _priv_gst_caps_features_cleanup (void)
   _gst_caps_features_memory_system_memory = NULL;
 }
 
+/**
+ * gst_is_caps_features:
+ *
+ * Checks if @obj is a #GstCapsFeatures
+ *
+ * Returns: %TRUE if @obj is a #GstCapsFeatures %FALSE otherwise
+ */
 gboolean
 gst_is_caps_features (gconstpointer obj)
 {
@@ -164,8 +171,6 @@ gst_caps_feature_name_is_valid (const gchar * feature)
  *
  * Creates a new, empty #GstCapsFeatures.
  *
- * Free-function: gst_caps_features_free
- *
  * Returns: (transfer full): a new, empty #GstCapsFeatures
  *
  * Since: 1.2
@@ -193,8 +198,6 @@ gst_caps_features_new_empty (void)
  * to any other #GstCapsFeatures but caps with these are
  * unfixed.
  *
- * Free-function: gst_caps_features_free
- *
  * Returns: (transfer full): a new, ANY #GstCapsFeatures
  *
  * Since: 1.2
@@ -211,6 +214,29 @@ gst_caps_features_new_any (void)
 }
 
 /**
+ * gst_caps_features_new_single:
+ * @feature: The feature
+ *
+ * Creates a new, ANY #GstCapsFeatures. This will be equal
+ * to any other #GstCapsFeatures but caps with these are
+ * unfixed.
+ *
+ * Returns: (transfer full): a new #GstCapsFeatures
+ *
+ * Since: 1.20
+ */
+GstCapsFeatures *
+gst_caps_features_new_single (const gchar * feature)
+{
+  GstCapsFeatures *features;
+  g_return_val_if_fail (feature != NULL, NULL);
+
+  features = gst_caps_features_new_empty ();
+  gst_caps_features_add (features, feature);
+  return features;
+}
+
+/**
  * gst_caps_features_new:
  * @feature1: name of first feature to set
  * @...: additional features
@@ -218,8 +244,6 @@ gst_caps_features_new_any (void)
  * Creates a new #GstCapsFeatures with the given features.
  * The last argument must be %NULL.
  *
- * Free-function: gst_caps_features_free
- *
  * Returns: (transfer full): a new, empty #GstCapsFeatures
  *
  * Since: 1.2
@@ -246,8 +270,6 @@ gst_caps_features_new (const gchar * feature1, ...)
  *
  * Creates a new #GstCapsFeatures with the given features.
  *
- * Free-function: gst_caps_features_free
- *
  * Returns: (transfer full): a new, empty #GstCapsFeatures
  *
  * Since: 1.2
@@ -277,8 +299,6 @@ gst_caps_features_new_valist (const gchar * feature1, va_list varargs)
  * Creates a new #GstCapsFeatures with the given features.
  * The last argument must be 0.
  *
- * Free-function: gst_caps_features_free
- *
  * Returns: (transfer full): a new, empty #GstCapsFeatures
  *
  * Since: 1.2
@@ -305,8 +325,6 @@ gst_caps_features_new_id (GQuark feature1, ...)
  *
  * Creates a new #GstCapsFeatures with the given features.
  *
- * Free-function: gst_caps_features_free
- *
  * Returns: (transfer full): a new, empty #GstCapsFeatures
  *
  * Since: 1.2
@@ -336,7 +354,7 @@ gst_caps_features_new_id_valist (GQuark feature1, va_list varargs)
  * Sets the parent_refcount field of #GstCapsFeatures. This field is used to
  * determine whether a caps features is mutable or not. This function should only be
  * called by code implementing parent objects of #GstCapsFeatures, as described in
- * the MT Refcounting section of the design documents.
+ * [the MT refcounting design document](additional/design/MT-refcounting.md).
  *
  * Returns: %TRUE if the parent refcount could be set.
  *
@@ -373,8 +391,6 @@ gst_caps_features_set_parent_refcount (GstCapsFeatures * features,
  *
  * Duplicates a #GstCapsFeatures and all its values.
  *
- * Free-function: gst_caps_features_free
- *
  * Returns: (transfer full): a new #GstCapsFeatures.
  *
  * Since: 1.2
@@ -427,15 +443,14 @@ gst_caps_features_free (GstCapsFeatures * features)
  * Converts @features to a human-readable string representation.
  *
  * For debugging purposes its easier to do something like this:
- * |[<!-- language="C" -->
+ *
+ * ``` C
  * GST_LOG ("features is %" GST_PTR_FORMAT, features);
- * ]|
- * This prints the features in human readable form.
+ * ```
  *
- * Free-function: g_free
+ * This prints the features in human readable form.
  *
  * Returns: (transfer full): a pointer to string allocated by g_malloc().
- *     g_free() after usage.
  *
  * Since: 1.2
  */
@@ -482,11 +497,8 @@ priv_gst_caps_features_append_to_gstring (const GstCapsFeatures * features,
  *
  * Creates a #GstCapsFeatures from a string representation.
  *
- * Free-function: gst_caps_features_free
- *
  * Returns: (transfer full) (nullable): a new #GstCapsFeatures or
- *     %NULL when the string could not be parsed. Free with
- *     gst_caps_features_free() after use.
+ *     %NULL when the string could not be parsed.
  *
  * Since: 1.2
  */
@@ -642,7 +654,7 @@ gst_caps_features_get_nth_id (const GstCapsFeatures * features, guint i)
  * @features: a #GstCapsFeatures.
  * @feature: a feature
  *
- * Check if @features contains @feature.
+ * Checks if @features contains @feature.
  *
  * Returns: %TRUE if @features contains @feature.
  *
@@ -664,7 +676,7 @@ gst_caps_features_contains (const GstCapsFeatures * features,
  * @features: a #GstCapsFeatures.
  * @feature: a feature
  *
- * Check if @features contains @feature.
+ * Checks if @features contains @feature.
  *
  * Returns: %TRUE if @features contains @feature.
  *
@@ -698,7 +710,7 @@ gst_caps_features_contains_id (const GstCapsFeatures * features, GQuark feature)
  * @features1: a #GstCapsFeatures.
  * @features2: a #GstCapsFeatures.
  *
- * Check if @features1 and @features2 are equal.
+ * Checks if @features1 and @features2 are equal.
  *
  * Returns: %TRUE if @features1 and @features2 are equal.
  *
@@ -744,7 +756,7 @@ gst_caps_features_is_equal (const GstCapsFeatures * features1,
  * gst_caps_features_is_any:
  * @features: a #GstCapsFeatures.
  *
- * Check if @features is %GST_CAPS_FEATURES_ANY.
+ * Checks if @features is %GST_CAPS_FEATURES_ANY.
  *
  * Returns: %TRUE if @features is %GST_CAPS_FEATURES_ANY.
  *
index 4477b28..cdf7755 100644 (file)
@@ -58,7 +58,10 @@ GST_API
 GstCapsFeatures * gst_caps_features_new_any (void);
 
 GST_API
-GstCapsFeatures * gst_caps_features_new (const gchar *feature1, ...);
+GstCapsFeatures * gst_caps_features_new_single (const gchar *feature) G_GNUC_MALLOC;
+
+GST_API
+GstCapsFeatures * gst_caps_features_new (const gchar *feature1, ...) G_GNUC_NULL_TERMINATED;
 
 GST_API
 GstCapsFeatures * gst_caps_features_new_valist (const gchar *feature1, va_list varargs);
@@ -117,9 +120,7 @@ void              gst_caps_features_remove (GstCapsFeatures * features, const gc
 GST_API
 void              gst_caps_features_remove_id (GstCapsFeatures * features, GQuark feature);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstCapsFeatures, gst_caps_features_free)
-#endif
 
 G_END_DECLS
 
index 22c5d1a..77ef181 100644 (file)
@@ -35,9 +35,9 @@
  * By implementing this interface the child properties can be accessed from the
  * parent element by using gst_child_proxy_get() and gst_child_proxy_set().
  *
- * Property names are written as "child-name::property-name". The whole naming
- * scheme is recursive. Thus "child1::child2::property" is valid too, if
- * "child1" and "child2" implement the #GstChildProxy interface.
+ * Property names are written as `child-name::property-name`. The whole naming
+ * scheme is recursive. Thus `child1::child2::property` is valid too, if
+ * `child1` and `child2` implement the #GstChildProxy interface.
  */
 
 #include "gst_private.h"
@@ -92,7 +92,7 @@ gst_child_proxy_default_get_child_by_name (GstChildProxy * parent,
       break;
     }
   next:
-    g_object_unref (object);
+    gst_object_unref (object);
   }
   return result;
 }
@@ -110,9 +110,7 @@ gst_child_proxy_default_get_child_by_name (GstChildProxy * parent,
  * #GObjects, this methods needs to be overridden.
  *
  * Returns: (transfer full) (nullable): the child object or %NULL if
- *     not found. Unref after usage.
- *
- * MT safe.
+ *     not found.
  */
 GObject *
 gst_child_proxy_get_child_by_name (GstChildProxy * parent, const gchar * name)
@@ -137,9 +135,7 @@ gst_child_proxy_get_child_by_name (GstChildProxy * parent, const gchar * name)
  * Fetches a child by its number.
  *
  * Returns: (transfer full) (nullable): the child object or %NULL if
- *     not found (index too high). Unref after usage.
- *
- * MT safe.
+ *     not found (index too high).
  */
 GObject *
 gst_child_proxy_get_child_by_index (GstChildProxy * parent, guint index)
@@ -163,8 +159,6 @@ gst_child_proxy_get_child_by_index (GstChildProxy * parent, guint index)
  * Gets the number of child objects this parent contains.
  *
  * Returns: the number of child objects
- *
- * MT safe.
  */
 guint
 gst_child_proxy_get_children_count (GstChildProxy * parent)
@@ -192,11 +186,9 @@ gst_child_proxy_get_children_count (GstChildProxy * parent)
  *
  * Looks up which object and #GParamSpec would be effected by the given @name.
  *
- * MT safe.
- *
  * Returns: %TRUE if @target and @pspec could be found. %FALSE otherwise. In that
  * case the values for @pspec and @target are not modified. Unref @target after
- * usage. For plain GObjects @target is the same as @object.
+ * usage. For plain #GObject @target is the same as @object.
  */
 gboolean
 gst_child_proxy_lookup (GstChildProxy * object, const gchar * name,
@@ -228,7 +220,7 @@ gst_child_proxy_lookup (GstChildProxy * object, const gchar * name,
       GST_INFO ("no such object %s", current[0]);
       break;
     }
-    g_object_unref (obj);
+    gst_object_unref (obj);
     obj = next;
     current++;
   }
@@ -249,7 +241,7 @@ gst_child_proxy_lookup (GstChildProxy * object, const gchar * name,
       res = TRUE;
     }
   }
-  g_object_unref (obj);
+  gst_object_unref (obj);
   g_strfreev (names);
   return res;
 }
@@ -272,13 +264,17 @@ gst_child_proxy_get_property (GstChildProxy * object, const gchar * name,
 
   g_return_if_fail (GST_IS_CHILD_PROXY (object));
   g_return_if_fail (name != NULL);
-  g_return_if_fail (G_IS_VALUE (value));
+  g_return_if_fail (value != NULL);
 
   if (!gst_child_proxy_lookup (object, name, &target, &pspec))
     goto not_found;
 
+  if (!G_IS_VALUE (value)) {
+    g_value_init (value, pspec->value_type);
+  }
+
   g_object_get_property (target, pspec->name, value);
-  g_object_unref (target);
+  gst_object_unref (target);
 
   return;
 
@@ -319,7 +315,7 @@ gst_child_proxy_get_valist (GstChildProxy * object,
 
     g_value_init (&value, pspec->value_type);
     g_object_get_property (target, pspec->name, &value);
-    g_object_unref (target);
+    gst_object_unref (target);
 
     G_VALUE_LCOPY (&value, var_args, 0, &error);
     if (error)
@@ -388,7 +384,7 @@ gst_child_proxy_set_property (GstChildProxy * object, const gchar * name,
     goto not_found;
 
   g_object_set_property (target, pspec->name, value);
-  g_object_unref (target);
+  gst_object_unref (target);
   return;
 
 not_found:
@@ -433,7 +429,7 @@ gst_child_proxy_set_valist (GstChildProxy * object,
       goto cant_copy;
 
     g_object_set_property (target, pspec->name, &value);
-    g_object_unref (target);
+    gst_object_unref (target);
 
     g_value_unset (&value);
     name = va_arg (var_args, gchar *);
@@ -451,7 +447,7 @@ cant_copy:
     g_warning ("error copying value %s in object %s: %s", pspec->name,
         (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : ""), error);
     g_value_unset (&value);
-    g_object_unref (target);
+    gst_object_unref (target);
     g_free (error);
     return;
   }
@@ -484,7 +480,7 @@ gst_child_proxy_set (GstChildProxy * object, const gchar * first_property_name,
  * @child: the newly added child
  * @name: the name of the new child
  *
- * Emits the "child-added" signal.
+ * Emits the #GstChildProxy::child-added signal.
  */
 void
 gst_child_proxy_child_added (GstChildProxy * parent, GObject * child,
@@ -499,7 +495,7 @@ gst_child_proxy_child_added (GstChildProxy * parent, GObject * child,
  * @child: the removed child
  * @name: the name of the old child
  *
- * Emits the "child-removed" signal.
+ * Emits the #GstChildProxy::child-removed signal.
  */
 void
 gst_child_proxy_child_removed (GstChildProxy * parent, GObject * child,
@@ -527,7 +523,7 @@ gst_child_proxy_base_init (gpointer g_class)
     /* create interface signals and properties here. */
     /**
      * GstChildProxy::child-added:
-     * @child_proxy: the #GstChildProxy
+     * @self: the #GstChildProxy
      * @object: the #GObject that was added
      * @name: the name of the new child
      *
@@ -536,12 +532,12 @@ gst_child_proxy_base_init (gpointer g_class)
     signals[CHILD_ADDED] =
         g_signal_new ("child-added", G_TYPE_FROM_CLASS (g_class),
         G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstChildProxyInterface,
-            child_added), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE,
+            child_added), NULL, NULL, NULL, G_TYPE_NONE,
         2, G_TYPE_OBJECT, G_TYPE_STRING);
 
     /**
      * GstChildProxy::child-removed:
-     * @child_proxy: the #GstChildProxy
+     * @self: the #GstChildProxy
      * @object: the #GObject that was removed
      * @name: the name of the old child
      *
@@ -550,7 +546,7 @@ gst_child_proxy_base_init (gpointer g_class)
     signals[CHILD_REMOVED] =
         g_signal_new ("child-removed", G_TYPE_FROM_CLASS (g_class),
         G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstChildProxyInterface,
-            child_removed), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE,
+            child_removed), NULL, NULL, NULL, G_TYPE_NONE,
         2, G_TYPE_OBJECT, G_TYPE_STRING);
 
     initialized = TRUE;
@@ -560,7 +556,7 @@ gst_child_proxy_base_init (gpointer g_class)
 GType
 gst_child_proxy_get_type (void)
 {
-  static volatile gsize type = 0;
+  static gsize type = 0;
 
   if (g_once_init_enter (&type)) {
     GType _type;
index 57e3012..47444fc 100644 (file)
@@ -44,9 +44,6 @@ typedef struct _GstChildProxyInterface GstChildProxyInterface;
 /**
  * GstChildProxyInterface:
  * @parent: parent interface type.
- * @get_child_by_name:  virtual method to fetch the child by name
- * @get_child_by_index: virtual method to fetch the child by index
- * @get_children_count: virtual method to get the children count
  *
  * #GstChildProxy interface.
  */
@@ -55,12 +52,60 @@ struct _GstChildProxyInterface
   GTypeInterface parent;
 
   /* methods */
+
+  /**
+   * #GstChildProxyInterface::get_child_by_name:
+   * @parent: the #GstChildProxy
+   * @name: the name of the child to fetch
+   *
+   * Fetch a child object by name
+   *
+   * Returns: (transfer full) (nullable): the child object
+   */
   GObject * (*get_child_by_name)  (GstChildProxy * parent, const gchar * name);
+
+  /**
+   * #GstChildProxyInterface::get_child_by_index:
+   * @parent: the #GstChildProxy
+   * @index: the index of the child to fetch
+   *
+   * Fetch a child object by index
+   *
+   * Returns: (transfer full) (nullable): the child object
+   */
   GObject * (*get_child_by_index) (GstChildProxy * parent, guint index);
+
+  /**
+   * #GstChildProxyInterface::get_children_count:
+   * @parent: the #GstChildProxy
+   *
+   * Get the number of children in @parent
+   *
+   * Returns: the number of children
+   */
   guint     (*get_children_count) (GstChildProxy * parent);
+
   /*< private >*/
   /* signals */
+
+  /**
+   * #GstChildProxyInterface::child_added:
+   * @parent: the #GstChildProxy
+   * @child: the child object
+   * @name: the name of the child object
+   *
+   * Called when @child is added to @parent
+   */
   void      (*child_added)        (GstChildProxy * parent, GObject * child, const gchar * name);
+
+  /**
+   * #GstChildProxyInterface::child_removed:
+   * @parent: the #GstChildProxy
+   * @child: the child object
+   * @name: the name of the child object
+   *
+   * Called when @child is removed from @parent
+   */
   void      (*child_removed)      (GstChildProxy * parent, GObject * child, const gchar * name);
 
   /*< private >*/
index 279b1f8..9a83cc9 100644 (file)
@@ -40,7 +40,7 @@
  *
  * The pipeline uses the clock to calculate the running time. Usually all
  * renderers synchronize to the global clock using the buffer timestamps, the
- * newsegment events and the element's base time, see #GstPipeline.
+ * #GST_EVENT_SEGMENT events and the element's base time, see #GstPipeline.
  *
  * A clock implementation can support periodic and single shot clock
  * notifications both synchronous and asynchronous.
  * notification using gst_clock_new_single_shot_id() or
  * gst_clock_new_periodic_id().
  *
- * To perform a blocking wait for the specific time of the #GstClockID use the
+ * To perform a blocking wait for the specific time of the #GstClockID use
  * gst_clock_id_wait(). To receive a callback when the specific time is reached
  * in the clock use gst_clock_id_wait_async(). Both these calls can be
  * interrupted with the gst_clock_id_unschedule() call. If the blocking wait is
  * unscheduled a return value of #GST_CLOCK_UNSCHEDULED is returned.
  *
  * Periodic callbacks scheduled async will be repeatedly called automatically
- * until it is unscheduled. To schedule a sync periodic callback,
+ * until they are unscheduled. To schedule a sync periodic callback,
  * gst_clock_id_wait() should be called repeatedly.
  *
  * The async callbacks can happen from any thread, either provided by the core
@@ -84,7 +84,7 @@
  * the clock is not PLAYING.
  *
  * When a clock has the #GST_CLOCK_FLAG_CAN_SET_MASTER flag set, it can be
- * slaved to another #GstClock with the gst_clock_set_master(). The clock will
+ * slaved to another #GstClock with gst_clock_set_master(). The clock will
  * then automatically be synchronized to this master clock by repeatedly
  * sampling the master clock and the slave clock and recalibrating the slave
  * clock with gst_clock_set_calibration(). This feature is mostly useful for
@@ -167,11 +167,7 @@ struct _GstClockPrivate
   gboolean synced;
 };
 
-typedef struct
-{
-  GstClockEntry entry;
-  GWeakRef clock;
-} GstClockEntryImpl;
+typedef struct _GstClockEntryImpl GstClockEntryImpl;
 
 #define GST_CLOCK_ENTRY_CLOCK_WEAK_REF(entry) (&((GstClockEntryImpl *)(entry))->clock)
 
@@ -249,7 +245,7 @@ gst_clock_entry_new (GstClock * clock, GstClockTime time,
 {
   GstClockEntry *entry;
 
-  entry = (GstClockEntry *) g_slice_new (GstClockEntryImpl);
+  entry = (GstClockEntry *) g_slice_new0 (GstClockEntryImpl);
 
   /* FIXME: add tracer hook for struct allocations such as clock entries */
 
@@ -314,6 +310,8 @@ gboolean
 gst_clock_single_shot_id_reinit (GstClock * clock, GstClockID id,
     GstClockTime time)
 {
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (time), FALSE);
+
   return gst_clock_entry_reinit (clock, (GstClockEntry *) id, time,
       GST_CLOCK_TIME_NONE, GST_CLOCK_ENTRY_SINGLE);
 }
@@ -335,6 +333,9 @@ gboolean
 gst_clock_periodic_id_reinit (GstClock * clock, GstClockID id,
     GstClockTime start_time, GstClockTime interval)
 {
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (start_time), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE);
+
   return gst_clock_entry_reinit (clock, (GstClockEntry *) id, start_time,
       interval, GST_CLOCK_ENTRY_PERIODIC);
 }
@@ -343,11 +344,9 @@ gst_clock_periodic_id_reinit (GstClock * clock, GstClockID id,
  * gst_clock_id_ref:
  * @id: The #GstClockID to ref
  *
- * Increase the refcount of given @id.
+ * Increases the refcount of given @id.
  *
  * Returns: (transfer full): The same #GstClockID with increased refcount.
- *
- * MT safe.
  */
 GstClockID
 gst_clock_id_ref (GstClockID id)
@@ -363,6 +362,7 @@ static void
 _gst_clock_id_free (GstClockID id)
 {
   GstClockEntry *entry;
+  GstClockEntryImpl *entry_impl;
   g_return_if_fail (id != NULL);
 
   GST_CAT_DEBUG (GST_CAT_CLOCK, "freed entry %p", id);
@@ -370,6 +370,10 @@ _gst_clock_id_free (GstClockID id)
   if (entry->destroy_data)
     entry->destroy_data (entry->user_data);
 
+  entry_impl = (GstClockEntryImpl *) id;
+  if (entry_impl->destroy_entry)
+    entry_impl->destroy_entry (entry_impl);
+
   g_weak_ref_clear (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
 
   /* FIXME: add tracer hook for struct allocations such as clock entries */
@@ -381,10 +385,8 @@ _gst_clock_id_free (GstClockID id)
  * gst_clock_id_unref:
  * @id: (transfer full): The #GstClockID to unref
  *
- * Unref given @id. When the refcount reaches 0 the
+ * Unrefs given @id. When the refcount reaches 0 the
  * #GstClockID will be freed.
- *
- * MT safe.
  */
 void
 gst_clock_id_unref (GstClockID id)
@@ -405,21 +407,17 @@ gst_clock_id_unref (GstClockID id)
  * @clock: The #GstClockID to get a single shot notification from
  * @time: the requested time
  *
- * Get a #GstClockID from @clock to trigger a single shot
- * notification at the requested time. The single shot id should be
- * unreffed after usage.
- *
- * Free-function: gst_clock_id_unref
+ * Gets a #GstClockID from @clock to trigger a single shot
+ * notification at the requested time.
  *
  * Returns: (transfer full): a #GstClockID that can be used to request the
  *     time notification.
- *
- * MT safe.
  */
 GstClockID
 gst_clock_new_single_shot_id (GstClock * clock, GstClockTime time)
 {
   g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (time), NULL);
 
   return gst_clock_entry_new (clock,
       time, GST_CLOCK_TIME_NONE, GST_CLOCK_ENTRY_SINGLE);
@@ -431,17 +429,12 @@ gst_clock_new_single_shot_id (GstClock * clock, GstClockTime time)
  * @start_time: the requested start time
  * @interval: the requested interval
  *
- * Get an ID from @clock to trigger a periodic notification.
+ * Gets an ID from @clock to trigger a periodic notification.
  * The periodic notifications will start at time @start_time and
- * will then be fired with the given @interval. @id should be unreffed
- * after usage.
- *
- * Free-function: gst_clock_id_unref
+ * will then be fired with the given @interval.
  *
  * Returns: (transfer full): a #GstClockID that can be used to request the
  *     time notification.
- *
- * MT safe.
  */
 GstClockID
 gst_clock_new_periodic_id (GstClock * clock, GstClockTime start_time,
@@ -464,9 +457,7 @@ gst_clock_new_periodic_id (GstClock * clock, GstClockTime start_time,
  * Compares the two #GstClockID instances. This function can be used
  * as a GCompareFunc when sorting ids.
  *
- * Returns: negative value if a < b; zero if a = b; positive value if a > b
- *
- * MT safe.
+ * Returns: negative value if `a < b`; zero if `a = b`; positive value if `a > b`
  */
 gint
 gst_clock_id_compare_func (gconstpointer id1, gconstpointer id2)
@@ -489,11 +480,9 @@ gst_clock_id_compare_func (gconstpointer id1, gconstpointer id2)
  * gst_clock_id_get_time:
  * @id: The #GstClockID to query
  *
- * Get the time of the clock ID
+ * Gets the time of the clock ID
  *
  * Returns: the time of the given clock id.
- *
- * MT safe.
  */
 GstClockTime
 gst_clock_id_get_time (GstClockID id)
@@ -509,7 +498,7 @@ gst_clock_id_get_time (GstClockID id)
  * @jitter: (out) (allow-none): a pointer that will contain the jitter,
  *     can be %NULL.
  *
- * Perform a blocking wait on @id.
+ * Performs a blocking wait on @id.
  * @id should have been created with gst_clock_new_single_shot_id()
  * or gst_clock_new_periodic_id() and should not have been unscheduled
  * with a call to gst_clock_id_unschedule().
@@ -527,8 +516,6 @@ gst_clock_id_get_time (GstClockID id)
  * if the current clock time is past the time of @id, #GST_CLOCK_OK if
  * @id was scheduled in time. #GST_CLOCK_UNSCHEDULED if @id was
  * unscheduled with gst_clock_id_unschedule().
- *
- * MT safe.
  */
 GstClockReturn
 gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter)
@@ -600,18 +587,16 @@ invalid_entry:
  * @user_data: User data passed in the callback
  * @destroy_data: #GDestroyNotify for user_data
  *
- * Register a callback on the given #GstClockID @id with the given
+ * Registers a callback on the given #GstClockID @id with the given
  * function and user_data. When passing a #GstClockID with an invalid
  * time to this function, the callback will be called immediately
- * with  a time set to GST_CLOCK_TIME_NONE. The callback will
+ * with  a time set to %GST_CLOCK_TIME_NONE. The callback will
  * be called when the time of @id has been reached.
  *
  * The callback @func can be invoked from any thread, either provided by the
  * core or from a streaming thread. The application should be prepared for this.
  *
  * Returns: the result of the non blocking wait.
- *
- * MT safe.
  */
 GstClockReturn
 gst_clock_id_wait_async (GstClockID id,
@@ -676,12 +661,10 @@ invalid_entry:
  * gst_clock_id_unschedule:
  * @id: The id to unschedule
  *
- * Cancel an outstanding request with @id. This can either
+ * Cancels an outstanding request with @id. This can either
  * be an outstanding async notification or a pending sync notification.
  * After this call, @id cannot be used anymore to receive sync or
  * async notifications, you need to create a new #GstClockID.
- *
- * MT safe.
  */
 void
 gst_clock_id_unschedule (GstClockID id)
@@ -746,10 +729,10 @@ gst_clock_class_init (GstClockClass * klass)
 
   /**
    * GstClock::synced:
-   * @clock: the clock
+   * @self: the clock
    * @synced: if the clock is synced now
    *
-   * Signaled on clocks with GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC set once
+   * Signaled on clocks with %GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC set once
    * the clock is synchronized, or when it completely lost synchronization.
    * This signal will not be emitted on clocks without the flag.
    *
@@ -760,8 +743,7 @@ gst_clock_class_init (GstClockClass * klass)
    */
   gst_clock_signals[SIGNAL_SYNCED] =
       g_signal_new ("synced", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
-      0, NULL, NULL,
-      g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+      0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
 }
 
 static void
@@ -830,7 +812,7 @@ gst_clock_finalize (GObject * object)
  * @clock: a #GstClock
  * @resolution: The resolution to set
  *
- * Set the accuracy of the clock. Some clocks have the possibility to operate
+ * Sets the accuracy of the clock. Some clocks have the possibility to operate
  * with different accuracy at the expense of more resource usage. There is
  * normally no need to change the default resolution of a clock. The resolution
  * of a clock can only be changed if the clock has the
@@ -861,12 +843,10 @@ gst_clock_set_resolution (GstClock * clock, GstClockTime resolution)
  * gst_clock_get_resolution:
  * @clock: a #GstClock
  *
- * Get the accuracy of the clock. The accuracy of the clock is the granularity
+ * Gets the accuracy of the clock. The accuracy of the clock is the granularity
  * of the values returned by gst_clock_get_time().
  *
  * Returns: the resolution of the clock in units of #GstClockTime.
- *
- * MT safe.
  */
 GstClockTime
 gst_clock_get_resolution (GstClock * clock)
@@ -1063,10 +1043,8 @@ gst_clock_unadjust_unlocked (GstClock * clock, GstClockTime external)
  * Gets the current internal time of the given clock. The time is returned
  * unadjusted for the offset and the rate.
  *
- * Returns: the internal time of the clock. Or GST_CLOCK_TIME_NONE when
+ * Returns: the internal time of the clock. Or %GST_CLOCK_TIME_NONE when
  * given invalid input.
- *
- * MT safe.
  */
 GstClockTime
 gst_clock_get_internal_time (GstClock * clock)
@@ -1110,10 +1088,8 @@ not_supported:
  * monotonically increasing and adjusted according to the current
  * offset and rate.
  *
- * Returns: the time of the clock. Or GST_CLOCK_TIME_NONE when
+ * Returns: the time of the clock. Or %GST_CLOCK_TIME_NONE when
  * given invalid input.
- *
- * MT safe.
  */
 GstClockTime
 gst_clock_get_time (GstClock * clock)
@@ -1159,9 +1135,9 @@ gst_clock_get_time (GstClock * clock)
  * Subsequent calls to gst_clock_get_time() will return clock times computed as
  * follows:
  *
- * |[
+ * ``` C
  *   time = (internal_time - internal) * rate_num / rate_denom + external
- * ]|
+ * ```
  *
  * This formula is implemented in gst_clock_adjust_unlocked(). Of course, it
  * tries to do the integer arithmetic as precisely as possible.
@@ -1169,8 +1145,6 @@ gst_clock_get_time (GstClock * clock)
  * Note that gst_clock_get_time() always returns increasing values so when you
  * move the clock backwards, gst_clock_get_time() will report the previous value
  * until the clock catches up.
- *
- * MT safe.
  */
 void
 gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime
@@ -1179,6 +1153,8 @@ gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime
   GstClockPrivate *priv;
 
   g_return_if_fail (GST_IS_CLOCK (clock));
+  g_return_if_fail (GST_CLOCK_TIME_IS_VALID (internal));
+  g_return_if_fail (GST_CLOCK_TIME_IS_VALID (external));
   g_return_if_fail (rate_num != GST_CLOCK_TIME_NONE);
   g_return_if_fail (rate_denom > 0 && rate_denom != GST_CLOCK_TIME_NONE);
 
@@ -1211,8 +1187,6 @@ gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime
  *
  * @internal, @external, @rate_num, and @rate_denom can be left %NULL if the
  * caller is not interested in the values.
- *
- * MT safe.
  */
 void
 gst_clock_get_calibration (GstClock * clock, GstClockTime * internal,
@@ -1273,7 +1247,7 @@ gst_clock_slave_callback (GstClock * master, GstClockTime time,
  * @clock: a #GstClock
  * @master: (allow-none): a master #GstClock
  *
- * Set @master as the master clock for @clock. @clock will be automatically
+ * Sets @master as the master clock for @clock. @clock will be automatically
  * calibrated so that gst_clock_get_time() reports the same time as the
  * master clock.
  *
@@ -1287,8 +1261,6 @@ gst_clock_slave_callback (GstClock * master, GstClockTime time,
  * Returns: %TRUE if the clock is capable of being slaved to a master clock.
  * Trying to set a master on a clock without the
  * #GST_CLOCK_FLAG_CAN_SET_MASTER flag will make this function return %FALSE.
- *
- * MT safe.
  */
 gboolean
 gst_clock_set_master (GstClock * clock, GstClock * master)
@@ -1360,14 +1332,11 @@ master_not_synced:
  * gst_clock_get_master:
  * @clock: a #GstClock
  *
- * Get the master clock that @clock is slaved to or %NULL when the clock is
+ * Gets the master clock that @clock is slaved to or %NULL when the clock is
  * not slaved to any master clock.
  *
  * Returns: (transfer full) (nullable): a master #GstClock or %NULL
- *     when this clock is not slaved to a master clock. Unref after
- *     usage.
- *
- * MT safe.
+ *     when this clock is not slaved to a master clock.
  */
 GstClock *
 gst_clock_get_master (GstClock * clock)
@@ -1394,10 +1363,7 @@ gst_clock_get_master (GstClock * clock)
  * This function returns the underlying clock.
  *
  * Returns: (transfer full) (nullable): a #GstClock or %NULL when the
- *     underlying clock has been freed.  Unref after usage.
- *
- * MT safe.
- *
+ *     underlying clock has been freed.
  * Since: 1.16
  */
 GstClock *
@@ -1422,9 +1388,6 @@ gst_clock_id_get_clock (GstClockID id)
  * no longer usable and should be freed.
  *
  * Returns: whether the clock @id uses the same underlying #GstClock @clock.
- *
- * MT safe.
- *
  * Since: 1.16
  */
 gboolean
@@ -1469,8 +1432,6 @@ gst_clock_id_uses_clock (GstClockID id, GstClock * clock)
  *
  * Returns: %TRUE if enough observations were added to run the
  * regression algorithm.
- *
- * MT safe.
  */
 gboolean
 gst_clock_add_observation (GstClock * clock, GstClockTime slave,
@@ -1506,6 +1467,8 @@ gst_clock_add_observation (GstClock * clock, GstClockTime slave,
  * The caller can then take the results and call gst_clock_set_calibration()
  * with the values, or some modified version of them.
  *
+ * Returns: %TRUE if enough observations were added to run the
+ * regression algorithm.
  * Since: 1.6
  */
 gboolean
@@ -1519,6 +1482,8 @@ gst_clock_add_observation_unapplied (GstClock * clock, GstClockTime slave,
   guint n;
 
   g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (slave), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (master), FALSE);
   g_return_val_if_fail (r_squared != NULL, FALSE);
 
   priv = clock->priv;
@@ -1581,7 +1546,7 @@ invalid:
  * @clock: a #GstClock
  * @timeout: a timeout
  *
- * Set the amount of time, in nanoseconds, to sample master and slave
+ * Sets the amount of time, in nanoseconds, to sample master and slave
  * clocks
  */
 void
@@ -1598,7 +1563,7 @@ gst_clock_set_timeout (GstClock * clock, GstClockTime timeout)
  * gst_clock_get_timeout:
  * @clock: a #GstClock
  *
- * Get the amount of time that master and slave clocks are sampled.
+ * Gets the amount of time that master and slave clocks are sampled.
  *
  * Returns: the interval between samples.
  */
@@ -1692,9 +1657,9 @@ gst_clock_get_property (GObject * object, guint prop_id,
  * is %GST_CLOCK_TIME_NONE it will wait forever, otherwise it will time out
  * after @timeout nanoseconds.
  *
- * For asynchronous waiting, the GstClock::synced signal can be used.
+ * For asynchronous waiting, the #GstClock::synced signal can be used.
  *
- * This returns immediately with TRUE if GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC
+ * This returns immediately with %TRUE if %GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC
  * is not set on the clock, or if the clock is already synced.
  *
  * Returns: %TRUE if waiting was successful, or %FALSE on timeout
@@ -1739,9 +1704,8 @@ gst_clock_wait_for_sync (GstClock * clock, GstClockTime timeout)
  * gst_clock_is_synced:
  * @clock: a GstClock
  *
- * Checks if the clock is currently synced.
- *
- * This returns if GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC is not set on the clock.
+ * Checks if the clock is currently synced, by looking at whether
+ * %GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC is set.
  *
  * Returns: %TRUE if the clock is currently synced
  *
@@ -1761,10 +1725,10 @@ gst_clock_is_synced (GstClock * clock)
  * @clock: a GstClock
  * @synced: if the clock is synced
  *
- * Sets @clock to synced and emits the GstClock::synced signal, and wakes up any
+ * Sets @clock to synced and emits the #GstClock::synced signal, and wakes up any
  * thread waiting in gst_clock_wait_for_sync().
  *
- * This function must only be called if GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC
+ * This function must only be called if %GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC
  * is set on the clock, and is intended to be called by subclasses only.
  *
  * Since: 1.6
index f34c97d..46419c9 100644 (file)
@@ -125,28 +125,28 @@ typedef gpointer GstClockID;
  * GST_TIME_AS_SECONDS:
  * @time: the time
  *
- * Convert a #GstClockTime to seconds.
+ * Converts a #GstClockTime to seconds.
  */
 #define GST_TIME_AS_SECONDS(time)  ((time) / GST_SECOND)
 /**
  * GST_TIME_AS_MSECONDS:
  * @time: the time
  *
- * Convert a #GstClockTime to milliseconds (1/1000 of a second).
+ * Converts a #GstClockTime to milliseconds (1/1000 of a second).
  */
 #define GST_TIME_AS_MSECONDS(time) ((time) / G_GINT64_CONSTANT (1000000))
 /**
  * GST_TIME_AS_USECONDS:
  * @time: the time
  *
- * Convert a #GstClockTime to microseconds (1/1000000 of a second).
+ * Converts a #GstClockTime to microseconds (1/1000000 of a second).
  */
 #define GST_TIME_AS_USECONDS(time) ((time) / G_GINT64_CONSTANT (1000))
 /**
  * GST_TIME_AS_NSECONDS:
  * @time: the time
  *
- * Convert a #GstClockTime to nanoseconds (1/1000000000 of a second).
+ * Converts a #GstClockTime to nanoseconds (1/1000000000 of a second).
  */
 #define GST_TIME_AS_NSECONDS(time) (time)
 
@@ -155,7 +155,7 @@ typedef gpointer GstClockID;
  * @s: the first time
  * @e: the second time
  *
- * Calculate a difference between two clock times as a #GstClockTimeDiff.
+ * Calculates 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))
@@ -164,7 +164,7 @@ typedef gpointer GstClockID;
  * GST_TIMEVAL_TO_TIME:
  * @tv: the timeval to convert
  *
- * Convert a #GTimeVal to a #GstClockTime.
+ * Converts a GTimeVal to a #GstClockTime.
  */
 #define GST_TIMEVAL_TO_TIME(tv)         (GstClockTime)((tv).tv_sec * GST_SECOND + (tv).tv_usec * GST_USECOND)
 
@@ -173,7 +173,7 @@ typedef gpointer GstClockID;
  * @t: The #GstClockTime to convert
  * @tv: The target timeval
  *
- * Convert a #GstClockTime to a #GTimeVal
+ * Converts a #GstClockTime to a GTimeVal
  *
  * > on 32-bit systems, a timeval has a range of only 2^32 - 1 seconds,
  * > which is about 68 years.  Expect trouble if you want to schedule stuff
@@ -193,7 +193,7 @@ G_STMT_START {                                                  \
  * GST_TIMESPEC_TO_TIME:
  * @ts: the timespec to convert
  *
- * Convert a struct timespec (see man pselect) to a #GstClockTime.
+ * Converts 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)
 /**
@@ -201,7 +201,7 @@ G_STMT_START {                                                  \
  * @t: The #GstClockTime to convert
  * @ts: The target timespec
  *
- * Convert a #GstClockTime to a struct timespec (see man pselect)
+ * Converts a #GstClockTime to a struct timespec (see `man pselect`)
  */
 #define GST_TIME_TO_TIMESPEC(t,ts)                                \
 G_STMT_START {                                                    \
@@ -216,20 +216,21 @@ G_STMT_START {                                                    \
  * GST_TIME_FORMAT: (skip):
  *
  * A string that can be used in printf-like format strings to display a
- * #GstClockTime value in h:m:s format.  Use GST_TIME_ARGS() to construct
+ * #GstClockTime value in `h:m:s` format.  Use GST_TIME_ARGS() to construct
  * the matching arguments.
  *
  * Example:
- * |[<!-- language="C" -->
+ *
+ * ``` C
  * printf("%" GST_TIME_FORMAT "\n", GST_TIME_ARGS(ts));
- * ]|
+ * ``` 
  */
 #define GST_TIME_FORMAT "u:%02u:%02u.%09u"
 /**
  * GST_TIME_ARGS: (skip):
  * @t: a #GstClockTime
  *
- * Format @t for the #GST_TIME_FORMAT format string. Note: @t will be
+ * Formats @t for the #GST_TIME_FORMAT format string. Note: @t will be
  * evaluated more than once.
  */
 #define GST_TIME_ARGS(t) \
@@ -245,13 +246,14 @@ G_STMT_START {                                                    \
  * GST_STIME_FORMAT: (skip):
  *
  * A string that can be used in printf-like format strings to display a signed
- * #GstClockTimeDiff or #gint64 value in h:m:s format.  Use GST_TIME_ARGS() to
+ * #GstClockTimeDiff or #gint64 value in `h:m:s` format.  Use GST_TIME_ARGS() to
  * construct the matching arguments.
  *
  * Example:
- * |[
+ *
+ * ``` C
  * printf("%" GST_STIME_FORMAT "\n", GST_STIME_ARGS(ts));
- * ]|
+ * ```
  *
  * Since: 1.6
  */
@@ -260,7 +262,7 @@ G_STMT_START {                                                    \
  * GST_STIME_ARGS: (skip):
  * @t: a #GstClockTimeDiff or #gint64
  *
- * Format @t for the #GST_STIME_FORMAT format string. Note: @t will be
+ * Formats @t for the #GST_STIME_FORMAT format string. Note: @t will be
  * evaluated more than once.
  *
  * Since: 1.6
@@ -336,7 +338,7 @@ typedef enum {
  * GST_CLOCK_ENTRY:
  * @entry: the entry to cast
  *
- * Cast to a clock entry
+ * Casts to a clock entry
  */
 #define GST_CLOCK_ENTRY(entry)          ((GstClockEntry *)(entry))
 
@@ -345,7 +347,7 @@ typedef enum {
  * GST_CLOCK_ENTRY_CLOCK:
  * @entry: the entry to query
  *
- * Get the owner clock of the entry
+ * Gets the owner clock of the entry
  *
  * Deprecated: Use gst_clock_id_get_clock() instead.
  */
@@ -355,21 +357,21 @@ typedef enum {
  * GST_CLOCK_ENTRY_TYPE:
  * @entry: the entry to query
  *
- * Get the type of the clock entry
+ * Gets the type of the clock entry
  */
 #define GST_CLOCK_ENTRY_TYPE(entry)     ((entry)->type)
 /**
  * GST_CLOCK_ENTRY_TIME:
  * @entry: the entry to query
  *
- * Get the requested time of this entry
+ * Gets the requested time of this entry
  */
 #define GST_CLOCK_ENTRY_TIME(entry)     ((entry)->time)
 /**
  * GST_CLOCK_ENTRY_INTERVAL:
  * @entry: the entry to query
  *
- * Get the interval of this periodic entry
+ * Gets the interval of this periodic entry
  */
 #define GST_CLOCK_ENTRY_INTERVAL(entry) ((entry)->interval)
 /**
@@ -391,7 +393,7 @@ typedef enum {
  */
 struct _GstClockEntry {
   gint                  refcount;
-  /*< protected >*/
+  /*< private >*/
 #ifndef GST_REMOVE_DEPRECATED
 #ifndef GST_DISABLE_DEPRECATED
   GstClock              *clock;
@@ -423,8 +425,6 @@ struct _GstClockEntry {
  * @GST_CLOCK_FLAG_CAN_DO_PERIODIC_ASYNC: clock can do async periodic timeout callbacks
  * @GST_CLOCK_FLAG_CAN_SET_RESOLUTION: clock's resolution can be changed
  * @GST_CLOCK_FLAG_CAN_SET_MASTER: clock can be slaved to a master clock
- * @GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC: clock needs to be synced before it can be used
- *     (Since: 1.6)
  * @GST_CLOCK_FLAG_LAST: subclasses can add additional flags starting from this flag
  *
  * The capabilities of this clock
@@ -436,6 +436,14 @@ typedef enum {
   GST_CLOCK_FLAG_CAN_DO_PERIODIC_ASYNC  = (GST_OBJECT_FLAG_LAST << 3),
   GST_CLOCK_FLAG_CAN_SET_RESOLUTION     = (GST_OBJECT_FLAG_LAST << 4),
   GST_CLOCK_FLAG_CAN_SET_MASTER         = (GST_OBJECT_FLAG_LAST << 5),
+
+  /**
+   * GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC:
+   *
+   * clock needs to be synced before it can be used
+   *
+   * Since: 1.6
+   */
   GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC     = (GST_OBJECT_FLAG_LAST << 6),
   /* padding */
   GST_CLOCK_FLAG_LAST                   = (GST_OBJECT_FLAG_LAST << 8)
@@ -451,9 +459,9 @@ typedef enum {
 
 /**
  * GstClock:
+ * @object: the parent structure
  *
- * #GstClock base structure. The values of this structure are
- * protected for subclasses, use the methods to use the #GstClock.
+ * #GstClock base structure.
  */
 struct _GstClock {
   GstObject      object;
@@ -467,15 +475,6 @@ struct _GstClock {
 /**
  * GstClockClass:
  * @parent_class: the parent class structure
- * @change_resolution: change the resolution of the clock. Not all values might
- *                     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.
- *        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.
  *
  * GStreamer clock class. Override the vmethods to implement the clock
  * functionality.
@@ -485,17 +484,81 @@ struct _GstClockClass {
 
   /*< public >*/
   /* vtable */
+
+  /**
+   * GstClockClass::change_resolution:
+   * @clock: the #GstClock
+   * @old_resolution: the previous resolution
+   * @new_resolution: the new resolution
+   *
+   * Change the resolution of the clock. Not all values might
+   * be acceptable.
+   *
+   * Returns: the new resolution
+   */
   GstClockTime          (*change_resolution)    (GstClock *clock,
                                                  GstClockTime old_resolution,
                                                  GstClockTime new_resolution);
+
+  /**
+   * GstClockClass::get_resolution:
+   * @clock: the #GstClock
+   *
+   * Get the resolution of the clock.
+   *
+   * Returns: the current resolution
+   */
   GstClockTime          (*get_resolution)       (GstClock *clock);
 
+  /**
+   * GstClockClass::get_internal_time:
+   * @clock: the #GstClock
+   *
+   * Get the internal unadjusted time of the clock.
+   *
+   * Implement #GstClockClass::wait instead.
+   *
+   * Returns: the internal time
+   */
   GstClockTime          (*get_internal_time)    (GstClock *clock);
 
   /* waiting on an ID */
+
+  /**
+   * GstClockClass::wait:
+   * @clock: the #GstClock
+   * @entry: the entry to wait on
+   * @jitter: (out) (allow-none): a pointer that will contain the jitter
+   *
+   * Perform a blocking wait on the given #GstClockEntry and return
+   * the jitter.
+   *
+   * Returns: the result of the blocking wait. #GST_CLOCK_EARLY will be returned
+   * if the current clock time is past the time of @id, #GST_CLOCK_OK if
+   * @id was scheduled in time. #GST_CLOCK_UNSCHEDULED if @id was
+   * unscheduled with gst_clock_id_unschedule().
+   */
   GstClockReturn        (*wait)                 (GstClock *clock, GstClockEntry *entry,
                                                  GstClockTimeDiff *jitter);
+
+  /**
+   * GstClockClass::wait_async:
+   * @clock: the #GstClock
+   * @entry: the entry to wait on
+   *
+   * Perform an asynchronous wait on the given #GstClockEntry.
+   *
+   * Returns: the result of the non blocking wait.
+   */
   GstClockReturn        (*wait_async)           (GstClock *clock, GstClockEntry *entry);
+
+  /**
+   * GstClockClass::unschedule:
+   * @clock: the #GstClock
+   * @entry: the entry to unschedule
+   *
+   * Unblock a blocking or async wait operation.
+   */
   void                  (*unschedule)           (GstClock *clock, GstClockEntry *entry);
 
   /*< private >*/
@@ -641,9 +704,8 @@ gboolean                gst_clock_periodic_id_reinit    (GstClock * clock,
                                                          GstClockTime start_time,
                                                          GstClockTime interval);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstClock, gst_object_unref)
-#endif
+G_DEFINE_AUTO_CLEANUP_FREE_FUNC(GstClockID, gst_clock_id_unref, 0)
 
 G_END_DECLS
 
index 7be1b19..cc5794e 100644 (file)
  *
  * If a subsystem is disabled in GStreamer, a value is defined in
  * &lt;gst/gst.h&gt;. You can check this if you do subsystem-specific stuff.
- * <example id="example-gstconfig">
- * <title>Doing subsystem specific things</title>
- * <programlisting>
- * &hash;ifndef GST_DISABLE_GST_DEBUG
+ *
+ * ``` C
+ * #ifndef GST_DISABLE_GST_DEBUG
  * // do stuff specific to the debugging subsystem
- * &hash;endif // GST_DISABLE_GST_DEBUG
- * </programlisting>
- * </example>
+ * #endif // GST_DISABLE_GST_DEBUG
+ * ```
  */
 
 #ifndef __GST_CONFIG_H__
  * http://docs.oracle.com/cd/E19205-01/820-4155/c++_faq.html#Vers6
  * https://software.intel.com/en-us/node/583402
  */
-#if defined(__alpha__) || defined(__arc__) || defined(__arm__) || defined(__aarch64__) || defined(__bfin) || defined(__hppa__) || defined(__nios2__) || defined(__MICROBLAZE__) || defined(__mips__) || defined(__or1k__) || defined(__sh__) || defined(__SH4__) || defined(__sparc__) || defined(__sparc) || defined(__ia64__) || defined(_M_ALPHA) || defined(_M_ARM) || defined(_M_IA64) || defined(__xtensa__) || defined(__e2k__) || defined(__riscv)
+#if defined(__alpha__) || defined(__arc__) || defined(__arm__) || defined(__aarch64__) || defined(__bfin) || defined(__hppa__) || defined(__nios2__) || defined(__MICROBLAZE__) || defined(__mips__) || defined(__or1k__) || defined(__sh__) || defined(__SH4__) || defined(__sparc__) || defined(__sparc) || defined(__ia64__) || defined(_M_ALPHA) || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_IA64) || defined(__xtensa__) || defined(__e2k__) || defined(__riscv)
 #  define GST_HAVE_UNALIGNED_ACCESS 0
 #elif defined(__i386__) || defined(__i386) || defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__ppc__) || defined(__ppc64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__m68k__) || defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || defined(__s390__) || defined(__s390x__) || defined(__zarch__)
 #  define GST_HAVE_UNALIGNED_ACCESS 1
index c1bbe0a..424cbe7 100644 (file)
  *
  * Applications can set a context on a complete pipeline by using
  * gst_element_set_context(), which will then be propagated to all
- * child elements. Elements can handle these in #GstElementClass.set_context()
+ * child elements. Elements can handle these in #GstElementClass::set_context
  * and merge them with the context information they already have.
  *
  * When an element needs a context it will do the following actions in this
  * order until one step succeeds:
+ *
  * 1. Check if the element already has a context
- * 2. Query downstream with GST_QUERY_CONTEXT for the context
- * 3. Query upstream with GST_QUERY_CONTEXT for the context
- * 4. Post a GST_MESSAGE_NEED_CONTEXT message on the bus with the required
+ * 2. Query downstream with %GST_QUERY_CONTEXT for the context
+ * 3. Query upstream with %GST_QUERY_CONTEXT for the context
+ * 4. Post a %GST_MESSAGE_NEED_CONTEXT message on the bus with the required
  *    context types and afterwards check if a usable context was set now
- * 5. Create a context by itself and post a GST_MESSAGE_HAVE_CONTEXT message
+ * 5. Create a context by itself and post a %GST_MESSAGE_HAVE_CONTEXT message
  *    on the bus.
  *
- * Bins will catch GST_MESSAGE_NEED_CONTEXT messages and will set any previously
+ * Bins will catch %GST_MESSAGE_NEED_CONTEXT messages and will set any previously
  * known context on the element that asks for it if possible. Otherwise the
  * application should provide one if it can.
  *
- * #GstContext<!-- -->s can be persistent.
+ * #GstContext can be persistent.
  * A persistent #GstContext is kept in elements when they reach
  * %GST_STATE_NULL, non-persistent ones will be removed.
  * Also, a non-persistent context won't override a previous persistent
@@ -59,6 +60,7 @@
  * Since: 1.2
  */
 
+#define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 #include "gst_private.h"
 #include <string.h>
 #include "gstcontext.h"
@@ -155,7 +157,7 @@ gst_context_init (GstContext * context)
  * @context_type: Context type
  * @persistent: Persistent context
  *
- * Create a new context.
+ * Creates a new context.
  *
  * Returns: (transfer full): The new context.
  *
@@ -188,7 +190,7 @@ gst_context_new (const gchar * context_type, gboolean persistent)
  * gst_context_get_context_type:
  * @context: The #GstContext.
  *
- * Get the type of @context.
+ * Gets the type of @context.
  *
  * Returns: The type of the context.
  *
@@ -227,7 +229,7 @@ gst_context_has_context_type (const GstContext * context,
  * gst_context_get_structure:
  * @context: The #GstContext.
  *
- * Access the structure of the context.
+ * Accesses the structure of the context.
  *
  * Returns: (transfer none): The structure of the context. The structure is
  * still owned by the context, which means that you should not modify it,
@@ -247,7 +249,7 @@ gst_context_get_structure (const GstContext * context)
  * gst_context_writable_structure:
  * @context: The #GstContext.
  *
- * Get a writable version of the structure.
+ * Gets a writable version of the structure.
  *
  * Returns: The structure of the context. The structure is still
  * owned by the context, which means that you should not free it and
@@ -269,7 +271,7 @@ gst_context_writable_structure (GstContext * context)
  * gst_context_is_persistent:
  * @context: The #GstContext.
  *
- * Check if @context is persistent.
+ * Checks if @context is persistent.
  *
  * Returns: %TRUE if the context is persistent.
  *
@@ -282,3 +284,79 @@ gst_context_is_persistent (const GstContext * context)
 
   return context->persistent;
 }
+
+/**
+ * gst_context_ref:
+ * @context: the context to ref
+ *
+ * Convenience macro to increase the reference count of the context.
+ *
+ * Returns: @context (for convenience when doing assignments)
+ *
+ * Since: 1.2
+ */
+GstContext *
+gst_context_ref (GstContext * context)
+{
+  return (GstContext *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (context));
+}
+
+/**
+ * gst_context_unref:
+ * @context: the context to unref
+ *
+ * Convenience macro to decrease the reference count of the context, possibly
+ * freeing it.
+ *
+ * Since: 1.2
+ */
+void
+gst_context_unref (GstContext * context)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (context));
+}
+
+/**
+ * gst_context_copy:
+ * @context: the context to copy
+ *
+ * Creates a copy of the context. Returns a copy of the context.
+ *
+ * Returns: (transfer full): a new copy of @context.
+ *
+ * MT safe
+ *
+ * Since: 1.2
+ */
+GstContext *
+gst_context_copy (const GstContext * context)
+{
+  return
+      GST_CONTEXT_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST
+          (context)));
+}
+
+/**
+ * gst_context_replace:
+ * @old_context: (inout) (transfer full): pointer to a pointer to a #GstContext
+ *     to be replaced.
+ * @new_context: (allow-none) (transfer none): pointer to a #GstContext that will
+ *     replace the context pointed to by @old_context.
+ *
+ * Modifies a pointer to a #GstContext to point to a different #GstContext. 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
+ * context is unreffed, the new one is reffed).
+ *
+ * Either @new_context or the #GstContext pointed to by @old_context may be %NULL.
+ *
+ * Returns: %TRUE if @new_context was different from @old_context
+ *
+ * Since: 1.2
+ */
+gboolean
+gst_context_replace (GstContext ** old_context, GstContext * new_context)
+{
+  return gst_mini_object_replace ((GstMiniObject **) old_context,
+      (GstMiniObject *) new_context);
+}
index f55e84c..92d8502 100644 (file)
@@ -45,29 +45,14 @@ GST_API GType _gst_context_type;
 GST_API
 GType           gst_context_get_type            (void);
 
-
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 /* refcounting */
-/**
- * gst_context_ref:
- * @context: the context to ref
- *
- * Convenience macro to increase the reference count of the context.
- *
- * Returns: @context (for convenience when doing assignments)
- */
 static inline GstContext *
 gst_context_ref (GstContext * context)
 {
   return (GstContext *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (context));
 }
 
-/**
- * gst_context_unref:
- * @context: the context to unref
- *
- * Convenience macro to decrease the reference count of the context, possibly
- * freeing it.
- */
 static inline void
 gst_context_unref (GstContext * context)
 {
@@ -75,21 +60,21 @@ gst_context_unref (GstContext * context)
 }
 
 /* copy context */
-/**
- * gst_context_copy:
- * @context: the context to copy
- *
- * Creates a copy of the context. Returns a copy of the context.
- *
- * Returns: (transfer full): a new copy of @context.
- *
- * MT safe
- */
 static inline GstContext *
 gst_context_copy (const GstContext * context)
 {
   return GST_CONTEXT_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (context)));
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+GstContext * gst_context_ref    (GstContext * context);
+
+GST_API
+void         gst_context_unref  (GstContext * context);
+
+GST_API
+GstContext * gst_context_copy   (const GstContext * context);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 /**
  * gst_context_is_writable:
@@ -111,27 +96,18 @@ gst_context_copy (const GstContext * context)
  * MT safe
  */
 #define         gst_context_make_writable(context)  GST_CONTEXT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (context)))
-/**
- * gst_context_replace:
- * @old_context: (inout) (transfer full): pointer to a pointer to a #GstContext
- *     to be replaced.
- * @new_context: (allow-none) (transfer none): pointer to a #GstContext that will
- *     replace the context pointed to by @old_context.
- *
- * Modifies a pointer to a #GstContext to point to a different #GstContext. 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
- * context is unreffed, the new one is reffed).
- *
- * Either @new_context or the #GstContext pointed to by @old_context may be %NULL.
- *
- * Returns: %TRUE if @new_context was different from @old_context
- */
+
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 static inline gboolean
 gst_context_replace (GstContext **old_context, GstContext *new_context)
 {
   return gst_mini_object_replace ((GstMiniObject **) old_context, (GstMiniObject *) new_context);
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+gboolean              gst_context_replace                  (GstContext ** old_context,
+                                                            GstContext * new_context);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 GST_API
 GstContext *          gst_context_new                      (const gchar * context_type,
@@ -151,9 +127,7 @@ GstStructure *        gst_context_writable_structure       (GstContext * context
 GST_API
 gboolean              gst_context_is_persistent            (const GstContext * context);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstContext, gst_context_unref)
-#endif
 
 G_END_DECLS
 
index 568f82f..42c32f1 100644 (file)
@@ -24,7 +24,7 @@
  * @title: GstControlBinding
  * @short_description: attachment for control source sources
  *
- * A base class for value mapping objects that attaches control sources to gobject
+ * A base class for value mapping objects that attaches control sources to #GObject
  * properties. Such an object is taking one or more #GstControlSource instances,
  * combines them and maps the resulting value to the type and value range of the
  * bound property.
@@ -145,7 +145,7 @@ gst_control_binding_constructor (GType type, guint n_construct_params,
               binding->name))) {
     GST_DEBUG_OBJECT (object, "  psec->flags : 0x%08x", pspec->flags);
 
-    /* check if this param is witable && controlable && !construct-only */
+    /* check if this param is writeable && controllable && !construct-only */
     if ((pspec->flags & (G_PARAM_WRITABLE | GST_PARAM_CONTROLLABLE |
                 G_PARAM_CONSTRUCT_ONLY)) ==
         (G_PARAM_WRITABLE | GST_PARAM_CONTROLLABLE)) {
@@ -153,7 +153,7 @@ gst_control_binding_constructor (GType type, guint n_construct_params,
     } else {
       GST_WARNING_OBJECT (object,
           "property '%s' on class '%s' needs to "
-          "be writeable, controlable and not construct_only", binding->name,
+          "be writeable, controllable and not construct_only", binding->name,
           G_OBJECT_TYPE_NAME (object));
     }
   } else {
@@ -244,7 +244,7 @@ gst_control_binding_get_property (GObject * object, guint prop_id,
  * @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.
+ * handles it 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.
@@ -260,6 +260,7 @@ gst_control_binding_sync_values (GstControlBinding * binding,
   gboolean ret = FALSE;
 
   g_return_val_if_fail (GST_IS_CONTROL_BINDING (binding), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
 
   if (binding->disabled)
     return TRUE;
@@ -313,7 +314,7 @@ gst_control_binding_get_value (GstControlBinding * binding,
  * @values: (array length=n_values): array to put control-values in
  *
  * Gets a number of values for the given controlled property starting at the
- * requested time. The array @values need to hold enough space for @n_values of
+ * requested time. The array @values needs 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
@@ -482,7 +483,7 @@ gst_control_binding_set_disabled (GstControlBinding * binding,
  * gst_control_binding_is_disabled:
  * @binding: the control binding
  *
- * Check if the control binding is disabled.
+ * Checks if the control binding is disabled.
  *
  * Returns: %TRUE if the binding is inactive
  */
index ba67547..e357669 100644 (file)
@@ -48,11 +48,15 @@ typedef struct _GstControlBindingPrivate GstControlBindingPrivate;
 
 #include <gst/gstcontrolsource.h>
 
-/* FIXME(2.0): remove, this is unused */
+/**
+ * GstControlBindingConvert: (attributes doc.skip=true)
+ * FIXME(2.0): remove, this is unused
+ */
 typedef void (* GstControlBindingConvert) (GstControlBinding *binding, gdouble src_value, GValue *dest_value);
 
 /**
  * GstControlBinding:
+ * @parent: the parent structure
  * @name: name of the property of this binding
  * @pspec: #GParamSpec for this property
  *
@@ -76,8 +80,10 @@ struct _GstControlBinding {
 
   union {
     struct {
+      /*< private >*/
       GstControlBindingPrivate *priv;
     } abi;
+    /*< private >*/
     gpointer _gst_reserved[GST_PADDING];
   } ABI;
 };
@@ -85,11 +91,6 @@ struct _GstControlBinding {
 /**
  * GstControlBindingClass:
  * @parent_class: Parent class
- * @sync_values: implementation for updating the target values
- * @get_value: implementation to fetch a single control-value
- * @get_value_array: implementation to fetch a series of control-values
- * @get_g_value_array: implementation to fetch a series of control-values
- *                     as g_values
  *
  * The class structure of #GstControlBinding.
  */
@@ -99,9 +100,59 @@ struct _GstControlBindingClass
   GstObjectClass parent_class;
 
   /*< public >*/
+
+  /**
+   * GstControlBindingClass::sync_values:
+   * @binding: 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
+   *
+   * Update the target values
+   *
+   * Returns: %TRUE if the controller value could be applied to the object
+   * property, %FALSE otherwise
+   */
   gboolean (* sync_values) (GstControlBinding *binding, GstObject *object, GstClockTime timestamp, GstClockTime last_sync);
+
+  /**
+   * GstControlBindingClass::get_value:
+   * @binding: the control binding
+   * @timestamp: the time the control-change should be read from
+   *
+   * Fetch a single control-value
+   *
+   * Returns: (nullable): the GValue of the property at the given time,
+   * or %NULL if the property isn't controlled.
+   */
   GValue * (* get_value) (GstControlBinding *binding, GstClockTime timestamp);
+
+  /**
+   * GstControlBindingClass::get_value_array:
+   * @binding: 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 length=n_values): array to put control-values in
+   *
+   * Fetch a series of control-values
+   *
+   * Returns: %TRUE if the given array could be filled, %FALSE otherwise
+   */
   gboolean (* get_value_array) (GstControlBinding *binding, GstClockTime timestamp,GstClockTime interval, guint n_values, gpointer values);
+
+  /**
+   * GstControlBindingClass::get_g_value_array:
+   * @binding: 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 length=n_values): array to put control-values in
+   *
+   * Fetch a series of control-values as g_values
+   *
+   * Returns: %TRUE if the given array could be filled, %FALSE otherwise
+   */
   gboolean (* get_g_value_array) (GstControlBinding *binding, GstClockTime timestamp,GstClockTime interval, guint n_values, GValue *values);
 
   /*< private >*/
@@ -133,9 +184,7 @@ void                gst_control_binding_set_disabled       (GstControlBinding *
 GST_API
 gboolean            gst_control_binding_is_disabled        (GstControlBinding * binding);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstControlBinding, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 1817edc..04271be 100644 (file)
@@ -84,6 +84,7 @@ gst_control_source_get_value (GstControlSource * self, GstClockTime timestamp,
     gdouble * value)
 {
   g_return_val_if_fail (GST_IS_CONTROL_SOURCE (self), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
 
   if (G_LIKELY (self->get_value)) {
     return self->get_value (self, timestamp, value);
@@ -112,6 +113,8 @@ gst_control_source_get_value_array (GstControlSource * self,
     gdouble * values)
 {
   g_return_val_if_fail (GST_IS_CONTROL_SOURCE (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);
 
   if (G_LIKELY (self->get_value_array)) {
     return self->get_value_array (self, timestamp, interval, n_values, values);
index 295d46f..cd2dfaf 100644 (file)
@@ -54,7 +54,7 @@ typedef struct _GstValueArray GstValueArray;
  * @timestamp: timestamp of the value change
  * @value: the corresponding value
  *
- * Structure for saving a timestamp and a value.
+ * Structure for storing a timestamp and a value.
  */
 struct _GstTimedValue
 {
@@ -84,7 +84,7 @@ typedef gboolean (* GstControlSourceGetValue) (GstControlSource *self,
  * @n_values: the number of values
  * @values: array to put control-values in
  *
- * Function for returning an array of values for starting at a given timestamp.
+ * Function for returning an array of values starting at a given timestamp.
  *
  * Returns: %TRUE if the values were successfully calculated.
  *
@@ -94,6 +94,7 @@ typedef gboolean (* GstControlSourceGetValueArray) (GstControlSource *self,
 
 /**
  * GstControlSource:
+ * @parent: the parent structure
  * @get_value: Function for returning a value for a given timestamp
  * @get_value_array: Function for returning a values array for a given timestamp
  *
@@ -137,13 +138,9 @@ GST_API
 gboolean       gst_control_source_get_value_array       (GstControlSource *self, GstClockTime timestamp,
                                                          GstClockTime interval, guint n_values,
                                                          gdouble *values);
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstControlSource, gst_object_unref)
-#endif
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstValueArray, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 6d6e7c8..10e73e2 100644 (file)
  * Struct to store date, time and timezone information altogether.
  * #GstDateTime is refcounted and immutable.
  *
- * Date information is handled using the proleptic Gregorian calendar.
+ * Date information is handled using the [proleptic Gregorian calendar].
  *
  * Provides basic creation functions and accessor functions to its fields.
+ *
+ * [proleptic Gregorian calendar]: https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar
  */
 
 typedef enum
@@ -70,14 +72,12 @@ static void gst_date_time_free (GstDateTime * datetime);
 
 /**
  * gst_date_time_new_from_g_date_time:
- * @dt: (transfer full): the #GDateTime. The new #GstDateTime takes ownership.
+ * @dt: (transfer full) (nullable): the #GDateTime.
  *
  * Creates a new #GstDateTime from a #GDateTime object.
  *
- * Free-function: gst_date_time_unref
- *
  * Returns: (transfer full) (nullable): a newly created #GstDateTime,
- * or %NULL on error
+ * or %NULL if @dt is %NULL.
  */
 GstDateTime *
 gst_date_time_new_from_g_date_time (GDateTime * dt)
@@ -103,10 +103,9 @@ gst_date_time_new_from_g_date_time (GDateTime * dt)
  *
  * Creates a new #GDateTime from a fully defined #GstDateTime object.
  *
- * Free-function: g_date_time_unref
- *
  * Returns: (transfer full) (nullable): a newly created #GDateTime, or
- * %NULL on error
+ * %NULL on error or if @datetime does not have a year, month, day, hour,
+ * minute and second.
  */
 GDateTime *
 gst_date_time_to_g_date_time (GstDateTime * datetime)
@@ -195,7 +194,7 @@ gst_date_time_has_second (const GstDateTime * datetime)
  * gst_date_time_get_year:
  * @datetime: a #GstDateTime
  *
- * Returns the year of this #GstDateTime
+ * Returns the year of this #GstDateTime.
  * Call gst_date_time_has_year() before, to avoid warnings.
  *
  * Return value: The year of this #GstDateTime
@@ -213,15 +212,16 @@ gst_date_time_get_year (const GstDateTime * datetime)
  * @datetime: a #GstDateTime
  *
  * Returns the month of this #GstDateTime. January is 1, February is 2, etc..
- * Call gst_date_time_has_month() before, to avoid warnings.
  *
- * Return value: The month of this #GstDateTime
+ * Return value: The month of this #GstDateTime, or -1 if none is set.
  */
 gint
 gst_date_time_get_month (const GstDateTime * datetime)
 {
   g_return_val_if_fail (datetime != NULL, 0);
-  g_return_val_if_fail (gst_date_time_has_month (datetime), 0);
+
+  if (!gst_date_time_has_month (datetime))
+    return -1;
 
   return g_date_time_get_month (datetime->datetime);
 }
@@ -231,15 +231,16 @@ gst_date_time_get_month (const GstDateTime * datetime)
  * @datetime: a #GstDateTime
  *
  * Returns the day of the month of this #GstDateTime.
- * Call gst_date_time_has_day() before, to avoid warnings.
  *
- * Return value: The day of this #GstDateTime
+ * Return value: The day of this #GstDateTime, or -1 if none is set.
  */
 gint
 gst_date_time_get_day (const GstDateTime * datetime)
 {
   g_return_val_if_fail (datetime != NULL, 0);
-  g_return_val_if_fail (gst_date_time_has_day (datetime), 0);
+
+  if (!gst_date_time_has_day (datetime))
+    return -1;
 
   return g_date_time_get_day_of_month (datetime->datetime);
 }
@@ -250,15 +251,16 @@ gst_date_time_get_day (const GstDateTime * datetime)
  *
  * Retrieves the hour of the day represented by @datetime in the gregorian
  * calendar. The return is in the range of 0 to 23.
- * Call gst_date_time_has_time() before, to avoid warnings.
  *
- * Return value: the hour of the day
+ * Return value: the hour of the day, or -1 if none is set.
  */
 gint
 gst_date_time_get_hour (const GstDateTime * datetime)
 {
   g_return_val_if_fail (datetime != NULL, 0);
-  g_return_val_if_fail (gst_date_time_has_time (datetime), 0);
+
+  if (!gst_date_time_has_time (datetime))
+    return -1;
 
   return g_date_time_get_hour (datetime->datetime);
 }
@@ -269,15 +271,16 @@ gst_date_time_get_hour (const GstDateTime * datetime)
  *
  * Retrieves the minute of the hour represented by @datetime in the gregorian
  * calendar.
- * Call gst_date_time_has_time() before, to avoid warnings.
  *
- * Return value: the minute of the hour
+ * Return value: the minute of the hour, or -1 if none is set.
  */
 gint
 gst_date_time_get_minute (const GstDateTime * datetime)
 {
   g_return_val_if_fail (datetime != NULL, 0);
-  g_return_val_if_fail (gst_date_time_has_time (datetime), 0);
+
+  if (!gst_date_time_has_time (datetime))
+    return -1;
 
   return g_date_time_get_minute (datetime->datetime);
 }
@@ -288,15 +291,16 @@ gst_date_time_get_minute (const GstDateTime * datetime)
  *
  * Retrieves the second of the minute represented by @datetime in the gregorian
  * calendar.
- * Call gst_date_time_has_time() before, to avoid warnings.
  *
- * Return value: the second represented by @datetime
+ * Return value: the second represented by @datetime, or -1 if none is set.
  */
 gint
 gst_date_time_get_second (const GstDateTime * datetime)
 {
   g_return_val_if_fail (datetime != NULL, 0);
-  g_return_val_if_fail (gst_date_time_has_second (datetime), 0);
+
+  if (!gst_date_time_has_second (datetime))
+    return -1;
 
   return g_date_time_get_second (datetime->datetime);
 }
@@ -308,13 +312,15 @@ gst_date_time_get_second (const GstDateTime * datetime)
  * Retrieves the fractional part of the seconds in microseconds represented by
  * @datetime in the gregorian calendar.
  *
- * Return value: the microsecond of the second
+ * Return value: the microsecond of the second, or -1 if none is set.
  */
 gint
 gst_date_time_get_microsecond (const GstDateTime * datetime)
 {
   g_return_val_if_fail (datetime != NULL, 0);
-  g_return_val_if_fail (gst_date_time_has_second (datetime), 0);
+
+  if (!gst_date_time_has_second (datetime))
+    return -1;
 
   return g_date_time_get_microsecond (datetime->datetime);
 }
@@ -328,13 +334,15 @@ gst_date_time_get_microsecond (const GstDateTime * datetime)
  * values, timezones before (to the west) of UTC have negative values.
  * If @datetime represents UTC time, then the offset is zero.
  *
- * Return value: the offset from UTC in hours
+ * Return value: the offset from UTC in hours, or %G_MAXDOUBLE if none is set.
  */
 gfloat
 gst_date_time_get_time_zone_offset (const GstDateTime * datetime)
 {
   g_return_val_if_fail (datetime != NULL, 0.0);
-  g_return_val_if_fail (gst_date_time_has_time (datetime), 0.0);
+
+  if (!gst_date_time_has_time (datetime))
+    return G_MAXDOUBLE;
 
   return (g_date_time_get_utc_offset (datetime->datetime) /
       G_USEC_PER_SEC) / 3600.0;
@@ -349,9 +357,8 @@ gst_date_time_get_time_zone_offset (const GstDateTime * datetime)
  *
  * @year should be from 1 to 9999.
  *
- * Free-function: gst_date_time_unref
- *
- * Return value: (transfer full): the newly created #GstDateTime
+ * Return value: (transfer full) (nullable): the newly created #GstDateTime,
+ * or %NULL on error.
  */
 GstDateTime *
 gst_date_time_new_y (gint year)
@@ -372,9 +379,8 @@ gst_date_time_new_y (gint year)
  * If value is -1 then all over value will be ignored. For example
  * if @month == -1, then #GstDateTime will created only for @year.
  *
- * Free-function: gst_date_time_unref
- *
- * Return value: (transfer full): the newly created #GstDateTime
+ * Return value: (transfer full) (nullable): the newly created #GstDateTime,
+ * or %NULL on error.
  */
 GstDateTime *
 gst_date_time_new_ym (gint year, gint month)
@@ -399,9 +405,8 @@ gst_date_time_new_ym (gint year, gint month)
  * @day == -1, then #GstDateTime will created for @year and @month and
  * so on.
  *
- * Free-function: gst_date_time_unref
- *
- * Return value: (transfer full): the newly created #GstDateTime
+ * Return value: (transfer full) (nullable): the newly created #GstDateTime,
+ * or %NULL on error.
  */
 GstDateTime *
 gst_date_time_new_ymd (gint year, gint month, gint day)
@@ -416,9 +421,8 @@ gst_date_time_new_ymd (gint year, gint month, gint day)
  * Creates a new #GstDateTime using the time since Jan 1, 1970 specified by
  * @secs. The #GstDateTime is in the local timezone.
  *
- * Free-function: gst_date_time_unref
- *
- * Return value: (transfer full): the newly created #GstDateTime
+ * Return value: (transfer full) (nullable): the newly created #GstDateTime,
+ * or %NULL on error.
  */
 GstDateTime *
 gst_date_time_new_from_unix_epoch_local_time (gint64 secs)
@@ -426,6 +430,9 @@ gst_date_time_new_from_unix_epoch_local_time (gint64 secs)
   GDateTime *datetime;
 
   datetime = g_date_time_new_from_unix_local (secs);
+  if (!datetime)
+    return NULL;
+
   return gst_date_time_new_from_g_date_time (datetime);
 }
 
@@ -436,17 +443,79 @@ gst_date_time_new_from_unix_epoch_local_time (gint64 secs)
  * Creates a new #GstDateTime using the time since Jan 1, 1970 specified by
  * @secs. The #GstDateTime is in the UTC timezone.
  *
- * Free-function: gst_date_time_unref
- *
- * Return value: (transfer full): the newly created #GstDateTime
+ * Return value: (transfer full) (nullable): the newly created #GstDateTime,
+ * or %NULL on error.
  */
 GstDateTime *
 gst_date_time_new_from_unix_epoch_utc (gint64 secs)
 {
-  GstDateTime *datetime;
-  datetime =
-      gst_date_time_new_from_g_date_time (g_date_time_new_from_unix_utc (secs));
-  return datetime;
+  GDateTime *datetime;
+
+  datetime = g_date_time_new_from_unix_utc (secs);
+  if (!datetime)
+    return NULL;
+
+  return gst_date_time_new_from_g_date_time (datetime);
+}
+
+/**
+ * gst_date_time_new_from_unix_epoch_local_time_usecs:
+ * @usecs: microseconds from the Unix epoch
+ *
+ * Creates a new #GstDateTime using the time since Jan 1, 1970 specified by
+ * @usecs. The #GstDateTime is in the local timezone.
+ *
+ * Returns: (transfer full) (nullable): a newly created #GstDateTime, or %NULL
+ * on error.
+ *
+ * Since: 1.18
+ */
+GstDateTime *
+gst_date_time_new_from_unix_epoch_local_time_usecs (gint64 usecs)
+{
+  GDateTime *dt, *datetime;
+  gint64 secs = usecs / G_USEC_PER_SEC;
+  gint64 usec_part = usecs % G_USEC_PER_SEC;
+
+  dt = g_date_time_new_from_unix_local (secs);
+  if (!dt)
+    return NULL;
+  datetime = g_date_time_add_seconds (dt, (gdouble) usec_part / G_USEC_PER_SEC);
+  g_date_time_unref (dt);
+  if (!datetime)
+    return NULL;
+
+  return gst_date_time_new_from_g_date_time (datetime);
+}
+
+/**
+ * gst_date_time_new_from_unix_epoch_utc_usecs:
+ * @usecs: microseconds from the Unix epoch
+ *
+ * Creates a new #GstDateTime using the time since Jan 1, 1970 specified by
+ * @usecs. The #GstDateTime is in UTC.
+ *
+ * Returns: (transfer full) (nullable): a newly created #GstDateTime, or %NULL
+ * on error.
+ *
+ * Since: 1.18
+ */
+GstDateTime *
+gst_date_time_new_from_unix_epoch_utc_usecs (gint64 usecs)
+{
+  GDateTime *dt, *datetime;
+  gint64 secs = usecs / G_USEC_PER_SEC;
+  gint64 usec_part = usecs % G_USEC_PER_SEC;
+
+  dt = g_date_time_new_from_unix_utc (secs);
+  if (!dt)
+    return NULL;
+  datetime = g_date_time_add_seconds (dt, (gdouble) usec_part / G_USEC_PER_SEC);
+  g_date_time_unref (dt);
+  if (!datetime)
+    return NULL;
+
+  return gst_date_time_new_from_g_date_time (datetime);
 }
 
 static GstDateTimeFields
@@ -496,29 +565,45 @@ gst_date_time_check_fields (gint * year, gint * month, gint * day,
  * @month and @day, and the time fields will be considered not set. In this
  * case @minute and @seconds should also be -1.
  *
- * Free-function: gst_date_time_unref
- *
- * Return value: (transfer full): the newly created #GstDateTime
+ * Return value: (transfer full) (nullable): the newly created #GstDateTime,
+ * or %NULL on error.
  */
 GstDateTime *
 gst_date_time_new_local_time (gint year, gint month, gint day, gint hour,
     gint minute, gdouble seconds)
 {
   GstDateTimeFields fields;
+  GDateTime *dt;
   GstDateTime *datetime;
 
-  g_return_val_if_fail (year > 0 && year <= 9999, NULL);
-  g_return_val_if_fail ((month > 0 && month <= 12) || month == -1, NULL);
-  g_return_val_if_fail ((day > 0 && day <= 31) || day == -1, NULL);
-  g_return_val_if_fail ((hour >= 0 && hour < 24) || hour == -1, NULL);
-  g_return_val_if_fail ((minute >= 0 && minute < 60) || minute == -1, NULL);
-  g_return_val_if_fail ((seconds >= 0 && seconds < 60) || seconds == -1, NULL);
+  if (year <= 0 || year > 9999)
+    return NULL;
+
+  if ((month <= 0 || month > 12) && month != -1)
+    return NULL;
+
+  if ((day <= 0 || day > 31) && day != -1)
+    return NULL;
+
+  if ((hour < 0 || hour >= 24) && hour != -1)
+    return NULL;
+
+  if ((minute < 0 || minute >= 60) && minute != -1)
+    return NULL;
+
+  if ((seconds < 0 || seconds >= 60) && seconds != -1)
+    return NULL;
 
   fields = gst_date_time_check_fields (&year, &month, &day,
       &hour, &minute, &seconds);
 
-  datetime = gst_date_time_new_from_g_date_time (g_date_time_new_local (year,
-          month, day, hour, minute, seconds));
+  dt = g_date_time_new_local (year, month, day, hour, minute, seconds);
+  if (dt == NULL)
+    return NULL;
+
+  datetime = gst_date_time_new_from_g_date_time (dt);
+  if (datetime == NULL)
+    return NULL;
 
   datetime->fields = fields;
   return datetime;
@@ -529,15 +614,19 @@ gst_date_time_new_local_time (gint year, gint month, gint day, gint hour,
  *
  * Creates a new #GstDateTime representing the current date and time.
  *
- * Free-function: gst_date_time_unref
- *
- * Return value: (transfer full): the newly created #GstDateTime which should
- *     be freed with gst_date_time_unref().
+ * Return value: (transfer full) (nullable): the newly created #GstDateTime which should
+ *     be freed with gst_date_time_unref(), or %NULL on error.
  */
 GstDateTime *
 gst_date_time_new_now_local_time (void)
 {
-  return gst_date_time_new_from_g_date_time (g_date_time_new_now_local ());
+  GDateTime *dt;
+
+  dt = g_date_time_new_now_local ();
+  if (!dt)
+    return NULL;
+
+  return gst_date_time_new_from_g_date_time (dt);
 }
 
 /**
@@ -546,15 +635,19 @@ gst_date_time_new_now_local_time (void)
  * Creates a new #GstDateTime that represents the current instant at Universal
  * coordinated time.
  *
- * Free-function: gst_date_time_unref
- *
- * Return value: (transfer full): the newly created #GstDateTime which should
- *   be freed with gst_date_time_unref().
+ * Return value: (transfer full) (nullable): the newly created #GstDateTime which should
+ *   be freed with gst_date_time_unref(), or %NULL on error.
  */
 GstDateTime *
 gst_date_time_new_now_utc (void)
 {
-  return gst_date_time_new_from_g_date_time (g_date_time_new_now_utc ());
+  GDateTime *dt;
+
+  dt = g_date_time_new_now_utc ();
+  if (!dt)
+    return NULL;
+
+  return gst_date_time_new_from_g_date_time (dt);
 }
 
 gint
@@ -601,13 +694,12 @@ __gst_date_time_compare (const GstDateTime * dt1, const GstDateTime * dt2)
  * representing it in hours for most timezones.
  *
  * If value is -1 then all over value will be ignored. For example
- * if @month == -1, then #GstDateTime will created only for @year. If
- * @day == -1, then #GstDateTime will created for @year and @month and
+ * if @month == -1, then #GstDateTime will be created only for @year. If
+ * @day == -1, then #GstDateTime will be created for @year and @month and
  * so on.
  *
- * Free-function: gst_date_time_unref
- *
- * Return value: (transfer full): the newly created #GstDateTime
+ * Return value: (transfer full) (nullable): the newly created #GstDateTime,
+ * or %NULL on error.
  */
 GstDateTime *
 gst_date_time_new (gfloat tzoffset, gint year, gint month, gint day, gint hour,
@@ -620,15 +712,30 @@ gst_date_time_new (gfloat tzoffset, gint year, gint month, gint day, gint hour,
   GstDateTime *datetime;
   gint tzhour, tzminute;
 
-  g_return_val_if_fail (year > 0 && year <= 9999, NULL);
-  g_return_val_if_fail ((month > 0 && month <= 12) || month == -1, NULL);
-  g_return_val_if_fail ((day > 0 && day <= 31) || day == -1, NULL);
-  g_return_val_if_fail ((hour >= 0 && hour < 24) || hour == -1, NULL);
-  g_return_val_if_fail ((minute >= 0 && minute < 60) || minute == -1, NULL);
-  g_return_val_if_fail ((seconds >= 0 && seconds < 60) || seconds == -1, NULL);
-  g_return_val_if_fail (tzoffset >= -12.0 && tzoffset <= 12.0, NULL);
-  g_return_val_if_fail ((hour >= 0 && minute >= 0) ||
-      (hour == -1 && minute == -1 && seconds == -1 && tzoffset == 0.0), NULL);
+  if (year <= 0 || year > 9999)
+    return NULL;
+
+  if ((month <= 0 || month > 12) && month != -1)
+    return NULL;
+
+  if ((day <= 0 || day > 31) && day != -1)
+    return NULL;
+
+  if ((hour < 0 || hour >= 24) && hour != -1)
+    return NULL;
+
+  if ((minute < 0 || minute >= 60) && minute != -1)
+    return NULL;
+
+  if ((seconds < 0 || seconds >= 60) && seconds != -1)
+    return NULL;
+
+  if (tzoffset < -12.0 || tzoffset > 12.0)
+    return NULL;
+
+  if ((hour < 0 || minute < 0) &&
+      (hour != -1 || minute != -1 || seconds != -1 || tzoffset != 0.0))
+    return NULL;
 
   tzhour = (gint) ABS (tzoffset);
   tzminute = (gint) ((ABS (tzoffset) - tzhour) * 60);
@@ -636,7 +743,15 @@ gst_date_time_new (gfloat tzoffset, gint year, gint month, gint day, gint hour,
   g_snprintf (buf, 6, "%c%02d%02d", tzoffset >= 0 ? '+' : '-', tzhour,
       tzminute);
 
+#if GLIB_CHECK_VERSION (2, 67, 1)
+  /* g_time_zone_new() would always return UTC if the identifier can't be
+   * parsed, which is rather suboptimal. */
+  tz = g_time_zone_new_identifier (buf);
+  if (!tz)
+    return NULL;
+#else
   tz = g_time_zone_new (buf);
+#endif
 
   fields = gst_date_time_check_fields (&year, &month, &day,
       &hour, &minute, &seconds);
@@ -644,6 +759,9 @@ gst_date_time_new (gfloat tzoffset, gint year, gint month, gint day, gint hour,
   dt = g_date_time_new (tz, year, month, day, hour, minute, seconds);
   g_time_zone_unref (tz);
 
+  if (!dt)
+    return NULL;                /* date failed validation */
+
   datetime = gst_date_time_new_from_g_date_time (dt);
   datetime->fields = fields;
 
@@ -721,16 +839,15 @@ done:
 
 /**
  * gst_date_time_to_iso8601_string:
- * @datetime: GstDateTime.
+ * @datetime: a #GstDateTime.
  *
  * Create a minimal string compatible with ISO-8601. Possible output formats
- * are (for example): 2012, 2012-06, 2012-06-23, 2012-06-23T23:30Z,
- * 2012-06-23T23:30+0100, 2012-06-23T23:30:59Z, 2012-06-23T23:30:59+0100
+ * are (for example): `2012`, `2012-06`, `2012-06-23`, `2012-06-23T23:30Z`,
+ * `2012-06-23T23:30+0100`, `2012-06-23T23:30:59Z`, `2012-06-23T23:30:59+0100`
  *
  * Returns: (nullable): a newly allocated string formatted according
  *     to ISO 8601 and only including the datetime fields that are
- *     valid, or %NULL in case there was an error. The string should
- *     be freed with g_free().
+ *     valid, or %NULL in case there was an error.
  */
 gchar *
 gst_date_time_to_iso8601_string (GstDateTime * datetime)
@@ -749,15 +866,13 @@ gst_date_time_to_iso8601_string (GstDateTime * datetime)
  *
  * Tries to parse common variants of ISO-8601 datetime strings into a
  * #GstDateTime. Possible input formats are (for example):
- * 2012-06-30T22:46:43Z, 2012, 2012-06, 2012-06-30, 2012-06-30T22:46:43-0430,
- * 2012-06-30T22:46Z, 2012-06-30T22:46-0430, 2012-06-30 22:46,
- * 2012-06-30 22:46:43, 2012-06-00, 2012-00-00, 2012-00-30, 22:46:43Z, 22:46Z,
- * 22:46:43-0430, 22:46-0430, 22:46:30, 22:46
+ * `2012-06-30T22:46:43Z`, `2012`, `2012-06`, `2012-06-30`, `2012-06-30T22:46:43-0430`,
+ * `2012-06-30T22:46Z`, `2012-06-30T22:46-0430`, `2012-06-30 22:46`,
+ * `2012-06-30 22:46:43`, `2012-06-00`, `2012-00-00`, `2012-00-30`, `22:46:43Z`, `22:46Z`,
+ * `22:46:43-0430`, `22:46-0430`, `22:46:30`, `22:46`
  * If no date is provided, it is assumed to be "today" in the timezone
  * provided (if any), otherwise UTC.
  *
- * Free-function: gst_date_time_unref
- *
  * Returns: (transfer full) (nullable): a newly created #GstDateTime,
  * or %NULL on error
  */
@@ -808,7 +923,7 @@ gst_date_time_new_from_iso8601_string (const gchar * string)
       goto ymd;
 
     string += 10;
-    /* Exit if there is no expeceted value on this stage */
+    /* Exit if there is no expected value on this stage */
     if (!(*string == 'T' || *string == '-' || *string == ' '))
       goto ymd;
 
@@ -895,6 +1010,9 @@ ymd_hms:
 
     /* No date was supplied: make it today */
     now_utc = g_date_time_new_now_utc ();
+    if (!now_utc)
+      return NULL;
+
     if (tzoffset != 0.0) {
       /* If a timezone offset was supplied, get the date of that timezone */
       g_assert (gmt_offset_min != -99);
@@ -903,6 +1021,8 @@ ymd_hms:
           g_date_time_add_minutes (now_utc,
           (60 * gmt_offset_hour) + gmt_offset_min);
       g_date_time_unref (now_utc);
+      if (!now_in_given_tz)
+        return NULL;
     } else {
       now_in_given_tz = now_utc;
     }
index 61a32ec..8d2b747 100644 (file)
@@ -32,8 +32,8 @@ G_BEGIN_DECLS
  * GstDateTime:
  *
  * Opaque, immutable, refcounted struct that stores date, time and timezone
- * information. It currently supports ranges from 0001-01-01 to
- * 9999-12-31 in the Gregorian proleptic calendar.
+ * information. It currently supports ranges from `0001-01-01` to
+ * `9999-12-31` in the Gregorian proleptic calendar.
  *
  * Use the accessor functions to get the stored values.
  */
@@ -106,6 +106,12 @@ GST_API
 GstDateTime *   gst_date_time_new_from_unix_epoch_utc   (gint64 secs) G_GNUC_MALLOC;
 
 GST_API
+GstDateTime *   gst_date_time_new_from_unix_epoch_local_time_usecs (gint64 usecs) G_GNUC_MALLOC;
+
+GST_API
+GstDateTime *   gst_date_time_new_from_unix_epoch_utc_usecs (gint64 usecs) G_GNUC_MALLOC;
+
+GST_API
 GstDateTime *   gst_date_time_new_local_time            (gint year,
                                                          gint month,
                                                          gint day,
@@ -154,9 +160,7 @@ GstDateTime *   gst_date_time_ref                (GstDateTime * datetime);
 GST_API
 void            gst_date_time_unref              (GstDateTime * datetime);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstDateTime, gst_date_time_unref)
-#endif
 
 G_END_DECLS
 
index a13f548..8ca334a 100644 (file)
  *     caps (simple caps = one line)
  */
 
+/**
+ * SECTION: debugutils
+ * @title: Debugging utilities
+ * @short_description: A set of utilities for debugging and development
+ *
+ * These utility functions help with generating dot graphs which can
+ * be rendered with [graphviz] to multiple formats.
+ *
+ * [graphviz]: https://graphviz.org/
+ */
+
 #include "gst_private.h"
 #include "gstdebugutils.h"
 
@@ -118,7 +129,8 @@ debug_dump_get_object_params (GObject * object,
       /* skip some properties */
       if (!(property->flags & G_PARAM_READABLE))
         continue;
-      if (!strcmp (property->name, "name"))
+      if (!strcmp (property->name, "name")
+          || !strcmp (property->name, "parent"))
         continue;
 
       if (ignored_propnames)
@@ -230,8 +242,7 @@ debug_dump_pad (GstPad * pad, const gchar * color_name,
   GstPadPresence presence;
   gchar *pad_name, *param_name = NULL;
   const gchar *style_name;
-  static const char *const ignore_propnames[] =
-      { "parent", "direction", "template",
+  static const char *const ignore_propnames[] = { "direction", "template",
     "caps", NULL
   };
   const gchar *spc = MAKE_INDENT (indent);
@@ -614,6 +625,7 @@ debug_dump_element (GstBin * bin, GstDebugGraphDetails details,
   gchar *state_name = NULL;
   gchar *param_name = NULL;
   const gchar *spc = MAKE_INDENT (indent);
+  static const char *const ignore_propnames[] = { "stats", NULL };
 
   element_iter = gst_bin_iterate_elements (bin);
   elements_done = FALSE;
@@ -628,7 +640,7 @@ debug_dump_element (GstBin * bin, GstDebugGraphDetails details,
         }
         if (details & GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS) {
           param_name = debug_dump_get_object_params (G_OBJECT (element),
-              details, NULL);
+              details, ignore_propnames);
         }
         /* elements */
         g_string_append_printf (str, "%ssubgraph cluster_%s {\n", spc,
@@ -798,7 +810,7 @@ debug_dump_footer (GString * str)
  * @details: type of #GstDebugGraphDetails to use
  *
  * To aid debugging applications one can use this method to obtain the whole
- * network of gstreamer elements that form the pipeline into an dot file.
+ * network of gstreamer elements that form the pipeline into a dot file.
  * This data can be processed with graphviz to get an image.
  *
  * Returns: (transfer full): a string containing the pipeline in graphviz
@@ -827,11 +839,12 @@ gst_debug_bin_to_dot_data (GstBin * bin, GstDebugGraphDetails details)
  * @file_name: (type filename): output base filename (e.g. "myplayer")
  *
  * To aid debugging applications one can use this method to write out the whole
- * network of gstreamer elements that form the pipeline into an dot file.
+ * network of gstreamer elements that form the pipeline into a dot file.
  * This file can be processed with graphviz to get an image.
- * <informalexample><programlisting>
+ *
+ * ``` shell
  *  dot -Tpng -oimage.png graph_lowlevel.dot
- * </programlisting></informalexample>
+ * ```
  */
 void
 gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
index 3808fc6..6a2caa9 100644 (file)
@@ -80,17 +80,21 @@ void gst_debug_bin_to_dot_file_with_ts (GstBin *bin, GstDebugGraphDetails detail
  * @file_name: output base filename (e.g. "myplayer")
  *
  * To aid debugging applications one can use this method to write out the whole
- * network of gstreamer elements that form the pipeline into an dot file.
+ * network of gstreamer elements that form the pipeline into a dot file.
  * This file can be processed with graphviz to get an image, like this:
- * |[
- *  dot -Tpng -oimage.png graph_lowlevel.dot
- * ]|
- * There is also a utility called xdot which allows you to view the dot file
+ *
+ * ``` shell
+ * dot -Tpng -oimage.png graph_lowlevel.dot
+ * ```
+ *
+ * There is also a utility called [xdot] which allows you to view the dot file
  * directly without converting it first.
  *
- * The macro is only active if the environment variable GST_DEBUG_DUMP_DOT_DIR
- * is set to a basepath (e.g. /tmp), and the GStreamer debugging subsystem is
- * enabled (i.e., no use of `./configure --disable-gst-debug')
+ * The macro is only active if the environment variable `GST_DEBUG_DUMP_DOT_DIR`
+ * is set to a basepath (e.g. `/tmp`), and the GStreamer debugging subsystem is
+ * enabled (i.e., no use of `./configure --disable-gst-debug`)
+ *
+ * [xdot]: https://pypi.org/project/xdot/
  */
 #define GST_DEBUG_BIN_TO_DOT_FILE(bin, details, file_name) gst_debug_bin_to_dot_file (bin, details, file_name)
 
index 64f5ba5..8f31ffe 100644 (file)
@@ -212,11 +212,13 @@ gst_device_create_element (GstDevice * device, const gchar * name)
   if (klass->create_element)
     element = klass->create_element (device, name);
 
-  /* Ensure that the reference is floating. Bindings might have a hard time
-   * making sure that the reference is indeed still floating after returning
-   * here */
-  if (element)
-    g_object_force_floating ((GObject *) element);
+  if (element && !g_object_is_floating ((GObject *) element)) {
+    /* The reference we receive here should be floating, but we can't force
+     * it at our level. Simply raise a critical to make the issue obvious to bindings
+     * developers */
+    g_critical ("The created element should be floating, "
+        "this is probably caused by faulty bindings");
+  }
 
   return element;
 }
index 334c4fb..48c4cda 100644 (file)
@@ -113,9 +113,7 @@ gboolean        gst_device_has_classes        (GstDevice * device,
                                                const gchar * classes);
 
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstDevice, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 088eb4c..fae2f61 100644 (file)
@@ -98,6 +98,9 @@
 #include "gst_private.h"
 #include "gstdevicemonitor.h"
 
+GST_DEBUG_CATEGORY_STATIC (devicemonitor_debug);
+#define GST_CAT_DEFAULT devicemonitor_debug
+
 struct _GstDeviceMonitorPrivate
 {
   gboolean started;
@@ -187,6 +190,8 @@ gst_device_monitor_class_init (GstDeviceMonitorClass * klass)
   object_class->set_property = gst_device_monitor_set_property;
   object_class->dispose = gst_device_monitor_dispose;
 
+  GST_DEBUG_CATEGORY_INIT (devicemonitor_debug, "devicemonitor", 0,
+      "debugging info for the device monitor");
   g_object_class_install_property (object_class, PROP_SHOW_ALL,
       g_param_spec_boolean ("show-all", "Show All",
           "Show all devices, even those from hidden providers",
@@ -379,6 +384,13 @@ again:
   devices = NULL;
   hidden = NULL;
 
+  for (i = 0; i < monitor->priv->providers->len; i++) {
+    GstDeviceProvider *provider =
+        g_ptr_array_index (monitor->priv->providers, i);
+
+    update_hidden_providers_list (&hidden, provider);
+  }
+
   cookie = monitor->priv->cookie;
 
   for (i = 0; i < monitor->priv->providers->len; i++) {
@@ -393,7 +405,6 @@ again:
       tmpdev = gst_device_provider_get_devices (provider);
 
       GST_OBJECT_LOCK (monitor);
-      update_hidden_providers_list (&hidden, provider);
     } else {
       tmpdev = NULL;
     }
@@ -499,14 +510,13 @@ again:
   while (pending) {
     GstDeviceProvider *provider = pending->data;
 
-    if (gst_device_provider_can_monitor (provider)) {
-      GST_OBJECT_UNLOCK (monitor);
+    GST_OBJECT_UNLOCK (monitor);
 
-      if (!gst_device_provider_start (provider))
-        goto start_failed;
+    if (!gst_device_provider_start (provider))
+      goto start_failed;
+
+    GST_OBJECT_LOCK (monitor);
 
-      GST_OBJECT_LOCK (monitor);
-    }
     started = g_list_prepend (started, provider);
     pending = g_list_delete_link (pending, pending);
 
@@ -561,15 +571,15 @@ gst_device_monitor_stop (GstDeviceMonitor * monitor)
     GstDeviceProvider *provider =
         g_ptr_array_index (monitor->priv->providers, i);
 
-    started = g_list_prepend (started, gst_object_ref (provider));
+    if (gst_device_provider_is_started (provider))
+      started = g_list_prepend (started, gst_object_ref (provider));
   }
   GST_OBJECT_UNLOCK (monitor);
 
   while (started) {
     GstDeviceProvider *provider = started->data;
 
-    if (gst_device_provider_can_monitor (provider))
-      gst_device_provider_stop (provider);
+    gst_device_provider_stop (provider);
 
     started = g_list_delete_link (started, started);
     gst_object_unref (provider);
@@ -889,7 +899,7 @@ gst_device_monitor_set_show_all_devices (GstDeviceMonitor * monitor,
  * gst_device_monitor_get_show_all_devices:
  * @monitor: a #GstDeviceMonitor
  *
- * Get if @monitor is curretly showing all devices, even those from hidden
+ * Get if @monitor is currently showing all devices, even those from hidden
  * providers.
  *
  * Returns: %TRUE when all devices will be shown.
index 39e8cca..5817cd4 100644 (file)
@@ -111,9 +111,7 @@ void      gst_device_monitor_set_show_all_devices (GstDeviceMonitor * monitor, g
 GST_API
 gboolean  gst_device_monitor_get_show_all_devices (GstDeviceMonitor * monitor);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstDeviceMonitor, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index c3d794e..f073ede 100644 (file)
@@ -55,7 +55,7 @@ struct _GstDeviceProviderPrivate
 
   GMutex start_lock;
 
-  gboolean started_count;
+  gint started_count;
 
   GList *hidden_providers;
 };
@@ -84,7 +84,7 @@ static gint private_offset = 0;
 GType
 gst_device_provider_get_type (void)
 {
-  static volatile gsize gst_device_provider_type = 0;
+  static gsize gst_device_provider_type = 0;
 
   if (g_once_init_enter (&gst_device_provider_type)) {
     GType _type;
@@ -151,13 +151,11 @@ gst_device_provider_class_init (GstDeviceProviderClass * klass)
 
   gst_device_provider_signals[PROVIDER_HIDDEN] =
       g_signal_new ("provider-hidden", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_FIRST, 0, NULL,
-      NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_STRING);
+      G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING);
 
   gst_device_provider_signals[PROVIDER_UNHIDDEN] =
       g_signal_new ("provider-unhidden", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_FIRST, 0, NULL,
-      NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_STRING);
+      G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING);
 }
 
 static void
@@ -167,6 +165,8 @@ gst_device_provider_init (GstDeviceProvider * provider)
 
   g_mutex_init (&provider->priv->start_lock);
 
+  provider->priv->started_count = 0;
+
   provider->priv->bus = gst_bus_new ();
   gst_bus_set_flushing (provider->priv->bus, TRUE);
 }
@@ -391,6 +391,9 @@ gst_device_provider_get_metadata (GstDeviceProvider * provider,
  * Gets a list of devices that this provider understands. This may actually
  * probe the hardware if the provider is not currently started.
  *
+ * If the provider has been started, this will returned the same #GstDevice
+ * objedcts that have been returned by the #GST_MESSAGE_DEVICE_ADDED messages.
+ *
  * Returns: (transfer full) (element-type GstDevice): a #GList of
  *   #GstDevice
  *
@@ -416,9 +419,15 @@ gst_device_provider_get_devices (GstDeviceProvider * provider)
     for (item = provider->devices; item; item = item->next)
       devices = g_list_prepend (devices, gst_object_ref (item->data));
     GST_OBJECT_UNLOCK (provider);
-  } else if (klass->probe)
+  } else if (klass->probe) {
+
     devices = klass->probe (provider);
 
+    for (item = devices; item; item = item->next)
+      if (g_object_is_floating (item->data))
+        g_object_ref_sink (item->data);
+  }
+
   g_mutex_unlock (&provider->priv->start_lock);
 
   return devices;
@@ -437,6 +446,10 @@ gst_device_provider_get_devices (GstDeviceProvider * provider)
  * user of the object, gst_device_provider_stop() needs to be called the same
  * number of times.
  *
+ * After this function has been called, gst_device_provider_get_devices() will
+ * return the same objects that have been received from the
+ * #GST_MESSAGE_DEVICE_ADDED messages and will no longer probe.
+ *
  * Returns: %TRUE if the device providering could be started
  *
  * Since: 1.4
@@ -459,12 +472,34 @@ gst_device_provider_start (GstDeviceProvider * provider)
     goto started;
   }
 
-  if (klass->start)
+  gst_bus_set_flushing (provider->priv->bus, FALSE);
+
+  if (klass->start) {
     ret = klass->start (provider);
+  } else {
+    GList *devices = NULL, *item;
+
+    devices = klass->probe (provider);
+
+    for (item = devices; item; item = item->next) {
+      GstDevice *device = GST_DEVICE (item->data);
+      gboolean was_floating = g_object_is_floating (item->data);
+
+      gst_device_provider_device_add (provider, device);
+
+      if (!was_floating)
+        g_object_unref (item->data);
+    }
+
+    g_list_free (devices);
+
+    ret = TRUE;
+  }
 
   if (ret) {
     provider->priv->started_count++;
-    gst_bus_set_flushing (provider->priv->bus, FALSE);
+  } else if (provider->priv->started_count == 0) {
+    gst_bus_set_flushing (provider->priv->bus, TRUE);
   }
 
 started:
@@ -513,14 +548,13 @@ gst_device_provider_stop (GstDeviceProvider * provider)
   g_mutex_unlock (&provider->priv->start_lock);
 }
 
-
 /**
  * gst_device_provider_get_factory:
  * @provider: a #GstDeviceProvider to request the device provider factory of.
  *
  * Retrieves the factory that was used to create this device provider.
  *
- * Returns: (transfer none): the #GstDeviceProviderFactory used for
+ * Returns: (transfer none) (nullable): the #GstDeviceProviderFactory used for
  *     creating this device provider. no refcounting is needed.
  *
  * Since: 1.4
@@ -776,7 +810,7 @@ gst_device_provider_unhide_provider (GstDeviceProvider * provider,
 /**
  * gst_device_provider_device_changed:
  * @device: (transfer none): the new version of @changed_device
- * @changed_device: (transfer floating): the old version of the device that has been udpated
+ * @changed_device: (transfer floating): the old version of the device that has been updated
  *
  * This function is used when @changed_device was modified into its new form
  * @device. This will post a `DEVICE_CHANGED` message on the bus to let
@@ -822,3 +856,24 @@ gst_device_provider_device_changed (GstDeviceProvider * provider,
   gst_bus_post (provider->priv->bus, message);
   gst_object_unparent (GST_OBJECT (changed_device));
 }
+
+/**
+ * gst_device_provider_is_started:
+ * @provider: a #GstDeviceProvider
+ *
+ * This function can be used to know if the @provider was successfully started.
+ *
+ * Since: 1.20
+ */
+gboolean
+gst_device_provider_is_started (GstDeviceProvider * provider)
+{
+  gboolean started = FALSE;
+
+  g_return_val_if_fail (GST_IS_DEVICE_PROVIDER (provider), FALSE);
+
+  g_mutex_lock (&provider->priv->start_lock);
+  started = provider->priv->started_count > 0;
+  g_mutex_unlock (&provider->priv->start_lock);
+  return started;
+}
index bcde319..1d69a7d 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
-
-
 #ifndef __GST_DEVICE_PROVIDER_H__
 #define __GST_DEVICE_PROVIDER_H__
 
 #include <gst/gstelement.h>
 
+/**
+ * GST_DEVICE_PROVIDER_REGISTER_DEFINE_CUSTOM:
+ * @d_p: The device provider name in lower case, with words separated by '_'.
+ * Used to generate `gst_device_provider_register_*(GstPlugin* plugin)`.
+ * @register_func: pointer to a method with the format: `gboolean register_func (GstPlugin* plugin);`
+ *
+ * A convenience macro to define the entry point of a
+ * device provider `gst_device_provider_register_*(GstPlugin* plugin)` which uses
+ * register_func as the main registration method for the device provider.
+ * As an example, you may define the device provider named "device-provider"
+ * with the namespace `my` as following using `device_provider_register_custom`:
+ *
+ * ```
+ *
+ * gboolean my_device_provider_register_custom (GstPlugin * plugin)
+ * {
+ *    gboolean ret = FALSE;
+ *    ret |= gst_device_provider_register (plugin, "my-device-provider",
+         GST_RANK_PRIMARY, GST_TYPE_MY_DEVICE_PROVIDER);
+ *    return TRUE;
+ * }
+ *
+ * GST_DEVICE_PROVIDER_REGISTER_DEFINE_CUSTOM (my_device_provider, my_device_provider_register_custom)
+ * ```
+ *
+ * Since: 1.20
+ */
+#define GST_DEVICE_PROVIDER_REGISTER_DEFINE_CUSTOM(d_p, register_func) \
+G_BEGIN_DECLS \
+gboolean G_PASTE (gst_device_provider_register_, d_p) (GstPlugin * plugin) \
+{ \
+  return register_func (plugin); \
+} \
+G_END_DECLS
+
+/**
+ * GST_DEVICE_PROVIDER_REGISTER_DEFINE:
+ * @d_p: The device provider name in lower case, with words separated by '_'.
+ * Used to generate `gst_device_provider_register_*(GstPlugin* plugin)`.
+ * @d_p_n: The public name of the device provider
+ * @r: The #GstRank of the device provider (higher rank means more importance when autoplugging, see #GstRank)
+ * @t: The #GType of the device provider.
+ *
+ * A convenience macro to define the entry point of a
+ * device provider `gst_device_provider_register_*(GstPlugin* plugin)`.
+ *
+ * Since: 1.20
+ */
+#define GST_DEVICE_PROVIDER_REGISTER_DEFINE(d_p, d_p_n, r, t) \
+G_BEGIN_DECLS \
+gboolean G_PASTE (gst_device_provider_register_, d_p) (GstPlugin * plugin) \
+{ \
+  return gst_device_provider_register (plugin, d_p_n, r, t); \
+} \
+G_END_DECLS
+
+/**
+ * GST_DEVICE_PROVIDER_REGISTER_DECLARE:
+ * @d_p: The device provider name in lower case, with words separated by '_'.
+ *
+ * This macro can be used to declare a new device provider.
+ * It has to be used in combination with #GST_DEVICE_PROVIDER_REGISTER_DEFINE macro
+ * and must be placed outside any block to declare the device provider registration
+ * function.
+ *
+ * Since: 1.20
+ */
+#define GST_DEVICE_PROVIDER_REGISTER_DECLARE(d_p) \
+G_BEGIN_DECLS \
+gboolean G_PASTE(gst_device_provider_register_, d_p) (GstPlugin * plugin); \
+G_END_DECLS
+
+/**
+ * GST_DEVICE_PROVIDER_REGISTER:
+ * @d_p: The device provider name in lower case, with words separated by '_'.
+ * @plugin: The #GstPlugin where to register the device provider.
+ *
+ * This macro can be used to register a device provider into a #GstPlugin.
+ * This method will be usually called in the plugin init function
+ * but can also be called with a NULL plugin.
+ *
+ * Since: 1.20
+ */
+#define GST_DEVICE_PROVIDER_REGISTER(d_p, plugin) G_PASTE(gst_device_provider_register_, d_p) (plugin)
+
 G_BEGIN_DECLS
 
 typedef struct _GstDeviceProvider GstDeviceProvider;
@@ -71,7 +154,8 @@ struct _GstDeviceProvider {
  * @factory: a pointer to the #GstDeviceProviderFactory that creates this
  *  provider
  * @probe: Returns a list of devices that are currently available.
- *  This should never block.
+ *  This should never block. The devices should not have a parent and should
+ *  be floating.
  * @start: Starts monitoring for new devices. Only subclasses that can know
  *  that devices have been added or remove need to implement this method.
  * @stop: Stops monitoring for new devices. Only subclasses that implement
@@ -138,6 +222,9 @@ GST_API
 const gchar * gst_device_provider_get_metadata       (GstDeviceProvider * provider,
                                                       const gchar * key);
 
+GST_API
+gboolean    gst_device_provider_is_started     (GstDeviceProvider * provider);
+
 /* device provider class meta data */
 
 GST_API
@@ -172,9 +259,7 @@ void gst_device_provider_device_changed                    (GstDeviceProvider *
 GST_API
 GstDeviceProviderFactory * gst_device_provider_get_factory (GstDeviceProvider * provider);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstDeviceProvider, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 3fbaa3b..91e96ef 100644 (file)
@@ -292,7 +292,8 @@ gst_device_provider_factory_get (GstDeviceProviderFactory * factory)
    * an device provider at the same moment
    */
   oclass = GST_DEVICE_PROVIDER_GET_CLASS (device_provider);
-  if (!g_atomic_pointer_compare_and_exchange (&oclass->factory, NULL, factory)) {
+  if (!g_atomic_pointer_compare_and_exchange (&oclass->factory,
+          (GstDeviceProviderFactory *) NULL, factory)) {
     gst_object_unref (factory);
   } else {
     /* This ref will never be dropped as the class is never destroyed */
@@ -302,8 +303,8 @@ gst_device_provider_factory_get (GstDeviceProviderFactory * factory)
   gst_object_ref_sink (device_provider);
 
   /* We use an atomic to make sure we don't create two in parallel */
-  if (!g_atomic_pointer_compare_and_exchange (&newfactory->provider, NULL,
-          device_provider)) {
+  if (!g_atomic_pointer_compare_and_exchange (&newfactory->provider,
+          (GstDeviceProvider *) NULL, device_provider)) {
     gst_object_unref (device_provider);
 
     device_provider = g_atomic_pointer_get (&newfactory->provider);
index 41840b8..03f571d 100644 (file)
@@ -95,9 +95,7 @@ GST_API
 GList *       gst_device_provider_factory_list_get_device_providers (
                                                        GstRank minrank) G_GNUC_MALLOC;
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstDeviceProviderFactory, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index cb388a5..c9605f1 100644 (file)
@@ -141,6 +141,15 @@ gst_dynamic_type_factory_create (GstRegistry * registry,
   return factory;
 }
 
+/**
+ * gst_dynamic_type_register:
+ * @plugin: The #GstPlugin to register @dyn_type for
+ * @type: The #GType to register dynamically
+ *
+ * Registers a new #GstDynamicTypeFactory in the registry
+ *
+ * Since: 1.12
+ */
 gboolean
 gst_dynamic_type_register (GstPlugin * plugin, GType dyn_type)
 {
index 2778408..371dafb 100644 (file)
 #define __GST_DYNAMIC_TYPE_FACTORY_H__
 
 /**
+ * GST_DYNAMIC_TYPE_REGISTER_DEFINE:
+ * @t_n: The dynamic type name in lower case, with words separated by '_'.
+ * Used to generate `gst_dynamic_type_register_*(GstPlugin* plugin)`.
+ * @t: The #GType of the dynamic type
+
+ * A convenience macro to define the entry point of a
+ * dynamic type `gst_dynamic_type_register_*(GstPlugin* plugin)`.
+ *
+ * Since: 1.20
+ */
+#define GST_DYNAMIC_TYPE_REGISTER_DEFINE(t_n, t) \
+G_BEGIN_DECLS \
+gboolean G_PASTE (gst_dynamic_type_register_, t_n) (GstPlugin * plugin) \
+{ \
+  return gst_dynamic_type_register (plugin, t); \
+} \
+G_END_DECLS
+
+/**
+ * GST_DYNAMIC_TYPE_REGISTER_DECLARE:
+ * @t_f: The dynamic type name in lower case, with words separated by '_'.
+ *
+ * This macro can be used to declare a new dynamic type.
+ * It has to be used in combination with #GST_DYNAMIC_TYPE_REGISTER_DEFINE macro
+ * and must be placed outside any block to declare the type find registration
+ * function.
+ *
+ * Since: 1.20
+ */
+#define GST_DYNAMIC_TYPE_REGISTER_DECLARE(t_n) \
+G_BEGIN_DECLS \
+gboolean G_PASTE(gst_dynamic_type_register_, t_n) (GstPlugin * plugin); \
+G_END_DECLS
+
+/**
+ * GST_DYNAMIC_TYPE_REGISTER:
+ * @t_n: The dynamic type name to register
+ * @plugin: The #GstPlugin where to register the dynamic type.
+ *
+ * This macro can be used to register a dynamic type into a #GstPlugin.
+ * This method will be usually called in the plugin init function
+ * but can also be called with a NULL plugin.
+ *
+ * Since: 1.20
+ */
+#define GST_DYNAMIC_TYPE_REGISTER(t_n, plugin) G_PASTE(gst_dynamic_type_register_, t_n) (plugin)
+
+/**
  * GstDynamicTypeFactory:
  *
  * The opaque #GstDynamicTypeFactory data structure.
+ *
+ * Since: 1.12
  */
 typedef struct _GstDynamicTypeFactory GstDynamicTypeFactory;
 typedef struct _GstDynamicTypeFactoryClass GstDynamicTypeFactoryClass;
index 2b2c597..e3f8a94 100644 (file)
  * @title: GstElement
  * @short_description: Abstract base class for all pipeline elements
  * @see_also: #GstElementFactory, #GstPad
+ * @symbols:
+ * - GST_ELEMENT_METADATA_LONGNAME
+ * - GST_ELEMENT_METADATA_KLASS
+ * - GST_ELEMENT_METADATA_DESCRIPTION
+ * - GST_ELEMENT_METADATA_AUTHOR
+ * - GST_ELEMENT_METADATA_DOC_URI
+ * - GST_ELEMENT_METADATA_ICON_NAME
  *
  * GstElement is the abstract base class needed to construct an element that
  * can be used in a GStreamer pipeline. Please refer to the plugin writers
@@ -88,6 +95,7 @@
 #include "gstbus.h"
 #include "gsterror.h"
 #include "gstevent.h"
+#include "gstghostpad.h"
 #include "gstutils.h"
 #include "gstinfo.h"
 #include "gstquark.h"
@@ -144,7 +152,7 @@ static gboolean gst_element_default_query (GstElement * element,
     GstQuery * query);
 
 static GstPadTemplate
-    * gst_element_class_get_request_pad_template (GstElementClass *
+    * gst_element_class_request_pad_simple_template (GstElementClass *
     element_class, const gchar * name);
 
 static void gst_element_call_async_func (gpointer data, gpointer user_data);
@@ -152,6 +160,7 @@ static void gst_element_call_async_func (gpointer data, gpointer user_data);
 static GstObjectClass *parent_class = NULL;
 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
 
+static GMutex _element_pool_lock;
 static GThreadPool *gst_element_pool = NULL;
 
 /* this is used in gstelementfactory.c:gst_element_register() */
@@ -160,7 +169,7 @@ GQuark __gst_elementclass_factory = 0;
 GType
 gst_element_get_type (void)
 {
-  static volatile gsize gst_element_type = 0;
+  static gsize gst_element_type = 0;
 
   if (g_once_init_enter (&gst_element_type)) {
     GType _type;
@@ -187,19 +196,22 @@ gst_element_get_type (void)
   return gst_element_type;
 }
 
-static void
+static GThreadPool *
 gst_element_setup_thread_pool (void)
 {
   GError *err = NULL;
+  GThreadPool *pool;
 
   GST_DEBUG ("creating element thread pool");
-  gst_element_pool =
+  pool =
       g_thread_pool_new ((GFunc) gst_element_call_async_func, NULL, -1, FALSE,
       &err);
   if (err != NULL) {
     g_critical ("could not alloc threadpool %s", err->message);
     g_clear_error (&err);
   }
+
+  return pool;
 }
 
 static void
@@ -225,7 +237,7 @@ gst_element_class_init (GstElementClass * klass)
   gst_element_signals[PAD_ADDED] =
       g_signal_new ("pad-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstElementClass, pad_added), NULL, NULL,
-      g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD);
+      NULL, G_TYPE_NONE, 1, GST_TYPE_PAD);
   /**
    * GstElement::pad-removed:
    * @gstelement: the object which received the signal
@@ -236,7 +248,7 @@ gst_element_class_init (GstElementClass * klass)
   gst_element_signals[PAD_REMOVED] =
       g_signal_new ("pad-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
-      g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD);
+      NULL, G_TYPE_NONE, 1, GST_TYPE_PAD);
   /**
    * GstElement::no-more-pads:
    * @gstelement: the object which received the signal
@@ -248,7 +260,7 @@ gst_element_class_init (GstElementClass * klass)
   gst_element_signals[NO_MORE_PADS] =
       g_signal_new ("no-more-pads", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, no_more_pads), NULL,
-      NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 0);
+      NULL, NULL, G_TYPE_NONE, 0);
 
   gobject_class->dispose = gst_element_dispose;
   gobject_class->finalize = gst_element_finalize;
@@ -266,8 +278,6 @@ gst_element_class_init (GstElementClass * klass)
   klass->set_context = GST_DEBUG_FUNCPTR (gst_element_set_context_default);
 
   klass->elementfactory = NULL;
-
-  gst_element_setup_thread_pool ();
 }
 
 static void
@@ -478,6 +488,7 @@ gst_element_set_base_time (GstElement * element, GstClockTime time)
   GstClockTime old;
 
   g_return_if_fail (GST_IS_ELEMENT (element));
+  g_return_if_fail (GST_CLOCK_TIME_IS_VALID (time));
 
   GST_OBJECT_LOCK (element);
   old = element->base_time;
@@ -579,6 +590,80 @@ gst_element_get_start_time (GstElement * element)
   return result;
 }
 
+/**
+ * gst_element_get_current_running_time:
+ * @element: a #GstElement.
+ *
+ * Returns the running time of the element. The running time is the
+ * element's clock time minus its base time. Will return GST_CLOCK_TIME_NONE
+ * if the element has no clock, or if its base time has not been set.
+ *
+ * Returns: the running time of the element, or GST_CLOCK_TIME_NONE if the
+ * element has no clock or its base time has not been set.
+ *
+ * Since: 1.18
+ */
+GstClockTime
+gst_element_get_current_running_time (GstElement * element)
+{
+  GstClockTime base_time, clock_time;
+
+  g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_TIME_NONE);
+
+  base_time = gst_element_get_base_time (element);
+
+  if (!GST_CLOCK_TIME_IS_VALID (base_time)) {
+    GST_DEBUG_OBJECT (element, "Could not determine base time");
+    return GST_CLOCK_TIME_NONE;
+  }
+
+  clock_time = gst_element_get_current_clock_time (element);
+
+  if (!GST_CLOCK_TIME_IS_VALID (clock_time)) {
+    return GST_CLOCK_TIME_NONE;
+  }
+
+  if (clock_time < base_time) {
+    GST_DEBUG_OBJECT (element, "Got negative current running time");
+    return GST_CLOCK_TIME_NONE;
+  }
+
+  return clock_time - base_time;
+}
+
+/**
+ * gst_element_get_current_clock_time:
+ * @element: a #GstElement.
+ *
+ * Returns the current clock time of the element, as in, the time of the
+ * element's clock, or GST_CLOCK_TIME_NONE if there is no clock.
+ *
+ * Returns: the clock time of the element, or GST_CLOCK_TIME_NONE if there is
+ * no clock.
+ *
+ * Since: 1.18
+ */
+GstClockTime
+gst_element_get_current_clock_time (GstElement * element)
+{
+  GstClock *clock = NULL;
+  GstClockTime ret;
+
+  g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_TIME_NONE);
+
+  clock = gst_element_get_clock (element);
+
+  if (!clock) {
+    GST_DEBUG_OBJECT (element, "Element has no clock");
+    return GST_CLOCK_TIME_NONE;
+  }
+
+  ret = gst_clock_get_time (clock);
+  gst_object_unref (clock);
+
+  return ret;
+}
+
 #if 0
 /**
  * gst_element_set_index:
@@ -806,6 +891,16 @@ gst_element_remove_pad (GstElement * element, GstPad * pad)
     gst_object_unref (peer);
   }
 
+  /* if this is a ghost pad we also need to unset the target or it
+   * will stay linked although not allowed according to the topology.
+   *
+   * FIXME 2.0: Do this generically somehow from inside GstGhostPad
+   * when it gets unparented.
+   */
+  if (GST_IS_GHOST_PAD (pad)) {
+    gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL);
+  }
+
   GST_OBJECT_LOCK (element);
   /* remove it from the list */
   switch (gst_pad_get_direction (pad)) {
@@ -1078,11 +1173,34 @@ _gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
   return newpad;
 }
 
+#ifndef GST_REMOVE_DEPRECATED
 /**
  * gst_element_get_request_pad:
  * @element: a #GstElement to find a request pad of.
  * @name: the name of the request #GstPad to retrieve.
  *
+ * The name of this function is confusing to people learning GStreamer.
+ * gst_element_request_pad_simple() aims at making it more explicit it is
+ * a simplified gst_element_request_pad().
+ *
+ * Deprecated: 1.20: Prefer using gst_element_request_pad_simple() which
+ * provides the exact same functionality.
+ *
+ * Returns: (transfer full) (nullable): requested #GstPad if found,
+ *     otherwise %NULL.  Release after usage.
+ */
+GstPad *
+gst_element_get_request_pad (GstElement * element, const gchar * name)
+{
+  return gst_element_request_pad_simple (element, name);
+}
+#endif
+
+/**
+ * gst_element_request_pad_simple:
+ * @element: a #GstElement to find a request pad of.
+ * @name: the name of the request #GstPad to retrieve.
+ *
  * Retrieves a pad from the element by name (e.g. "src_\%d"). This version only
  * retrieves request pads. The pad should be released with
  * gst_element_release_request_pad().
@@ -1091,11 +1209,18 @@ _gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
  * gst_element_request_pad() if the pads should have a specific name (e.g.
  * @name is "src_1" instead of "src_\%u").
  *
+ * Note that this function was introduced in GStreamer 1.20 in order to provide
+ * a better name to gst_element_get_request_pad(). Prior to 1.20, users
+ * should use gst_element_get_request_pad() which provides the same
+ * functionality.
+ *
  * Returns: (transfer full) (nullable): requested #GstPad if found,
  *     otherwise %NULL.  Release after usage.
+ *
+ * Since: 1.20
  */
 GstPad *
-gst_element_get_request_pad (GstElement * element, const gchar * name)
+gst_element_request_pad_simple (GstElement * element, const gchar * name)
 {
   GstPadTemplate *templ = NULL;
   GstPad *pad;
@@ -1109,7 +1234,7 @@ gst_element_get_request_pad (GstElement * element, const gchar * name)
 
   class = GST_ELEMENT_GET_CLASS (element);
 
-  templ = gst_element_class_get_request_pad_template (class, name);
+  templ = gst_element_class_request_pad_simple_template (class, name);
   if (templ) {
     req_name = strstr (name, "%") ? NULL : name;
     templ_found = TRUE;
@@ -1722,7 +1847,7 @@ gst_element_get_pad_template (GstElement * element, const gchar * name)
 }
 
 static GstPadTemplate *
-gst_element_class_get_request_pad_template (GstElementClass *
+gst_element_class_request_pad_simple_template (GstElementClass *
     element_class, const gchar * name)
 {
   GstPadTemplate *tmpl;
@@ -3296,6 +3421,7 @@ gst_element_dispose (GObject * object)
   gst_object_replace ((GstObject **) clock_p, NULL);
   gst_object_replace ((GstObject **) bus_p, NULL);
   g_list_free_full (element->contexts, (GDestroyNotify) gst_context_unref);
+  element->contexts = NULL;
   GST_OBJECT_UNLOCK (element);
 
   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "%p parent class dispose",
@@ -3542,7 +3668,7 @@ gst_element_get_context_unlocked (GstElement * element,
  *
  * MT safe.
  *
- * Returns: (transfer full): A #GstContext or NULL
+ * Returns: (transfer full) (nullable): A #GstContext or NULL
  *
  * Since: 1.8
  */
@@ -3733,18 +3859,34 @@ gst_element_call_async (GstElement * element, GstElementCallAsyncFunc func,
   async_data->user_data = user_data;
   async_data->destroy_notify = destroy_notify;
 
-  g_thread_pool_push (gst_element_pool, async_data, NULL);
+  g_mutex_lock (&_element_pool_lock);
+  if (G_UNLIKELY (gst_element_pool == NULL))
+    gst_element_pool = gst_element_setup_thread_pool ();
+  g_thread_pool_push ((GThreadPool *) gst_element_pool, async_data, NULL);
+  g_mutex_unlock (&_element_pool_lock);
 }
 
 void
 _priv_gst_element_cleanup (void)
 {
+  g_mutex_lock (&_element_pool_lock);
   if (gst_element_pool) {
-    g_thread_pool_free (gst_element_pool, FALSE, TRUE);
-    gst_element_setup_thread_pool ();
+    g_thread_pool_free ((GThreadPool *) gst_element_pool, FALSE, TRUE);
+    gst_element_pool = NULL;
   }
+  g_mutex_unlock (&_element_pool_lock);
 }
 
+/**
+ * gst_make_element_message_details:
+ * @name: Name of the first field to set
+ * @...: variable arguments in the same form as #GstStructure
+ *
+ * Create a #GstStructure to be used with #gst_element_message_full_with_details.
+ * %NULL terminator required.
+ *
+ * Since: 1.10
+ */
 GstStructure *
 gst_make_element_message_details (const char *name, ...)
 {
index 4ebfd09..e690bf0 100644 (file)
 
 G_BEGIN_DECLS
 
+/**
+ * _GST_ELEMENT_REGISTER_DEFINE_BEGIN: (attributes doc.skip=true)
+ */
+#define _GST_ELEMENT_REGISTER_DEFINE_BEGIN(element) \
+G_BEGIN_DECLS \
+gboolean G_PASTE (gst_element_register_, element) (GstPlugin * plugin) \
+{ \
+  {
+
+/**
+ * _GST_ELEMENT_REGISTER_DEFINE_END: (attributes doc.skip=true)
+ */
+#define _GST_ELEMENT_REGISTER_DEFINE_END(element_name, rank, type) \
+  } \
+  return gst_element_register (plugin, element_name, rank, type); \
+} \
+G_END_DECLS
+
+/**
+ * GST_ELEMENT_REGISTER_DEFINE_CUSTOM:
+ * @element: The element name in lower case, with words separated by '_'.
+ * Used to generate `gst_element_register_*(GstPlugin* plugin)`.
+ * @register_func: pointer to a method with the format: `gboolean register_func (GstPlugin* plugin);`
+ *
+ * A convenience macro to define the entry point of an
+ * element `gst_element_register_*(GstPlugin* plugin)` which uses
+ * register_func as the main registration method for the element.
+ * As an example, you may define the element named "streamer-filter"
+ * with the namespace `my` as following using `element_register_custom`:
+ *
+ * ```
+ * GST_ELEMENT_REGISTER_DEFINE_CUSTOM (my_element, element_register_custom)
+ * ```
+ *
+ * Since: 1.20
+ */
+#define GST_ELEMENT_REGISTER_DEFINE_CUSTOM(element, register_func) \
+G_BEGIN_DECLS \
+gboolean G_PASTE (gst_element_register_, element) (GstPlugin * plugin) \
+{ \
+  return register_func (plugin); \
+} \
+G_END_DECLS
+
+/**
+ * GST_ELEMENT_REGISTER_DEFINE:
+ * @e: The element name in lower case, with words separated by '_'.
+ * Used to generate `gst_element_register_*(GstPlugin* plugin)`.
+ * @e_n: The public name of the element
+ * @r: The #GstRank of the element (higher rank means more importance when autoplugging, see #GstRank)
+ * @t: The #GType of the element.
+ *
+ * A convenience macro to define the entry point of an
+ * element `gst_element_register_*(GstPlugin* plugin)`.
+ * As an example, you may define the element named "streamer-filter"
+ * with the namespace `my` as following:
+ *
+ * ```
+ * GST_ELEMENT_REGISTER_REGISTER_DEFINE (stream_filter, "stream-filter", GST_RANK_PRIMARY, MY_TYPE_STREAM_FILTER)
+ * ```
+ *
+ * Since: 1.20
+ */
+#define GST_ELEMENT_REGISTER_DEFINE(e, e_n, r, t) _GST_ELEMENT_REGISTER_DEFINE_BEGIN(e) _GST_ELEMENT_REGISTER_DEFINE_END(e_n, r, t)
+
+/**
+ * GST_ELEMENT_REGISTER_DEFINE_WITH_CODE:
+ * @e: The element name in lower case, with words separated by '_'.
+ * Used to generate `gst_element_register_*(GstPlugin* plugin)`.
+ * @e_n: The public name of the element
+ * @r: The #GstRank of the element (higher rank means more importance when autoplugging, see #GstRank)
+ * @t: The #GType of the element.
+ * @_c_: Custom code that gets inserted in the gst_element_register_*() function.
+ *
+ * A convenience macro to define the entry point of an
+ * element `gst_element_register_*(GstPlugin* plugin)` executing code
+ * before gst_element_register in `gst_element_register_*(GstPlugin* plugin)`.
+
+ * As an example, you may define the element named "stream-filter"
+ * with the namespace `my` as following:
+ *
+ * ```
+ * #define _pre_register_init \
+ *   my_stream_filter_pre_register (plugin);
+ * GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (stream_filter, "stream-filter", GST_RANK_PRIMARY, MY_TYPE_STREAM_FILTER, _pre_register_init)
+ * ```
+ *
+ * Since: 1.20
+ */
+#define GST_ELEMENT_REGISTER_DEFINE_WITH_CODE(e, e_n, r, t, _c_) _GST_ELEMENT_REGISTER_DEFINE_BEGIN(e) {_c_;} _GST_ELEMENT_REGISTER_DEFINE_END(e_n, r, t)
+
+/**
+ * GST_ELEMENT_REGISTER_DECLARE:
+ * @element: The element name in lower case, with words separated by '_'.
+ *
+ * This macro can be used to declare a new element.
+ * It has to be used in combination with #GST_ELEMENT_REGISTER_DEFINE macros
+ * and must be placed outside any block to declare the element registration
+ * function.
+ * As an example, you may declare the element named "stream-filter"
+ * with the namespace `my` as following:
+ *
+ * ```
+ * GST_ELEMENT_REGISTER_DECLARE (stream_filter)
+ * ```
+ *
+ * Since: 1.20
+ */
+#define GST_ELEMENT_REGISTER_DECLARE(element) \
+G_BEGIN_DECLS \
+gboolean G_PASTE(gst_element_register_, element) (GstPlugin * plugin); \
+G_END_DECLS
+
+/**
+ * GST_ELEMENT_REGISTER:
+ * @element: The element name in lower case, with words separated by '_'.
+ * @plugin: The #GstPlugin where to register the element.
+ *
+ * This macro can be used to register an element into a #GstPlugin.
+ * This method will be usually called in the plugin init function
+ * but can also be called with a NULL plugin,
+ * for example with a static registration of the element.
+ * It has to be used in combination with #GST_ELEMENT_REGISTER_DECLARE.
+ *
+ * ```
+ * GstPlugin* plugin;
+ *
+ * ...
+ *
+ * GST_ELEMENT_REGISTER (stream_filter, plugin);
+ * ```
+ *
+ * Since: 1.20
+ */
+#define GST_ELEMENT_REGISTER(element, plugin) G_PASTE(gst_element_register_, element) (plugin)
+
 /* gstelement.h and gstelementfactory.h include each other */
 typedef struct _GstElement GstElement;
 typedef struct _GstElementClass GstElementClass;
@@ -348,7 +484,7 @@ typedef enum
 #define GST_ELEMENT_START_TIME(elem)            (GST_ELEMENT_CAST(elem)->start_time)
 
 GST_API
-GstStructure *gst_make_element_message_details (const char *name, ...);
+GstStructure *gst_make_element_message_details (const char *name, ...) G_GNUC_NULL_TERMINATED;
 
 #define GST_ELEMENT_MESSAGE_MAKE_DETAILS(args) gst_make_element_message_details args
 
@@ -373,8 +509,8 @@ G_STMT_START {                                                          \
 /**
  * GST_ELEMENT_ERROR_WITH_DETAILS:
  * @el:     the element that generates the error
- * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see #gstreamer-GstGError)
- * @code:   error code defined for that domain (see #gstreamer-GstGError)
+ * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see [GstGError](gsterror))
+ * @code:   error code defined for that domain (see [GstGError](gsterror))
  * @text:   the message to display (format string and args enclosed in
             parentheses)
  * @debug:  debugging information for the message (format string and args
@@ -406,8 +542,8 @@ G_STMT_START {                                                          \
 /**
  * GST_ELEMENT_ERROR:
  * @el:     the element that generates the error
- * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see #gstreamer-GstGError)
- * @code:   error code defined for that domain (see #gstreamer-GstGError)
+ * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see [GstGError](gsterror))
+ * @code:   error code defined for that domain (see [GstGError](gsterror))
  * @text:   the message to display (format string and args enclosed in
             parentheses)
  * @debug:  debugging information for the message (format string and args
@@ -434,8 +570,8 @@ G_STMT_START {                                                          \
 /**
  * GST_ELEMENT_WARNING_WITH_DETAILS:
  * @el:     the element that generates the warning
- * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see #gstreamer-GstGError)
- * @code:   error code defined for that domain (see #gstreamer-GstGError)
+ * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see [GstGError](gsterror))
+ * @code:   error code defined for that domain (see [GstGError](gsterror))
  * @text:   the message to display (format string and args enclosed in
             parentheses)
  * @debug:  debugging information for the message (format string and args
@@ -467,8 +603,8 @@ G_STMT_START {                                                          \
 /**
  * GST_ELEMENT_WARNING:
  * @el:     the element that generates the warning
- * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see #gstreamer-GstGError)
- * @code:   error code defined for that domain (see #gstreamer-GstGError)
+ * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see [GstGError](gsterror))
+ * @code:   error code defined for that domain (see [GstGError](gsterror))
  * @text:   the message to display (format string and args enclosed in
             parentheses)
  * @debug:  debugging information for the message (format string and args
@@ -495,8 +631,8 @@ G_STMT_START {                                                          \
 /**
  * GST_ELEMENT_INFO_WITH_DETAILS:
  * @el:     the element that generates the information
- * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see #gstreamer-GstGError)
- * @code:   error code defined for that domain (see #gstreamer-GstGError)
+ * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see [GstGError](gsterror))
+ * @code:   error code defined for that domain (see [GstGError](gsterror))
  * @text:   the message to display (format string and args enclosed in
             parentheses)
  * @debug:  debugging information for the message (format string and args
@@ -531,8 +667,8 @@ G_STMT_START {                                                          \
 /**
  * GST_ELEMENT_INFO:
  * @el:     the element that generates the information
- * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see #gstreamer-GstGError)
- * @code:   error code defined for that domain (see #gstreamer-GstGError)
+ * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see [GstGError](gsterror))
+ * @code:   error code defined for that domain (see [GstGError](gsterror))
  * @text:   the message to display (format string and args enclosed in
             parentheses)
  * @debug:  debugging information for the message (format string and args
@@ -860,6 +996,12 @@ void                    gst_element_set_start_time      (GstElement *element, Gs
 GST_API
 GstClockTime            gst_element_get_start_time      (GstElement *element);
 
+GST_API
+GstClockTime            gst_element_get_current_running_time (GstElement *element);
+
+GST_API
+GstClockTime            gst_element_get_current_clock_time (GstElement *element);
+
 /* bus */
 
 GST_API
@@ -896,10 +1038,13 @@ void                    gst_element_no_more_pads        (GstElement *element);
 GST_API
 GstPad*                 gst_element_get_static_pad      (GstElement *element, const gchar *name);
 
-GST_API
+GST_API G_DEPRECATED_FOR(gst_element_request_pad_simple)
 GstPad*                 gst_element_get_request_pad     (GstElement *element, const gchar *name);
 
 GST_API
+GstPad*                 gst_element_request_pad_simple  (GstElement *element, const gchar *name);
+
+GST_API
 GstPad*                 gst_element_request_pad         (GstElement *element, GstPadTemplate *templ,
                                                         const gchar * name, const GstCaps *caps);
 GST_API
@@ -1016,6 +1161,13 @@ GST_API
 void                    gst_element_lost_state          (GstElement * element);
 
 
+/**
+ * GstElementCallAsyncFunc:
+ * @element: The #GstElement this function has been called against
+ * @user_data: Data passed in the function where that callback has been passed
+ *
+ * Callback prototype used in #gst_element_call_async
+ */
 typedef void          (*GstElementCallAsyncFunc)        (GstElement * element,
                                                          gpointer     user_data);
 GST_API
@@ -1050,9 +1202,7 @@ GList*                  gst_element_get_pad_template_list      (GstElement *elem
 GST_API
 const gchar *           gst_element_get_metadata               (GstElement * element, const gchar * key);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstElement, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 2d5dd42..70a183c 100644 (file)
@@ -65,6 +65,8 @@
 
 #include "glib-compat-private.h"
 
+#include <gobject/gvaluecollector.h>
+
 GST_DEBUG_CATEGORY_STATIC (element_factory_debug);
 #define GST_CAT_DEFAULT element_factory_debug
 
@@ -224,7 +226,7 @@ gst_element_register (GstPlugin * plugin, const gchar * name, guint rank,
    * features are removed and readded.
    */
   existing_feature = gst_registry_lookup_feature (registry, name);
-  if (existing_feature) {
+  if (existing_feature && existing_feature->plugin == plugin) {
     GST_DEBUG_OBJECT (registry, "update existing feature %p (%s)",
         existing_feature, name);
     factory = GST_ELEMENT_FACTORY_CAST (existing_feature);
@@ -233,6 +235,8 @@ gst_element_register (GstPlugin * plugin, const gchar * name, guint rank,
     g_type_set_qdata (type, __gst_elementclass_factory, factory);
     gst_object_unref (existing_feature);
     return TRUE;
+  } else if (existing_feature) {
+    gst_object_unref (existing_feature);
   }
 
   factory = g_object_new (GST_TYPE_ELEMENT_FACTORY, NULL);
@@ -328,21 +332,94 @@ detailserror:
   }
 }
 
+static gboolean
+gst_element_factory_property_valist_to_array (const gchar * first,
+    va_list properties, GType object_type, guint * n, const gchar ** names[],
+    GValue ** values)
+{
+  GObjectClass *class;
+  const gchar *name;
+  guint n_params = 0;
+  guint n_params_alloc = 16;
+  GValue *values_array;
+  const gchar **names_array;
+
+  if (!first)
+    return FALSE;
+
+  g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), FALSE);
+
+  class = g_type_class_ref (object_type);
+  if (!class)
+    return FALSE;
+
+  name = first;
+  names_array = g_new0 (const gchar *, n_params_alloc);
+  values_array = g_new0 (GValue, n_params_alloc);
+
+  do {
+    gchar *error = NULL;
+    GParamSpec *pspec;
+
+    pspec = g_object_class_find_property (class, name);
+    if (!pspec)
+      goto cleanup;
+
+    if (G_UNLIKELY (n_params == n_params_alloc)) {
+      n_params_alloc *= 2u;
+      names_array =
+          g_realloc (names_array, sizeof (const gchar *) * n_params_alloc);
+      values_array = g_realloc (values_array, sizeof (GValue) * n_params_alloc);
+      memset (&values_array[n_params], 0,
+          sizeof (GValue) * (n_params_alloc - n_params));
+    }
+
+    names_array[n_params] = name;
+
+    G_VALUE_COLLECT_INIT (&values_array[n_params], pspec->value_type,
+        properties, 0, &error);
+
+    if (error) {
+      g_critical ("%s", error);
+      g_free (error);
+      goto cleanup;
+    }
+
+    ++n_params;
+    name = va_arg (properties, const gchar *);
+  } while (name);
+
+  *n = n_params;
+  *names = names_array;
+  *values = values_array;
+  g_type_class_unref (class);
+  return TRUE;
+
+cleanup:
+  g_free (names_array);
+  g_free (values_array);
+  g_type_class_unref (class);
+  return FALSE;
+}
+
 /**
- * gst_element_factory_create:
+ * gst_element_factory_create_with_properties:
  * @factory: factory to instantiate
- * @name: (allow-none): name of new element, or %NULL to automatically create
- *    a unique name
+ * @n: count of properties
+ * @names: (nullable): array of properties names
+ * @values: (nullable): array of associated properties values
  *
  * Create a new element of the type defined by the given elementfactory.
- * It will be given the name supplied, since all elements require a name as
- * their first argument.
+ * The supplied list of properties, will be passed at object construction.
  *
  * Returns: (transfer floating) (nullable): new #GstElement or %NULL
  *     if the element couldn't be created
+ *
+ * Since: 1.20
  */
 GstElement *
-gst_element_factory_create (GstElementFactory * factory, const gchar * name)
+gst_element_factory_create_with_properties (GstElementFactory * factory,
+    guint n, const gchar * names[], const GValue values[])
 {
   GstElement *element;
   GstElementClass *oclass;
@@ -359,22 +436,14 @@ gst_element_factory_create (GstElementFactory * factory, const gchar * name)
 
   factory = newfactory;
 
-  if (name)
-    GST_INFO ("creating element \"%s\" named \"%s\"",
-        GST_OBJECT_NAME (factory), GST_STR_NULL (name));
-  else
-    GST_INFO ("creating element \"%s\"", GST_OBJECT_NAME (factory));
+  GST_INFO ("creating element \"%s\"", GST_OBJECT_NAME (factory));
 
   if (factory->type == 0)
     goto no_type;
 
-  /* create an instance of the element, cast so we don't assert on NULL
-   * also set name as early as we can
-   */
-  if (name)
-    element = g_object_new (factory->type, "name", name, NULL);
-  else
-    element = g_object_new (factory->type, NULL);
+  element = (GstElement *) g_object_new_with_properties (factory->type, n,
+      names, values);
+
   if (G_UNLIKELY (element == NULL))
     goto no_element;
 
@@ -384,18 +453,21 @@ 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,
-          factory))
+  if (!g_atomic_pointer_compare_and_exchange (&oclass->elementfactory,
+          (GstElementFactory *) NULL, factory))
     gst_object_unref (factory);
   else
     /* This ref will never be dropped as the class is never destroyed */
     GST_OBJECT_FLAG_SET (factory, GST_OBJECT_FLAG_MAY_BE_LEAKED);
 
-  /* Ensure that the reference is floating. Bindings might have a hard time
-   * making sure that the reference is indeed still floating after returning
-   * here */
-  if (element)
-    g_object_force_floating ((GObject *) element);
+  if (!g_object_is_floating ((GObject *) element)) {
+    /* The reference we receive here should be floating, but we can't force
+     * it at our level. Simply raise a critical to make the issue obvious to bindings
+     * users / developers */
+    g_critical ("The created element should be floating, "
+        "this is probably caused by faulty bindings");
+  }
+
 
   GST_DEBUG ("created element \"%s\"", GST_OBJECT_NAME (factory));
 
@@ -404,8 +476,7 @@ gst_element_factory_create (GstElementFactory * factory, const gchar * name)
   /* ERRORS */
 load_failed:
   {
-    GST_WARNING_OBJECT (factory,
-        "loading plugin containing feature %s returned NULL!", name);
+    GST_WARNING_OBJECT (factory, "loading plugin returned NULL!");
     return NULL;
   }
 no_type:
@@ -423,21 +494,188 @@ no_element:
 }
 
 /**
- * gst_element_factory_make:
- * @factoryname: a named factory to instantiate
- * @name: (allow-none): name of new element, or %NULL to automatically create
+ * gst_element_factory_create_valist:
+ * @factory: factory to instantiate
+ * @first: (nullable): name of the first property
+ * @properties: (nullable): list of properties
+ *
+ * Create a new element of the type defined by the given elementfactory.
+ * The supplied list of properties, will be passed at object construction.
+ *
+ * Returns: (transfer floating) (nullable): new #GstElement or %NULL
+ *     if the element couldn't be created
+ *
+ * Since: 1.20
+ */
+GstElement *
+gst_element_factory_create_valist (GstElementFactory * factory,
+    const gchar * first, va_list properties)
+{
+  GstElementFactory *newfactory;
+  GstElement *element;
+  const gchar **names = NULL;
+  GValue *values = NULL;
+  guint n = 0;
+
+  g_return_val_if_fail (factory != NULL, NULL);
+
+  newfactory =
+      GST_ELEMENT_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE
+          (factory)));
+
+  g_return_val_if_fail (newfactory != NULL, NULL);
+  g_return_val_if_fail (newfactory->type != 0, NULL);
+
+  factory = newfactory;
+
+  if (!first) {
+    element =
+        gst_element_factory_create_with_properties (factory, 0, NULL, NULL);
+    goto out;
+  }
+
+  if (!gst_element_factory_property_valist_to_array (first, properties,
+          factory->type, &n, &names, &values)) {
+    GST_ERROR_OBJECT (factory, "property parsing failed");
+    element = NULL;
+    goto out;
+  }
+
+  element = gst_element_factory_create_with_properties (factory, n, names,
+      values);
+
+  g_free (names);
+  while (n--)
+    g_value_unset (&values[n]);
+  g_free (values);
+
+out:
+  gst_object_unref (factory);
+  return element;
+}
+
+/**
+ * gst_element_factory_create_full:
+ * @factory: factory to instantiate
+ * @first: (nullable): name of the first property
+ * @...: (nullable): %NULL terminated list of properties
+ *
+ * Create a new element of the type defined by the given elementfactory.
+ * The supplied list of properties, will be passed at object construction.
+ *
+ * Returns: (transfer floating) (nullable): new #GstElement or %NULL
+ *     if the element couldn't be created
+ *
+ * Since: 1.20
+ */
+GstElement *
+gst_element_factory_create_full (GstElementFactory * factory,
+    const gchar * first, ...)
+{
+  GstElement *element;
+  va_list properties;
+
+  va_start (properties, first);
+  element = gst_element_factory_create_valist (factory, first, properties);
+  va_end (properties);
+
+  return element;
+}
+
+/**
+ * gst_element_factory_create:
+ * @factory: factory to instantiate
+ * @name: (nullable): name of new element, or %NULL to automatically create
  *    a unique name
  *
+ * Create a new element of the type defined by the given elementfactory.
+ * It will be given the name supplied, since all elements require a name as
+ * their first argument.
+ *
+ * Returns: (transfer floating) (nullable): new #GstElement or %NULL
+ *     if the element couldn't be created
+ */
+GstElement *
+gst_element_factory_create (GstElementFactory * factory, const gchar * name)
+{
+  if (name)
+    return gst_element_factory_create_full (factory, "name", name, NULL);
+  else
+    return gst_element_factory_create_with_properties (factory, 0, NULL, NULL);
+}
+
+/**
+ * gst_element_factory_make_with_properties:
+ * @factoryname: a named factory to instantiate
+ * @n: count of properties
+ * @names: (nullable): array of properties names
+ * @values: (nullable): array of associated properties values
+ *
+ * Create a new element of the type defined by the given elementfactory.
+ * The supplied list of properties, will be passed at object construction.
+ *
+ * Returns: (transfer floating) (nullable): new #GstElement or %NULL
+ *     if the element couldn't be created
+ *
+ * Since: 1.20
+ */
+GstElement *
+gst_element_factory_make_with_properties (const gchar * factoryname,
+    guint n, const gchar * names[], const GValue values[])
+{
+  GstElementFactory *factory;
+  GstElement *element;
+
+  g_return_val_if_fail (factoryname != NULL, NULL);
+  g_return_val_if_fail (gst_is_initialized (), NULL);
+
+  GST_LOG ("gstelementfactory: make \"%s\"", factoryname);
+
+  factory = gst_element_factory_find (factoryname);
+  if (factory == NULL)
+    goto no_factory;
+
+  GST_LOG_OBJECT (factory, "found factory %p", factory);
+  element = gst_element_factory_create_with_properties (factory, n, names,
+      values);
+  if (element == NULL)
+    goto create_failed;
+
+  gst_object_unref (factory);
+
+  return element;
+
+  /* ERRORS */
+no_factory:
+  {
+    GST_WARNING ("no such element factory \"%s\"!", factoryname);
+    return NULL;
+  }
+create_failed:
+  {
+    GST_INFO_OBJECT (factory, "couldn't create instance!");
+    gst_object_unref (factory);
+    return NULL;
+  }
+}
+
+/**
+ * gst_element_factory_make_valist:
+ * @factoryname: a named factory to instantiate
+ * @first: (nullable): name of first property
+ * @properties: (nullable): list of properties
+ *
  * Create a new element of the type defined by the given element factory.
- * If name is %NULL, then the element will receive a guaranteed unique name,
- * consisting of the element factory name and a number.
- * If name is given, it will be given the name supplied.
+ * The supplied list of properties, will be passed at object construction.
  *
  * Returns: (transfer floating) (nullable): new #GstElement or %NULL
  * if unable to create element
+ *
+ * Since: 1.20
  */
 GstElement *
-gst_element_factory_make (const gchar * factoryname, const gchar * name)
+gst_element_factory_make_valist (const gchar * factoryname,
+    const gchar * first, va_list properties)
 {
   GstElementFactory *factory;
   GstElement *element;
@@ -445,15 +683,14 @@ gst_element_factory_make (const gchar * factoryname, const gchar * name)
   g_return_val_if_fail (factoryname != NULL, NULL);
   g_return_val_if_fail (gst_is_initialized (), NULL);
 
-  GST_LOG ("gstelementfactory: make \"%s\" \"%s\"",
-      factoryname, GST_STR_NULL (name));
+  GST_LOG ("gstelementfactory: make \"%s\"", factoryname);
 
   factory = gst_element_factory_find (factoryname);
   if (factory == NULL)
     goto no_factory;
 
   GST_LOG_OBJECT (factory, "found factory %p", factory);
-  element = gst_element_factory_create (factory, name);
+  element = gst_element_factory_create_valist (factory, first, properties);
   if (element == NULL)
     goto create_failed;
 
@@ -475,6 +712,59 @@ create_failed:
   }
 }
 
+/**
+ * gst_element_factory_make_full:
+ * @factoryname: a named factory to instantiate
+ * @first: (nullable): name of first property
+ * @...: (nullable): %NULL terminated list of properties
+ *
+ * Create a new element of the type defined by the given element factory.
+ * The supplied list of properties, will be passed at object construction.
+ *
+ * Returns: (transfer floating) (nullable): new #GstElement or %NULL
+ * if unable to create element
+ *
+ * Since: 1.20
+ */
+GstElement *
+gst_element_factory_make_full (const gchar * factoryname,
+    const gchar * first, ...)
+{
+  GstElement *element;
+  va_list properties;
+
+  va_start (properties, first);
+
+  element = gst_element_factory_make_valist (factoryname, first, properties);
+
+  va_end (properties);
+  return element;
+}
+
+/**
+ * gst_element_factory_make:
+ * @factoryname: a named factory to instantiate
+ * @name: (nullable): name of new element, or %NULL to automatically create
+ *    a unique name
+ *
+ * Create a new element of the type defined by the given element factory.
+ * If name is %NULL, then the element will receive a guaranteed unique name,
+ * consisting of the element factory name and a number.
+ * If name is given, it will be given the name supplied.
+ *
+ * Returns: (transfer floating) (nullable): new #GstElement or %NULL
+ * if unable to create element
+ */
+GstElement *
+gst_element_factory_make (const gchar * factoryname, const gchar * name)
+{
+  if (name)
+    return gst_element_factory_make_full (factoryname, "name", name, NULL);
+  else
+    return gst_element_factory_make_with_properties (factoryname, 0, NULL,
+        NULL);
+}
+
 void
 __gst_element_factory_add_static_pad_template (GstElementFactory * factory,
     GstStaticPadTemplate * templ)
index e0d2108..ae501c1 100644 (file)
@@ -84,9 +84,27 @@ GST_API
 GstElement*             gst_element_factory_create              (GstElementFactory *factory,
                                                                  const gchar *name) G_GNUC_MALLOC;
 GST_API
+GstElement*             gst_element_factory_create_full         (GstElementFactory * factory,
+                                                                 const gchar * first, ...) G_GNUC_MALLOC;
+GST_API
+GstElement *            gst_element_factory_create_valist       (GstElementFactory * factory,
+                                                                 const gchar * first, va_list properties) G_GNUC_MALLOC;
+GST_API
+GstElement *            gst_element_factory_create_with_properties (GstElementFactory * factory,
+                                                                 guint n, const gchar *names[], const GValue values[]) G_GNUC_MALLOC;
+GST_API
 GstElement*             gst_element_factory_make                (const gchar *factoryname, const gchar *name) G_GNUC_MALLOC;
 
 GST_API
+GstElement*             gst_element_factory_make_full           (const gchar *factoryname,
+                                                                  const gchar *first, ...) G_GNUC_MALLOC;
+GST_API
+GstElement*             gst_element_factory_make_valist         (const gchar *factoryname,
+                                                                 const gchar *first, va_list properties) G_GNUC_MALLOC;
+GST_API
+GstElement*             gst_element_factory_make_with_properties (const gchar *factoryname,
+                                                                 guint n, const gchar *names[], const GValue values[]) G_GNUC_MALLOC;
+GST_API
 gboolean                gst_element_register                    (GstPlugin *plugin, const gchar *name,
                                                                  guint rank, GType type);
 #ifdef TIZEN_PROFILE_TV
@@ -125,6 +143,11 @@ GstElement              *gst_element_factory_get                (GstElementFacto
  * matching the specified media types will be selected.
  */
 
+/**
+ * GstElementFactoryListType:
+ *
+ * A type defining the type of an element factory.
+ */
 typedef guint64 GstElementFactoryListType;
 
 #define  GST_ELEMENT_FACTORY_TYPE_DECODER        ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 0))
@@ -240,9 +263,7 @@ GST_API
 GList *       gst_element_factory_list_filter       (GList *list, const GstCaps *caps,
                                                      GstPadDirection direction,
                                                      gboolean subsetonly) G_GNUC_MALLOC;
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstElementFactory, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 820b51e..059cbca 100644 (file)
 
 /**
  * SECTION:gsterror
- * @title: GstError
+ * @title: GstGError
  * @short_description: Categorized error messages
  * @see_also: #GstMessage
+ * @symbols:
+ * - gst_error_get_message
+ * - gst_stream_error_quark
+ * - gst_core_error_quark
+ * - gst_resource_error_quark
+ * - gst_library_error_quark
  *
  * GStreamer elements can throw non-fatal warnings and fatal errors.
  * Higher-level elements and applications can programmatically filter
  * the ones they are interested in or can recover from,
  * and have a default handler handle the rest of them.
  *
- * The rest of this section will use the term <quote>error</quote>
+ * The rest of this section will use the term "error"
  * to mean both (non-fatal) warnings and (fatal) errors; they are treated
  * similarly.
  *
index 9cb6d40..17f7f39 100644 (file)
@@ -245,15 +245,27 @@ typedef enum
 GST_API
 gchar *gst_error_get_message (GQuark domain, gint code);
 
+/**
+ * gst_stream_error_quark: (attributes doc.skip=true)
+ */
 GST_API
 GQuark gst_stream_error_quark (void);
 
+/**
+ * gst_core_error_quark: (attributes doc.skip=true)
+ */
 GST_API
 GQuark gst_core_error_quark (void);
 
+/**
+ * gst_resource_error_quark: (attributes doc.skip=true)
+ */
 GST_API
 GQuark gst_resource_error_quark (void);
 
+/**
+ * gst_library_error_quark: (attributes doc.skip=true)
+ */
 GST_API
 GQuark gst_library_error_quark (void);
 
index f4bb816..225ed3b 100644 (file)
@@ -71,7 +71,7 @@
  * ]|
  */
 
-
+#define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 #include "gst_private.h"
 #include <string.h>             /* memcpy */
 
@@ -132,6 +132,8 @@ static GstEventQuarks event_quarks[] = {
   {GST_EVENT_CUSTOM_BOTH, "custom-both", 0},
   {GST_EVENT_CUSTOM_BOTH_OOB, "custom-both-oob", 0},
   {GST_EVENT_STREAM_GROUP_DONE, "stream-group-done", 0},
+  {GST_EVENT_INSTANT_RATE_CHANGE, "instant-rate-change", 0},
+  {GST_EVENT_INSTANT_RATE_SYNC_TIME, "instant-rate-sync-time", 0},
 
   {0, NULL, 0}
 };
@@ -406,6 +408,29 @@ gst_event_has_name (GstEvent * event, const gchar * name)
 }
 
 /**
+ * gst_event_has_name_id:
+ * @event: The #GstEvent.
+ * @name: name to check as a GQuark
+ *
+ * Checks if @event has the given @name. This function is usually used to
+ * check the name of a custom event.
+ *
+ * Returns: %TRUE if @name matches the name of the event structure.
+ *
+ * Since: 1.18
+ */
+gboolean
+gst_event_has_name_id (GstEvent * event, GQuark name)
+{
+  g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
+
+  if (GST_EVENT_STRUCTURE (event) == NULL)
+    return FALSE;
+
+  return (GST_EVENT_STRUCTURE (event)->name == name);
+}
+
+/**
  * gst_event_get_seqnum:
  * @event: A #GstEvent.
  *
@@ -688,6 +713,8 @@ gst_event_new_stream_group_done (guint group_id)
 {
   GstStructure *s;
 
+  g_return_val_if_fail (group_id != GST_GROUP_ID_INVALID, NULL);
+
   s = gst_structure_new_id (GST_QUARK (EVENT_STREAM_GROUP_DONE),
       GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id, NULL);
 
@@ -800,6 +827,51 @@ gst_event_parse_gap (GstEvent * event, GstClockTime * timestamp,
 }
 
 /**
+ * gst_event_set_gap_flags:
+ * @event: a #GstEvent of type #GST_EVENT_GAP
+ * @flags: a #GstGapFlags
+ *
+ * Sets @flags on @event to give additional information about the reason for
+ * the #GST_EVENT_GAP.
+ *
+ * Since: 1.20
+ */
+void
+gst_event_set_gap_flags (GstEvent * event, GstGapFlags flags)
+{
+  g_return_if_fail (event != NULL);
+  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_GAP);
+  g_return_if_fail (gst_event_is_writable (event));
+
+  gst_structure_id_set (GST_EVENT_STRUCTURE (event),
+      GST_QUARK (GAP_FLAGS), GST_TYPE_GAP_FLAGS, flags, NULL);
+}
+
+/**
+ * gst_event_parse_gap_flags:
+ * @event: a #GstEvent of type #GST_EVENT_GAP
+ * @flags: (out): a #GstGapFlags or %NULL
+ *
+ * Retrieve the gap flags that may have been set on a gap event with
+ * gst_event_set_gap_flags().
+ *
+ * Since: 1.20
+ */
+void
+gst_event_parse_gap_flags (GstEvent * event, GstGapFlags * flags)
+{
+  g_return_if_fail (event != NULL);
+  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_GAP);
+
+  /* Initialize to 0 for GAP events that don't have the field set */
+  if (flags)
+    *flags = 0;
+
+  gst_structure_id_get (GST_EVENT_STRUCTURE (event),
+      GST_QUARK (GAP_FLAGS), GST_TYPE_GAP_FLAGS, flags, NULL);
+}
+
+/**
  * gst_event_new_caps:
  * @caps: (transfer none): a #GstCaps
  *
@@ -1270,6 +1342,10 @@ gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
   GstStructure *structure;
 
   g_return_val_if_fail (rate != 0.0, NULL);
+  g_return_val_if_fail ((flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) == 0
+      || (start_type == GST_SEEK_TYPE_NONE
+          && stop_type == GST_SEEK_TYPE_NONE
+          && (flags & GST_SEEK_FLAG_FLUSH) == 0), NULL);
 
   /* SNAP flags only make sense in combination with the KEYUNIT flag. Warn
    * and unset the SNAP flags if they're set without the KEYUNIT flag */
@@ -1406,6 +1482,9 @@ gst_event_parse_seek_trickmode_interval (GstEvent * event,
   g_return_if_fail (interval != NULL);
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
 
+  if (interval)
+    *interval = GST_CLOCK_TIME_NONE;
+
   gst_structure_id_get (GST_EVENT_STRUCTURE (event),
       GST_QUARK (TRICKMODE_INTERVAL), GST_TYPE_CLOCK_TIME, interval, NULL);
 }
@@ -1446,6 +1525,8 @@ gst_event_new_latency (GstClockTime latency)
   GstEvent *event;
   GstStructure *structure;
 
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (latency), NULL);
+
   GST_CAT_INFO (GST_CAT_EVENT,
       "creating latency event %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
 
@@ -1740,10 +1821,10 @@ gst_event_parse_stream (GstEvent * event, GstStream ** stream)
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START);
 
   if (stream) {
+    *stream = NULL;
     gst_structure_id_get (GST_EVENT_STRUCTURE (event),
         GST_QUARK (STREAM), GST_TYPE_STREAM, stream, NULL);
   }
-
 }
 
 /**
@@ -1778,6 +1859,7 @@ gst_event_parse_stream_flags (GstEvent * event, GstStreamFlags * flags)
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START);
 
   if (flags) {
+    *flags = 0;
     gst_structure_id_get (GST_EVENT_STRUCTURE (event),
         GST_QUARK (FLAGS), GST_TYPE_STREAM_FLAGS, flags, NULL);
   }
@@ -1804,6 +1886,7 @@ gst_event_set_group_id (GstEvent * event, guint group_id)
   g_return_if_fail (event != NULL);
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START);
   g_return_if_fail (gst_event_is_writable (event));
+  g_return_if_fail (group_id != GST_GROUP_ID_INVALID);
 
   gst_structure_id_set (GST_EVENT_STRUCTURE (event),
       GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id, NULL);
@@ -1827,6 +1910,7 @@ gst_event_parse_group_id (GstEvent * event, guint * group_id)
       FALSE);
 
   if (group_id) {
+    *group_id = 0;
     return gst_structure_id_get (GST_EVENT_STRUCTURE (event),
         GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id, NULL);
   }
@@ -1994,7 +2078,7 @@ gst_event_parse_toc_select (GstEvent * event, gchar ** uid)
   val = gst_structure_id_get_value (structure, GST_QUARK (UID));
 
   if (uid != NULL)
-    *uid = g_strdup (g_value_get_string (val));
+    *uid = g_value_dup_string (val);
 
 }
 
@@ -2167,3 +2251,272 @@ gst_event_parse_segment_done (GstEvent * event, GstFormat * format,
   if (position != NULL)
     *position = g_value_get_int64 (val);
 }
+
+/**
+ * gst_event_new_instant_rate_change:
+ * @rate_multiplier: the multiplier to be applied to the playback rate
+ * @new_flags: A new subset of segment flags to replace in segments
+ *
+ * Create a new instant-rate-change event. This event is sent by seek
+ * handlers (e.g. demuxers) when receiving a seek with the
+ * %GST_SEEK_FLAG_INSTANT_RATE_CHANGE and signals to downstream elements that
+ * the playback rate in the existing segment should be immediately multiplied
+ * by the @rate_multiplier factor.
+ *
+ * The flags provided replace any flags in the existing segment, for the
+ * flags within the %GST_SEGMENT_INSTANT_FLAGS set. Other GstSegmentFlags
+ * are ignored and not transferred in the event.
+ *
+ * Returns: (transfer full): the new instant-rate-change event.
+ *
+ * Since: 1.18
+ */
+GstEvent *
+gst_event_new_instant_rate_change (gdouble rate_multiplier,
+    GstSegmentFlags new_flags)
+{
+  GstEvent *event;
+
+  g_return_val_if_fail (rate_multiplier != 0.0, NULL);
+
+  new_flags &= GST_SEGMENT_INSTANT_FLAGS;
+
+  GST_CAT_TRACE (GST_CAT_EVENT, "creating instant-rate-change event %lf %08x",
+      rate_multiplier, new_flags);
+
+  event = gst_event_new_custom (GST_EVENT_INSTANT_RATE_CHANGE,
+      gst_structure_new_id (GST_QUARK (EVENT_INSTANT_RATE_CHANGE),
+          GST_QUARK (RATE), G_TYPE_DOUBLE, rate_multiplier,
+          GST_QUARK (FLAGS), GST_TYPE_SEGMENT_FLAGS, new_flags, NULL));
+
+  return event;
+}
+
+/**
+ * gst_event_parse_instant_rate_change:
+ * @event: a #GstEvent of type #GST_EVENT_INSTANT_RATE_CHANGE
+ * @rate_multiplier: (out) (allow-none): location in which to store the rate
+ *     multiplier of the instant-rate-change event, or %NULL
+ * @new_flags: (out) (allow-none): location in which to store the new
+ *     segment flags of the instant-rate-change event, or %NULL
+ *
+ * Extract rate and flags from an instant-rate-change event.
+ *
+ * Since: 1.18
+ */
+void
+gst_event_parse_instant_rate_change (GstEvent * event,
+    gdouble * rate_multiplier, GstSegmentFlags * new_flags)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_IS_EVENT (event));
+  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_INSTANT_RATE_CHANGE);
+
+  structure = GST_EVENT_STRUCTURE (event);
+  gst_structure_id_get (structure, GST_QUARK (RATE), G_TYPE_DOUBLE,
+      rate_multiplier, GST_QUARK (FLAGS), GST_TYPE_SEGMENT_FLAGS, new_flags,
+      NULL);
+}
+
+/**
+ * gst_event_new_instant_rate_sync_time:
+ * @rate_multiplier: the new playback rate multiplier to be applied
+ * @running_time: Running time when the rate change should be applied
+ * @upstream_running_time: The upstream-centric running-time when the
+ *    rate change should be applied.
+ *
+ * Create a new instant-rate-sync-time event. This event is sent by the
+ * pipeline to notify elements handling the instant-rate-change event about
+ * the running-time when the new rate should be applied. The running time
+ * may be in the past when elements handle this event, which can lead to
+ * switching artifacts. The magnitude of those depends on the exact timing
+ * of event delivery to each element and the magnitude of the change in
+ * playback rate being applied.
+ *
+ * The @running_time and @upstream_running_time are the same if this
+ * is the first instant-rate adjustment, but will differ for later ones
+ * to compensate for the accumulated offset due to playing at a rate
+ * different to the one indicated in the playback segments.
+ *
+ * Returns: (transfer full): the new instant-rate-sync-time event.
+ *
+ * Since: 1.18
+ */
+GstEvent *
+gst_event_new_instant_rate_sync_time (gdouble rate_multiplier,
+    GstClockTime running_time, GstClockTime upstream_running_time)
+{
+  GstEvent *event;
+
+  g_return_val_if_fail (rate_multiplier != 0.0, NULL);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (running_time), NULL);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (upstream_running_time), NULL);
+
+  GST_CAT_TRACE (GST_CAT_EVENT,
+      "creating instant-rate-sync-time event %lf %" GST_TIME_FORMAT
+      " %" GST_TIME_FORMAT, rate_multiplier,
+      GST_TIME_ARGS (running_time), GST_TIME_ARGS (upstream_running_time));
+
+  event = gst_event_new_custom (GST_EVENT_INSTANT_RATE_SYNC_TIME,
+      gst_structure_new_id (GST_QUARK (EVENT_INSTANT_RATE_SYNC_TIME),
+          GST_QUARK (RATE), G_TYPE_DOUBLE, rate_multiplier,
+          GST_QUARK (RUNNING_TIME), GST_TYPE_CLOCK_TIME, running_time,
+          GST_QUARK (UPSTREAM_RUNNING_TIME), GST_TYPE_CLOCK_TIME,
+          upstream_running_time, NULL));
+
+  return event;
+}
+
+/**
+ * gst_event_parse_instant_rate_sync_time:
+ * @event: a #GstEvent of type #GST_EVENT_INSTANT_RATE_CHANGE
+ * @rate_multiplier: (out) (allow-none): location where to store the rate of
+ *     the instant-rate-sync-time event, or %NULL
+ * @running_time: (out) (allow-none): location in which to store the running time
+ *     of the instant-rate-sync-time event, or %NULL
+ * @upstream_running_time: (out) (allow-none): location in which to store the
+ *     upstream running time of the instant-rate-sync-time event, or %NULL
+ *
+ * Extract the rate multiplier and running times from an instant-rate-sync-time event.
+ *
+ * Since: 1.18
+ */
+void
+gst_event_parse_instant_rate_sync_time (GstEvent * event,
+    gdouble * rate_multiplier, GstClockTime * running_time,
+    GstClockTime * upstream_running_time)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_IS_EVENT (event));
+  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_INSTANT_RATE_SYNC_TIME);
+
+  structure = GST_EVENT_STRUCTURE (event);
+  gst_structure_id_get (structure, GST_QUARK (RATE), G_TYPE_DOUBLE,
+      rate_multiplier, GST_QUARK (RUNNING_TIME), GST_TYPE_CLOCK_TIME,
+      running_time, GST_QUARK (UPSTREAM_RUNNING_TIME), GST_TYPE_CLOCK_TIME,
+      upstream_running_time, NULL);
+}
+
+/**
+ * gst_event_replace: (skip)
+ * @old_event: (inout) (transfer full) (nullable): pointer to a
+ *     pointer to a #GstEvent to be replaced.
+ * @new_event: (allow-none) (transfer none): 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. 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
+ * event is unreffed, the new one is reffed).
+ *
+ * Either @new_event or the #GstEvent pointed to by @old_event may be %NULL.
+ *
+ * Returns: %TRUE if @new_event was different from @old_event
+ */
+gboolean
+gst_event_replace (GstEvent ** old_event, GstEvent * new_event)
+{
+  return gst_mini_object_replace ((GstMiniObject **) old_event,
+      (GstMiniObject *) new_event);
+}
+
+/**
+ * gst_event_steal: (skip)
+ * @old_event: (inout) (transfer full) (nullable): 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
+ */
+GstEvent *
+gst_event_steal (GstEvent ** old_event)
+{
+  return GST_EVENT_CAST (gst_mini_object_steal ((GstMiniObject **) old_event));
+}
+
+/**
+ * gst_event_take: (skip)
+ * @old_event: (inout) (transfer full) (nullable): 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
+ */
+gboolean
+gst_event_take (GstEvent ** old_event, GstEvent * new_event)
+{
+  return gst_mini_object_take ((GstMiniObject **) old_event,
+      (GstMiniObject *) new_event);
+}
+
+/**
+ * gst_event_ref: (skip)
+ * @event: The event to refcount
+ *
+ * Increase the refcount of this event.
+ *
+ * Returns: (transfer full): @event (for convenience when doing assignments)
+ */
+GstEvent *
+gst_event_ref (GstEvent * event)
+{
+  return (GstEvent *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (event));
+}
+
+/**
+ * gst_event_unref: (skip)
+ * @event: (transfer full): the event to refcount
+ *
+ * Decrease the refcount of an event, freeing it if the refcount reaches 0.
+ */
+void
+gst_event_unref (GstEvent * event)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (event));
+}
+
+/**
+ * gst_clear_event: (skip)
+ * @event_ptr: a pointer to a #GstEvent reference
+ *
+ * Clears a reference to a #GstEvent.
+ *
+ * @event_ptr must not be %NULL.
+ *
+ * If the reference is %NULL then this function does nothing. Otherwise, the
+ * reference count of the event is decreased and the pointer is set to %NULL.
+ *
+ * Since: 1.16
+ */
+void
+gst_clear_event (GstEvent ** event_ptr)
+{
+  gst_clear_mini_object ((GstMiniObject **) event_ptr);
+}
+
+/**
+ * gst_event_copy: (skip)
+ * @event: The event to copy
+ *
+ * Copy the event using the event specific copy function.
+ *
+ * Returns: (transfer full): the new event
+ */
+GstEvent *
+gst_event_copy (const GstEvent * event)
+{
+  return
+      GST_EVENT_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST
+          (event)));
+}
index 38ad3fb..e036a34 100644 (file)
@@ -70,7 +70,7 @@ typedef enum {
 #define GST_EVENT_MAKE_TYPE(num,flags) \
     (((num) << GST_EVENT_NUM_SHIFT) | (flags))
 
-#define FLAG(name) GST_EVENT_TYPE_##name
+#define _FLAG(name) GST_EVENT_TYPE_##name
 
 /**
  * GstEventType:
@@ -121,6 +121,11 @@ typedef enum {
  * @GST_EVENT_RECONFIGURE: A request for upstream renegotiating caps and reconfiguring.
  * @GST_EVENT_TOC_SELECT: A request for a new playback position based on TOC
  *                        entry's UID.
+ * @GST_EVENT_INSTANT_RATE_CHANGE: Notify downstream that a playback rate override
+ *                                 should be applied as soon as possible. (Since: 1.18)
+ * @GST_EVENT_INSTANT_RATE_SYNC_TIME: Sent by the pipeline to notify elements that handle the
+ *                                    instant-rate-change event about the running-time when
+ *                                    the rate multiplier should be applied (or was applied). (Since: 1.18)
  * @GST_EVENT_CUSTOM_UPSTREAM: Upstream custom event
  * @GST_EVENT_CUSTOM_DOWNSTREAM: Downstream custom event that travels in the
  *                        data flow.
@@ -143,45 +148,49 @@ typedef enum {
   GST_EVENT_UNKNOWN               = GST_EVENT_MAKE_TYPE (0, 0),
 
   /* bidirectional events */
-  GST_EVENT_FLUSH_START           = GST_EVENT_MAKE_TYPE (10, FLAG(BOTH)),
-  GST_EVENT_FLUSH_STOP            = GST_EVENT_MAKE_TYPE (20, FLAG(BOTH) | FLAG(SERIALIZED)),
+  GST_EVENT_FLUSH_START           = GST_EVENT_MAKE_TYPE (10, _FLAG(BOTH)),
+  GST_EVENT_FLUSH_STOP            = GST_EVENT_MAKE_TYPE (20, _FLAG(BOTH) | _FLAG(SERIALIZED)),
 
   /* downstream serialized events */
-  GST_EVENT_STREAM_START          = GST_EVENT_MAKE_TYPE (40, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)),
-  GST_EVENT_CAPS                  = GST_EVENT_MAKE_TYPE (50, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)),
-  GST_EVENT_SEGMENT               = GST_EVENT_MAKE_TYPE (70, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)),
-  GST_EVENT_STREAM_COLLECTION     = GST_EVENT_MAKE_TYPE (75, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)),
-  GST_EVENT_TAG                   = GST_EVENT_MAKE_TYPE (80, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)),
-  GST_EVENT_BUFFERSIZE            = GST_EVENT_MAKE_TYPE (90, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)),
-  GST_EVENT_SINK_MESSAGE          = GST_EVENT_MAKE_TYPE (100, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)),
-  GST_EVENT_STREAM_GROUP_DONE     = GST_EVENT_MAKE_TYPE (105, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)),
-  GST_EVENT_EOS                   = GST_EVENT_MAKE_TYPE (110, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)),
-  GST_EVENT_TOC                   = GST_EVENT_MAKE_TYPE (120, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)),
-  GST_EVENT_PROTECTION            = GST_EVENT_MAKE_TYPE (130, FLAG (DOWNSTREAM) | FLAG (SERIALIZED) | FLAG (STICKY) | FLAG (STICKY_MULTI)),
+  GST_EVENT_STREAM_START          = GST_EVENT_MAKE_TYPE (40, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED) | _FLAG(STICKY)),
+  GST_EVENT_CAPS                  = GST_EVENT_MAKE_TYPE (50, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED) | _FLAG(STICKY)),
+  GST_EVENT_SEGMENT               = GST_EVENT_MAKE_TYPE (70, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED) | _FLAG(STICKY)),
+  GST_EVENT_STREAM_COLLECTION     = GST_EVENT_MAKE_TYPE (75, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED) | _FLAG(STICKY) | _FLAG(STICKY_MULTI)),
+  GST_EVENT_TAG                   = GST_EVENT_MAKE_TYPE (80, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED) | _FLAG(STICKY) | _FLAG(STICKY_MULTI)),
+  GST_EVENT_BUFFERSIZE            = GST_EVENT_MAKE_TYPE (90, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED) | _FLAG(STICKY)),
+  GST_EVENT_SINK_MESSAGE          = GST_EVENT_MAKE_TYPE (100, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED) | _FLAG(STICKY) | _FLAG(STICKY_MULTI)),
+  GST_EVENT_STREAM_GROUP_DONE     = GST_EVENT_MAKE_TYPE (105, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED) | _FLAG(STICKY)),
+  GST_EVENT_EOS                   = GST_EVENT_MAKE_TYPE (110, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED) | _FLAG(STICKY)),
+  GST_EVENT_TOC                   = GST_EVENT_MAKE_TYPE (120, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED) | _FLAG(STICKY) | _FLAG(STICKY_MULTI)),
+  GST_EVENT_PROTECTION            = GST_EVENT_MAKE_TYPE (130, _FLAG (DOWNSTREAM) | _FLAG (SERIALIZED) | _FLAG (STICKY) | _FLAG (STICKY_MULTI)),
 
   /* non-sticky downstream serialized */
-  GST_EVENT_SEGMENT_DONE          = GST_EVENT_MAKE_TYPE (150, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
-  GST_EVENT_GAP                   = GST_EVENT_MAKE_TYPE (160, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
+  GST_EVENT_SEGMENT_DONE          = GST_EVENT_MAKE_TYPE (150, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED)),
+  GST_EVENT_GAP                   = GST_EVENT_MAKE_TYPE (160, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED)),
+
+  /* sticky downstream non-serialized */
+  GST_EVENT_INSTANT_RATE_CHANGE   = GST_EVENT_MAKE_TYPE (180, _FLAG(DOWNSTREAM) | _FLAG(STICKY)),
 
   /* upstream events */
-  GST_EVENT_QOS                   = GST_EVENT_MAKE_TYPE (190, FLAG(UPSTREAM)),
-  GST_EVENT_SEEK                  = GST_EVENT_MAKE_TYPE (200, FLAG(UPSTREAM)),
-  GST_EVENT_NAVIGATION            = GST_EVENT_MAKE_TYPE (210, FLAG(UPSTREAM)),
-  GST_EVENT_LATENCY               = GST_EVENT_MAKE_TYPE (220, FLAG(UPSTREAM)),
-  GST_EVENT_STEP                  = GST_EVENT_MAKE_TYPE (230, FLAG(UPSTREAM)),
-  GST_EVENT_RECONFIGURE           = GST_EVENT_MAKE_TYPE (240, FLAG(UPSTREAM)),
-  GST_EVENT_TOC_SELECT            = GST_EVENT_MAKE_TYPE (250, FLAG(UPSTREAM)),
-  GST_EVENT_SELECT_STREAMS        = GST_EVENT_MAKE_TYPE (260, FLAG(UPSTREAM)),
+  GST_EVENT_QOS                    = GST_EVENT_MAKE_TYPE (190, _FLAG(UPSTREAM)),
+  GST_EVENT_SEEK                   = GST_EVENT_MAKE_TYPE (200, _FLAG(UPSTREAM)),
+  GST_EVENT_NAVIGATION             = GST_EVENT_MAKE_TYPE (210, _FLAG(UPSTREAM)),
+  GST_EVENT_LATENCY                = GST_EVENT_MAKE_TYPE (220, _FLAG(UPSTREAM)),
+  GST_EVENT_STEP                   = GST_EVENT_MAKE_TYPE (230, _FLAG(UPSTREAM)),
+  GST_EVENT_RECONFIGURE            = GST_EVENT_MAKE_TYPE (240, _FLAG(UPSTREAM)),
+  GST_EVENT_TOC_SELECT             = GST_EVENT_MAKE_TYPE (250, _FLAG(UPSTREAM)),
+  GST_EVENT_SELECT_STREAMS         = GST_EVENT_MAKE_TYPE (260, _FLAG(UPSTREAM)),
+  GST_EVENT_INSTANT_RATE_SYNC_TIME = GST_EVENT_MAKE_TYPE (261, _FLAG(UPSTREAM)),
 
   /* custom events start here */
-  GST_EVENT_CUSTOM_UPSTREAM          = GST_EVENT_MAKE_TYPE (270, FLAG(UPSTREAM)),
-  GST_EVENT_CUSTOM_DOWNSTREAM        = GST_EVENT_MAKE_TYPE (280, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
-  GST_EVENT_CUSTOM_DOWNSTREAM_OOB    = GST_EVENT_MAKE_TYPE (290, FLAG(DOWNSTREAM)),
-  GST_EVENT_CUSTOM_DOWNSTREAM_STICKY = GST_EVENT_MAKE_TYPE (300, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)),
-  GST_EVENT_CUSTOM_BOTH              = GST_EVENT_MAKE_TYPE (310, FLAG(BOTH) | FLAG(SERIALIZED)),
-  GST_EVENT_CUSTOM_BOTH_OOB          = GST_EVENT_MAKE_TYPE (320, FLAG(BOTH))
+  GST_EVENT_CUSTOM_UPSTREAM          = GST_EVENT_MAKE_TYPE (270, _FLAG(UPSTREAM)),
+  GST_EVENT_CUSTOM_DOWNSTREAM        = GST_EVENT_MAKE_TYPE (280, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED)),
+  GST_EVENT_CUSTOM_DOWNSTREAM_OOB    = GST_EVENT_MAKE_TYPE (290, _FLAG(DOWNSTREAM)),
+  GST_EVENT_CUSTOM_DOWNSTREAM_STICKY = GST_EVENT_MAKE_TYPE (300, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED) | _FLAG(STICKY) | _FLAG(STICKY_MULTI)),
+  GST_EVENT_CUSTOM_BOTH              = GST_EVENT_MAKE_TYPE (310, _FLAG(BOTH) | _FLAG(SERIALIZED)),
+  GST_EVENT_CUSTOM_BOTH_OOB          = GST_EVENT_MAKE_TYPE (320, _FLAG(BOTH))
 } GstEventType;
-#undef FLAG
+#undef _FLAG
 
 /**
  * GstStreamFlags:
@@ -312,64 +321,37 @@ GST_API GType _gst_event_type;
  *     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) (nullable): pointer to a
- *     pointer to a #GstEvent to be replaced.
- * @new_event: (allow-none) (transfer none): 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. 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
- * event is unreffed, the new one is reffed).
- *
- * Either @new_event or the #GstEvent pointed to by @old_event may be %NULL.
- *
- * Returns: %TRUE if @new_event was different from @old_event
- */
+
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 static inline gboolean
-gst_event_replace (GstEvent **old_event, GstEvent *new_event)
+gst_event_replace(GstEvent** old_event, GstEvent* new_event)
 {
   return gst_mini_object_replace ((GstMiniObject **) old_event, (GstMiniObject *) new_event);
 }
 
-/**
- * gst_event_steal:
- * @old_event: (inout) (transfer full) (nullable): 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
- */
 static inline GstEvent *
 gst_event_steal (GstEvent **old_event)
 {
   return GST_EVENT_CAST (gst_mini_object_steal ((GstMiniObject **) old_event));
 }
 
-/**
- * gst_event_take:
- * @old_event: (inout) (transfer full) (nullable): 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
- */
 static inline gboolean
 gst_event_take (GstEvent **old_event, GstEvent *new_event)
 {
   return gst_mini_object_take ((GstMiniObject **) old_event, (GstMiniObject *) new_event);
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+gboolean    gst_event_replace (GstEvent ** old_event,
+                               GstEvent * new_event);
+
+GST_API
+GstEvent *  gst_event_steal   (GstEvent ** old_event);
+
+GST_API
+gboolean    gst_event_take    (GstEvent ** old_event,
+                               GstEvent *new_event);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 /**
  * GstQOSType:
@@ -392,6 +374,19 @@ typedef enum {
   GST_QOS_TYPE_THROTTLE        = 2
 } GstQOSType;
 
+/**
+ * GstGapFlags:
+ * @GST_GAP_FLAG_MISSING_DATA: The #GST_EVENT_GAP signals missing data,
+ *    for example because of packet loss.
+ *
+ * The different flags that can be set on #GST_EVENT_GAP events. See
+ * gst_event_set_gap_flags() for details.
+ *
+ * Since: 1.20
+ */
+typedef enum {
+  GST_GAP_FLAG_MISSING_DATA = (1<<0),
+} GstGapFlags;
 
 /**
  * GstEvent:
@@ -422,47 +417,20 @@ GST_API
 GstEventTypeFlags
                 gst_event_type_get_flags        (GstEventType type);
 
-
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 /* refcounting */
-/**
- * gst_event_ref:
- * @event: The event to refcount
- *
- * Increase the refcount of this event.
- *
- * Returns: (transfer full): @event (for convenience when doing assignments)
- */
 static inline GstEvent *
 gst_event_ref (GstEvent * event)
 {
   return (GstEvent *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (event));
 }
 
-/**
- * gst_event_unref:
- * @event: (transfer full): the event to refcount
- *
- * Decrease the refcount of an event, freeing it if the refcount reaches 0.
- */
 static inline void
 gst_event_unref (GstEvent * event)
 {
   gst_mini_object_unref (GST_MINI_OBJECT_CAST (event));
 }
 
-/**
- * gst_clear_event: (skip)
- * @event_ptr: a pointer to a #GstEvent reference
- *
- * Clears a reference to a #GstEvent.
- *
- * @event_ptr must not be %NULL.
- *
- * If the reference is %NULL then this function does nothing. Otherwise, the
- * reference count of the event is decreased and the pointer is set to %NULL.
- *
- * Since: 1.16
- */
 static inline void
 gst_clear_event (GstEvent ** event_ptr)
 {
@@ -470,19 +438,24 @@ gst_clear_event (GstEvent ** event_ptr)
 }
 
 /* copy event */
-/**
- * gst_event_copy:
- * @event: The event to copy
- *
- * Copy the event using the event specific copy function.
- *
- * Returns: (transfer full): the new event
- */
 static inline GstEvent *
 gst_event_copy (const GstEvent * event)
 {
   return GST_EVENT_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (event)));
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+GstEvent *      gst_event_ref                   (GstEvent * event);
+
+GST_API
+void            gst_event_unref                 (GstEvent * event);
+
+GST_API
+void            gst_clear_event                 (GstEvent ** event_ptr);
+
+GST_API
+GstEvent *      gst_event_copy                  (const GstEvent * event);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 GST_API
 GType           gst_event_get_type              (void);
@@ -502,6 +475,9 @@ GstStructure *  gst_event_writable_structure    (GstEvent *event);
 GST_API
 gboolean        gst_event_has_name              (GstEvent *event, const gchar *name);
 
+GST_API
+gboolean        gst_event_has_name_id           (GstEvent *event, GQuark name);
+
 /* identifiers for events and messages */
 
 GST_API
@@ -594,6 +570,14 @@ void            gst_event_parse_gap             (GstEvent     * event,
                                                  GstClockTime * timestamp,
                                                  GstClockTime * duration);
 
+GST_API
+void            gst_event_set_gap_flags           (GstEvent    * event,
+                                                   GstGapFlags   flags);
+
+GST_API
+void            gst_event_parse_gap_flags         (GstEvent    * event,
+                                                   GstGapFlags * flags);
+
 /* Caps events */
 
 GST_API
@@ -725,9 +709,29 @@ GstEvent*       gst_event_new_segment_done      (GstFormat format, gint64 positi
 GST_API
 void            gst_event_parse_segment_done    (GstEvent *event, GstFormat *format, gint64 *position);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
+/* instant-rate-change event */
+
+GST_API
+GstEvent *      gst_event_new_instant_rate_change   (gdouble rate_multiplier, GstSegmentFlags new_flags) G_GNUC_MALLOC;
+
+GST_API
+void            gst_event_parse_instant_rate_change (GstEvent *event,
+                                                     gdouble  *rate_multiplier, GstSegmentFlags *new_flags);
+
+/* instant-rate-change-sync-time event */
+
+GST_API
+GstEvent *      gst_event_new_instant_rate_sync_time   (gdouble      rate_multiplier,
+                                                        GstClockTime running_time,
+                                                        GstClockTime upstream_running_time) G_GNUC_MALLOC;
+
+GST_API
+void            gst_event_parse_instant_rate_sync_time (GstEvent     *event,
+                                                        gdouble      *rate_multiplier,
+                                                        GstClockTime *running_time,
+                                                        GstClockTime *upstream_running_time);
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstEvent, gst_event_unref)
-#endif
 
 G_END_DECLS
 
index ffbe650..99f1cf5 100644 (file)
@@ -257,19 +257,10 @@ gst_proxy_pad_init (GstProxyPad * ppad)
 /***********************************************************************
  * Ghost pads, implemented as a pair of proxy pads (sort of)
  */
-
-
-#define GST_GHOST_PAD_PRIVATE(obj)     (GST_GHOST_PAD_CAST (obj)->priv)
-
-struct _GstGhostPadPrivate
-{
-  /* with PROXY_LOCK */
-  gboolean constructed;
-};
-
-G_DEFINE_TYPE_WITH_PRIVATE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD);
+G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD);
 
 static void gst_ghost_pad_dispose (GObject * object);
+static void gst_ghost_pad_constructed (GObject * object);
 
 static gboolean
 gst_ghost_pad_internal_activate_push_default (GstPad * pad, GstObject * parent,
@@ -459,6 +450,7 @@ gst_ghost_pad_class_init (GstGhostPadClass * klass)
   GObjectClass *gobject_class = (GObjectClass *) klass;
 
   gobject_class->dispose = gst_ghost_pad_dispose;
+  gobject_class->constructed = gst_ghost_pad_constructed;
 
   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_pull_default);
   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_push_default);
@@ -467,8 +459,6 @@ gst_ghost_pad_class_init (GstGhostPadClass * klass)
 static void
 gst_ghost_pad_init (GstGhostPad * pad)
 {
-  GST_GHOST_PAD_PRIVATE (pad) = gst_ghost_pad_get_instance_private (pad);
-
   gst_pad_set_activatemode_function (GST_PAD_CAST (pad),
       gst_ghost_pad_activate_mode_default);
 }
@@ -516,32 +506,19 @@ gst_ghost_pad_dispose (GObject * object)
   G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object);
 }
 
-/**
- * gst_ghost_pad_construct:
- * @gpad: the newly allocated ghost pad
- *
- * Finish initialization of a newly allocated ghost pad.
- *
- * This function is most useful in language bindings and when subclassing
- * #GstGhostPad; plugin and application developers normally will not call this
- * function. Call this function directly after a call to g_object_new
- * (GST_TYPE_GHOST_PAD, "direction", @dir, ..., NULL).
- *
- * Returns: %TRUE if the construction succeeds, %FALSE otherwise.
- */
-gboolean
-gst_ghost_pad_construct (GstGhostPad * gpad)
+static void
+gst_ghost_pad_constructed (GObject * object)
 {
+  GstGhostPad *gpad = GST_GHOST_PAD (object);
   GstPadDirection dir, otherdir;
   GstPadTemplate *templ;
   GstPad *pad, *internal;
 
-  g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
-  g_return_val_if_fail (!GST_GHOST_PAD_PRIVATE (gpad)->constructed, FALSE);
+  G_OBJECT_CLASS (gst_ghost_pad_parent_class)->constructed (object);
 
   g_object_get (gpad, "direction", &dir, "template", &templ, NULL);
 
-  g_return_val_if_fail (dir != GST_PAD_UNKNOWN, FALSE);
+  g_return_if_fail (dir != GST_PAD_UNKNOWN);
 
   pad = GST_PAD (gpad);
 
@@ -577,12 +554,8 @@ gst_ghost_pad_construct (GstGhostPad * gpad)
     gst_pad_set_getrange_function (internal, gst_proxy_pad_getrange_default);
   }
 
-  GST_OBJECT_LOCK (pad);
-
   /* now make the ghostpad a parent of the internal pad */
-  if (!gst_object_set_parent (GST_OBJECT_CAST (internal),
-          GST_OBJECT_CAST (pad)))
-    goto parent_failed;
+  gst_object_set_parent (GST_OBJECT_CAST (internal), GST_OBJECT_CAST (pad));
 
   /* The ghostpad is the parent of the internal pad and is the only object that
    * can have a refcount on the internal pad.
@@ -598,23 +571,31 @@ gst_ghost_pad_construct (GstGhostPad * gpad)
   /* special activation functions for the internal pad */
   gst_pad_set_activatemode_function (internal,
       gst_ghost_pad_internal_activate_mode_default);
+}
 
-  GST_OBJECT_UNLOCK (pad);
-
-  GST_GHOST_PAD_PRIVATE (gpad)->constructed = TRUE;
+#ifndef GST_REMOVE_DEPRECATED
+/**
+ * gst_ghost_pad_construct:
+ * @gpad: the newly allocated ghost pad
+ *
+ * Finish initialization of a newly allocated ghost pad.
+ *
+ * This function is most useful in language bindings and when subclassing
+ * #GstGhostPad; plugin and application developers normally will not call this
+ * function. Call this function directly after a call to g_object_new
+ * (GST_TYPE_GHOST_PAD, "direction", @dir, ..., NULL).
+ *
+ * Deprecated: This function is deprecated since 1.18 and does nothing
+ * anymore.
+ *
+ * Returns: %TRUE if the construction succeeds, %FALSE otherwise.
+ */
+gboolean
+gst_ghost_pad_construct (GstGhostPad * gpad)
+{
   return TRUE;
-
-  /* ERRORS */
-parent_failed:
-  {
-    GST_WARNING_OBJECT (gpad, "Could not set internal pad %s:%s",
-        GST_DEBUG_PAD_NAME (internal));
-    g_critical ("Could not set internal pad %s:%s",
-        GST_DEBUG_PAD_NAME (internal));
-    GST_OBJECT_UNLOCK (pad);
-    return FALSE;
-  }
 }
+#endif
 
 static GstPad *
 gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir,
@@ -638,15 +619,7 @@ gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir,
         "direction", dir, NULL);
   }
 
-  if (!gst_ghost_pad_construct (ret))
-    goto construct_failed;
-
   return GST_PAD_CAST (ret);
-
-construct_failed:
-  /* already logged */
-  gst_object_unref (ret);
-  return NULL;
 }
 
 /**
index 98a364d..7f4a253 100644 (file)
@@ -132,7 +132,7 @@ GstPad*          gst_ghost_pad_get_target        (GstGhostPad *gpad);
 GST_API
 gboolean         gst_ghost_pad_set_target        (GstGhostPad *gpad, GstPad *newtarget);
 
-GST_API
+GST_DEPRECATED
 gboolean         gst_ghost_pad_construct         (GstGhostPad *gpad);
 
 GST_API
@@ -142,13 +142,9 @@ GST_API
 gboolean         gst_ghost_pad_internal_activate_mode_default   (GstPad * pad, GstObject * parent,
                                                                  GstPadMode mode, gboolean active);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstGhostPad, gst_object_unref)
-#endif
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstProxyPad, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 9fd8338..525c9f0 100644 (file)
@@ -72,7 +72,7 @@
  * So don't take addresses of these functions or use other tricks.
  * If you must do that for some reason, there is still an option.
  * If the debugging
- * subsystem was compiled out, #GST_DISABLE_GST_DEBUG is defined in
+ * subsystem was compiled out, GST_DISABLE_GST_DEBUG is defined in
  * &lt;gst/gst.h&gt;,
  * so you can check that before doing your trick.
  * Disabling the debugging subsystem will give you a slight (read: unnoticeable)
@@ -147,6 +147,28 @@ static char *gst_info_printf_pointer_extension_func (const char *format,
 
 #ifdef HAVE_DW
 #include <elfutils/libdwfl.h>
+static Dwfl *_global_dwfl = NULL;
+static GMutex _dwfl_mutex;
+
+#define GST_DWFL_LOCK() g_mutex_lock(&_dwfl_mutex);
+#define GST_DWFL_UNLOCK() g_mutex_unlock(&_dwfl_mutex);
+
+static Dwfl *
+get_global_dwfl (void)
+{
+  if (g_once_init_enter (&_global_dwfl)) {
+    static Dwfl_Callbacks callbacks = {
+      .find_elf = dwfl_linux_proc_find_elf,
+      .find_debuginfo = dwfl_standard_find_debuginfo,
+    };
+    Dwfl *_dwfl = dwfl_begin (&callbacks);
+    g_mutex_init (&_dwfl_mutex);
+    g_once_init_leave (&_global_dwfl, _dwfl);
+  }
+
+  return _global_dwfl;
+}
+
 #endif /* HAVE_DW */
 #endif /* HAVE_UNWIND */
 
@@ -156,9 +178,10 @@ static char *gst_info_printf_pointer_extension_func (const char *format,
 #endif /* HAVE_BACKTRACE */
 
 #ifdef HAVE_DBGHELP
-#include <Windows.h>
+#include <windows.h>
 #include <dbghelp.h>
 #include <tlhelp32.h>
+#include <gmodule.h>
 #endif /* HAVE_DBGHELP */
 
 #ifdef G_OS_WIN32
@@ -311,38 +334,8 @@ static gboolean add_default_log_func = TRUE;
 #define PRETTY_TAGS_DEFAULT  TRUE
 static gboolean pretty_tags = PRETTY_TAGS_DEFAULT;
 
-static volatile gint G_GNUC_MAY_ALIAS __default_level = GST_LEVEL_DEFAULT;
-static volatile gint G_GNUC_MAY_ALIAS __use_color = GST_DEBUG_COLOR_MODE_ON;
-
-/* FIXME: export this? */
-gboolean
-_priv_gst_in_valgrind (void)
-{
-  static enum
-  {
-    GST_VG_UNCHECKED,
-    GST_VG_NO_VALGRIND,
-    GST_VG_INSIDE
-  }
-  in_valgrind = GST_VG_UNCHECKED;
-
-  if (in_valgrind == GST_VG_UNCHECKED) {
-#ifdef HAVE_VALGRIND_VALGRIND_H
-    if (RUNNING_ON_VALGRIND) {
-      GST_CAT_INFO (GST_CAT_GST_INIT, "we're running inside valgrind");
-      in_valgrind = GST_VG_INSIDE;
-    } else {
-      GST_CAT_LOG (GST_CAT_GST_INIT, "not doing extra valgrind stuff");
-      in_valgrind = GST_VG_NO_VALGRIND;
-    }
-#else
-    in_valgrind = GST_VG_NO_VALGRIND;
-#endif
-    g_assert (in_valgrind == GST_VG_NO_VALGRIND ||
-        in_valgrind == GST_VG_INSIDE);
-  }
-  return (in_valgrind == GST_VG_INSIDE);
-}
+static gint G_GNUC_MAY_ALIAS __default_level = GST_LEVEL_DEFAULT;
+static gint G_GNUC_MAY_ALIAS __use_color = GST_DEBUG_COLOR_MODE_ON;
 
 static gchar *
 _replace_pattern_in_gst_debug_file_name (gchar * name, const char *token,
@@ -472,9 +465,6 @@ _priv_gst_debug_init (void)
   _priv_GST_CAT_PROTECTION =
       _gst_debug_category_new ("GST_PROTECTION", 0, "protection");
 
-  /* print out the valgrind message if we're in valgrind */
-  _priv_gst_in_valgrind ();
-
   env = g_getenv ("GST_DEBUG_OPTIONS");
   if (env != NULL) {
     if (strstr (env, "full_tags") || strstr (env, "full-tags"))
@@ -572,6 +562,10 @@ gst_debug_log_valist (GstDebugCategory * category, GstDebugLevel level,
 
   g_return_if_fail (category != NULL);
 
+#ifdef GST_ENABLE_EXTRA_CHECKS
+  g_warn_if_fail (object == NULL || G_IS_OBJECT (object));
+#endif
+
   if (level > gst_debug_category_get_threshold (category))
     return;
 
@@ -969,6 +963,16 @@ gst_info_printf_pointer_extension_func (const char *format, void *ptr)
       case 'B':                /* GST_SEGMENT_FORMAT */
         s = gst_debug_print_segment (ptr);
         break;
+      case 'T':                /* GST_TIMEP_FORMAT */
+        if (ptr)
+          s = g_strdup_printf ("%" GST_TIME_FORMAT,
+              GST_TIME_ARGS (*(GstClockTime *) ptr));
+        break;
+      case 'S':                /* GST_STIMEP_FORMAT */
+        if (ptr)
+          s = g_strdup_printf ("%" GST_STIME_FORMAT,
+              GST_STIME_ARGS (*(gint64 *) ptr));
+        break;
       case 'a':                /* GST_WRAPPED_PTR_FORMAT */
         s = priv_gst_string_take_and_wrap (gst_debug_print_object (ptr));
         break;
@@ -1089,6 +1093,7 @@ gst_debug_construct_win_color (guint colorinfo)
 #endif
 #define PID_FMT "%5d"
 #define CAT_FMT "%20s %s:%d:%s:%s"
+#define NOCOLOR_PRINT_FMT " "PID_FMT" "PTR_FMT" %s "CAT_FMT" %s\n"
 
 #ifdef G_OS_WIN32
 static const guchar levelcolormap_w32[GST_LEVEL_COUNT] = {
@@ -1133,6 +1138,122 @@ static const gchar *levelcolormap[GST_LEVEL_COUNT] = {
   "\033[37m"                    /* GST_LEVEL_MEMDUMP */
 };
 
+static void
+_gst_debug_log_preamble (GstDebugMessage * message, GObject * object,
+    const gchar ** file, const gchar ** message_str, gchar ** obj_str,
+    GstClockTime * elapsed)
+{
+  gchar c;
+
+  /* Get message string first because printing it might call into our custom
+   * printf format extension mechanism which in turn might log something, e.g.
+   * from inside gst_structure_to_string() when something can't be serialised.
+   * This means we either need to do this outside of any critical section or
+   * use a recursive lock instead. As we always need the message string in all
+   * code paths, we might just as well get it here first thing and outside of
+   * the win_print_mutex critical section. */
+  *message_str = gst_debug_message_get (message);
+
+  /* __FILE__ might be a file name or an absolute path or a
+   * relative path, irrespective of the exact compiler used,
+   * in which case we want to shorten it to the filename for
+   * readability. */
+  c = (*file)[0];
+  if (c == '.' || c == '/' || c == '\\' || (c != '\0' && (*file)[1] == ':')) {
+    *file = gst_path_basename (*file);
+  }
+
+  if (object) {
+    *obj_str = gst_debug_print_object (object);
+  } else {
+    *obj_str = (gchar *) "";
+  }
+
+  *elapsed = GST_CLOCK_DIFF (_priv_gst_start_time, gst_util_get_timestamp ());
+}
+
+/**
+ * gst_debug_log_get_line:
+ * @category: category to log
+ * @level: level of the message
+ * @file: the file that emitted the message, usually the __FILE__ identifier
+ * @function: the function that emitted the message
+ * @line: the line from that the message was emitted, usually __LINE__
+ * @object: (transfer none) (allow-none): the object this message relates to,
+ *     or %NULL if none
+ * @message: the actual message
+ *
+ * Returns the string representation for the specified debug log message
+ * formatted in the same way as gst_debug_log_default() (the default handler),
+ * without color. The purpose is to make it easy for custom log output
+ * handlers to get a log output that is identical to what the default handler
+ * would write out.
+ *
+ * Since: 1.18
+ */
+gchar *
+gst_debug_log_get_line (GstDebugCategory * category, GstDebugLevel level,
+    const gchar * file, const gchar * function, gint line,
+    GObject * object, GstDebugMessage * message)
+{
+  GstClockTime elapsed;
+  gchar *ret, *obj_str = NULL;
+  const gchar *message_str;
+
+#ifdef GST_ENABLE_EXTRA_CHECKS
+  g_warn_if_fail (object == NULL || G_IS_OBJECT (object));
+#endif
+
+  _gst_debug_log_preamble (message, object, &file, &message_str, &obj_str,
+      &elapsed);
+
+  ret = g_strdup_printf ("%" GST_TIME_FORMAT NOCOLOR_PRINT_FMT,
+      GST_TIME_ARGS (elapsed), getpid (), g_thread_self (),
+      gst_debug_level_get_name (level), gst_debug_category_get_name
+      (category), file, line, function, obj_str, message_str);
+
+  if (object != NULL)
+    g_free (obj_str);
+  return ret;
+}
+
+#ifdef G_OS_WIN32
+static void
+_gst_debug_fprintf (FILE * file, const gchar * format, ...)
+{
+  va_list args;
+  gchar *str = NULL;
+  gint length;
+
+  va_start (args, format);
+  length = gst_info_vasprintf (&str, format, args);
+  va_end (args);
+
+  if (length == 0 || !str)
+    return;
+
+  /* Even if it's valid UTF-8 string, console might print broken string
+   * depending on codepage and the content of the given string.
+   * Fortunately, g_print* family will take care of the Windows' codepage
+   * specific behavior.
+   */
+  if (file == stderr) {
+    g_printerr ("%s", str);
+  } else if (file == stdout) {
+    g_print ("%s", str);
+  } else {
+    /* We are writing to file. Text editors/viewers should be able to
+     * decode valid UTF-8 string regardless of codepage setting */
+    fwrite (str, 1, length, file);
+
+    /* FIXME: fflush here might be redundant if setvbuf works as expected */
+    fflush (file);
+  }
+
+  g_free (str);
+}
+#endif
+
 /**
  * gst_debug_log_default:
  * @category: category to log
@@ -1168,37 +1289,27 @@ gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level,
 #if defined(G_OS_WIN32) || !defined(USE_DLOG)
   FILE *log_file = user_data ? user_data : stderr;
 #endif
-  gchar c;
+#ifdef G_OS_WIN32
+#define FPRINTF_DEBUG _gst_debug_fprintf
+/* _gst_debug_fprintf will do fflush if it's required */
+#define FFLUSH_DEBUG(f) ((void)(f))
+#else
+#define FPRINTF_DEBUG fprintf
+#define FFLUSH_DEBUG(f) G_STMT_START { \
+    fflush (f); \
+  } G_STMT_END
+#endif
 
-  /* Get message string first because printing it might call into our custom
-   * printf format extension mechanism which in turn might log something, e.g.
-   * from inside gst_structure_to_string() when something can't be serialised.
-   * This means we either need to do this outside of any critical section or
-   * use a recursive lock instead. As we always need the message string in all
-   * code paths, we might just as well get it here first thing and outside of
-   * the win_print_mutex critical section. */
-  message_str = gst_debug_message_get (message);
+#ifdef GST_ENABLE_EXTRA_CHECKS
+  g_warn_if_fail (object == NULL || G_IS_OBJECT (object));
+#endif
 
-  /* __FILE__ might be a file name or an absolute path or a
-   * relative path, irrespective of the exact compiler used,
-   * in which case we want to shorten it to the filename for
-   * readability. */
-  c = file[0];
-  if (c == '.' || c == '/' || c == '\\' || (c != '\0' && file[1] == ':')) {
-    file = gst_path_basename (file);
-  }
+  _gst_debug_log_preamble (message, object, &file, &message_str, &obj,
+      &elapsed);
 
   pid = getpid ();
   color_mode = gst_debug_get_color_mode ();
 
-  if (object) {
-    obj = gst_debug_print_object (object);
-  } else {
-    obj = (gchar *) "";
-  }
-
-  elapsed = GST_CLOCK_DIFF (_priv_gst_start_time, gst_util_get_timestamp ());
-
   if (color_mode != GST_DEBUG_COLOR_MODE_OFF) {
 #ifdef G_OS_WIN32
     G_LOCK (win_print_mutex);
@@ -1213,11 +1324,10 @@ gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level,
       color = gst_debug_construct_term_color (gst_debug_category_get_color
           (category));
       clear = "\033[00m";
-      g_sprintf (pidcolor, "\033[3%1dm", pid % 6 + 31);
+      g_sprintf (pidcolor, "\033[%02dm", pid % 6 + 31);
       levelcolor = levelcolormap[level];
 
 #define PRINT_FMT " %s"PID_FMT"%s "PTR_FMT" %s%s%s %s"CAT_FMT"%s %s\n"
-
 #if defined(USE_DLOG)
     GST_SLOGW("%" GST_TIME_FORMAT "%s "PTR_FMT" %s%s%s %s"CAT_FMT"%s %s\n", GST_TIME_ARGS (elapsed),
         clear, g_thread_self (), levelcolor,
@@ -1225,14 +1335,13 @@ gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level,
         gst_debug_category_get_name (category), file, line, function, obj,
         clear, message_str);
 #else
-      fprintf (log_file, "%" GST_TIME_FORMAT PRINT_FMT, GST_TIME_ARGS (elapsed),
-          pidcolor, pid, clear, g_thread_self (), levelcolor,
-          gst_debug_level_get_name (level), clear, color,
+      FPRINTF_DEBUG (log_file, "%" GST_TIME_FORMAT PRINT_FMT,
+          GST_TIME_ARGS (elapsed), pidcolor, pid, clear, g_thread_self (),
+          levelcolor, gst_debug_level_get_name (level), clear, color,
           gst_debug_category_get_name (category), file, line, function, obj,
           clear, message_str);
-      fflush (log_file);
+      FFLUSH_DEBUG (log_file);
 #endif
-
 #undef PRINT_FMT
       g_free (color);
 #ifdef G_OS_WIN32
@@ -1244,52 +1353,43 @@ gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level,
     SetConsoleTextAttribute (GetStdHandle (STD_ERROR_HANDLE), (c)); \
   } G_STMT_END
       /* timestamp */
-      fprintf (log_file, "%" GST_TIME_FORMAT " ", GST_TIME_ARGS (elapsed));
-      fflush (log_file);
+      FPRINTF_DEBUG (log_file, "%" GST_TIME_FORMAT " ",
+          GST_TIME_ARGS (elapsed));
       /* pid */
       SET_COLOR (available_colors[pid % G_N_ELEMENTS (available_colors)]);
-      fprintf (log_file, PID_FMT, pid);
-      fflush (log_file);
+      FPRINTF_DEBUG (log_file, PID_FMT, pid);
       /* thread */
       SET_COLOR (clear);
-      fprintf (log_file, " " PTR_FMT " ", g_thread_self ());
-      fflush (log_file);
+      FPRINTF_DEBUG (log_file, " " PTR_FMT " ", g_thread_self ());
       /* level */
       SET_COLOR (levelcolormap_w32[level]);
-      fprintf (log_file, "%s ", gst_debug_level_get_name (level));
-      fflush (log_file);
+      FPRINTF_DEBUG (log_file, "%s ", gst_debug_level_get_name (level));
       /* category */
       SET_COLOR (gst_debug_construct_win_color (gst_debug_category_get_color
               (category)));
-      fprintf (log_file, CAT_FMT, gst_debug_category_get_name (category),
+      FPRINTF_DEBUG (log_file, CAT_FMT, gst_debug_category_get_name (category),
           file, line, function, obj);
-      fflush (log_file);
       /* message */
       SET_COLOR (clear);
-      fprintf (log_file, " %s\n", message_str);
-      fflush (log_file);
+      FPRINTF_DEBUG (log_file, " %s\n", message_str);
     }
     G_UNLOCK (win_print_mutex);
 #endif
   } else {
     /* no color, all platforms */
-#define PRINT_FMT " "PID_FMT" "PTR_FMT" %s "CAT_FMT" %s\n"
-
-    /* Tizen doesn't care about Win32 */
 #if defined(USE_DLOG) && !defined(G_OS_WIN32)
     GST_SLOGW("%" GST_TIME_FORMAT " "PTR_FMT" %s "CAT_FMT" %s\n", GST_TIME_ARGS (elapsed),
         g_thread_self (), gst_debug_level_get_name (level),
         gst_debug_category_get_name (category), file, line, function, obj,
         message_str);
 #else
-    fprintf (log_file, "%" GST_TIME_FORMAT PRINT_FMT, GST_TIME_ARGS (elapsed),
-        pid, g_thread_self (), gst_debug_level_get_name (level),
+    FPRINTF_DEBUG (log_file, "%" GST_TIME_FORMAT NOCOLOR_PRINT_FMT,
+        GST_TIME_ARGS (elapsed), pid, g_thread_self (),
+        gst_debug_level_get_name (level),
         gst_debug_category_get_name (category), file, line, function, obj,
         message_str);
-    fflush (log_file);
+    FFLUSH_DEBUG (log_file);
 #endif
-
-#undef PRINT_FMT
   }
 
   if (object != NULL)
@@ -1781,27 +1881,20 @@ _gst_debug_category_new (const gchar * name, guint color,
   return cat;
 }
 
+#ifndef GST_REMOVE_DEPRECATED
 /**
  * gst_debug_category_free:
  * @category: #GstDebugCategory to free.
  *
  * Removes and frees the category and all associated resources.
+ *
+ * Deprecated: This function can easily cause memory corruption, don't use it.
  */
 void
 gst_debug_category_free (GstDebugCategory * category)
 {
-  if (category == NULL)
-    return;
-
-  /* remove from category list */
-  g_mutex_lock (&__cat_mutex);
-  __categories = g_slist_remove (__categories, category);
-  g_mutex_unlock (&__cat_mutex);
-
-  g_free ((gpointer) category->name);
-  g_free ((gpointer) category->description);
-  g_slice_free (GstDebugCategory, category);
 }
+#endif
 
 /**
  * gst_debug_category_set_threshold:
@@ -2143,6 +2236,35 @@ _priv_gst_debug_cleanup (void)
   }
 
   g_mutex_unlock (&__dbg_functions_mutex);
+
+  g_mutex_lock (&__cat_mutex);
+  while (__categories) {
+    GstDebugCategory *cat = __categories->data;
+    g_free ((gpointer) cat->name);
+    g_free ((gpointer) cat->description);
+    g_slice_free (GstDebugCategory, cat);
+    __categories = g_slist_delete_link (__categories, __categories);
+  }
+  g_mutex_unlock (&__cat_mutex);
+
+  g_mutex_lock (&__level_name_mutex);
+  while (__level_name) {
+    LevelNameEntry *level_name_entry = __level_name->data;
+    g_pattern_spec_free (level_name_entry->pat);
+    g_slice_free (LevelNameEntry, level_name_entry);
+    __level_name = g_slist_delete_link (__level_name, __level_name);
+  }
+  g_mutex_unlock (&__level_name_mutex);
+
+  g_mutex_lock (&__log_func_mutex);
+  while (__log_functions) {
+    LogFuncEntry *log_func_entry = __log_functions->data;
+    if (log_func_entry->notify)
+      log_func_entry->notify (log_func_entry->user_data);
+    g_slice_free (LogFuncEntry, log_func_entry);
+    __log_functions = g_slist_delete_link (__log_functions, __log_functions);
+  }
+  g_mutex_unlock (&__log_func_mutex);
 }
 
 static void
@@ -2265,6 +2387,8 @@ void
 gst_debug_add_log_function (GstLogFunction func, gpointer user_data,
     GDestroyNotify notify)
 {
+  if (notify)
+    notify (user_data);
 }
 
 guint
@@ -2343,10 +2467,12 @@ gst_debug_unset_threshold_for_name (const gchar * name)
 {
 }
 
+#ifndef GST_REMOVE_DEPRECATED
 void
 gst_debug_category_free (GstDebugCategory * category)
 {
 }
+#endif
 
 void
 gst_debug_category_set_threshold (GstDebugCategory * category,
@@ -2407,12 +2533,6 @@ gst_debug_construct_win_color (guint colorinfo)
   return 0;
 }
 
-gboolean
-_priv_gst_in_valgrind (void)
-{
-  return FALSE;
-}
-
 void
 _gst_debug_dump_mem (GstDebugCategory * cat, const gchar * file,
     const gchar * func, gint line, GObject * obj, const gchar * msg,
@@ -2729,12 +2849,6 @@ append_debug_info (GString * trace, Dwfl * dwfl, const void *ip)
   Dwfl_Module *module;
   const gchar *function_name;
 
-  if (dwfl_linux_proc_report (dwfl, getpid ()) != 0)
-    return FALSE;
-
-  if (dwfl_report_end (dwfl, NULL, NULL))
-    return FALSE;
-
   addr = (uintptr_t) ip;
   module = dwfl_addrmodule (dwfl, addr);
   function_name = dwfl_module_addrname (module, addr);
@@ -2772,13 +2886,15 @@ generate_unwind_trace (GstStackTraceFlags flags)
 
 #ifdef HAVE_DW
   Dwfl *dwfl = NULL;
-  Dwfl_Callbacks callbacks = {
-    .find_elf = dwfl_linux_proc_find_elf,
-    .find_debuginfo = dwfl_standard_find_debuginfo,
-  };
 
-  if ((flags & GST_STACK_TRACE_SHOW_FULL))
-    dwfl = dwfl_begin (&callbacks);
+  if ((flags & GST_STACK_TRACE_SHOW_FULL)) {
+    dwfl = get_global_dwfl ();
+    if (G_UNLIKELY (dwfl == NULL)) {
+      GST_WARNING ("Failed to initialize dwlf");
+      goto done;
+    }
+    GST_DWFL_LOCK ();
+  }
 #endif /* HAVE_DW */
 
   unret = unw_getcontext (&uc);
@@ -2793,6 +2909,12 @@ generate_unwind_trace (GstStackTraceFlags flags)
 
     goto done;
   }
+#ifdef HAVE_DW
+  /* Due to plugins being loaded, mapping of process might have changed,
+   * so always scan it. */
+  if (dwfl_linux_proc_report (dwfl, getpid ()) != 0)
+    goto done;
+#endif
 
   while (unw_step (&cursor) > 0) {
 #ifdef HAVE_DW
@@ -2801,7 +2923,7 @@ generate_unwind_trace (GstStackTraceFlags flags)
 
       unret = unw_get_reg (&cursor, UNW_REG_IP, &ip);
       if (unret) {
-        GST_DEBUG ("libunwind could read frame info (%d)", unret);
+        GST_DEBUG ("libunwind could not read frame info (%d)", unret);
 
         goto done;
       }
@@ -2826,7 +2948,7 @@ generate_unwind_trace (GstStackTraceFlags flags)
 done:
 #ifdef HAVE_DW
   if (dwfl)
-    dwfl_end (dwfl);
+    GST_DWFL_UNLOCK ();
 #endif
 
   return g_string_free (trace, FALSE);
@@ -2863,19 +2985,91 @@ generate_backtrace_trace (void)
 #endif /* HAVE_BACKTRACE */
 
 #ifdef HAVE_DBGHELP
-static void
+/* *INDENT-OFF* */
+static struct
+{
+  DWORD (WINAPI * pSymSetOptions) (DWORD SymOptions);
+  BOOL  (WINAPI * pSymInitialize) (HANDLE hProcess,
+                                   PCSTR UserSearchPath,
+                                   BOOL fInvadeProcess);
+  BOOL  (WINAPI * pStackWalk64)   (DWORD MachineType,
+                                   HANDLE hProcess,
+                                   HANDLE hThread,
+                                   LPSTACKFRAME64 StackFrame,
+                                   PVOID ContextRecord,
+                                   PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
+                                   PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
+                                   PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
+                                   PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
+  PVOID (WINAPI * pSymFunctionTableAccess64) (HANDLE hProcess,
+                                              DWORD64 AddrBase);
+  DWORD64 (WINAPI * pSymGetModuleBase64) (HANDLE hProcess,
+                                          DWORD64 qwAddr);
+  BOOL (WINAPI * pSymFromAddr) (HANDLE hProcess,
+                                DWORD64 Address,
+                                PDWORD64 Displacement,
+                                PSYMBOL_INFO Symbol);
+  BOOL (WINAPI * pSymGetModuleInfo64) (HANDLE hProcess,
+                                       DWORD64 qwAddr,
+                                       PIMAGEHLP_MODULE64 ModuleInfo);
+  BOOL (WINAPI * pSymGetLineFromAddr64) (HANDLE hProcess,
+                                         DWORD64 qwAddr,
+                                         PDWORD pdwDisplacement,
+                                         PIMAGEHLP_LINE64 Line64);
+} dbg_help_vtable = { NULL,};
+/* *INDENT-ON* */
+
+static GModule *dbg_help_module = NULL;
+
+static gboolean
+dbghelp_load_symbol (const gchar * symbol_name, gpointer * symbol)
+{
+  if (dbg_help_module &&
+      !g_module_symbol (dbg_help_module, symbol_name, symbol)) {
+    GST_WARNING ("Cannot load %s symbol", symbol_name);
+    g_module_close (dbg_help_module);
+    dbg_help_module = NULL;
+  }
+
+  return ! !dbg_help_module;
+}
+
+static gboolean
 dbghelp_initialize_symbols (HANDLE process)
 {
   static gsize initialization_value = 0;
 
   if (g_once_init_enter (&initialization_value)) {
     GST_INFO ("Initializing Windows symbol handler");
-    SymSetOptions (SYMOPT_LOAD_LINES);
-    SymInitialize (process, NULL, TRUE);
-    GST_INFO ("Initialized Windows symbol handler");
+
+    dbg_help_module = g_module_open ("dbghelp.dll", G_MODULE_BIND_LAZY);
+    dbghelp_load_symbol ("SymSetOptions",
+        (gpointer *) & dbg_help_vtable.pSymSetOptions);
+    dbghelp_load_symbol ("SymInitialize",
+        (gpointer *) & dbg_help_vtable.pSymInitialize);
+    dbghelp_load_symbol ("StackWalk64",
+        (gpointer *) & dbg_help_vtable.pStackWalk64);
+    dbghelp_load_symbol ("SymFunctionTableAccess64",
+        (gpointer *) & dbg_help_vtable.pSymFunctionTableAccess64);
+    dbghelp_load_symbol ("SymGetModuleBase64",
+        (gpointer *) & dbg_help_vtable.pSymGetModuleBase64);
+    dbghelp_load_symbol ("SymFromAddr",
+        (gpointer *) & dbg_help_vtable.pSymFromAddr);
+    dbghelp_load_symbol ("SymGetModuleInfo64",
+        (gpointer *) & dbg_help_vtable.pSymGetModuleInfo64);
+    dbghelp_load_symbol ("SymGetLineFromAddr64",
+        (gpointer *) & dbg_help_vtable.pSymGetLineFromAddr64);
+
+    if (dbg_help_module) {
+      dbg_help_vtable.pSymSetOptions (SYMOPT_LOAD_LINES);
+      dbg_help_vtable.pSymInitialize (process, NULL, TRUE);
+      GST_INFO ("Initialized Windows symbol handler");
+    }
 
     g_once_init_leave (&initialization_value, 1);
   }
+
+  return ! !dbg_help_module;
 }
 
 static gchar *
@@ -2888,9 +3082,10 @@ generate_dbghelp_trace (void)
   CONTEXT context;
   STACKFRAME64 frame = { 0 };
   PVOID save_context;
-  GString *trace = g_string_new (NULL);
+  GString *trace = NULL;
 
-  dbghelp_initialize_symbols (process);
+  if (!dbghelp_initialize_symbols (process))
+    return NULL;
 
   memset (&context, 0, sizeof (CONTEXT));
   context.ContextFlags = CONTEXT_FULL;
@@ -2912,9 +3107,11 @@ generate_dbghelp_trace (void)
   frame.AddrPC.Offset = context.Rip;
   frame.AddrStack.Offset = context.Rsp;
 #else
-  goto done;
+  return NULL;
 #endif
 
+  trace = g_string_new (NULL);
+
   module_info.SizeOfStruct = sizeof (module_info);
   save_context = (machine == IMAGE_FILE_MACHINE_I386) ? NULL : &context;
 
@@ -2929,19 +3126,23 @@ generate_dbghelp_trace (void)
 
     line.SizeOfStruct = sizeof (line);
 
-    if (!StackWalk64 (machine, process, thread, &frame, save_context, 0,
-            SymFunctionTableAccess64, SymGetModuleBase64, 0))
+    if (!dbg_help_vtable.pStackWalk64 (machine, process, thread, &frame,
+            save_context, 0, dbg_help_vtable.pSymFunctionTableAccess64,
+            dbg_help_vtable.pSymGetModuleBase64, 0)) {
       break;
+    }
 
-    if (SymFromAddr (process, frame.AddrPC.Offset, 0, symbol))
+    if (dbg_help_vtable.pSymFromAddr (process, frame.AddrPC.Offset, 0, symbol))
       g_string_append_printf (trace, "%s ", symbol->Name);
     else
       g_string_append (trace, "?? ");
 
-    if (SymGetLineFromAddr64 (process, frame.AddrPC.Offset, &displacement,
-            &line))
-      g_string_append_printf (trace, "(%s:%u)", line.FileName, line.LineNumber);
-    else if (SymGetModuleInfo64 (process, frame.AddrPC.Offset, &module_info))
+    if (dbg_help_vtable.pSymGetLineFromAddr64 (process, frame.AddrPC.Offset,
+            &displacement, &line))
+      g_string_append_printf (trace, "(%s:%lu)", line.FileName,
+          line.LineNumber);
+    else if (dbg_help_vtable.pSymGetModuleInfo64 (process, frame.AddrPC.Offset,
+            &module_info))
       g_string_append_printf (trace, "(%s)", module_info.ImageName);
     else
       g_string_append_printf (trace, "(%s)", "??");
@@ -2949,15 +3150,14 @@ generate_dbghelp_trace (void)
     g_string_append (trace, "\n");
   }
 
-done:
   return g_string_free (trace, FALSE);
 }
 #endif /* HAVE_DBGHELP */
 
 /**
  * gst_debug_get_stack_trace:
- * @flags: A set of #GstStackTraceFlags to determine how the stack
- * trace should look like. Pass 0 to retrieve a minimal backtrace.
+ * @flags: A set of #GstStackTraceFlags to determine how the stack trace should
+ * look like. Pass #GST_STACK_TRACE_SHOW_NONE to retrieve a minimal backtrace.
  *
  * Returns: (nullable): a stack trace, if libunwind or glibc backtrace are
  * present, else %NULL.
@@ -2977,9 +3177,7 @@ gst_debug_get_stack_trace (GstStackTraceFlags flags)
 #ifdef HAVE_UNWIND
   if ((flags & GST_STACK_TRACE_SHOW_FULL) || !have_backtrace)
     trace = generate_unwind_trace (flags);
-#endif /* HAVE_UNWIND */
-
-#ifdef HAVE_DBGHELP
+#elif defined(HAVE_DBGHELP)
   trace = generate_dbghelp_trace ();
 #endif
 
index 2016d4e..9d8d7f9 100644 (file)
@@ -177,12 +177,17 @@ typedef enum { /*< flags >*/
 
 /**
  * GstStackTraceFlags:
- * @GST_STACK_TRACE_SHOW_FULL: Try to retrieve as much information as
- *                             possible when getting the stack trace
+ * @GST_STACK_TRACE_SHOW_NONE: Try to retrieve the minimum information
+ *                             available, which may be none on some platforms
+ *                             (Since: 1.18)
+ * @GST_STACK_TRACE_SHOW_FULL: Try to retrieve as much information as possible,
+ *                             including source information when getting the
+ *                             stack trace
  *
  * Since: 1.12
  */
 typedef enum {
+    GST_STACK_TRACE_SHOW_NONE = 0,
     GST_STACK_TRACE_SHOW_FULL = 1 << 0
 } GstStackTraceFlags;
 
@@ -297,6 +302,32 @@ struct _GstDebugCategory {
  */
 #define GST_SEGMENT_FORMAT "p\aB"
 
+/**
+ * GST_TIMEP_FORMAT: (skip):
+ *
+ * printf format type used to debug GStreamer ClockTime pointers. You can use
+ * this in combination with GStreamer's debug logging system as well as the
+ * functions gst_info_vasprintf(), gst_info_strdup_vprintf() and
+ * gst_info_strdup_printf() to pretty-print #GstClockTime pointers. This can
+ * only be used on pointers to GstClockTime values.
+ *
+ * Since: 1.18
+ */
+#define GST_TIMEP_FORMAT "p\aT"
+
+/**
+ * GST_STIMEP_FORMAT: (skip):
+ *
+ * printf format type used to debug GStreamer signed time value pointers. You
+ * can use this in combination with GStreamer's debug logging system as well as
+ * the functions gst_info_vasprintf(), gst_info_strdup_vprintf() and
+ * gst_info_strdup_printf() to pretty-print signed time (pointers to
+ * #GstClockTimeDiff or #gint64).
+ *
+ * Since: 1.18
+ */
+#define GST_STIMEP_FORMAT "p\aS"
+
 typedef struct _GstDebugMessage GstDebugMessage;
 
 /**
@@ -362,7 +393,9 @@ void _gst_debug_dump_mem (GstDebugCategory * cat, const gchar * file,
     const gchar * func, gint line, GObject * obj, const gchar * msg,
     const guint8 * data, guint length);
 
-/* we define this to avoid a compiler warning regarding a cast from a function
+/**
+ * GstDebugFuncPtr: (attributes doc.skip=true)
+ * we define this to avoid a compiler warning regarding a cast from a function
  * pointer to a void pointer
  * (see https://bugzilla.gnome.org/show_bug.cgi?id=309253)
  */
@@ -382,6 +415,15 @@ GST_API
 const gchar   * gst_debug_message_get    (GstDebugMessage  * message);
 
 GST_API
+gchar         * gst_debug_log_get_line    (GstDebugCategory * category,
+                                           GstDebugLevel      level,
+                                           const gchar      * file,
+                                           const gchar      * function,
+                                           gint               line,
+                                           GObject          * object,
+                                           GstDebugMessage  * message) G_GNUC_NO_INSTRUMENT;
+
+GST_API
 void            gst_debug_log_default    (GstDebugCategory * category,
                                           GstDebugLevel      level,
                                           const gchar      * file,
@@ -390,6 +432,7 @@ void            gst_debug_log_default    (GstDebugCategory * category,
                                           GObject          * object,
                                           GstDebugMessage  * message,
                                           gpointer           user_data) G_GNUC_NO_INSTRUMENT;
+
 GST_API
 const gchar *   gst_debug_level_get_name (GstDebugLevel level);
 
@@ -439,8 +482,7 @@ void            gst_debug_set_threshold_from_string  (const gchar * list, gboole
 GST_API
 void            gst_debug_unset_threshold_for_name   (const gchar * name);
 
-
-GST_API
+GST_DEPRECATED
 void            gst_debug_category_free              (GstDebugCategory *       category);
 
 GST_API
@@ -1485,7 +1527,9 @@ GST_TRACE (const char *format, ...)
 
 #define GST_DEBUG_CATEGORY_INIT(var,name,color,desc)   G_STMT_START{ }G_STMT_END
 #define GST_DEBUG_CATEGORY_GET(var,name)               G_STMT_START{ }G_STMT_END
+#ifndef GST_DISABLE_DEPRECATED
 #define gst_debug_category_free(category)              G_STMT_START{ }G_STMT_END
+#endif
 #define gst_debug_category_set_threshold(category,level) G_STMT_START{ }G_STMT_END
 #define gst_debug_category_reset_threshold(category)   G_STMT_START{ }G_STMT_END
 #define gst_debug_category_get_threshold(category)     (GST_LEVEL_NONE)
index e7e5875..82847bf 100644 (file)
@@ -212,7 +212,7 @@ static void
 gst_list_iterator_free (GstListIterator * it)
 {
   if (it->owner)
-    g_object_unref (it->owner);
+    gst_object_unref (it->owner);
 }
 
 /**
@@ -629,12 +629,7 @@ gst_iterator_fold (GstIterator * it, GstIteratorFoldFunction func,
 
 fold_done:
 
-#if GLIB_CHECK_VERSION (2, 48, 0)
   g_value_unset (&item);
-#else
-  if (item.g_type != 0)
-    g_value_unset (&item);
-#endif
 
   return result;
 }
index 2f53507..6305dd9 100644 (file)
@@ -283,9 +283,7 @@ GST_API
 gboolean                gst_iterator_find_custom        (GstIterator *it, GCompareFunc func,
                                                          GValue *elem, gpointer user_data);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstIterator, gst_iterator_free)
-#endif
 
 G_END_DECLS
 
index a68aa47..0eaf208 100644 (file)
@@ -67,6 +67,7 @@
 #include "config.h"
 #endif
 
+#define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 #include "gst_private.h"
 #include "gstmemory.h"
 
@@ -169,7 +170,7 @@ gst_memory_is_type (GstMemory * mem, const gchar * mem_type)
  *
  * Get the current @size, @offset and @maxsize of @mem.
  *
- * Returns: the current sizes of @mem
+ * Returns: the current size of @mem
  */
 gsize
 gst_memory_get_sizes (GstMemory * mem, gsize * offset, gsize * maxsize)
@@ -219,7 +220,7 @@ gst_memory_resize (GstMemory * mem, gssize offset, gsize size)
 /**
  * gst_memory_make_mapped:
  * @mem: (transfer full): a #GstMemory
- * @info: (out): pointer for info
+ * @info: (out caller-allocates): pointer for info
  * @flags: mapping flags
  *
  * Create a #GstMemory object that is mapped with @flags. If @mem is mappable
@@ -269,7 +270,7 @@ cannot_map:
 /**
  * gst_memory_map:
  * @mem: a #GstMemory
- * @info: (out): pointer for info
+ * @info: (out caller-allocates): pointer for info
  * @flags: mapping flags
  *
  * Fill @info with the pointer and sizes of the memory in @mem that can be
@@ -464,3 +465,29 @@ _priv_gst_memory_initialize (void)
 {
   _gst_memory_type = gst_memory_get_type ();
 }
+
+/**
+ * gst_memory_ref: (skip)
+ * @memory: The memory to refcount
+ *
+ * Increase the refcount of this memory.
+ *
+ * Returns: (transfer full): @memory (for convenience when doing assignments)
+ */
+GstMemory *
+gst_memory_ref (GstMemory * memory)
+{
+  return (GstMemory *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (memory));
+}
+
+/**
+ * gst_memory_unref: (skip)
+ * @memory: (transfer full): the memory to refcount
+ *
+ * Decrease the refcount of a memory, freeing it if the refcount reaches 0.
+ */
+void
+gst_memory_unref (GstMemory * memory)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (memory));
+}
index 40d4fc4..cf84de2 100644 (file)
@@ -47,11 +47,16 @@ typedef struct _GstAllocator GstAllocator;
  * @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.
+ * made when this memory needs to be shared between buffers. (DEPRECATED:
+ * do not use in new code, instead you should create a custom GstAllocator for
+ * memory pooling instead of relying on the GstBuffer they were originally
+ * attached to.)
  * @GST_MEMORY_FLAG_ZERO_PREFIXED: the memory prefix is filled with 0 bytes
  * @GST_MEMORY_FLAG_ZERO_PADDED: the memory padding is filled with 0 bytes
- * @GST_MEMORY_FLAG_PHYSICALLY_CONTIGUOUS: the memory is physically contiguous. (Since: 1.2)
- * @GST_MEMORY_FLAG_NOT_MAPPABLE: the memory can't be mapped via gst_memory_map() without any preconditions. (Since: 1.2)
+ * @GST_MEMORY_FLAG_PHYSICALLY_CONTIGUOUS: the memory is physically
+ * contiguous. (Since: 1.2)
+ * @GST_MEMORY_FLAG_NOT_MAPPABLE: the memory can't be mapped via
+ * gst_memory_map() without any preconditions. (Since: 1.2)
  * @GST_MEMORY_FLAG_LAST: first flag that can be used for custom purposes
  *
  * Flags for wrapped memory.
@@ -255,7 +260,7 @@ typedef gpointer    (*GstMemoryMapFullFunction)       (GstMemory *mem, GstMapInf
  * GstMemoryUnmapFunction:
  * @mem: a #GstMemory
  *
- * Return the pointer previously retrieved with gst_memory_map().
+ * Release the pointer previously retrieved with gst_memory_map().
  */
 typedef void        (*GstMemoryUnmapFunction)     (GstMemory *mem);
 
@@ -264,7 +269,7 @@ typedef void        (*GstMemoryUnmapFunction)     (GstMemory *mem);
  * @mem: a #GstMemory
  * @info: a #GstMapInfo
  *
- * Return the pointer previously retrieved with gst_memory_map() with @info.
+ * Release the pointer previously retrieved with gst_memory_map() with @info.
  */
 typedef void        (*GstMemoryUnmapFullFunction)     (GstMemory *mem, GstMapInfo * info);
 
@@ -318,32 +323,26 @@ void           gst_memory_init         (GstMemory *mem, GstMemoryFlags flags,
 GST_API
 gboolean       gst_memory_is_type      (GstMemory *mem, const gchar *mem_type);
 
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 /* refcounting */
-/**
- * gst_memory_ref:
- * @memory: The memory to refcount
- *
- * Increase the refcount of this memory.
- *
- * Returns: (transfer full): @memory (for convenience when doing assignments)
- */
 static inline GstMemory *
 gst_memory_ref (GstMemory * memory)
 {
   return (GstMemory *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (memory));
 }
 
-/**
- * gst_memory_unref:
- * @memory: (transfer full): the memory to refcount
- *
- * Decrease the refcount of an memory, freeing it if the refcount reaches 0.
- */
 static inline void
 gst_memory_unref (GstMemory * memory)
 {
   gst_mini_object_unref (GST_MINI_OBJECT_CAST (memory));
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+GstMemory *    gst_memory_ref   (GstMemory * memory);
+
+GST_API
+void           gst_memory_unref (GstMemory * memory);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 /* getting/setting memory properties */
 
@@ -382,13 +381,9 @@ GstMemory *    gst_memory_share        (GstMemory *mem, gssize offset, gssize si
 GST_API
 gboolean       gst_memory_is_span      (GstMemory *mem1, GstMemory *mem2, gsize *offset);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstMemory, gst_memory_unref)
-#endif
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAllocator, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index f72bd62..45d4f4f 100644 (file)
@@ -43,7 +43,7 @@
  * container using gst_element_post_message().
  */
 
-
+#define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 #include "gst_private.h"
 #include <string.h>             /* memcpy */
 #include "gsterror.h"
@@ -112,6 +112,7 @@ static GstMessageQuarks message_quarks[] = {
   {GST_MESSAGE_STREAM_COLLECTION, "stream-collection", 0},
   {GST_MESSAGE_STREAMS_SELECTED, "streams-selected", 0},
   {GST_MESSAGE_REDIRECT, "redirect", 0},
+  {GST_MESSAGE_INSTANT_RATE_REQUEST, "instant-rate-request", 0},
   {0, NULL, 0}
 };
 
@@ -2353,6 +2354,8 @@ gst_message_new_reset_time (GstObject * src, GstClockTime running_time)
   GstMessage *message;
   GstStructure *structure;
 
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (running_time), NULL);
+
   structure = gst_structure_new_id (GST_QUARK (MESSAGE_RESET_TIME),
       GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time, NULL);
   message = gst_message_new_custom (GST_MESSAGE_RESET_TIME, src, structure);
@@ -2435,6 +2438,7 @@ gst_message_set_group_id (GstMessage * message, guint group_id)
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_START);
   g_return_if_fail (gst_message_is_writable (message));
+  g_return_if_fail (group_id != GST_GROUP_ID_INVALID);
 
   structure = GST_MESSAGE_STRUCTURE (message);
   gst_structure_id_set (structure, GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id,
@@ -2468,6 +2472,8 @@ gst_message_parse_group_id (GstMessage * message, guint * group_id)
   if (!group_id)
     return TRUE;
 
+  *group_id = 0;
+
   structure = GST_MESSAGE_STRUCTURE (message);
 
   v = gst_structure_id_get_value (structure, GST_QUARK (GROUP_ID));
@@ -3050,8 +3056,8 @@ gst_message_parse_streams_selected (GstMessage * message,
  * such as bitrate statistics for the given location.
  *
  * By default, message recipients should treat entries in the order they are
- * stored. The recipient should therefore try entry #0 first, and if this
- * entry is not acceptable or working, try entry #1 etc. Senders must make
+ * stored. The recipient should therefore try entry \#0 first, and if this
+ * entry is not acceptable or working, try entry \#1 etc. Senders must make
  * sure that they add entries in this order. However, recipients are free to
  * ignore the order and pick an entry that is "best" for them. One example
  * would be a recipient that scans the entries for the one with the highest
@@ -3266,3 +3272,168 @@ gst_message_get_num_redirect_entries (GstMessage * message)
 
   return size;
 }
+
+/**
+ * gst_message_new_instant_rate_request:
+ * @src: The #GstObject that posted the message
+ * @rate_multiplier: the rate multiplier factor that should be applied
+ *
+ * Creates a new instant-rate-request message. Elements handling the
+ * instant-rate-change event must post this message. The message is
+ * handled at the pipeline, and allows the pipeline to select the
+ * running time when the rate change should happen and to send an
+ * @GST_EVENT_INSTANT_RATE_SYNC_TIME event to notify the elements
+ * in the pipeline.
+ *
+ * Returns: a newly allocated #GstMessage
+ *
+ * Since: 1.18
+ */
+GstMessage *
+gst_message_new_instant_rate_request (GstObject * src, gdouble rate_multiplier)
+{
+  GstStructure *structure;
+  GstMessage *message;
+
+  g_return_val_if_fail (rate_multiplier != 0.0, NULL);
+
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_INSTANT_RATE_REQUEST),
+      GST_QUARK (RATE), G_TYPE_DOUBLE, rate_multiplier, NULL);
+  message =
+      gst_message_new_custom (GST_MESSAGE_INSTANT_RATE_REQUEST, src, structure);
+
+  return message;
+}
+
+/**
+ * gst_message_parse_instant_rate_request:
+ * @message: a #GstMessage of type %GST_MESSAGE_INSTANT_RATE_REQUEST
+ * @rate_multiplier: (out) (allow-none): return location for the rate, or %NULL
+ *
+ * Parses the rate_multiplier from the instant-rate-request message.
+ *
+ * Since: 1.18
+ */
+void
+gst_message_parse_instant_rate_request (GstMessage * message,
+    gdouble * rate_multiplier)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) ==
+      GST_MESSAGE_INSTANT_RATE_REQUEST);
+
+  structure = GST_MESSAGE_STRUCTURE (message);
+  gst_structure_id_get (structure, GST_QUARK (RATE), G_TYPE_DOUBLE,
+      rate_multiplier, NULL);
+}
+
+/**
+ * gst_message_ref: (skip)
+ * @msg: the message to ref
+ *
+ * Convenience macro to increase the reference count of the message.
+ *
+ * Returns: @msg (for convenience when doing assignments)
+ */
+GstMessage *
+gst_message_ref (GstMessage * msg)
+{
+  return (GstMessage *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (msg));
+}
+
+/**
+ * gst_message_unref: (skip)
+ * @msg: the message to unref
+ *
+ * Convenience macro to decrease the reference count of the message, possibly
+ * freeing it.
+ */
+void
+gst_message_unref (GstMessage * msg)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (msg));
+}
+
+/**
+ * gst_clear_message: (skip)
+ * @msg_ptr: a pointer to a #GstMessage reference
+ *
+ * Clears a reference to a #GstMessage.
+ *
+ * @msg_ptr must not be %NULL.
+ *
+ * If the reference is %NULL then this function does nothing. Otherwise, the
+ * reference count of the message is decreased and the pointer is set to %NULL.
+ *
+ * Since: 1.16
+ */
+void
+gst_clear_message (GstMessage ** msg_ptr)
+{
+  gst_clear_mini_object ((GstMiniObject **) msg_ptr);
+}
+
+/**
+ * gst_message_copy: (skip)
+ * @msg: the message to copy
+ *
+ * Creates a copy of the message. Returns a copy of the message.
+ *
+ * Returns: (transfer full): a new copy of @msg.
+ *
+ * MT safe
+ */
+GstMessage *
+gst_message_copy (const GstMessage * msg)
+{
+  return
+      GST_MESSAGE_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST
+          (msg)));
+}
+
+/**
+ * gst_message_replace: (skip)
+ * @old_message: (inout) (transfer full) (nullable): 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
+ */
+gboolean
+gst_message_replace (GstMessage ** old_message, GstMessage * new_message)
+{
+  return gst_mini_object_replace ((GstMiniObject **) old_message,
+      (GstMiniObject *) new_message);
+}
+
+/**
+ * gst_message_take:
+ * @old_message: (inout) (transfer full): pointer to a pointer to a #GstMessage
+ *     to be replaced.
+ * @new_message: (transfer full) (allow-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. This
+ * function is similar to gst_message_replace() except that it takes ownership
+ * of @new_message.
+ *
+ * Returns: %TRUE if @new_message was different from @old_message
+ *
+ * Since: 1.16
+ */
+gboolean
+gst_message_take (GstMessage ** old_message, GstMessage * new_message)
+{
+  return gst_mini_object_take ((GstMiniObject **) old_message,
+      (GstMiniObject *) new_message);
+}
index d5bc2a9..ea3f49f 100644 (file)
@@ -37,7 +37,9 @@ typedef struct _GstMessage GstMessage;
  * flushing seek in the pipeline, which will undo the EOS state again.
  * @GST_MESSAGE_ERROR: an error occurred. When the application receives an error
  * message it should stop playback of the pipeline and not assume that more
- * data will be played.
+ * data will be played. It is possible to specify a redirection url to the error
+ * messages by setting a `redirect-location` field into the error message, application
+ * or high level bins might use the information as required.
  * @GST_MESSAGE_WARNING: a warning occurred.
  * @GST_MESSAGE_INFO: an info message occurred
  * @GST_MESSAGE_TAG: a tag was found.
@@ -121,6 +123,9 @@ typedef struct _GstMessage GstMessage;
  *     response is received with a non-HTTP URL inside. (Since: 1.10)
  * @GST_MESSAGE_DEVICE_CHANGED: Message indicating a #GstDevice was changed
  *     a #GstDeviceProvider (Since: 1.16)
+ * @GST_MESSAGE_INSTANT_RATE_REQUEST: Message sent by elements to request the
+ *     running time from the pipeline when an instant rate change should
+ *     be applied (which may be in the past when the answer arrives). (Since: 1.18)
  * @GST_MESSAGE_ANY: mask for all of the above messages.
  *
  * The different message types that are available.
@@ -174,6 +179,7 @@ typedef enum
   GST_MESSAGE_STREAMS_SELECTED  = GST_MESSAGE_EXTENDED + 5,
   GST_MESSAGE_REDIRECT          = GST_MESSAGE_EXTENDED + 6,
   GST_MESSAGE_DEVICE_CHANGED    = GST_MESSAGE_EXTENDED + 7,
+  GST_MESSAGE_INSTANT_RATE_REQUEST = GST_MESSAGE_EXTENDED + 8,
   GST_MESSAGE_ANY               = (gint) (0xffffffff)
 } GstMessageType;
 
@@ -354,47 +360,20 @@ const gchar*    gst_message_type_get_name       (GstMessageType type);
 GST_API
 GQuark          gst_message_type_to_quark       (GstMessageType type);
 
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 /* refcounting */
-/**
- * gst_message_ref:
- * @msg: the message to ref
- *
- * Convenience macro to increase the reference count of the message.
- *
- * Returns: @msg (for convenience when doing assignments)
- */
 static inline GstMessage *
 gst_message_ref (GstMessage * msg)
 {
   return (GstMessage *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (msg));
 }
 
-/**
- * gst_message_unref:
- * @msg: the message to unref
- *
- * Convenience macro to decrease the reference count of the message, possibly
- * freeing it.
- */
 static inline void
 gst_message_unref (GstMessage * msg)
 {
   gst_mini_object_unref (GST_MINI_OBJECT_CAST (msg));
 }
 
-/**
- * gst_clear_message: (skip)
- * @msg_ptr: a pointer to a #GstMessage reference
- *
- * Clears a reference to a #GstMessage.
- *
- * @msg_ptr must not be %NULL.
- *
- * If the reference is %NULL then this function does nothing. Otherwise, the
- * reference count of the message is decreased and the pointer is set to %NULL.
- *
- * Since: 1.16
- */
 static inline void
 gst_clear_message (GstMessage ** msg_ptr)
 {
@@ -402,21 +381,25 @@ gst_clear_message (GstMessage ** msg_ptr)
 }
 
 /* copy message */
-/**
- * gst_message_copy:
- * @msg: the message to copy
- *
- * Creates a copy of the message. Returns a copy of the message.
- *
- * Returns: (transfer full): a new copy of @msg.
- *
- * MT safe
- */
+static inline GstMessage * gst_message_copy (const GstMessage * msg);
 static inline GstMessage *
 gst_message_copy (const GstMessage * msg)
 {
   return GST_MESSAGE_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (msg)));
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+GstMessage *  gst_message_ref   (GstMessage * msg);
+
+GST_API
+void          gst_message_unref (GstMessage * msg);
+
+GST_API
+void          gst_clear_message (GstMessage ** msg_ptr);
+
+GST_API
+GstMessage *  gst_message_copy  (const GstMessage * msg);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 /**
  * gst_message_is_writable:
@@ -438,50 +421,30 @@ 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) (nullable): 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
- */
+
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
+static inline gboolean gst_message_replace (GstMessage **old_message, GstMessage *new_message);
 static inline gboolean
 gst_message_replace (GstMessage **old_message, GstMessage *new_message)
 {
   return gst_mini_object_replace ((GstMiniObject **) old_message, (GstMiniObject *) new_message);
 }
 
-/**
- * gst_message_take:
- * @old_message: (inout) (transfer full): pointer to a pointer to a #GstMessage
- *     to be replaced.
- * @new_message: (transfer full) (allow-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. This
- * function is similar to gst_message_replace() except that it takes ownership
- * of @new_message.
- *
- * Returns: %TRUE if @new_message was different from @old_message
- *
- * Since: 1.16
- */
 static inline gboolean
 gst_message_take (GstMessage **old_message, GstMessage *new_message)
 {
   return gst_mini_object_take ((GstMiniObject **) old_message,
       (GstMiniObject *) new_message);
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+gboolean  gst_message_replace                   (GstMessage ** old_message,
+                                                 GstMessage * new_message);
 
+GST_API
+gboolean  gst_message_take                      (GstMessage ** old_message,
+                                                 GstMessage * new_message);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 /* custom messages */
 
@@ -865,9 +828,14 @@ void            gst_message_parse_redirect_entry     (GstMessage * message, gsiz
 GST_API
 gsize           gst_message_get_num_redirect_entries (GstMessage * message);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
+/* INSTANT_RATE_REQUEST */
+
+GST_API
+GstMessage *    gst_message_new_instant_rate_request   (GstObject * src, gdouble rate_multiplier) G_GNUC_MALLOC;
+GST_API
+void            gst_message_parse_instant_rate_request (GstMessage * message, gdouble * rate_multiplier);
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstMessage, gst_message_unref)
-#endif
 
 G_END_DECLS
 
index 4bcaa7a..fc86956 100644 (file)
@@ -50,6 +50,7 @@
 #include "gstmeta.h"
 #include "gstinfo.h"
 #include "gstutils.h"
+#include "gstquark.h"
 
 static GHashTable *metainfo = NULL;
 static GRWLock lock;
@@ -57,16 +58,60 @@ static GRWLock lock;
 GQuark _gst_meta_transform_copy;
 GQuark _gst_meta_tag_memory;
 
+typedef struct
+{
+  GstCustomMeta meta;
+
+  GstStructure *structure;
+} GstCustomMetaImpl;
+
+typedef struct
+{
+  GstMetaInfo info;
+  GstCustomMetaTransformFunction custom_transform_func;
+  gpointer custom_transform_user_data;
+  GDestroyNotify custom_transform_destroy_notify;
+  gboolean is_custom;
+} GstMetaInfoImpl;
+
+static void
+free_info (gpointer data)
+{
+  g_slice_free (GstMetaInfoImpl, data);
+}
+
 void
 _priv_gst_meta_initialize (void)
 {
   g_rw_lock_init (&lock);
-  metainfo = g_hash_table_new (g_str_hash, g_str_equal);
+  metainfo = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_info);
 
   _gst_meta_transform_copy = g_quark_from_static_string ("gst-copy");
   _gst_meta_tag_memory = g_quark_from_static_string ("memory");
 }
 
+static gboolean
+notify_custom (gchar * key, GstMetaInfo * info, gpointer unused)
+{
+  GstMetaInfoImpl *impl = (GstMetaInfoImpl *) info;
+
+  if (impl->is_custom) {
+    if (impl->custom_transform_destroy_notify)
+      impl->custom_transform_destroy_notify (impl->custom_transform_user_data);
+  }
+  return TRUE;
+}
+
+void
+_priv_gst_meta_cleanup (void)
+{
+  if (metainfo != NULL) {
+    g_hash_table_foreach_remove (metainfo, (GHRFunc) notify_custom, NULL);
+    g_hash_table_unref (metainfo);
+    metainfo = NULL;
+  }
+}
+
 /**
  * gst_meta_api_type_register:
  * @api: an API to register
@@ -98,12 +143,173 @@ gst_meta_api_type_register (const gchar * api, const gchar ** tags)
     }
   }
 
-  g_type_set_qdata (type, g_quark_from_string ("tags"),
-      g_strdupv ((gchar **) tags));
+  g_type_set_qdata (type, GST_QUARK (TAGS), g_strdupv ((gchar **) tags));
 
   return type;
 }
 
+static gboolean
+custom_init_func (GstMeta * meta, gpointer params, GstBuffer * buffer)
+{
+  GstCustomMetaImpl *cmeta = (GstCustomMetaImpl *) meta;
+
+  cmeta->structure = gst_structure_new_empty (g_type_name (meta->info->type));
+
+  gst_structure_set_parent_refcount (cmeta->structure,
+      &GST_MINI_OBJECT_REFCOUNT (buffer));
+
+  return TRUE;
+}
+
+static void
+custom_free_func (GstMeta * meta, GstBuffer * buffer)
+{
+  GstCustomMetaImpl *cmeta = (GstCustomMetaImpl *) meta;
+
+  gst_structure_set_parent_refcount (cmeta->structure, NULL);
+  gst_structure_free (cmeta->structure);
+}
+
+static gboolean
+custom_transform_func (GstBuffer * transbuf, GstMeta * meta,
+    GstBuffer * buffer, GQuark type, gpointer data)
+{
+  GstCustomMetaImpl *custom, *cmeta = (GstCustomMetaImpl *) meta;
+  GstMetaInfoImpl *info = (GstMetaInfoImpl *) meta->info;
+
+  if (info->custom_transform_func)
+    return info->custom_transform_func (transbuf, (GstCustomMeta *) meta,
+        buffer, type, data, info->custom_transform_user_data);
+
+  if (GST_META_TRANSFORM_IS_COPY (type)) {
+    custom =
+        (GstCustomMetaImpl *) gst_buffer_add_meta (transbuf, meta->info, NULL);
+    gst_structure_set_parent_refcount (custom->structure, NULL);
+    gst_structure_take (&custom->structure,
+        gst_structure_copy (cmeta->structure));
+    gst_structure_set_parent_refcount (custom->structure,
+        &GST_MINI_OBJECT_REFCOUNT (buffer));
+  } else {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+ * gst_custom_meta_get_structure:
+ *
+ * Retrieve the #GstStructure backing a custom meta, the structure's mutability
+ * is conditioned to the writability of the #GstBuffer @meta is attached to.
+ *
+ * Returns: (transfer none): the #GstStructure backing @meta
+ * Since: 1.20
+ */
+GstStructure *
+gst_custom_meta_get_structure (GstCustomMeta * meta)
+{
+  g_return_val_if_fail (meta != NULL, NULL);
+  g_return_val_if_fail (gst_meta_info_is_custom (((GstMeta *) meta)->info),
+      NULL);
+
+  return ((GstCustomMetaImpl *) meta)->structure;
+}
+
+/**
+ * gst_custom_meta_has_name:
+ *
+ * Checks whether the name of the custom meta is @name
+ *
+ * Returns: Whether @name is the name of the custom meta
+ * Since: 1.20
+ */
+gboolean
+gst_custom_meta_has_name (GstCustomMeta * meta, const gchar * name)
+{
+  g_return_val_if_fail (meta != NULL, FALSE);
+  g_return_val_if_fail (gst_meta_info_is_custom (((GstMeta *) meta)->info),
+      FALSE);
+
+  return gst_structure_has_name (((GstCustomMetaImpl *) meta)->structure, name);
+}
+
+/**
+ * gst_meta_register_custom:
+ * @name: the name of the #GstMeta implementation
+ * @tags: (array zero-terminated=1): tags for @api
+ * @transform_func: (scope notified) (nullable): a #GstMetaTransformFunction
+ * @user_data: (closure): user data passed to @transform_func
+ * @destroy_data: #GDestroyNotify for user_data
+ *
+ * Register a new custom #GstMeta implementation, backed by an opaque
+ * structure holding a #GstStructure.
+ *
+ * The registered info can be retrieved later with gst_meta_get_info() by using
+ * @name as the key.
+ *
+ * The backing #GstStructure can be retrieved with
+ * gst_custom_meta_get_structure(), its mutability is conditioned by the
+ * writability of the buffer the meta is attached to.
+ *
+ * When @transform_func is %NULL, the meta and its backing #GstStructure
+ * will always be copied when the transform operation is copy, other operations
+ * are discarded, copy regions are ignored.
+ *
+ * Returns: (transfer none): a #GstMetaInfo that can be used to
+ * access metadata.
+ * Since: 1.20
+ */
+const GstMetaInfo *
+gst_meta_register_custom (const gchar * name, const gchar ** tags,
+    GstCustomMetaTransformFunction transform_func,
+    gpointer user_data, GDestroyNotify destroy_data)
+{
+  gchar *api_name = g_strdup_printf ("%s-api", name);
+  GType api;
+  GstMetaInfoImpl *info;
+  GstMetaInfo *ret = NULL;
+
+  g_return_val_if_fail (tags != NULL, NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+
+  api = gst_meta_api_type_register (api_name, tags);
+  g_free (api_name);
+  if (api == G_TYPE_INVALID)
+    goto done;
+
+  info = (GstMetaInfoImpl *) gst_meta_register (api, name,
+      sizeof (GstCustomMetaImpl),
+      custom_init_func, custom_free_func, custom_transform_func);
+
+  if (!info)
+    goto done;
+
+  info->is_custom = TRUE;
+  info->custom_transform_func = transform_func;
+  info->custom_transform_user_data = user_data;
+  info->custom_transform_destroy_notify = destroy_data;
+
+  ret = (GstMetaInfo *) info;
+
+done:
+  return ret;
+}
+
+/**
+ * gst_meta_info_is_custom:
+ *
+ * Returns: whether @info was registered as a #GstCustomMeta with
+ *   gst_meta_register_custom()
+ * Since:1.20
+ */
+gboolean
+gst_meta_info_is_custom (const GstMetaInfo * info)
+{
+  g_return_val_if_fail (info != NULL, FALSE);
+
+  return ((GstMetaInfoImpl *) info)->is_custom;
+}
+
 /**
  * gst_meta_api_type_has_tag:
  * @api: an API
@@ -136,7 +342,7 @@ gst_meta_api_type_get_tags (GType api)
   const gchar **tags;
   g_return_val_if_fail (api != 0, FALSE);
 
-  tags = g_type_get_qdata (api, g_quark_from_string ("tags"));
+  tags = g_type_get_qdata (api, GST_QUARK (TAGS));
 
   if (!tags[0])
     return NULL;
@@ -158,7 +364,7 @@ gst_meta_api_type_get_tags (GType api)
  * The same @info can be retrieved later with gst_meta_get_info() by using
  * @impl as the key.
  *
- * Returns: (transfer none) (nullable): a #GstMetaInfo that can be used to
+ * Returns: (transfer none): a #GstMetaInfo that can be used to
  * access metadata.
  */
 
@@ -185,20 +391,22 @@ gst_meta_register (GType api, const gchar * impl, gsize size,
   if (type == 0)
     return NULL;
 
-  info = g_slice_new (GstMetaInfo);
+  info = (GstMetaInfo *) g_slice_new (GstMetaInfoImpl);
   info->api = api;
   info->type = type;
   info->size = size;
   info->init_func = init_func;
   info->free_func = free_func;
   info->transform_func = transform_func;
+  ((GstMetaInfoImpl *) info)->is_custom = FALSE;
 
   GST_CAT_DEBUG (GST_CAT_META,
       "register \"%s\" implementing \"%s\" of size %" G_GSIZE_FORMAT, impl,
       g_type_name (api), size);
 
   g_rw_lock_writer_lock (&lock);
-  g_hash_table_insert (metainfo, (gpointer) impl, (gpointer) info);
+  g_hash_table_insert (metainfo, (gpointer) g_intern_string (impl),
+      (gpointer) info);
   g_rw_lock_writer_unlock (&lock);
 
   return info;
index d617ef8..547e5fc 100644 (file)
@@ -105,6 +105,17 @@ struct _GstMeta {
   const GstMetaInfo *info;
 };
 
+/**
+ * GstCustomMeta:
+ *
+ * Simple typing wrapper around #GstMeta
+ *
+ * Since: 1.20
+ */
+typedef struct {
+  GstMeta meta;
+} GstCustomMeta;
+
 #include <gst/gstbuffer.h>
 
 /**
@@ -179,6 +190,30 @@ typedef gboolean (*GstMetaTransformFunction) (GstBuffer *transbuf,
                                               GQuark type, gpointer data);
 
 /**
+ * GstCustomMetaTransformFunction:
+ * @transbuf: a #GstBuffer
+ * @meta: a #GstCustomMeta
+ * @buffer: a #GstBuffer
+ * @type: the transform type
+ * @data: transform specific data.
+ * @user_data: user data passed when registering the meta
+ *
+ * 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 as @data.
+ *
+ * Implementations should check the @type of the transform and parse
+ * additional type specific fields in @data that should be used to update
+ * the metadata on @transbuf.
+ *
+ * Returns: %TRUE if the transform could be performed
+ * Since: 1.20
+ */
+typedef gboolean (*GstCustomMetaTransformFunction) (GstBuffer *transbuf,
+                                                    GstCustomMeta *meta, GstBuffer *buffer,
+                                                    GQuark type, gpointer data, gpointer user_data);
+
+/**
  * GstMetaInfo:
  * @api: tag identifying the metadata structure and api
  * @type: type identifying the implementor of the api
@@ -216,6 +251,21 @@ const GstMetaInfo *  gst_meta_register          (GType api, const gchar *impl,
                                                  GstMetaInitFunction      init_func,
                                                  GstMetaFreeFunction      free_func,
                                                  GstMetaTransformFunction transform_func);
+
+GST_API
+const GstMetaInfo *  gst_meta_register_custom   (const gchar *name, const gchar **tags,
+                                                 GstCustomMetaTransformFunction transform_func,
+                                                 gpointer user_data, GDestroyNotify destroy_data);
+
+GST_API
+gboolean             gst_meta_info_is_custom    (const GstMetaInfo *info);
+
+GST_API
+GstStructure *       gst_custom_meta_get_structure (GstCustomMeta *meta);
+
+GST_API
+gboolean             gst_custom_meta_has_name (GstCustomMeta *meta, const gchar * name);
+
 GST_API
 const GstMetaInfo *  gst_meta_get_info          (const gchar * impl);
 
index d5c28ba..e980c89 100644 (file)
@@ -59,6 +59,8 @@
 #include "gst/gstinfo.h"
 #include <gobject/gvaluecollector.h>
 
+GType _gst_mini_object_type = 0;
+
 /* Mutex used for weak referencing */
 G_LOCK_DEFINE_STATIC (qdata_mutex);
 static GQuark weak_ref_quark;
@@ -72,6 +74,14 @@ static GQuark weak_ref_quark;
 #define LOCK_MASK ((SHARE_ONE - 1) - FLAG_MASK)
 #define LOCK_FLAG_MASK (SHARE_ONE - 1)
 
+/**
+ * GST_TYPE_MINI_OBJECT:
+ *
+ * The #GType associated with #GstMiniObject.
+ *
+ * Since: 1.20
+ */
+
 /* For backwards compatibility reasons we use the
  * guint and gpointer in the GstMiniObject struct in
  * a rather complicated way to store the parent(s) and qdata.
@@ -126,9 +136,12 @@ typedef struct
 #define QDATA_DATA(o,i)     (QDATA(o,i).data)
 #define QDATA_DESTROY(o,i)  (QDATA(o,i).destroy)
 
+GST_DEFINE_MINI_OBJECT_TYPE (GstMiniObject, gst_mini_object);
+
 void
 _priv_gst_mini_object_initialize (void)
 {
+  _gst_mini_object_type = gst_mini_object_get_type ();
   weak_ref_quark = g_quark_from_static_string ("GstMiniObjectWeakRefQuark");
 }
 
@@ -722,7 +735,7 @@ gst_mini_object_replace (GstMiniObject ** olddata, GstMiniObject * newdata)
       *olddata, *olddata ? (*olddata)->refcount : 0,
       newdata, newdata ? newdata->refcount : 0);
 
-  olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
+  olddata_val = (GstMiniObject *) g_atomic_pointer_get ((gpointer *) olddata);
 
   if (G_UNLIKELY (olddata_val == newdata))
     return FALSE;
@@ -731,7 +744,7 @@ gst_mini_object_replace (GstMiniObject ** olddata, GstMiniObject * newdata)
     gst_mini_object_ref (newdata);
 
   while (G_UNLIKELY (!g_atomic_pointer_compare_and_exchange ((gpointer *)
-              olddata, olddata_val, newdata))) {
+              olddata, (gpointer) olddata_val, newdata))) {
     olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
     if (G_UNLIKELY (olddata_val == newdata))
       break;
@@ -764,11 +777,11 @@ gst_mini_object_steal (GstMiniObject ** olddata)
       *olddata, *olddata ? (*olddata)->refcount : 0);
 
   do {
-    olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
+    olddata_val = (GstMiniObject *) 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)));
+              olddata, (gpointer) olddata_val, NULL)));
 
   return olddata_val;
 }
@@ -800,11 +813,11 @@ gst_mini_object_take (GstMiniObject ** olddata, GstMiniObject * newdata)
       newdata, newdata ? newdata->refcount : 0);
 
   do {
-    olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
+    olddata_val = (GstMiniObject *) 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)));
+              olddata, (gpointer) olddata_val, newdata)));
 
   if (olddata_val)
     gst_mini_object_unref (olddata_val);
@@ -953,7 +966,7 @@ gst_mini_object_get_qdata (GstMiniObject * object, GQuark quark)
  * @quark: A #GQuark, naming the user data pointer
  *
  * This function gets back user data pointers stored via gst_mini_object_set_qdata()
- * and removes the data from @object without invoking its destroy() function (if
+ * and removes the data from @object without invoking its `destroy()` function (if
  * any was set).
  *
  * Returns: (transfer full) (nullable): The user data pointer set, or
index b931e76..f4dfa8d 100644 (file)
 
 G_BEGIN_DECLS
 
+GST_API GType _gst_mini_object_type;
+
+#define GST_TYPE_MINI_OBJECT               (_gst_mini_object_type)
+
 #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))
@@ -36,6 +40,9 @@ G_BEGIN_DECLS
 
 typedef struct _GstMiniObject GstMiniObject;
 
+GST_API
+GType           gst_mini_object_get_type   (void);
+
 /**
  * GstMiniObjectCopyFunction:
  * @obj: MiniObject to copy
index d0c52c8..08e7797 100644 (file)
@@ -156,7 +156,8 @@ gst_object_class_init (GstObjectClass * klass)
 
   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);
+      G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS |
+      GST_PARAM_DOC_SHOW_DEFAULT);
 
   /**
    * GstObject:parent:
@@ -169,13 +170,16 @@ gst_object_class_init (GstObjectClass * klass)
    */
   properties[PROP_PARENT] =
       g_param_spec_object ("parent", "Parent", "The parent of the object",
-      GST_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+      GST_TYPE_OBJECT,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_DOC_SHOW_DEFAULT);
+
 #ifdef TIZEN_PROFILE_TV
   properties[PROP_FAMILY_ID] =
       g_param_spec_int ("family-id", "Family Id",
       "The family id of this object group, usually inherit from parent.",
       -G_MAXINT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 #endif
+
   g_object_class_install_properties (gobject_class, PROP_LAST, properties);
 
   /**
@@ -192,8 +196,7 @@ gst_object_class_init (GstObjectClass * klass)
       g_signal_new ("deep-notify", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED |
       G_SIGNAL_NO_HOOKS, G_STRUCT_OFFSET (GstObjectClass, deep_notify), NULL,
-      NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, GST_TYPE_OBJECT,
-      G_TYPE_PARAM);
+      NULL, NULL, G_TYPE_NONE, 2, GST_TYPE_OBJECT, G_TYPE_PARAM);
 
   klass->path_string_separator = "/";
 
@@ -358,7 +361,7 @@ gst_object_replace (GstObject ** oldobj, GstObject * newobj)
       newobj ? G_OBJECT (newobj)->ref_count : 0);
 #endif
 
-  oldptr = g_atomic_pointer_get ((gpointer *) oldobj);
+  oldptr = (GstObject *) g_atomic_pointer_get ((gpointer *) oldobj);
 
   if (G_UNLIKELY (oldptr == newobj))
     return FALSE;
@@ -367,7 +370,7 @@ gst_object_replace (GstObject ** oldobj, GstObject * newobj)
     gst_object_ref (newobj);
 
   while (G_UNLIKELY (!g_atomic_pointer_compare_and_exchange ((gpointer *)
-              oldobj, oldptr, newobj))) {
+              oldobj, (gpointer) oldptr, newobj))) {
     oldptr = g_atomic_pointer_get ((gpointer *) oldobj);
     if (G_UNLIKELY (oldptr == newobj))
       break;
@@ -604,29 +607,11 @@ had_parent:
   }
 }
 
-/**
- * gst_object_set_name:
- * @object: a #GstObject
- * @name: (allow-none): new name of object
- *
- * Sets the name of @object, or gives @object a guaranteed unique
- * name (if @name is %NULL).
- * This function makes a copy of the provided name, so the caller
- * retains ownership of the name it sent.
- *
- * Returns: %TRUE if the name could be set. Since Objects that have
- * a parent cannot be renamed, this function returns %FALSE in those
- * cases.
- *
- * MT safe.  This function grabs and releases @object's LOCK.
- */
-gboolean
-gst_object_set_name (GstObject * object, const gchar * name)
+static gboolean
+gst_object_set_name_intern (GstObject * object, const gchar * name)
 {
   gboolean result;
 
-  g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
-
   GST_OBJECT_LOCK (object);
 
   /* parented objects cannot be renamed */
@@ -643,7 +628,6 @@ gst_object_set_name (GstObject * object, const gchar * name)
     result = gst_object_set_name_default (object);
   }
 
-  g_object_notify (G_OBJECT (object), "name");
   return result;
 
   /* error */
@@ -656,6 +640,34 @@ had_parent:
 }
 
 /**
+ * gst_object_set_name:
+ * @object: a #GstObject
+ * @name: (allow-none): new name of object
+ *
+ * Sets the name of @object, or gives @object a guaranteed unique
+ * name (if @name is %NULL).
+ * This function makes a copy of the provided name, so the caller
+ * retains ownership of the name it sent.
+ *
+ * Returns: %TRUE if the name could be set. Since Objects that have
+ * a parent cannot be renamed, this function returns %FALSE in those
+ * cases.
+ *
+ * MT safe.  This function grabs and releases @object's LOCK.
+ */
+gboolean
+gst_object_set_name (GstObject * object, const gchar * name)
+{
+  gboolean result;
+
+  g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
+
+  if ((result = gst_object_set_name_intern (object, name)))
+    g_object_notify_by_pspec (G_OBJECT (object), properties[PROP_NAME]);
+  return result;
+}
+
+/**
  * gst_object_get_name:
  * @object: a #GstObject
  *
@@ -935,7 +947,7 @@ gst_object_set_property (GObject * object, guint prop_id,
 
   switch (prop_id) {
     case PROP_NAME:
-      gst_object_set_name (gstobject, g_value_get_string (value));
+      gst_object_set_name_intern (gstobject, g_value_get_string (value));
       break;
     case PROP_PARENT:
       gst_object_set_parent (gstobject, g_value_get_object (value));
index c10c62f..6035e29 100644 (file)
@@ -327,9 +327,7 @@ GstClockTime    gst_object_get_control_rate       (GstObject * object);
 GST_API
 void            gst_object_set_control_rate       (GstObject * object, GstClockTime control_rate);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstObject, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 18f22ee..c3b288d 100644 (file)
@@ -43,7 +43,7 @@
  * then a guaranteed unique name will be assigned to it.
  *
  * A #GstElement creating a pad will typically use the various
- * gst_pad_set_*_function() calls to register callbacks for events, queries or
+ * gst_pad_set_*_function\() calls to register callbacks for events, queries or
  * dataflow on the pads.
  *
  * gst_pad_get_parent() will retrieve the #GstElement that owns the pad.
@@ -344,7 +344,7 @@ gst_pad_class_init (GstPadClass * klass)
   gst_pad_signals[PAD_LINKED] =
       g_signal_new ("linked", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstPadClass, linked), NULL, NULL,
-      g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD);
+      NULL, G_TYPE_NONE, 1, GST_TYPE_PAD);
   /**
    * GstPad::unlinked:
    * @pad: the pad that emitted the signal
@@ -355,7 +355,7 @@ gst_pad_class_init (GstPadClass * klass)
   gst_pad_signals[PAD_UNLINKED] =
       g_signal_new ("unlinked", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstPadClass, unlinked), NULL, NULL,
-      g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD);
+      NULL, G_TYPE_NONE, 1, GST_TYPE_PAD);
 
   pspec_caps = g_param_spec_boxed ("caps", "Caps",
       "The capabilities of the pad", GST_TYPE_CAPS,
@@ -723,9 +723,8 @@ gst_pad_dispose (GObject * object)
 
   GST_OBJECT_LOCK (pad);
   remove_events (pad);
-  GST_OBJECT_UNLOCK (pad);
-
   g_hook_list_clear (&pad->probes);
+  GST_OBJECT_UNLOCK (pad);
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
@@ -1372,8 +1371,10 @@ cleanup_hook (GstPad * pad, GHook * hook)
   GST_DEBUG_OBJECT (pad,
       "cleaning up hook %lu with flags %08x", hook->hook_id, hook->flags);
 
-  if (!G_HOOK_IS_VALID (hook))
+  if (!G_HOOK_IS_VALID (hook)) {
+    /* We've already destroyed this hook */
     return;
+  }
 
   type = (hook->flags) >> G_HOOK_FLAG_USER_SHIFT;
 
@@ -1493,6 +1494,9 @@ gst_pad_add_probe (GstPad * pad, GstPadProbeType mask,
       gst_object_ref (pad);
       pad->priv->idle_running++;
 
+      /* Ref the hook, it could be destroyed by the callback or concurrently */
+      g_hook_ref (&pad->probes, hook);
+
       /* 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");
@@ -1524,6 +1528,7 @@ gst_pad_add_probe (GstPad * pad, GstPadProbeType mask,
           GST_DEBUG_OBJECT (pad, "probe returned %d", ret);
           break;
       }
+      g_hook_unref (&pad->probes, hook);
       pad->priv->idle_running--;
       if (pad->priv->idle_running == 0) {
         GST_PAD_BLOCK_BROADCAST (pad);
@@ -2851,6 +2856,72 @@ no_peer:
 }
 
 /**
+ * gst_pad_get_single_internal_link:
+ * @pad: the #GstPad to get the internal link of.
+ *
+ * If there is a single internal link of the given pad, this function will
+ * return it. Otherwise, it will return NULL.
+ *
+ * Returns: (transfer full) (nullable): a #GstPad, or %NULL if @pad has none
+ * or more than one internal links. Unref returned pad with
+ * gst_object_unref().
+ *
+ * Since: 1.18
+ */
+GstPad *
+gst_pad_get_single_internal_link (GstPad * pad)
+{
+  GstIterator *iter;
+  gboolean done = FALSE;
+  GValue item = { 0, };
+  GstPad *ret = NULL;
+
+  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+
+  iter = gst_pad_iterate_internal_links (pad);
+
+  if (!iter)
+    return NULL;
+
+  while (!done) {
+    switch (gst_iterator_next (iter, &item)) {
+      case GST_ITERATOR_OK:
+      {
+        if (ret == NULL) {
+          ret = g_value_dup_object (&item);
+        } else {
+          /* More than one internal link found - don't bother reffing */
+          gst_clear_object (&ret);
+          GST_DEBUG_OBJECT (pad,
+              "Requested single internally linked pad, multiple found");
+          done = TRUE;
+        }
+        g_value_reset (&item);
+        break;
+      }
+      case GST_ITERATOR_RESYNC:
+        gst_clear_object (&ret);
+        gst_iterator_resync (iter);
+        break;
+      case GST_ITERATOR_ERROR:
+        GST_ERROR_OBJECT (pad, "Could not iterate over internally linked pads");
+        return NULL;
+      case GST_ITERATOR_DONE:
+        if (ret == NULL) {
+          GST_DEBUG_OBJECT (pad,
+              "Requested single internally linked pad, none found");
+        }
+        done = TRUE;
+        break;
+    }
+  }
+  g_value_unset (&item);
+  gst_iterator_free (iter);
+
+  return ret;
+}
+
+/**
  * gst_pad_iterate_internal_links_default:
  * @pad: the #GstPad to get the internal links of.
  * @parent: (allow-none): the parent of @pad or %NULL
@@ -3160,11 +3231,17 @@ gst_pad_query_accept_caps_default (GstPad * pad, GstQuery * query)
           GST_PTR_FORMAT, allowed, caps);
       result = gst_caps_is_subset (caps, allowed);
     }
+    if (!result) {
+      GST_CAT_WARNING_OBJECT (GST_CAT_CAPS, pad, "caps: %" GST_PTR_FORMAT
+          " were not compatible with: %" GST_PTR_FORMAT, caps, allowed);
+    }
     gst_caps_unref (allowed);
   } else {
-    GST_DEBUG_OBJECT (pad, "no compatible caps allowed on the pad");
+    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+        "no compatible caps allowed on the pad");
     result = FALSE;
   }
+
   gst_query_set_accept_caps_result (query, result);
 
 done:
@@ -3461,15 +3538,13 @@ gst_pad_query_default (GstPad * pad, GstObject * parent, GstQuery * query)
 
 #define N_STACK_ALLOCATE_PROBES (16)
 
-static void
-probe_hook_marshal (GHook * hook, ProbeMarshall * data)
+/* A helper that checks if a probe was already
+ * in the called_probes list, and adds it if
+ * not. Used to avoid calling probes a 2nd time when
+ * looping again after probe removal */
+static gboolean
+check_probe_already_called (GHook * hook, ProbeMarshall * data)
 {
-  GstPad *pad = data->pad;
-  GstPadProbeInfo *info = data->info;
-  GstPadProbeType type, flags;
-  GstPadProbeCallback callback;
-  GstPadProbeReturn ret;
-  gpointer original_data;
   guint i;
 
   /* if we have called this callback, do nothing. But only check
@@ -3477,9 +3552,7 @@ probe_hook_marshal (GHook * hook, ProbeMarshall * data)
   if (data->retry) {
     for (i = 0; i < data->n_called_probes; i++) {
       if (data->called_probes[i] == hook->hook_id) {
-        GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-            "hook %lu already called", hook->hook_id);
-        return;
+        return TRUE;
       }
     }
   }
@@ -3501,6 +3574,20 @@ probe_hook_marshal (GHook * hook, ProbeMarshall * data)
   }
   data->called_probes[data->n_called_probes++] = hook->hook_id;
 
+  /* This probe was not alraedy called */
+  return FALSE;
+}
+
+static void
+probe_hook_marshal (GHook * hook, ProbeMarshall * data)
+{
+  GstPad *pad = data->pad;
+  GstPadProbeInfo *info = data->info;
+  GstPadProbeType type, flags;
+  GstPadProbeCallback callback;
+  GstPadProbeReturn ret;
+  gpointer original_data;
+
   flags = hook->flags >> G_HOOK_FLAG_USER_SHIFT;
   type = info->type;
   original_data = info->data;
@@ -3546,14 +3633,26 @@ probe_hook_marshal (GHook * hook, ProbeMarshall * data)
       (flags & GST_PAD_PROBE_TYPE_EVENT_FLUSH & type) == 0)
     goto no_match;
 
+  if (check_probe_already_called (hook, data)) {
+    /* Reset marshalled = TRUE here, because the probe
+     * was already called and set it the first time around,
+     * and we may want to keep blocking on it.
+     *
+     * https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/658
+     */
+    data->marshalled = TRUE;
+    goto already_called;
+  }
+
   GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
       "hook %lu with flags 0x%08x matches", hook->hook_id, flags);
 
-  data->marshalled = TRUE;
-
   callback = (GstPadProbeCallback) hook->func;
-  if (callback == NULL)
+  if (callback == NULL) {
+    /* No callback is equivalent to just returning GST_PAD_PROBE_OK */
+    data->marshalled = TRUE;
     return;
+  }
 
   info->id = hook->hook_id;
 
@@ -3566,6 +3665,18 @@ probe_hook_marshal (GHook * hook, ProbeMarshall * data)
 
   GST_OBJECT_LOCK (pad);
 
+  /* If the probe callback asked for the
+   * probe to be removed, don't set the marshalled flag
+   * otherwise, you can get a case where you return
+   * GST_PAD_PROBE_REMOVE from a buffer probe and
+   * then the pad blocks anyway if there's any other
+   * blocking probes installed.
+   *
+   * https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/658
+   */
+  if (ret != GST_PAD_PROBE_REMOVE)
+    data->marshalled = TRUE;
+
   if ((flags & GST_PAD_PROBE_TYPE_IDLE))
     pad->priv->idle_running--;
 
@@ -3614,6 +3725,12 @@ no_match:
         hook->hook_id, flags, info->type);
     return;
   }
+already_called:
+  {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "hook %lu already called", hook->hook_id);
+    return;
+  }
 }
 
 /* a probe that does not take or return any data */
@@ -3702,7 +3819,6 @@ do_probe_callbacks (GstPad * pad, GstPadProbeInfo * info,
   data.info = info;
   data.pass = FALSE;
   data.handled = FALSE;
-  data.marshalled = FALSE;
   data.dropped = FALSE;
 
   /* We stack-allocate for N_STACK_ALLOCATE_PROBES hooks as a first step. If more are needed,
@@ -3725,6 +3841,10 @@ again:
   GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "do probes");
   cookie = pad->priv->probe_list_cookie;
 
+  /* Clear the marshalled flag before doing callbacks. Only if
+   * there are matching callbacks still will it get set */
+  data.marshalled = FALSE;
+
   g_hook_list_marshal (&pad->probes, TRUE,
       (GHookMarshaller) probe_hook_marshal, &data);
 
@@ -4346,6 +4466,8 @@ gst_pad_chain_data_unchecked (GstPad * pad, GstPadProbeType type, void *data)
         GST_DEBUG_FUNCPTR_NAME (chainlistfunc), gst_flow_get_name (ret));
   }
 
+  pad->ABI.abi.last_flowret = ret;
+
   RELEASE_PARENT (parent);
 
   GST_PAD_STREAM_UNLOCK (pad);
@@ -4357,6 +4479,7 @@ flushing:
   {
     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
         "chaining, but pad was flushing");
+    pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
     GST_OBJECT_UNLOCK (pad);
     GST_PAD_STREAM_UNLOCK (pad);
     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
@@ -4365,6 +4488,7 @@ flushing:
 eos:
   {
     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "chaining, but pad was EOS");
+    pad->ABI.abi.last_flowret = GST_FLOW_EOS;
     GST_OBJECT_UNLOCK (pad);
     GST_PAD_STREAM_UNLOCK (pad);
     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
@@ -4374,6 +4498,7 @@ wrong_mode:
   {
     g_critical ("chain on pad %s:%s but it was not in push mode",
         GST_DEBUG_PAD_NAME (pad));
+    pad->ABI.abi.last_flowret = GST_FLOW_ERROR;
     GST_OBJECT_UNLOCK (pad);
     GST_PAD_STREAM_UNLOCK (pad);
     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
@@ -4384,8 +4509,6 @@ probe_handled:
   /* PASSTHROUGH */
 probe_stopped:
   {
-    GST_OBJECT_UNLOCK (pad);
-    GST_PAD_STREAM_UNLOCK (pad);
     /* We unref the buffer, except if the probe handled it (CUSTOM_SUCCESS_1) */
     if (!handled)
       gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
@@ -4400,11 +4523,15 @@ probe_stopped:
         GST_DEBUG_OBJECT (pad, "an error occurred %s", gst_flow_get_name (ret));
         break;
     }
+    pad->ABI.abi.last_flowret = ret;
+    GST_OBJECT_UNLOCK (pad);
+    GST_PAD_STREAM_UNLOCK (pad);
     return ret;
   }
 no_parent:
   {
     GST_DEBUG_OBJECT (pad, "No parent when chaining %" GST_PTR_FORMAT, data);
+    pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
     GST_OBJECT_UNLOCK (pad);
     GST_PAD_STREAM_UNLOCK (pad);
@@ -4412,6 +4539,7 @@ no_parent:
   }
 no_function:
   {
+    pad->ABI.abi.last_flowret = GST_FLOW_NOT_SUPPORTED;
     RELEASE_PARENT (parent);
     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
     g_critical ("chain on pad %s:%s but it has no chainfunction",
@@ -4466,7 +4594,7 @@ gst_pad_chain_list_default (GstPad * pad, GstObject * parent,
   GstBuffer *buffer;
   GstFlowReturn ret;
 
-  GST_INFO_OBJECT (pad, "chaining each buffer in list individually");
+  GST_LOG_OBJECT (pad, "chaining each buffer in list individually");
 
   len = gst_buffer_list_length (list);
 
@@ -4806,6 +4934,10 @@ probed_data:
 
   GST_PAD_STREAM_UNLOCK (pad);
 
+  /* If the caller provided a buffer it must be filled by the getrange
+   * function instead of it returning a new buffer */
+  g_return_val_if_fail (!*buffer || res_buf == *buffer, GST_FLOW_ERROR);
+
   *buffer = res_buf;
 
   return ret;
@@ -5144,7 +5276,7 @@ store_sticky_event (GstPad * pad, GstEvent * event)
   GstEventType type;
   GArray *events;
   gboolean res = FALSE;
-  const gchar *name = NULL;
+  GQuark name_id = 0;
   gboolean insert = TRUE;
 
   type = GST_EVENT_TYPE (event);
@@ -5161,9 +5293,10 @@ store_sticky_event (GstPad * pad, GstEvent * event)
   /* Unset the EOS flag when received STREAM_START event, so pad can
    * store sticky event and then push it later */
   if (type == GST_EVENT_STREAM_START) {
-    GST_LOG_OBJECT (pad, "Removing pending EOS and StreamGroupDone events");
+    GST_LOG_OBJECT (pad, "Removing pending EOS, StreamGroupDone, TAG events");
     remove_event_by_type (pad, GST_EVENT_EOS);
     remove_event_by_type (pad, GST_EVENT_STREAM_GROUP_DONE);
+    remove_event_by_type (pad, GST_EVENT_TAG);
     GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS);
   }
 
@@ -5171,7 +5304,7 @@ store_sticky_event (GstPad * pad, GstEvent * event)
     goto eos;
 
   if (type & GST_EVENT_TYPE_STICKY_MULTI)
-    name = gst_structure_get_name (gst_event_get_structure (event));
+    name_id = gst_structure_get_name_id (gst_event_get_structure (event));
 
   events = pad->priv->events;
   len = events->len;
@@ -5184,7 +5317,7 @@ store_sticky_event (GstPad * pad, GstEvent * event)
 
     if (type == GST_EVENT_TYPE (ev->event)) {
       /* matching types, check matching name if needed */
-      if (name && !gst_event_has_name (ev->event, name))
+      if (name_id && !gst_event_has_name_id (ev->event, name_id))
         continue;
 
       /* overwrite */
@@ -5621,7 +5754,7 @@ pre_eventfunc_check (GstPad * pad, GstEvent * event)
   /* ERRORS */
 not_accepted:
   {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+    GST_CAT_WARNING_OBJECT (GST_CAT_CAPS, pad,
         "caps %" GST_PTR_FORMAT " not accepted", caps);
     return GST_FLOW_NOT_NEGOTIATED;
   }
@@ -5706,6 +5839,7 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
           GST_LOG_OBJECT (pad, "Removing pending EOS events");
           remove_event_by_type (pad, GST_EVENT_EOS);
           remove_event_by_type (pad, GST_EVENT_STREAM_GROUP_DONE);
+          remove_event_by_type (pad, GST_EVENT_TAG);
           GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS);
           break;
         default:
@@ -6081,18 +6215,16 @@ do_stream_status (GstPad * pad, GstStreamStatusType type,
       GValue value = { 0 };
 
       if (type == GST_STREAM_STATUS_TYPE_ENTER) {
-        gchar *tname, *ename, *pname;
+        gchar *tname;
 
-        /* create a good task name */
-        ename = gst_element_get_name (parent);
-        pname = gst_pad_get_name (pad);
+        /* create a good task name (we can directly grab the parent and pad
+         * names since they both exist at this point, and changing the name of
+         * parent and pad when a pad is activating is a big no-no). */
 #ifdef TIZEN_PROFILE_TV
-        tname = g_strdup_printf ("%s-%s", ename, pname);
-#else
-        tname = g_strdup_printf ("%s:%s", ename, pname);
-#endif
-        g_free (ename);
-        g_free (pname);
+        tname = g_strdup_printf ("%s-%s", GST_DEBUG_PAD_NAME (pad));
+#else           
+        tname = g_strdup_printf ("%s:%s", GST_DEBUG_PAD_NAME (pad));
+#endif         
 
         gst_object_set_name (GST_OBJECT_CAST (task), tname);
         g_free (tname);
index 1908398..c89be30 100644 (file)
@@ -137,8 +137,8 @@ typedef enum {
  * @GST_FLOW_EOS:                Pad is EOS.
  * @GST_FLOW_NOT_NEGOTIATED:    Pad is not negotiated.
  * @GST_FLOW_ERROR:             Some (fatal) error occurred. Element generating
- *                               this error should post an error message with more
- *                               details.
+ *                               this error should post an error message using
+ *                               GST_ELEMENT_ERROR() with more details.
  * @GST_FLOW_NOT_SUPPORTED:     This operation is not supported.
  * @GST_FLOW_CUSTOM_SUCCESS:    Elements can use values starting from
  *                               this (and higher) to define custom success
@@ -548,9 +548,12 @@ typedef enum
  *        the data item is not passed upstream. In both cases, no other probes
  *        are called for this item and %GST_FLOW_OK or %TRUE is returned to the
  *        caller.
- * @GST_PAD_PROBE_REMOVE: remove this probe.
+ * @GST_PAD_PROBE_REMOVE: remove this probe, passing the data. For blocking probes
+ *        this will cause data flow to unblock, unless there are also other
+ *        blocking probes installed.
  * @GST_PAD_PROBE_PASS: pass the data item in the block probe and block on the
- *        next item.
+ *        next item. Note, that if there are multiple pad probes installed and
+ *        any probe returns PASS, the data will be passed.
  * @GST_PAD_PROBE_HANDLED: Data has been handled in the probe and will not be
  *        forwarded further. For events and buffers this is the same behaviour as
  *        %GST_PAD_PROBE_DROP (except that in this case you need to unref the buffer
@@ -1539,6 +1542,9 @@ GstIterator *           gst_pad_iterate_internal_links_default  (GstPad * pad, G
 
 #define gst_pad_set_iterate_internal_links_function(p,f) gst_pad_set_iterate_internal_links_function_full((p),(f),NULL,NULL)
 
+GST_API
+GstPad *                gst_pad_get_single_internal_link        (GstPad * pad);
+
 /* generic query function */
 
 GST_API
@@ -1563,9 +1569,7 @@ GST_API
 gboolean               gst_pad_forward                         (GstPad *pad, GstPadForwardFunction forward,
                                                                 gpointer user_data);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPad, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 952f07e..8055a9a 100644 (file)
@@ -42,7 +42,7 @@
  * GST_PAD_TEMPLATE_DIRECTION().
  *
  * The GST_PAD_TEMPLATE_NAME_TEMPLATE () is important for GST_PAD_REQUEST pads
- * because it has to be used as the name in the gst_element_get_request_pad()
+ * because it has to be used as the name in the gst_element_request_pad_simple()
  * call to instantiate a pad from this template.
  *
  * Padtemplates can be created with gst_pad_template_new() or with
@@ -146,7 +146,7 @@ gst_pad_template_class_init (GstPadTemplateClass * klass)
   gst_pad_template_signals[TEMPL_PAD_CREATED] =
       g_signal_new ("pad-created", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstPadTemplateClass, pad_created),
-      NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD);
+      NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_PAD);
 
   gobject_class->dispose = gst_pad_template_dispose;
 
@@ -230,6 +230,8 @@ gst_pad_template_dispose (GObject * object)
     gst_caps_unref (GST_PAD_TEMPLATE_CAPS (templ));
   }
 
+  gst_caps_replace (&templ->ABI.abi.documentation_caps, NULL);
+
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
@@ -479,6 +481,52 @@ gst_pad_template_get_caps (GstPadTemplate * templ)
 }
 
 /**
+ * gst_pad_template_set_documentation_caps:
+ * @templ: the pad template to set documented capabilities on
+ * @caps: (transfer full): the documented capabilities
+ *
+ * Certain elements will dynamically construct the caps of their
+ * pad templates. In order not to let environment-specific information
+ * into the documentation, element authors should use this method to
+ * expose "stable" caps to the reader.
+ *
+ * Since: 1.18
+ */
+void
+gst_pad_template_set_documentation_caps (GstPadTemplate * templ, GstCaps * caps)
+{
+  g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
+  g_return_if_fail (GST_IS_CAPS (caps));
+
+  if (caps)
+    GST_MINI_OBJECT_FLAG_SET (caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
+  gst_caps_replace (&(((GstPadTemplate *) (templ))->ABI.abi.documentation_caps),
+      caps);
+}
+
+/**
+ * gst_pad_template_get_documentation_caps:
+ * @templ: the pad template to get documented capabilities on
+ *
+ * See gst_pad_template_set_documentation_caps().
+ *
+ * Returns: The caps to document. For convenience, this will return
+ *   gst_pad_template_get_caps() when no documentation caps were set.
+ * Since: 1.18
+ */
+GstCaps *
+gst_pad_template_get_documentation_caps (GstPadTemplate * templ)
+{
+  g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
+
+  if (((GstPadTemplate *) (templ))->ABI.abi.documentation_caps)
+    return gst_caps_ref (((GstPadTemplate *) (templ))->ABI.abi.
+        documentation_caps);
+  else
+    return gst_pad_template_get_caps (templ);
+}
+
+/**
  * gst_pad_template_pad_created:
  * @templ: a #GstPadTemplate that has been created
  * @pad:   the #GstPad that created it
index fb15c40..0736818 100644 (file)
@@ -141,6 +141,7 @@ struct _GstPadTemplate {
     gpointer _gst_reserved[GST_PADDING];
     struct {
       GType gtype;
+      GstCaps *documentation_caps;
     } abi;
   } ABI;
 };
@@ -200,6 +201,9 @@ struct _GstStaticPadTemplate {
 GST_API
 GType                  gst_pad_template_get_type               (void);
 
+/**
+ * gst_static_pad_template_get_type: (attributes doc.skip=true)
+ */
 GST_API
 GType                  gst_static_pad_template_get_type        (void);
 
@@ -226,11 +230,15 @@ GST_API
 GstCaps*               gst_pad_template_get_caps               (GstPadTemplate *templ);
 
 GST_API
+void        gst_pad_template_set_documentation_caps (GstPadTemplate *templ, GstCaps *caps);
+
+GST_API
+GstCaps*    gst_pad_template_get_documentation_caps (GstPadTemplate *templ);
+
+GST_API
 void                    gst_pad_template_pad_created            (GstPadTemplate * templ, GstPad * pad);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPadTemplate, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 7de51d7..39c378c 100644 (file)
@@ -123,7 +123,7 @@ _gst_param_fraction_values_cmp (GParamSpec * pspec, const GValue * value1,
 GType
 gst_param_spec_fraction_get_type (void)
 {
-  static volatile GType gst_faction_type = 0;
+  static GType gst_faction_type = 0;
 
   /* register GST_TYPE_PARAM_FRACTION */
   if (g_once_init_enter (&gst_faction_type)) {
@@ -304,7 +304,7 @@ _gst_param_array_values_cmp (GParamSpec * pspec, const GValue * value1,
 GType
 gst_param_spec_array_get_type (void)
 {
-  static volatile GType gst_array_type = 0;
+  static GType gst_array_type = 0;
 
   /* register GST_TYPE_PARAM_FRACTION */
   if (g_once_init_enter (&gst_array_type)) {
index 4f5d8e3..ff35507 100644 (file)
@@ -61,6 +61,29 @@ G_BEGIN_DECLS
 #define GST_PARAM_MUTABLE_PLAYING  (1 << (G_PARAM_USER_SHIFT + 4))
 
 /**
+ * GST_PARAM_DOC_SHOW_DEFAULT: (value 8192)
+ *
+ * Use this flag on GObject properties of GstObject to indicate that
+ * during `gst-inspect` and friends, the default value should be used
+ * as default instead of the current value.
+ *
+ * Since: 1.18
+ */
+#define GST_PARAM_DOC_SHOW_DEFAULT  (1 << (G_PARAM_USER_SHIFT + 5))
+
+/**
+ * GST_PARAM_CONDITIONALLY_AVAILABLE: (value 16384)
+ *
+ * Use this flag on GObject properties of GstObject to indicate that
+ * they might not be available depending on environment such as OS, device, etc,
+ * so such properties will be installed conditionally only if the GstObject is
+ * able to support it.
+ *
+ * Since: 1.18
+ */
+#define GST_PARAM_CONDITIONALLY_AVAILABLE  (1 << (G_PARAM_USER_SHIFT + 6))
+
+/**
  * GST_PARAM_USER_SHIFT: (value 65536)
  *
  * Bits based on GST_PARAM_USER_SHIFT can be used by 3rd party applications.
@@ -70,10 +93,25 @@ G_BEGIN_DECLS
 
 /* --- type macros --- */
 
+/**
+ * GstParamFraction:
+ *
+ * A fundamental type that describes a #GParamSpec for fractional
+ * properties
+ */
+
 #define GST_TYPE_PARAM_FRACTION           (gst_param_spec_fraction_get_type ())
 #define GST_IS_PARAM_SPEC_FRACTION(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GST_TYPE_PARAM_FRACTION))
 #define GST_PARAM_SPEC_FRACTION(pspec)    (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GST_TYPE_PARAM_FRACTION, GstParamSpecFraction))
 
+/**
+ * GstParamArray:
+ *
+ * A fundamental type that describes a #GParamSpec for arrays of
+ * values
+ *
+ * Since: 1.12
+ */
 
 #define GST_TYPE_PARAM_ARRAY_LIST           (gst_param_spec_array_get_type ())
 #define GST_IS_PARAM_SPEC_ARRAY_LIST(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GST_TYPE_PARAM_ARRAY_LIST))
index 9f97637..b44d345 100644 (file)
@@ -100,6 +100,8 @@ gst_parse_context_new (void)
  * Copies the @context.
  *
  * Returns: (transfer full) (nullable): A copied #GstParseContext
+ *
+ * Since: 1.12.1
  */
 GstParseContext *
 gst_parse_context_copy (const GstParseContext * context)
@@ -216,7 +218,7 @@ _gst_parse_escape (const gchar * str)
  * @error will contain an error message if an erroneous pipeline is specified.
  * An error does not mean that the pipeline could not be constructed.
  *
- * Returns: (transfer floating) (nullable): a new element on success and %NULL
+ * Returns: (transfer floating): a new element on success and %NULL
  * on failure.
  */
 GstElement *
@@ -237,7 +239,7 @@ gst_parse_launchv (const gchar ** argv, GError ** error)
  * @error will contain an error message if an erroneous pipeline is specified.
  * An error does not mean that the pipeline could not be constructed.
  *
- * Returns: (transfer floating) (nullable): a new element on success; on
+ * Returns: (transfer floating): a new element on success; on
  *   failure, either %NULL or a partially-constructed bin or element will be
  *   returned and @error will be set (unless you passed
  *   #GST_PARSE_FLAG_FATAL_ERRORS in @flags, then %NULL will always be returned
@@ -291,7 +293,10 @@ gst_parse_launchv_full (const gchar ** argv, GstParseContext * context,
  * the @error is set. In this case there was a recoverable parsing error and you
  * can try to play the pipeline.
  *
- * Returns: (transfer floating) (nullable): a new element on success, %NULL on
+ * To create a sub-pipeline (bin) for embedding into an existing pipeline
+ * use gst_parse_bin_from_description().
+ *
+ * Returns: (transfer floating): a new element on success, %NULL on
  *   failure. If more than one toplevel element is specified by the
  *   @pipeline_description, all elements are put into a #GstPipeline, which
  *   than is returned.
@@ -316,7 +321,10 @@ gst_parse_launch (const gchar * pipeline_description, GError ** error)
  * the @error is set. In this case there was a recoverable parsing error and you
  * can try to play the pipeline.
  *
- * Returns: (transfer floating) (nullable): a new element on success, %NULL on
+ * To create a sub-pipeline (bin) for embedding into an existing pipeline
+ * use gst_parse_bin_from_description_full().
+ *
+ * Returns: (transfer floating): a new element on success, %NULL on
  *    failure. If more than one toplevel element is specified by the
  *    @pipeline_description, all elements are put into a #GstPipeline, which
  *    then is returned (unless the GST_PARSE_FLAG_PLACE_IN_BIN flag is set, in
index c0cef77..8dfe8e5 100644 (file)
@@ -131,9 +131,7 @@ GstElement      * gst_parse_launchv_full (const gchar     ** argv,
                                           GstParseFlags      flags,
                                           GError          ** error) G_GNUC_MALLOC;
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstParseContext, gst_parse_context_free)
-#endif
 
 G_END_DECLS
 
index ca9091b..b5bbb45 100644 (file)
  * methods like gst_bin_add() and gst_bin_remove() (see #GstBin).
  *
  * Before changing the state of the #GstPipeline (see #GstElement) a #GstBus
- * can be retrieved with gst_pipeline_get_bus(). This bus can then be
- * used to receive #GstMessage from the elements in the pipeline.
+ * should be retrieved with gst_pipeline_get_bus(). This #GstBus should then
+ * be used to receive #GstMessage from the elements in the pipeline. Listening
+ * to the #GstBus is necessary for retrieving error messages from the
+ * #GstPipeline and otherwise the #GstPipeline might stop without any
+ * indication, why. Furthermore, the #GstPipeline posts messages even if
+ * nobody listens on the #GstBus, which will pile up and use up memory.
  *
  * By default, a #GstPipeline will automatically flush the pending #GstBus
  * messages when going to the NULL state to ensure that no circular
@@ -109,6 +113,7 @@ struct _GstPipelinePrivate
 {
   /* with LOCK */
   gboolean auto_flush_bus;
+  gboolean is_live;
 
   /* when we need to update stream_time or clock when going back to
    * PLAYING*/
@@ -116,6 +121,12 @@ struct _GstPipelinePrivate
   gboolean update_clock;
 
   GstClockTime latency;
+
+  /* seqnum of the most recent instant-rate-request, %GST_SEQNUM_INVALID if none */
+  guint32 instant_rate_seqnum;
+  gdouble active_instant_rate;
+  GstClockTime instant_rate_upstream_anchor;
+  GstClockTime instant_rate_clock_anchor;
 };
 
 
@@ -131,6 +142,8 @@ static GstStateChangeReturn gst_pipeline_change_state (GstElement * element,
 
 static void gst_pipeline_handle_message (GstBin * bin, GstMessage * message);
 static gboolean gst_pipeline_do_latency (GstBin * bin);
+static gboolean gst_pipeline_handle_instant_rate (GstPipeline * pipeline,
+    gdouble rate, guint32 seqnum);
 
 /* static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 }; */
 
@@ -220,6 +233,8 @@ gst_pipeline_init (GstPipeline * pipeline)
   pipeline->delay = DEFAULT_DELAY;
   pipeline->priv->latency = DEFAULT_LATENCY;
 
+  pipeline->priv->is_live = FALSE;
+
   /* create and set a default bus */
   bus = gst_bus_new ();
 #if 0
@@ -302,6 +317,15 @@ reset_start_time (GstPipeline * pipeline, GstClockTime start_time)
     GST_DEBUG_OBJECT (pipeline, "reset start_time to 0");
     GST_ELEMENT_START_TIME (pipeline) = start_time;
     pipeline->priv->last_start_time = -1;
+
+    /* Reset instant rate multiplier because we flushed / reset time.
+     * Old anchor's don't make sense */
+    pipeline->priv->instant_rate_seqnum = GST_SEQNUM_INVALID;
+    pipeline->priv->instant_rate_upstream_anchor =
+        pipeline->priv->instant_rate_clock_anchor = GST_CLOCK_TIME_NONE;
+    pipeline->priv->active_instant_rate = 1.0;
+    GST_DEBUG_OBJECT (pipeline, "Reset start time to %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (start_time));
   } else {
     GST_DEBUG_OBJECT (pipeline, "application asked to not reset stream_time");
   }
@@ -495,6 +519,7 @@ gst_pipeline_change_state (GstElement * element, GstStateChange transition)
       break;
     }
     case GST_STATE_CHANGE_PAUSED_TO_READY:
+      pipeline->priv->is_live = FALSE;
       reset_start_time (pipeline, 0);
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
@@ -503,6 +528,12 @@ gst_pipeline_change_state (GstElement * element, GstStateChange transition)
 
   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
 
+  if (GST_STATE_TRANSITION_NEXT (transition) == GST_STATE_PAUSED) {
+    pipeline->priv->is_live = result == GST_STATE_CHANGE_NO_PREROLL;
+    GST_INFO_OBJECT (pipeline, "pipeline is%slive",
+        pipeline->priv->is_live ? " " : " not ");
+  }
+
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_NULL:
       break;
@@ -575,6 +606,12 @@ invalid_clock:
  * the PAUSED, pending PAUSED state. When the ASYNC_DONE message is received the
  * pipeline will redistribute the new base_time and will bring the elements back
  * to the desired state of the pipeline. */
+/* GST_MESSAGE_INSTANT_RATE_REQUEST: This message is only posted by sinks and
+ *     bins containing sinks (which are also considered sinks). Once all sinks
+ *     have posted this message it is posted to the parent bin, or if this is
+ *     a top-level bin (e.g. pipeline), a instant-rate-sync-time event with
+ *     the current running time is sent to the whole pipeline.
+ */
 static void
 gst_pipeline_handle_message (GstBin * bin, GstMessage * message)
 {
@@ -590,6 +627,14 @@ gst_pipeline_handle_message (GstBin * bin, GstMessage * message)
       /* reset our running time if we need to distribute a new base_time to the
        * children. */
       reset_start_time (pipeline, running_time);
+
+      /* If we are live, sample a new base_time immediately */
+      if (pipeline->priv->is_live
+          && GST_STATE_TARGET (pipeline) == GST_STATE_PLAYING) {
+        gst_pipeline_change_state (GST_ELEMENT (pipeline),
+            GST_STATE_CHANGE_PAUSED_TO_PLAYING);
+      }
+
       break;
     }
     case GST_MESSAGE_CLOCK_LOST:
@@ -606,6 +651,18 @@ gst_pipeline_handle_message (GstBin * bin, GstMessage * message)
       }
       GST_OBJECT_UNLOCK (bin);
     }
+      break;
+
+    case GST_MESSAGE_INSTANT_RATE_REQUEST:{
+      guint32 seqnum = gst_message_get_seqnum (message);
+      gdouble rate_multiplier;
+
+      gst_message_parse_instant_rate_request (message, &rate_multiplier);
+
+      gst_pipeline_handle_instant_rate (pipeline, rate_multiplier, seqnum);
+
+      break;
+    }
     default:
       break;
   }
@@ -1026,3 +1083,88 @@ gst_pipeline_get_latency (GstPipeline * pipeline)
 
   return latency;
 }
+
+static gboolean
+gst_pipeline_handle_instant_rate (GstPipeline * pipeline, gdouble rate,
+    guint32 seqnum)
+{
+  GstClockTime running_time = GST_CLOCK_TIME_NONE;
+  GstClockTime upstream_running_time = GST_CLOCK_TIME_NONE;
+  gboolean is_playing;
+  GstEvent *event;
+
+  GST_OBJECT_LOCK (pipeline);
+
+  if (pipeline->priv->instant_rate_seqnum != GST_SEQNUM_INVALID &&
+      pipeline->priv->instant_rate_seqnum == seqnum) {
+    GST_DEBUG_OBJECT (pipeline,
+        "Handling duplicate instant-rate-request message with seqnum %u",
+        seqnum);
+    upstream_running_time = pipeline->priv->instant_rate_upstream_anchor;
+    running_time = pipeline->priv->instant_rate_clock_anchor;
+
+    if (G_UNLIKELY (rate != pipeline->priv->active_instant_rate)) {
+      GST_WARNING_OBJECT (pipeline,
+          "Repeated instant-rate-request has a different rate to before! %f != %f",
+          rate, pipeline->priv->active_instant_rate);
+      rate = pipeline->priv->active_instant_rate;
+    }
+  } else {
+    /* Get the current running time of the pipeline */
+    is_playing = GST_STATE (pipeline) == GST_STATE_PLAYING
+        && (GST_STATE_PENDING (pipeline) == GST_STATE_VOID_PENDING ||
+        GST_STATE_PENDING (pipeline) == GST_STATE_PLAYING);
+
+    if (is_playing) {
+      GstClockTime base_time, clock_time;
+      GstClock *clock;
+
+      base_time = GST_ELEMENT_CAST (pipeline)->base_time;
+      clock = GST_ELEMENT_CLOCK (pipeline);
+
+      if (clock) {
+        clock_time = gst_clock_get_time (clock);
+        running_time = clock_time - base_time;
+      }
+    } else {
+      running_time = GST_ELEMENT_START_TIME (pipeline);
+    }
+
+    if (!GST_CLOCK_TIME_IS_VALID (running_time)) {
+      GST_OBJECT_UNLOCK (pipeline);
+      return FALSE;
+    }
+
+    if (GST_CLOCK_TIME_IS_VALID (pipeline->priv->instant_rate_upstream_anchor)) {
+      /* Already had an override, calculate the adjustment due to that
+       * elapsed duration */
+      GstClockTime elapsed =
+          running_time - pipeline->priv->instant_rate_clock_anchor;
+      pipeline->priv->instant_rate_upstream_anchor +=
+          elapsed * pipeline->priv->active_instant_rate;
+      pipeline->priv->instant_rate_clock_anchor = running_time;
+    } else {
+      /* Else this is the first override event */
+      pipeline->priv->instant_rate_upstream_anchor =
+          pipeline->priv->instant_rate_clock_anchor = running_time;
+    }
+    upstream_running_time = pipeline->priv->instant_rate_upstream_anchor;
+
+    pipeline->priv->instant_rate_seqnum = seqnum;
+    pipeline->priv->active_instant_rate = rate;
+  }
+
+  GST_OBJECT_UNLOCK (pipeline);
+
+  GST_DEBUG_OBJECT (pipeline,
+      "Instant rate multiplier to %f rt %" GST_TIME_FORMAT " upstream %"
+      GST_TIME_FORMAT, rate, GST_TIME_ARGS (running_time),
+      GST_TIME_ARGS (upstream_running_time));
+
+  event =
+      gst_event_new_instant_rate_sync_time (rate, running_time,
+      upstream_running_time);
+  gst_event_set_seqnum (event, seqnum);
+
+  return gst_element_send_event (GST_ELEMENT_CAST (pipeline), event);
+}
index ac0befb..6406fb8 100644 (file)
@@ -130,9 +130,7 @@ void            gst_pipeline_set_auto_flush_bus (GstPipeline *pipeline, gboolean
 GST_API
 gboolean        gst_pipeline_get_auto_flush_bus (GstPipeline *pipeline);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPipeline, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 70c942d..da2221f 100644 (file)
  * @see_also: #GstPluginFeature, #GstElementFactory
  *
  * GStreamer is extensible, so #GstElement instances can be loaded at runtime.
- * A plugin system can provide one or more of the basic
- * <application>GStreamer</application> #GstPluginFeature subclasses.
+ * A plugin system can provide one or more of the basic GStreamer
+ * #GstPluginFeature subclasses.
  *
- * A plugin should export a symbol <symbol>gst_plugin_desc</symbol> that is a
+ * A plugin should export a symbol `gst_plugin_desc` that is a
  * struct of type #GstPluginDesc.
  * the plugin loader will check the version of the core library the plugin was
  * linked against and will create a new #GstPlugin. It will then call the
  * #GstPluginInitFunc function that was provided in the
- * <symbol>gst_plugin_desc</symbol>.
+ * `gst_plugin_desc`.
  *
  * Once you have a handle to a #GstPlugin (e.g. from the #GstRegistry), you
  * can add any object that subclasses #GstPluginFeature.
 
 #include <gst/gst.h>
 
+#ifdef G_OS_WIN32
+#include <windows.h>
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+#define GST_WINAPI_ONLY_APP
+#endif
+#endif
+
 #define GST_CAT_DEFAULT GST_CAT_PLUGIN_LOADING
 
 static guint _num_static_plugins;       /* 0    */
@@ -79,33 +86,29 @@ static gchar **_plugin_loading_whitelist;       /* NULL */
 /* static variables for segfault handling of plugin loading */
 static char *_gst_plugin_fault_handler_filename = NULL;
 
-/* list of valid licenses.
- * One of these must be specified or the plugin won't be loaded
- * Please file a bug to request any additional license be added.
- *
- * GPL: http://www.gnu.org/copyleft/gpl.html
- * LGPL: http://www.gnu.org/copyleft/lesser.html
- * QPL: http://www.trolltech.com/licenses/qpl.html
- * MPL: http://www.opensource.org/licenses/mozilla1.1.php
- * MIT/X11: http://www.opensource.org/licenses/mit-license.php
+/* List of known licenses:
+ * GPL: https://opensource.org/licenses/gpl-license
+ * LGPL: https://opensource.org/licenses/lgpl-license
+ * QPL: https://opensource.org/licenses/QPL-1.0
+ * MPL: https://opensource.org/licenses/MPL-1.1
+ * MPL-2.0: https://opensource.org/licenses/MPL-2.0
+ * MIT/X11: https://opensource.org/licenses/MIT
  * 3-clause BSD: https://opensource.org/licenses/BSD-3-Clause
  * Zero-Clause BSD: https://opensource.org/licenses/0BSD
+ * FIXME: update to use SPDX identifiers, or just remove entirely
  */
-static const gchar valid_licenses[] = "LGPL\000"        /* GNU Lesser General Public License */
+static const gchar known_licenses[] = "LGPL\000"        /* GNU Lesser General Public License */
     "GPL\000"                   /* GNU General Public License */
     "QPL\000"                   /* Trolltech Qt Public License */
     "GPL/QPL\000"               /* Combi-license of GPL + QPL */
     "MPL\000"                   /* MPL 1.1 license */
+    "MPL-2.0\000"               /* MPL 2.0 license */
     "BSD\000"                   /* 3-clause BSD license */
     "MIT/X11\000"               /* MIT/X11 license */
     "0BSD\000"                  /* Zero-Clause BSD */
     "Proprietary\000"           /* Proprietary license */
     GST_LICENSE_UNKNOWN;        /* some other license */
 
-static const guint8 valid_licenses_idx[] = { 0, 5, 9, 13, 21, 25, 29, 37, 42,
-  54
-};
-
 static GstPlugin *gst_plugin_register_func (GstPlugin * plugin,
     const GstPluginDesc * desc, gpointer user_data);
 static void gst_plugin_desc_copy (GstPluginDesc * dest,
@@ -455,12 +458,13 @@ priv_gst_plugin_loading_get_whitelist_hash (void)
 static gboolean
 gst_plugin_check_license (const gchar * license)
 {
-  gint i;
+  const gchar *l, *end = known_licenses + sizeof (known_licenses);
 
-  for (i = 0; i < G_N_ELEMENTS (valid_licenses_idx); ++i) {
-    if (strcmp (license, valid_licenses + valid_licenses_idx[i]) == 0)
+  for (l = known_licenses; l < end; l += strlen (l) + 1) {
+    if (strcmp (license, l) == 0)
       return TRUE;
   }
+
   return FALSE;
 }
 
@@ -482,7 +486,7 @@ gst_plugin_register_func (GstPlugin * plugin, const GstPluginDesc * desc,
   if (!gst_plugin_check_version (desc->major_version, desc->minor_version)) {
     if (GST_CAT_DEFAULT)
       GST_WARNING ("plugin \"%s\" has incompatible version "
-          "(plugin: %d.%d, gst: %d,%d), not loading",
+          "(plugin: %d.%d, gst: %d.%d), not loading",
           GST_STR_NULL (plugin->filename), desc->major_version,
           desc->minor_version, GST_VERSION_MAJOR, GST_VERSION_MINOR);
     return NULL;
@@ -498,9 +502,9 @@ gst_plugin_register_func (GstPlugin * plugin, const GstPluginDesc * desc,
 
   if (!gst_plugin_check_license (desc->license)) {
     if (GST_CAT_DEFAULT)
-      GST_WARNING ("plugin \"%s\" has invalid license \"%s\", not loading",
+      GST_WARNING ("plugin \"%s\" has unknown license \"%s\"",
           GST_STR_NULL (plugin->filename), desc->license);
-    return NULL;
+    /* We still want to load the plugin, it's not our job to validate licenses */
   }
 
   if (GST_CAT_DEFAULT)
@@ -767,7 +771,12 @@ _priv_gst_plugin_load_file_for_registry (const gchar * filename,
         GST_PLUGIN_ERROR_MODULE, "Dynamic loading not supported");
     goto return_error;
   }
-
+#if defined(GST_WINAPI_ONLY_APP)
+  /* plugins loaded by filename by Universal Windows Platform apps do not use
+   * an actual file with a path, they use a packaged (asset) library */
+  file_status.st_mtime = 0;
+  file_status.st_size = 0;
+#else
   if (g_stat (filename, &file_status)) {
     GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING, "problem accessing file");
     g_set_error (error,
@@ -776,6 +785,7 @@ _priv_gst_plugin_load_file_for_registry (const gchar * filename,
         g_strerror (errno));
     goto return_error;
   }
+#endif
 
   flags = G_MODULE_BIND_LOCAL;
   /* libgstpython.so is the gst-python plugin loader. It needs to be loaded with
@@ -972,7 +982,7 @@ gst_plugin_get_description (GstPlugin * plugin)
  *
  * get the filename of the plugin
  *
- * Returns: (type filename): the filename of the plugin
+ * Returns: (type filename) (nullable): the filename of the plugin
  */
 const gchar *
 gst_plugin_get_filename (GstPlugin * plugin)
index 94ceeac..7bb3356 100644 (file)
@@ -395,9 +395,7 @@ void                    gst_plugin_add_dependency_simple (GstPlugin   * plugin,
 GST_API
 void                    gst_plugin_list_free (GList *list);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPlugin, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 831236e..ac61cc0 100644 (file)
@@ -124,6 +124,8 @@ gst_plugin_feature_load (GstPluginFeature * feature)
   else if (!real_feature->loaded)
     goto not_found;
 
+  GST_TRACER_PLUGIN_FEATURE_LOADED (real_feature);
+
   return real_feature;
 
   /* ERRORS */
@@ -405,3 +407,97 @@ gst_plugin_feature_rank_compare_func (gconstpointer p1, gconstpointer p2)
 
   return diff;
 }
+
+static gboolean
+parse_feature_name (gchar * str, const gchar ** feature)
+{
+  if (!str)
+    return FALSE;
+
+  /* works in place */
+  g_strstrip (str);
+
+  if (str[0] != '\0') {
+    *feature = str;
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+static gboolean
+parse_feature_rank (gchar * str, GstRank * rank)
+{
+  if (!str)
+    return FALSE;
+
+  /* works in place */
+  g_strstrip (str);
+
+  if (g_ascii_isdigit (str[0])) {
+    unsigned long l;
+    char *endptr;
+    l = strtoul (str, &endptr, 10);
+    if (endptr > str && endptr[0] == 0) {
+      *rank = (GstRank) l;
+    } else {
+      return FALSE;
+    }
+  } else if (g_ascii_strcasecmp (str, "NONE") == 0) {
+    *rank = GST_RANK_NONE;
+  } else if (g_ascii_strcasecmp (str, "MARGINAL") == 0) {
+    *rank = GST_RANK_MARGINAL;
+  } else if (g_ascii_strcasecmp (str, "SECONDARY") == 0) {
+    *rank = GST_RANK_SECONDARY;
+  } else if (g_ascii_strcasecmp (str, "PRIMARY") == 0) {
+    *rank = GST_RANK_PRIMARY;
+  } else if (g_ascii_strcasecmp (str, "MAX") == 0) {
+    *rank = (GstRank) G_MAXINT;
+  } else {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+void
+_priv_gst_plugin_feature_rank_initialize (void)
+{
+  const gchar *env;
+  gchar **split;
+  gchar **walk;
+
+  env = g_getenv ("GST_PLUGIN_FEATURE_RANK");
+
+  if (!env)
+    return;
+
+  split = g_strsplit (env, ",", 0);
+
+  for (walk = split; *walk; walk++) {
+    if (strchr (*walk, ':')) {
+      gchar **values = g_strsplit (*walk, ":", 2);
+
+      if (values[0] && values[1]) {
+        GstRank rank;
+        const gchar *str;
+
+        if (parse_feature_name (values[0], &str)
+            && parse_feature_rank (values[1], &rank)) {
+          GstPluginFeature *feature;
+
+          feature = gst_registry_find_feature (gst_registry_get (), str,
+              GST_TYPE_ELEMENT_FACTORY);
+          if (feature) {
+            gst_plugin_feature_set_rank (feature, rank);
+            GST_DEBUG ("Update rank of plugin feature \"%s\" to %d", str, rank);
+          }
+        }
+      }
+
+      g_strfreev (values);
+    }
+  }
+
+  g_strfreev (split);
+}
index d8db095..87f3707 100644 (file)
@@ -155,9 +155,7 @@ GST_API
 gint            gst_plugin_feature_rank_compare_func    (gconstpointer p1,
                                                         gconstpointer p2);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPluginFeature, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index a933a4b..4e0f646 100644 (file)
@@ -171,8 +171,11 @@ plugin_loader_free (GstPluginLoader * loader)
 {
   GList *cur;
   gboolean got_plugin_details;
+  gint fsync_ret;
 
-  fsync (loader->fd_w.fd);
+  do {
+    fsync_ret = fsync (loader->fd_w.fd);
+  } while (fsync_ret < 0 && errno == EINTR);
 
   if (loader->child_running) {
     put_packet (loader, PACKET_EXIT, 0, NULL, 0);
@@ -378,7 +381,7 @@ plugin_loader_create_blacklist_plugin (GstPluginLoader * l,
 static gboolean
 gst_plugin_loader_use_usr_bin_arch (void)
 {
-  static volatile gsize multiarch = 0;
+  static gsize multiarch = 0;
 
   if (g_once_init_enter (&multiarch)) {
     gsize res = NO_MULTIARCH;
@@ -461,20 +464,19 @@ gst_plugin_loader_spawn (GstPluginLoader * loader)
   if (loader->child_running)
     return TRUE;
 
-  /* Find the gst-plugin-scanner: first try the env-var if it is set,
-   * otherwise use the installed version */
+  /* Find the gst-plugin-scanner */
   env = g_getenv ("GST_PLUGIN_SCANNER_1_0");
   if (env == NULL)
     env = g_getenv ("GST_PLUGIN_SCANNER");
 
   if (env != NULL && *env != '\0') {
+    /* use the env-var if it is set */
     GST_LOG ("Trying GST_PLUGIN_SCANNER env var: %s", env);
     helper_bin = g_strdup (env);
     res = gst_plugin_loader_try_helper (loader, helper_bin);
     g_free (helper_bin);
-  }
-
-  if (!res) {
+  } else {
+    /* use the installed version */
     GST_LOG ("Trying installed plugin scanner");
 
 #ifdef G_OS_WIN32
@@ -494,10 +496,10 @@ gst_plugin_loader_spawn (GstPluginLoader * loader)
 #endif
     res = gst_plugin_loader_try_helper (loader, helper_bin);
     g_free (helper_bin);
+  }
 
-    if (!res) {
-      GST_INFO ("No gst-plugin-scanner available, or not working");
-    }
+  if (!res) {
+    GST_INFO ("No gst-plugin-scanner available, or not working");
   }
 
   return loader->child_running;
index 5e0a668..f5f10bc 100644 (file)
@@ -28,7 +28,7 @@
  *                     to wait on them in a cancellable way
  *
  * A #GstPoll keeps track of file descriptors much like fd_set (used with
- * select()) or a struct pollfd array (used with poll()). Once created with
+ * select ()) or a struct pollfd array (used with poll ()). Once created with
  * gst_poll_new(), the set can be used to wait for file descriptors to be
  * readable and/or writable. It is possible to make this wait be controlled
  * by specifying %TRUE for the @controllable flag when creating the set (or
@@ -151,11 +151,11 @@ struct _GstPoll
 #endif
 
   gboolean controllable;
-  volatile gint waiting;
-  volatile gint control_pending;
-  volatile gint flushing;
+  gint waiting;
+  gint control_pending;
+  gint flushing;
   gboolean timer;
-  volatile gint rebuild;
+  gint rebuild;
 };
 
 static gboolean gst_poll_fd_ctl_read_unlocked (GstPoll * set, GstPollFD * fd,
index 7584c5b..ed25b5b 100644 (file)
@@ -622,7 +622,7 @@ gst_preset_default_get_property_names (GstPreset * preset)
         g_free (props);
       }
 
-      g_object_unref (child);
+      gst_object_unref (child);
     }
   }
   if (!result) {
@@ -1054,7 +1054,7 @@ no_presets:
  *
  * Get a copy of preset names as a %NULL terminated string array.
  *
- * Returns: (transfer full) (array zero-terminated=1) (element-type gchar*):
+ * Returns: (transfer full) (array zero-terminated=1) (element-type utf8):
  *     list with names, use g_strfreev() after usage.
  */
 gchar **
@@ -1071,7 +1071,7 @@ gst_preset_get_preset_names (GstPreset * preset)
  *
  * Get a the names of the GObject properties that can be used for presets.
  *
- * Returns: (transfer full) (array zero-terminated=1) (element-type gchar*): an
+ * Returns: (transfer full) (array zero-terminated=1) (element-type utf8): an
  *   array of property names which should be freed with g_strfreev() after use.
  */
 gchar **
@@ -1322,7 +1322,7 @@ gst_preset_base_init (gpointer g_class)
 GType
 gst_preset_get_type (void)
 {
-  static volatile gsize type = 0;
+  static gsize type = 0;
 
   if (g_once_init_enter (&type)) {
     GType _type;
index e8e971a..322d603 100644 (file)
@@ -21,6 +21,7 @@
 # include "config.h"
 #endif
 
+#define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 #include "gst_private.h"
 
 #include "gstpromise.h"
@@ -32,18 +33,19 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
  * SECTION:gstpromise
  * @title: GstPromise
  * @short_description: a miniobject for future/promise-like functionality
- * @see_also:
  *
  * The #GstPromise object implements the container for values that may
  * be available later. i.e. a Future or a Promise in
- * <ulink url="https://en.wikipedia.org/wiki/Futures_and_promises">https://en.wikipedia.org/wiki/Futures_and_promises</ulink>
+ * <https://en.wikipedia.org/wiki/Futures_and_promises>.
  * As with all Future/Promise-like functionality, there is the concept of the
  * producer of the value and the consumer of the value.
  *
  * A #GstPromise is created with gst_promise_new() by the consumer and passed
  * to the producer to avoid thread safety issues with the change callback.
  * A #GstPromise can be replied to with a value (or an error) by the producer
- * with gst_promise_reply(). gst_promise_interrupt() is for the consumer to
+ * with gst_promise_reply(). The exact value returned is defined by the API
+ * contract of the producer and %NULL may be a valid reply.
+ * gst_promise_interrupt() is for the consumer to
  * indicate to the producer that the value is not needed anymore and producing
  * that value can stop.  The @GST_PROMISE_RESULT_EXPIRED state set by a call
  * to gst_promise_expire() indicates to the consumer that a value will never
@@ -148,7 +150,7 @@ gst_promise_wait (GstPromise * promise)
 /**
  * gst_promise_reply:
  * @promise: (allow-none): a #GstPromise
- * @s: (transfer full): a #GstStructure with the the reply contents
+ * @s: (transfer full) (nullable): a #GstStructure with the the reply contents
  *
  * Set a reply on @promise.  This will wake up any waiters with
  * %GST_PROMISE_RESULT_REPLIED.  Called by the producer of the value to
@@ -219,7 +221,7 @@ gst_promise_reply (GstPromise * promise, GstStructure * s)
  * Retrieve the reply set on @promise.  @promise must be in
  * %GST_PROMISE_RESULT_REPLIED and the returned structure is owned by @promise
  *
- * Returns: (transfer none): The reply set on @promise
+ * Returns: (transfer none) (nullable): The reply set on @promise
  *
  * Since: 1.14
  */
@@ -345,7 +347,7 @@ gst_promise_free (GstMiniObject * object)
 static void
 gst_promise_init (GstPromise * promise)
 {
-  static volatile gsize _init = 0;
+  static gsize _init = 0;
 
   if (g_once_init_enter (&_init)) {
     GST_DEBUG_CATEGORY_INIT (gst_promise_debug, "gstpromise", 0, "gstpromise");
@@ -407,3 +409,34 @@ gst_promise_new_with_change_func (GstPromiseChangeFunc func, gpointer user_data,
 }
 
 GST_DEFINE_MINI_OBJECT_TYPE (GstPromise, gst_promise);
+
+/**
+ * gst_promise_ref:
+ * @promise: a #GstPromise.
+ *
+ * Increases the refcount of the given @promise by one.
+ *
+ * Returns: (transfer full): @promise
+ *
+ * Since: 1.14
+ */
+GstPromise *
+gst_promise_ref (GstPromise * promise)
+{
+  return (GstPromise *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (promise));
+}
+
+/**
+ * gst_promise_unref:
+ * @promise: (transfer full): a #GstPromise.
+ *
+ * Decreases the refcount of the promise. If the refcount reaches 0, the
+ * promise will be freed.
+ *
+ * Since: 1.14
+ */
+void
+gst_promise_unref (GstPromise * promise)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (promise));
+}
index a09cc4f..b9ea6ba 100644 (file)
@@ -93,40 +93,27 @@ void                    gst_promise_expire                  (GstPromise * promis
 GST_API
 const GstStructure *    gst_promise_get_reply               (GstPromise * promise);
 
-/**
- * gst_promise_ref:
- * @promise: a #GstPromise.
- *
- * Increases the refcount of the given @promise by one.
- *
- * Returns: (transfer full): @promise
- *
- * Since: 1.14
- */
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 static inline GstPromise *
 gst_promise_ref (GstPromise * promise)
 {
   return (GstPromise *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (promise));
 }
 
-/**
- * gst_promise_unref:
- * @promise: (transfer full): a #GstPromise.
- *
- * Decreases the refcount of the promise. If the refcount reaches 0, the
- * promise will be freed.
- *
- * Since: 1.14
- */
 static inline void
 gst_promise_unref (GstPromise * promise)
 {
   gst_mini_object_unref (GST_MINI_OBJECT_CAST (promise));
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+GstPromise *  gst_promise_ref (GstPromise * promise);
+
+GST_API
+void          gst_promise_unref (GstPromise * promise);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPromise, gst_promise_unref)
-#endif
 
 G_END_DECLS
 
index af0434a..73deed8 100644 (file)
@@ -56,7 +56,7 @@ static const gchar *gst_protection_factory_check (GstElementFactory * fact,
 GType
 gst_protection_meta_api_get_type (void)
 {
-  static volatile GType type;
+  static GType type;
   static const gchar *tags[] = { NULL };
 
   if (g_once_init_enter (&type)) {
@@ -134,8 +134,7 @@ gst_protection_meta_get_info (void)
  *
  * Attaches protection metadata to a #GstBuffer.
  *
- * Returns: (transfer none): a pointer to the added #GstProtectionMeta if successful; %NULL if
- * unsuccessful.
+ * Returns: (transfer none): a pointer to the added #GstProtectionMeta if successful
  *
  * Since: 1.6
  */
index f77a7bf..d0d4ba9 100644 (file)
@@ -70,6 +70,9 @@ struct _GstProtectionMeta
   GstStructure *info;
 };
 
+/**
+ * gst_protection_meta_api_get_type: (attributes doc.skip=true)
+ */
 GST_API
 GType gst_protection_meta_api_get_type (void);
 
index caa5c8c..93c35b2 100644 (file)
@@ -80,6 +80,10 @@ static const gchar *_quark_strings[] = {
 #ifdef TIZEN_PROFILE_TV
   "GstQuarkQueryResource",
 #endif
+  "GstEventInstantRateChange",
+  "GstEventInstantRateSyncTime", "GstMessageInstantRateRequest",
+  "upstream-running-time", "base", "offset", "plugin-api", "plugin-api-flags",
+  "gap-flags"
 };
 
 GQuark _priv_gst_quark_table[GST_QUARK_MAX];
index d69fec7..855d89f 100644 (file)
@@ -222,11 +222,20 @@ typedef enum _GstQuarkId
   GST_QUARK_MESSAGE_DEVICE_CHANGED = 191,
   GST_QUARK_DEVICE_CHANGED = 192,
   GST_QUARK_TRICKMODE_INTERVAL = 193,
+  GST_QUARK_EVENT_INSTANT_RATE_CHANGE = 194,
+  GST_QUARK_EVENT_INSTANT_RATE_SYNC_TIME = 195,
+  GST_QUARK_MESSAGE_INSTANT_RATE_REQUEST = 196,
+  GST_QUARK_UPSTREAM_RUNNING_TIME = 197,
+  GST_QUARK_BASE = 198,
+  GST_QUARK_OFFSET = 199,
+  GST_QUARK_PLUGIN_API = 200,
+  GST_QUARK_PLUGIN_API_FLAGS = 201,
+  GST_QUARK_GAP_FLAGS = 202,
 #ifndef TIZEN_PROFILE_TV
-  GST_QUARK_MAX = 194
+  GST_QUARK_MAX = 203
 #else
-  GST_QUARK_QUERY_RESOURCE = 194,
-  GST_QUARK_MAX = 195
+  GST_QUARK_QUERY_RESOURCE = 203,
+  GST_QUARK_MAX = 204
 #endif
 } GstQuarkId;
 
index 6c2147d..d0a2b2a 100644 (file)
@@ -53,7 +53,7 @@
  * ]|
  */
 
-
+#define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 #include "gst_private.h"
 #include "gstinfo.h"
 #include "gstquery.h"
@@ -2792,3 +2792,112 @@ gst_query_parse_bitrate (GstQuery * query, guint * nominal_bitrate)
     *nominal_bitrate = g_value_get_uint (value);
   }
 }
+
+/**
+ * gst_query_ref:
+ * @q: a #GstQuery to increase the refcount of.
+ *
+ * Increases the refcount of the given query by one.
+ *
+ * Returns: @q
+ */
+GstQuery *
+gst_query_ref (GstQuery * q)
+{
+  return GST_QUERY_CAST (gst_mini_object_ref (GST_MINI_OBJECT_CAST (q)));
+}
+
+/**
+ * gst_query_unref: (skip)
+ * @q: a #GstQuery to decrease the refcount of.
+ *
+ * Decreases the refcount of the query. If the refcount reaches 0, the query
+ * will be freed.
+ */
+void
+gst_query_unref (GstQuery * q)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (q));
+}
+
+/**
+ * gst_clear_query: (skip)
+ * @query_ptr: a pointer to a #GstQuery reference
+ *
+ * Clears a reference to a #GstQuery.
+ *
+ * @query_ptr must not be %NULL.
+ *
+ * If the reference is %NULL then this function does nothing. Otherwise, the
+ * reference count of the query is decreased and the pointer is set to %NULL.
+ *
+ * Since: 1.16
+ */
+void
+gst_clear_query (GstQuery ** query_ptr)
+{
+  gst_clear_mini_object ((GstMiniObject **) query_ptr);
+}
+
+/**
+ * gst_query_copy: (skip)
+ * @q: a #GstQuery to copy.
+ *
+ * Copies the given query using the copy function of the parent #GstStructure.
+ *
+ * Free-function: gst_query_unref
+ *
+ * Returns: (transfer full): a new copy of @q.
+ */
+GstQuery *
+gst_query_copy (const GstQuery * q)
+{
+  return GST_QUERY_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (q)));
+}
+
+/**
+ * gst_query_replace: (skip)
+ * @old_query: (inout) (transfer full) (nullable): 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
+ */
+gboolean
+gst_query_replace (GstQuery ** old_query, GstQuery * new_query)
+{
+  return gst_mini_object_replace ((GstMiniObject **) old_query,
+      (GstMiniObject *) new_query);
+}
+
+/**
+ * gst_query_take:
+ * @old_query: (inout) (transfer full) (nullable): pointer to a
+ *     pointer to a #GstQuery to be stolen.
+ * @new_query: (allow-none) (transfer full): 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. This
+ * function is similar to gst_query_replace() except that it takes ownership of
+ * @new_query.
+ *
+ * Either @new_query or the #GstQuery pointed to by @old_query may be %NULL.
+ *
+ * Returns: %TRUE if @new_query was different from @old_query
+ *
+ * Since: 1.16
+ */
+gboolean
+gst_query_take (GstQuery ** old_query, GstQuery * new_query)
+{
+  return gst_mini_object_take ((GstMiniObject **) old_query,
+      (GstMiniObject *) new_query);
+}
index 6bc6020..5d5460b 100644 (file)
@@ -74,7 +74,7 @@ typedef enum {
 #define GST_QUERY_MAKE_TYPE(num,flags) \
     (((num) << GST_QUERY_NUM_SHIFT) | (flags))
 
-#define FLAG(name) GST_QUERY_TYPE_##name
+#define _FLAG(name) GST_QUERY_TYPE_##name
 
 
 /**
@@ -107,30 +107,30 @@ typedef enum {
  * this enum */
 typedef enum {
   GST_QUERY_UNKNOWN      = GST_QUERY_MAKE_TYPE (0, 0),
-  GST_QUERY_POSITION     = GST_QUERY_MAKE_TYPE (10, FLAG(BOTH)),
-  GST_QUERY_DURATION     = GST_QUERY_MAKE_TYPE (20, FLAG(BOTH)),
-  GST_QUERY_LATENCY      = GST_QUERY_MAKE_TYPE (30, FLAG(BOTH)),
-  GST_QUERY_JITTER       = GST_QUERY_MAKE_TYPE (40, FLAG(BOTH)),
-  GST_QUERY_RATE         = GST_QUERY_MAKE_TYPE (50, FLAG(BOTH)),
-  GST_QUERY_SEEKING      = GST_QUERY_MAKE_TYPE (60, FLAG(BOTH)),
-  GST_QUERY_SEGMENT      = GST_QUERY_MAKE_TYPE (70, FLAG(BOTH)),
-  GST_QUERY_CONVERT      = GST_QUERY_MAKE_TYPE (80, FLAG(BOTH)),
-  GST_QUERY_FORMATS      = GST_QUERY_MAKE_TYPE (90, FLAG(BOTH)),
-  GST_QUERY_BUFFERING    = GST_QUERY_MAKE_TYPE (110, FLAG(BOTH)),
-  GST_QUERY_CUSTOM       = GST_QUERY_MAKE_TYPE (120, FLAG(BOTH)),
-  GST_QUERY_URI          = GST_QUERY_MAKE_TYPE (130, FLAG(BOTH)),
-  GST_QUERY_ALLOCATION   = GST_QUERY_MAKE_TYPE (140, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
-  GST_QUERY_SCHEDULING   = GST_QUERY_MAKE_TYPE (150, FLAG(UPSTREAM)),
-  GST_QUERY_ACCEPT_CAPS  = GST_QUERY_MAKE_TYPE (160, FLAG(BOTH)),
-  GST_QUERY_CAPS         = GST_QUERY_MAKE_TYPE (170, FLAG(BOTH)),
-  GST_QUERY_DRAIN        = GST_QUERY_MAKE_TYPE (180, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
-  GST_QUERY_CONTEXT      = GST_QUERY_MAKE_TYPE (190, FLAG(BOTH)),
-  GST_QUERY_BITRATE      = GST_QUERY_MAKE_TYPE (200, FLAG(DOWNSTREAM)),
+  GST_QUERY_POSITION     = GST_QUERY_MAKE_TYPE (10, _FLAG(BOTH)),
+  GST_QUERY_DURATION     = GST_QUERY_MAKE_TYPE (20, _FLAG(BOTH)),
+  GST_QUERY_LATENCY      = GST_QUERY_MAKE_TYPE (30, _FLAG(BOTH)),
+  GST_QUERY_JITTER       = GST_QUERY_MAKE_TYPE (40, _FLAG(BOTH)),
+  GST_QUERY_RATE         = GST_QUERY_MAKE_TYPE (50, _FLAG(BOTH)),
+  GST_QUERY_SEEKING      = GST_QUERY_MAKE_TYPE (60, _FLAG(BOTH)),
+  GST_QUERY_SEGMENT      = GST_QUERY_MAKE_TYPE (70, _FLAG(BOTH)),
+  GST_QUERY_CONVERT      = GST_QUERY_MAKE_TYPE (80, _FLAG(BOTH)),
+  GST_QUERY_FORMATS      = GST_QUERY_MAKE_TYPE (90, _FLAG(BOTH)),
+  GST_QUERY_BUFFERING    = GST_QUERY_MAKE_TYPE (110, _FLAG(BOTH)),
+  GST_QUERY_CUSTOM       = GST_QUERY_MAKE_TYPE (120, _FLAG(BOTH)),
+  GST_QUERY_URI          = GST_QUERY_MAKE_TYPE (130, _FLAG(BOTH)),
+  GST_QUERY_ALLOCATION   = GST_QUERY_MAKE_TYPE (140, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED)),
+  GST_QUERY_SCHEDULING   = GST_QUERY_MAKE_TYPE (150, _FLAG(UPSTREAM)),
+  GST_QUERY_ACCEPT_CAPS  = GST_QUERY_MAKE_TYPE (160, _FLAG(BOTH)),
+  GST_QUERY_CAPS         = GST_QUERY_MAKE_TYPE (170, _FLAG(BOTH)),
+  GST_QUERY_DRAIN        = GST_QUERY_MAKE_TYPE (180, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED)),
+  GST_QUERY_CONTEXT      = GST_QUERY_MAKE_TYPE (190, _FLAG(BOTH)),
+  GST_QUERY_BITRATE      = GST_QUERY_MAKE_TYPE (200, _FLAG(DOWNSTREAM)),
 #ifdef TIZEN_PROFILE_TV
   GST_QUERY_RESOURCE     = GST_QUERY_MAKE_TYPE (210, FLAG (BOTH)), /*< skip >*/
 #endif
 } GstQueryType;
-#undef FLAG
+#undef _FLAG
 
 GST_API GType _gst_query_type;
 
@@ -231,47 +231,20 @@ GstQueryTypeFlags
 GST_API
 GType           gst_query_get_type             (void);
 
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 /* refcounting */
-/**
- * gst_query_ref:
- * @q: a #GstQuery to increase the refcount of.
- *
- * Increases the refcount of the given query by one.
- *
- * Returns: @q
- */
 static inline GstQuery *
 gst_query_ref (GstQuery * q)
 {
   return GST_QUERY_CAST (gst_mini_object_ref (GST_MINI_OBJECT_CAST (q)));
 }
 
-/**
- * gst_query_unref:
- * @q: a #GstQuery to decrease the refcount of.
- *
- * Decreases the refcount of the query. If the refcount reaches 0, the query
- * will be freed.
- */
 static inline void
 gst_query_unref (GstQuery * q)
 {
   gst_mini_object_unref (GST_MINI_OBJECT_CAST (q));
 }
 
-/**
- * gst_clear_query: (skip)
- * @query_ptr: a pointer to a #GstQuery reference
- *
- * Clears a reference to a #GstQuery.
- *
- * @query_ptr must not be %NULL.
- *
- * If the reference is %NULL then this function does nothing. Otherwise, the
- * reference count of the query is decreased and the pointer is set to %NULL.
- *
- * Since: 1.16
- */
 static inline void
 gst_clear_query (GstQuery ** query_ptr)
 {
@@ -279,21 +252,24 @@ gst_clear_query (GstQuery ** query_ptr)
 }
 
 /* copy query */
-/**
- * gst_query_copy:
- * @q: a #GstQuery to copy.
- *
- * Copies the given query using the copy function of the parent #GstStructure.
- *
- * Free-function: gst_query_unref
- *
- * Returns: (transfer full): a new copy of @q.
- */
 static inline GstQuery *
 gst_query_copy (const GstQuery * q)
 {
   return GST_QUERY_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (q)));
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+GstQuery *  gst_query_ref   (GstQuery * q);
+
+GST_API
+void        gst_query_unref (GstQuery * q);
+
+GST_API
+void        gst_clear_query (GstQuery ** query_ptr);
+
+GST_API
+GstQuery *  gst_query_copy  (const GstQuery * q);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 /**
  * gst_query_is_writable:
@@ -311,51 +287,29 @@ 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) (nullable): 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
- */
+
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 static inline gboolean
 gst_query_replace (GstQuery **old_query, GstQuery *new_query)
 {
   return gst_mini_object_replace ((GstMiniObject **) old_query, (GstMiniObject *) new_query);
 }
 
-/**
- * gst_query_take:
- * @old_query: (inout) (transfer full) (nullable): pointer to a
- *     pointer to a #GstQuery to be stolen.
- * @new_query: (allow-none) (transfer full): 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. This
- * function is similar to gst_query_replace() except that it takes ownership of
- * @new_query.
- *
- * Either @new_query or the #GstQuery pointed to by @old_query may be %NULL.
- *
- * Returns: %TRUE if @new_query was different from @old_query
- *
- * Since: 1.16
- */
 static inline gboolean
 gst_query_take (GstQuery **old_query, GstQuery *new_query)
 {
   return gst_mini_object_take ((GstMiniObject **) old_query,
       (GstMiniObject *) new_query);
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+gboolean        gst_query_replace               (GstQuery ** old_query,
+                                                 GstQuery * new_query);
+
+GST_API
+gboolean        gst_query_take                  (GstQuery ** old_query,
+                                                 GstQuery * new_query);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 /* application specific query */
 
@@ -714,9 +668,7 @@ void            gst_query_set_bitrate              (GstQuery * query, guint nomi
 GST_API
 void            gst_query_parse_bitrate            (GstQuery * query, guint * nominal_bitrate);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstQuery, gst_query_unref)
-#endif
 
 G_END_DECLS
 
index 7efe0ca..6831966 100644 (file)
@@ -74,7 +74,7 @@ typedef enum {
 #define GST_QUERY_MAKE_TYPE(num,flags) \
     (((num) << GST_QUERY_NUM_SHIFT) | (flags))
 
-#define FLAG(name) GST_QUERY_TYPE_##name
+#define _FLAG(name) GST_QUERY_TYPE_##name
 
 
 /**
@@ -107,28 +107,28 @@ typedef enum {
  * this enum */
 typedef enum {
   GST_QUERY_UNKNOWN      = GST_QUERY_MAKE_TYPE (0, 0),
-  GST_QUERY_POSITION     = GST_QUERY_MAKE_TYPE (10, FLAG(BOTH)),
-  GST_QUERY_DURATION     = GST_QUERY_MAKE_TYPE (20, FLAG(BOTH)),
-  GST_QUERY_LATENCY      = GST_QUERY_MAKE_TYPE (30, FLAG(BOTH)),
-  GST_QUERY_JITTER       = GST_QUERY_MAKE_TYPE (40, FLAG(BOTH)),
-  GST_QUERY_RATE         = GST_QUERY_MAKE_TYPE (50, FLAG(BOTH)),
-  GST_QUERY_SEEKING      = GST_QUERY_MAKE_TYPE (60, FLAG(BOTH)),
-  GST_QUERY_SEGMENT      = GST_QUERY_MAKE_TYPE (70, FLAG(BOTH)),
-  GST_QUERY_CONVERT      = GST_QUERY_MAKE_TYPE (80, FLAG(BOTH)),
-  GST_QUERY_FORMATS      = GST_QUERY_MAKE_TYPE (90, FLAG(BOTH)),
-  GST_QUERY_BUFFERING    = GST_QUERY_MAKE_TYPE (110, FLAG(BOTH)),
-  GST_QUERY_CUSTOM       = GST_QUERY_MAKE_TYPE (120, FLAG(BOTH)),
-  GST_QUERY_URI          = GST_QUERY_MAKE_TYPE (130, FLAG(BOTH)),
-  GST_QUERY_ALLOCATION   = GST_QUERY_MAKE_TYPE (140, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
-  GST_QUERY_SCHEDULING   = GST_QUERY_MAKE_TYPE (150, FLAG(UPSTREAM)),
-  GST_QUERY_ACCEPT_CAPS  = GST_QUERY_MAKE_TYPE (160, FLAG(BOTH)),
-  GST_QUERY_CAPS         = GST_QUERY_MAKE_TYPE (170, FLAG(BOTH)),
-  GST_QUERY_DRAIN        = GST_QUERY_MAKE_TYPE (180, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
-  GST_QUERY_CONTEXT      = GST_QUERY_MAKE_TYPE (190, FLAG(BOTH)),
-  GST_QUERY_BITRATE      = GST_QUERY_MAKE_TYPE (200, FLAG(DOWNSTREAM)),
+  GST_QUERY_POSITION     = GST_QUERY_MAKE_TYPE (10, _FLAG(BOTH)),
+  GST_QUERY_DURATION     = GST_QUERY_MAKE_TYPE (20, _FLAG(BOTH)),
+  GST_QUERY_LATENCY      = GST_QUERY_MAKE_TYPE (30, _FLAG(BOTH)),
+  GST_QUERY_JITTER       = GST_QUERY_MAKE_TYPE (40, _FLAG(BOTH)),
+  GST_QUERY_RATE         = GST_QUERY_MAKE_TYPE (50, _FLAG(BOTH)),
+  GST_QUERY_SEEKING      = GST_QUERY_MAKE_TYPE (60, _FLAG(BOTH)),
+  GST_QUERY_SEGMENT      = GST_QUERY_MAKE_TYPE (70, _FLAG(BOTH)),
+  GST_QUERY_CONVERT      = GST_QUERY_MAKE_TYPE (80, _FLAG(BOTH)),
+  GST_QUERY_FORMATS      = GST_QUERY_MAKE_TYPE (90, _FLAG(BOTH)),
+  GST_QUERY_BUFFERING    = GST_QUERY_MAKE_TYPE (110, _FLAG(BOTH)),
+  GST_QUERY_CUSTOM       = GST_QUERY_MAKE_TYPE (120, _FLAG(BOTH)),
+  GST_QUERY_URI          = GST_QUERY_MAKE_TYPE (130, _FLAG(BOTH)),
+  GST_QUERY_ALLOCATION   = GST_QUERY_MAKE_TYPE (140, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED)),
+  GST_QUERY_SCHEDULING   = GST_QUERY_MAKE_TYPE (150, _FLAG(UPSTREAM)),
+  GST_QUERY_ACCEPT_CAPS  = GST_QUERY_MAKE_TYPE (160, _FLAG(BOTH)),
+  GST_QUERY_CAPS         = GST_QUERY_MAKE_TYPE (170, _FLAG(BOTH)),
+  GST_QUERY_DRAIN        = GST_QUERY_MAKE_TYPE (180, _FLAG(DOWNSTREAM) | _FLAG(SERIALIZED)),
+  GST_QUERY_CONTEXT      = GST_QUERY_MAKE_TYPE (190, _FLAG(BOTH)),
+  GST_QUERY_BITRATE      = GST_QUERY_MAKE_TYPE (200, _FLAG(DOWNSTREAM)),
   GST_QUERY_RESOURCE     = GST_QUERY_MAKE_TYPE (210, FLAG (BOTH)),
 } GstQueryType;
-#undef FLAG
+#undef _FLAG
 
 GST_API GType _gst_query_type;
 
@@ -229,47 +229,20 @@ GstQueryTypeFlags
 GST_API
 GType           gst_query_get_type             (void);
 
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 /* refcounting */
-/**
- * gst_query_ref:
- * @q: a #GstQuery to increase the refcount of.
- *
- * Increases the refcount of the given query by one.
- *
- * Returns: @q
- */
 static inline GstQuery *
 gst_query_ref (GstQuery * q)
 {
   return GST_QUERY_CAST (gst_mini_object_ref (GST_MINI_OBJECT_CAST (q)));
 }
 
-/**
- * gst_query_unref:
- * @q: a #GstQuery to decrease the refcount of.
- *
- * Decreases the refcount of the query. If the refcount reaches 0, the query
- * will be freed.
- */
 static inline void
 gst_query_unref (GstQuery * q)
 {
   gst_mini_object_unref (GST_MINI_OBJECT_CAST (q));
 }
 
-/**
- * gst_clear_query: (skip)
- * @query_ptr: a pointer to a #GstQuery reference
- *
- * Clears a reference to a #GstQuery.
- *
- * @query_ptr must not be %NULL.
- *
- * If the reference is %NULL then this function does nothing. Otherwise, the
- * reference count of the query is decreased and the pointer is set to %NULL.
- *
- * Since: 1.16
- */
 static inline void
 gst_clear_query (GstQuery ** query_ptr)
 {
@@ -277,21 +250,24 @@ gst_clear_query (GstQuery ** query_ptr)
 }
 
 /* copy query */
-/**
- * gst_query_copy:
- * @q: a #GstQuery to copy.
- *
- * Copies the given query using the copy function of the parent #GstStructure.
- *
- * Free-function: gst_query_unref
- *
- * Returns: (transfer full): a new copy of @q.
- */
 static inline GstQuery *
 gst_query_copy (const GstQuery * q)
 {
   return GST_QUERY_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (q)));
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+GstQuery *  gst_query_ref   (GstQuery * q);
+
+GST_API
+void        gst_query_unref (GstQuery * q);
+
+GST_API
+void        gst_clear_query (GstQuery ** query_ptr);
+
+GST_API
+GstQuery *  gst_query_copy  (const GstQuery * q);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 /**
  * gst_query_is_writable:
@@ -309,51 +285,29 @@ 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) (nullable): 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
- */
+
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 static inline gboolean
 gst_query_replace (GstQuery **old_query, GstQuery *new_query)
 {
   return gst_mini_object_replace ((GstMiniObject **) old_query, (GstMiniObject *) new_query);
 }
 
-/**
- * gst_query_take:
- * @old_query: (inout) (transfer full) (nullable): pointer to a
- *     pointer to a #GstQuery to be stolen.
- * @new_query: (allow-none) (transfer full): 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. This
- * function is similar to gst_query_replace() except that it takes ownership of
- * @new_query.
- *
- * Either @new_query or the #GstQuery pointed to by @old_query may be %NULL.
- *
- * Returns: %TRUE if @new_query was different from @old_query
- *
- * Since: 1.16
- */
 static inline gboolean
 gst_query_take (GstQuery **old_query, GstQuery *new_query)
 {
   return gst_mini_object_take ((GstMiniObject **) old_query,
       (GstMiniObject *) new_query);
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+gboolean        gst_query_replace               (GstQuery ** old_query,
+                                                 GstQuery * new_query);
+
+GST_API
+gboolean        gst_query_take                  (GstQuery ** old_query,
+                                                 GstQuery * new_query);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 /* application specific query */
 
@@ -712,9 +666,7 @@ void            gst_query_set_bitrate              (GstQuery * query, guint nomi
 GST_API
 void            gst_query_parse_bitrate            (GstQuery * query, guint * nominal_bitrate);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstQuery, gst_query_unref)
-#endif
 
 G_END_DECLS
 
index a8b2f51..2e09033 100644 (file)
 extern HMODULE _priv_gst_dll_handle;
 #endif
 
+/* Use a toolchain-dependent suffix on Windows */
+#ifdef G_OS_WIN32
+# ifdef _MSC_VER
+#  define GST_REGISTRY_FILE_SUFFIX TARGET_CPU "-msvc"
+# else
+#  define GST_REGISTRY_FILE_SUFFIX TARGET_CPU "-mingw"
+# endif
+#else
+# define GST_REGISTRY_FILE_SUFFIX TARGET_CPU
+#endif
+#define GST_REGISTRY_FILE_NAME "registry." GST_REGISTRY_FILE_SUFFIX ".bin"
+
+
 #define GST_CAT_DEFAULT GST_CAT_REGISTRY
 
 struct _GstRegistryPrivate
@@ -215,8 +228,7 @@ 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, 0, NULL, NULL, g_cclosure_marshal_generic,
-      G_TYPE_NONE, 1, GST_TYPE_PLUGIN);
+      G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_PLUGIN);
 
   /**
    * GstRegistry::feature-added:
@@ -228,7 +240,7 @@ 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, 0, NULL, NULL, g_cclosure_marshal_generic,
+      G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
       G_TYPE_NONE, 1, GST_TYPE_PLUGIN_FEATURE);
 
   gobject_class->finalize = gst_registry_finalize;
@@ -381,8 +393,8 @@ was_added:
  *
  * Get the list of paths for the given registry.
  *
- * Returns: (transfer container) (element-type char*): A #GList of paths as
- *     strings. g_list_free after use.
+ * Returns: (transfer container) (element-type filename): A #GList of
+ *     paths as strings. g_list_free after use.
  *
  * MT safe.
  */
@@ -1006,7 +1018,7 @@ gst_registry_lookup_feature_locked (GstRegistry * registry, const char *name)
  *
  * Find a #GstPluginFeature with @name in @registry.
  *
- * Returns: (transfer full): a #GstPluginFeature with its refcount incremented,
+ * Returns: (transfer full) (nullable): a #GstPluginFeature with its refcount incremented,
  *     use gst_object_unref() after usage.
  *
  * MT safe.
@@ -1198,8 +1210,13 @@ gst_registry_scan_plugin_file (GstRegistryScanContext * context,
 }
 
 static gboolean
-is_blacklisted_hidden_directory (const gchar * dirent)
+is_blacklisted_directory (const gchar * dirent)
 {
+  /* hotdoc private folder can contain many files and it slows down
+   * the discovery for nothing */
+  if (g_str_has_prefix (dirent, "hotdoc-private-"))
+    return TRUE;
+
   if (G_LIKELY (dirent[0] != '.'))
     return FALSE;
 
@@ -1242,7 +1259,7 @@ gst_registry_scan_path_level (GstRegistryScanContext * context,
     }
 
     if (file_status.st_mode & S_IFDIR) {
-      if (G_UNLIKELY (is_blacklisted_hidden_directory (dirent))) {
+      if (G_UNLIKELY (is_blacklisted_directory (dirent))) {
         GST_TRACE_OBJECT (context->registry, "ignoring %s directory", dirent);
         g_free (filename);
         continue;
@@ -1425,6 +1442,24 @@ gst_registry_get_feature_list_by_plugin (GstRegistry * registry,
       _gst_plugin_feature_filter_plugin_name, FALSE, (gpointer) name);
 }
 
+/* Private function for getting plugin features directly */
+GList *
+_priv_plugin_get_features (GstRegistry * registry, GstPlugin * plugin)
+{
+  GList *res = NULL;
+  GList *walk;
+
+  GST_OBJECT_LOCK (registry);
+  for (walk = registry->priv->features; walk; walk = walk->next) {
+    GstPluginFeature *feat = (GstPluginFeature *) walk->data;
+    if (feat->plugin == plugin)
+      res = g_list_prepend (res, gst_object_ref (feat));
+  }
+  GST_OBJECT_UNLOCK (registry);
+
+  return res;
+}
+
 /* Unref and delete the default registry */
 void
 _priv_gst_registry_cleanup (void)
@@ -1713,7 +1748,7 @@ ensure_current_registry (GError ** error)
     registry_file = g_strdup (g_getenv ("GST_REGISTRY"));
   if (registry_file == NULL) {
     registry_file = g_build_filename (g_get_user_cache_dir (),
-        "gstreamer-" GST_API_VERSION, "registry." TARGET_CPU ".bin", NULL);
+        "gstreamer-" GST_API_VERSION, GST_REGISTRY_FILE_NAME, NULL);
   }
 
   if (!_gst_disable_registry_cache) {
@@ -1840,10 +1875,12 @@ gst_update_registry (void)
   res = TRUE;
 #endif /* GST_DISABLE_REGISTRY */
 
+#ifndef GST_DISABLE_OPTION_PARSING
   if (_priv_gst_preload_plugins) {
     GST_DEBUG ("Preloading indicated plugins...");
     g_slist_foreach (_priv_gst_preload_plugins, load_plugin_func, NULL);
   }
+#endif
 
   return res;
 }
index a5ae603..4b8f368 100644 (file)
@@ -124,9 +124,7 @@ gboolean                gst_registry_check_feature_version (GstRegistry *registr
                                                             guint        min_minor,
                                                             guint        min_micro);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstRegistry, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 2e6451b..db2846f 100644 (file)
@@ -167,18 +167,19 @@ typedef struct BinaryRegistryCache
   const char *location;
   char *tmp_location;
   unsigned long currentoffset;
-  int cache_fd;
+  FILE *cache_file;
 } BinaryRegistryCache;
 
 static BinaryRegistryCache *
 gst_registry_binary_cache_init (GstRegistry * registry, const char *location)
 {
   BinaryRegistryCache *cache = g_slice_new0 (BinaryRegistryCache);
+  int fd;
 
   cache->location = location;
   cache->tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL);
-  cache->cache_fd = g_mkstemp (cache->tmp_location);
-  if (cache->cache_fd == -1) {
+  fd = g_mkstemp (cache->tmp_location);
+  if (fd == -1) {
     int ret;
     GStatBuf statbuf;
     gchar *dir;
@@ -197,9 +198,9 @@ gst_registry_binary_cache_init (GstRegistry * registry, const char *location)
     /* the previous g_mkstemp call overwrote the XXXXXX placeholder ... */
     g_free (cache->tmp_location);
     cache->tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL);
-    cache->cache_fd = g_mkstemp (cache->tmp_location);
+    fd = g_mkstemp (cache->tmp_location);
 
-    if (cache->cache_fd == -1) {
+    if (fd == -1) {
       GST_DEBUG ("g_mkstemp() failed: %s", g_strerror (errno));
       g_free (cache->tmp_location);
       g_slice_free (BinaryRegistryCache, cache);
@@ -212,6 +213,15 @@ gst_registry_binary_cache_init (GstRegistry * registry, const char *location)
     }
   }
 
+  cache->cache_file = fdopen (fd, "w");
+  if (!cache->cache_file) {
+    GST_DEBUG ("fdopen() failed: %s", g_strerror (errno));
+    close (fd);
+    g_free (cache->tmp_location);
+    g_slice_free (BinaryRegistryCache, cache);
+    return NULL;
+  }
+
   return cache;
 }
 
@@ -221,7 +231,7 @@ gst_registry_binary_cache_write (BinaryRegistryCache * cache,
 {
   long written;
   if (offset != cache->currentoffset) {
-    if (lseek (cache->cache_fd, offset, SEEK_SET) < 0) {
+    if (fseek (cache->cache_file, offset, SEEK_SET) < 0) {
       GST_ERROR ("Seeking to new offset failed: %s", g_strerror (errno));
       return -1;
     }
@@ -229,7 +239,7 @@ gst_registry_binary_cache_write (BinaryRegistryCache * cache,
     cache->currentoffset = offset;
   }
 
-  written = write (cache->cache_fd, data, length);
+  written = fwrite (data, 1, length, cache->cache_file);
   if (written != length) {
     GST_ERROR ("Failed to write to cache file");
   }
@@ -241,21 +251,46 @@ gst_registry_binary_cache_write (BinaryRegistryCache * cache,
 static gboolean
 gst_registry_binary_cache_finish (BinaryRegistryCache * cache, gboolean success)
 {
-  /* only fsync if we're actually going to use and rename the file below */
-  if (success && fsync (cache->cache_fd) < 0)
-    goto fsync_failed;
+  gint fclose_ret;
+
+  if (success) {
+    /* flush the file and make sure the OS's buffer has been written to disk */
+    gint fflush_ret, fsync_ret;
+    int file_fd;
+
+    file_fd = fileno (cache->cache_file);
+
+    do {
+      fflush_ret = fflush (cache->cache_file);
+    } while (fflush_ret && errno == EINTR);
+    if (fflush_ret)
+      goto fflush_failed;
+
+    do {
+      fsync_ret = fsync (file_fd);
+    } while (fsync_ret < 0 && errno == EINTR);
+    if (fsync_ret < 0)
+      goto fsync_failed;
+  }
 
-  if (close (cache->cache_fd) < 0)
-    goto close_failed;
+  /* close the file, even when unsuccessful, so not to leak a file descriptor.
+   * We must not retry fclose() on EINTR as POSIX states:
+   *   After the call to fclose(), any use of stream results in undefined
+   *   behavior.
+   * We ensure above with fflush() and fsync() that everything is written out
+   * so chances of running into EINTR are very low. Nonetheless assume that
+   * the file can't be safely renamed, we'll just try again on the next
+   * opportunity. */
+  fclose_ret = fclose (cache->cache_file);
+  if (fclose_ret)
+    goto fclose_failed;
 
   if (!success)
-    goto fail_after_close;
+    goto fail_after_fclose;
 
   /* Only do the rename if we wrote the entire file successfully */
-  if (g_rename (cache->tmp_location, cache->location) < 0) {
-    GST_ERROR ("g_rename() failed: %s", g_strerror (errno));
+  if (g_rename (cache->tmp_location, cache->location) < 0)
     goto rename_failed;
-  }
 
   g_free (cache->tmp_location);
   g_slice_free (BinaryRegistryCache, cache);
@@ -263,27 +298,37 @@ gst_registry_binary_cache_finish (BinaryRegistryCache * cache, gboolean success)
   return TRUE;
 
 /* ERRORS */
-fail_after_close:
+fail_before_fclose:
+  {
+    fclose (cache->cache_file);
+  }
+  /* fall through */
+fail_after_fclose:
   {
     g_unlink (cache->tmp_location);
     g_free (cache->tmp_location);
     g_slice_free (BinaryRegistryCache, cache);
     return FALSE;
   }
+fflush_failed:
+  {
+    GST_ERROR ("fflush() failed: %s", g_strerror (errno));
+    goto fail_before_fclose;
+  }
 fsync_failed:
   {
     GST_ERROR ("fsync() failed: %s", g_strerror (errno));
-    goto fail_after_close;
+    goto fail_before_fclose;
   }
-close_failed:
+fclose_failed:
   {
-    GST_ERROR ("close() failed: %s", g_strerror (errno));
-    goto fail_after_close;
+    GST_ERROR ("fclose() failed: %s", g_strerror (errno));
+    goto fail_after_fclose;
   }
 rename_failed:
   {
     GST_ERROR ("g_rename() failed: %s", g_strerror (errno));
-    goto fail_after_close;
+    goto fail_after_fclose;
   }
 }
 #endif
index f83ac2f..80d0d4f 100644 (file)
 #include <gst/gstinfo.h>
 #include <gst/gstenumtypes.h>
 #include <gst/gstpadtemplate.h>
-#ifdef TIZEN_FEATURE_UPSTREAM
 #include "glib-compat-private.h"
-#endif /* TIZEN_FEATURE_UPSTREAM */
 
 #include <gst/gstregistrychunks.h>
 
 #define GST_CAT_DEFAULT GST_CAT_REGISTRY
 
 /* count string length, but return -1 if we hit the eof */
-static gint
+#ifdef HAVE_STRNLEN
+static inline gint
+_strnlen (const gchar * str, gint maxlen)
+{
+  gint len = strnlen (str, maxlen);
+
+  if (G_UNLIKELY (len == maxlen))
+    return -1;
+  return len;
+}
+#else
+static inline gint
 _strnlen (const gchar * str, gint maxlen)
 {
   gint len = 0;
@@ -61,6 +70,7 @@ _strnlen (const gchar * str, gint maxlen)
   }
   return -1;
 }
+#endif
 
 /* Macros */
 #define unpack_element(inptr, outptr, element, endptr, error_label) G_STMT_START{ \
@@ -82,7 +92,6 @@ _strnlen (const gchar * str, gint maxlen)
   inptr += _len + 1; \
 }G_STMT_END
 
-#ifdef TIZEN_FEATURE_UPSTREAM
 #define unpack_string(inptr, outptr, endptr, error_label)  G_STMT_START{\
   gint _len = _strnlen (inptr, (endptr-inptr)); \
   if (_len == -1) \
@@ -90,15 +99,6 @@ _strnlen (const gchar * str, gint maxlen)
   outptr = g_memdup2 ((gconstpointer)inptr, _len + 1); \
   inptr += _len + 1; \
 }G_STMT_END
-#else /* TIZEN_FEATURE_UPSTREAM */
-#define unpack_string(inptr, outptr, endptr, error_label)  G_STMT_START{\
-  gint _len = _strnlen (inptr, (endptr-inptr)); \
-  if (_len == -1) \
-    goto error_label; \
-  outptr = g_memdup ((gconstpointer)inptr, _len + 1); \
-  inptr += _len + 1; \
-}G_STMT_END
-#endif /* TIZEN_FEATURE_UPSTREAM */
 
 #define unpack_string_nocopy(inptr, outptr, endptr, error_label)  G_STMT_START{\
   gint _len = _strnlen (inptr, (endptr-inptr)); \
@@ -461,8 +461,7 @@ _priv_gst_registry_chunks_save_plugin (GList ** list, GstRegistry * registry,
   }
 
   /* pack plugin features */
-  plugin_features =
-      gst_registry_get_feature_list_by_plugin (registry, plugin->desc.name);
+  plugin_features = _priv_plugin_get_features (registry, plugin);
   for (walk = plugin_features; walk; walk = g_list_next (walk), pe->nfeatures++) {
     GstPluginFeature *feature = GST_PLUGIN_FEATURE (walk->data);
 
@@ -496,8 +495,8 @@ _priv_gst_registry_chunks_save_plugin (GList ** list, GstRegistry * registry,
 
   *list = g_list_prepend (*list, chk);
 
-  GST_DEBUG ("Found %d features in plugin \"%s\"", pe->nfeatures,
-      plugin->desc.name);
+  GST_DEBUG ("Found %d features in plugin %p (%s)", pe->nfeatures,
+      plugin, plugin->desc.name);
   return TRUE;
 
   /* Errors */
@@ -589,11 +588,11 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
         plugin_name);
     return FALSE;
   }
-  if (G_UNLIKELY ((feature = g_object_new (type, NULL)) == NULL)) {
+  if (G_UNLIKELY ((feature =
+              g_object_new (type, "name", feature_name, NULL)) == NULL)) {
     GST_ERROR ("Can't create feature from type");
     return FALSE;
   }
-  gst_plugin_feature_set_name (feature, feature_name);
 
   if (G_UNLIKELY (!GST_IS_PLUGIN_FEATURE (feature))) {
     GST_ERROR ("typename : '%s' is not a plugin feature", type_name);
@@ -748,10 +747,7 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
 fail:
   GST_INFO ("Reading plugin feature failed");
   if (feature) {
-    if (GST_IS_OBJECT (feature))
-      gst_object_unref (feature);
-    else
-      g_object_unref (feature);
+    gst_object_unref (feature);
   }
   return FALSE;
 }
index 627ea07..57a3285 100644 (file)
@@ -28,6 +28,7 @@
  * A #GstSample is a small object containing data, a type, timing and
  * extra arbitrary information.
  */
+#define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 #include "gst_private.h"
 
 #include "gstsample.h"
@@ -432,3 +433,48 @@ had_parent:
   g_warning ("structure is already owned by another object");
   return FALSE;
 }
+
+/**
+ * gst_sample_ref: (skip)
+ * @sample: a #GstSample
+ *
+ * Increases the refcount of the given sample by one.
+ *
+ * Returns: (transfer full): @sample
+ */
+GstSample *
+gst_sample_ref (GstSample * sample)
+{
+  return GST_SAMPLE_CAST (gst_mini_object_ref (GST_MINI_OBJECT_CAST (sample)));
+}
+
+/**
+ * gst_sample_unref: (skip)
+ * @sample: (transfer full): a #GstSample
+ *
+ * Decreases the refcount of the sample. If the refcount reaches 0, the
+ * sample will be freed.
+ */
+void
+gst_sample_unref (GstSample * sample)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (sample));
+}
+
+/**
+ * gst_sample_copy: (skip)
+ * @buf: a #GstSample.
+ *
+ * Create a copy of the given sample. This will also make a newly allocated
+ * copy of the data the source sample contains.
+ *
+ * Returns: (transfer full): a new copy of @buf.
+ *
+ * Since: 1.2
+ */
+GstSample *
+gst_sample_copy (const GstSample * buf)
+{
+  return
+      GST_SAMPLE_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (buf)));
+}
index 268119c..e3023b0 100644 (file)
@@ -87,15 +87,8 @@ void                 gst_sample_set_segment   (GstSample * sample, const GstSegm
 GST_API
 gboolean             gst_sample_set_info      (GstSample *sample, GstStructure *info);
 
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 /* refcounting */
-/**
- * gst_sample_ref:
- * @sample: a #GstSample
- *
- * Increases the refcount of the given sample by one.
- *
- * Returns: (transfer full): @sample
- */
 static inline GstSample *
 gst_sample_ref (GstSample * sample)
 {
@@ -103,18 +96,18 @@ gst_sample_ref (GstSample * sample)
       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.
- */
 static inline void
 gst_sample_unref (GstSample * sample)
 {
   gst_mini_object_unref (GST_MINI_OBJECT_CAST (sample));
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+GstSample * gst_sample_ref    (GstSample * sample);
+
+GST_API
+void        gst_sample_unref  (GstSample * sample);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 /**
  * gst_sample_is_writable:
@@ -154,24 +147,17 @@ gst_sample_unref (GstSample * sample)
  */
 #define         gst_sample_make_writable(sample)   GST_SAMPLE_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (sample)))
 
-
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 /* copy sample */
-/**
- * gst_sample_copy:
- * @buf: a #GstSample.
- *
- * Create a copy of the given sample. This will also make a newly allocated
- * copy of the data the source sample contains.
- *
- * Returns: (transfer full): a new copy of @buf.
- *
- * Since: 1.2
- */
 static inline GstSample *
 gst_sample_copy (const GstSample * buf)
 {
   return GST_SAMPLE_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (buf)));
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+GstSample *   gst_sample_copy(const GstSample * buf);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
 
 /**
  * gst_value_set_sample:
@@ -201,9 +187,7 @@ gst_sample_copy (const GstSample * buf)
  */
 #define         gst_value_get_sample(v)         GST_SAMPLE_CAST (g_value_get_boxed(v))
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstSample, gst_sample_unref)
-#endif
 
 G_END_DECLS
 
index 958b39f..f397707 100644 (file)
@@ -241,6 +241,11 @@ gst_segment_do_seek (GstSegment * segment, gdouble rate,
   g_return_val_if_fail (segment != NULL, FALSE);
   g_return_val_if_fail (segment->format == format, FALSE);
 
+  /* Elements should not pass instant-rate seeks to gst_segment_do_seek().
+   * This helps catch elements that have not been updated yet */
+  if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE)
+    return FALSE;
+
   update_start = update_stop = TRUE;
 
   position = segment->position;
@@ -354,6 +359,8 @@ gst_segment_do_seek (GstSegment * segment, gdouble rate,
     segment->flags |= GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS;
   if ((flags & GST_SEEK_FLAG_TRICKMODE_NO_AUDIO) != 0)
     segment->flags |= GST_SEGMENT_FLAG_TRICKMODE_NO_AUDIO;
+  if ((flags & GST_SEEK_FLAG_TRICKMODE_FORWARD_PREDICTED) != 0)
+    segment->flags |= GST_SEGMENT_FLAG_TRICKMODE_FORWARD_PREDICTED;
 
   segment->rate = rate;
   segment->applied_rate = 1.0;
index 923a06f..7207cc5 100644 (file)
@@ -73,9 +73,18 @@ typedef enum {
  *                     playback, request that elements only decode keyframes
  *                     and skip all other content, for formats that have
  *                     keyframes. (Since: 1.6)
+ * @GST_SEEK_FLAG_TRICKMODE_FORWARD_PREDICTED: When doing fast forward or fast reverse
+ *                     playback, request that elements only decode keyframes and
+ *                     forward predicted frames and skip all other content (for example
+ *                     B-Frames), for formats that have keyframes and forward predicted
+ *                     frames. (Since: 1.18)
  * @GST_SEEK_FLAG_TRICKMODE_NO_AUDIO: when doing fast forward or fast reverse
  *                     playback, request that audio decoder elements skip
  *                     decoding and output only gap events or silence. (Since: 1.6)
+ * @GST_SEEK_FLAG_INSTANT_RATE_CHANGE: Signals that a rate change should be
+ *                     applied immediately. Only valid if start/stop position
+ *                     are GST_CLOCK_TIME_NONE, the playback direction does not change
+ *                     and the seek is not flushing. (Since: 1.18)
  * @GST_SEEK_FLAG_SKIP: Deprecated backward compatibility flag, replaced
  *                     by %GST_SEEK_FLAG_TRICKMODE
  *
@@ -96,6 +105,16 @@ typedef enum {
  * continue playback. With this seek method it is possible to perform seamless
  * looping or simple linear editing.
  *
+ * When only changing the playback rate and not the direction, the
+ * %GST_SEEK_FLAG_INSTANT_RATE_CHANGE flag can be used for a non-flushing seek
+ * to signal that the rate change should be applied immediately. This requires
+ * special support in the seek handlers (e.g. demuxers) and any elements
+ * synchronizing to the clock, and in general can't work in all cases (for example
+ * UDP streaming where the delivery rate is controlled by a remote server). The
+ * instant-rate-change mode supports changing the trickmode-related GST_SEEK_ flags,
+ * but can't be used in conjunction with other seek flags that affect the new
+ * playback position - as the playback position will not be changing.
+ *
  * When doing fast forward (rate > 1.0) or fast reverse (rate < -1.0) trickmode
  * playback, the %GST_SEEK_FLAG_TRICKMODE flag can be used to instruct decoders
  * and demuxers to adjust the playback rate by skipping frames. This can improve
@@ -137,6 +156,8 @@ typedef enum {
   /* Careful to restart next flag with 1<<7 here */
   GST_SEEK_FLAG_TRICKMODE_KEY_UNITS = (1 << 7),
   GST_SEEK_FLAG_TRICKMODE_NO_AUDIO  = (1 << 8),
+  GST_SEEK_FLAG_TRICKMODE_FORWARD_PREDICTED = (1 << 9),
+  GST_SEEK_FLAG_INSTANT_RATE_CHANGE = (1 << 10),
 } GstSeekFlags;
 
 /**
@@ -148,6 +169,8 @@ typedef enum {
  * @GST_SEGMENT_FLAG_SEGMENT: send SEGMENT_DONE instead of EOS
  * @GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS: Decode only keyframes, where
  *                                        possible (Since: 1.6)
+ * @GST_SEGMENT_FLAG_TRICKMODE_FORWARD_PREDICTED: Decode only keyframes or forward
+ *                                        predicted frames, where possible (Since: 1.18)
  * @GST_SEGMENT_FLAG_TRICKMODE_NO_AUDIO: Do not decode any audio, where
  *                                        possible (Since: 1.6)
  * @GST_SEGMENT_FLAG_SKIP: Deprecated backward compatibility flag, replaced
@@ -166,27 +189,76 @@ typedef enum { /*< flags >*/
   GST_SEGMENT_FLAG_SKIP            = GST_SEEK_FLAG_TRICKMODE,
   GST_SEGMENT_FLAG_SEGMENT         = GST_SEEK_FLAG_SEGMENT,
   GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS = GST_SEEK_FLAG_TRICKMODE_KEY_UNITS,
+  GST_SEGMENT_FLAG_TRICKMODE_FORWARD_PREDICTED = GST_SEEK_FLAG_TRICKMODE_FORWARD_PREDICTED,
   GST_SEGMENT_FLAG_TRICKMODE_NO_AUDIO      = GST_SEEK_FLAG_TRICKMODE_NO_AUDIO
 } GstSegmentFlags;
 
+/* Flags that are reflected for instant-rate-change seeks */
+#define GST_SEGMENT_INSTANT_FLAGS \
+    (GST_SEGMENT_FLAG_TRICKMODE|GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS|GST_SEEK_FLAG_TRICKMODE_FORWARD_PREDICTED|GST_SEGMENT_FLAG_TRICKMODE_NO_AUDIO)
+
 /**
  * GstSegment:
- * @flags: flags for this segment
- * @rate: the playback rate of the segment
- * @applied_rate: the already applied rate to the segment
- * @format: the format of the segment values
- * @base: the running time (plus elapsed time, see offset) of the segment start
- * @offset: the amount (in buffer timestamps) that has already been elapsed in
- *     the segment
- * @start: the start of the segment in buffer timestamp time (PTS)
- * @stop: the stop of the segment in buffer timestamp time (PTS)
- * @time: the stream time of the segment start
- * @position: the buffer timestamp position in the segment (used internally by
- *     elements such as sources, demuxers or parsers to track progress)
- * @duration: the duration of the stream
+ * @flags:        flags for this segment
+ * @rate:         the playback rate of the segment is set in response to a seek
+ *                event and, without any seek, the value should be `1.0`. This
+ *                value is used by elements that synchronize buffer [running
+ *                times](additional/design/synchronisation.md#running-time) on
+ *                the clock (usually the sink elements), leading to consuming
+ *                buffers faster (for a value `> 1.0`) or slower (for `0.0 <
+ *                value < 1.0`) than normal playback speed. The rate also
+ *                defines the playback direction, meaning that when the value is
+ *                lower than `0.0`, the playback happens in reverse, and the
+ *                [stream-time](additional/design/synchronisation.md#stream-time)
+ *                is going backward. The `rate` value should never be `0.0`.
+ * @applied_rate: The applied rate is the rate that has been applied to the stream.
+ *                The effective/resulting playback rate of a stream is
+ *                `rate * applied_rate`.
+ *                The applied rate can be set by source elements when a server is
+ *                sending the stream with an already modified playback speed
+ *                rate. Filter elements that modify the stream in a way that
+ *                modifies the playback speed should also modify the applied
+ *                rate. For example the #videorate element when its
+ *                #videorate:rate property is set will set the applied rate of
+ *                the segment it pushed downstream. Also #scaletempo applies the
+ *                input segment rate to the stream and outputs a segment with
+ *                rate=1.0 and applied_rate=<inputsegment.rate>.
+ * @format:       the unit used for all of the segment's values.
+ * @base:         the running time (plus elapsed time, see offset) of the
+ *                segment [start](GstSegment.start) ([stop](GstSegment.stop) if
+ *                rate < 0.0).
+ * @offset:       the offset expresses the elapsed time (in buffer timestamps)
+ *                before a seek with its start (stop if rate < 0.0) seek type
+ *                set to #GST_SEEK_TYPE_NONE, the value is set to the position
+ *                of the segment at the time of the seek.
+ * @start:        the start time of the segment (in buffer timestamps)
+ *                [(PTS)](GstBuffer.pts), that is the timestamp of the first
+ *                buffer to output inside the segment (last one during
+ *                reverse playback). For example decoders will
+ *                [clip](gst_segment_clip) out the buffers before the start
+ *                time.
+ * @stop:         the stop time of the segment (in buffer timestamps)
+ *                [(PTS)](GstBuffer.pts), that is the timestamp of the last
+ *                buffer to output inside the segment (first one during
+ *                reverse playback). For example decoders will
+ *                [clip](gst_segment_clip) out buffers after the stop time.
+ * @time:         the stream time of the segment [start](GstSegment.start)
+ *                ([stop](GstSegment.stop) if rate < 0.0).
+ * @position:     the buffer timestamp position in the segment is supposed to be
+ *                updated by elements such as sources, demuxers or parsers to
+ *                track progress by setting it to the last pushed buffer' end time
+ *                ([timestamp](GstBuffer.pts) + #GstBuffer.duration) for that
+ *                specific segment. The position is used when reconfiguring the
+ *                segment with #gst_segment_do_seek when the seek is only
+ *                updating the segment (see [offset](GstSegment.offset)).
+ * @duration:     the duration of the segment is the maximum absolute difference
+ *                between #GstSegment.start and #GstSegment.stop if stop is not
+ *                set, otherwise it should be the difference between those
+ *                two values. This should be set by elements that know the
+ *                overall stream duration (like demuxers) and will be used when
+ *                seeking with #GST_SEEK_TYPE_END.
  *
- * A helper structure that holds the configured region of
- * interest in a media file.
+ * The structure that holds the configured region of interest in a media file.
  */
 struct _GstSegment {
   /*< public >*/
@@ -272,9 +344,7 @@ gboolean     gst_segment_do_seek             (GstSegment * segment, gdouble rate
 GST_API
 gboolean     gst_segment_is_equal            (const GstSegment * s0, const GstSegment * s1);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstSegment, gst_segment_free)
-#endif
 
 G_END_DECLS
 
index ec12e4a..6ec7935 100644 (file)
@@ -120,7 +120,7 @@ gst_stream_collection_class_init (GstStreamCollectionClass * klass)
       g_signal_new ("stream-notify", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED |
       G_SIGNAL_NO_HOOKS, G_STRUCT_OFFSET (GstStreamCollectionClass,
-          stream_notify), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE,
+          stream_notify), NULL, NULL, NULL, G_TYPE_NONE,
       2, GST_TYPE_STREAM, G_TYPE_PARAM);
 
   gobject_class->dispose = gst_stream_collection_dispose;
@@ -204,7 +204,7 @@ gst_stream_collection_set_upstream_id (GstStreamCollection * collection,
  *
  * Returns the upstream id of the @collection.
  *
- * Returns: (transfer none): The upstream id
+ * Returns: (transfer none) (nullable): The upstream id
  *
  * Since: 1.10
  */
index 11345c5..c6030c8 100644 (file)
@@ -112,9 +112,7 @@ GST_API
 gboolean gst_stream_collection_add_stream (GstStreamCollection *collection,
                                            GstStream *stream);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstStreamCollection, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 503ce22..6df80d1 100644 (file)
@@ -232,18 +232,20 @@ gst_stream_set_stream_id (GstStream * stream, const gchar * stream_id)
 
   GST_OBJECT_LOCK (stream);
   g_assert (stream->stream_id == NULL);
-  if (stream_id)
+  if (stream_id) {
     stream->stream_id = g_strdup (stream_id);
-  else {
+  else {
     /* Create a random stream_id if NULL */
-    GST_FIXME_OBJECT (stream, "Creating random stream-id, consider "
-        "implementing a deterministic way of creating a stream-id");
     stream->stream_id =
         g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
         g_random_int (), g_random_int ());
   }
 
   GST_OBJECT_UNLOCK (stream);
+
+  if (!stream_id)
+    GST_FIXME_OBJECT (stream, "Created random stream-id, consider "
+        "implementing a deterministic way of creating a stream-id");
 }
 
 /**
@@ -541,7 +543,7 @@ gst_stream_get_property (GObject * object, guint prop_id,
  *
  * Get a descriptive string for a given #GstStreamType
  *
- * Returns: (nullable): A string describing the stream type
+ * Returns: A string describing the stream type
  *
  * Since: 1.10
  */
@@ -561,8 +563,7 @@ gst_stream_type_get_name (GstStreamType stype)
     case GST_STREAM_TYPE_TEXT:
       return "text";
     default:
-      return NULL;
+      g_return_val_if_reached ("invalid");
+      return "invalid";
   }
-
-  return NULL;
 }
index e3e52ad..b4d40d3 100644 (file)
@@ -152,9 +152,7 @@ GstCaps *      gst_stream_get_caps (GstStream *stream);
 GST_API
 const gchar *  gst_stream_type_get_name (GstStreamType stype);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstStream, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index ee60ce0..95ef23c 100644 (file)
  * @short_description: Generic structure containing fields of names and values
  * @see_also: #GstCaps, #GstMessage, #GstEvent, #GstQuery
  *
- * A #GstStructure is a collection of key/value pairs. The keys are expressed
- * as GQuarks and the values can be of any GType.
+ * A #GstStructure is a collection of key/value pairs. The keys are expressed as
+ * GQuarks and the values can be of any GType.
  *
  * In addition to the key/value pairs, a #GstStructure also has a name. The name
- * starts with a letter and can be filled by letters, numbers and any of "/-_.:".
+ * starts with a letter and can be filled by letters, numbers and any of
+ * "/-_.:".
  *
- * #GstStructure is used by various GStreamer subsystems to store information
- * in a flexible and extensible way. A #GstStructure does not have a refcount
+ * #GstStructure is used by various GStreamer subsystems to store information in
+ * a flexible and extensible way. A #GstStructure does not have a refcount
  * because it usually is part of a higher level object such as #GstCaps,
  * #GstMessage, #GstEvent, #GstQuery. It 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_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.
+ * gst_structure_new(), which both take a name and an optional set of key/value
+ * pairs along with the types of the values.
  *
  * Field values can be changed with gst_structure_set_value() or
  * gst_structure_set().
  * Fields can be removed with gst_structure_remove_field() or
  * gst_structure_remove_fields().
  *
- * Strings in structures must be ASCII or UTF-8 encoded. Other encodings are
- * not allowed. Strings may be %NULL however.
+ * Strings in structures must be ASCII or UTF-8 encoded. Other encodings are not
+ * allowed. Strings may be %NULL however.
  *
- * Be aware that the current #GstCaps / #GstStructure serialization into string
- * has limited support for nested #GstCaps / #GstStructure fields. It can only
- * support one level of nesting. Using more levels will lead to unexpected
- * behavior when using serialization features, such as gst_caps_to_string() or
- * gst_value_serialize() and their counterparts.
+ * ## The serialization format
+ *
+ * GstStructure serialization format serialize the GstStructure name,
+ * keys/GType/values in a comma separated list with the structure name as first
+ * field without value followed by separated key/value pairs in the form
+ * `key=value`, for example:
+ *
+ * ```
+ * a-structure, key=value
+ * ````
+ *
+ * The values type will be inferred if not explicitly specified with the
+ * `(GTypeName)value` syntax, for example the following struct will have one
+ * field called 'is-string' which has the string 'true' as a value:
+ *
+ * ```
+ * a-struct, field-is-string=(string)true, field-is-boolean=true
+ * ```
+ *
+ * *Note*: without specifying `(string), `field-is-string` type would have been
+ * inferred as boolean.
+ *
+ * *Note*: we specified `(string)` as a type even if `gchararray` is the actual
+ * GType name as for convenience some well known types have been aliased or
+ * abbreviated.
+ *
+ * To avoid specifying the type, you can give some hints to the "type system".
+ * For example to specify a value as a double, you should add a decimal (ie. `1`
+ * is an `int` while `1.0` is a `double`).
+ *
+ * *Note*: when a structure is serialized with #gst_structure_to_string, all
+ * values are explicitly typed.
+ *
+ * Some types have special delimiters:
+ *
+ * - [GstValueArray](GST_TYPE_ARRAY) are inside curly brackets (`{` and `}`).
+ *   For example `a-structure, array={1, 2, 3}`
+ * - Ranges are inside brackets (`[` and `]`). For example `a-structure,
+ *   range=[1, 6, 2]` 1 being the min value, 6 the maximum and 2 the step. To
+ *   specify a #GST_TYPE_INT64_RANGE you need to explicitly specify it like:
+ *   `a-structure, a-int64-range=(gint64) [1, 5]`
+ * - [GstValueList](GST_TYPE_LIST) are inside "less and greater than" (`<` and
+ *   `>`). For example `a-structure, list=<1, 2, 3>
+ *
+ * Structures are delimited either by a null character `\0` or a semicolon `;`
+ * the latter allowing to store multiple structures in the same string (see
+ * #GstCaps).
+ *
+ * Quotes are used as "default" delimiters and can be used around any types that
+ * don't use other delimiters (for example `a-struct, i=(int)"1"`). They are use
+ * to allow adding spaces or special characters (such as delimiters,
+ * semicolumns, etc..) inside strings and you can use backslashes `\` to escape
+ * characters inside them, for example:
+ *
+ * ```
+ * a-struct, special="\"{[(;)]}\" can be used inside quotes"
+ * ```
+ *
+ * They also allow for nested structure, such as:
+ *
+ * ```
+ * a-struct, nested=(GstStructure)"nested-struct, nested=true"
+ * ```
+ *
+ * Since 1.20, nested structures and caps can be specified using brackets (`[`
+ * and `]`), for example:
+ *
+ * ```
+ * a-struct, nested=[nested-struct, nested=true]
+ * ```
+ *
+ * > *note*: gst_structure_to_string() won't use that syntax for backward
+ * > compatibility reason, gst_structure_serialize() has been added for
+ * > that purpose.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -94,14 +164,24 @@ typedef struct
   /* owned by parent structure, NULL if no parent */
   gint *parent_refcount;
 
-  GArray *fields;
+  guint fields_len;             /* Number of valid items in fields */
+  guint fields_alloc;           /* Allocated items in fields */
+
+  /* Fields are allocated if GST_STRUCTURE_IS_USING_DYNAMIC_ARRAY(),
+   *  else it's a pointer to the arr field. */
+  GstStructureField *fields;
+
+  GstStructureField arr[1];
 } GstStructureImpl;
 
 #define GST_STRUCTURE_REFCOUNT(s) (((GstStructureImpl*)(s))->parent_refcount)
-#define GST_STRUCTURE_FIELDS(s) (((GstStructureImpl*)(s))->fields)
+#define GST_STRUCTURE_LEN(s) (((GstStructureImpl*)(s))->fields_len)
+
+#define GST_STRUCTURE_IS_USING_DYNAMIC_ARRAY(s) \
+  (((GstStructureImpl*)(s))->fields != &((GstStructureImpl*)(s))->arr[0])
 
 #define GST_STRUCTURE_FIELD(structure, index) \
-    &g_array_index(GST_STRUCTURE_FIELDS(structure), GstStructureField, (index))
+  (&((GstStructureImpl*)(structure))->fields[(index)])
 
 #define IS_MUTABLE(structure) \
     (!GST_STRUCTURE_REFCOUNT(structure) || \
@@ -110,6 +190,54 @@ typedef struct
 #define IS_TAGLIST(structure) \
     (structure->name == GST_QUARK (TAGLIST))
 
+/* Replacement for g_array_append_val */
+static void
+_structure_append_val (GstStructure * s, GstStructureField * val)
+{
+  GstStructureImpl *impl = (GstStructureImpl *) s;
+
+  /* resize if needed */
+  if (G_UNLIKELY (impl->fields_len == impl->fields_alloc)) {
+    guint want_alloc;
+
+    if (G_UNLIKELY (impl->fields_alloc > (G_MAXUINT / 2)))
+      g_error ("Growing structure would result in overflow");
+
+    want_alloc =
+        MAX (GST_ROUND_UP_8 (impl->fields_len + 1), impl->fields_alloc * 2);
+    if (GST_STRUCTURE_IS_USING_DYNAMIC_ARRAY (s)) {
+      impl->fields = g_renew (GstStructureField, impl->fields, want_alloc);
+    } else {
+      impl->fields = g_new0 (GstStructureField, want_alloc);
+      memcpy (impl->fields, &impl->arr[0],
+          impl->fields_len * sizeof (GstStructureField));
+      GST_CAT_LOG (GST_CAT_PERFORMANCE, "Exceeding pre-allocated array");
+    }
+    impl->fields_alloc = want_alloc;
+  }
+
+  /* Finally set value */
+  impl->fields[impl->fields_len++] = *val;
+}
+
+/* Replacement for g_array_remove_index */
+static inline void
+_structure_remove_index (GstStructure * s, guint idx)
+{
+  GstStructureImpl *impl = (GstStructureImpl *) s;
+
+  /* We never "reduce" the memory footprint. */
+  if (idx >= impl->fields_len)
+    return;
+
+  /* Shift everything if it's not the last item */
+  if (idx != impl->fields_len)
+    memmove (&impl->fields[idx],
+        &impl->fields[idx + 1],
+        (impl->fields_len - idx - 1) * sizeof (GstStructureField));
+  impl->fields_len--;
+}
+
 static void gst_structure_set_field (GstStructure * structure,
     GstStructureField * field);
 static GstStructureField *gst_structure_get_field (const GstStructure *
@@ -142,14 +270,24 @@ _priv_gst_structure_initialize (void)
 static GstStructure *
 gst_structure_new_id_empty_with_size (GQuark quark, guint prealloc)
 {
+  guint n_alloc;
   GstStructureImpl *structure;
 
-  structure = g_slice_new (GstStructureImpl);
+  if (prealloc == 0)
+    prealloc = 1;
+
+  n_alloc = GST_ROUND_UP_8 (prealloc);
+  structure =
+      g_malloc0 (sizeof (GstStructureImpl) + (n_alloc -
+          1) * sizeof (GstStructureField));
+
   ((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);
+
+  structure->fields_len = 0;
+  structure->fields_alloc = n_alloc;
+  structure->fields = &structure->arr[0];
 
   GST_TRACE ("created structure %p", structure);
 
@@ -174,7 +312,6 @@ gst_structure_new_id_empty (GQuark quark)
   return gst_structure_new_id_empty_with_size (quark, 0);
 }
 
-#ifndef G_DISABLE_CHECKS
 static gboolean
 gst_structure_validate_name (const gchar * name)
 {
@@ -208,7 +345,6 @@ gst_structure_validate_name (const gchar * name)
 
   return TRUE;
 }
-#endif
 
 /**
  * gst_structure_new_empty:
@@ -279,8 +415,25 @@ gst_structure_new_valist (const gchar * name,
     const gchar * firstfield, va_list varargs)
 {
   GstStructure *structure;
+  va_list copy;
+  guint len = 0;
+  const gchar *field_copy = firstfield;
+  GType type_copy;
 
-  structure = gst_structure_new_empty (name);
+  g_return_val_if_fail (gst_structure_validate_name (name), NULL);
+
+  /* Calculate size of varargs */
+  va_copy (copy, varargs);
+  while (field_copy) {
+    type_copy = va_arg (copy, GType);
+    G_VALUE_COLLECT_SKIP (type_copy, copy);
+    field_copy = va_arg (copy, gchar *);
+    len++;
+  }
+  va_end (copy);
+
+  structure =
+      gst_structure_new_id_empty_with_size (g_quark_from_string (name), len);
 
   if (structure)
     gst_structure_set_valist (structure, firstfield, varargs);
@@ -343,7 +496,7 @@ gst_structure_copy (const GstStructure * structure)
 
   g_return_val_if_fail (structure != NULL, NULL);
 
-  len = GST_STRUCTURE_FIELDS (structure)->len;
+  len = GST_STRUCTURE_LEN (structure);
   new_structure = gst_structure_new_id_empty_with_size (structure->name, len);
 
   for (i = 0; i < len; i++) {
@@ -353,7 +506,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 (GST_STRUCTURE_FIELDS (new_structure), new_field);
+    _structure_append_val (new_structure, &new_field);
   }
   GST_CAT_TRACE (GST_CAT_PERFORMANCE, "doing copy %p -> %p",
       structure, new_structure);
@@ -377,7 +530,7 @@ gst_structure_free (GstStructure * structure)
   g_return_if_fail (structure != NULL);
   g_return_if_fail (GST_STRUCTURE_REFCOUNT (structure) == NULL);
 
-  len = GST_STRUCTURE_FIELDS (structure)->len;
+  len = GST_STRUCTURE_LEN (structure);
   for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
 
@@ -385,13 +538,15 @@ gst_structure_free (GstStructure * structure)
       g_value_unset (&field->value);
     }
   }
-  g_array_free (GST_STRUCTURE_FIELDS (structure), TRUE);
+  if (GST_STRUCTURE_IS_USING_DYNAMIC_ARRAY (structure))
+    g_free (((GstStructureImpl *) structure)->fields);
+
 #ifdef USE_POISONING
   memset (structure, 0xff, sizeof (GstStructure));
 #endif
   GST_TRACE ("free structure %p", structure);
 
-  g_slice_free1 (sizeof (GstStructureImpl), structure);
+  g_free (structure);
 }
 
 /**
@@ -419,6 +574,47 @@ gst_clear_structure (GstStructure ** structure_ptr)
 }
 
 /**
+ * gst_structure_take:
+ * @oldstr_ptr: (inout) (transfer full) (nullable): pointer to a place of
+ *     a #GstStructure to take
+ * @newstr: (transfer full) (allow-none): a new #GstStructure
+ *
+ * Atomically modifies a pointer to point to a new structure.
+ * The #GstStructure @oldstr_ptr is pointing to is freed and
+ * @newstr is taken ownership over.
+ *
+ * Either @newstr and the value pointed to by @oldstr_ptr may be %NULL.
+ *
+ * It is a programming error if both @newstr and the value pointed to by
+ * @oldstr_ptr refer to the same, non-%NULL structure.
+ *
+ * Returns: %TRUE if @newstr was different from @oldstr_ptr
+ *
+ * Since: 1.18
+ */
+gboolean
+gst_structure_take (GstStructure ** oldstr_ptr, GstStructure * newstr)
+{
+  GstStructure *oldstr;
+
+  g_return_val_if_fail (oldstr_ptr != NULL, FALSE);
+
+  do {
+    oldstr = g_atomic_pointer_get ((gpointer *) oldstr_ptr);
+    if (G_UNLIKELY (oldstr == newstr)) {
+      g_return_val_if_fail (newstr == NULL, FALSE);
+      return FALSE;
+    }
+  } while (G_UNLIKELY (!g_atomic_pointer_compare_and_exchange ((gpointer *)
+              oldstr_ptr, (gpointer) oldstr, newstr)));
+
+  if (oldstr)
+    gst_structure_free (oldstr);
+
+  return TRUE;
+}
+
+/**
  * gst_structure_get_name:
  * @structure: a #GstStructure
  *
@@ -771,13 +967,28 @@ gst_structure_new_id (GQuark name_quark, GQuark field_quark, ...)
 {
   GstStructure *s;
   va_list varargs;
+  va_list copy;
+  guint len = 0;
+  GQuark quark_copy = field_quark;
+  GType type_copy;
 
   g_return_val_if_fail (name_quark != 0, NULL);
   g_return_val_if_fail (field_quark != 0, NULL);
 
-  s = gst_structure_new_id_empty (name_quark);
-
   va_start (varargs, field_quark);
+
+  /* Calculate size of varargs */
+  va_copy (copy, varargs);
+  while (quark_copy) {
+    type_copy = va_arg (copy, GType);
+    G_VALUE_COLLECT_SKIP (type_copy, copy);
+    quark_copy = va_arg (copy, GQuark);
+    len++;
+  }
+  va_end (copy);
+
+  s = gst_structure_new_id_empty_with_size (name_quark, len);
+
   gst_structure_id_set_valist_internal (s, field_quark, varargs);
   va_end (varargs);
 
@@ -801,7 +1012,7 @@ gst_structure_set_field (GstStructure * structure, GstStructureField * field)
   GType field_value_type;
   guint i, len;
 
-  len = GST_STRUCTURE_FIELDS (structure)->len;
+  len = GST_STRUCTURE_LEN (structure);
 
   field_value_type = G_VALUE_TYPE (&field->value);
   if (field_value_type == G_TYPE_STRING) {
@@ -862,7 +1073,7 @@ gst_structure_set_field (GstStructure * structure, GstStructureField * field)
     }
   }
 
-  g_array_append_val (GST_STRUCTURE_FIELDS (structure), *field);
+  _structure_append_val (structure, field);
 }
 
 /* If there is no field with the given ID, NULL is returned.
@@ -873,7 +1084,7 @@ gst_structure_id_get_field (const GstStructure * structure, GQuark field_id)
   GstStructureField *field;
   guint i, len;
 
-  len = GST_STRUCTURE_FIELDS (structure)->len;
+  len = GST_STRUCTURE_LEN (structure);
 
   for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
@@ -968,7 +1179,7 @@ gst_structure_remove_field (GstStructure * structure, const gchar * fieldname)
   g_return_if_fail (IS_MUTABLE (structure));
 
   id = g_quark_from_string (fieldname);
-  len = GST_STRUCTURE_FIELDS (structure)->len;
+  len = GST_STRUCTURE_LEN (structure);
 
   for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
@@ -977,8 +1188,7 @@ gst_structure_remove_field (GstStructure * structure, const gchar * fieldname)
       if (G_IS_VALUE (&field->value)) {
         g_value_unset (&field->value);
       }
-      GST_STRUCTURE_FIELDS (structure) =
-          g_array_remove_index (GST_STRUCTURE_FIELDS (structure), i);
+      _structure_remove_index (structure, i);
       return;
     }
   }
@@ -1047,14 +1257,13 @@ gst_structure_remove_all_fields (GstStructure * structure)
   g_return_if_fail (structure != NULL);
   g_return_if_fail (IS_MUTABLE (structure));
 
-  for (i = GST_STRUCTURE_FIELDS (structure)->len - 1; i >= 0; i--) {
+  for (i = GST_STRUCTURE_LEN (structure) - 1; i >= 0; i--) {
     field = GST_STRUCTURE_FIELD (structure, i);
 
     if (G_IS_VALUE (&field->value)) {
       g_value_unset (&field->value);
     }
-    GST_STRUCTURE_FIELDS (structure) =
-        g_array_remove_index (GST_STRUCTURE_FIELDS (structure), i);
+    _structure_remove_index (structure, i);
   }
 }
 
@@ -1098,7 +1307,7 @@ gst_structure_n_fields (const GstStructure * structure)
 {
   g_return_val_if_fail (structure != NULL, 0);
 
-  return GST_STRUCTURE_FIELDS (structure)->len;
+  return GST_STRUCTURE_LEN (structure);
 }
 
 /**
@@ -1116,7 +1325,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 < GST_STRUCTURE_FIELDS (structure)->len, NULL);
+  g_return_val_if_fail (index < GST_STRUCTURE_LEN (structure), NULL);
 
   field = GST_STRUCTURE_FIELD (structure, index);
 
@@ -1147,7 +1356,7 @@ gst_structure_foreach (const GstStructure * structure,
   g_return_val_if_fail (structure != NULL, FALSE);
   g_return_val_if_fail (func != NULL, FALSE);
 
-  len = GST_STRUCTURE_FIELDS (structure)->len;
+  len = GST_STRUCTURE_LEN (structure);
 
   for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
@@ -1184,7 +1393,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 = GST_STRUCTURE_FIELDS (structure)->len;
+  len = GST_STRUCTURE_LEN (structure);
 
   for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
@@ -1222,7 +1431,7 @@ gst_structure_filter_and_map_in_place (GstStructure * structure,
   g_return_if_fail (structure != NULL);
   g_return_if_fail (IS_MUTABLE (structure));
   g_return_if_fail (func != NULL);
-  len = GST_STRUCTURE_FIELDS (structure)->len;
+  len = GST_STRUCTURE_LEN (structure);
 
   for (i = 0; i < len;) {
     field = GST_STRUCTURE_FIELD (structure, i);
@@ -1233,9 +1442,8 @@ gst_structure_filter_and_map_in_place (GstStructure * structure,
       if (G_IS_VALUE (&field->value)) {
         g_value_unset (&field->value);
       }
-      GST_STRUCTURE_FIELDS (structure) =
-          g_array_remove_index (GST_STRUCTURE_FIELDS (structure), i);
-      len = GST_STRUCTURE_FIELDS (structure)->len;
+      _structure_remove_index (structure, i);
+      len = GST_STRUCTURE_LEN (structure);
     } else {
       i++;
     }
@@ -1795,6 +2003,9 @@ gst_structure_value_get_generic_type (const GValue * val)
       || G_VALUE_TYPE (val) == GST_TYPE_ARRAY) {
     GArray *array = g_value_peek_pointer (val);
 
+    /* Note, we can do this because the internal
+     * GstValueList/GstValueArray implementation is API/ABI compatible
+     * with GArray */
     if (array->len > 0) {
       GValue *value = &g_array_index (array, GValue, 0);
 
@@ -1816,16 +2027,18 @@ gst_structure_value_get_generic_type (const GValue * val)
 
 gboolean
 priv_gst_structure_append_to_gstring (const GstStructure * structure,
-    GString * s)
+    GString * s, GstSerializeFlags flags)
 {
   GstStructureField *field;
   guint i, len;
+  gboolean nested_structs_brackets =
+      !(flags & GST_SERIALIZE_FLAG_BACKWARD_COMPAT);
 
   g_return_val_if_fail (s != NULL, FALSE);
 
-  len = GST_STRUCTURE_FIELDS (structure)->len;
+  len = GST_STRUCTURE_LEN (structure);
   for (i = 0; i < len; i++) {
-    char *t;
+    gchar *t = NULL;
     GType type;
 
     field = GST_STRUCTURE_FIELD (structure, i);
@@ -1834,7 +2047,9 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure,
       t = _priv_gst_value_serialize_any_list (&field->value, "< ", " >", FALSE);
     } else if (G_VALUE_TYPE (&field->value) == GST_TYPE_LIST) {
       t = _priv_gst_value_serialize_any_list (&field->value, "{ ", " }", FALSE);
-    } else {
+    } else if (!nested_structs_brackets
+        || (G_VALUE_TYPE (&field->value) != GST_TYPE_STRUCTURE
+            && G_VALUE_TYPE (&field->value) != GST_TYPE_CAPS)) {
       t = gst_value_serialize (&field->value);
     }
 
@@ -1846,7 +2061,22 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure,
     g_string_append_len (s, "=(", 2);
     g_string_append (s, _priv_gst_value_gtype_to_abbr (type));
     g_string_append_c (s, ')');
-    if (t) {
+    if (nested_structs_brackets
+        && G_VALUE_TYPE (&field->value) == GST_TYPE_STRUCTURE) {
+      const GstStructure *substruct = gst_value_get_structure (&field->value);
+
+      g_string_append_c (s, '[');
+      g_string_append (s, g_quark_to_string (substruct->name));
+      priv_gst_structure_append_to_gstring (substruct, s, flags);
+      g_string_append_c (s, ']');
+    } else if (nested_structs_brackets
+        && G_VALUE_TYPE (&field->value) == GST_TYPE_CAPS) {
+      const GstCaps *subcaps = gst_value_get_caps (&field->value);
+      gchar *capsstr = gst_caps_serialize (subcaps, flags);
+
+      g_string_append_printf (s, "[%s]", capsstr);
+      g_free (capsstr);
+    } else if (t) {
       g_string_append (s, t);
       g_free (t);
     } else if (G_TYPE_CHECK_VALUE_TYPE (&field->value, G_TYPE_POINTER)) {
@@ -1919,20 +2149,42 @@ priv__gst_structure_append_template_to_gstring (GQuark field_id,
   return TRUE;
 }
 
+static gchar *
+structure_serialize (const GstStructure * structure, GstSerializeFlags flags)
+{
+  GString *s;
+
+  /* NOTE:  This function is potentially called by the debug system,
+   * so any calls to gst_log() (and GST_DEBUG(), GST_LOG(), etc.)
+   * should be careful to avoid recursion.  This includes any functions
+   * called by gst_structure_to_string.  In particular, calls should
+   * not use the GST_PTR_FORMAT extension.  */
+
+  g_return_val_if_fail (structure != NULL, NULL);
+
+  /* we estimate a minimum size based on the number of fields in order to
+   * avoid unnecessary reallocs within GString */
+  s = g_string_sized_new (STRUCTURE_ESTIMATED_STRING_LEN (structure));
+  g_string_append (s, g_quark_to_string (structure->name));
+  priv_gst_structure_append_to_gstring (structure, s, flags);
+  return g_string_free (s, FALSE);
+
+}
+
 /**
  * gst_structure_to_string:
  * @structure: a #GstStructure
  *
  * Converts @structure to a human-readable string representation.
  *
- * For debugging purposes its easier to do something like this:
- * |[<!-- language="C" -->
- * GST_LOG ("structure is %" GST_PTR_FORMAT, structure);
+ * For debugging purposes its easier to do something like this: |[<!--
+ * language="C" --> GST_LOG ("structure is %" GST_PTR_FORMAT, structure);
  * ]|
  * This prints the structure in human readable form.
  *
- * The current implementation of serialization will lead to unexpected results
- * when there are nested #GstCaps / #GstStructure deeper than one level.
+ * This function will lead to unexpected results when there are nested #GstCaps
+ * / #GstStructure deeper than one level, you should user
+ * gst_structure_serialize() instead for those cases.
  *
  * Free-function: g_free
  *
@@ -1942,22 +2194,33 @@ priv__gst_structure_append_template_to_gstring (GQuark field_id,
 gchar *
 gst_structure_to_string (const GstStructure * structure)
 {
-  GString *s;
-
-  /* NOTE:  This function is potentially called by the debug system,
-   * so any calls to gst_log() (and GST_DEBUG(), GST_LOG(), etc.)
-   * should be careful to avoid recursion.  This includes any functions
-   * called by gst_structure_to_string.  In particular, calls should
-   * not use the GST_PTR_FORMAT extension.  */
-
-  g_return_val_if_fail (structure != NULL, NULL);
+  return structure_serialize (structure, GST_SERIALIZE_FLAG_BACKWARD_COMPAT);
+}
 
-  /* we estimate a minimum size based on the number of fields in order to
-   * avoid unnecessary reallocs within GString */
-  s = g_string_sized_new (STRUCTURE_ESTIMATED_STRING_LEN (structure));
-  g_string_append (s, g_quark_to_string (structure->name));
-  priv_gst_structure_append_to_gstring (structure, s);
-  return g_string_free (s, FALSE);
+/**
+ * gst_structure_serialize:
+ * @structure: a #GstStructure
+ * @flags: The flags to use to serialize structure
+ *
+ * Converts @structure to a human-readable string representation.
+ *
+ * This version of the caps serialization function introduces support for nested
+ * structures and caps but the resulting strings won't be parsable with
+ * GStreamer prior to 1.20 unless #GST_SERIALIZE_FLAG_BACKWARD_COMPAT is passed
+ * as @flag.
+ *
+ * Free-function: g_free
+ *
+ * Returns: (transfer full): a pointer to string allocated by g_malloc().
+ *     g_free() after usage.
+ *
+ * Since: 1.20
+ */
+gchar *
+gst_structure_serialize (const GstStructure * structure,
+    GstSerializeFlags flags)
+{
+  return structure_serialize (structure, flags);
 }
 
 static gboolean
@@ -1996,7 +2259,7 @@ gst_structure_parse_field (gchar * str,
   *name_end = c;
 
   if (G_UNLIKELY (!_priv_gst_value_parse_value (s, &s, &field->value,
-              G_TYPE_INVALID))) {
+              G_TYPE_INVALID, NULL))) {
     GST_WARNING ("failed to parse value %s", str);
     return FALSE;
   }
@@ -2007,7 +2270,7 @@ gst_structure_parse_field (gchar * str,
 
 gboolean
 priv_gst_structure_parse_name (gchar * str, gchar ** start, gchar ** end,
-    gchar ** next)
+    gchar ** next, gboolean check_valid)
 {
   char *w;
   char *r;
@@ -2026,6 +2289,17 @@ priv_gst_structure_parse_name (gchar * str, gchar ** start, gchar ** end,
     return FALSE;
   }
 
+  if (check_valid) {
+    gchar save = *w;
+
+    *w = '\0';
+    if (!gst_structure_validate_name (*start)) {
+      *w = save;
+      return FALSE;
+    }
+    *w = save;
+  }
+
   *end = w;
   *next = r;
 
@@ -2063,6 +2337,14 @@ priv_gst_structure_parse_fields (gchar * str, gchar ** end,
                 && g_ascii_isspace (r[1]))))
       r++;
 
+    /* Trailing comma */
+    if (*r == '\0') {
+      break;
+    } else if (*r == ';') {
+      r++;
+      break;
+    }
+
     memset (&field, 0, sizeof (field));
     if (G_UNLIKELY (!gst_structure_parse_field (r, &r, &field))) {
       GST_WARNING ("Failed to parse field, r=%s", r);
@@ -2085,7 +2367,9 @@ priv_gst_structure_parse_fields (gchar * str, gchar ** end,
  * where parsing ended will be returned.
  *
  * The current implementation of serialization will lead to unexpected results
- * when there are nested #GstCaps / #GstStructure deeper than one level.
+ * when there are nested #GstCaps / #GstStructure deeper than one level unless
+ * the gst_structure_serialize() function is used (without
+ * #GST_SERIALIZE_FLAG_BACKWARD_COMPAT)
  *
  * Free-function: gst_structure_free
  *
@@ -2102,7 +2386,7 @@ gst_structure_new_from_string (const gchar * string)
 }
 
 /**
- * gst_structure_from_string:
+ * gst_structure_from_string: (constructor):
  * @string: a string representation of a #GstStructure.
  * @end: (out) (allow-none) (transfer none) (skip): pointer to store the end of the string in.
  *
@@ -2131,7 +2415,7 @@ gst_structure_from_string (const gchar * string, gchar ** end)
   copy = g_strdup (string);
   r = copy;
 
-  if (!priv_gst_structure_parse_name (r, &name, &w, &r))
+  if (!priv_gst_structure_parse_name (r, &name, &w, &r, FALSE))
     goto error;
 
   save = *w;
@@ -2725,7 +3009,7 @@ wrong_type:
  * The last variable argument should be %NULL.
  *
  * For refcounted (mini)objects you will receive a new reference which
- * you must release with a suitable _unref() when no longer needed. For
+ * you must release with a suitable _unref\() when no longer needed. For
  * strings and boxed types you will receive a copy which you will need to
  * release with either g_free() or the suitable function for the boxed type.
  *
@@ -2768,7 +3052,7 @@ gst_structure_get (const GstStructure * structure, const char *first_fieldname,
  * quark hashtable.
  *
  * For refcounted (mini)objects you will receive a new reference which
- * you must release with a suitable _unref() when no longer needed. For
+ * you must release with a suitable _unref\() when no longer needed. For
  * strings and boxed types you will receive a copy which you will need to
  * release with either g_free() or the suitable function for the boxed type.
  *
@@ -2831,8 +3115,7 @@ gst_structure_is_equal (const GstStructure * structure1,
   if (structure1->name != structure2->name) {
     return FALSE;
   }
-  if (GST_STRUCTURE_FIELDS (structure1)->len !=
-      GST_STRUCTURE_FIELDS (structure2)->len) {
+  if (GST_STRUCTURE_LEN (structure1) != GST_STRUCTURE_LEN (structure2)) {
     return FALSE;
   }
 
@@ -2840,45 +3123,6 @@ gst_structure_is_equal (const GstStructure * structure1,
       (gpointer) structure2);
 }
 
-
-typedef struct
-{
-  GstStructure *dest;
-  const GstStructure *intersect;
-}
-IntersectData;
-
-static gboolean
-gst_structure_intersect_field1 (GQuark id, const GValue * val1, gpointer data)
-{
-  IntersectData *idata = (IntersectData *) data;
-  const GValue *val2 = gst_structure_id_get_value (idata->intersect, id);
-
-  if (G_UNLIKELY (val2 == NULL)) {
-    gst_structure_id_set_value (idata->dest, id, val1);
-  } else {
-    GValue dest_value = { 0 };
-    if (gst_value_intersect (&dest_value, val1, val2)) {
-      gst_structure_id_take_value (idata->dest, id, &dest_value);
-    } else {
-      return FALSE;
-    }
-  }
-  return TRUE;
-}
-
-static gboolean
-gst_structure_intersect_field2 (GQuark id, const GValue * val1, gpointer data)
-{
-  IntersectData *idata = (IntersectData *) data;
-  const GValue *val2 = gst_structure_id_get_value (idata->intersect, id);
-
-  if (G_UNLIKELY (val2 == NULL)) {
-    gst_structure_id_set_value (idata->dest, id, val1);
-  }
-  return TRUE;
-}
-
 /**
  * gst_structure_intersect:
  * @struct1: a #GstStructure
@@ -2892,7 +3136,8 @@ GstStructure *
 gst_structure_intersect (const GstStructure * struct1,
     const GstStructure * struct2)
 {
-  IntersectData data;
+  guint it1, len1, it2, len2;
+  GstStructure *dest;
 
   g_assert (struct1 != NULL);
   g_assert (struct2 != NULL);
@@ -2900,24 +3145,59 @@ gst_structure_intersect (const GstStructure * struct1,
   if (G_UNLIKELY (struct1->name != struct2->name))
     return NULL;
 
+  len1 = GST_STRUCTURE_LEN (struct1);
+  len2 = GST_STRUCTURE_LEN (struct2);
+
+  /* Resulting structure will be at most the size of the smallest structure */
+  dest = gst_structure_new_id_empty_with_size (struct1->name, MIN (len1, len2));
+
   /* copy fields from struct1 which we have not in struct2 to target
    * intersect if we have the field in both */
-  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)))
-    goto error;
+  for (it1 = 0; it1 < len1; it1++) {
+    GstStructureField *field1 = GST_STRUCTURE_FIELD (struct1, it1);
+    gboolean seenother = FALSE;
+    for (it2 = 0; it2 < len2; it2++) {
+      GstStructureField *field2 = GST_STRUCTURE_FIELD (struct2, it2);
+      if (field1->name == field2->name) {
+        GValue dest_value = { 0 };
+        seenother = TRUE;
+        /* Get the intersection if any */
+        if (gst_value_intersect (&dest_value, &field1->value, &field2->value)) {
+          gst_structure_id_take_value (dest, field1->name, &dest_value);
+          break;
+        } else {
+          /* No intersection, return nothing */
+          goto error;
+        }
+      }
+    }
+    /* Field1 was only present in struct1, copy it over */
+    if (!seenother)
+      gst_structure_id_set_value (dest, field1->name, &field1->value);
+  }
 
-  /* copy fields from struct2 which we have not in struct1 to target */
-  data.intersect = struct1;
-  if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct2,
-              gst_structure_intersect_field2, &data)))
-    goto error;
+  /* Now iterate over the 2nd struct and copy over everything which
+   * isn't present in the 1st struct (we've already taken care of
+   * values being present in both just above) */
+  for (it2 = 0; it2 < len2; it2++) {
+    GstStructureField *field2 = GST_STRUCTURE_FIELD (struct2, it2);
+    gboolean seenother = FALSE;
+    for (it1 = 0; it1 < len1; it1++) {
+      GstStructureField *field1 = GST_STRUCTURE_FIELD (struct1, it1);
+      if (field1->name == field2->name) {
+        seenother = TRUE;
+        break;
+      }
+    }
+    if (!seenother)
+      gst_structure_id_set_value (dest, field2->name, &field2->value);
 
-  return data.dest;
+  }
+
+  return dest;
 
 error:
-  gst_structure_free (data.dest);
+  gst_structure_free (dest);
   return NULL;
 }
 
@@ -2972,30 +3252,6 @@ gst_structure_can_intersect (const GstStructure * struct1,
       gst_caps_structure_can_intersect_field, (gpointer) struct2);
 }
 
-static gboolean
-gst_caps_structure_is_superset_field (GQuark field_id, const GValue * value,
-    gpointer user_data)
-{
-  GstStructure *subset = user_data;
-  const GValue *other;
-  int comparison;
-
-  if (!(other = gst_structure_id_get_value (subset, field_id)))
-    /* field is missing in the subset => no subset */
-    return FALSE;
-
-  comparison = gst_value_compare (value, other);
-
-  /* equal values are subset */
-  if (comparison == GST_VALUE_EQUAL)
-    return TRUE;
-
-  /* ordered, but unequal, values are not */
-  if (comparison != GST_VALUE_UNORDERED)
-    return FALSE;
-
-  return gst_value_is_subset (other, value);
-}
 
 /**
  * gst_structure_is_subset:
@@ -3012,12 +3268,51 @@ gboolean
 gst_structure_is_subset (const GstStructure * subset,
     const GstStructure * superset)
 {
-  if ((superset->name != subset->name) ||
-      (gst_structure_n_fields (superset) > gst_structure_n_fields (subset)))
+  guint it1, len1, it2, len2;
+
+  g_assert (superset);
+
+  if (G_UNLIKELY (superset->name != subset->name))
     return FALSE;
 
-  return gst_structure_foreach ((GstStructure *) superset,
-      gst_caps_structure_is_superset_field, (gpointer) subset);
+  len1 = GST_STRUCTURE_LEN (subset);
+  len2 = GST_STRUCTURE_LEN (superset);
+  if (len2 > len1)
+    return FALSE;
+
+  for (it2 = 0; it2 < len2; it2++) {
+    GstStructureField *superfield = GST_STRUCTURE_FIELD (superset, it2);
+    gboolean seenother = FALSE;
+    for (it1 = 0; it1 < len1; it1++) {
+      GstStructureField *subfield = GST_STRUCTURE_FIELD (subset, it1);
+      if (subfield->name == superfield->name) {
+        int comparison =
+            gst_value_compare (&subfield->value, &superfield->value);
+        seenother = TRUE;
+
+        /* If present and equal, stop iterating */
+        if (comparison == GST_VALUE_EQUAL)
+          break;
+
+        /* Stop everything if ordered but unequal */
+        if (comparison != GST_VALUE_UNORDERED)
+          return FALSE;
+
+        /* Stop everything if not a subset */
+        if (!gst_value_is_subset (&subfield->value, &superfield->value))
+          return FALSE;
+
+        break;
+      }
+    }
+
+    /* We did not see superfield in subfield */
+    if (!seenother)
+      return FALSE;
+  }
+
+  /* We saw everything from subset in the superset */
+  return TRUE;
 }
 
 
@@ -3077,6 +3372,8 @@ _gst_structure_get_any_list (GstStructure * structure, GType 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 %GST_TYPE_ARRAY,
  * this function returns %FALSE.
+ *
+ * Since: 1.12
  */
 gboolean
 gst_structure_get_array (GstStructure * structure, const gchar * fieldname,
index 8e6b972..38ea209 100644 (file)
@@ -32,6 +32,20 @@ GST_API GType _gst_structure_type;
 
 typedef struct _GstStructure GstStructure;
 
+/**
+ * GstSerializeFlags:
+ * @GST_SERIALIZE_FLAG_NONE: No special flags specified.
+ * @GST_SERIALIZE_FLAG_BACKWARD_COMPAT: Serialize using the old format for
+ *                                      nested structures.
+ *
+ * Since: 1.20
+ */
+typedef enum
+{
+  GST_SERIALIZE_FLAG_NONE = 0,
+  GST_SERIALIZE_FLAG_BACKWARD_COMPAT = (1 << 0),
+} GstSerializeFlags;
+
 #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))
@@ -138,6 +152,9 @@ void                  gst_clear_structure                (GstStructure **structu
 #define               gst_clear_structure(structure_ptr) g_clear_pointer ((structure_ptr), gst_structure_free)
 
 GST_API
+gboolean              gst_structure_take                 (GstStructure ** oldstr_ptr,
+                                                          GstStructure * newstr);
+GST_API
 const gchar *         gst_structure_get_name             (const GstStructure  * structure);
 
 GST_API
@@ -326,7 +343,10 @@ gboolean              gst_structure_get_list             (GstStructure        *
                                                           const gchar         * fieldname,
                                                           GValueArray        ** array);
 GST_API
-gchar *               gst_structure_to_string    (const GstStructure * structure) G_GNUC_MALLOC;
+gchar *               gst_structure_to_string            (const GstStructure * structure) G_GNUC_MALLOC;
+GST_API
+gchar *               gst_structure_serialize            (const GstStructure * structure,
+                                                          GstSerializeFlags flags) G_GNUC_MALLOC;
 
 GST_API
 GstStructure *        gst_structure_from_string  (const gchar * string,
@@ -371,9 +391,7 @@ GST_API
 GstStructure *        gst_structure_intersect     (const GstStructure * struct1,
                                                    const GstStructure * struct2) G_GNUC_MALLOC;
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstStructure, gst_structure_free)
-#endif
 
 G_END_DECLS
 
index 73dbfb4..6d0b6ec 100644 (file)
 #include <mach/mach_time.h>
 #endif
 
-#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(\
-                                       (&GST_CLOCK_ENTRY_STATUS(e)), (old), (val)))
-
 /* Define this to get some extra debug about jitter from each clock_wait */
 #undef WAIT_DEBUGGING
 
+#define GST_SYSTEM_CLOCK_GET_LOCK(clock)        GST_OBJECT_GET_LOCK(clock)
+#define GST_SYSTEM_CLOCK_LOCK(clock)            g_mutex_lock(GST_SYSTEM_CLOCK_GET_LOCK(clock))
+#define GST_SYSTEM_CLOCK_UNLOCK(clock)          g_mutex_unlock(GST_SYSTEM_CLOCK_GET_LOCK(clock))
 #define GST_SYSTEM_CLOCK_GET_COND(clock)        (&GST_SYSTEM_CLOCK_CAST(clock)->priv->entries_changed)
-#define GST_SYSTEM_CLOCK_WAIT(clock)            g_cond_wait(GST_SYSTEM_CLOCK_GET_COND(clock),GST_OBJECT_GET_LOCK(clock))
-#define GST_SYSTEM_CLOCK_TIMED_WAIT(clock,tv)   g_cond_timed_wait(GST_SYSTEM_CLOCK_GET_COND(clock),GST_OBJECT_GET_LOCK(clock),tv)
+#define GST_SYSTEM_CLOCK_WAIT(clock)            g_cond_wait(GST_SYSTEM_CLOCK_GET_COND(clock),GST_SYSTEM_CLOCK_GET_LOCK(clock))
 #define GST_SYSTEM_CLOCK_BROADCAST(clock)       g_cond_broadcast(GST_SYSTEM_CLOCK_GET_COND(clock))
 
+#if defined(HAVE_FUTEX)
+#include <unistd.h>
+#include <linux/futex.h>
+#include <sys/syscall.h>
+
+#ifndef FUTEX_WAIT_BITSET_PRIVATE
+#define FUTEX_WAIT_BITSET_PRIVATE FUTEX_WAIT_BITSET
+#endif
+#ifndef FUTEX_WAKE_PRIVATE
+#define FUTEX_WAKE_PRIVATE FUTEX_WAKE
+#endif
+
+#define GST_SYSTEM_CLOCK_ENTRY_GET_LOCK(entry)          (&(entry)->lock)
+#define GST_SYSTEM_CLOCK_ENTRY_GET_COND(entry)          (&(entry)->cond_val)
+#define GST_SYSTEM_CLOCK_ENTRY_LOCK(entry)              (g_mutex_lock(GST_SYSTEM_CLOCK_ENTRY_GET_LOCK(entry)))
+#define GST_SYSTEM_CLOCK_ENTRY_UNLOCK(entry)            (g_mutex_unlock(GST_SYSTEM_CLOCK_ENTRY_GET_LOCK(entry)))
+#define GST_SYSTEM_CLOCK_ENTRY_WAIT_UNTIL(entry,ns)     gst_futex_cond_wait_until(GST_SYSTEM_CLOCK_ENTRY_GET_COND(entry),GST_SYSTEM_CLOCK_ENTRY_GET_LOCK(entry),(ns))
+#define GST_SYSTEM_CLOCK_ENTRY_BROADCAST(entry)         gst_futex_cond_broadcast(GST_SYSTEM_CLOCK_ENTRY_GET_COND(entry))
+
+#define CLOCK_MIN_WAIT_TIME 100 /* ns */
+
+typedef struct _GstClockEntryFutex GstClockEntryImpl;
+struct _GstClockEntryFutex
+{
+  GstClockEntry entry;
+  GWeakRef clock;
+  GDestroyNotify destroy_entry;
+
+  gboolean initialized;
+
+  GMutex lock;
+  guint cond_val;
+};
+
+static void
+clear_entry (GstClockEntryImpl * entry)
+{
+  g_mutex_clear (&entry->lock);
+}
+
+static void
+init_entry (GstClockEntryImpl * entry)
+{
+  g_mutex_init (&entry->lock);
+
+  entry->destroy_entry = (GDestroyNotify) clear_entry;
+}
+
+static void
+gst_futex_cond_broadcast (guint * cond_val)
+{
+  g_atomic_int_inc (cond_val);
+
+  syscall (__NR_futex, cond_val, (gsize) FUTEX_WAKE_PRIVATE, (gsize) INT_MAX,
+      NULL);
+}
+
+static gboolean
+gst_futex_cond_wait_until (guint * cond_val, GMutex * mutex, gint64 end_time)
+{
+  struct timespec end;
+  guint sampled;
+  int res;
+  gboolean success;
+
+  if (end_time < 0)
+    return FALSE;
+
+  end.tv_sec = end_time / 1000000000;
+  end.tv_nsec = end_time % 1000000000;
+
+  sampled = *cond_val;
+  g_mutex_unlock (mutex);
+  /* we use FUTEX_WAIT_BITSET_PRIVATE rather than FUTEX_WAIT_PRIVATE to be
+   * able to use absolute time */
+  res =
+      syscall (__NR_futex, cond_val, (gsize) FUTEX_WAIT_BITSET_PRIVATE,
+      (gsize) sampled, &end, NULL, FUTEX_BITSET_MATCH_ANY);
+  success = (res < 0 && errno == ETIMEDOUT) ? FALSE : TRUE;
+  g_mutex_lock (mutex);
+
+  return success;
+}
+
+#elif defined (G_OS_UNIX)
+#define GST_SYSTEM_CLOCK_ENTRY_GET_LOCK(entry)          (&(entry)->lock)
+#define GST_SYSTEM_CLOCK_ENTRY_GET_COND(entry)          (&(entry)->cond)
+#define GST_SYSTEM_CLOCK_ENTRY_LOCK(entry)              (pthread_mutex_lock(GST_SYSTEM_CLOCK_ENTRY_GET_LOCK(entry)))
+#define GST_SYSTEM_CLOCK_ENTRY_UNLOCK(entry)            (pthread_mutex_unlock(GST_SYSTEM_CLOCK_ENTRY_GET_LOCK(entry)))
+#define GST_SYSTEM_CLOCK_ENTRY_WAIT_UNTIL(entry,ns)     gst_pthread_cond_wait_until(GST_SYSTEM_CLOCK_ENTRY_GET_COND(entry),GST_SYSTEM_CLOCK_ENTRY_GET_LOCK(entry),(ns))
+#define GST_SYSTEM_CLOCK_ENTRY_BROADCAST(entry)         pthread_cond_broadcast(GST_SYSTEM_CLOCK_ENTRY_GET_COND(entry))
+
+#define CLOCK_MIN_WAIT_TIME 500 /* ns */
+
+typedef struct _GstClockEntryPThread GstClockEntryImpl;
+struct _GstClockEntryPThread
+{
+  GstClockEntry entry;
+  GWeakRef clock;
+  GDestroyNotify destroy_entry;
+
+  gboolean initialized;
+
+  pthread_cond_t cond;
+  pthread_mutex_t lock;
+};
+
+static gboolean
+gst_pthread_cond_wait_until (pthread_cond_t * cond, pthread_mutex_t * lock,
+    guint64 end_time)
+{
+  struct timespec ts;
+  gint status;
+
+#if defined (HAVE_PTHREAD_CONDATTR_SETCLOCK) && defined (CLOCK_MONOTONIC)
+  /* This is the exact check we used during init to set the clock to
+   * monotonic, so if we're in this branch, timedwait() will already be
+   * expecting a monotonic clock.
+   */
+  {
+    ts.tv_sec = end_time / 1000000000;
+    ts.tv_nsec = end_time % 1000000000;
+
+    if ((status = pthread_cond_timedwait (cond, lock, &ts)) == 0)
+      return TRUE;
+  }
+#elif defined (HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP)
+  /* end_time is given relative to the monotonic clock as returned by
+   * g_get_monotonic_time().
+   *
+   * Since this pthreads wants the relative time, convert it back again.
+   */
+  {
+    gint64 now = g_get_monotonic_time () * 1000;
+    gint64 relative;
+
+    if (end_time <= now)
+      return FALSE;
+
+    relative = end_time - now;
+
+    ts.tv_sec = relative / 1000000000;
+    ts.tv_nsec = relative % 1000000000;
+
+    if ((status = pthread_cond_timedwait_relative_np (cond, lock, &ts)) == 0)
+      return TRUE;
+  }
+#else
+#error Cannot use pthread condition variables on your platform.
+#endif
+
+  if (G_UNLIKELY (status != ETIMEDOUT)) {
+    g_error ("pthread_cond_timedwait returned %d", status);
+  }
+
+  return FALSE;
+}
+
+static void
+clear_entry (GstClockEntryImpl * entry)
+{
+  pthread_cond_destroy (&entry->cond);
+  pthread_mutex_destroy (&entry->lock);
+}
+
+static void
+init_entry (GstClockEntryImpl * entry)
+{
+  pthread_mutexattr_t *m_pattr = NULL;
+#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
+  pthread_mutexattr_t m_attr;
+#endif
+  pthread_condattr_t c_attr;
+  gint status;
+
+  pthread_condattr_init (&c_attr);
+
+#if defined (HAVE_PTHREAD_CONDATTR_SETCLOCK) && defined (CLOCK_MONOTONIC)
+  status = pthread_condattr_setclock (&c_attr, CLOCK_MONOTONIC);
+  if (G_UNLIKELY (status != 0)) {
+    g_error ("pthread_condattr_setclock returned %d", status);
+  }
+#elif defined (HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP)
+#else
+#error Cannot use pthread condition variables on your platform.
+#endif
+
+  status = pthread_cond_init (&entry->cond, &c_attr);
+  if (G_UNLIKELY (status != 0)) {
+    g_error ("pthread_cond_init returned %d", status);
+  }
+
+  pthread_condattr_destroy (&c_attr);
+
+#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
+  pthread_mutexattr_init (&m_attr);
+  pthread_mutexattr_settype (&m_attr, PTHREAD_MUTEX_ADAPTIVE_NP);
+  m_pattr = &m_attr;
+#endif
+
+  status = pthread_mutex_init (&entry->lock, m_pattr);
+  if (G_UNLIKELY (status != 0)) {
+    g_error ("pthread_mutex_init returned %d", status);
+  }
+#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
+  pthread_mutexattr_destroy (&m_attr);
+#endif
+
+  entry->destroy_entry = (GDestroyNotify) clear_entry;
+}
+#else
+#define GST_SYSTEM_CLOCK_ENTRY_GET_LOCK(entry)          (&(entry)->lock)
+#define GST_SYSTEM_CLOCK_ENTRY_GET_COND(entry)          (&(entry)->cond)
+#define GST_SYSTEM_CLOCK_ENTRY_LOCK(entry)              (g_mutex_lock(GST_SYSTEM_CLOCK_ENTRY_GET_LOCK(entry)))
+#define GST_SYSTEM_CLOCK_ENTRY_UNLOCK(entry)            (g_mutex_unlock(GST_SYSTEM_CLOCK_ENTRY_GET_LOCK(entry)))
+#define GST_SYSTEM_CLOCK_ENTRY_WAIT_UNTIL(entry,ns)     g_cond_wait_until(GST_SYSTEM_CLOCK_ENTRY_GET_COND(entry),GST_SYSTEM_CLOCK_ENTRY_GET_LOCK(entry),((ns) / 1000))
+#define GST_SYSTEM_CLOCK_ENTRY_BROADCAST(entry)         g_cond_broadcast(GST_SYSTEM_CLOCK_ENTRY_GET_COND(entry))
+
+#if defined (G_OS_WIN32)
+/* min wait time is 1ms on windows with GCond */
+#define CLOCK_MIN_WAIT_TIME GST_MSECOND
+#else
+/* min wait time is 1us on non-windows with GCond */
+#define CLOCK_MIN_WAIT_TIME GST_USECOND
+#endif
+
+typedef struct _GstClockEntryGLib GstClockEntryImpl;
+struct _GstClockEntryGLib
+{
+  GstClockEntry entry;
+  GWeakRef clock;
+  GDestroyNotify destroy_entry;
+
+  gboolean initialized;
+
+  GMutex lock;
+  GCond cond;
+};
+
+static void
+clear_entry (GstClockEntryImpl * entry)
+{
+  g_cond_clear (&entry->cond);
+  g_mutex_clear (&entry->lock);
+}
+
+static void
+init_entry (GstClockEntryImpl * entry)
+{
+  g_cond_init (&entry->cond);
+  g_mutex_init (&entry->lock);
+
+  entry->destroy_entry = (GDestroyNotify) clear_entry;
+}
+#endif
+
+/* check that our impl is smaller than what will be allocated by gstclock.c */
+G_STATIC_ASSERT (sizeof (GstClockEntryImpl) <=
+    sizeof (struct _GstClockEntryImpl));
+
+/* Must be called with clock lock */
+static inline void
+ensure_entry_initialized (GstClockEntryImpl * entry_impl)
+{
+  if (!entry_impl->initialized) {
+    init_entry (entry_impl);
+    entry_impl->initialized = TRUE;
+  }
+}
+
 struct _GstSystemClockPrivate
 {
   GThread *thread;              /* thread for async notify */
@@ -82,14 +349,9 @@ struct _GstSystemClockPrivate
   GCond entries_changed;
 
   GstClockType clock_type;
-  GstPoll *timer;
-  gint wakeup_count;            /* the number of entries with a pending wakeup */
-  gboolean async_wakeup;        /* if the wakeup was because of a async list change */
 
 #ifdef G_OS_WIN32
-  LARGE_INTEGER start;
   LARGE_INTEGER frequency;
-  guint64 ratio;
 #endif                          /* G_OS_WIN32 */
 #ifdef __APPLE__
   struct mach_timebase_info mach_timebase;
@@ -103,7 +365,7 @@ struct _GstSystemClockPrivate
 #  define DEFAULT_CLOCK_TYPE GST_CLOCK_TYPE_REALTIME
 # endif
 #else
-#define DEFAULT_CLOCK_TYPE GST_CLOCK_TYPE_REALTIME
+#define DEFAULT_CLOCK_TYPE GST_CLOCK_TYPE_MONOTONIC
 #endif
 
 enum
@@ -124,6 +386,10 @@ static void gst_system_clock_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
 static GstClockTime gst_system_clock_get_internal_time (GstClock * clock);
+#if !defined HAVE_POSIX_TIMERS || !defined HAVE_CLOCK_GETTIME
+static GstClockTime gst_system_clock_get_mono_time (GstSystemClock * clock);
+static GstClockTime gst_system_clock_get_real_time ();
+#endif
 static guint64 gst_system_clock_get_resolution (GstClock * clock);
 static GstClockReturn gst_system_clock_id_wait_jitter (GstClock * clock,
     GstClockEntry * entry, GstClockTimeDiff * jitter);
@@ -136,7 +402,6 @@ static void gst_system_clock_id_unschedule (GstClock * clock,
     GstClockEntry * entry);
 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 GMutex _gst_sysclock_mutex;
 
@@ -185,18 +450,12 @@ gst_system_clock_init (GstSystemClock * clock)
   clock->priv = priv = gst_system_clock_get_instance_private (clock);
 
   priv->clock_type = DEFAULT_CLOCK_TYPE;
-  priv->timer = gst_poll_new_timer ();
 
   priv->entries = NULL;
   g_cond_init (&priv->entries_changed);
 
 #ifdef G_OS_WIN32
   QueryPerformanceFrequency (&priv->frequency);
-  /* can be 0 if the hardware does not have hardware support */
-  if (priv->frequency.QuadPart != 0)
-    /* we take a base time so that time starts from 0 to ease debugging */
-    QueryPerformanceCounter (&priv->start);
-  priv->ratio = GST_SECOND / priv->frequency.QuadPart;
 #endif /* G_OS_WIN32 */
 
 #ifdef __APPLE__
@@ -205,9 +464,9 @@ gst_system_clock_init (GstSystemClock * clock)
 
 #if 0
   /* Uncomment this to start the async clock thread straight away */
-  GST_OBJECT_LOCK (clock);
+  GST_SYSTEM_CLOCK_LOCK (clock);
   gst_system_clock_start_async (clock);
-  GST_OBJECT_UNLOCK (clock);
+  GST_SYSTEM_CLOCK_UNLOCK (clock);
 #endif
 }
 
@@ -220,36 +479,54 @@ gst_system_clock_dispose (GObject * object)
   GList *entries;
 
   /* else we have to stop the thread */
-  GST_OBJECT_LOCK (clock);
+  GST_SYSTEM_CLOCK_LOCK (clock);
   priv->stopping = TRUE;
   /* unschedule all entries */
   for (entries = priv->entries; entries; entries = g_list_next (entries)) {
-    GstClockEntry *entry = (GstClockEntry *) entries->data;
-
-    GST_CAT_DEBUG (GST_CAT_CLOCK, "unscheduling entry %p", entry);
-    SET_ENTRY_STATUS (entry, GST_CLOCK_UNSCHEDULED);
+    GstClockEntryImpl *entry = (GstClockEntryImpl *) entries->data;
+
+    /* We don't need to take the entry lock here because the async thread
+     * would only ever look at the head entry, which is locked below and only
+     * accesses new entries with the clock lock, which we hold here.
+     */
+    GST_CLOCK_ENTRY_STATUS ((GstClockEntry *) entry) = GST_CLOCK_UNSCHEDULED;
+
+    /* Wake up only the head entry: the async thread would only be waiting for
+     * this one, not all of them. Once the head entry is unscheduled it tries
+     * to get the system clock lock (which we hold here) and then look for the
+     * next entry. Once it gets the lock it will notice that all further
+     * entries are unscheduled, would remove them one by one from the list and
+     * then shut down. */
+    if (!entries->prev) {
+      /* it was initialized before adding to the list */
+      g_assert (entry->initialized);
+
+      GST_SYSTEM_CLOCK_ENTRY_LOCK (entry);
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "unscheduling entry %p",
+          entry);
+      GST_SYSTEM_CLOCK_ENTRY_BROADCAST (entry);
+      GST_SYSTEM_CLOCK_ENTRY_UNLOCK ((GstClockEntryImpl *) entry);
+    }
   }
   GST_SYSTEM_CLOCK_BROADCAST (clock);
-  gst_system_clock_add_wakeup (sysclock);
-  GST_OBJECT_UNLOCK (clock);
+  GST_SYSTEM_CLOCK_UNLOCK (clock);
 
   if (priv->thread)
     g_thread_join (priv->thread);
   priv->thread = NULL;
-  GST_CAT_DEBUG (GST_CAT_CLOCK, "joined thread");
+  GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "joined thread");
 
   g_list_foreach (priv->entries, (GFunc) gst_clock_id_unref, NULL);
   g_list_free (priv->entries);
   priv->entries = NULL;
 
-  gst_poll_free (priv->timer);
   g_cond_clear (&priv->entries_changed);
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 
   if (_the_system_clock == clock) {
     _the_system_clock = NULL;
-    GST_CAT_DEBUG (GST_CAT_CLOCK, "disposed system clock");
+    GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "disposed system clock");
   }
 }
 
@@ -262,7 +539,7 @@ gst_system_clock_set_property (GObject * object, guint prop_id,
   switch (prop_id) {
     case PROP_CLOCK_TYPE:
       sysclock->priv->clock_type = (GstClockType) g_value_get_enum (value);
-      GST_CAT_DEBUG (GST_CAT_CLOCK, "clock-type set to %d",
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, sysclock, "clock-type set to %d",
           sysclock->priv->clock_type);
       break;
     default:
@@ -311,7 +588,7 @@ gst_system_clock_set_default (GstClock * new_clock)
   clock = _the_system_clock;
 
   if (clock != NULL)
-    g_object_unref (clock);
+    gst_object_unref (clock);
 
   if (new_clock == NULL) {
     GST_CAT_DEBUG (GST_CAT_CLOCK, "resetting default system clock");
@@ -353,6 +630,7 @@ gst_system_clock_obtain (void)
 
     /* Clear floating flag */
     gst_object_ref_sink (clock);
+    GST_OBJECT_FLAG_SET (clock, GST_OBJECT_FLAG_MAY_BE_LEAKED);
     _the_system_clock = clock;
     g_mutex_unlock (&_gst_sysclock_mutex);
   } else {
@@ -365,46 +643,6 @@ gst_system_clock_obtain (void)
   return clock;
 }
 
-static void
-gst_system_clock_remove_wakeup (GstSystemClock * sysclock)
-{
-  g_return_if_fail (sysclock->priv->wakeup_count > 0);
-
-  sysclock->priv->wakeup_count--;
-  GST_CAT_DEBUG (GST_CAT_CLOCK, "reading control");
-  while (!gst_poll_read_control (sysclock->priv->timer)) {
-    if (errno == EWOULDBLOCK) {
-      /* Try again and give other threads the chance to do something */
-      g_thread_yield ();
-      continue;
-    } else {
-      /* Critical error, GstPoll will have printed a critical warning already */
-      break;
-    }
-  }
-  GST_SYSTEM_CLOCK_BROADCAST (sysclock);
-  GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup count %d",
-      sysclock->priv->wakeup_count);
-}
-
-static void
-gst_system_clock_add_wakeup (GstSystemClock * sysclock)
-{
-  GST_CAT_DEBUG (GST_CAT_CLOCK, "writing control");
-  gst_poll_write_control (sysclock->priv->timer);
-  sysclock->priv->wakeup_count++;
-  GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup count %d",
-      sysclock->priv->wakeup_count);
-}
-
-static void
-gst_system_clock_wait_wakeup (GstSystemClock * sysclock)
-{
-  while (sysclock->priv->wakeup_count > 0) {
-    GST_SYSTEM_CLOCK_WAIT (sysclock);
-  }
-}
-
 /* this thread reads the sorted clock entries from the queue.
  *
  * It waits on each of them and fires the callback when the timeout occurs.
@@ -423,9 +661,10 @@ gst_system_clock_async_thread (GstClock * clock)
   GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
   GstSystemClockPrivate *priv = sysclock->priv;
   GstClockReturn status;
+  gboolean entry_needs_unlock = FALSE;
 
-  GST_CAT_DEBUG (GST_CAT_CLOCK, "enter system clock thread");
-  GST_OBJECT_LOCK (clock);
+  GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "enter system clock thread");
+  GST_SYSTEM_CLOCK_LOCK (clock);
   /* signal spinup */
   GST_SYSTEM_CLOCK_BROADCAST (clock);
   /* now enter our (almost) infinite loop */
@@ -436,77 +675,86 @@ gst_system_clock_async_thread (GstClock * clock)
 
     /* check if something to be done */
     while (priv->entries == NULL) {
-      GST_CAT_DEBUG (GST_CAT_CLOCK, "no clock entries, waiting..");
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
+          "no clock entries, waiting..");
       /* wait for work to do */
       GST_SYSTEM_CLOCK_WAIT (clock);
-      GST_CAT_DEBUG (GST_CAT_CLOCK, "got signal");
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "got signal");
       /* clock was stopping, exit */
       if (priv->stopping)
         goto exit;
     }
 
-    /* see if we have a pending wakeup because the order of the list
-     * changed. */
-    if (priv->async_wakeup) {
-      GST_CAT_DEBUG (GST_CAT_CLOCK, "clear async wakeup");
-      gst_system_clock_remove_wakeup (sysclock);
-      priv->async_wakeup = FALSE;
-    }
-
     /* pick the next entry */
     entry = priv->entries->data;
 
-    /* set entry status to busy before we release the clock lock */
-    do {
-      status = GET_ENTRY_STATUS (entry);
+    /* it was initialized before adding to the list */
+    g_assert (((GstClockEntryImpl *) entry)->initialized);
 
-      /* check for unscheduled */
-      if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) {
-        /* entry was unscheduled, move to the next one */
-        GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p unscheduled", entry);
-        goto next_entry;
-      }
+    /* unlocked before the next loop iteration at latest */
+    GST_SYSTEM_CLOCK_ENTRY_LOCK ((GstClockEntryImpl *) entry);
+    entry_needs_unlock = TRUE;
 
-      /* for periodic timers, status can be EARLY from a previous run */
-      if (G_UNLIKELY (status != GST_CLOCK_OK && status != GST_CLOCK_EARLY))
-        GST_CAT_ERROR (GST_CAT_CLOCK, "unexpected status %d for entry %p",
-            status, entry);
+    /* set entry status to busy before we release the clock lock */
+    status = GST_CLOCK_ENTRY_STATUS (entry);
+
+    /* check for unscheduled */
+    if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) {
+      /* entry was unscheduled, move to the next one */
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
+          "async entry %p unscheduled", entry);
+      GST_SYSTEM_CLOCK_UNLOCK (clock);
+      goto next_entry;
+    }
 
-      /* mark the entry as busy but watch out for intermediate unscheduled
-       * statuses */
-    } while (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status, GST_CLOCK_BUSY)));
+    /* for periodic timers, status can be EARLY from a previous run */
+    if (G_UNLIKELY (status != GST_CLOCK_OK && status != GST_CLOCK_EARLY))
+      GST_CAT_ERROR_OBJECT (GST_CAT_CLOCK, clock,
+          "unexpected status %d for entry %p", status, entry);
 
-    GST_OBJECT_UNLOCK (clock);
+    /* mark the entry as busy */
+    GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_BUSY;
 
     requested = entry->time;
 
+    /* needs to be locked again before the next loop iteration, and we only
+     * unlock it here so that gst_system_clock_id_wait_async() is guaranteed
+     * to see status==BUSY later and wakes up this thread, and dispose() does
+     * not override BUSY with UNSCHEDULED here. */
+    GST_SYSTEM_CLOCK_UNLOCK (clock);
+
+    GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "waiting on entry %p", entry);
+
     /* now wait for the entry */
     res =
         gst_system_clock_id_wait_jitter_unlocked (clock, (GstClockID) entry,
         NULL, FALSE);
 
-    GST_OBJECT_LOCK (clock);
-
     switch (res) {
       case GST_CLOCK_UNSCHEDULED:
         /* entry was unscheduled, move to the next */
-        GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p unscheduled", entry);
+        GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
+            "async entry %p unscheduled", entry);
         goto next_entry;
       case GST_CLOCK_OK:
       case GST_CLOCK_EARLY:
       {
+        GST_SYSTEM_CLOCK_ENTRY_UNLOCK ((GstClockEntryImpl *) entry);
+        entry_needs_unlock = FALSE;
         /* entry timed out normally, fire the callback and move to the next
          * entry */
-        GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p timed out", entry);
+        GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "async entry %p timed out",
+            entry);
         if (entry->func) {
           /* unlock before firing the callback */
-          GST_OBJECT_UNLOCK (clock);
           entry->func (clock, entry->time, (GstClockID) entry,
               entry->user_data);
-          GST_OBJECT_LOCK (clock);
         }
         if (entry->type == GST_CLOCK_ENTRY_PERIODIC) {
-          GST_CAT_DEBUG (GST_CAT_CLOCK, "updating periodic entry %p", entry);
+          GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
+              "updating periodic entry %p", entry);
+
+          GST_SYSTEM_CLOCK_LOCK (clock);
           /* adjust time now */
           entry->time = requested + entry->interval;
           /* and resort the list now */
@@ -515,30 +763,37 @@ gst_system_clock_async_thread (GstClock * clock)
           /* and restart */
           continue;
         } else {
-          GST_CAT_DEBUG (GST_CAT_CLOCK, "moving to next entry");
+          GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "moving to next entry");
           goto next_entry;
         }
       }
       case GST_CLOCK_BUSY:
         /* somebody unlocked the entry but is was not canceled, This means that
-         * either a new entry was added in front of the queue or some other entry
-         * was canceled. Whatever it is, pick the head entry of the list and
-         * continue waiting. */
-        GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p needs restart", entry);
+         * a new entry was added in front of the queue. Pick the new head
+         * entry of the list and continue waiting. */
+        GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
+            "async entry %p needs restart", entry);
 
         /* we set the entry back to the OK state. This is needed so that the
          * _unschedule() code can see if an entry is currently being waited
          * on (when its state is BUSY). */
-        SET_ENTRY_STATUS (entry, GST_CLOCK_OK);
+        GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_OK;
+        if (entry_needs_unlock)
+          GST_SYSTEM_CLOCK_ENTRY_UNLOCK ((GstClockEntryImpl *) entry);
+        GST_SYSTEM_CLOCK_LOCK (clock);
         continue;
       default:
-        GST_CAT_DEBUG (GST_CAT_CLOCK,
+        GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
             "strange result %d waiting for %p, skipping", res, entry);
         g_warning ("%s: strange result %d waiting for %p, skipping",
             GST_OBJECT_NAME (clock), res, entry);
         goto next_entry;
     }
   next_entry:
+    if (entry_needs_unlock)
+      GST_SYSTEM_CLOCK_ENTRY_UNLOCK ((GstClockEntryImpl *) entry);
+    GST_SYSTEM_CLOCK_LOCK (clock);
+
     /* we remove the current entry and unref it */
     priv->entries = g_list_remove (priv->entries, entry);
     gst_clock_id_unref ((GstClockID) entry);
@@ -546,8 +801,8 @@ gst_system_clock_async_thread (GstClock * clock)
 exit:
   /* signal exit */
   GST_SYSTEM_CLOCK_BROADCAST (clock);
-  GST_OBJECT_UNLOCK (clock);
-  GST_CAT_DEBUG (GST_CAT_CLOCK, "exit system clock thread");
+  GST_SYSTEM_CLOCK_UNLOCK (clock);
+  GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "exit system clock thread");
 }
 
 #ifdef HAVE_POSIX_TIMERS
@@ -559,7 +814,14 @@ clock_type_to_posix_id (GstClockType clock_type)
     return CLOCK_MONOTONIC;
   else
 #endif
-    return CLOCK_REALTIME;
+  if (clock_type == GST_CLOCK_TYPE_TAI)
+#ifdef CLOCK_TAI
+    return CLOCK_TAI;
+#else
+    GST_ERROR
+        ("No CLOCK_TAI available on the system. Falling back to CLOCK_REALTIME");
+#endif
+  return CLOCK_REALTIME;
 }
 #endif
 
@@ -567,136 +829,137 @@ clock_type_to_posix_id (GstClockType clock_type)
 static GstClockTime
 gst_system_clock_get_internal_time (GstClock * clock)
 {
-#if defined __APPLE__
   GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
+#if defined HAVE_POSIX_TIMERS && defined HAVE_CLOCK_GETTIME
+  // BSD and Linux' Posix timers and clock_gettime cover all of the different clock types
+  // without need for special handling so we'll use those.
+  clockid_t ptype;
+  struct timespec ts;
+
+  ptype = clock_type_to_posix_id (sysclock->priv->clock_type);
+
+  if (G_UNLIKELY (clock_gettime (ptype, &ts)))
+    return GST_CLOCK_TIME_NONE;
+
+  return GST_TIMESPEC_TO_TIME (ts);
+#else
+  if (sysclock->priv->clock_type == GST_CLOCK_TYPE_REALTIME) {
+    return gst_system_clock_get_real_time ();
+  } else {
+    return gst_system_clock_get_mono_time (sysclock);
+  }
+#endif /* !HAVE_POSIX_TIMERS || !HAVE_CLOCK_GETTIME */
+}
+
+#if !defined HAVE_POSIX_TIMERS || !defined HAVE_CLOCK_GETTIME
+static GstClockTime
+gst_system_clock_get_real_time ()
+{
+  gint64 rt_micros = g_get_real_time ();
+  // g_get_real_time returns microseconds but we need nanos, so we'll multiply by 1000
+  return ((guint64) rt_micros) * 1000;
+}
+
+static GstClockTime
+gst_system_clock_get_mono_time (GstSystemClock * sysclock)
+{
+#if defined __APPLE__
   uint64_t mach_t = mach_absolute_time ();
   return gst_util_uint64_scale (mach_t, sysclock->priv->mach_timebase.numer,
       sysclock->priv->mach_timebase.denom);
 #else
-#ifdef G_OS_WIN32
-  GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
-
+#if defined G_OS_WIN32
   if (sysclock->priv->frequency.QuadPart != 0) {
     LARGE_INTEGER now;
 
     /* we prefer the highly accurate performance counters on windows */
     QueryPerformanceCounter (&now);
 
-    return ((now.QuadPart -
-            sysclock->priv->start.QuadPart) * sysclock->priv->ratio);
+    return gst_util_uint64_scale (now.QuadPart,
+        GST_SECOND, sysclock->priv->frequency.QuadPart);
   } else
 #endif /* G_OS_WIN32 */
-#if !defined HAVE_POSIX_TIMERS || !defined HAVE_CLOCK_GETTIME
-  {
-    GTimeVal timeval;
-
-    g_get_current_time (&timeval);
-
-    return GST_TIMEVAL_TO_TIME (timeval);
-  }
-#else
   {
-    GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
-    clockid_t ptype;
-    struct timespec ts;
-
-    ptype = clock_type_to_posix_id (sysclock->priv->clock_type);
+    gint64 monotime;
 
-    if (G_UNLIKELY (clock_gettime (ptype, &ts)))
-      return GST_CLOCK_TIME_NONE;
+    monotime = g_get_monotonic_time ();
 
-    return GST_TIMESPEC_TO_TIME (ts);
+    return monotime * 1000;
   }
-#endif
 #endif /* __APPLE__ */
 }
+#endif /* !HAVE_POSIX_TIMERS || !HAVE_CLOCK_GETTIME */
 
 static guint64
 gst_system_clock_get_resolution (GstClock * clock)
 {
-#if defined __APPLE__
-  GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
-  return gst_util_uint64_scale (GST_NSECOND,
-      sysclock->priv->mach_timebase.numer, sysclock->priv->mach_timebase.denom);
-#else
-#ifdef G_OS_WIN32
   GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
-
-  if (sysclock->priv->frequency.QuadPart != 0) {
-    return GST_SECOND / sysclock->priv->frequency.QuadPart;
+#if defined __APPLE__ || defined G_OS_WIN32
+  if (sysclock->priv->clock_type == GST_CLOCK_TYPE_REALTIME) {
+    return 1 * GST_USECOND;
   } else
-#endif /* G_OS_WIN32 */
-#if defined(HAVE_POSIX_TIMERS) && defined(HAVE_CLOCK_GETTIME)
+#endif
+#if defined __APPLE__
   {
-    GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
+    return gst_util_uint64_scale (GST_NSECOND,
+        sysclock->priv->mach_timebase.numer,
+        sysclock->priv->mach_timebase.denom);
+  }
+#elif defined G_OS_WIN32
+  {
+    if (sysclock->priv->frequency.QuadPart != 0) {
+      return GST_SECOND / sysclock->priv->frequency.QuadPart;
+    } else {
+      return 1 * GST_USECOND;
+    }
+  }
+#elif defined(HAVE_POSIX_TIMERS) && defined(HAVE_CLOCK_GETTIME)
     clockid_t ptype;
-    struct timespec ts;
+  struct timespec ts;
 
-    ptype = clock_type_to_posix_id (sysclock->priv->clock_type);
+  ptype = clock_type_to_posix_id (sysclock->priv->clock_type);
 
-    if (G_UNLIKELY (clock_getres (ptype, &ts)))
-      return GST_CLOCK_TIME_NONE;
+  if (G_UNLIKELY (clock_getres (ptype, &ts)))
+    return GST_CLOCK_TIME_NONE;
 
-    return GST_TIMESPEC_TO_TIME (ts);
-  }
+  return GST_TIMESPEC_TO_TIME (ts);
 #else
-  {
     return 1 * GST_USECOND;
-  }
-#endif
 #endif /* __APPLE__ */
 }
 
-static inline void
-gst_system_clock_cleanup_unscheduled (GstSystemClock * sysclock,
-    GstClockEntry * entry)
-{
-  /* try to clean up.
-   * The unschedule function managed to set the status to
-   * unscheduled. We now take the lock and mark the entry as unscheduled.
-   * This makes sure that the unschedule function doesn't perform a
-   * wakeup anymore. If the unschedule function has a change to perform
-   * the wakeup before us, we clean up here */
-  GST_OBJECT_LOCK (sysclock);
-  entry->unscheduled = TRUE;
-  if (entry->woken_up) {
-    gst_system_clock_remove_wakeup (sysclock);
-  }
-  GST_OBJECT_UNLOCK (sysclock);
-}
-
 /* synchronously wait on the given GstClockEntry.
  *
- * We do this by blocking on the global GstPoll timer with
- * the requested timeout. This allows us to unblock the
- * entry by writing on the control fd.
- *
- * Note that writing the global GstPoll unlocks all waiting entries. So
- * we need to check if an unlocked entry has changed when it unlocks.
+ * We do this by blocking on the entry specifically rather than a global
+ * condition variable so that each possible thread may be woken up
+ * individually. This ensures that we don't wake up possibly multiple threads
+ * when unscheduling an entry.
  *
  * Entries that arrive too late are simply not waited on and a
  * GST_CLOCK_EARLY result is returned.
  *
+ * This is called with the ENTRY_LOCK but not SYSTEM_CLOCK_LOCK!
+ *
  * MT safe.
  */
 static GstClockReturn
 gst_system_clock_id_wait_jitter_unlocked (GstClock * clock,
     GstClockEntry * entry, GstClockTimeDiff * jitter, gboolean restart)
 {
-  GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
   GstClockTime entryt, now;
   GstClockTimeDiff diff;
   GstClockReturn status;
+  gint64 mono_ts;
 
-  status = GET_ENTRY_STATUS (entry);
+  status = GST_CLOCK_ENTRY_STATUS (entry);
   if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) {
-    gst_system_clock_cleanup_unscheduled (sysclock, entry);
     return GST_CLOCK_UNSCHEDULED;
   }
 
   /* need to call the overridden method because we want to sync against the time
    * of the clock, whatever the subclass uses as a clock. */
   now = gst_clock_get_time (clock);
+  mono_ts = g_get_monotonic_time ();
 
   /* get the time of the entry */
   entryt = GST_CLOCK_ENTRY_TIME (entry);
@@ -707,84 +970,94 @@ gst_system_clock_id_wait_jitter_unlocked (GstClock * clock,
   if (G_LIKELY (jitter))
     *jitter = -diff;
 
-  GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p"
+  GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "entry %p"
       " time %" GST_TIME_FORMAT
       " now %" GST_TIME_FORMAT
       " diff (time-now) %" G_GINT64_FORMAT,
       entry, GST_TIME_ARGS (entryt), GST_TIME_ARGS (now), diff);
 
-  if (G_LIKELY (diff > 0)) {
+  if (G_LIKELY (diff > CLOCK_MIN_WAIT_TIME)) {
 #ifdef WAIT_DEBUGGING
     GstClockTime final;
 #endif
 
     while (TRUE) {
-      gint pollret;
+      gboolean waitret;
+
+#ifdef HAVE_CLOCK_NANOSLEEP
+      if (diff <= 500 * GST_USECOND) {
+        /* In order to provide more accurate wait, we will use BLOCKING
+           clock_nanosleep for any deadlines at or below 500us */
+        struct timespec end;
+        GST_TIME_TO_TIMESPEC (mono_ts * 1000 + diff, end);
+        GST_SYSTEM_CLOCK_ENTRY_UNLOCK ((GstClockEntryImpl *) entry);
+        waitret =
+            clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME, &end, NULL) == 0;
+        GST_SYSTEM_CLOCK_ENTRY_LOCK ((GstClockEntryImpl *) entry);
+      } else {
+
+        if (diff < 2 * GST_MSECOND) {
+          /* For any deadline within 2ms, we first use the regular non-blocking
+             wait by reducing the diff accordingly */
+          diff -= 500 * GST_USECOND;
+        }
+#endif
 
-      /* now wait on the entry, it either times out or the fd is written. The
-       * status of the entry is BUSY only around the poll. */
-      pollret = gst_poll_wait (sysclock->priv->timer, diff);
+        /* now wait on the entry, it either times out or the cond is signalled.
+         * The status of the entry is BUSY only around the wait. */
+        waitret =
+            GST_SYSTEM_CLOCK_ENTRY_WAIT_UNTIL ((GstClockEntryImpl *) entry,
+            mono_ts * 1000 + diff);
+
+#ifdef HAVE_CLOCK_NANOSLEEP
+      }
+#endif
 
       /* get the new status, mark as DONE. We do this so that the unschedule
        * function knows when we left the poll and doesn't need to wakeup the
        * poll anymore. */
-      do {
-        status = GET_ENTRY_STATUS (entry);
-        /* we were unscheduled, exit immediately */
-        if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED))
-          break;
-        if (G_UNLIKELY (status != GST_CLOCK_BUSY))
-          GST_CAT_ERROR (GST_CAT_CLOCK, "unexpected status %d for entry %p",
-              status, entry);
-      } while (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status, GST_CLOCK_DONE)));
-
-      GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p unlocked, status %d, ret %d",
-          entry, status, pollret);
+      status = GST_CLOCK_ENTRY_STATUS (entry);
+      /* we were unscheduled, exit immediately */
+      if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED))
+        break;
+      if (G_UNLIKELY (status != GST_CLOCK_BUSY))
+        GST_CAT_ERROR_OBJECT (GST_CAT_CLOCK, clock,
+            "unexpected status %d for entry %p", status, entry);
+      GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_DONE;
+
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
+          "entry %p unlocked, status %d", entry, status);
 
       if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) {
-        gst_system_clock_cleanup_unscheduled (sysclock, entry);
         goto done;
       } else {
-        if (G_UNLIKELY (pollret != 0)) {
+        if (waitret) {
           /* some other id got unlocked */
           if (!restart) {
             /* this can happen if the entry got unlocked because of an async
              * entry was added to the head of the async queue. */
-            GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup waiting for entry %p", entry);
+            GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
+                "wakeup waiting for entry %p", entry);
             goto done;
           }
 
-          /* wait till all the entries got woken up */
-          GST_OBJECT_LOCK (sysclock);
-          gst_system_clock_wait_wakeup (sysclock);
-          GST_OBJECT_UNLOCK (sysclock);
-
-          GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p needs to be restarted",
-              entry);
+          GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
+              "entry %p needs to be restarted", entry);
         } else {
-          GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p unlocked after timeout",
-              entry);
+          GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
+              "entry %p unlocked after timeout", entry);
         }
 
-        /* reschedule if gst_poll_wait returned early or we have to reschedule after
+        /* reschedule if gst_cond_wait_until returned early or we have to reschedule after
          * an unlock*/
+        mono_ts = g_get_monotonic_time ();
         now = gst_clock_get_time (clock);
         diff = GST_CLOCK_DIFF (now, entryt);
 
-        if (diff <= 0) {
+        if (diff <= CLOCK_MIN_WAIT_TIME) {
           /* timeout, this is fine, we can report success now */
-          if (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, GST_CLOCK_DONE,
-                      GST_CLOCK_OK))) {
-            status = GET_ENTRY_STATUS (entry);
-            if (status != GST_CLOCK_UNSCHEDULED)
-              GST_CAT_ERROR (GST_CAT_CLOCK, "unexpected status %d for entry %p",
-                  status, entry);
-            goto done;
-          } else {
-            status = GST_CLOCK_OK;
-          }
-
-          GST_CAT_DEBUG (GST_CAT_CLOCK,
+          GST_CLOCK_ENTRY_STATUS (entry) = status = GST_CLOCK_OK;
+          GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
               "entry %p finished, diff %" G_GINT64_FORMAT, entry, diff);
 
 #ifdef WAIT_DEBUGGING
@@ -799,46 +1072,19 @@ gst_system_clock_id_wait_jitter_unlocked (GstClock * clock,
 #endif
           goto done;
         } else {
-          GST_CAT_DEBUG (GST_CAT_CLOCK,
+          GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
               "entry %p restart, diff %" G_GINT64_FORMAT, entry, diff);
           /* we are going to poll again, set status back to busy */
-          do {
-            status = GET_ENTRY_STATUS (entry);
-            /* we were unscheduled, exit immediately */
-            if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED))
-              goto done;
-            if (G_UNLIKELY (status != GST_CLOCK_DONE))
-              GST_CAT_ERROR (GST_CAT_CLOCK, "unexpected status %d for entry %p",
-                  status, entry);
-          } while (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status,
-                      GST_CLOCK_BUSY)));
+          GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_BUSY;
         }
       }
     }
   } else {
     /* we are right on time or too late */
     if (G_UNLIKELY (diff == 0)) {
-      if (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status, GST_CLOCK_OK))) {
-        status = GET_ENTRY_STATUS (entry);
-        if (G_LIKELY (status == GST_CLOCK_UNSCHEDULED))
-          gst_system_clock_cleanup_unscheduled (sysclock, entry);
-        else
-          GST_CAT_ERROR (GST_CAT_CLOCK, "unexpected status %d for entry %p",
-              status, entry);
-      } else {
-        status = GST_CLOCK_OK;
-      }
+      GST_CLOCK_ENTRY_STATUS (entry) = status = GST_CLOCK_OK;
     } else {
-      if (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status, GST_CLOCK_EARLY))) {
-        status = GET_ENTRY_STATUS (entry);
-        if (G_LIKELY (status == GST_CLOCK_UNSCHEDULED))
-          gst_system_clock_cleanup_unscheduled (sysclock, entry);
-        else
-          GST_CAT_ERROR (GST_CAT_CLOCK, "unexpected status %d for entry %p",
-              status, entry);
-      } else {
-        status = GST_CLOCK_EARLY;
-      }
+      GST_CLOCK_ENTRY_STATUS (entry) = status = GST_CLOCK_EARLY;
     }
   }
 done:
@@ -850,22 +1096,36 @@ gst_system_clock_id_wait_jitter (GstClock * clock, GstClockEntry * entry,
     GstClockTimeDiff * jitter)
 {
   GstClockReturn status;
-  do {
-    status = GET_ENTRY_STATUS (entry);
+  GstClockEntryImpl *entry_impl = (GstClockEntryImpl *) entry;
+
+  GST_SYSTEM_CLOCK_LOCK (clock);
+  ensure_entry_initialized (entry_impl);
+  GST_SYSTEM_CLOCK_UNLOCK (clock);
 
-    /* stop when we are unscheduled */
-    if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED))
-      return status;
+  GST_SYSTEM_CLOCK_ENTRY_LOCK (entry_impl);
+  status = GST_CLOCK_ENTRY_STATUS (entry);
 
-    if (G_UNLIKELY (status != GST_CLOCK_OK))
-      GST_CAT_ERROR (GST_CAT_CLOCK, "unexpected status %d for entry %p",
-          status, entry);
+  /* stop when we are unscheduled */
+  if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) {
+    GST_SYSTEM_CLOCK_ENTRY_UNLOCK (entry_impl);
+    return status;
+  }
+
+  if (G_UNLIKELY (status != GST_CLOCK_OK))
+    GST_CAT_ERROR_OBJECT (GST_CAT_CLOCK, clock,
+        "unexpected status %d for entry %p", status, entry);
+
+  /* mark the entry as busy */
+  GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_BUSY;
 
-    /* mark the entry as busy but watch out for intermediate unscheduled
-     * statuses */
-  } while (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status, GST_CLOCK_BUSY)));
+  GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "waiting on entry %p", entry);
 
-  return gst_system_clock_id_wait_jitter_unlocked (clock, entry, jitter, TRUE);
+  status =
+      gst_system_clock_id_wait_jitter_unlocked (clock, entry, jitter, TRUE);
+
+  GST_SYSTEM_CLOCK_ENTRY_UNLOCK (entry_impl);
+
+  return status;
 }
 
 /* Start the async clock thread. Must be called with the object lock
@@ -916,15 +1176,18 @@ gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry)
   sysclock = GST_SYSTEM_CLOCK_CAST (clock);
   priv = sysclock->priv;
 
-  GST_CAT_DEBUG (GST_CAT_CLOCK, "adding async entry %p", entry);
+  GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "adding async entry %p", entry);
 
-  GST_OBJECT_LOCK (clock);
+  GST_SYSTEM_CLOCK_LOCK (clock);
   /* Start the clock async thread if needed */
   if (G_UNLIKELY (!gst_system_clock_start_async (sysclock)))
     goto thread_error;
 
-  if (G_UNLIKELY (GET_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED))
+  ensure_entry_initialized ((GstClockEntryImpl *) entry);
+  GST_SYSTEM_CLOCK_ENTRY_LOCK ((GstClockEntryImpl *) entry);
+  if (G_UNLIKELY (GST_CLOCK_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED))
     goto was_unscheduled;
+  GST_SYSTEM_CLOCK_ENTRY_UNLOCK ((GstClockEntryImpl *) entry);
 
   if (priv->entries)
     head = priv->entries->data;
@@ -933,6 +1196,7 @@ gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry)
 
   /* need to take a ref */
   gst_clock_id_ref ((GstClockID) entry);
+
   /* insert the entry in sorted order */
   priv->entries = g_list_insert_sorted (priv->entries, entry,
       gst_clock_id_compare_func);
@@ -941,31 +1205,36 @@ gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry)
    * front, else the thread is just waiting for another entry and
    * will get to this entry automatically. */
   if (priv->entries->data == entry) {
-    GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry added to head %p", head);
+    GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
+        "async entry added to head %p", head);
     if (head == NULL) {
       /* the list was empty before, signal the cond so that the async thread can
        * start taking a look at the queue */
-      GST_CAT_DEBUG (GST_CAT_CLOCK, "first entry, sending signal");
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
+          "first entry, sending signal");
       GST_SYSTEM_CLOCK_BROADCAST (clock);
     } else {
       GstClockReturn status;
 
-      status = GET_ENTRY_STATUS (head);
-      GST_CAT_DEBUG (GST_CAT_CLOCK, "head entry %p status %d", head, status);
+      /* it was initialized before adding to the list */
+      g_assert (((GstClockEntryImpl *) head)->initialized);
+
+      GST_SYSTEM_CLOCK_ENTRY_LOCK ((GstClockEntryImpl *) head);
+      status = GST_CLOCK_ENTRY_STATUS (head);
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "head entry %p status %d",
+          head, status);
 
       if (status == GST_CLOCK_BUSY) {
-        GST_CAT_DEBUG (GST_CAT_CLOCK, "head entry is busy");
         /* the async thread was waiting for an entry, unlock the wait so that it
          * looks at the new head entry instead, we only need to do this once */
-        if (!priv->async_wakeup) {
-          GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup async thread");
-          priv->async_wakeup = TRUE;
-          gst_system_clock_add_wakeup (sysclock);
-        }
+        GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
+            "head entry was busy. Wakeup async thread");
+        GST_SYSTEM_CLOCK_ENTRY_BROADCAST ((GstClockEntryImpl *) head);
       }
+      GST_SYSTEM_CLOCK_ENTRY_UNLOCK ((GstClockEntryImpl *) head);
     }
   }
-  GST_OBJECT_UNLOCK (clock);
+  GST_SYSTEM_CLOCK_UNLOCK (clock);
 
   return GST_CLOCK_OK;
 
@@ -973,12 +1242,13 @@ gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry)
 thread_error:
   {
     /* Could not start the async clock thread */
-    GST_OBJECT_UNLOCK (clock);
+    GST_SYSTEM_CLOCK_UNLOCK (clock);
     return GST_CLOCK_ERROR;
   }
 was_unscheduled:
   {
-    GST_OBJECT_UNLOCK (clock);
+    GST_SYSTEM_CLOCK_ENTRY_UNLOCK ((GstClockEntryImpl *) entry);
+    GST_SYSTEM_CLOCK_UNLOCK (clock);
     return GST_CLOCK_UNSCHEDULED;
   }
 }
@@ -993,30 +1263,25 @@ was_unscheduled:
 static void
 gst_system_clock_id_unschedule (GstClock * clock, GstClockEntry * entry)
 {
-  GstSystemClock *sysclock;
   GstClockReturn status;
 
-  sysclock = GST_SYSTEM_CLOCK_CAST (clock);
+  GST_SYSTEM_CLOCK_LOCK (clock);
+
+  GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "unscheduling entry %p time %"
+      GST_TIME_FORMAT, entry, GST_TIME_ARGS (GST_CLOCK_ENTRY_TIME (entry)));
 
-  GST_CAT_DEBUG (GST_CAT_CLOCK, "unscheduling entry %p", entry);
+  ensure_entry_initialized ((GstClockEntryImpl *) entry);
 
-  GST_OBJECT_LOCK (clock);
+  GST_SYSTEM_CLOCK_ENTRY_LOCK ((GstClockEntryImpl *) entry);
   /* change the entry status to unscheduled */
-  do {
-    status = GET_ENTRY_STATUS (entry);
-  } while (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status,
-              GST_CLOCK_UNSCHEDULED)));
+  status = GST_CLOCK_ENTRY_STATUS (entry);
+  GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_UNSCHEDULED;
 
   if (G_LIKELY (status == GST_CLOCK_BUSY)) {
-    /* the entry was being busy, wake up all entries so that they recheck their
-     * status. We cannot wake up just one entry because allocating such a
-     * datastructure for each entry would be too heavy and unlocking an entry
-     * is usually done when shutting down or some other exceptional case. */
-    GST_CAT_DEBUG (GST_CAT_CLOCK, "entry was BUSY, doing wakeup");
-    if (!entry->unscheduled && !entry->woken_up) {
-      gst_system_clock_add_wakeup (sysclock);
-      entry->woken_up = TRUE;
-    }
+    /* the entry was being busy, wake up the entry */
+    GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "entry was BUSY, doing wakeup");
+    GST_SYSTEM_CLOCK_ENTRY_BROADCAST ((GstClockEntryImpl *) entry);
   }
-  GST_OBJECT_UNLOCK (clock);
+  GST_SYSTEM_CLOCK_ENTRY_UNLOCK ((GstClockEntryImpl *) entry);
+  GST_SYSTEM_CLOCK_UNLOCK (clock);
 }
index 585afb8..01b1f22 100644 (file)
@@ -48,13 +48,16 @@ typedef struct _GstSystemClockPrivate GstSystemClockPrivate;
  * @GST_CLOCK_TYPE_MONOTONIC: monotonic time since some unspecified starting
  *                            point
  * @GST_CLOCK_TYPE_OTHER: some other time source is used (Since: 1.0.5)
+ * @GST_CLOCK_TYPE_TAI: time since Epoch, but using International Atomic Time
+ *                      as reference (Since: 1.18)
  *
  * The different kind of clocks.
  */
 typedef enum {
   GST_CLOCK_TYPE_REALTIME       = 0,
   GST_CLOCK_TYPE_MONOTONIC      = 1,
-  GST_CLOCK_TYPE_OTHER          = 2
+  GST_CLOCK_TYPE_OTHER          = 2,
+  GST_CLOCK_TYPE_TAI            = 3
 } GstClockType;
 
 /**
@@ -87,9 +90,7 @@ GstClock*               gst_system_clock_obtain         (void);
 GST_API
 void                    gst_system_clock_set_default    (GstClock *new_clock);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstSystemClock, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index c304609..f74fc51 100644 (file)
@@ -34,6 +34,7 @@
 #  include "config.h"
 #endif
 
+#define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 #include "gst_private.h"
 #include "math-compat.h"
 #include "gst-i18n-lib.h"
@@ -958,24 +959,35 @@ gst_tag_list_is_empty (const GstTagList * list)
 }
 
 static gboolean
-gst_tag_list_fields_equal (const GValue * value1, const GValue * value2)
+gst_tag_list_fields_equal (GQuark field_id, const GValue * value2,
+    gpointer data)
 {
+  const GstStructure *struct1 = (const GstStructure *) data;
+  const GValue *value1 = gst_structure_id_get_value (struct1, field_id);
   gdouble d1, d2;
 
+  if (value1 == NULL) {
+    /* no value with this field id, clearly not equal */
+    return FALSE;
+  }
+
   if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL)
     return TRUE;
 
   /* fields not equal: add some tolerance for doubles, otherwise bail out */
-  if (!G_VALUE_HOLDS_DOUBLE (value1) || !G_VALUE_HOLDS_DOUBLE (value2))
-    return FALSE;
+  if ((G_VALUE_TYPE (value1) == G_VALUE_TYPE (value2)) &&
+      G_VALUE_TYPE (value1) == G_TYPE_DOUBLE) {
+    d1 = g_value_get_double (value1);
+    d2 = g_value_get_double (value2);
 
-  d1 = g_value_get_double (value1);
-  d2 = g_value_get_double (value2);
+    /* This will only work for 'normal' values and values around 0,
+     * which should be good enough for our purposes here
+     * FIXME: maybe add this to gst_value_compare_double() ? */
+    return (fabs (d1 - d2) < 0.0000001);
 
-  /* This will only work for 'normal' values and values around 0,
-   * which should be good enough for our purposes here
-   * FIXME: maybe add this to gst_value_compare_double() ? */
-  return (fabs (d1 - d2) < 0.0000001);
+  }
+
+  return FALSE;
 }
 
 /**
@@ -991,7 +1003,6 @@ gboolean
 gst_tag_list_is_equal (const GstTagList * list1, const GstTagList * list2)
 {
   const GstStructure *s1, *s2;
-  gint num_fields1, num_fields2, i;
 
   g_return_val_if_fail (GST_IS_TAG_LIST (list1), FALSE);
   g_return_val_if_fail (GST_IS_TAG_LIST (list2), FALSE);
@@ -1002,28 +1013,14 @@ gst_tag_list_is_equal (const GstTagList * list1, const GstTagList * list2)
   s1 = GST_TAG_LIST_STRUCTURE (list1);
   s2 = GST_TAG_LIST_STRUCTURE (list2);
 
-  num_fields1 = gst_structure_n_fields (s1);
-  num_fields2 = gst_structure_n_fields (s2);
+  if (G_UNLIKELY (s1 == s2))
+    return TRUE;
 
-  if (num_fields1 != num_fields2)
+  if (gst_structure_n_fields (s1) != gst_structure_n_fields (s2)) {
     return FALSE;
-
-  for (i = 0; i < num_fields1; i++) {
-    const GValue *value1, *value2;
-    const gchar *tag_name;
-
-    tag_name = gst_structure_nth_field_name (s1, i);
-    value1 = gst_structure_get_value (s1, tag_name);
-    value2 = gst_structure_get_value (s2, tag_name);
-
-    if (value2 == NULL)
-      return FALSE;
-
-    if (!gst_tag_list_fields_equal (value1, value2))
-      return FALSE;
   }
 
-  return TRUE;
+  return gst_structure_foreach (s1, gst_tag_list_fields_equal, (gpointer) s2);
 }
 
 typedef struct
@@ -2070,3 +2067,123 @@ gst_tag_list_get_sample_index (const GstTagList * list,
   *sample = g_value_dup_boxed (v);
   return (*sample != NULL);
 }
+
+/**
+ * gst_tag_list_copy:
+ * @taglist: a #GstTagList.
+ *
+ * Creates a new #GstTagList as a copy of the old @taglist. The new taglist
+ * will have a refcount of 1, owned by the caller, and will be writable as
+ * a result.
+ *
+ * Note that this function is the semantic equivalent of a gst_tag_list_ref()
+ * followed by a gst_tag_list_make_writable(). If you only want to hold on to a
+ * reference to the data, you should use gst_tag_list_ref().
+ *
+ * When you are finished with the taglist, call gst_tag_list_unref() on it.
+ *
+ * Returns: the new #GstTagList
+ */
+GstTagList *(gst_tag_list_copy) (const GstTagList * taglist)
+{
+  return GST_TAG_LIST (gst_mini_object_copy (GST_MINI_OBJECT_CAST (taglist)));
+}
+
+/**
+ * gst_tag_list_ref: (skip)
+ * @taglist: the #GstTagList to reference
+ *
+ * Add a reference to a #GstTagList mini object.
+ *
+ * From this point on, until the caller calls gst_tag_list_unref() or
+ * gst_tag_list_make_writable(), it is guaranteed that the taglist object will
+ * not change. To use a #GstTagList object, you must always have a refcount on
+ * it -- either the one made implicitly by e.g. gst_tag_list_new(), or via
+ * taking one explicitly with this function.
+ *
+ * Returns: the same #GstTagList mini object.
+ */
+GstTagList *
+gst_tag_list_ref (GstTagList * taglist)
+{
+  return (GstTagList *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (taglist));
+}
+
+/**
+ * gst_tag_list_unref: (skip)
+ * @taglist: a #GstTagList.
+ *
+ * Unref a #GstTagList, and and free all its memory when the refcount reaches 0.
+ */
+void
+gst_tag_list_unref (GstTagList * taglist)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (taglist));
+}
+
+/**
+ * gst_clear_tag_list: (skip)
+ * @taglist_ptr: a pointer to a #GstTagList reference
+ *
+ * Clears a reference to a #GstTagList.
+ *
+ * @taglist_ptr must not be %NULL.
+ *
+ * If the reference is %NULL then this function does nothing. Otherwise, the
+ * reference count of the taglist is decreased and the pointer is set to %NULL.
+ *
+ * Since: 1.16
+ */
+void
+gst_clear_tag_list (GstTagList ** taglist_ptr)
+{
+  gst_clear_mini_object ((GstMiniObject **) taglist_ptr);
+}
+
+/**
+ * gst_tag_list_replace:
+ * @old_taglist: (inout) (transfer full) (nullable): pointer to a pointer to a
+ *     #GstTagList to be replaced.
+ * @new_taglist: (transfer none) (allow-none): pointer to a #GstTagList that
+ *     will replace the tag list pointed to by @old_taglist.
+ *
+ * Modifies a pointer to a #GstTagList to point to a different #GstTagList. 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 tag list is unreffed, the new is reffed).
+ *
+ * Either @new_taglist or the #GstTagList pointed to by @old_taglist may be
+ * %NULL.
+ *
+ * Returns: %TRUE if @new_taglist was different from @old_taglist
+ *
+ * Since: 1.16
+ */
+gboolean
+gst_tag_list_replace (GstTagList ** old_taglist, GstTagList * new_taglist)
+{
+  return gst_mini_object_replace ((GstMiniObject **) old_taglist,
+      (GstMiniObject *) new_taglist);
+}
+
+/**
+ * gst_tag_list_take:
+ * @old_taglist: (inout) (transfer full): pointer to a pointer to a #GstTagList
+ *     to be replaced.
+ * @new_taglist: (transfer full) (allow-none): pointer to a #GstTagList that
+ *     will replace the taglist pointed to by @old_taglist.
+ *
+ * Modifies a pointer to a #GstTagList to point to a different #GstTagList.
+ * This function is similar to gst_tag_list_replace() except that it takes
+ * ownership of @new_taglist.
+ *
+ * Returns: %TRUE if @new_taglist was different from @old_taglist
+ *
+ * Since: 1.16
+ */
+gboolean
+gst_tag_list_take (GstTagList ** old_taglist, GstTagList * new_taglist)
+{
+  return gst_mini_object_take ((GstMiniObject **) old_taglist,
+      (GstMiniObject *) new_taglist);
+}
index c964d1b..e8e4f3a 100644 (file)
@@ -49,65 +49,16 @@ G_BEGIN_DECLS
  * In the table below this is shown for the cases that a tag exists in the list
  * (A) or does not exists (!A) and combinations thereof.
  *
- * <table frame="all" colsep="1" rowsep="1">
- *   <title>merge mode</title>
- *   <tgroup cols='5' align='left'>
- *     <thead>
- *       <row>
- *         <entry>merge mode</entry>
- *         <entry>A + B</entry>
- *         <entry>A + !B</entry>
- *         <entry>!A + B</entry>
- *         <entry>!A + !B</entry>
- *       </row>
- *     </thead>
- *     <tbody>
- *       <row>
- *         <entry>REPLACE_ALL</entry>
- *         <entry>B</entry>
- *         <entry>-</entry>
- *         <entry>B</entry>
- *         <entry>-</entry>
- *       </row>
- *       <row>
- *         <entry>REPLACE</entry>
- *         <entry>B</entry>
- *         <entry>A</entry>
- *         <entry>B</entry>
- *         <entry>-</entry>
- *       </row>
- *       <row>
- *         <entry>APPEND</entry>
- *         <entry>A, B</entry>
- *         <entry>A</entry>
- *         <entry>B</entry>
- *         <entry>-</entry>
- *       </row>
- *       <row>
- *         <entry>PREPEND</entry>
- *         <entry>B, A</entry>
- *         <entry>A</entry>
- *         <entry>B</entry>
- *         <entry>-</entry>
- *       </row>
- *       <row>
- *         <entry>KEEP</entry>
- *         <entry>A</entry>
- *         <entry>A</entry>
- *         <entry>B</entry>
- *         <entry>-</entry>
- *       </row>
- *       <row>
- *         <entry>KEEP_ALL</entry>
- *         <entry>A</entry>
- *         <entry>A</entry>
- *         <entry>-</entry>
- *         <entry>-</entry>
- *       </row>
- *     </tbody>
- *   </tgroup>
- * </table>
+ * | merge mode  | A + B | A + !B | !A + B | !A + !B |
+ * | ----------- | ----- | ------ | ------ | ------- |
+ * | REPLACE_ALL | B     | ø      | B      | ø       |
+ * | REPLACE     | B     | A      | B      | ø       |
+ * | APPEND      | A, B  | A      | B      | ø       |
+ * | PREPEND     | B, A  | A      | B      | ø       |
+ * | KEEP        | A     | A      | B      | ø       |
+ * | KEEP_ALL    | A     | A      | ø      | ø       |
  */
+
 typedef enum {
   GST_TAG_MERGE_UNDEFINED,
   GST_TAG_MERGE_REPLACE_ALL,
@@ -250,7 +201,7 @@ GST_API
 GstTagList * gst_tag_list_new_empty         (void) G_GNUC_MALLOC;
 
 GST_API
-GstTagList * gst_tag_list_new               (const gchar * tag, ...) G_GNUC_MALLOC;
+GstTagList * gst_tag_list_new               (const gchar * tag, ...) G_GNUC_NULL_TERMINATED G_GNUC_MALLOC;
 
 GST_API
 GstTagList * gst_tag_list_new_valist        (va_list var_args) G_GNUC_MALLOC;
@@ -448,99 +399,42 @@ gboolean     gst_tag_list_get_sample_index  (const GstTagList * list,
                                              guint              index,
                                              GstSample       ** sample);
 
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 /* refcounting */
-/**
- * gst_tag_list_ref:
- * @taglist: the #GstTagList to reference
- *
- * Add a reference to a #GstTagList mini object.
- *
- * From this point on, until the caller calls gst_tag_list_unref() or
- * gst_tag_list_make_writable(), it is guaranteed that the taglist object will
- * not change. To use a #GstTagList object, you must always have a refcount on
- * it -- either the one made implicitly by e.g. gst_tag_list_new(), or via
- * taking one explicitly with this function.
- *
- * Returns: the same #GstTagList mini object.
- */
 static inline GstTagList *
 gst_tag_list_ref (GstTagList * taglist)
 {
   return (GstTagList *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (taglist));
 }
 
-/**
- * gst_tag_list_unref:
- * @taglist: a #GstTagList.
- *
- * Unref a #GstTagList, and and free all its memory when the refcount reaches 0.
- */
 static inline void
 gst_tag_list_unref (GstTagList * taglist)
 {
   gst_mini_object_unref (GST_MINI_OBJECT_CAST (taglist));
 }
 
-/**
- * gst_clear_tag_list: (skip)
- * @taglist_ptr: a pointer to a #GstTagList reference
- *
- * Clears a reference to a #GstTagList.
- *
- * @taglist_ptr must not be %NULL.
- *
- * If the reference is %NULL then this function does nothing. Otherwise, the
- * reference count of the taglist is decreased and the pointer is set to %NULL.
- *
- * Since: 1.16
- */
 static inline void
 gst_clear_tag_list (GstTagList ** taglist_ptr)
 {
   gst_clear_mini_object ((GstMiniObject **) taglist_ptr);
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+GstTagList *  gst_tag_list_ref   (GstTagList * taglist);
 
-/**
- * gst_tag_list_copy:
- * @taglist: a #GstTagList.
- *
- * Creates a new #GstTagList as a copy of the old @taglist. The new taglist
- * will have a refcount of 1, owned by the caller, and will be writable as
- * a result.
- *
- * Note that this function is the semantic equivalent of a gst_tag_list_ref()
- * followed by a gst_tag_list_make_writable(). If you only want to hold on to a
- * reference to the data, you should use gst_tag_list_ref().
- *
- * When you are finished with the taglist, call gst_tag_list_unref() on it.
- *
- * Returns: the new #GstTagList
- */
-static inline GstTagList *
-gst_tag_list_copy (const GstTagList * taglist)
-{
-  return GST_TAG_LIST (gst_mini_object_copy (GST_MINI_OBJECT_CAST (taglist)));
-}
+GST_API
+void          gst_tag_list_unref (GstTagList * taglist);
 
-/**
- * gst_tag_list_replace:
- * @old_taglist: (inout) (transfer full) (nullable): pointer to a pointer to a
- *     #GstTagList to be replaced.
- * @new_taglist: (transfer none) (allow-none): pointer to a #GstTagList that
- *     will replace the tag list pointed to by @old_taglist.
- *
- * Modifies a pointer to a #GstTagList to point to a different #GstTagList. 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 tag list is unreffed, the new is reffed).
- *
- * Either @new_taglist or the #GstTagList pointed to by @old_taglist may be
- * %NULL.
- *
- * Returns: %TRUE if @new_taglist was different from @old_taglist
- *
- * Since: 1.16
- */
+GST_API
+void          gst_clear_tag_list (GstTagList ** taglist_ptr);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+
+GST_API
+GstTagList* gst_tag_list_copy(const GstTagList* taglist);
+
+#define gst_tag_list_copy(taglist) GST_TAG_LIST (gst_mini_object_copy (GST_MINI_OBJECT_CAST (taglist)))
+
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 static inline gboolean
 gst_tag_list_replace (GstTagList **old_taglist, GstTagList *new_taglist)
 {
@@ -548,27 +442,21 @@ gst_tag_list_replace (GstTagList **old_taglist, GstTagList *new_taglist)
         (GstMiniObject *) new_taglist);
 }
 
-/**
- * gst_tag_list_take:
- * @old_taglist: (inout) (transfer full): pointer to a pointer to a #GstTagList
- *     to be replaced.
- * @new_taglist: (transfer full) (allow-none): pointer to a #GstTagList that
- *     will replace the taglist pointed to by @old_taglist.
- *
- * Modifies a pointer to a #GstTagList to point to a different #GstTagList.
- * This function is similar to gst_tag_list_replace() except that it takes
- * ownership of @new_taglist.
- *
- * Returns: %TRUE if @new_taglist was different from @old_taglist
- *
- * Since: 1.16
- */
 static inline gboolean
 gst_tag_list_take (GstTagList **old_taglist, GstTagList *new_taglist)
 {
   return gst_mini_object_take ((GstMiniObject **) old_taglist,
       (GstMiniObject *) new_taglist);
 }
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+gboolean  gst_tag_list_replace (GstTagList ** old_taglist,
+                                GstTagList * new_taglist);
+
+GST_API
+gboolean  gst_tag_list_take    (GstTagList ** old_taglist,
+                                GstTagList * new_taglist);
+#endif
 
 /**
  * gst_tag_list_is_writable:
@@ -946,7 +834,7 @@ gst_tag_list_take (GstTagList **old_taglist, GstTagList *new_taglist)
  * ISO-639-2 or ISO-639-1 code for the language the content is in (string)
  *
  * There is utility API in libgsttag in gst-plugins-base to obtain a translated
- * language name from the language code: gst_tag_get_language_name()
+ * language name from the language code: `gst_tag_get_language_name()`
  */
 #define GST_TAG_LANGUAGE_CODE          "language-code"
 /**
@@ -963,7 +851,7 @@ gst_tag_list_take (GstTagList **old_taglist, GstTagList *new_taglist)
  * GST_TAG_IMAGE:
  *
  * image (sample) (sample taglist should specify the content type and preferably
- * also set "image-type" field as #GstTagImageType)
+ * also set "image-type" field as `GstTagImageType`)
  */
 #define GST_TAG_IMAGE                  "image"
 /**
@@ -1210,7 +1098,7 @@ gst_tag_list_take (GstTagList **old_taglist, GstTagList *new_taglist)
 /**
  * GST_TAG_MIDI_BASE_NOTE:
  *
- * <ulink url="http://en.wikipedia.org/wiki/Note#Note_designation_in_accordance_with_octave_name">Midi note number</ulink>
+ * [Midi note number](http://en.wikipedia.org/wiki/Note#Note_designation_in_accordance_with_octave_name)
  * of the audio track. This is useful for sample instruments and in particular
  * for multi-samples.
  *
@@ -1235,9 +1123,7 @@ gst_tag_list_take (GstTagList **old_taglist, GstTagList *new_taglist)
  */
 #define GST_TAG_PRIVATE_DATA                         "private-data"
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTagList, gst_tag_list_unref)
-#endif
 
 G_END_DECLS
 
index 30f25fe..da81820 100644 (file)
@@ -112,6 +112,11 @@ struct _GstTaskPrivate
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 
+typedef HRESULT (WINAPI * pSetThreadDescription) (HANDLE hThread,
+    PCWSTR lpThreadDescription);
+static pSetThreadDescription SetThreadDescriptionFunc = NULL;
+HMODULE kernel32_module = NULL;
+
 struct _THREADNAME_INFO
 {
   DWORD dwType;                 // must be 0x1000
@@ -121,7 +126,7 @@ struct _THREADNAME_INFO
 };
 typedef struct _THREADNAME_INFO THREADNAME_INFO;
 
-void
+static void
 SetThreadName (DWORD dwThreadID, LPCSTR szThreadName)
 {
   THREADNAME_INFO info;
@@ -137,6 +142,57 @@ SetThreadName (DWORD dwThreadID, LPCSTR szThreadName)
   __except (EXCEPTION_CONTINUE_EXECUTION) {
   }
 }
+
+static gboolean
+gst_task_win32_load_library (void)
+{
+  /* FIXME: Add support for UWP app */
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+  static gsize _init_once = 0;
+  if (g_once_init_enter (&_init_once)) {
+    kernel32_module = LoadLibraryW (L"kernel32.dll");
+    if (kernel32_module) {
+      SetThreadDescriptionFunc =
+          (pSetThreadDescription) GetProcAddress (kernel32_module,
+          "SetThreadDescription");
+      if (!SetThreadDescriptionFunc)
+        FreeLibrary (kernel32_module);
+    }
+    g_once_init_leave (&_init_once, 1);
+  }
+#endif
+
+  return ! !SetThreadDescriptionFunc;
+}
+
+static gboolean
+gst_task_win32_set_thread_desc (const gchar * name)
+{
+  HRESULT hr;
+  wchar_t *namew;
+
+  if (!gst_task_win32_load_library () || !name)
+    return FALSE;
+
+  namew = g_utf8_to_utf16 (name, -1, NULL, NULL, NULL);
+  if (!namew)
+    return FALSE;
+
+  hr = SetThreadDescriptionFunc (GetCurrentThread (), namew);
+
+  g_free (namew);
+  return SUCCEEDED (hr);
+}
+
+static void
+gst_task_win32_set_thread_name (const gchar * name)
+{
+  /* Prefer SetThreadDescription over exception based way if available,
+   * since thread description set by SetThreadDescription will be preserved
+   * in dump file */
+  if (!gst_task_win32_set_thread_desc (name))
+    SetThreadName ((DWORD) - 1, name);
+}
 #endif
 
 static void gst_task_finalize (GObject * object);
@@ -145,6 +201,8 @@ static void gst_task_func (GstTask * task);
 
 static GMutex pool_lock;
 
+static GstTaskPool *_global_task_pool = NULL;
+
 #define _do_init \
 { \
   GST_DEBUG_CATEGORY_INIT (task_debug, "task", 0, "Processing tasks"); \
@@ -153,19 +211,18 @@ static GMutex pool_lock;
 G_DEFINE_TYPE_WITH_CODE (GstTask, gst_task, GST_TYPE_OBJECT,
     G_ADD_PRIVATE (GstTask) _do_init);
 
+/* Called with pool_lock */
 static void
-init_klass_pool (GstTaskClass * klass)
+ensure_klass_pool (GstTaskClass * klass)
 {
-  g_mutex_lock (&pool_lock);
-  if (klass->pool) {
-    gst_task_pool_cleanup (klass->pool);
-    gst_object_unref (klass->pool);
+  if (G_UNLIKELY (_global_task_pool == NULL)) {
+    _global_task_pool = gst_task_pool_new ();
+    gst_task_pool_prepare (_global_task_pool, NULL);
+
+    /* Classes are never destroyed so this ref will never be dropped */
+    GST_OBJECT_FLAG_SET (_global_task_pool, GST_OBJECT_FLAG_MAY_BE_LEAKED);
   }
-  klass->pool = gst_task_pool_new ();
-  /* Classes are never destroyed so this ref will never be dropped */
-  GST_OBJECT_FLAG_SET (klass->pool, GST_OBJECT_FLAG_MAY_BE_LEAKED);
-  gst_task_pool_prepare (klass->pool, NULL);
-  g_mutex_unlock (&pool_lock);
+  klass->pool = _global_task_pool;
 }
 
 static void
@@ -176,8 +233,6 @@ gst_task_class_init (GstTaskClass * klass)
   gobject_class = (GObjectClass *) klass;
 
   gobject_class->finalize = gst_task_finalize;
-
-  init_klass_pool (klass);
 }
 
 static void
@@ -197,6 +252,7 @@ gst_task_init (GstTask * task)
   /* use the default klass pool for this task, users can
    * override this later */
   g_mutex_lock (&pool_lock);
+  ensure_klass_pool (klass);
   task->priv->pool = gst_object_ref (klass->pool);
   g_mutex_unlock (&pool_lock);
 }
@@ -265,7 +321,7 @@ gst_task_configure_name (GstTask * task)
 
   /* set the thread name to something easily identifiable */
   GST_DEBUG_OBJECT (task, "Setting thread name to '%s'", name);
-  SetThreadName (-1, name);
+  gst_task_win32_set_thread_name (name);
 #endif
 }
 
@@ -378,7 +434,14 @@ gst_task_cleanup_all (void)
   GstTaskClass *klass;
 
   if ((klass = g_type_class_peek (GST_TYPE_TASK))) {
-    init_klass_pool (klass);
+    if (klass->pool) {
+      g_mutex_lock (&pool_lock);
+      gst_task_pool_cleanup (klass->pool);
+      gst_object_unref (klass->pool);
+      klass->pool = NULL;
+      _global_task_pool = NULL;
+      g_mutex_unlock (&pool_lock);
+    }
   }
 
   /* GstElement owns a GThreadPool */
@@ -657,33 +720,14 @@ start_task (GstTask * task)
   return res;
 }
 
-
-/**
- * gst_task_set_state:
- * @task: a #GstTask
- * @state: the new task state
- *
- * Sets the state of @task to @state.
- *
- * The @task must have a lock associated with it using
- * gst_task_set_lock() when going to GST_TASK_STARTED or GST_TASK_PAUSED or
- * this function will return %FALSE.
- *
- * MT safe.
- *
- * Returns: %TRUE if the state could be changed.
- */
-gboolean
-gst_task_set_state (GstTask * task, GstTaskState state)
+static inline gboolean
+gst_task_set_state_unlocked (GstTask * task, GstTaskState state)
 {
   GstTaskState old;
   gboolean res = TRUE;
 
-  g_return_val_if_fail (GST_IS_TASK (task), FALSE);
-
   GST_DEBUG_OBJECT (task, "Changing task %p to state %d", task, state);
 
-  GST_OBJECT_LOCK (task);
   if (state != GST_TASK_STOPPED)
     if (G_UNLIKELY (GST_TASK_GET_LOCK (task) == NULL))
       goto no_lock;
@@ -709,7 +753,6 @@ gst_task_set_state (GstTask * task, GstTaskState state)
         break;
     }
   }
-  GST_OBJECT_UNLOCK (task);
 
   return res;
 
@@ -717,12 +760,41 @@ gst_task_set_state (GstTask * task, GstTaskState state)
 no_lock:
   {
     GST_WARNING_OBJECT (task, "state %d set on task without a lock", state);
-    GST_OBJECT_UNLOCK (task);
     g_warning ("task without a lock can't be set to state %d", state);
     return FALSE;
   }
 }
 
+
+/**
+ * gst_task_set_state:
+ * @task: a #GstTask
+ * @state: the new task state
+ *
+ * Sets the state of @task to @state.
+ *
+ * The @task must have a lock associated with it using
+ * gst_task_set_lock() when going to GST_TASK_STARTED or GST_TASK_PAUSED or
+ * this function will return %FALSE.
+ *
+ * MT safe.
+ *
+ * Returns: %TRUE if the state could be changed.
+ */
+gboolean
+gst_task_set_state (GstTask * task, GstTaskState state)
+{
+  gboolean res = TRUE;
+
+  g_return_val_if_fail (GST_IS_TASK (task), FALSE);
+
+  GST_OBJECT_LOCK (task);
+  res = gst_task_set_state_unlocked (task, state);
+  GST_OBJECT_UNLOCK (task);
+
+  return res;
+}
+
 /**
  * gst_task_start:
  * @task: The #GstTask to start
@@ -778,6 +850,32 @@ gst_task_pause (GstTask * task)
 }
 
 /**
+ * gst_task_resume:
+ * @task: The #GstTask to resume
+ *
+ * Resume @task in case it was paused. If the task was stopped, it will
+ * remain in that state and this function will return %FALSE.
+ *
+ * Returns: %TRUE if the task could be resumed.
+ *
+ * MT safe.
+ * Since: 1.18
+ */
+gboolean
+gst_task_resume (GstTask * task)
+{
+  gboolean res = FALSE;
+  g_return_val_if_fail (GST_IS_TASK (task), FALSE);
+
+  GST_OBJECT_LOCK (task);
+  if (GET_TASK_STATE (task) != GST_TASK_STOPPED)
+    res = gst_task_set_state_unlocked (task, GST_TASK_STARTED);
+  GST_OBJECT_UNLOCK (task);
+
+  return res;
+}
+
+/**
  * gst_task_join:
  * @task: The #GstTask to join
  *
index f93d4c1..7ae1d43 100644 (file)
@@ -208,11 +208,12 @@ GST_API
 gboolean        gst_task_pause          (GstTask *task);
 
 GST_API
+gboolean        gst_task_resume         (GstTask *task);
+
+GST_API
 gboolean        gst_task_join           (GstTask *task);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTask, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 89c8905..3116cc7 100644 (file)
@@ -127,6 +127,12 @@ default_join (GstTaskPool * pool, gpointer id)
 }
 
 static void
+default_dispose_handle (GstTaskPool * pool, gpointer id)
+{
+  /* we do nothing here, the default handle is NULL */
+}
+
+static void
 gst_task_pool_class_init (GstTaskPoolClass * klass)
 {
   GObjectClass *gobject_class;
@@ -143,6 +149,7 @@ gst_task_pool_class_init (GstTaskPoolClass * klass)
   gsttaskpool_class->cleanup = default_cleanup;
   gsttaskpool_class->push = default_push;
   gsttaskpool_class->join = default_join;
+  gsttaskpool_class->dispose_handle = default_dispose_handle;
 }
 
 static void
@@ -233,9 +240,11 @@ gst_task_pool_cleanup (GstTaskPool * pool)
  *
  * Start the execution of a new thread from @pool.
  *
- * Returns: (transfer none) (nullable): a pointer that should be used
+ * Returns: (transfer full) (nullable): a pointer that should be used
  * for the gst_task_pool_join function. This pointer can be %NULL, you
- * must check @error to detect errors.
+ * must check @error to detect errors. If the pointer is not %NULL and
+ * gst_task_pool_join() is not used, call gst_task_pool_dispose_handle()
+ * instead.
  */
 gpointer
 gst_task_pool_push (GstTaskPool * pool, GstTaskPoolFunction func,
@@ -263,10 +272,14 @@ not_supported:
 /**
  * gst_task_pool_join:
  * @pool: a #GstTaskPool
- * @id: the id
+ * @id: (transfer full) (nullable): the id
  *
  * Join a task and/or return it to the pool. @id is the id obtained from
- * gst_task_pool_push().
+ * gst_task_pool_push(). The default implementation does nothing, as the
+ * default #GstTaskPoolClass::push implementation always returns %NULL.
+ *
+ * This method should only be called with the same @pool instance that provided
+ * @id.
  */
 void
 gst_task_pool_join (GstTaskPool * pool, gpointer id)
@@ -280,3 +293,257 @@ gst_task_pool_join (GstTaskPool * pool, gpointer id)
   if (klass->join)
     klass->join (pool, id);
 }
+
+/**
+ * gst_task_pool_dispose_handle:
+ * @pool: a #GstTaskPool
+ * @id: (transfer full) (nullable): the id
+ *
+ * Dispose of the handle returned by gst_task_pool_push(). This does
+ * not need to be called with the default implementation as the default
+ * #GstTaskPoolClass::push implementation always returns %NULL. This does not need to be
+ * called either when calling gst_task_pool_join(), but should be called
+ * when joining is not necessary, but gst_task_pool_push() returned a
+ * non-%NULL value.
+ *
+ * This method should only be called with the same @pool instance that provided
+ * @id.
+ *
+ * Since: 1.20
+ */
+void
+gst_task_pool_dispose_handle (GstTaskPool * pool, gpointer id)
+{
+  GstTaskPoolClass *klass;
+
+  g_return_if_fail (GST_IS_TASK_POOL (pool));
+
+  klass = GST_TASK_POOL_GET_CLASS (pool);
+
+  if (klass->dispose_handle)
+    klass->dispose_handle (pool, id);
+}
+
+typedef struct
+{
+  gboolean done;
+  guint64 id;
+  GstTaskPoolFunction func;
+  gpointer user_data;
+  GMutex done_lock;
+  GCond done_cond;
+  gint refcount;
+} SharedTaskData;
+
+static SharedTaskData *
+shared_task_data_ref (SharedTaskData * tdata)
+{
+  g_atomic_int_add (&tdata->refcount, 1);
+
+  return tdata;
+}
+
+static void
+shared_task_data_unref (SharedTaskData * tdata)
+{
+  if (g_atomic_int_dec_and_test (&tdata->refcount)) {
+    g_mutex_clear (&tdata->done_lock);
+    g_cond_clear (&tdata->done_cond);
+    g_slice_free (SharedTaskData, tdata);
+  }
+}
+
+struct _GstSharedTaskPoolPrivate
+{
+  guint max_threads;
+};
+
+#define GST_SHARED_TASK_POOL_CAST(pool)       ((GstSharedTaskPool*)(pool))
+
+G_DEFINE_TYPE_WITH_PRIVATE (GstSharedTaskPool, gst_shared_task_pool,
+    GST_TYPE_TASK_POOL);
+
+static void
+shared_func (SharedTaskData * tdata, GstTaskPool * pool)
+{
+  tdata->func (tdata->user_data);
+
+  g_mutex_lock (&tdata->done_lock);
+  tdata->done = TRUE;
+  g_cond_signal (&tdata->done_cond);
+  g_mutex_unlock (&tdata->done_lock);
+
+  shared_task_data_unref (tdata);
+}
+
+static gpointer
+shared_push (GstTaskPool * pool, GstTaskPoolFunction func,
+    gpointer user_data, GError ** error)
+{
+  SharedTaskData *ret = NULL;
+
+  GST_OBJECT_LOCK (pool);
+
+  if (!pool->pool) {
+    GST_OBJECT_UNLOCK (pool);
+    goto done;
+  }
+
+  ret = g_slice_new (SharedTaskData);
+
+  ret->done = FALSE;
+  ret->func = func;
+  ret->user_data = user_data;
+  g_atomic_int_set (&ret->refcount, 1);
+  g_cond_init (&ret->done_cond);
+  g_mutex_init (&ret->done_lock);
+
+  g_thread_pool_push (pool->pool, shared_task_data_ref (ret), error);
+
+  GST_OBJECT_UNLOCK (pool);
+
+done:
+  return ret;
+}
+
+static void
+shared_join (GstTaskPool * pool, gpointer id)
+{
+  SharedTaskData *tdata;
+
+  if (!id)
+    return;
+
+  tdata = (SharedTaskData *) id;
+
+  g_mutex_lock (&tdata->done_lock);
+  while (!tdata->done) {
+    g_cond_wait (&tdata->done_cond, &tdata->done_lock);
+  }
+  g_mutex_unlock (&tdata->done_lock);
+
+  shared_task_data_unref (tdata);
+}
+
+static void
+shared_dispose_handle (GstTaskPool * pool, gpointer id)
+{
+  SharedTaskData *tdata;
+
+  if (!id)
+    return;
+
+  tdata = (SharedTaskData *) id;
+
+
+  shared_task_data_unref (tdata);
+}
+
+static void
+shared_prepare (GstTaskPool * pool, GError ** error)
+{
+  GstSharedTaskPool *shared_pool = GST_SHARED_TASK_POOL_CAST (pool);
+
+  GST_OBJECT_LOCK (pool);
+  pool->pool =
+      g_thread_pool_new ((GFunc) shared_func, pool,
+      shared_pool->priv->max_threads, FALSE, error);
+  GST_OBJECT_UNLOCK (pool);
+}
+
+static void
+gst_shared_task_pool_class_init (GstSharedTaskPoolClass * klass)
+{
+  GstTaskPoolClass *taskpoolclass = GST_TASK_POOL_CLASS (klass);
+
+  taskpoolclass->prepare = shared_prepare;
+  taskpoolclass->push = shared_push;
+  taskpoolclass->join = shared_join;
+  taskpoolclass->dispose_handle = shared_dispose_handle;
+}
+
+static void
+gst_shared_task_pool_init (GstSharedTaskPool * pool)
+{
+  GstSharedTaskPoolPrivate *priv;
+
+  priv = pool->priv = gst_shared_task_pool_get_instance_private (pool);
+  priv->max_threads = 1;
+}
+
+/**
+ * gst_shared_task_pool_set_max_threads:
+ * @pool: a #GstSharedTaskPool
+ * @max_threads: Maximum number of threads to spawn.
+ *
+ * Update the maximal number of threads the @pool may spawn. When
+ * the maximal number of threads is reduced, existing threads are not
+ * immediately shut down, see g_thread_pool_set_max_threads().
+ *
+ * Setting @max_threads to 0 effectively freezes the pool.
+ *
+ * Since: 1.20
+ */
+void
+gst_shared_task_pool_set_max_threads (GstSharedTaskPool * pool,
+    guint max_threads)
+{
+  GstTaskPool *taskpool;
+
+  g_return_if_fail (GST_IS_SHARED_TASK_POOL (pool));
+
+  taskpool = GST_TASK_POOL (pool);
+
+  GST_OBJECT_LOCK (pool);
+  if (taskpool->pool)
+    g_thread_pool_set_max_threads (taskpool->pool, max_threads, NULL);
+  pool->priv->max_threads = max_threads;
+  GST_OBJECT_UNLOCK (pool);
+}
+
+/**
+ * gst_shared_task_pool_get_max_threads:
+ * @pool: a #GstSharedTaskPool
+ *
+ * Returns: the maximum number of threads @pool is configured to spawn
+ * Since: 1.20
+ */
+guint
+gst_shared_task_pool_get_max_threads (GstSharedTaskPool * pool)
+{
+  guint ret;
+
+  g_return_val_if_fail (GST_IS_SHARED_TASK_POOL (pool), 0);
+
+  GST_OBJECT_LOCK (pool);
+  ret = pool->priv->max_threads;
+  GST_OBJECT_UNLOCK (pool);
+
+  return ret;
+}
+
+/**
+ * gst_shared_task_pool_new:
+ *
+ * Create a new shared task pool. The shared task pool will queue tasks on
+ * a maximum number of threads, 1 by default.
+ *
+ * Do not use a #GstSharedTaskPool to manage potentially inter-dependent tasks such
+ * as pad tasks, as having one task waiting on another to return before returning
+ * would cause obvious deadlocks if they happen to share the same thread.
+ *
+ * Returns: (transfer full): a new #GstSharedTaskPool. gst_object_unref() after usage.
+ * Since: 1.20
+ */
+GstTaskPool *
+gst_shared_task_pool_new (void)
+{
+  GstTaskPool *pool;
+
+  pool = g_object_new (GST_TYPE_SHARED_TASK_POOL, NULL);
+
+  /* clear floating flag */
+  gst_object_ref_sink (pool);
+
+  return pool;
+}
index 3b654d9..94c5ebe 100644 (file)
@@ -81,8 +81,19 @@ struct _GstTaskPoolClass {
                          gpointer user_data, GError **error);
   void      (*join)     (GstTaskPool *pool, gpointer id);
 
+  /**
+   * GstTaskPoolClass::dispose_handle:
+   * @pool: a #GstTaskPool
+   * @id: (transfer full): the handle to dispose of
+   *
+   * free / unref the handle returned in GstTaskPoolClass::push.
+   *
+   * Since: 1.20
+   */
+  void      (*dispose_handle) (GstTaskPool *pool, gpointer id);
+
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
+  gpointer _gst_reserved[GST_PADDING - 1];
 };
 
 GST_API
@@ -101,11 +112,65 @@ GST_API
 void            gst_task_pool_join        (GstTaskPool *pool, gpointer id);
 
 GST_API
+void            gst_task_pool_dispose_handle (GstTaskPool *pool, gpointer id);
+
+GST_API
 void           gst_task_pool_cleanup     (GstTaskPool *pool);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTaskPool, gst_object_unref)
-#endif
+
+typedef struct _GstSharedTaskPool GstSharedTaskPool;
+typedef struct _GstSharedTaskPoolClass GstSharedTaskPoolClass;
+typedef struct _GstSharedTaskPoolPrivate GstSharedTaskPoolPrivate;
+
+#define GST_TYPE_SHARED_TASK_POOL             (gst_shared_task_pool_get_type ())
+#define GST_SHARED_TASK_POOL(pool)            (G_TYPE_CHECK_INSTANCE_CAST ((pool), GST_TYPE_TASK_POOL, GstSharedTaskPool))
+#define GST_IS_SHARED_TASK_POOL(pool)         (G_TYPE_CHECK_INSTANCE_TYPE ((pool), GST_TYPE_SHARED_TASK_POOL))
+#define GST_SHARED_TASK_POOL_CLASS(pclass)    (G_TYPE_CHECK_CLASS_CAST ((pclass), GST_TYPE_SHARED_TASK_POOL, GstSharedTaskPoolClass))
+#define GST_IS_SHARED_TASK_POOL_CLASS(pclass) (G_TYPE_CHECK_CLASS_TYPE ((pclass), GST_TYPE_SHARED_TASK_POOL))
+#define GST_SHARED_TASK_POOL_GET_CLASS(pool)  (G_TYPE_INSTANCE_GET_CLASS ((pool), GST_TYPE_SHARED_TASK_POOL, GstSharedTaskPoolClass))
+
+/**
+ * GstSharedTaskPool:
+ *
+ * The #GstSharedTaskPool object.
+ *
+ * since: 1.20
+ */
+struct _GstSharedTaskPool {
+  GstTaskPool parent;
+
+  /*< private >*/
+  GstSharedTaskPoolPrivate *priv;
+
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+/**
+ * GstSharedTaskPoolClass:
+ *
+ * The #GstSharedTaskPoolClass object.
+ *
+ * Since: 1.20
+ */
+struct _GstSharedTaskPoolClass {
+  GstTaskPoolClass parent_class;
+
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+GST_API
+GType           gst_shared_task_pool_get_type        (void);
+
+GST_API
+void            gst_shared_task_pool_set_max_threads (GstSharedTaskPool *pool, guint max_threads);
+
+GST_API
+guint           gst_shared_task_pool_get_max_threads (GstSharedTaskPool *pool);
+
+GST_API
+GstTaskPool *   gst_shared_task_pool_new             (void);
 
 G_END_DECLS
 
index 807c521..a82c9f1 100644 (file)
@@ -228,7 +228,6 @@ GstTocEntry *      gst_toc_entry_get_parent              (GstTocEntry *entry);
 GST_API
 const gchar *      gst_toc_entry_type_get_nick     (GstTocEntryType type);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 static inline void
 _gst_autoptr_toc_unref (GstToc *toc)
 {
@@ -243,7 +242,6 @@ _gst_autoptr_toc_entry_unref (GstTocEntry *entry)
 
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstToc, _gst_autoptr_toc_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTocEntry, _gst_autoptr_toc_entry_unref)
-#endif
 
 G_END_DECLS
 
index eaeddbd..1849142 100644 (file)
@@ -32,8 +32,6 @@
  * Since: 1.8
  */
 
-#define GST_USE_UNSTABLE_API
-
 #include "gst_private.h"
 #include "gstenumtypes.h"
 #include "gsttracer.h"
index 1d2726d..6560296 100644 (file)
@@ -41,6 +41,11 @@ typedef struct _GstTracerClass GstTracerClass;
 #define GST_TRACER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_TRACER,GstTracerClass))
 #define GST_TRACER_CAST(obj)       ((GstTracer *)(obj))
 
+/**
+ * GstTracer:
+ *
+ * The opaque GstTracer instance structure
+ */
 struct _GstTracer {
   GstObject        parent;
   /*< private >*/
@@ -58,8 +63,6 @@ struct _GstTracerClass {
 GST_API
 GType gst_tracer_get_type          (void);
 
-#ifdef GST_USE_UNSTABLE_API
-
 GST_API
 void gst_tracing_register_hook (GstTracer *tracer, const gchar *detail,
   GCallback func);
@@ -69,11 +72,10 @@ void gst_tracing_register_hook (GstTracer *tracer, const gchar *detail,
 GST_API
 gboolean gst_tracer_register (GstPlugin * plugin, const gchar * name, GType type);
 
-#endif
+GST_API
+GList* gst_tracing_get_active_tracers (void);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTracer, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 32c4c74..3942ace 100644 (file)
@@ -88,6 +88,8 @@ gst_tracer_factory_get_list (void)
  *
  * Returns: the #GType for tracers managed by this factory or 0 if
  * the factory is not loaded.
+ *
+ * Since: 1.14
  */
 GType
 gst_tracer_factory_get_tracer_type (GstTracerFactory * factory)
index 44b10ec..ff88a4a 100644 (file)
@@ -57,9 +57,7 @@ GList *         gst_tracer_factory_get_list          (void);
 GST_API
 GType           gst_tracer_factory_get_tracer_type   (GstTracerFactory * factory);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTracerFactory, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 639a4cc..1caa687 100644 (file)
@@ -30,8 +30,6 @@
  * Since: 1.8
  */
 
-#define GST_USE_UNSTABLE_API
-
 #include "gst_private.h"
 #include "gstenumtypes.h"
 #include "gstinfo.h"
@@ -70,7 +68,7 @@ build_field_template (GQuark field_id, const GValue * value, gpointer user_data)
   gboolean res;
 
   if (G_VALUE_TYPE (value) != GST_TYPE_STRUCTURE) {
-    GST_WARNING ("expected field of type GstStructure, but %s is %s",
+    GST_ERROR ("expected field of type GstStructure, but %s is %s",
         g_quark_to_string (field_id), G_VALUE_TYPE_NAME (value));
     return FALSE;
   }
@@ -161,6 +159,7 @@ gst_tracer_record_init (GstTracerRecord * self)
  *
  * Create a new tracer record. The record instance can be used to efficiently
  * log entries using gst_tracer_record_log().
+ * %NULL terminator required after the last argument.
  *
  * The @name without the ".class" suffix will be used for the log records.
  * There must be fields for each value that gets logged where the field name is
@@ -179,6 +178,8 @@ gst_tracer_record_init (GstTracerRecord * self)
  * > Please note that this is still under discussion and subject to change.
  *
  * Returns: (transfer full): a new #GstTracerRecord
+ *
+ * Since: 1.8
  */
 GstTracerRecord *
 gst_tracer_record_new (const gchar * name, const gchar * firstfield, ...)
@@ -201,8 +202,11 @@ gst_tracer_record_new (const gchar * name, const gchar * firstfield, ...)
 
     /* all fields passed here must be GstStructures which we take over */
     if (type != GST_TYPE_STRUCTURE) {
-      GST_WARNING ("expected field of type GstStructure, but %s is %s",
+      GST_ERROR ("expected field of type GstStructure, but %s is %s",
           firstfield, g_type_name (type));
+      va_end (varargs);
+      gst_structure_free (structure);
+      return NULL;
     }
 
     G_VALUE_COLLECT_INIT (&val, type, varargs, G_VALUE_NOCOPY_CONTENTS, &err);
@@ -211,7 +215,9 @@ gst_tracer_record_new (const gchar * name, const gchar * firstfield, ...)
       g_free (err);
       break;
     }
-    /* see boxed_proxy_collect_value */
+    /* give ownership of the GstStructure "value" collected from varargs
+     * to this structure by unsetting the NOCOPY_CONTENTS collect-flag.
+     * see boxed_proxy_collect_value in glib's gobject/gboxed.c */
     val.data[1].v_uint &= ~G_VALUE_NOCOPY_CONTENTS;
     gst_structure_id_take_value (structure, id, &val);
 
@@ -242,6 +248,8 @@ gst_tracer_record_new (const gchar * name, const gchar * firstfield, ...)
  * the category "GST_TRACER".
  *
  * > Please note that this is still under discussion and subject to change.
+ *
+ * Since: 1.8
  */
 void
 gst_tracer_record_log (GstTracerRecord * self, ...)
index 2392d1c..3d8c4da 100644 (file)
 
 G_BEGIN_DECLS
 
+/**
+ * GstTracerRecord:
+ *
+ * The opaque GstTracerRecord instance structure
+ *
+ * Since: 1.8
+ */
 typedef struct _GstTracerRecord GstTracerRecord;
 typedef struct _GstTracerRecordClass GstTracerRecordClass;
 
@@ -40,9 +47,7 @@ typedef struct _GstTracerRecordClass GstTracerRecordClass;
 GST_API
 GType gst_tracer_record_get_type          (void);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTracerRecord, gst_object_unref)
-#endif
 
 /**
  * GstTracerValueScope:
@@ -86,10 +91,8 @@ typedef enum
   GST_TRACER_VALUE_FLAGS_AGGREGATED = (1 << 1),
 } GstTracerValueFlags;
 
-#ifdef GST_USE_UNSTABLE_API
-
 GST_API
-GstTracerRecord * gst_tracer_record_new (const gchar * name, const gchar * firstfield, ...);
+GstTracerRecord * gst_tracer_record_new (const gchar * name, const gchar * firstfield, ...) G_GNUC_NULL_TERMINATED;
 
 #ifndef GST_DISABLE_GST_DEBUG
 GST_API
@@ -98,8 +101,6 @@ void              gst_tracer_record_log (GstTracerRecord *self, ...);
 #define gst_tracer_record_log(...) G_STMT_START {} G_STMT_END
 #endif
 
-#endif
-
 G_END_DECLS
 
 #endif /* __GST_TRACER_RECORD_H__ */
index 2522cbf..cc92e64 100644 (file)
@@ -31,8 +31,6 @@
  * and needs to be done before any pipeline state is set to PAUSED.
  */
 
-#define GST_USE_UNSTABLE_API
-
 #include "gst_private.h"
 #include "gsttracer.h"
 #include "gsttracerfactory.h"
@@ -56,7 +54,7 @@ static const gchar *_quark_strings[] = {
   "element-change-state-pre", "element-change-state-post",
   "mini-object-created", "mini-object-destroyed", "object-created",
   "object-destroyed", "mini-object-reffed", "mini-object-unreffed",
-  "object-reffed", "object-unreffed",
+  "object-reffed", "object-unreffed", "plugin-feature-loaded"
 };
 
 GQuark _priv_gst_tracer_quark_table[GST_TRACER_QUARK_MAX];
@@ -188,6 +186,8 @@ gst_tracing_register_hook_id (GstTracer * tracer, GQuark detail, GCallback func)
  *
  * Register @func to be called when the trace hook @detail is getting invoked.
  * Use %NULL for @detail to register to all hooks.
+ *
+ * Since: 1.8
  */
 void
 gst_tracing_register_hook (GstTracer * tracer, const gchar * detail,
@@ -196,6 +196,44 @@ gst_tracing_register_hook (GstTracer * tracer, const gchar * detail,
   gst_tracing_register_hook_id (tracer, g_quark_try_string (detail), func);
 }
 
+/**
+ * gst_tracing_get_active_tracers:
+ *
+ * Get a list of all active tracer objects owned by the tracing framework for
+ * the entirety of the run-time of the process or till gst_deinit() is called.
+ *
+ * Returns: (transfer full) (element-type Gst.Tracer): A #GList of
+ * #GstTracer objects
+ *
+ * Since: 1.18
+ */
+GList *
+gst_tracing_get_active_tracers (void)
+{
+  GList *tracers, *h_list, *h_node, *t_node;
+  GstTracerHook *hook;
+
+  if (!_priv_tracer_enabled || !_priv_tracers)
+    return NULL;
+
+  tracers = NULL;
+  h_list = g_hash_table_get_values (_priv_tracers);
+  for (h_node = h_list; h_node; h_node = g_list_next (h_node)) {
+    for (t_node = h_node->data; t_node; t_node = g_list_next (t_node)) {
+      hook = (GstTracerHook *) t_node->data;
+      /* Skip duplicate tracers from different hooks. This function is O(n), but
+       * that should be fine since the number of tracers enabled on a process
+       * should be small. */
+      if (g_list_index (tracers, hook->tracer) >= 0)
+        continue;
+      tracers = g_list_prepend (tracers, gst_object_ref (hook->tracer));
+    }
+  }
+  g_list_free (h_list);
+
+  return tracers;
+}
+
 #else /* !GST_DISABLE_GST_TRACER_HOOKS */
 
 void
@@ -204,4 +242,9 @@ gst_tracing_register_hook (GstTracer * tracer, const gchar * detail,
 {
 }
 
+GList *
+gst_tracing_get_active_tracers (void)
+{
+  return NULL;
+}
 #endif /* GST_DISABLE_GST_TRACER_HOOKS */
index a2a5ed6..48b0864 100644 (file)
@@ -79,6 +79,7 @@ typedef enum /*< skip >*/
   GST_TRACER_QUARK_HOOK_MINI_OBJECT_UNREFFED,
   GST_TRACER_QUARK_HOOK_OBJECT_REFFED,
   GST_TRACER_QUARK_HOOK_OBJECT_UNREFFED,
+  GST_TRACER_QUARK_HOOK_PLUGIN_FEATURE_LOADED,
   GST_TRACER_QUARK_MAX
 } GstTracerQuarkId;
 
@@ -689,11 +690,38 @@ typedef void (*GstTracerHookObjectCreated) (GObject *self, GstClockTime ts,
  */
 typedef void (*GstTracerHookObjectDestroyed) (GObject *self, GstClockTime ts,
     GstObject *object);
+
 #define GST_TRACER_OBJECT_DESTROYED(object) G_STMT_START{ \
   GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_OBJECT_DESTROYED), \
     GstTracerHookObjectDestroyed, (GST_TRACER_ARGS, object)); \
 }G_STMT_END
 
+/**
+ * GstTracerHookPluginFeatureLoaded:
+ * @self: the tracer instance
+ * @ts: the current timestamp
+ * @feature: the plugin feature that was loaded
+ *
+ * Hook called when a GstPluginFeature is loaded named
+ * "plugin-feature-loaded".
+ *
+ * Since: 1.20
+ */
+typedef void (*GstTracerHookPluginFeatureLoaded) (GObject *self, GstClockTime ts,
+    GstPluginFeature *feature);
+/**
+ * GST_TRACER_PLUGIN_FEATURE_LOADED:
+ * @feature: The feature that this tracer is called for
+ *
+ * Add a tracepoint when a plugin feature is loaded.
+ *
+ * Since: 1.20
+ */
+#define GST_TRACER_PLUGIN_FEATURE_LOADED(feature) G_STMT_START{ \
+  GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PLUGIN_FEATURE_LOADED), \
+    GstTracerHookPluginFeatureLoaded, (GST_TRACER_ARGS, feature)); \
+}G_STMT_END
+
 
 #else /* !GST_DISABLE_GST_TRACER_HOOKS */
 
@@ -743,6 +771,7 @@ _priv_gst_tracing_deinit (void)
 #define GST_TRACER_OBJECT_DESTROYED(object)
 #define GST_TRACER_OBJECT_REFFED(object, new_refcount)
 #define GST_TRACER_OBJECT_UNREFFED(object, new_refcount)
+#define GST_TRACER_PLUGIN_FEATURE_LOADED(feature)
 
 #endif /* GST_DISABLE_GST_TRACER_HOOKS */
 
index 5c2b0d1..bd48bf2 100644 (file)
@@ -41,13 +41,13 @@ G_DEFINE_POINTER_TYPE (GstTypeFind, gst_type_find);
 
 /**
  * gst_type_find_register:
- * @plugin: (allow-none): A #GstPlugin, or %NULL for a static typefind function
+ * @plugin: (nullable): A #GstPlugin, or %NULL for a static typefind function
  * @name: The name for registering
  * @rank: The rank (or importance) of this typefind function
  * @func: The #GstTypeFindFunction to use
- * @extensions: (allow-none): Optional comma-separated list of extensions
+ * @extensions: (nullable): Optional comma-separated list of extensions
  *     that could belong to this type
- * @possible_caps: Optionally the caps that could be returned when typefinding
+ * @possible_caps: (nullable): Optionally the caps that could be returned when typefinding
  *                 succeeds
  * @data: Optional user data. This user data must be available until the plugin
  *        is unloaded.
@@ -149,6 +149,38 @@ gst_type_find_suggest (GstTypeFind * find, guint probability, GstCaps * caps)
 }
 
 /**
+ * gst_type_find_suggest_empty_simple:
+ * @find: The #GstTypeFind object the function was called with
+ * @probability: The probability in percent that the suggestion is right
+ * @media_type: the media type of the suggested caps
+ *
+ * If a #GstTypeFindFunction calls this function it suggests caps of the
+ * given @media_type with the given @probability.
+ *
+ * This function is similar to gst_type_find_suggest_simple(), but uses
+ * a #GstCaps with no fields.
+ *
+ * Since: 1.20
+ */
+void
+gst_type_find_suggest_empty_simple (GstTypeFind * find,
+    guint probability, const char *media_type)
+{
+  GstCaps *caps;
+
+  g_return_if_fail (find->suggest != NULL);
+  g_return_if_fail (probability <= 100);
+  g_return_if_fail (media_type != NULL);
+
+  caps = gst_caps_new_empty_simple (media_type);
+
+  g_return_if_fail (gst_caps_is_fixed (caps));
+
+  find->suggest (find->data, probability, caps);
+  gst_caps_unref (caps);
+}
+
+/**
  * gst_type_find_suggest_simple:
  * @find: The #GstTypeFind object the function was called with
  * @probability: The probability in percent that the suggestion is right
@@ -156,7 +188,8 @@ gst_type_find_suggest (GstTypeFind * find, guint probability, GstCaps * caps)
  * @fieldname: (allow-none): first field of the suggested caps, or %NULL
  * @...: additional arguments to the suggested caps in the same format as the
  *     arguments passed to gst_structure_new() (ie. triplets of field name,
- *     field GType and field value)
+ *     field GType and field value).  If @fieldname is %NULL, this list
+ *     must be exactly one %NULL.
  *
  * If a #GstTypeFindFunction calls this function it suggests the caps with the
  * given probability. A #GstTypeFindFunction may supply different suggestions
index 90c9e94..6c2e595 100644 (file)
 #include <gst/gstpluginfeature.h>
 
 G_BEGIN_DECLS
+/**
+ * GST_TYPE_FIND_REGISTER_DEFINE_CUSTOM:
+ * @type_find: The type find name in lower case, with words separated by '_'.
+ * Used to generate `gst_type_find_register_*(GstPlugin* plugin)`.
+ * @register_func: pointer to a method with the format: `gboolean register_func (GstPlugin* plugin);`
+ *
+ * A convenience macro to define the entry point of a
+ * type find `gst_type_find_register_*(GstPlugin* plugin)` which uses
+ * register_func as the main registration method for the type find.
+ * As an example, you may define the type find named "custom-typefind"
+ * as following using `type_find_register_custom`:
+ *
+ * ```
+ * GST_TYPE_FIND_REGISTER_DEFINE_CUSTOM (plugin, type_find_register_custom)
+ * ```
+ *
+ * Since: 1.20
+ */
+#define GST_TYPE_FIND_REGISTER_DEFINE_CUSTOM(type_find, register_func) \
+G_BEGIN_DECLS \
+gboolean G_PASTE (gst_type_find_register_, type_find) (GstPlugin * plugin) \
+{ \
+  return register_func (plugin); \
+} \
+G_END_DECLS
+
+/**
+ * GST_TYPE_FIND_REGISTER_DEFINE:
+ * @t_f: The type find name in lower case, with words separated by '_'.
+ * Used to generate `gst_type_find_register_*(GstPlugin* plugin)`.
+ * @t_f_n: The public name of the type find
+ * @r: The #GstRank of the type find (higher rank means more importance when autoplugging, see #GstRank)
+ * @func: The #GstTypeFindFunction to use
+ * @extensions: (nullable): Optional comma-separated list of extensions
+ *     that could belong to this type
+ * @possible_caps: (nullable): Optionally the caps that could be returned when typefinding
+ *                 succeeds
+ * @data: Optional user data. This user data must be available until the plugin
+ *        is unloaded.
+ * @data_notify: a #GDestroyNotify that will be called on @data when the plugin
+ *        is unloaded.
+ *
+ * A convenience macro to define the entry point of a
+ * type find `gst_type_find_register_*(GstPlugin* plugin)`.
+ *
+ * Since: 1.20
+ */
+#define GST_TYPE_FIND_REGISTER_DEFINE(t_f, t_f_n, r, func, extensions, possible_caps, data, data_notify) \
+G_BEGIN_DECLS \
+gboolean G_PASTE (gst_type_find_register_, t_f) (GstPlugin * plugin) \
+{ \
+  return gst_type_find_register (plugin, t_f_n, r, func, extensions, possible_caps, data, data_notify); \
+} \
+G_END_DECLS
+
+/**
+ * GST_TYPE_FIND_REGISTER_DECLARE:
+ * @t_f: The type find name in lower case, with words separated by '_'.
+ *
+ * This macro can be used to declare a new type find.
+ * It has to be used in combination with #GST_TYPE_FIND_REGISTER_DEFINE macro
+ * and must be placed outside any block to declare the type find registration
+ * function.
+ *
+ * Since: 1.20
+ */
+#define GST_TYPE_FIND_REGISTER_DECLARE(t_f) \
+G_BEGIN_DECLS \
+gboolean G_PASTE(gst_type_find_register_, t_f) (GstPlugin * plugin); \
+G_END_DECLS
+
+/**
+ * GST_TYPE_FIND_REGISTER:
+ * @t_f: The type find name in lower case, with words separated by '_'.
+ * @plugin: The #GstPlugin where to register the type find.
+
+ *
+ * This macro can be used to register a type find into a #GstPlugin.
+ * This method will be usually called in the plugin init function
+ * but can also be called with a NULL plugin.
+ *
+ * Since: 1.20
+ */
+#define GST_TYPE_FIND_REGISTER(t_f, plugin) G_PASTE(gst_type_find_register_, t_f) (plugin)
+
 
 #define GST_TYPE_TYPE_FIND  (gst_type_find_get_type())
 
@@ -91,6 +176,9 @@ struct _GstTypeFind {
   gpointer _gst_reserved[GST_PADDING];
 };
 
+/**
+ * gst_type_find_get_type: (attributes doc.skip=true)
+ */
 GST_API
 GType     gst_type_find_get_type   (void);
 
@@ -105,10 +193,14 @@ void            gst_type_find_suggest    (GstTypeFind   * find,
                                           guint           probability,
                                           GstCaps       * caps);
 GST_API
+void            gst_type_find_suggest_empty_simple (GstTypeFind * find,
+                                                    guint         probability,
+                                                    const char  * media_type);
+GST_API
 void            gst_type_find_suggest_simple (GstTypeFind * find,
                                               guint         probability,
                                               const char  * media_type,
-                                              const char  * fieldname, ...);
+                                              const char  * fieldname, ...) G_GNUC_NULL_TERMINATED;
 GST_API
 guint64   gst_type_find_get_length (GstTypeFind   * find);
 
index fb5c098..433b9ad 100644 (file)
@@ -159,7 +159,7 @@ gst_type_find_factory_get_list (void)
  *
  * Gets the #GstCaps associated with a typefind factory.
  *
- * Returns: (transfer none): the #GstCaps associated with this factory
+ * Returns: (transfer none) (nullable): the #GstCaps associated with this factory
  */
 GstCaps *
 gst_type_find_factory_get_caps (GstTypeFindFactory * factory)
index d0a7e1d..08227b1 100644 (file)
@@ -65,9 +65,7 @@ GST_API
 void            gst_type_find_factory_call_function     (GstTypeFindFactory *factory,
                                                          GstTypeFind *find);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTypeFindFactory, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 61c8ec9..de61365 100644 (file)
@@ -42,6 +42,7 @@
 #  include "config.h"
 #endif
 
+#define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 #include "gst_private.h"
 #include "gst.h"
 #include "gsturi.h"
@@ -122,7 +123,7 @@ _gst_ascii_strcasestr (const gchar * s, const gchar * find)
 GType
 gst_uri_handler_get_type (void)
 {
-  static volatile gsize urihandler_type = 0;
+  static gsize urihandler_type = 0;
 
   if (g_once_init_enter (&urihandler_type)) {
     GType _type;
@@ -404,8 +405,8 @@ gst_uri_get_protocol (const gchar * uri)
 {
   gchar *colon;
 
-  g_return_val_if_fail (uri != NULL, NULL);
-  g_return_val_if_fail (gst_uri_is_valid (uri), NULL);
+  if (!gst_uri_is_valid (uri))
+    return NULL;
 
   colon = strstr (uri, ":");
 
@@ -426,9 +427,11 @@ gst_uri_has_protocol (const gchar * uri, const gchar * protocol)
 {
   gchar *colon;
 
-  g_return_val_if_fail (uri != NULL, FALSE);
   g_return_val_if_fail (protocol != NULL, FALSE);
-  g_return_val_if_fail (gst_uri_is_valid (uri), FALSE);
+
+  if (!gst_uri_is_valid (uri)) {
+    return FALSE;
+  }
 
   colon = strstr (uri, ":");
 
@@ -459,8 +462,9 @@ gst_uri_get_location (const gchar * uri)
   const gchar *colon;
   gchar *unescaped = NULL;
 
-  g_return_val_if_fail (uri != NULL, NULL);
-  g_return_val_if_fail (gst_uri_is_valid (uri), NULL);
+  if (!gst_uri_is_valid (uri)) {
+    return NULL;
+  }
 
   colon = strstr (uri, "://");
   if (!colon)
@@ -618,7 +622,7 @@ gst_uri_protocol_is_supported (const GstURIType type, const gchar * protocol)
  *
  * Creates an element for handling the given URI.
  *
- * Returns: (transfer floating) (nullable): a new element or %NULL if none
+ * Returns: (transfer floating): a new element or %NULL if none
  * could be created
  */
 GstElement *
@@ -631,9 +635,14 @@ gst_element_make_from_uri (const GstURIType type, const gchar * uri,
 
   g_return_val_if_fail (gst_is_initialized (), NULL);
   g_return_val_if_fail (GST_URI_TYPE_IS_VALID (type), NULL);
-  g_return_val_if_fail (gst_uri_is_valid (uri), NULL);
   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
+  if (!gst_uri_is_valid (uri)) {
+    g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
+        _("Invalid URI: %s"), uri);
+    return NULL;
+  }
+
   GST_DEBUG ("type:%d, uri:%s, elementname:%s", type, uri, elementname);
 
   protocol = gst_uri_get_protocol (uri);
@@ -795,13 +804,18 @@ gst_uri_handler_set_uri (GstURIHandler * handler, const gchar * uri,
   gchar *protocol;
 
   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);
   g_return_val_if_fail (iface->set_uri != NULL, FALSE);
 
+  if (!gst_uri_is_valid (uri)) {
+    g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
+        _("Invalid URI: %s"), uri);
+    return FALSE;
+  }
+
   protocol = gst_uri_get_protocol (uri);
 
   if (iface->get_protocols) {
@@ -900,7 +914,7 @@ file_path_contains_relatives (const gchar * path)
  * the current working directory if it is a relative path, and then the path
  * will be canonicalised so that it doesn't contain any './' or '../' segments.
  *
- * On Windows #filename should be in UTF-8 encoding.
+ * On Windows @filename should be in UTF-8 encoding.
  *
  * Returns: newly-allocated URI string, or NULL on error. The caller must
  *   free the URI string with g_free() when no longer needed.
@@ -1265,7 +1279,7 @@ _gst_uri_escape_http_query_element (const gchar * element)
 {
   gchar *ret, *c;
 
-  ret = g_uri_escape_string (element, "!$'()*,;:@/? ", FALSE);
+  ret = g_uri_escape_string (element, "!$'()*,;:@/?= ", FALSE);
   for (c = ret; *c; c++)
     if (*c == ' ')
       *c = '+';
@@ -2874,3 +2888,75 @@ gst_uri_get_media_fragment_table (const GstUri * uri)
     return NULL;
   return _gst_uri_string_to_table (uri->fragment, "&", "=", TRUE, TRUE);
 }
+
+/**
+ * gst_uri_copy:
+ * @uri: This #GstUri object.
+ *
+ * Create a new #GstUri object with the same data as this #GstUri object.
+ * If @uri is %NULL then returns %NULL.
+ *
+ * Returns: (transfer full): A new #GstUri object which is a copy of this
+ *          #GstUri or %NULL.
+ *
+ * Since: 1.6
+ */
+GstUri *
+gst_uri_copy (const GstUri * uri)
+{
+  return GST_URI_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (uri)));
+}
+
+/**
+ * gst_uri_ref:
+ * @uri: (transfer none): This #GstUri object.
+ *
+ * Add a reference to this #GstUri object. See gst_mini_object_ref() for further
+ * info.
+ *
+ * Returns: This object with the reference count incremented.
+ *
+ * Since: 1.6
+ */
+GstUri *
+gst_uri_ref (GstUri * uri)
+{
+  return GST_URI_CAST (gst_mini_object_ref (GST_MINI_OBJECT_CAST (uri)));
+}
+
+/**
+ * gst_uri_unref:
+ * @uri: (transfer full): This #GstUri object.
+ *
+ * Decrement the reference count to this #GstUri object.
+ *
+ * If the reference count drops to 0 then finalize this object.
+ *
+ * See gst_mini_object_unref() for further info.
+ *
+ * Since: 1.6
+ */
+void
+gst_uri_unref (GstUri * uri)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (uri));
+}
+
+/**
+ * gst_clear_uri: (skip)
+ * @uri_ptr: a pointer to a #GstUri reference
+ *
+ * Clears a reference to a #GstUri.
+ *
+ * @uri_ptr must not be %NULL.
+ *
+ * If the reference is %NULL then this function does nothing. Otherwise, the
+ * reference count of the uri is decreased and the pointer is set to %NULL.
+ *
+ * Since: 1.18
+ */
+void
+gst_clear_uri (GstUri ** uri_ptr)
+{
+  gst_clear_mini_object ((GstMiniObject **) uri_ptr);
+}
index 8199c38..8c5881b 100644 (file)
@@ -33,6 +33,9 @@ G_BEGIN_DECLS
 
 #include <gst/gstconfig.h>
 
+/**
+ * gst_uri_error_quark: (attributes doc.skip=true)
+ */
 GST_API
 GQuark gst_uri_error_quark (void);
 
@@ -348,56 +351,45 @@ gboolean gst_uri_set_fragment          (GstUri * uri, const gchar * fragment);
 GST_API
 GHashTable * gst_uri_get_media_fragment_table  (const GstUri * uri);
 
-/**
- * gst_uri_copy:
- * @uri: This #GstUri object.
- *
- * Create a new #GstUri object with the same data as this #GstUri object.
- * If @uri is %NULL then returns %NULL.
- *
- * Returns: (transfer full): A new #GstUri object which is a copy of this
- *          #GstUri or %NULL.
- */
+#ifndef GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 static inline GstUri *
 gst_uri_copy (const GstUri * uri)
 {
   return GST_URI_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (uri)));
 }
 
-/**
- * gst_uri_ref:
- * @uri: (transfer none): This #GstUri object.
- *
- * Add a reference to this #GstUri object. See gst_mini_object_ref() for further
- * info.
- *
- * Returns: This object with the reference count incremented.
- */
 static inline GstUri *
 gst_uri_ref (GstUri * uri)
 {
   return GST_URI_CAST (gst_mini_object_ref (GST_MINI_OBJECT_CAST (uri)));
 }
 
-/**
- * gst_uri_unref:
- * @uri: (transfer full): This #GstUri object.
- *
- * Decrement the reference count to this #GstUri object.
- *
- * If the reference count drops to 0 then finalize this object.
- *
- * See gst_mini_object_unref() for further info.
- */
 static inline void
 gst_uri_unref (GstUri * uri)
 {
   gst_mini_object_unref (GST_MINI_OBJECT_CAST (uri));
 }
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
+static inline void
+gst_clear_uri (GstUri ** uri_ptr)
+{
+  gst_clear_mini_object ((GstMiniObject **) uri_ptr);
+}
+#else /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+GST_API
+GstUri * gst_uri_copy  (const GstUri * uri);
+
+GST_API
+GstUri * gst_uri_ref   (GstUri * uri);
+
+GST_API
+void     gst_uri_unref (GstUri * uri);
+
+GST_API
+void     gst_clear_uri (GstUri ** uri_ptr);
+#endif /* GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS */
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstUri, gst_uri_unref)
-#endif
 
 G_END_DECLS
 
index 34bffaa..0b273d7 100644 (file)
@@ -44,6 +44,7 @@
 #include "gstinfo.h"
 #include "gstparse.h"
 #include "gstvalue.h"
+#include "gstquark.h"
 #include "gst-i18n-lib.h"
 #include "glib-compat-private.h"
 #include <math.h>
 #include "gstchildproxy.h"
 #endif
 
-/**
- * gst_util_dump_mem:
- * @mem: (array length=size): a pointer to the memory to dump
- * @size: the size of the memory block to dump
- *
- * Dumps the memory block into a hex representation. Useful for debugging.
- */
-void
-gst_util_dump_mem (const guchar * mem, guint size)
+
+static void
+gst_util_dump_mem_offset (const guchar * mem, guint size, guint offset)
 {
   guint i, j;
   GString *string = g_string_sized_new (50);
@@ -78,7 +73,7 @@ gst_util_dump_mem (const guchar * mem, guint size)
     i++;
 
     if (j == 16 || i == size) {
-      g_print ("%08x (%p): %-48.48s %-16.16s\n", i - j, mem + i - j,
+      g_print ("%08x (%p): %-48.48s %-16.16s\n", i - j + offset, mem + i - j,
           string->str, chars->str);
       g_string_set_size (string, 0);
       g_string_set_size (chars, 0);
@@ -90,6 +85,19 @@ gst_util_dump_mem (const guchar * mem, guint size)
 }
 
 /**
+ * gst_util_dump_mem:
+ * @mem: (array length=size): a pointer to the memory to dump
+ * @size: the size of the memory block to dump
+ *
+ * Dumps the memory block into a hex representation. Useful for debugging.
+ */
+void
+gst_util_dump_mem (const guchar * mem, guint size)
+{
+  gst_util_dump_mem_offset (mem, size, 0);
+}
+
+/**
  * gst_util_dump_buffer:
  * @buf: a #GstBuffer whose memory to dump
  *
@@ -101,10 +109,35 @@ void
 gst_util_dump_buffer (GstBuffer * buf)
 {
   GstMapInfo map;
+  GstMemory *mem;
+  guint n_memory;
+  guint i;
+  guint offset;
+
+  n_memory = gst_buffer_n_memory (buf);
 
-  if (gst_buffer_map (buf, &map, GST_MAP_READ)) {
-    gst_util_dump_mem (map.data, map.size);
-    gst_buffer_unmap (buf, &map);
+  if (n_memory == 1) {
+    if (gst_buffer_map (buf, &map, GST_MAP_READ)) {
+      gst_util_dump_mem (map.data, map.size);
+      gst_buffer_unmap (buf, &map);
+    }
+  } else if (n_memory > 1) {
+    /* gst_buffer_map() will merge multiple memory segments into one contiguous
+     * area so we need to use gst_memory_map() in order not to affect the
+     * contents of buf */
+    offset = 0;
+    for (i = 0; i < n_memory; ++i) {
+      g_print ("[Memory #%u]\n", i);
+      mem = gst_buffer_get_memory (buf, i);
+      if (gst_memory_map (mem, &map, GST_MAP_READ)) {
+        gst_util_dump_mem_offset (map.data, map.size, offset);
+        offset += map.size;
+        gst_memory_unmap (mem, &map);
+      }
+      gst_memory_unref (mem);
+    }
+  } else {
+    g_print ("[Empty]\n");
   }
 }
 
@@ -183,7 +216,7 @@ gst_util_set_object_arg (GObject * object, const gchar * name,
     goto done;
   }
 
-  if (!gst_value_deserialize (&v, value))
+  if (!gst_value_deserialize_with_pspec (&v, value, pspec))
     return;
 
 done:
@@ -268,6 +301,12 @@ gst_util_get_object_array (GObject * object, const gchar * name,
  * double conversion is not defined/implemented.
  */
 
+/**
+ * gst_util_guint64_to_gdouble:
+ * @value: The #guint64 value to convert to double
+ *
+ * Returns: @value casted to #gdouble
+ */
 gdouble
 gst_util_guint64_to_gdouble (guint64 value)
 {
@@ -277,6 +316,12 @@ gst_util_guint64_to_gdouble (guint64 value)
     return (gdouble) ((gint64) value);
 }
 
+/**
+ * gst_util_gdouble_to_guint64:
+ * @value: The #gdouble value to convert guint64 double
+ *
+ * Returns: @value casted to #guint64
+ */
 guint64
 gst_util_gdouble_to_guint64 (gdouble value)
 {
@@ -346,7 +391,7 @@ gst_util_uint64_mul_uint64 (GstUInt64 * c1, GstUInt64 * c0, guint64 arg1,
   b0.ll = (guint64) v.l.high * n.l.low;
 
   /* add the high word of a0 to the low words of a1 and b0 using c1 as
-   * scrach space to capture the carry.  the low word of the result becomes
+   * scratch space to capture the carry.  the low word of the result becomes
    * the final high word of c0 */
   c1->ll = (guint64) c0->l.high + a1.l.low + b0.l.low;
   c0->l.high = c1->l.low;
@@ -1783,7 +1828,7 @@ gst_element_link_pads_full (GstElement * src, const gchar * srcpadname,
   if (srcpadname) {
     /* name specified, look it up */
     if (!(srcpad = gst_element_get_static_pad (src, srcpadname))) {
-      if ((srcpad = gst_element_get_request_pad (src, srcpadname)))
+      if ((srcpad = gst_element_request_pad_simple (src, srcpadname)))
         srcrequest = TRUE;
     }
     if (!srcpad) {
@@ -1822,7 +1867,7 @@ gst_element_link_pads_full (GstElement * src, const gchar * srcpadname,
   if (destpadname) {
     /* name specified, look it up */
     if (!(destpad = gst_element_get_static_pad (dest, destpadname))) {
-      if ((destpad = gst_element_get_request_pad (dest, destpadname)))
+      if ((destpad = gst_element_request_pad_simple (dest, destpadname)))
         destrequest = TRUE;
     }
     if (!destpad) {
@@ -2282,14 +2327,14 @@ gst_element_unlink_pads (GstElement * src, const gchar * srcpadname,
 
   /* obtain the pads requested */
   if (!(srcpad = gst_element_get_static_pad (src, srcpadname)))
-    if ((srcpad = gst_element_get_request_pad (src, srcpadname)))
+    if ((srcpad = gst_element_request_pad_simple (src, srcpadname)))
       srcrequest = TRUE;
   if (srcpad == NULL) {
     GST_WARNING_OBJECT (src, "source element has no pad \"%s\"", srcpadname);
     return;
   }
   if (!(destpad = gst_element_get_static_pad (dest, destpadname)))
-    if ((destpad = gst_element_get_request_pad (dest, destpadname)))
+    if ((destpad = gst_element_request_pad_simple (dest, destpadname)))
       destrequest = TRUE;
   if (destpad == NULL) {
     GST_WARNING_OBJECT (dest, "destination element has no pad \"%s\"",
@@ -2674,7 +2719,7 @@ gst_bin_add_many (GstBin * bin, GstElement * element_1, ...)
  * @element_1: (transfer none): the first #GstElement to remove from the bin
  * @...: (transfer none): %NULL-terminated list of elements to remove from the bin
  *
- * Remove a list of elements from a bin. This function is equivalent
+ * Removes a list of elements from a bin. This function is equivalent
  * to calling gst_bin_remove() with each member of the list.
  */
 void
@@ -3253,7 +3298,7 @@ element_find_unlinked_pad (GstElement * element, GstPadDirection direction)
  * pad when it is not needed any longer.
  *
  * Returns: (transfer full) (nullable): unlinked pad of the given
- * direction, %NULL.
+ * direction.
  */
 GstPad *
 gst_bin_find_unlinked_pad (GstBin * bin, GstPadDirection direction)
@@ -3365,7 +3410,7 @@ gst_bin_sync_children_states (GstBin * bin)
  * and want them all ghosted, you will have to create the ghost pads
  * yourself).
  *
- * Returns: (transfer floating) (type Gst.Bin) (nullable): a
+ * Returns: (transfer floating) (type Gst.Bin): a
  *   newly-created bin, or %NULL if an error occurred.
  */
 GstElement *
@@ -3396,9 +3441,9 @@ gst_parse_bin_from_description (const gchar * bin_description,
  * and want them all ghosted, you will have to create the ghost pads
  * yourself).
  *
- * Returns: (transfer floating) (type Gst.Element) (nullable): a newly-created
+ * Returns: (transfer floating) (type Gst.Element): a newly-created
  *   element, which is guaranteed to be a bin unless
- *   GST_FLAG_NO_SINGLE_ELEMENT_BINS was passed, or %NULL if an error
+ *   #GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS was passed, or %NULL if an error
  *   occurred.
  */
 GstElement *
@@ -3956,7 +4001,7 @@ gst_pad_create_stream_id_internal (GstPad * pad, GstElement * parent,
     gst_object_unref (sinkpad);
   }
 
-  /* The only case where we don't have an upstream start-start event
+  /* The only case where we don't have an upstream stream-start event
    * here is for source elements */
   if (!upstream_stream_id) {
     GstQuery *query;
@@ -4578,3 +4623,55 @@ gst_set_family_id_to_child (GstElement * child, int id)
 }
 
 #endif
+
+/**
+ * gst_type_mark_as_plugin_api:
+ * @type: a GType
+ * @flags: a set of #GstPluginAPIFlags to further inform cache generation.
+ *
+ * Marks @type as plugin API. This should be called in `class_init` of
+ * elements that expose new types (i.e. enums, flags or internal GObjects) via
+ * properties, signals or pad templates.
+ *
+ * Types exposed by plugins are not automatically added to the documentation
+ * as they might originate from another library and should in that case be
+ * documented via that library instead.
+ *
+ * By marking a type as plugin API it will be included in the documentation of
+ * the plugin that defines it.
+ *
+ * Since: 1.18
+ */
+void
+gst_type_mark_as_plugin_api (GType type, GstPluginAPIFlags flags)
+{
+  g_type_set_qdata (type, GST_QUARK (PLUGIN_API), GINT_TO_POINTER (TRUE));
+  g_type_set_qdata (type, GST_QUARK (PLUGIN_API_FLAGS),
+      GINT_TO_POINTER (flags));
+}
+
+/**
+ * gst_type_is_plugin_api:
+ * @type: a GType
+ * @flags: (out) (nullable): What #GstPluginAPIFlags the plugin was marked with
+ *
+ * Checks if @type is plugin API. See gst_type_mark_as_plugin_api() for
+ * details.
+ *
+ * Returns: %TRUE if @type is plugin API or %FALSE otherwise.
+ *
+ * Since: 1.18
+ */
+gboolean
+gst_type_is_plugin_api (GType type, GstPluginAPIFlags * flags)
+{
+  gboolean ret =
+      ! !GPOINTER_TO_INT (g_type_get_qdata (type, GST_QUARK (PLUGIN_API)));
+
+  if (ret && flags) {
+    *flags =
+        GPOINTER_TO_INT (g_type_get_qdata (type, GST_QUARK (PLUGIN_API_FLAGS)));
+  }
+
+  return ret;
+}
index c145806..daf84df 100644 (file)
@@ -554,11 +554,12 @@ static inline guint16 __gst_slow_read16_le (const guint8 * data) {
                                         } while (0)
 
 /* Float endianness conversion macros */
+#ifndef __GI_SCANNER__
 
 /* FIXME: Remove this once we depend on a GLib version with this */
 #ifndef GFLOAT_FROM_LE
 /**
- * GFLOAT_SWAP_LE_BE:
+ * GFLOAT_SWAP_LE_BE: (skip)
  * @in: input value
  *
  * Swap byte order of a 32-bit floating point value (float).
@@ -580,7 +581,7 @@ GFLOAT_SWAP_LE_BE(gfloat in)
 }
 
 /**
- * GDOUBLE_SWAP_LE_BE:
+ * GDOUBLE_SWAP_LE_BE: (skip)
  * @in: input value
  *
  * Swap byte order of a 64-bit floating point value (double).
@@ -602,28 +603,28 @@ GDOUBLE_SWAP_LE_BE(gdouble in)
 }
 
 /**
- * GDOUBLE_TO_LE:
+ * GDOUBLE_TO_LE: (skip)
  * @val: value
  *
  * Convert 64-bit floating point value (double) from native byte order into
  * little endian byte order.
  */
 /**
- * GDOUBLE_TO_BE:
+ * GDOUBLE_TO_BE: (skip)
  * @val: value
  *
  * Convert 64-bit floating point value (double) from native byte order into
  * big endian byte order.
  */
 /**
- * GDOUBLE_FROM_LE:
+ * GDOUBLE_FROM_LE: (skip)
  * @val: value
  *
  * Convert 64-bit floating point value (double) from little endian byte order
  * into native byte order.
  */
 /**
- * GDOUBLE_FROM_BE:
+ * GDOUBLE_FROM_BE: (skip)
  * @val: value
  *
  * Convert 64-bit floating point value (double) from big endian byte order
@@ -631,28 +632,28 @@ GDOUBLE_SWAP_LE_BE(gdouble in)
  */
 
 /**
- * GFLOAT_TO_LE:
+ * GFLOAT_TO_LE: (skip)
  * @val: value
  *
  * Convert 32-bit floating point value (float) from native byte order into
  * little endian byte order.
  */
 /**
- * GFLOAT_TO_BE:
+ * GFLOAT_TO_BE: (skip)
  * @val: value
  *
  * Convert 32-bit floating point value (float) from native byte order into
  * big endian byte order.
  */
 /**
- * GFLOAT_FROM_LE:
+ * GFLOAT_FROM_LE: (skip)
  * @val: value
  *
  * Convert 32-bit floating point value (float) from little endian byte order
  * into native byte order.
  */
 /**
- * GFLOAT_FROM_BE:
+ * GFLOAT_FROM_BE: (skip)
  * @val: value
  *
  * Convert 32-bit floating point value (float) from big endian byte order
@@ -682,6 +683,8 @@ GDOUBLE_SWAP_LE_BE(gdouble in)
 
 #endif /* !defined(GFLOAT_FROM_LE) */
 
+#endif /* !__GI_SCANNER__ */
+
 /**
  * GST_READ_FLOAT_LE:
  * @data: memory location
@@ -1173,6 +1176,18 @@ typedef enum {
   GST_SEARCH_MODE_AFTER
 } GstSearchMode;
 
+/**
+ * GstPluginAPIFlags:
+ * @GST_PLUGIN_API_FLAG_IGNORE_ENUM_MEMBERS: Ignore enum members when generating
+ *   the plugins cache. This is useful if the members of the enum are generated
+ *   dynamically, in order not to expose incorrect documentation to the end user.
+ *
+ * Since: 1.18
+ */
+typedef enum {
+  GST_PLUGIN_API_FLAG_IGNORE_ENUM_MEMBERS = (1 << 0),
+} GstPluginAPIFlags;
+
 GST_API
 gpointer      gst_util_array_binary_search      (gpointer array, guint num_elements,
                                                  gsize element_size, GCompareDataFunc search_func,
@@ -1209,6 +1224,11 @@ gboolean      gst_calculate_linear_regression   (const GstClockTime * xy,
                                                  GstClockTime * b, GstClockTime * xbase,
                                                  gdouble * r_squared);
 
+GST_API
+void          gst_type_mark_as_plugin_api       (GType type, GstPluginAPIFlags flags);
+
+GST_API
+gboolean      gst_type_is_plugin_api            (GType type, GstPluginAPIFlags *flags);
 
 #ifdef TIZEN_PROFILE_TV
 void          gst_set_family_id_to_child        (GstElement* child, int id);
index 8835dce..2af4ead 100644 (file)
@@ -46,6 +46,7 @@
 #include <gst/gst.h>
 #include <gobject/gvaluecollector.h>
 #include "gstutils.h"
+#include "gstquark.h"
 
 /* GstValueUnionFunc:
  * @dest: a #GValue for the result
@@ -97,9 +98,9 @@ static void gst_value_register_subtract_func (GType minuend_type,
     GType subtrahend_type, GstValueSubtractFunc func);
 
 static gboolean _priv_gst_value_parse_list (gchar * s, gchar ** after,
-    GValue * value, GType type);
+    GValue * value, GType type, GParamSpec * pspec);
 static gboolean _priv_gst_value_parse_array (gchar * s, gchar ** after,
-    GValue * value, GType type);
+    GValue * value, GType type, GParamSpec * pspec);
 
 typedef struct _GstValueUnionInfo GstValueUnionInfo;
 struct _GstValueUnionInfo
@@ -141,14 +142,32 @@ struct _GstValueAbbreviation
   GType type;
 };
 
+/* Actual internal implementation of "GstValueList" and
+ * "GstValueArray" */
+typedef struct _GstValueList GstValueList;
+
+struct _GstValueList
+{
+  /* These 2 fields must remain the same so that they match the public
+   * GArray structure (which was the former implementation) just in
+   * case someone calls `gst_value_peek_pointer` to access the
+   * array/list (such as in gststructure.c) */
+  GValue *fields;
+  guint len;
+
+  guint allocated;
+  GValue arr[1];
+};
+
 #define FUNDAMENTAL_TYPE_ID_MAX \
     (G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT)
 #define FUNDAMENTAL_TYPE_ID(type) \
     ((type) >> G_TYPE_FUNDAMENTAL_SHIFT)
 
-#define VALUE_LIST_ARRAY(v) ((GArray *) (v)->data[0].v_pointer)
+#define VALUE_LIST_ARRAY(v) ((GstValueList *) (v)->data[0].v_pointer)
 #define VALUE_LIST_SIZE(v) (VALUE_LIST_ARRAY(v)->len)
-#define VALUE_LIST_GET_VALUE(v, index) ((const GValue *) &g_array_index (VALUE_LIST_ARRAY(v), GValue, (index)))
+#define VALUE_LIST_GET_VALUE(v, index) ((const GValue *) &(VALUE_LIST_ARRAY(v)->fields[index]))
+#define VALUE_LIST_IS_USING_DYNAMIC_ARRAY(array) ((array)->fields != &(array)->arr[0])
 
 static GArray *gst_value_table;
 static GHashTable *gst_value_hash;
@@ -159,10 +178,10 @@ static GArray *gst_value_subtract_funcs;
 
 /* Forward declarations */
 static gchar *gst_value_serialize_fraction (const GValue * value);
+static gint gst_value_compare_fraction (const GValue * value1,
+    const GValue * value2);
 
 static GstValueCompareFunc gst_value_get_compare_func (const GValue * value1);
-static gint gst_value_compare_with_func (const GValue * value1,
-    const GValue * value2, GstValueCompareFunc compare);
 
 static gchar *gst_string_wrap (const gchar * s);
 static gchar *gst_string_unwrap (const gchar * s);
@@ -195,6 +214,135 @@ gst_value_hash_add_type (GType type, const GstValueTable * table)
  * list *
  ********/
 
+static void
+resize_value_list (GstValueList * vlist)
+{
+  guint want_alloc;
+
+  if (G_UNLIKELY (vlist->allocated > (G_MAXUINT / 2)))
+    g_error ("Growing GstValueList would result in overflow");
+
+  want_alloc = MAX (GST_ROUND_UP_8 (vlist->len + 1), vlist->allocated * 2);
+
+  if (VALUE_LIST_IS_USING_DYNAMIC_ARRAY (vlist)) {
+    vlist->fields = g_renew (GValue, vlist->fields, want_alloc);
+  } else {
+    vlist->fields = g_new0 (GValue, want_alloc);
+    memcpy (vlist->fields, &vlist->arr[0], vlist->len * sizeof (GValue));
+    GST_CAT_LOG (GST_CAT_PERFORMANCE, "Exceeding pre-allocated array");
+  }
+  vlist->allocated = want_alloc;
+}
+
+/* Replacement for g_array_append_val */
+static void
+_gst_value_list_append_val (GstValueList * vlist, GValue * val)
+{
+  /* resize if needed */
+  if (G_UNLIKELY (vlist->len == vlist->allocated))
+    resize_value_list (vlist);
+
+  /* Finally set value */
+  vlist->fields[vlist->len++] = *val;
+}
+
+/* Replacement for g_array_prepend_val */
+static void
+_gst_value_list_prepend_val (GstValueList * vlist, GValue * val)
+{
+  /* resize if needed */
+  if (G_UNLIKELY (vlist->len == vlist->allocated))
+    resize_value_list (vlist);
+
+  /* Shift everything */
+  memmove (&vlist->fields[1], &vlist->fields[0],
+      (vlist->len) * sizeof (GValue));
+
+  vlist->fields[0] = *val;
+  vlist->len++;
+}
+
+static GstValueList *
+_gst_value_list_new (guint prealloc)
+{
+  guint n_alloc;
+  GstValueList *res;
+
+  if (prealloc == 0)
+    prealloc = 1;
+
+  n_alloc = GST_ROUND_UP_8 (prealloc);
+  res = g_malloc0 (sizeof (GstValueList) + (n_alloc - 1) * sizeof (GValue));
+
+  res->len = 0;
+  res->allocated = n_alloc;
+  res->fields = &res->arr[0];
+
+  return res;
+}
+
+static void
+_gst_value_list_init (GValue * value, guint prealloc)
+{
+  value->g_type = GST_TYPE_LIST;
+  memset (value->data, 0, sizeof (value->data));
+  value->data[0].v_pointer = _gst_value_list_new (prealloc);
+}
+
+/**
+ * gst_value_list_init:
+ * @value: A zero-filled (uninitialized) #GValue structure
+ * @prealloc: The number of entries to pre-allocate in the list
+ *
+ * Initializes and pre-allocates a #GValue of type #GST_TYPE_LIST.
+ *
+ * Returns: (transfer none): The #GValue structure that has been passed in
+ *
+ * Since: 1.18
+ */
+
+GValue *
+gst_value_list_init (GValue * value, guint prealloc)
+{
+  g_return_val_if_fail (value != NULL, NULL);
+  g_return_val_if_fail (G_VALUE_TYPE (value) == 0, NULL);
+
+  _gst_value_list_init (value, prealloc);
+
+  return value;
+}
+
+static void
+_gst_value_array_init (GValue * value, guint prealloc)
+{
+  value->g_type = GST_TYPE_ARRAY;
+  memset (value->data, 0, sizeof (value->data));
+  value->data[0].v_pointer = _gst_value_list_new (prealloc);
+}
+
+/**
+ * gst_value_array_init:
+ * @value: A zero-filled (uninitialized) #GValue structure
+ * @prealloc: The number of entries to pre-allocate in the array
+ *
+ * Initializes and pre-allocates a #GValue of type #GST_TYPE_ARRAY.
+ *
+ * Returns: (transfer none): The #GValue structure that has been passed in
+ *
+ * Since: 1.18
+ */
+
+GValue *
+gst_value_array_init (GValue * value, guint prealloc)
+{
+  g_return_val_if_fail (value != NULL, NULL);
+  g_return_val_if_fail (G_VALUE_TYPE (value) == 0, NULL);
+
+  _gst_value_array_init (value, prealloc);
+
+  return value;
+}
+
 /* two helper functions to serialize/stringify any type of list
  * regular lists are done with { }, arrays with < >
  */
@@ -203,17 +351,17 @@ _priv_gst_value_serialize_any_list (const GValue * value, const gchar * begin,
     const gchar * end, gboolean print_type)
 {
   guint i;
-  GArray *array = value->data[0].v_pointer;
+  GstValueList *vlist = value->data[0].v_pointer;
   GString *s;
   GValue *v;
   gchar *s_val;
-  guint alen = array->len;
+  guint alen = vlist->len;
 
   /* estimate minimum string length to minimise re-allocs in GString */
   s = g_string_sized_new (2 + (6 * alen) + 2);
   g_string_append (s, begin);
   for (i = 0; i < alen; i++) {
-    v = &g_array_index (array, GValue, i);
+    v = &vlist->fields[i];
     s_val = gst_value_serialize (v);
     if (s_val != NULL) {
       if (print_type) {
@@ -240,7 +388,7 @@ gst_value_transform_any_list_string (const GValue * src_value,
     GValue * dest_value, const gchar * begin, const gchar * end)
 {
   GValue *list_value;
-  GArray *array;
+  GstValueList *array;
   GString *s;
   guint i;
   gchar *list_s;
@@ -253,7 +401,7 @@ gst_value_transform_any_list_string (const GValue * src_value,
   s = g_string_sized_new (2 + (10 * alen) + 2);
   g_string_append (s, begin);
   for (i = 0; i < alen; i++) {
-    list_value = &g_array_index (array, GValue, i);
+    list_value = &array->fields[i];
 
     if (i != 0) {
       g_string_append_len (s, ", ", 2);
@@ -370,21 +518,20 @@ gst_type_is_fixed (GType type)
 static void
 gst_value_init_list_or_array (GValue * value)
 {
-  value->data[0].v_pointer = g_array_new (FALSE, TRUE, sizeof (GValue));
+  value->data[0].v_pointer = _gst_value_list_new (0);
 }
 
-static GArray *
-copy_garray_of_gstvalue (const GArray * src)
+static GstValueList *
+copy_gst_value_list (const GstValueList * src)
 {
-  GArray *dest;
+  GstValueList *dest;
   guint i, len;
 
   len = src->len;
-  dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), len);
-  g_array_set_size (dest, len);
+  dest = _gst_value_list_new (len);
+  dest->len = len;
   for (i = 0; i < len; i++) {
-    gst_value_init_and_copy (&g_array_index (dest, GValue, i),
-        &g_array_index (src, GValue, i));
+    gst_value_init_and_copy (&dest->fields[i], &src->fields[i]);
   }
 
   return dest;
@@ -394,21 +541,24 @@ static void
 gst_value_copy_list_or_array (const GValue * src_value, GValue * dest_value)
 {
   dest_value->data[0].v_pointer =
-      copy_garray_of_gstvalue ((GArray *) src_value->data[0].v_pointer);
+      copy_gst_value_list (VALUE_LIST_ARRAY (src_value));
 }
 
 static void
 gst_value_free_list_or_array (GValue * value)
 {
   guint i, len;
-  GArray *src = (GArray *) value->data[0].v_pointer;
+  GstValueList *src = VALUE_LIST_ARRAY (value);
   len = src->len;
 
   if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) {
     for (i = 0; i < len; i++) {
-      g_value_unset (&g_array_index (src, GValue, i));
+      g_value_unset (&src->fields[i]);
+    }
+    if (VALUE_LIST_IS_USING_DYNAMIC_ARRAY (src)) {
+      g_free (src->fields);
     }
-    g_array_free (src, TRUE);
+    g_free (src);
   }
 }
 
@@ -427,7 +577,7 @@ gst_value_collect_list_or_array (GValue * value, guint n_collect_values,
     value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
   } else {
     value->data[0].v_pointer =
-        copy_garray_of_gstvalue ((GArray *) collect_values[0].v_pointer);
+        copy_gst_value_list ((GstValueList *) collect_values[0].v_pointer);
   }
   return NULL;
 }
@@ -436,18 +586,19 @@ static gchar *
 gst_value_lcopy_list_or_array (const GValue * value, guint n_collect_values,
     GTypeCValue * collect_values, guint collect_flags)
 {
-  GArray **dest = collect_values[0].v_pointer;
+  GstValueList **dest = collect_values[0].v_pointer;
+
+  g_return_val_if_fail (dest != NULL,
+      g_strdup_printf ("value location for `%s' passed as NULL",
+          G_VALUE_TYPE_NAME (value)));
+  g_return_val_if_fail (value->data[0].v_pointer != NULL,
+      g_strdup_printf ("invalid value given for `%s'",
+          G_VALUE_TYPE_NAME (value)));
 
-  if (!dest)
-    return g_strdup_printf ("value location for `%s' passed as NULL",
-        G_VALUE_TYPE_NAME (value));
-  if (!value->data[0].v_pointer)
-    return g_strdup_printf ("invalid value given for `%s'",
-        G_VALUE_TYPE_NAME (value));
   if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
-    *dest = (GArray *) value->data[0].v_pointer;
+    *dest = (GstValueList *) value->data[0].v_pointer;
   } else {
-    *dest = copy_garray_of_gstvalue ((GArray *) value->data[0].v_pointer);
+    *dest = copy_gst_value_list (VALUE_LIST_ARRAY (value));
   }
   return NULL;
 }
@@ -458,19 +609,12 @@ gst_value_list_or_array_get_basic_type (const GValue * value, GType * type)
   if (G_UNLIKELY (value == NULL))
     return FALSE;
 
-  if (GST_VALUE_HOLDS_LIST (value)) {
+  if (GST_VALUE_HOLDS_LIST (value) || GST_VALUE_HOLDS_ARRAY (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);
 
@@ -512,7 +656,7 @@ gst_value_list_or_array_are_compatible (const GValue * value1,
 static inline void
 _gst_value_list_append_and_take_value (GValue * value, GValue * append_value)
 {
-  g_array_append_vals ((GArray *) value->data[0].v_pointer, append_value, 1);
+  _gst_value_list_append_val (VALUE_LIST_ARRAY (value), append_value);
   memset (append_value, 0, sizeof (GValue));
 }
 
@@ -554,7 +698,7 @@ gst_value_list_append_value (GValue * value, const GValue * append_value)
           append_value));
 
   gst_value_init_and_copy (&val, append_value);
-  g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
+  _gst_value_list_append_val (VALUE_LIST_ARRAY (value), &val);
 }
 
 /**
@@ -575,7 +719,7 @@ gst_value_list_prepend_value (GValue * value, const GValue * prepend_value)
           prepend_value));
 
   gst_value_init_and_copy (&val, prepend_value);
-  g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1);
+  _gst_value_list_prepend_val (VALUE_LIST_ARRAY (value), &val);
 }
 
 /**
@@ -593,7 +737,7 @@ gst_value_list_concat (GValue * dest, const GValue * value1,
     const GValue * value2)
 {
   guint i, value1_length, value2_length;
-  GArray *array;
+  GstValueList *vlist;
 
   g_return_if_fail (dest != NULL);
   g_return_if_fail (G_VALUE_TYPE (dest) == 0);
@@ -605,27 +749,27 @@ gst_value_list_concat (GValue * dest, const GValue * value1,
       (GST_VALUE_HOLDS_LIST (value1) ? VALUE_LIST_SIZE (value1) : 1);
   value2_length =
       (GST_VALUE_HOLDS_LIST (value2) ? VALUE_LIST_SIZE (value2) : 1);
-  g_value_init (dest, GST_TYPE_LIST);
-  array = (GArray *) dest->data[0].v_pointer;
-  g_array_set_size (array, value1_length + value2_length);
+
+  _gst_value_list_init (dest, value1_length + value2_length);
+  vlist = VALUE_LIST_ARRAY (dest);
+  vlist->len = value1_length + value2_length;
 
   if (GST_VALUE_HOLDS_LIST (value1)) {
     for (i = 0; i < value1_length; i++) {
-      gst_value_init_and_copy (&g_array_index (array, GValue, i),
+      gst_value_init_and_copy (&vlist->fields[i],
           VALUE_LIST_GET_VALUE (value1, i));
     }
   } else {
-    gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1);
+    gst_value_init_and_copy (&vlist->fields[0], value1);
   }
 
   if (GST_VALUE_HOLDS_LIST (value2)) {
     for (i = 0; i < value2_length; i++) {
-      gst_value_init_and_copy (&g_array_index (array, GValue,
-              i + value1_length), VALUE_LIST_GET_VALUE (value2, i));
+      gst_value_init_and_copy (&vlist->fields[i + value1_length],
+          VALUE_LIST_GET_VALUE (value2, i));
     }
   } else {
-    gst_value_init_and_copy (&g_array_index (array, GValue, value1_length),
-        value2);
+    gst_value_init_and_copy (&vlist->fields[value1_length], value2);
   }
 }
 
@@ -637,7 +781,7 @@ gst_value_list_concat_and_take_values (GValue * dest, GValue * val1,
   guint i, val1_length, val2_length;
   gboolean val1_is_list;
   gboolean val2_is_list;
-  GArray *array;
+  GstValueList *vlist;
 
   g_assert (dest != NULL);
   g_assert (G_VALUE_TYPE (dest) == 0);
@@ -651,30 +795,32 @@ gst_value_list_concat_and_take_values (GValue * dest, GValue * val1,
   val2_is_list = GST_VALUE_HOLDS_LIST (val2);
   val2_length = (val2_is_list ? VALUE_LIST_SIZE (val2) : 1);
 
-  g_value_init (dest, GST_TYPE_LIST);
-  array = (GArray *) dest->data[0].v_pointer;
-  g_array_set_size (array, val1_length + val2_length);
+  /* Overidding the default initialization to have a list of the target size */
+  _gst_value_list_init (dest, val1_length + val2_length);
+  vlist = VALUE_LIST_ARRAY (dest);
+  vlist->len = val1_length + val2_length;
 
   if (val1_is_list) {
     for (i = 0; i < val1_length; i++) {
-      g_array_index (array, GValue, i) = *VALUE_LIST_GET_VALUE (val1, i);
+      vlist->fields[i] = *VALUE_LIST_GET_VALUE (val1, i);
     }
-    g_array_set_size (VALUE_LIST_ARRAY (val1), 0);
+    VALUE_LIST_ARRAY (val1)->len = 0;
     g_value_unset (val1);
   } else {
-    g_array_index (array, GValue, 0) = *val1;
+    vlist->fields[0] = *val1;
     G_VALUE_TYPE (val1) = G_TYPE_INVALID;
   }
 
   if (val2_is_list) {
     for (i = 0; i < val2_length; i++) {
       const GValue *v2 = VALUE_LIST_GET_VALUE (val2, i);
-      g_array_index (array, GValue, i + val1_length) = *v2;
+      vlist->fields[i + val1_length] = *v2;
     }
-    g_array_set_size (VALUE_LIST_ARRAY (val2), 0);
+
+    VALUE_LIST_ARRAY (val2)->len = 0;
     g_value_unset (val2);
   } else {
-    g_array_index (array, GValue, val1_length) = *val2;
+    vlist->fields[val1_length] = *val2;
     G_VALUE_TYPE (val2) = G_TYPE_INVALID;
   }
 }
@@ -699,7 +845,7 @@ gst_value_list_merge (GValue * dest, const GValue * value1,
   guint i, j, k, value1_length, value2_length, skipped;
   const GValue *src;
   gboolean skip;
-  GArray *array;
+  GstValueList *vlist;
 
   g_return_if_fail (dest != NULL);
   g_return_if_fail (G_VALUE_TYPE (dest) == 0);
@@ -711,17 +857,18 @@ gst_value_list_merge (GValue * dest, const GValue * value1,
       (GST_VALUE_HOLDS_LIST (value1) ? VALUE_LIST_SIZE (value1) : 1);
   value2_length =
       (GST_VALUE_HOLDS_LIST (value2) ? VALUE_LIST_SIZE (value2) : 1);
-  g_value_init (dest, GST_TYPE_LIST);
-  array = (GArray *) dest->data[0].v_pointer;
-  g_array_set_size (array, value1_length + value2_length);
+
+  _gst_value_list_init (dest, value1_length + value2_length);
+  vlist = VALUE_LIST_ARRAY (dest);
+  vlist->len = value1_length + value2_length;
 
   if (GST_VALUE_HOLDS_LIST (value1)) {
     for (i = 0; i < value1_length; i++) {
-      gst_value_init_and_copy (&g_array_index (array, GValue, i),
-          VALUE_LIST_GET_VALUE (value1, i));
+      gst_value_init_and_copy (&vlist->fields[i], VALUE_LIST_GET_VALUE (value1,
+              i));
     }
   } else {
-    gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1);
+    gst_value_init_and_copy (&vlist->fields[0], value1);
   }
 
   j = value1_length;
@@ -731,30 +878,28 @@ gst_value_list_merge (GValue * dest, const GValue * value1,
       skip = FALSE;
       src = VALUE_LIST_GET_VALUE (value2, i);
       for (k = 0; k < value1_length; k++) {
-        if (gst_value_compare (&g_array_index (array, GValue, k),
-                src) == GST_VALUE_EQUAL) {
+        if (gst_value_compare (&vlist->fields[k], src) == GST_VALUE_EQUAL) {
           skip = TRUE;
           skipped++;
           break;
         }
       }
       if (!skip) {
-        gst_value_init_and_copy (&g_array_index (array, GValue, j), src);
+        gst_value_init_and_copy (&vlist->fields[j], src);
         j++;
       }
     }
   } else {
     skip = FALSE;
     for (k = 0; k < value1_length; k++) {
-      if (gst_value_compare (&g_array_index (array, GValue, k),
-              value2) == GST_VALUE_EQUAL) {
+      if (gst_value_compare (&vlist->fields[k], value2) == GST_VALUE_EQUAL) {
         skip = TRUE;
         skipped++;
         break;
       }
     }
     if (!skip) {
-      gst_value_init_and_copy (&g_array_index (array, GValue, j), value2);
+      gst_value_init_and_copy (&vlist->fields[j], value2);
     }
   }
   if (skipped) {
@@ -762,17 +907,17 @@ gst_value_list_merge (GValue * dest, const GValue * value1,
 
     if (new_size > 1) {
       /* shrink list */
-      g_array_set_size (array, new_size);
+      vlist->len = new_size;
     } else {
       GValue single_dest;
 
       /* size is 1, take single value in list and make it new dest */
-      single_dest = g_array_index (array, GValue, 0);
+      single_dest = vlist->fields[0];
 
       /* clean up old value allocations: must set array size to 0, because
        * allocated values are not inited meaning g_value_unset() will not
        * work on them */
-      g_array_set_size (array, 0);
+      vlist->len = 0;
       g_value_unset (dest);
 
       /* the single value is our new result */
@@ -794,7 +939,7 @@ gst_value_list_get_size (const GValue * value)
 {
   g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), 0);
 
-  return ((GArray *) value->data[0].v_pointer)->len;
+  return VALUE_LIST_SIZE (value);
 }
 
 /**
@@ -813,8 +958,7 @@ gst_value_list_get_value (const GValue * value, guint index)
   g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), NULL);
   g_return_val_if_fail (index < VALUE_LIST_SIZE (value), NULL);
 
-  return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
-      GValue, index);
+  return VALUE_LIST_GET_VALUE (value, index);
 }
 
 /**
@@ -835,13 +979,13 @@ gst_value_array_append_value (GValue * value, const GValue * append_value)
           append_value));
 
   gst_value_init_and_copy (&val, append_value);
-  g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
+  _gst_value_list_append_val (VALUE_LIST_ARRAY (value), &val);
 }
 
 static inline void
 _gst_value_array_append_and_take_value (GValue * value, GValue * append_value)
 {
-  g_array_append_vals ((GArray *) value->data[0].v_pointer, append_value, 1);
+  _gst_value_list_append_val (VALUE_LIST_ARRAY (value), append_value);
   memset (append_value, 0, sizeof (GValue));
 }
 
@@ -883,7 +1027,7 @@ gst_value_array_prepend_value (GValue * value, const GValue * prepend_value)
           prepend_value));
 
   gst_value_init_and_copy (&val, prepend_value);
-  g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1);
+  _gst_value_list_prepend_val (VALUE_LIST_ARRAY (value), &val);
 }
 
 /**
@@ -899,7 +1043,7 @@ gst_value_array_get_size (const GValue * value)
 {
   g_return_val_if_fail (GST_VALUE_HOLDS_ARRAY (value), 0);
 
-  return ((GArray *) value->data[0].v_pointer)->len;
+  return VALUE_LIST_SIZE (value);
 }
 
 /**
@@ -916,10 +1060,9 @@ const GValue *
 gst_value_array_get_value (const GValue * value, guint index)
 {
   g_return_val_if_fail (GST_VALUE_HOLDS_ARRAY (value), NULL);
-  g_return_val_if_fail (index < gst_value_array_get_size (value), NULL);
+  g_return_val_if_fail (index < VALUE_LIST_SIZE (value), NULL);
 
-  return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
-      GValue, index);
+  return VALUE_LIST_GET_VALUE (value, index);
 }
 
 static void
@@ -946,20 +1089,20 @@ gst_value_transform_g_value_array_any_list (const GValue * src_value,
     GValue * dest_value)
 {
   const GValueArray *varray;
-  GArray *array;
+  GstValueList *vlist;
   gint i;
 
+  varray = g_value_get_boxed (src_value);
+
   /* GLib will unset the value, memset to 0 the data instead of doing a proper
    * reset. That's why we need to allocate the array here */
-  gst_value_init_list_or_array (dest_value);
-
-  varray = g_value_get_boxed (src_value);
-  array = dest_value->data[0].v_pointer;
+  vlist = dest_value->data[0].v_pointer =
+      _gst_value_list_new (varray->n_values);
 
   for (i = 0; i < varray->n_values; i++) {
     GValue val = G_VALUE_INIT;
     gst_value_init_and_copy (&val, &varray->values[i]);
-    g_array_append_vals (array, &val, 1);
+    _gst_value_list_append_val (vlist, &val);
   }
 }
 
@@ -968,14 +1111,14 @@ gst_value_transform_any_list_g_value_array (const GValue * src_value,
     GValue * dest_value)
 {
   GValueArray *varray;
-  const GArray *array;
+  GstValueList *vlist;
   gint i;
 
-  array = src_value->data[0].v_pointer;
-  varray = g_value_array_new (array->len);
+  vlist = VALUE_LIST_ARRAY (src_value);
+  varray = g_value_array_new (vlist->len);
 
-  for (i = 0; i < array->len; i++)
-    g_value_array_append (varray, &g_array_index (array, GValue, i));
+  for (i = 0; i < vlist->len; i++)
+    g_value_array_append (varray, &vlist->fields[i]);
 
   g_value_take_boxed (dest_value, varray);
 }
@@ -985,8 +1128,8 @@ static gint
 gst_value_compare_value_list (const GValue * value1, const GValue * value2)
 {
   guint i, j;
-  GArray *array1 = value1->data[0].v_pointer;
-  GArray *array2 = value2->data[0].v_pointer;
+  GstValueList *vlist1 = VALUE_LIST_ARRAY (value1);
+  GstValueList *vlist2 = VALUE_LIST_ARRAY (value2);
   GValue *v1;
   GValue *v2;
   gint len, to_remove;
@@ -994,8 +1137,20 @@ gst_value_compare_value_list (const GValue * value1, const GValue * value2)
   GstValueCompareFunc compare;
 
   /* get length and do initial length check. */
-  len = array1->len;
-  if (len != array2->len)
+  len = vlist1->len;
+  if (len != vlist2->len)
+    return GST_VALUE_UNORDERED;
+
+  /* Empty lists are equal */
+  if (len == 0)
+    return GST_VALUE_EQUAL;
+
+  /* We know lists are not empty. do sanity check on first values */
+  if (G_VALUE_TYPE (&vlist1->fields[0]) != G_VALUE_TYPE (&vlist2->fields[0]))
+    return GST_VALUE_UNORDERED;
+
+  /* Get the compare function */
+  if (!(compare = gst_value_get_compare_func (&vlist1->fields[0])))
     return GST_VALUE_UNORDERED;
 
   /* place to mark removed value indices of array2 */
@@ -1006,25 +1161,25 @@ gst_value_compare_value_list (const GValue * value1, const GValue * value2)
   /* loop over array1, all items should be in array2. When we find an
    * item in array2, remove it from array2 by marking it as removed */
   for (i = 0; i < len; i++) {
-    v1 = &g_array_index (array1, GValue, i);
-    if ((compare = gst_value_get_compare_func (v1))) {
-      for (j = 0; j < len; j++) {
-        /* item is removed, we can skip it */
-        if (removed[j])
-          continue;
-        v2 = &g_array_index (array2, GValue, j);
-        if (gst_value_compare_with_func (v1, v2, compare) == GST_VALUE_EQUAL) {
-          /* mark item as removed now that we found it in array2 and
-           * decrement the number of remaining items in array2. */
-          removed[j] = 1;
-          to_remove--;
-          break;
-        }
+    v1 = &vlist1->fields[i];
+
+    for (j = 0; j < len; j++) {
+      /* item is removed, we can skip it */
+      if (removed[j])
+        continue;
+      v2 = &vlist2->fields[j];
+      /* Note: compare function can be called directly since we know the types
+       * are identical */
+      if (compare (v1, v2) == GST_VALUE_EQUAL) {
+        /* mark item as removed now that we found it in array2 and
+         * decrement the number of remaining items in array2. */
+        removed[j] = 1;
+        to_remove--;
+        break;
       }
-      /* item in array1 and not in array2, UNORDERED */
-      if (j == len)
-        return GST_VALUE_UNORDERED;
-    } else
+    }
+    /* item in array1 and not in array2, UNORDERED */
+    if (j == len)
       return GST_VALUE_UNORDERED;
   }
   /* if not all items were removed, array2 contained something not in array1 */
@@ -1040,18 +1195,18 @@ static gint
 gst_value_compare_value_array (const GValue * value1, const GValue * value2)
 {
   guint i;
-  GArray *array1 = value1->data[0].v_pointer;
-  GArray *array2 = value2->data[0].v_pointer;
-  guint len = array1->len;
+  GstValueList *vlist1 = VALUE_LIST_ARRAY (value1);
+  GstValueList *vlist2 = VALUE_LIST_ARRAY (value2);
+  guint len = vlist1->len;
   GValue *v1;
   GValue *v2;
 
-  if (len != array2->len)
+  if (len != vlist2->len)
     return GST_VALUE_UNORDERED;
 
   for (i = 0; i < len; i++) {
-    v1 = &g_array_index (array1, GValue, i);
-    v2 = &g_array_index (array2, GValue, i);
+    v1 = &vlist1->fields[i];
+    v2 = &vlist2->fields[i];
     if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL)
       return GST_VALUE_UNORDERED;
   }
@@ -1065,11 +1220,11 @@ gst_value_compare_g_value_array (const GValue * value1, const GValue * value2)
   guint i;
   GValueArray *array1 = value1->data[0].v_pointer;
   GValueArray *array2 = value2->data[0].v_pointer;
-  guint len = array1->n_values;
+  guint len = array1 ? array1->n_values : 0;
   GValue *v1;
   GValue *v2;
 
-  if (len != array2->n_values)
+  if (len != (array2 ? array2->n_values : 0))
     return GST_VALUE_UNORDERED;
 
   for (i = 0; i < len; i++) {
@@ -1089,10 +1244,11 @@ gst_value_serialize_value_list (const GValue * value)
 }
 
 static gboolean
-gst_value_deserialize_value_list (GValue * dest, const gchar * s)
+gst_value_deserialize_value_list (GValue * dest, const gchar * s,
+    GParamSpec * pspec)
 {
   gchar *s2 = (gchar *) s;
-  return _priv_gst_value_parse_list (s2, &s2, dest, G_TYPE_INVALID);
+  return _priv_gst_value_parse_list (s2, &s2, dest, G_TYPE_INVALID, pspec);
 }
 
 static gchar *
@@ -1102,10 +1258,11 @@ gst_value_serialize_value_array (const GValue * value)
 }
 
 static gboolean
-gst_value_deserialize_value_array (GValue * dest, const gchar * s)
+gst_value_deserialize_value_array (GValue * dest, const gchar * s,
+    GParamSpec * pspec)
 {
   gchar *s2 = (gchar *) s;
-  return _priv_gst_value_parse_array (s2, &s2, dest, G_TYPE_INVALID);
+  return _priv_gst_value_parse_array (s2, &s2, dest, G_TYPE_INVALID, pspec);
 }
 
 static gchar *
@@ -1157,12 +1314,12 @@ static gchar *
 gst_value_collect_int_range (GValue * value, guint n_collect_values,
     GTypeCValue * collect_values, guint collect_flags)
 {
-  if (n_collect_values != 2)
-    return g_strdup_printf ("not enough value locations for `%s' passed",
-        G_VALUE_TYPE_NAME (value));
-  if (collect_values[0].v_int >= collect_values[1].v_int)
-    return g_strdup_printf ("range start is not smaller than end for `%s'",
-        G_VALUE_TYPE_NAME (value));
+  g_return_val_if_fail (n_collect_values == 2,
+      g_strdup_printf ("not enough value locations for `%s' passed",
+          G_VALUE_TYPE_NAME (value)));
+  g_return_val_if_fail (collect_values[0].v_int < collect_values[1].v_int,
+      g_strdup_printf ("range start is not smaller than end for `%s'",
+          G_VALUE_TYPE_NAME (value)));
 
   gst_value_set_int_range_step (value, collect_values[0].v_int,
       collect_values[1].v_int, 1);
@@ -1177,12 +1334,12 @@ 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;
 
-  if (!int_range_start)
-    return g_strdup_printf ("start value location for `%s' passed as NULL",
-        G_VALUE_TYPE_NAME (value));
-  if (!int_range_end)
-    return g_strdup_printf ("end value location for `%s' passed as NULL",
-        G_VALUE_TYPE_NAME (value));
+  g_return_val_if_fail (int_range_start != NULL,
+      g_strdup_printf ("start value location for `%s' passed as NULL",
+          G_VALUE_TYPE_NAME (value)));
+  g_return_val_if_fail (int_range_end != NULL,
+      g_strdup_printf ("end value location for `%s' passed as NULL",
+          G_VALUE_TYPE_NAME (value)));
 
   *int_range_start = INT_RANGE_MIN (value);
   *int_range_end = INT_RANGE_MAX (value);
@@ -1295,33 +1452,28 @@ gst_value_transform_int_range_string (const GValue * src_value,
 static gint
 gst_value_compare_int_range (const GValue * value1, const GValue * value2)
 {
-  /* 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)
+#if 0
+  /* Compare the ranges. (Kept for clarity for the below comparision) */
+  if (INT_RANGE_MIN (value1) != INT_RANGE_MIN (value2) ||
+      INT_RANGE_MAX (value1) != INT_RANGE_MAX (value2))
+    return GST_VALUE_UNORDERED;
+#else
+  /* The MIN and MAX of the range are actually stored packed into one 64bit
+   * value. We can therefore compare them directly */
+  if (value1->data[0].v_uint64 != value2->data[0].v_uint64)
     return GST_VALUE_UNORDERED;
+#endif
 
-  /* if empty, equal */
-  if (n1 == 0)
+  /* The extents are equal */
+  /* If there is only one value (min == max), we ignore the step for
+   * comparison */
+  if (INT_RANGE_MIN (value1) == INT_RANGE_MAX (value1))
     return GST_VALUE_EQUAL;
 
-  /* 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_MIN (value1) == INT_RANGE_MIN (value2) &&
-        INT_RANGE_MAX (value1) == INT_RANGE_MAX (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;
-  }
+  /* Else the ranges are only equal if their step is also equal */
+  if (INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2))
+    return GST_VALUE_EQUAL;
+  return GST_VALUE_UNORDERED;
 }
 
 static gchar *
@@ -1396,12 +1548,13 @@ gst_value_collect_int64_range (GValue * value, guint n_collect_values,
 {
   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));
-  if (collect_values[0].v_int64 >= collect_values[1].v_int64)
-    return g_strdup_printf ("range start is not smaller than end for `%s'",
-        G_VALUE_TYPE_NAME (value));
+  g_return_val_if_fail (n_collect_values == 2,
+      g_strdup_printf ("not enough value locations for `%s' passed",
+          G_VALUE_TYPE_NAME (value)));
+
+  g_return_val_if_fail (collect_values[0].v_int64 < collect_values[1].v_int64,
+      g_strdup_printf ("range start is not smaller than end for `%s'",
+          G_VALUE_TYPE_NAME (value)));
 
   if (vals == NULL) {
     gst_value_init_int64_range (value);
@@ -1422,20 +1575,18 @@ gst_value_lcopy_int64_range (const GValue * value, guint n_collect_values,
   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",
-        G_VALUE_TYPE_NAME (value));
-  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));
+  g_return_val_if_fail (int_range_start != NULL,
+      g_strdup_printf ("start value location for `%s' passed as NULL",
+          G_VALUE_TYPE_NAME (value)));
+  g_return_val_if_fail (int_range_end != NULL,
+      g_strdup_printf ("end value location for `%s' passed as NULL",
+          G_VALUE_TYPE_NAME (value)));
+  g_return_val_if_fail (int_range_step != NULL,
+      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));
-  }
+  g_return_val_if_fail (vals != NULL,
+      g_strdup_printf ("Uninitialised `%s' passed", G_VALUE_TYPE_NAME (value)));
 
   *int_range_start = INT64_RANGE_MIN (value);
   *int_range_end = INT64_RANGE_MAX (value);
@@ -1550,33 +1701,21 @@ gst_value_transform_int64_range_string (const GValue * src_value,
 static gint
 gst_value_compare_int64_range (const GValue * value1, const GValue * value2)
 {
-  /* 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)
+  /* Compare the ranges. */
+  if (INT64_RANGE_MIN (value1) != INT64_RANGE_MIN (value2) ||
+      INT64_RANGE_MAX (value1) != INT64_RANGE_MAX (value2))
     return GST_VALUE_UNORDERED;
 
-  /* if empty, equal */
-  if (n1 == 0)
+  /* The extents are equal */
+  /* If there is only one value (min == max), we ignore the step for
+   * comparison */
+  if (INT64_RANGE_MIN (value1) == INT64_RANGE_MAX (value1))
     return GST_VALUE_EQUAL;
 
-  /* 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_MIN (value1) == INT64_RANGE_MIN (value2) &&
-        INT64_RANGE_MAX (value1) == INT64_RANGE_MAX (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;
-  }
+  /* Else the ranges are only equal if their step is also equal */
+  if (INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2))
+    return GST_VALUE_EQUAL;
+  return GST_VALUE_UNORDERED;
 }
 
 static gchar *
@@ -1622,12 +1761,12 @@ static gchar *
 gst_value_collect_double_range (GValue * value, guint n_collect_values,
     GTypeCValue * collect_values, guint collect_flags)
 {
-  if (n_collect_values != 2)
-    return g_strdup_printf ("not enough value locations for `%s' passed",
-        G_VALUE_TYPE_NAME (value));
-  if (collect_values[0].v_double >= collect_values[1].v_double)
-    return g_strdup_printf ("range start is not smaller than end for `%s'",
-        G_VALUE_TYPE_NAME (value));
+  g_return_val_if_fail (n_collect_values == 2,
+      g_strdup_printf ("not enough value locations for `%s' passed",
+          G_VALUE_TYPE_NAME (value)));
+  g_return_val_if_fail (collect_values[0].v_double < collect_values[1].v_double,
+      g_strdup_printf ("range start is not smaller than end for `%s'",
+          G_VALUE_TYPE_NAME (value)));
 
   value->data[0].v_double = collect_values[0].v_double;
   value->data[1].v_double = collect_values[1].v_double;
@@ -1642,12 +1781,12 @@ gst_value_lcopy_double_range (const GValue * value, guint n_collect_values,
   gdouble *double_range_start = collect_values[0].v_pointer;
   gdouble *double_range_end = collect_values[1].v_pointer;
 
-  if (!double_range_start)
-    return g_strdup_printf ("start value location for `%s' passed as NULL",
-        G_VALUE_TYPE_NAME (value));
-  if (!double_range_end)
-    return g_strdup_printf ("end value location for `%s' passed as NULL",
-        G_VALUE_TYPE_NAME (value));
+  g_return_val_if_fail (double_range_start != NULL,
+      g_strdup_printf ("start value location for `%s' passed as NULL",
+          G_VALUE_TYPE_NAME (value)));
+  g_return_val_if_fail (double_range_end != NULL,
+      g_strdup_printf ("end value location for `%s' passed as NULL",
+          G_VALUE_TYPE_NAME (value)));
 
   *double_range_start = value->data[0].v_double;
   *double_range_end = value->data[1].v_double;
@@ -1798,20 +1937,20 @@ gst_value_collect_fraction_range (GValue * value, guint n_collect_values,
 {
   GValue *vals = (GValue *) value->data[0].v_pointer;
 
-  if (n_collect_values != 4)
-    return g_strdup_printf ("not enough value locations for `%s' passed",
-        G_VALUE_TYPE_NAME (value));
-  if (collect_values[1].v_int == 0)
-    return g_strdup_printf ("passed '0' as first denominator for `%s'",
-        G_VALUE_TYPE_NAME (value));
-  if (collect_values[3].v_int == 0)
-    return g_strdup_printf ("passed '0' as second denominator for `%s'",
-        G_VALUE_TYPE_NAME (value));
-  if (gst_util_fraction_compare (collect_values[0].v_int,
+  g_return_val_if_fail (n_collect_values == 4,
+      g_strdup_printf ("not enough value locations for `%s' passed",
+          G_VALUE_TYPE_NAME (value)));
+  g_return_val_if_fail (collect_values[1].v_int != 0,
+      g_strdup_printf ("passed '0' as first denominator for `%s'",
+          G_VALUE_TYPE_NAME (value)));
+  g_return_val_if_fail (collect_values[3].v_int != 0,
+      g_strdup_printf ("passed '0' as second denominator for `%s'",
+          G_VALUE_TYPE_NAME (value)));
+  g_return_val_if_fail (gst_util_fraction_compare (collect_values[0].v_int,
           collect_values[1].v_int, collect_values[2].v_int,
-          collect_values[3].v_int) >= 0)
-    return g_strdup_printf ("range start is not smaller than end for `%s'",
-        G_VALUE_TYPE_NAME (value));
+          collect_values[3].v_int) < 0,
+      g_strdup_printf ("range start is not smaller than end for `%s'",
+          G_VALUE_TYPE_NAME (value)));
 
   if (vals == NULL) {
     gst_value_init_fraction_range (value);
@@ -1834,21 +1973,18 @@ gst_value_lcopy_fraction_range (const GValue * value, guint n_collect_values,
   gint *dest_values[4];
   GValue *vals = (GValue *) value->data[0].v_pointer;
 
-  if (G_UNLIKELY (n_collect_values != 4))
-    return g_strdup_printf ("not enough value locations for `%s' passed",
-        G_VALUE_TYPE_NAME (value));
+  g_return_val_if_fail (n_collect_values == 4,
+      g_strdup_printf ("not enough value locations for `%s' passed",
+          G_VALUE_TYPE_NAME (value)));
+  g_return_val_if_fail (vals != NULL,
+      g_strdup_printf ("Uninitialised `%s' passed", G_VALUE_TYPE_NAME (value)));
 
   for (i = 0; i < 4; i++) {
-    if (G_UNLIKELY (collect_values[i].v_pointer == NULL)) {
-      return g_strdup_printf ("value location for `%s' passed as NULL",
-          G_VALUE_TYPE_NAME (value));
-    }
-    dest_values[i] = collect_values[i].v_pointer;
-  }
+    g_return_val_if_fail (collect_values[i].v_pointer != NULL,
+        g_strdup_printf ("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));
+    dest_values[i] = collect_values[i].v_pointer;
   }
 
   dest_values[0][0] = gst_value_get_fraction_numerator (&vals[0]);
@@ -2013,7 +2149,6 @@ static gint
 gst_value_compare_fraction_range (const GValue * value1, const GValue * value2)
 {
   GValue *vals1, *vals2;
-  GstValueCompareFunc compare;
 
   if (value2->data[0].v_pointer == value1->data[0].v_pointer)
     return GST_VALUE_EQUAL;     /* Only possible if both are NULL */
@@ -2023,13 +2158,10 @@ gst_value_compare_fraction_range (const GValue * value1, const GValue * value2)
 
   vals1 = (GValue *) value1->data[0].v_pointer;
   vals2 = (GValue *) value2->data[0].v_pointer;
-  if ((compare = gst_value_get_compare_func (&vals1[0]))) {
-    if (gst_value_compare_with_func (&vals1[0], &vals2[0], compare) ==
-        GST_VALUE_EQUAL &&
-        gst_value_compare_with_func (&vals1[1], &vals2[1], compare) ==
-        GST_VALUE_EQUAL)
-      return GST_VALUE_EQUAL;
-  }
+  if (gst_value_compare_fraction (&vals1[0], &vals2[0]) == GST_VALUE_EQUAL &&
+      gst_value_compare_fraction (&vals1[1], &vals2[1]) == GST_VALUE_EQUAL)
+    return GST_VALUE_EQUAL;
+
   return GST_VALUE_UNORDERED;
 }
 
@@ -2087,6 +2219,12 @@ gst_value_compare_caps (const GValue * value1, const GValue * value2)
   GstCaps *caps1 = GST_CAPS (gst_value_get_caps (value1));
   GstCaps *caps2 = GST_CAPS (gst_value_get_caps (value2));
 
+  if (caps1 == caps2)
+    return GST_VALUE_EQUAL;
+
+  if (!caps1 || !caps2)
+    return GST_VALUE_UNORDERED;
+
   if (gst_caps_is_equal (caps1, caps2))
     return GST_VALUE_EQUAL;
   return GST_VALUE_UNORDERED;
@@ -2105,6 +2243,8 @@ gst_value_deserialize_caps (GValue * dest, const gchar * s)
   GstCaps *caps;
 
   if (*s != '"') {
+    /* this can happen if caps are ANY, EMPTY, or only contains a single
+     * empty structure */
     caps = gst_caps_from_string (s);
   } else {
     gchar *str = gst_string_unwrap (s);
@@ -2131,7 +2271,7 @@ static GstValueAbbreviation *
 _priv_gst_value_get_abbrs (gint * n_abbrs)
 {
   static GstValueAbbreviation *abbrs = NULL;
-  static volatile gsize num = 0;
+  static gsize num = 0;
 
   if (g_once_init_enter (&num)) {
     /* dynamically generate the array */
@@ -2333,23 +2473,23 @@ _priv_gst_value_parse_range (gchar * s, gchar ** after, GValue * value,
     return FALSE;
   s++;
 
-  ret = _priv_gst_value_parse_value (s, &s, &value1, type);
+  ret = _priv_gst_value_parse_value (s, &s, &value1, type, NULL);
   if (!ret)
-    return FALSE;
+    goto err;
 
   while (g_ascii_isspace (*s))
     s++;
 
   if (*s != ',')
-    return FALSE;
+    goto err;
   s++;
 
   while (g_ascii_isspace (*s))
     s++;
 
-  ret = _priv_gst_value_parse_value (s, &s, &value2, type);
+  ret = _priv_gst_value_parse_value (s, &s, &value2, type, NULL);
   if (!ret)
-    return FALSE;
+    goto err;
 
   while (g_ascii_isspace (*s))
     s++;
@@ -2363,9 +2503,9 @@ _priv_gst_value_parse_range (gchar * s, gchar ** after, GValue * value,
       while (g_ascii_isspace (*s))
         s++;
 
-      ret = _priv_gst_value_parse_value (s, &s, &value3, type);
+      ret = _priv_gst_value_parse_value (s, &s, &value3, type, NULL);
       if (!ret)
-        return FALSE;
+        goto err;
 
       while (g_ascii_isspace (*s))
         s++;
@@ -2375,7 +2515,7 @@ _priv_gst_value_parse_range (gchar * s, gchar ** after, GValue * value,
   }
 
   if (*s != ']')
-    return FALSE;
+    goto err;
   s++;
 
   if (G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value2))
@@ -2417,22 +2557,31 @@ _priv_gst_value_parse_range (gchar * s, gchar ** after, GValue * value,
     g_value_init (value, range_type);
     gst_value_set_fraction_range (value, &value1, &value2);
   } else {
-    return FALSE;
+    goto err;
   }
 
   *after = s;
   return TRUE;
+
+err:
+  g_value_unset (value);
+  g_value_unset (&value1);
+  g_value_unset (&value2);
+  g_value_unset (&value3);
+  return FALSE;
 }
 
 static gboolean
 _priv_gst_value_parse_any_list (gchar * s, gchar ** after, GValue * value,
-    GType type, char begin, char end)
+    GType type, char begin, char end, GParamSpec * pspec)
 {
   GValue list_value = { 0 };
   gboolean ret;
-  GArray *array;
+  GstValueList *vlist = VALUE_LIST_ARRAY (value);
+  GParamSpec *element_spec = NULL;
 
-  array = g_value_peek_pointer (value);
+  if (pspec)
+    element_spec = GST_PARAM_SPEC_ARRAY_LIST (pspec)->element_spec;
 
   if (*s != begin)
     return FALSE;
@@ -2440,37 +2589,32 @@ _priv_gst_value_parse_any_list (gchar * s, gchar ** after, GValue * value,
 
   while (g_ascii_isspace (*s))
     s++;
-  if (*s == end) {
-    s++;
-    *after = s;
-    return TRUE;
-  }
-
-  ret = _priv_gst_value_parse_value (s, &s, &list_value, type);
-  if (!ret)
-    return FALSE;
-
-  g_array_append_val (array, list_value);
-
-  while (g_ascii_isspace (*s))
-    s++;
 
   while (*s != end) {
-    if (*s != ',')
-      return FALSE;
-    s++;
-
-    while (g_ascii_isspace (*s))
+    if (*s == ',') {
       s++;
+      while (g_ascii_isspace (*s))
+        s++;
+
+      if (*s == ',')
+        return FALSE;
+
+      continue;
+    }
 
     memset (&list_value, 0, sizeof (list_value));
-    ret = _priv_gst_value_parse_value (s, &s, &list_value, type);
+
+    ret = _priv_gst_value_parse_value (s, &s, &list_value, type, element_spec);
     if (!ret)
       return FALSE;
 
-    g_array_append_val (array, list_value);
+    _gst_value_list_append_val (vlist, &list_value);
+
     while (g_ascii_isspace (*s))
       s++;
+
+    if (*s != ',' && *s != end)
+      return FALSE;
   }
 
   s++;
@@ -2481,16 +2625,18 @@ _priv_gst_value_parse_any_list (gchar * s, gchar ** after, GValue * value,
 
 static gboolean
 _priv_gst_value_parse_list (gchar * s, gchar ** after, GValue * value,
-    GType type)
+    GType type, GParamSpec * pspec)
 {
-  return _priv_gst_value_parse_any_list (s, after, value, type, '{', '}');
+  return _priv_gst_value_parse_any_list (s, after, value, type, '{', '}',
+      pspec);
 }
 
 static gboolean
 _priv_gst_value_parse_array (gchar * s, gchar ** after, GValue * value,
-    GType type)
+    GType type, GParamSpec * pspec)
 {
-  return _priv_gst_value_parse_any_list (s, after, value, type, '<', '>');
+  return _priv_gst_value_parse_any_list (s, after, value, type, '<', '>',
+      pspec);
 }
 
 gboolean
@@ -2507,9 +2653,90 @@ _priv_gst_value_parse_simple_string (gchar * str, gchar ** end)
   return (s != str);
 }
 
+static gboolean
+_priv_gst_value_parse_struct_or_caps (gchar * str, gchar ** after, GType type,
+    GValue * value)
+{
+  gint openers = 1;
+  gboolean ret = FALSE;
+  gchar *s = str, t, *start, *end, *next;
+
+  if (*s != '[')
+    return FALSE;
+
+  s++;
+  str = s;
+  for (; *s; s++) {
+    if (*s == ']')
+      openers--;
+    else if (*s == '[')
+      openers++;
+
+    if (openers == 0) {
+      *after = s + 1;
+      break;
+    }
+  }
+
+  if (*after == NULL)
+    return FALSE;
+
+  t = *s;
+  *s = '\0';
+  g_value_init (value, type);
+  if (priv_gst_structure_parse_name (str, &start, &end, &next, TRUE))
+    ret = gst_value_deserialize (value, str);
+  if (G_UNLIKELY (!ret)) {
+    *s = t;
+    g_value_unset (value);
+  }
+
+  return ret;
+}
+
+static gboolean
+_priv_gst_value_parse_range_struct_caps (gchar * s, gchar ** after,
+    GValue * value, GType type)
+{
+  gint i;
+  gchar *tmp = s;
+  gboolean ret = FALSE;
+  GType try_types[] = {
+    GST_TYPE_STRUCTURE,
+    GST_TYPE_CAPS,
+  };
+
+  if (type == GST_TYPE_CAPS || type == GST_TYPE_STRUCTURE)
+    ret = _priv_gst_value_parse_struct_or_caps (tmp, &tmp, type, value);
+
+  if (ret)
+    goto ok;
+
+  tmp = s;
+  ret = _priv_gst_value_parse_range (tmp, &tmp, value, type);
+  if (ret)
+    goto ok;
+
+  if (type != G_TYPE_INVALID)
+    return ret;
+
+  for (i = 0; i < G_N_ELEMENTS (try_types); i++) {
+    tmp = s;
+    ret = _priv_gst_value_parse_struct_or_caps (tmp, &tmp, try_types[i], value);
+    if (ret)
+      goto ok;
+  }
+
+  return ret;
+
+ok:
+  *after = tmp;
+  return ret;
+}
+
 gboolean
 _priv_gst_value_parse_value (gchar * str,
-    gchar ** after, GValue * value, GType default_type)
+    gchar ** after, GValue * value, GType default_type, GParamSpec * pspec)
 {
   gchar *type_name;
   gchar *type_end;
@@ -2526,6 +2753,7 @@ _priv_gst_value_parse_value (gchar * str,
 
   /* check if there's a (type_name) 'cast' */
   type_name = NULL;
+
   if (*s == '(') {
     s++;
     while (g_ascii_isspace (*s))
@@ -2552,18 +2780,20 @@ _priv_gst_value_parse_value (gchar * str,
       GST_WARNING ("invalid type");
       return FALSE;
     }
+  } else if (pspec) {
+    type = G_PARAM_SPEC_VALUE_TYPE (pspec);
   }
 
   while (g_ascii_isspace (*s))
     s++;
   if (*s == '[') {
-    ret = _priv_gst_value_parse_range (s, &s, value, type);
+    ret = _priv_gst_value_parse_range_struct_caps (s, &s, value, type);
   } else if (*s == '{') {
     g_value_init (value, GST_TYPE_LIST);
-    ret = _priv_gst_value_parse_list (s, &s, value, type);
+    ret = _priv_gst_value_parse_list (s, &s, value, type, pspec);
   } else if (*s == '<') {
     g_value_init (value, GST_TYPE_ARRAY);
-    ret = _priv_gst_value_parse_array (s, &s, value, type);
+    ret = _priv_gst_value_parse_array (s, &s, value, type, pspec);
   } else {
     value_s = s;
 
@@ -2573,35 +2803,58 @@ _priv_gst_value_parse_value (gchar * str,
         G_TYPE_BOOLEAN, G_TYPE_STRING
       };
       int i;
+      int value_size;
+      gboolean check_wrapped_non_string;
 
-      if (G_UNLIKELY (!_priv_gst_value_parse_string (s, &value_end, &s, TRUE)))
+      if (G_UNLIKELY (!_priv_gst_value_parse_string (s, &value_end, &s, FALSE)))
         return FALSE;
       /* Set NULL terminator for deserialization */
-      c = *value_end;
-      *value_end = '\0';
+      value_size = value_end - value_s;
+      value_s = g_strndup (value_s, value_end - value_s);
+      /* Keep old broken behavior where "2" could be interpretted as an int */
+      check_wrapped_non_string = value_s[0] == '"' &&
+          strlen (value_s) >= 2 && value_end[-1] == '"';
 
       for (i = 0; i < G_N_ELEMENTS (try_types); i++) {
         g_value_init (value, try_types[i]);
-        ret = gst_value_deserialize (value, value_s);
-        if (ret)
-          break;
+        if (try_types[i] != G_TYPE_STRING && check_wrapped_non_string) {
+          value_s[value_size - 1] = '\0';
+          ret = gst_value_deserialize (value, value_s + 1);
+          value_s[value_size - 1] = '"';
+          if (ret) {
+            const gchar *type_name = g_type_name (try_types[i]);
+
+            g_warning ("Received a structure string that contains "
+                "'=%s'. Reading as a %s value, rather than a string "
+                "value. This is undesired behaviour, and with GStreamer 1.22 "
+                " onward, this will be interpreted as a string value instead "
+                "because it is wrapped in '\"' quotes. If you want to "
+                "guarantee this value is read as a string, before this "
+                "change, use '=(string)%s' instead. If you want to read "
+                "in a %s value, leave its value unquoted.",
+                value_s, type_name, value_s, type_name);
+            break;
+          }
+        } else {
+          ret = gst_value_deserialize (value, value_s);
+          if (ret)
+            break;
+        }
         g_value_unset (value);
       }
     } else {
       g_value_init (value, type);
 
-      if (G_UNLIKELY (!_priv_gst_value_parse_string (s, &value_end, &s,
-                  (type != G_TYPE_STRING))))
+      if (G_UNLIKELY (!_priv_gst_value_parse_string (s, &value_end, &s, FALSE)))
         return FALSE;
       /* Set NULL terminator for deserialization */
-      c = *value_end;
-      *value_end = '\0';
+      value_s = g_strndup (value_s, value_end - value_s);
 
-      ret = gst_value_deserialize (value, value_s);
+      ret = gst_value_deserialize_with_pspec (value, value_s, pspec);
       if (G_UNLIKELY (!ret))
         g_value_unset (value);
     }
-    *value_end = c;
+    g_free (value_s);
   }
 
   *after = s;
@@ -2620,18 +2873,19 @@ gst_value_serialize_segment_internal (const GValue * value, gboolean escape)
   gchar *t, *res;
   GstStructure *s;
 
-  s = gst_structure_new ("GstSegment",
-      "flags", GST_TYPE_SEGMENT_FLAGS, seg->flags,
-      "rate", G_TYPE_DOUBLE, seg->rate,
-      "applied-rate", G_TYPE_DOUBLE, seg->applied_rate,
-      "format", GST_TYPE_FORMAT, seg->format,
-      "base", G_TYPE_UINT64, seg->base,
-      "offset", G_TYPE_UINT64, seg->offset,
-      "start", G_TYPE_UINT64, seg->start,
-      "stop", G_TYPE_UINT64, seg->stop,
-      "time", G_TYPE_UINT64, seg->time,
-      "position", G_TYPE_UINT64, seg->position,
-      "duration", G_TYPE_UINT64, seg->duration, NULL);
+  s = gst_structure_new_id (GST_QUARK (SEGMENT),
+      GST_QUARK (FLAGS), GST_TYPE_SEGMENT_FLAGS, seg->flags,
+      GST_QUARK (RATE), G_TYPE_DOUBLE, seg->rate,
+      GST_QUARK (APPLIED_RATE), G_TYPE_DOUBLE, seg->applied_rate,
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, seg->format,
+      GST_QUARK (BASE), G_TYPE_UINT64, seg->base,
+      GST_QUARK (OFFSET), G_TYPE_UINT64, seg->offset,
+      GST_QUARK (START), G_TYPE_UINT64, seg->start,
+      GST_QUARK (STOP), G_TYPE_UINT64, seg->stop,
+      GST_QUARK (TIME), G_TYPE_UINT64, seg->time,
+      GST_QUARK (POSITION), G_TYPE_UINT64, seg->position,
+      GST_QUARK (DURATION), G_TYPE_UINT64, seg->duration, NULL);
+
   t = gst_structure_to_string (s);
   if (escape) {
     res = g_strdup_printf ("\"%s\"", t);
@@ -2651,28 +2905,46 @@ gst_value_serialize_segment (const GValue * value)
 }
 
 static gboolean
-gst_value_deserialize_segment (GValue * dest, const gchar * s)
+gst_value_deserialize_segment_internal (GValue * dest, const gchar * s,
+    gboolean unescape)
 {
   GstStructure *str;
   GstSegment seg;
   gboolean res;
+  gsize len;
+  gchar *t;
 
-  str = gst_structure_from_string (s, NULL);
-  if (str == NULL)
+  if (unescape) {
+    len = strlen (s);
+    if (G_UNLIKELY (*s != '"' || len < 2 || s[len - 1] != '"')) {
+      /* "\"" is not an accepted string, so len must be at least 2 */
+      GST_ERROR ("Failed deserializing segement: expected string to start and "
+          "end with '\"'");
+      return FALSE;
+    }
+    t = g_strdup (s + 1);
+    t[len - 2] = '\0';
+    /* removed trailing '"' */
+    str = gst_structure_from_string (t, NULL);
+    g_free (t);
+  } else {
+    str = gst_structure_from_string (s, NULL);
+  }
+  if (G_UNLIKELY (str == NULL))
     return FALSE;
 
-  res = gst_structure_get (str,
-      "flags", GST_TYPE_SEGMENT_FLAGS, &seg.flags,
-      "rate", G_TYPE_DOUBLE, &seg.rate,
-      "applied-rate", G_TYPE_DOUBLE, &seg.applied_rate,
-      "format", GST_TYPE_FORMAT, &seg.format,
-      "base", G_TYPE_UINT64, &seg.base,
-      "offset", G_TYPE_UINT64, &seg.offset,
-      "start", G_TYPE_UINT64, &seg.start,
-      "stop", G_TYPE_UINT64, &seg.stop,
-      "time", G_TYPE_UINT64, &seg.time,
-      "position", G_TYPE_UINT64, &seg.position,
-      "duration", G_TYPE_UINT64, &seg.duration, NULL);
+  res = gst_structure_id_get (str,
+      GST_QUARK (FLAGS), GST_TYPE_SEGMENT_FLAGS, &seg.flags,
+      GST_QUARK (RATE), G_TYPE_DOUBLE, &seg.rate,
+      GST_QUARK (APPLIED_RATE), G_TYPE_DOUBLE, &seg.applied_rate,
+      GST_QUARK (FORMAT), GST_TYPE_FORMAT, &seg.format,
+      GST_QUARK (BASE), G_TYPE_UINT64, &seg.base,
+      GST_QUARK (OFFSET), G_TYPE_UINT64, &seg.offset,
+      GST_QUARK (START), G_TYPE_UINT64, &seg.start,
+      GST_QUARK (STOP), G_TYPE_UINT64, &seg.stop,
+      GST_QUARK (TIME), G_TYPE_UINT64, &seg.time,
+      GST_QUARK (POSITION), G_TYPE_UINT64, &seg.position,
+      GST_QUARK (DURATION), G_TYPE_UINT64, &seg.duration, NULL);
   gst_structure_free (str);
 
   if (res)
@@ -2681,6 +2953,12 @@ gst_value_deserialize_segment (GValue * dest, const gchar * s)
   return res;
 }
 
+static gboolean
+gst_value_deserialize_segment (GValue * dest, const gchar * s)
+{
+  return gst_value_deserialize_segment_internal (dest, s, TRUE);
+}
+
 /****************
  * GstStructure *
  ****************/
@@ -2725,6 +3003,8 @@ gst_value_serialize_structure (const GValue * value)
   GstStructure *structure = g_value_get_boxed (value);
 
   return priv_gst_string_take_and_wrap (gst_structure_to_string (structure));
+  /* string should always end up being wrapped, since a structure string
+   * ends in a ';' character */
 }
 
 static gboolean
@@ -2733,6 +3013,14 @@ gst_value_deserialize_structure (GValue * dest, const gchar * s)
   GstStructure *structure;
 
   if (*s != '"') {
+    /* the output of gst_value_serialize_structure would never produce
+     * such a string, but a user may pass to gst_structure_from_string
+     * the string:
+     *     name, sub=(GstStructure)sub-name, val=(int)5;
+     * and expect sub to be read as an *empty* structure with the name
+     * sub-name. Similar to
+     *     name, caps=(GstCaps)video/x-raw, val=(int)5;
+     * which gst_structure_to_string can produce. */
     structure = gst_structure_from_string (s, NULL);
   } else {
     gchar *str = gst_string_unwrap (s);
@@ -2821,6 +3109,9 @@ gst_value_deserialize_caps_features (GValue * dest, const gchar * s)
   GstCapsFeatures *features;
 
   if (*s != '"') {
+    /* This can happen if gst_caps_features_to_string only returns
+     * ALL, NONE, or a single features name, which means it is not
+     * actually wrapped by priv_gst_string_take_and_wrap */
     features = gst_caps_features_from_string (s);
   } else {
     gchar *str = gst_string_unwrap (s);
@@ -2859,6 +3150,13 @@ gst_value_deserialize_tag_list (GValue * dest, const gchar * s)
   GstTagList *taglist;
 
   if (*s != '"') {
+    /* the output of gst_value_serialize_tag_list would never produce
+     * such a string, but a user may pass to gst_structure_from_string
+     * the string:
+     *     name, list=(GstTagList)taglist, val=(int)5;
+     * and expect list to be read as an *empty* tag list. Similar to
+     *     name, caps=(GstCaps)video/x-raw, val=(int)5;
+     * which gst_structure_to_string can produce. */
     taglist = gst_tag_list_new_from_string (s);
   } else {
     gchar *str = gst_string_unwrap (s);
@@ -2883,6 +3181,8 @@ gst_value_serialize_tag_list (const GValue * value)
   GstTagList *taglist = g_value_get_boxed (value);
 
   return priv_gst_string_take_and_wrap (gst_tag_list_to_string (taglist));
+  /* string should always end up being wrapped, since a taglist (structure)
+   * string ends in a ';' character */
 }
 
 
@@ -3140,7 +3440,7 @@ gst_value_deserialize_sample (GValue * dest, const gchar * s)
     g_strdelimit (fields[2], "_", '=');
     g_base64_decode_inplace (fields[2], &outlen);
     GST_TRACE ("segment : %s", fields[2]);
-    if (!gst_value_deserialize_segment (&sval, fields[2]))
+    if (!gst_value_deserialize_segment_internal (&sval, fields[2], FALSE))
       goto fail;
   }
 
@@ -3657,13 +3957,13 @@ gst_string_unwrap (const gchar * s)
         /* if we run into a \0 here, we definitely won't get a quote later */
         if (*read == 0)
           goto beach;
-
         /* else copy \X sequence */
         *write++ = *read++;
       }
-    } else {
-      /* weird character, error */
+    } else if (*read == '\0') {
       goto beach;
+    } else {
+      *write++ = *read++;
     }
   }
   /* if the string is not ending in " and zero terminated, we error */
@@ -3701,6 +4001,10 @@ gst_value_deserialize_string (GValue * dest, const gchar * s)
     gchar *str = gst_string_unwrap (s);
     if (G_UNLIKELY (!str))
       return FALSE;
+    if (!g_utf8_validate (str, -1, NULL)) {
+      g_free (str);
+      return FALSE;
+    }
     g_value_take_string (dest, str);
   }
 
@@ -3754,7 +4058,7 @@ gst_value_serialize_enum (const GValue * value)
   }
 
   g_return_val_if_fail (en, NULL);
-  return g_strdup (en->value_name);
+  return g_strdup (en->value_nick);
 }
 
 static gint
@@ -4119,6 +4423,58 @@ gst_value_is_subset_structure_structure (const GValue * value1,
   return gst_structure_is_subset (s1, s2);
 }
 
+static gboolean
+gst_value_is_subset_list_list (const GValue * value1, const GValue * value2)
+{
+  GstValueList *vlist1 = VALUE_LIST_ARRAY (value1);
+  GstValueList *vlist2 = VALUE_LIST_ARRAY (value2);
+  gint it1, len1, it2, len2;
+
+  len1 = vlist1->len;
+  len2 = vlist2->len;
+
+  /* A list can't be a subset of a smaller list */
+  if (len1 > len2)
+    return FALSE;
+
+  /* Check if all elements of the first list are within the 2nd list */
+  for (it1 = 0; it1 < len1; it1++) {
+    const GValue *child1 = &vlist1->fields[it1];
+    gboolean seen = FALSE;
+
+    for (it2 = 0; it2 < len2; it2++) {
+      const GValue *child2 = &vlist2->fields[it2];
+      if (gst_value_compare (child1, child2) == GST_VALUE_EQUAL) {
+        seen = TRUE;
+        break;
+      }
+    }
+    if (!seen)
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_value_is_subset_list (const GValue * value1, const GValue * value2)
+{
+  GstValueList *vlist2 = VALUE_LIST_ARRAY (value2);
+  gint it2, len2;
+
+  len2 = vlist2->len;
+
+  /* Check whether value1 is within the list */
+  for (it2 = 0; it2 < len2; it2++) {
+    const GValue *child2 = &vlist2->fields[it2];
+    if (gst_value_compare (value1, child2) == GST_VALUE_EQUAL) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
 /**
  * gst_value_is_subset:
  * @value1: a #GValue
@@ -4131,6 +4487,9 @@ gst_value_is_subset_structure_structure (const GValue * value1,
 gboolean
 gst_value_is_subset (const GValue * value1, const GValue * value2)
 {
+  GType type1 = G_VALUE_TYPE (value1);
+  GType type2 = G_VALUE_TYPE (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
@@ -4146,6 +4505,10 @@ gst_value_is_subset (const GValue * value1, const GValue * value2)
   } else if (GST_VALUE_HOLDS_STRUCTURE (value1)
       && GST_VALUE_HOLDS_STRUCTURE (value2)) {
     return gst_value_is_subset_structure_structure (value1, value2);
+  } else if (type2 == GST_TYPE_LIST) {
+    if (type1 == GST_TYPE_LIST)
+      return gst_value_is_subset_list_list (value1, value2);
+    return gst_value_is_subset_list (value1, value2);
   }
 
   /*
@@ -4584,6 +4947,118 @@ gst_value_intersect_double_range_double_range (GValue * dest,
 }
 
 static gboolean
+gst_value_intersect_list_list (GValue * dest, const GValue * value1,
+    const GValue * value2)
+{
+  guint8 tmpfield[16];          /* Check up to 128 values */
+  guint8 *bitfield;
+  gboolean alloc_bitfield = FALSE;
+  gboolean res = FALSE;
+  GValue *tmp;
+  GType type1, type2;
+  guint it1, len1, start2, it2, len2, itar;
+  GstValueList *vlist = NULL;
+
+  /* If they don't have the same basic type, all bets are off :) */
+  if (!gst_value_list_or_array_get_basic_type (value1, &type1) ||
+      !gst_value_list_or_array_get_basic_type (value2, &type2) ||
+      type1 != type2)
+    return FALSE;
+
+  len1 = VALUE_LIST_SIZE (value1);
+  len2 = VALUE_LIST_SIZE (value2);
+
+  /* Fast-path with no dest (i.e. only interested in knowing whether
+   * both lists intersected without wanting the result) */
+  if (!dest) {
+    for (it1 = 0; it1 < len1; it1++) {
+      const GValue *item1 = VALUE_LIST_GET_VALUE (value1, it1);
+      for (it2 = 0; it2 < len2; it2++) {
+        const GValue *item2 = VALUE_LIST_GET_VALUE (value2, it2);
+        if (gst_value_intersect (NULL, item1, item2)) {
+          res = TRUE;
+          goto beach;
+        }
+      }
+    }
+    goto beach;
+  }
+#define is_visited(idx) (bitfield[(idx) >> 3]    & (1 << ((idx) & 0x7)))
+#define mark_visited(idx) (bitfield[(idx) >> 3] |= (1 << ((idx) & 0x7)))
+
+  /* Bitfield to avoid double-visiting */
+  if (G_UNLIKELY (len2 > 128)) {
+    alloc_bitfield = TRUE;
+    bitfield = g_malloc0 ((len2 / 8) + 1);
+    GST_CAT_LOG (GST_CAT_PERFORMANCE,
+        "Allocation for GstValueList with more than 128 members");
+  } else {
+    bitfield = &tmpfield[0];
+    memset (bitfield, 0, 16);
+  }
+
+
+  /* When doing list<->list intersections, there is a greater
+   * probability of ending up with a list than with a single value.
+   * Furthermore, the biggest that list can be will the smallest list
+   * (i.e. intersects fully).
+   * Therefore we pre-allocate a GstValueList of that size. */
+  vlist = _gst_value_list_new (MIN (len1, len2));
+
+  itar = 0;
+  tmp = &vlist->fields[0];
+  start2 = 0;
+
+  for (it1 = 0; it1 < len1; it1++) {
+    const GValue *item1 = VALUE_LIST_GET_VALUE (value1, it1);
+    for (it2 = start2; it2 < len2; it2++) {
+      const GValue *item2;
+      if (is_visited (it2))
+        continue;
+      item2 = VALUE_LIST_GET_VALUE (value2, it2);
+
+      if (gst_value_intersect (tmp, item1, item2)) {
+        res = TRUE;
+        mark_visited (it2);
+        /* Increment our inner-loop starting point */
+        if (it2 == start2)
+          start2++;
+
+        /* Move our collection value */
+        itar += 1;
+        tmp = &vlist->fields[itar];
+        vlist->len += 1;
+
+        /* We can stop iterating the second part now that we've matched */
+        break;
+      }
+    }
+  }
+
+#undef is_visited
+#undef mark_visited
+
+  if (res) {
+    /* If we end up with a single value in the list, just use that
+     * value. Else use the list */
+    if (vlist->len == 1) {
+      gst_value_move (dest, &vlist->fields[0]);
+      g_free (vlist);
+    } else {
+      dest->g_type = GST_TYPE_LIST;
+      dest->data[0].v_pointer = vlist;
+    }
+  } else {
+    g_free (vlist);
+  }
+
+beach:
+  if (alloc_bitfield)
+    g_free (bitfield);
+  return res;
+}
+
+static gboolean
 gst_value_intersect_list (GValue * dest, const GValue * value1,
     const GValue * value2)
 {
@@ -4591,6 +5066,11 @@ gst_value_intersect_list (GValue * dest, const GValue * value1,
   GValue intersection = { 0, };
   gboolean ret = FALSE;
 
+  /* Use optimized list-list intersection */
+  if (G_VALUE_TYPE (value2) == GST_TYPE_LIST) {
+    return gst_value_intersect_list_list (dest, value1, value2);
+  }
+
   size = VALUE_LIST_SIZE (value1);
   for (i = 0; i < size; i++) {
     const GValue *cur = VALUE_LIST_GET_VALUE (value1, i);
@@ -4669,25 +5149,21 @@ gst_value_intersect_fraction_fraction_range (GValue * dest, const GValue * src1,
 {
   gint res1, res2;
   GValue *vals;
-  GstValueCompareFunc compare;
 
   vals = src2->data[0].v_pointer;
 
   if (vals == NULL)
     return FALSE;
 
-  if ((compare = gst_value_get_compare_func (src1))) {
-    res1 = gst_value_compare_with_func (&vals[0], src1, compare);
-    res2 = gst_value_compare_with_func (&vals[1], src1, compare);
+  res1 = gst_value_compare_fraction (&vals[0], src1);
+  res2 = gst_value_compare_fraction (&vals[1], src1);
 
-    if ((res1 == GST_VALUE_EQUAL || res1 == GST_VALUE_LESS_THAN) &&
-        (res2 == GST_VALUE_EQUAL || res2 == GST_VALUE_GREATER_THAN)) {
-      if (dest)
-        gst_value_init_and_copy (dest, src1);
-      return TRUE;
-    }
+  if ((res1 == GST_VALUE_EQUAL || res1 == GST_VALUE_LESS_THAN) &&
+      (res2 == GST_VALUE_EQUAL || res2 == GST_VALUE_GREATER_THAN)) {
+    if (dest)
+      gst_value_init_and_copy (dest, src1);
+    return TRUE;
   }
-
   return FALSE;
 }
 
@@ -4699,45 +5175,42 @@ gst_value_intersect_fraction_range_fraction_range (GValue * dest,
   GValue *max;
   gint res;
   GValue *vals1, *vals2;
-  GstValueCompareFunc compare;
 
   vals1 = src1->data[0].v_pointer;
   vals2 = src2->data[0].v_pointer;
   g_return_val_if_fail (vals1 != NULL && vals2 != NULL, FALSE);
 
-  if ((compare = gst_value_get_compare_func (&vals1[0]))) {
-    /* min = MAX (src1.start, src2.start) */
-    res = gst_value_compare_with_func (&vals1[0], &vals2[0], compare);
-    g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
-    if (res == GST_VALUE_LESS_THAN)
-      min = &vals2[0];          /* Take the max of the 2 */
-    else
-      min = &vals1[0];
+  /* min = MAX (src1.start, src2.start) */
+  res = gst_value_compare_fraction (&vals1[0], &vals2[0]);
+  g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
+  if (res == GST_VALUE_LESS_THAN)
+    min = &vals2[0];            /* Take the max of the 2 */
+  else
+    min = &vals1[0];
 
-    /* max = MIN (src1.end, src2.end) */
-    res = gst_value_compare_with_func (&vals1[1], &vals2[1], compare);
-    g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
-    if (res == GST_VALUE_GREATER_THAN)
-      max = &vals2[1];          /* Take the min of the 2 */
-    else
-      max = &vals1[1];
+  /* max = MIN (src1.end, src2.end) */
+  res = gst_value_compare_fraction (&vals1[1], &vals2[1]);
+  g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
+  if (res == GST_VALUE_GREATER_THAN)
+    max = &vals2[1];            /* Take the min of the 2 */
+  else
+    max = &vals1[1];
 
-    res = gst_value_compare_with_func (min, max, compare);
-    g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
-    if (res == GST_VALUE_LESS_THAN) {
-      if (dest) {
-        g_value_init (dest, GST_TYPE_FRACTION_RANGE);
-        vals1 = dest->data[0].v_pointer;
-        g_value_copy (min, &vals1[0]);
-        g_value_copy (max, &vals1[1]);
-      }
-      return TRUE;
-    }
-    if (res == GST_VALUE_EQUAL) {
-      if (dest)
-        gst_value_init_and_copy (dest, min);
-      return TRUE;
+  res = gst_value_compare_fraction (min, max);
+  g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
+  if (res == GST_VALUE_LESS_THAN) {
+    if (dest) {
+      g_value_init (dest, GST_TYPE_FRACTION_RANGE);
+      vals1 = dest->data[0].v_pointer;
+      g_value_copy (min, &vals1[0]);
+      g_value_copy (max, &vals1[1]);
     }
+    return TRUE;
+  }
+  if (res == GST_VALUE_EQUAL) {
+    if (dest)
+      gst_value_init_and_copy (dest, min);
+    return TRUE;
   }
 
   return FALSE;
@@ -5270,21 +5743,17 @@ gst_value_subtract_fraction_fraction_range (GValue * dest,
 {
   const GValue *min = gst_value_get_fraction_range_min (subtrahend);
   const GValue *max = gst_value_get_fraction_range_max (subtrahend);
-  GstValueCompareFunc compare;
 
-  if ((compare = gst_value_get_compare_func (minuend))) {
-    /* subtracting a range from an fraction only works if the fraction
-     * is not in the range */
-    if (gst_value_compare_with_func (minuend, min, compare) ==
-        GST_VALUE_LESS_THAN ||
-        gst_value_compare_with_func (minuend, max, compare) ==
-        GST_VALUE_GREATER_THAN) {
-      /* and the result is the value */
-      if (dest)
-        gst_value_init_and_copy (dest, minuend);
-      return TRUE;
-    }
+  /* subtracting a range from an fraction only works if the fraction
+   * is not in the range */
+  if (gst_value_compare_fraction (minuend, min) == GST_VALUE_LESS_THAN ||
+      gst_value_compare_fraction (minuend, max) == GST_VALUE_GREATER_THAN) {
+    /* and the result is the value */
+    if (dest)
+      gst_value_init_and_copy (dest, minuend);
+    return TRUE;
   }
+
   return FALSE;
 }
 
@@ -5313,25 +5782,21 @@ gst_value_subtract_fraction_range_fraction_range (GValue * dest,
   GValue v1 = { 0, };
   GValue v2 = { 0, };
   GValue *pv1, *pv2;            /* yeah, hungarian! */
-  GstValueCompareFunc compare;
 
   g_return_val_if_fail (min1 != NULL && max1 != NULL, FALSE);
   g_return_val_if_fail (min2 != NULL && max2 != NULL, FALSE);
 
-  compare = gst_value_get_compare_func (min1);
-  g_return_val_if_fail (compare, FALSE);
-
-  cmp1 = gst_value_compare_with_func (max2, max1, compare);
+  cmp1 = gst_value_compare_fraction (max2, max1);
   g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE);
   if (cmp1 == GST_VALUE_LESS_THAN)
     max1 = max2;
-  cmp1 = gst_value_compare_with_func (min1, min2, compare);
+  cmp1 = gst_value_compare_fraction (min1, min2);
   g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE);
   if (cmp1 == GST_VALUE_GREATER_THAN)
     min2 = min1;
 
-  cmp1 = gst_value_compare_with_func (min1, max1, compare);
-  cmp2 = gst_value_compare_with_func (min2, max2, compare);
+  cmp1 = gst_value_compare_fraction (min1, max1);
+  cmp2 = gst_value_compare_fraction (min2, max2);
 
   if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) {
     pv1 = &v1;
@@ -5441,10 +5906,6 @@ gst_value_list_equals_range (const GValue * list, const GValue * value)
   const GValue *first;
   guint list_size, n;
 
-  g_assert (G_IS_VALUE (list));
-  g_assert (G_IS_VALUE (value));
-  g_assert (GST_VALUE_HOLDS_LIST (list));
-
   /* TODO: compare against an empty list ? No type though... */
   list_size = VALUE_LIST_SIZE (list);
   if (list_size == 0)
@@ -5453,7 +5914,7 @@ gst_value_list_equals_range (const GValue * list, const GValue * value)
   /* compare the basic types - they have to match */
   first = VALUE_LIST_GET_VALUE (list, 0);
 #define CHECK_TYPES(type,prefix) \
-  (prefix##_VALUE_HOLDS_##type(first) && GST_VALUE_HOLDS_##type##_RANGE (value))
+  ((first) && G_VALUE_TYPE(first) == prefix##_TYPE_##type && GST_VALUE_HOLDS_##type##_RANGE (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);
@@ -5594,30 +6055,6 @@ gst_value_compare (const GValue * value1, const GValue * value2)
   return _gst_value_compare_nolist (value1, value2);
 }
 
-/*
- * gst_value_compare_with_func:
- * @value1: a value to compare
- * @value2: another value to compare
- * @compare: compare function
- *
- * Compares @value1 and @value2 using the @compare function. Works like
- * gst_value_compare() but allows to save time determining the compare function
- * a multiple times.
- *
- * Returns: comparison result
- */
-static gint
-gst_value_compare_with_func (const GValue * value1, const GValue * value2,
-    GstValueCompareFunc compare)
-{
-  g_assert (compare);
-
-  if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
-    return GST_VALUE_UNORDERED;
-
-  return compare (value1, value2);
-}
-
 /* union */
 
 /**
@@ -5762,19 +6199,18 @@ gst_value_can_intersect (const GValue * value1, const GValue * value2)
 
   if (G_UNLIKELY (GST_VALUE_HOLDS_FLAG_SET (value1) &&
           GST_VALUE_HOLDS_FLAG_SET (value2))) {
-    GType type1, type2, flagset_type;
+    GType flagset_type;
 
-    type1 = G_VALUE_TYPE (value1);
-    type2 = G_VALUE_TYPE (value2);
     flagset_type = GST_TYPE_FLAG_SET;
 
     /* Allow intersection with the generic FlagSet type, on one
      * side, but not 2 different subtypes - that makes no sense */
-    if (type1 == type2 || type1 == flagset_type || type2 == flagset_type)
+    if (type1 == flagset_type || type2 == flagset_type)
       return TRUE;
   }
 
-  /* check registered intersect functions */
+  /* check registered intersect functions (only different gtype are checked at
+   * this point) */
   len = gst_value_intersect_funcs->len;
   for (i = 0; i < len; i++) {
     intersect_info = &g_array_index (gst_value_intersect_funcs,
@@ -5829,15 +6265,36 @@ gst_value_intersect (GValue * dest, const GValue * value1,
     return TRUE;
   }
 
-  len = gst_value_intersect_funcs->len;
-  for (i = 0; i < len; i++) {
-    intersect_info = &g_array_index (gst_value_intersect_funcs,
-        GstValueIntersectInfo, i);
-    if (intersect_info->type1 == type1 && intersect_info->type2 == type2) {
-      return intersect_info->func (dest, value1, value2);
-    }
-    if (intersect_info->type1 == type2 && intersect_info->type2 == type1) {
-      return intersect_info->func (dest, value2, value1);
+  if (type1 == type2) {
+    /* Equal type comparison */
+    if (type1 == GST_TYPE_INT_RANGE)
+      return gst_value_intersect_int_range_int_range (dest, value1, value2);
+    if (type1 == GST_TYPE_INT64_RANGE)
+      return gst_value_intersect_int64_range_int64_range (dest, value1, value2);
+    if (type1 == GST_TYPE_DOUBLE_RANGE)
+      return gst_value_intersect_double_range_double_range (dest, value1,
+          value2);
+    if (type1 == GST_TYPE_ARRAY)
+      return gst_value_intersect_array (dest, value1, value2);
+    if (type1 == GST_TYPE_FRACTION_RANGE)
+      return gst_value_intersect_fraction_range_fraction_range (dest, value1,
+          value2);
+    if (type1 == GST_TYPE_FLAG_SET)
+      return gst_value_intersect_flagset_flagset (dest, value1, value2);
+    if (type1 == GST_TYPE_STRUCTURE)
+      return gst_value_intersect_structure_structure (dest, value1, value2);
+  } else {
+    /* Different type comparison */
+    len = gst_value_intersect_funcs->len;
+    for (i = 0; i < len; i++) {
+      intersect_info = &g_array_index (gst_value_intersect_funcs,
+          GstValueIntersectInfo, i);
+      if (intersect_info->type1 == type1 && intersect_info->type2 == type2) {
+        return intersect_info->func (dest, value1, value2);
+      }
+      if (intersect_info->type1 == type2 && intersect_info->type2 == type1) {
+        return intersect_info->func (dest, value2, value1);
+      }
     }
   }
 
@@ -6049,10 +6506,24 @@ gst_value_register (const GstValueTable * table)
 void
 gst_value_init_and_copy (GValue * dest, const GValue * src)
 {
+  GType type;
+
   g_return_if_fail (G_IS_VALUE (src));
   g_return_if_fail (dest != NULL);
 
-  g_value_init (dest, G_VALUE_TYPE (src));
+  type = G_VALUE_TYPE (src);
+  /* We need to shortcut GstValueList/GstValueArray copying because:
+   * * g_value_init would end up allocating something
+   * * which g_value_copy would then free and re-alloc.
+   *
+   * Instead directly call the copy */
+  if (type == GST_TYPE_LIST || type == GST_TYPE_ARRAY) {
+    dest->g_type = type;
+    gst_value_copy_list_or_array (src, dest);
+    return;
+  }
+
+  g_value_init (dest, type);
   g_value_copy (src, dest);
 }
 
@@ -6143,19 +6614,80 @@ gst_value_deserialize (GValue * dest, const gchar * src)
   type = G_VALUE_TYPE (dest);
 
   best = gst_value_hash_lookup_type (type);
-  if (G_UNLIKELY (!best || !best->deserialize)) {
+  if (G_UNLIKELY (!best || (!best->deserialize
+              && !best->deserialize_with_pspec))) {
     len = gst_value_table->len;
     best = NULL;
     for (i = 0; i < len; i++) {
       table = &g_array_index (gst_value_table, GstValueTable, i);
-      if (table->deserialize && g_type_is_a (type, table->type)) {
+      if ((table->deserialize || table->deserialize_with_pspec) &&
+          g_type_is_a (type, table->type)) {
         if (!best || g_type_is_a (table->type, best->type))
           best = table;
       }
     }
   }
-  if (G_LIKELY (best))
-    return best->deserialize (dest, src);
+  if (G_LIKELY (best)) {
+    if (best->deserialize_with_pspec)
+      return best->deserialize_with_pspec (dest, src, NULL);
+    else
+      return best->deserialize (dest, src);
+  }
+
+  return FALSE;
+}
+
+/**
+ * gst_value_deserialize_with_pspec:
+ * @dest: (out caller-allocates): #GValue to fill with contents of
+ *     deserialization
+ * @src: string to deserialize
+ * @pspec: (nullable): the #GParamSpec describing the expected value
+ *
+ * Tries to deserialize a string into the type specified by the given GValue.
+ * @pspec may be used to guide the deserializing of nested members.
+ * If the operation succeeds, %TRUE is returned, %FALSE otherwise.
+ *
+ * Returns: %TRUE on success
+ * Since: 1.20
+ */
+gboolean
+gst_value_deserialize_with_pspec (GValue * dest, const gchar * src,
+    GParamSpec * pspec)
+{
+  GstValueTable *table, *best;
+  guint i, len;
+  GType type;
+
+  g_return_val_if_fail (src != NULL, FALSE);
+  g_return_val_if_fail (G_IS_VALUE (dest), FALSE);
+
+  if (pspec)
+    g_return_val_if_fail (G_VALUE_TYPE (dest) ==
+        G_PARAM_SPEC_VALUE_TYPE (pspec), FALSE);
+
+  type = G_VALUE_TYPE (dest);
+
+  best = gst_value_hash_lookup_type (type);
+  if (G_UNLIKELY (!best || (!best->deserialize
+              && !best->deserialize_with_pspec))) {
+    len = gst_value_table->len;
+    best = NULL;
+    for (i = 0; i < len; i++) {
+      table = &g_array_index (gst_value_table, GstValueTable, i);
+      if ((table->deserialize || table->deserialize_with_pspec) &&
+          g_type_is_a (type, table->type)) {
+        if (!best || g_type_is_a (table->type, best->type))
+          best = table;
+      }
+    }
+  }
+  if (G_LIKELY (best)) {
+    if (best->deserialize_with_pspec)
+      return best->deserialize_with_pspec (dest, src, pspec);
+    else
+      return best->deserialize (dest, src);
+  }
 
   return FALSE;
 }
@@ -6329,22 +6861,20 @@ static gchar *
 gst_value_collect_fraction (GValue * value, guint n_collect_values,
     GTypeCValue * collect_values, guint collect_flags)
 {
-  if (n_collect_values != 2)
-    return g_strdup_printf ("not enough value locations for `%s' passed",
-        G_VALUE_TYPE_NAME (value));
-  if (collect_values[1].v_int == 0)
-    return g_strdup_printf ("passed '0' as denominator for `%s'",
-        G_VALUE_TYPE_NAME (value));
-  if (collect_values[0].v_int < -G_MAXINT)
-    return
-        g_strdup_printf
-        ("passed value smaller than -G_MAXINT as numerator for `%s'",
-        G_VALUE_TYPE_NAME (value));
-  if (collect_values[1].v_int < -G_MAXINT)
-    return
-        g_strdup_printf
-        ("passed value smaller than -G_MAXINT as denominator for `%s'",
-        G_VALUE_TYPE_NAME (value));
+  g_return_val_if_fail (n_collect_values == 2,
+      g_strdup_printf ("not enough value locations for `%s' passed",
+          G_VALUE_TYPE_NAME (value)));
+  g_return_val_if_fail (collect_values[1].v_int != 0,
+      g_strdup_printf ("passed '0' as denominator for `%s'",
+          G_VALUE_TYPE_NAME (value)));
+  g_return_val_if_fail (collect_values[0].v_int >= -G_MAXINT,
+      g_strdup_printf
+      ("passed value smaller than -G_MAXINT as numerator for `%s'",
+          G_VALUE_TYPE_NAME (value)));
+  g_return_val_if_fail (collect_values[1].v_int >= -G_MAXINT,
+      g_strdup_printf
+      ("passed value smaller than -G_MAXINT as denominator for `%s'",
+          G_VALUE_TYPE_NAME (value)));
 
   gst_value_set_fraction (value,
       collect_values[0].v_int, collect_values[1].v_int);
@@ -6359,12 +6889,12 @@ gst_value_lcopy_fraction (const GValue * value, guint n_collect_values,
   gint *numerator = collect_values[0].v_pointer;
   gint *denominator = collect_values[1].v_pointer;
 
-  if (!numerator)
-    return g_strdup_printf ("numerator for `%s' passed as NULL",
-        G_VALUE_TYPE_NAME (value));
-  if (!denominator)
-    return g_strdup_printf ("denominator for `%s' passed as NULL",
-        G_VALUE_TYPE_NAME (value));
+  g_return_val_if_fail (numerator != NULL,
+      g_strdup_printf ("numerator for `%s' passed as NULL",
+          G_VALUE_TYPE_NAME (value)));
+  g_return_val_if_fail (denominator != NULL,
+      g_strdup_printf ("denominator for `%s' passed as NULL",
+          G_VALUE_TYPE_NAME (value)));
 
   *numerator = value->data[0].v_int;
   *denominator = value->data[1].v_int;
@@ -6815,9 +7345,9 @@ 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));
+  g_return_val_if_fail (n_collect_values == 1,
+      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);
 
@@ -6830,9 +7360,9 @@ gst_value_lcopy_bitmask (const GValue * value, guint n_collect_values,
 {
   guint64 *bitmask = collect_values[0].v_pointer;
 
-  if (!bitmask)
-    return g_strdup_printf ("value for `%s' passed as NULL",
-        G_VALUE_TYPE_NAME (value));
+  g_return_val_if_fail (bitmask != NULL,
+      g_strdup_printf ("value for `%s' passed as NULL",
+          G_VALUE_TYPE_NAME (value)));
 
   *bitmask = value->data[0].v_uint64;
 
@@ -6968,9 +7498,9 @@ static gchar *
 gst_value_collect_flagset (GValue * value, guint n_collect_values,
     GTypeCValue * collect_values, guint collect_flags)
 {
-  if (n_collect_values != 2)
-    return g_strdup_printf ("not enough value locations for `%s' passed",
-        G_VALUE_TYPE_NAME (value));
+  g_return_val_if_fail (n_collect_values == 2,
+      g_strdup_printf ("not enough value locations for `%s' passed",
+          G_VALUE_TYPE_NAME (value)));
 
   gst_value_set_flagset (value,
       (guint) collect_values[0].v_int, (guint) collect_values[1].v_int);
@@ -7325,7 +7855,7 @@ GType _gst_ ## type ## _type = 0;                               \
                                                                 \
 GType gst_ ## type ## _get_type (void)                          \
 {                                                               \
-  static volatile GType gst_ ## type ## _type = 0;              \
+  static GType gst_ ## type ## _type = 0;              \
                                                                 \
   if (g_once_init_enter (&gst_ ## type ## _type)) {             \
     GType _type;                                                \
@@ -7456,7 +7986,8 @@ gst_g_thread_get_type (void)
   return G_TYPE_THREAD;
 }
 
-#define SERIAL_VTABLE(t,c,s,d) { t, c, s, d }
+#define SERIAL_VTABLE(t,c,s,d) { t, c, s, d, NULL }
+#define SERIAL_VTABLE_PSPEC(t,c,s,d) { t, c, s, NULL, d }
 
 #define REGISTER_SERIALIZATION_CONST(_gtype, _type)                     \
 G_STMT_START {                                                          \
@@ -7475,6 +8006,15 @@ G_STMT_START {                                                          \
   gst_value_register (&gst_value);                                      \
 } G_STMT_END
 
+#define REGISTER_SERIALIZATION_WITH_PSPEC(_gtype, _type)                \
+G_STMT_START {                                                          \
+  static GstValueTable gst_value =                                      \
+    SERIAL_VTABLE_PSPEC (0, gst_value_compare_ ## _type,                \
+    gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type);    \
+  gst_value.type = _gtype;                                              \
+  gst_value_register (&gst_value);                                      \
+} G_STMT_END
+
 #define REGISTER_SERIALIZATION_NO_COMPARE(_gtype, _type)                \
 G_STMT_START {                                                          \
   static GstValueTable gst_value =                                      \
@@ -7498,7 +8038,7 @@ G_STMT_START {                                                          \
 
 static const gint GST_VALUE_TABLE_DEFAULT_SIZE = 40;
 static const gint GST_VALUE_UNION_TABLE_DEFAULT_SIZE = 8;
-static const gint GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE = 16;
+static const gint GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE = 4;
 static const gint GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE = 16;
 
 void
@@ -7519,8 +8059,6 @@ _priv_gst_value_initialize (void)
   REGISTER_SERIALIZATION (gst_int64_range_get_type (), int64_range);
   REGISTER_SERIALIZATION (gst_double_range_get_type (), double_range);
   REGISTER_SERIALIZATION (gst_fraction_range_get_type (), fraction_range);
-  REGISTER_SERIALIZATION (gst_value_list_get_type (), value_list);
-  REGISTER_SERIALIZATION (gst_value_array_get_type (), value_array);
   REGISTER_SERIALIZATION (g_value_array_get_type (), g_value_array);
   REGISTER_SERIALIZATION (gst_buffer_get_type (), buffer);
   REGISTER_SERIALIZATION (gst_sample_get_type (), sample);
@@ -7563,6 +8101,9 @@ _priv_gst_value_initialize (void)
 
   REGISTER_SERIALIZATION (G_TYPE_GTYPE, gtype);
 
+  REGISTER_SERIALIZATION_WITH_PSPEC (gst_value_list_get_type (), value_list);
+  REGISTER_SERIALIZATION_WITH_PSPEC (gst_value_array_get_type (), value_array);
+
   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,
@@ -7617,29 +8158,17 @@ _priv_gst_value_initialize (void)
   g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_FLAG_SET,
       gst_value_transform_string_flagset);
 
+  /* Only register intersection functions for *different* types.
+   * Identical type intersection should be specified directly in
+   * gst_value_intersect() */
   gst_value_register_intersect_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
       gst_value_intersect_int_int_range);
-  gst_value_register_intersect_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
-      gst_value_intersect_int_range_int_range);
   gst_value_register_intersect_func (G_TYPE_INT64, GST_TYPE_INT64_RANGE,
       gst_value_intersect_int64_int64_range);
-  gst_value_register_intersect_func (GST_TYPE_INT64_RANGE,
-      GST_TYPE_INT64_RANGE, gst_value_intersect_int64_range_int64_range);
   gst_value_register_intersect_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
       gst_value_intersect_double_double_range);
-  gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE,
-      GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range);
-  gst_value_register_intersect_func (GST_TYPE_ARRAY, GST_TYPE_ARRAY,
-      gst_value_intersect_array);
   gst_value_register_intersect_func (GST_TYPE_FRACTION,
       GST_TYPE_FRACTION_RANGE, gst_value_intersect_fraction_fraction_range);
-  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_FLAG_SET, GST_TYPE_FLAG_SET,
-      gst_value_intersect_flagset_flagset);
-  gst_value_register_intersect_func (GST_TYPE_STRUCTURE, GST_TYPE_STRUCTURE,
-      gst_value_intersect_structure_structure);
 
   gst_value_register_subtract_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
       gst_value_subtract_int_int_range);
@@ -7667,9 +8196,8 @@ _priv_gst_value_initialize (void)
       GST_TYPE_FRACTION_RANGE,
       gst_value_subtract_fraction_range_fraction_range);
 
-  /* see bug #317246, #64994, #65041 */
   {
-    volatile GType date_type = G_TYPE_DATE;
+    GType date_type = G_TYPE_DATE;
 
     g_type_name (date_type);
   }
index 7eeaf39..4c5bf29 100644 (file)
@@ -65,7 +65,7 @@ G_BEGIN_DECLS
  * GST_FOURCC_FORMAT: (skip):
  *
  * Can be used together with #GST_FOURCC_ARGS to properly output a
- * #guint32 fourcc value in a printf()-style text message.
+ * #guint32 fourcc value in a printf\()-style text message.
  *
  * |[
  * printf ("fourcc: %" GST_FOURCC_FORMAT "\n", GST_FOURCC_ARGS (fcc));
@@ -79,7 +79,7 @@ G_BEGIN_DECLS
  * @fourcc: a #guint32 fourcc value to output
  *
  * Can be used together with #GST_FOURCC_FORMAT to properly output a
- * #guint32 fourcc value in a printf()-style text message.
+ * #guint32 fourcc value in a printf\()-style text message.
  */
 
 #define __GST_PRINT_CHAR(c) \
@@ -95,7 +95,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_INT_RANGE value.
  */
-#define GST_VALUE_HOLDS_INT_RANGE(x)      ((x) != NULL && G_VALUE_TYPE(x) == _gst_int_range_type)
+#define GST_VALUE_HOLDS_INT_RANGE(x)      ((gpointer)(x) != NULL && G_VALUE_TYPE(x) == _gst_int_range_type)
 
 /**
  * GST_VALUE_HOLDS_INT64_RANGE:
@@ -103,7 +103,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_INT64_RANGE value.
  */
-#define GST_VALUE_HOLDS_INT64_RANGE(x)    ((x) != NULL && G_VALUE_TYPE(x) == _gst_int64_range_type)
+#define GST_VALUE_HOLDS_INT64_RANGE(x)    ((gpointer)(x) != NULL && G_VALUE_TYPE(x) == _gst_int64_range_type)
 
 /**
  * GST_VALUE_HOLDS_DOUBLE_RANGE:
@@ -111,7 +111,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_DOUBLE_RANGE value.
  */
-#define GST_VALUE_HOLDS_DOUBLE_RANGE(x)   ((x) != NULL && G_VALUE_TYPE(x) == _gst_double_range_type)
+#define GST_VALUE_HOLDS_DOUBLE_RANGE(x)   ((gpointer)(x) != NULL && G_VALUE_TYPE(x) == _gst_double_range_type)
 
 /**
  * GST_VALUE_HOLDS_FRACTION_RANGE:
@@ -119,7 +119,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_FRACTION_RANGE value.
  */
-#define GST_VALUE_HOLDS_FRACTION_RANGE(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_fraction_range_type)
+#define GST_VALUE_HOLDS_FRACTION_RANGE(x) ((gpointer)(x) != NULL && G_VALUE_TYPE(x) == _gst_fraction_range_type)
 
 /**
  * GST_VALUE_HOLDS_LIST:
@@ -127,7 +127,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_LIST value.
  */
-#define GST_VALUE_HOLDS_LIST(x)         ((x) != NULL && G_VALUE_TYPE(x) == _gst_value_list_type)
+#define GST_VALUE_HOLDS_LIST(x)         ((gpointer)(x) != NULL && G_VALUE_TYPE(x) == _gst_value_list_type)
 
 /**
  * GST_VALUE_HOLDS_ARRAY:
@@ -135,7 +135,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_ARRAY value.
  */
-#define GST_VALUE_HOLDS_ARRAY(x)        ((x) != NULL && G_VALUE_TYPE(x) == _gst_value_array_type)
+#define GST_VALUE_HOLDS_ARRAY(x)        ((gpointer)(x) != NULL && G_VALUE_TYPE(x) == _gst_value_array_type)
 
 /**
  * GST_VALUE_HOLDS_CAPS:
@@ -143,7 +143,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_CAPS value.
  */
-#define GST_VALUE_HOLDS_CAPS(x)         ((x) != NULL && G_VALUE_TYPE(x) == _gst_caps_type)
+#define GST_VALUE_HOLDS_CAPS(x)         ((gpointer)(x) != NULL && G_VALUE_TYPE(x) == _gst_caps_type)
 
 /**
  * GST_VALUE_HOLDS_STRUCTURE:
@@ -151,7 +151,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_STRUCTURE value.
  */
-#define GST_VALUE_HOLDS_STRUCTURE(x)            (G_VALUE_HOLDS((x), _gst_structure_type))
+#define GST_VALUE_HOLDS_STRUCTURE(x)      ((gpointer)(x) != NULL && G_VALUE_TYPE(x) == _gst_structure_type)
 
 /**
  * GST_VALUE_HOLDS_CAPS_FEATURES:
@@ -159,7 +159,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_CAPS_FEATURES value.
  */
-#define GST_VALUE_HOLDS_CAPS_FEATURES(x)        (G_VALUE_HOLDS((x), _gst_caps_features_type))
+#define GST_VALUE_HOLDS_CAPS_FEATURES(x)  ((gpointer)(x) != NULL && G_VALUE_TYPE(x) == _gst_caps_features_type)
 
 /**
  * GST_VALUE_HOLDS_BUFFER:
@@ -167,7 +167,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_BUFFER value.
  */
-#define GST_VALUE_HOLDS_BUFFER(x)       ((x) != NULL && G_VALUE_TYPE(x) == _gst_buffer_type)
+#define GST_VALUE_HOLDS_BUFFER(x)       ((gpointer)(x) != NULL && G_VALUE_TYPE(x) == _gst_buffer_type)
 
 /**
  * GST_VALUE_HOLDS_SAMPLE:
@@ -175,7 +175,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_SAMPLE value.
  */
-#define GST_VALUE_HOLDS_SAMPLE(x)       ((x) != NULL && G_VALUE_TYPE(x) == _gst_sample_type)
+#define GST_VALUE_HOLDS_SAMPLE(x)       ((gpointer)(x) != NULL && G_VALUE_TYPE(x) == _gst_sample_type)
 
 /**
  * GST_VALUE_HOLDS_FRACTION:
@@ -183,7 +183,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_FRACTION value.
  */
-#define GST_VALUE_HOLDS_FRACTION(x)     ((x) != NULL && G_VALUE_TYPE(x) == _gst_fraction_type)
+#define GST_VALUE_HOLDS_FRACTION(x)     ((gpointer)(x) != NULL && G_VALUE_TYPE(x) == _gst_fraction_type)
 
 /**
  * GST_VALUE_HOLDS_DATE_TIME:
@@ -191,7 +191,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_DATE_TIME value.
  */
-#define GST_VALUE_HOLDS_DATE_TIME(x)    ((x) != NULL && G_VALUE_TYPE(x) == _gst_date_time_type)
+#define GST_VALUE_HOLDS_DATE_TIME(x)    ((gpointer)(x) != NULL && G_VALUE_TYPE(x) == _gst_date_time_type)
 
 /**
  * GST_VALUE_HOLDS_BITMASK:
@@ -199,7 +199,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_BITMASK value.
  */
-#define GST_VALUE_HOLDS_BITMASK(x)      ((x) != NULL && G_VALUE_TYPE(x) == _gst_bitmask_type)
+#define GST_VALUE_HOLDS_BITMASK(x)      ((gpointer)(x) != NULL && G_VALUE_TYPE(x) == _gst_bitmask_type)
 
 /**
  * GST_VALUE_HOLDS_FLAG_SET:
@@ -209,7 +209,7 @@ G_BEGIN_DECLS
  *
  * Since: 1.6
  */
-#define GST_VALUE_HOLDS_FLAG_SET(x)     (G_TYPE_CHECK_VALUE_TYPE ((x), GST_TYPE_FLAG_SET))
+#define GST_VALUE_HOLDS_FLAG_SET(x)     (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE ((x))) == GST_TYPE_FLAG_SET)
 
 /**
  * GST_FLAG_SET_MASK_EXACT: (value 4294967295) (type guint)
@@ -225,6 +225,12 @@ G_BEGIN_DECLS
 GST_API GType _gst_int_range_type;
 
 /**
+ * GstIntRange:
+ *
+ * A fundamental type that describes a #gint range
+ */
+
+/**
  * GST_TYPE_INT_RANGE:
  *
  * a #GValue type that represents an integer range
@@ -236,6 +242,12 @@ GST_API GType _gst_int_range_type;
 GST_API GType _gst_int64_range_type;
 
 /**
+ * GstInt64Range:
+ *
+ * A fundamental type that describes a #gint64 range
+ */
+
+/**
  * GST_TYPE_INT64_RANGE:
  *
  * a #GValue type that represents an #gint64 range
@@ -247,6 +259,12 @@ GST_API GType _gst_int64_range_type;
 GST_API GType _gst_double_range_type;
 
 /**
+ * GstDoubleRange:
+ *
+ * A fundamental type that describes a #gdouble range
+ */
+
+/**
  * GST_TYPE_DOUBLE_RANGE:
  *
  * a #GValue type that represents a floating point range with double precision
@@ -258,6 +276,12 @@ GST_API GType _gst_double_range_type;
 GST_API GType _gst_fraction_range_type;
 
 /**
+ * GstFractionRange:
+ *
+ * A fundamental type that describes a #GstFractionRange range
+ */
+
+/**
  * GST_TYPE_FRACTION_RANGE:
  *
  * a #GValue type that represents a GstFraction range
@@ -269,6 +293,12 @@ GST_API GType _gst_fraction_range_type;
 GST_API GType _gst_value_list_type;
 
 /**
+ * GstValueList:
+ *
+ * A fundamental type that describes an unordered list of #GValue
+ */
+
+/**
  * GST_TYPE_LIST:
  *
  * a #GValue type that represents an unordered list of #GValue values. This
@@ -284,6 +314,12 @@ GST_API GType _gst_value_list_type;
 GST_API GType _gst_value_array_type;
 
 /**
+ * GstValueArray:
+ *
+ * A fundamental type that describes an ordered list of #GValue
+ */
+
+/**
  * GST_TYPE_ARRAY:
  *
  * a #GValue type that represents an ordered list of #GValue values. This is
@@ -300,6 +336,13 @@ GST_API GType _gst_value_array_type;
 GST_API GType _gst_fraction_type;
 
 /**
+ * GstFraction:
+ *
+ * A fundamental type that describes a fraction of an integer numerator
+ * over an integer denominator
+ */
+
+/**
  * GST_TYPE_FRACTION:
  *
  * a #GValue type that represents a fraction of an integer numerator over
@@ -313,6 +356,12 @@ GST_API GType _gst_fraction_type;
 GST_API GType _gst_bitmask_type;
 
 /**
+ * GstBitmask:
+ *
+ * A fundamental type that describes a 64-bit bitmask
+ */
+
+/**
  * GST_TYPE_BITMASK:
  *
  * a #GValue type that represents a 64-bit bitmask.
@@ -325,6 +374,13 @@ GST_API GType _gst_bitmask_type;
 GST_API GType _gst_flagset_type;
 
 /**
+ * GstFlagSet:
+ *
+ * A fundamental type that describes a 32-bit flag bitfield, with 32-bit
+ * mask indicating which of the bits in the field are explicitly set.
+ */
+
+/**
  * GST_TYPE_FLAG_SET:
  *
  * a #GValue type that represents a 32-bit flag bitfield, with 32-bit
@@ -416,6 +472,22 @@ typedef gchar *  (* GstValueSerializeFunc)   (const GValue *value1);
 typedef gboolean (* GstValueDeserializeFunc) (GValue       *dest,
                                               const gchar  *s);
 
+/**
+ * GstValueDeserializeWithPSpecFunc:
+ * @dest: a #GValue
+ * @s: a string
+ * @pspec: a #GParamSpec describing the expected value
+ *
+ * Used by gst_value_deserialize_with_pspec() to parse a non-binary form into the #GValue.
+ *
+ * Returns: %TRUE for success
+ * Since: 1.20
+ */
+typedef gboolean (* GstValueDeserializeWithPSpecFunc) (GValue       *dest,
+                                                       const gchar  *s,
+                                                       GParamSpec   *pspec);
+
+
 typedef struct _GstValueTable GstValueTable;
 /**
  * GstValueTable:
@@ -423,6 +495,7 @@ typedef struct _GstValueTable GstValueTable;
  * @compare: a #GstValueCompareFunc
  * @serialize: a #GstValueSerializeFunc
  * @deserialize: a #GstValueDeserializeFunc
+ * @deserialize_with_pspec: a #GstValueDeserializeWithPSpecFunc
  *
  * VTable for the #GValue @type.
  */
@@ -432,8 +505,17 @@ struct _GstValueTable {
   GstValueSerializeFunc serialize;
   GstValueDeserializeFunc deserialize;
 
+  /**
+   * GstValueTable.deserialize_with_pspec:
+   *
+   * a #GstValueDeserializeWithPSpecFunc
+   *
+   * Since: 1.20
+   */
+  GstValueDeserializeWithPSpecFunc deserialize_with_pspec;
+
   /*< private >*/
-  gpointer _gst_reserved [GST_PADDING];
+  gpointer _gst_reserved [GST_PADDING - 1];
 };
 
 GST_API
@@ -482,6 +564,11 @@ GST_API
 gboolean        gst_value_deserialize           (GValue                *dest,
                                                  const gchar           *src);
 
+GST_API
+gboolean        gst_value_deserialize_with_pspec (GValue               *dest,
+                                                 const gchar           *src,
+                                                 GParamSpec            *pspec);
+
 /* list */
 
 GST_API
@@ -508,6 +595,9 @@ GST_API
 const GValue *  gst_value_list_get_value        (const GValue   *value,
                                                  guint          index);
 
+GST_API
+GValue *        gst_value_list_init             (GValue *value,
+                                                guint prealloc);
 /* array */
 
 GST_API
@@ -525,6 +615,9 @@ guint           gst_value_array_get_size        (const GValue   *value);
 GST_API
 const GValue *  gst_value_array_get_value       (const GValue   *value,
                                                  guint          index);
+GST_API
+GValue *        gst_value_array_init            (GValue *value,
+                                                guint prealloc);
 
 /* int range */
 
index 7573b3a..fe3fe95 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef __GST_MATH_COMPAT_H__
 #define __GST_MATH_COMPAT_H__
 
+#ifndef __GI_SCANNER__
+
 /* This header is not included automatically via gst/gst.h, you need to
  * include it explicitly if you need it. */
 
@@ -109,4 +111,6 @@ static union {
 
 G_END_DECLS
 
+#endif /* !__GI_SCANNER__ */
+
 #endif /* __GST_MATH_COMPAT_H__ */
index d19689c..c70998c 100644 (file)
@@ -250,19 +250,29 @@ libgst = library('gstreamer-1.0', gst_sources,
                    + platform_deps,
 )
 
+pkgconfig.generate(libgst,
+  libraries : [glib_dep, gobject_dep],
+  variables : pkgconfig_variables,
+  uninstalled_variables: pkgconfig_uninstalled_variables,
+  subdirs : pkgconfig_subdirs,
+  name : 'gstreamer-1.0',
+  description : 'Streaming media framework',
+)
+
 if build_gir
-  gst_gir_extra_args = gir_init_section + [ '--c-include=gst/gst.h' ]
+  gst_gir_extra_args = gir_init_section + ['--c-include=gst/gst.h']
   if meson.is_subproject()
     # FIXME: There must be a better way to do this
     # Need to pass the include path to find gst/gst.h and gst/gstenumtypes.h (built)
     gst_gir_extra_args += ['--cflags-begin',
       '-I' + meson.current_source_dir() + '/..',
       '-I' + meson.current_build_dir() + '/..',
+      '-DGST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS',
       '--cflags-end']
   endif
 
   gst_incdirs += [configinc]
-  gst_gen_sources += [gnome.generate_gir(libgst,
+  gst_gir = gnome.generate_gir(libgst,
     sources : gst_sources + gst_headers + gst_enums + [gst_version_h],
     namespace : 'Gst',
     nsversion : apiversion,
@@ -272,7 +282,8 @@ if build_gir
     includes : ['GLib-2.0', 'GObject-2.0', 'GModule-2.0' ],
     install : true,
     extra_args : gst_gir_extra_args,
-  )]
+  )
+  gst_gen_sources += gst_gir
 endif
 
 gst_compile_args = []
@@ -287,3 +298,5 @@ gst_dep = declare_dependency(link_with : libgst,
   # Everything that uses libgst needs this built to compile
   sources : gst_gen_sources,
 )
+
+meson.override_dependency('gstreamer-1.0', gst_dep)
diff --git a/gst/parse/.gitignore b/gst/parse/.gitignore
deleted file mode 100644 (file)
index 5faa3b3..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-grammar
-grammar.output
-grammar.tab.c
-grammar.tab.h
-lex.yy.c
-parse.c
-parse_lex.h
-lex.priv_gst_parse_yy.c
-*.bb
-*.bbg
-*.da
-*.gcno
diff --git a/gst/parse/Makefile.am b/gst/parse/Makefile.am
deleted file mode 100644 (file)
index 41e0b90..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-# libgstparse.la is an optionally built helper library linked into core
-noinst_LTLIBRARIES = libgstparse.la
-
-CLEANFILES = grammar.tab.h parse_lex.h grammar.output
-EXTRA_DIST = \
-       get_flex_version.py \
-       grammar.y \
-       parse.l
-
-# uncomment these lines to dist the generated sources
-#BUILT_SOURCES = grammar.tab.h grammar.tab.c parse_lex.h lex.priv_gst_parse_yy.c
-#libgstparse_la_SOURCES = lex.priv_gst_parse_yy.c grammar.tab.c
-
-# uncomment these lines to _NOT_ dist the generated sources
-nodist_libgstparse_la_SOURCES = lex.priv_gst_parse_yy.c grammar.tab.c grammar.tag.h parse_lex.h
-CLEANFILES += grammar.tab.c lex.priv_gst_parse_yy.c
-
-libgstparse_la_CFLAGS = $(GST_ALL_CFLAGS) -DBUILDING_GST -DYYMALLOC=g_malloc -DYYFREE=g_free
-libgstparse_la_LIBADD = $(GST_ALL_LIBS)
-
-noinst_HEADERS = types.h
-
-grammar.tab.c grammar.tab.h: grammar.y
-       $(AM_V_GEN)$(BISON_PATH) -d -v -ppriv_gst_parse_yy $(srcdir)/grammar.y -o grammar.tab.c && \
-       mv grammar.tab.c grammar.tab_tmp.c && \
-       echo '#ifdef HAVE_CONFIG_H' > grammar.tab_tmp2.c && \
-       echo '#include <config.h>' >> grammar.tab_tmp2.c && \
-       echo '#endif' >> grammar.tab_tmp2.c && \
-       cat grammar.tab_tmp.c >> grammar.tab_tmp2.c && \
-       rm grammar.tab_tmp.c && \
-       mv grammar.tab_tmp2.c grammar.tab.c
-
-lex.priv_gst_parse_yy.c parse_lex.h: parse.l grammar.tab.h
-       $(AM_V_GEN)$(FLEX_PATH) --header-file=parse_lex.h -Ppriv_gst_parse_yy $^ && \
-       mv lex.priv_gst_parse_yy.c lex.priv_gst_parse_yy_tmp.c && \
-       echo '#ifdef HAVE_CONFIG_H' > lex.priv_gst_parse_yy_tmp2.c && \
-       echo '#include <config.h>' >> lex.priv_gst_parse_yy_tmp2.c && \
-       echo '#endif' >> lex.priv_gst_parse_yy_tmp2.c && \
-       { grep -q priv_gst_parse_yyget_column parse_lex.h || \
-       { echo 'int priv_gst_parse_yyget_column  (void * yyscanner);' >> lex.priv_gst_parse_yy_tmp2.c && \
-       echo 'void priv_gst_parse_yyset_column (int column_no , void * yyscanner);' >> lex.priv_gst_parse_yy_tmp2.c; }; } && \
-       cat lex.priv_gst_parse_yy_tmp.c >> lex.priv_gst_parse_yy_tmp2.c && \
-       rm lex.priv_gst_parse_yy_tmp.c && \
-       mv lex.priv_gst_parse_yy_tmp2.c lex.priv_gst_parse_yy.c
-
-.NOTPARALLEL:
-
similarity index 96%
rename from gst/parse/grammar.y
rename to gst/parse/grammar.y.in
index 1aa77ed..cf5eb16 100644 (file)
@@ -328,7 +328,7 @@ static void gst_parse_new_child(GstChildProxy *child_proxy, GObject *object,
     GST_CAT_LOG_OBJECT (GST_CAT_PIPELINE, child_proxy, "parsing delayed property %s as a %s from %s",
       pspec->name, g_type_name (value_type), set->value_str);
     g_value_init (&v, value_type);
-    if (gst_value_deserialize (&v, set->value_str))
+    if (gst_value_deserialize_with_pspec (&v, set->value_str, pspec))
       got_value = TRUE;
     else if (g_type_is_a (value_type, GST_TYPE_ELEMENT)) {
        GstElement *bin;
@@ -358,7 +358,7 @@ out:
   if (G_IS_VALUE (&v))
     g_value_unset (&v);
   if (target)
-    g_object_unref (target);
+    gst_object_unref (target);
   return;
 
 error:
@@ -398,7 +398,7 @@ static void gst_parse_element_set (gchar *value, GstElement *element, graph_t *g
   }
   gst_parse_unescape (pos);
 
-  if (GST_IS_CHILD_PROXY (element)) {
+  if (GST_IS_CHILD_PROXY (element) && strstr (value, "::") != NULL) {
     if (!gst_child_proxy_lookup (GST_CHILD_PROXY (element), value, &target, &pspec)) {
       /* do a delayed set */
       gst_parse_add_delayed_set (element, value, pos);
@@ -424,7 +424,7 @@ static void gst_parse_element_set (gchar *value, GstElement *element, graph_t *g
         pspec->name, g_type_name (value_type));
 
     g_value_init (&v, value_type);
-    if (gst_value_deserialize (&v, pos))
+    if (gst_value_deserialize_with_pspec (&v, pos, pspec))
       got_value = TRUE;
     else if (g_type_is_a (value_type, GST_TYPE_ELEMENT)) {
        GstElement *bin;
@@ -446,7 +446,7 @@ out:
   if (G_IS_VALUE (&v))
     g_value_unset (&v);
   if (target)
-    g_object_unref (target);
+    gst_object_unref (target);
   return;
 
 error:
@@ -456,6 +456,40 @@ error:
   goto out;
 }
 
+static void gst_parse_element_preset (gchar *value, GstElement *element, graph_t *graph)
+{
+  /* do nothing if preset is for missing element or its not a preset element */
+  if (element == NULL)
+    goto out;
+
+  if (!GST_IS_PRESET(element))
+    goto not_a_preset;
+
+  /* do nothing if no preset is given */
+  if (value == NULL || *value == '\0')
+    goto out;
+
+  gst_parse_unescape (value);
+  if (!gst_preset_load_preset (GST_PRESET (element), value))
+    goto error;
+
+out:
+  gst_parse_strfree (value);
+  return;
+
+not_a_preset:
+  SET_ERROR (graph->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
+         _("Element \"%s\" is not a GstPreset"),
+        GST_ELEMENT_NAME (element));
+  goto out;
+
+error:
+  SET_ERROR (graph->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
+         _("could not set preset \"%s\" in element \"%s\""),
+        value, GST_ELEMENT_NAME (element));
+  goto out;
+}
+
 static void gst_parse_free_reference (reference_t *rr)
 {
   if(rr->element) gst_object_unref(rr->element);
@@ -532,10 +566,11 @@ static void gst_parse_found_pad (GstElement *src, GstPad *pad, gpointer data)
                               link->all_pads ? "all pads" : "one pad",
                           PRETTY_PAD_NAME_ARGS (src, link->src_pad),
                    PRETTY_PAD_NAME_ARGS (link->sink, link->sink_pad));
-    g_signal_handler_disconnect (src, link->no_more_pads_signal_id);
     /* releases 'link' */
-    if (!link->all_pads)
+    if (!link->all_pads) {
+      g_signal_handler_disconnect (src, link->no_more_pads_signal_id);
       g_signal_handler_disconnect (src, link->pad_added_signal_id);
+    }
   }
 }
 
@@ -763,7 +798,7 @@ static int yyerror (void *scanner, graph_t *graph, const char *s);
 %token <ss> PARSE_URL
 %token <ss> IDENTIFIER
 %left  <ss> REF PADREF BINREF
-%token <ss> ASSIGNMENT
+%token <ss> ASSIGNMENT PRESET
 %token <ss> LINK
 %token <ss> LINK_ALL
 
@@ -796,7 +831,7 @@ static int yyerror (void *scanner, graph_t *graph, const char *s);
 %lex-param { void *scanner }
 %parse-param { void *scanner }
 %parse-param { graph_t *graph }
-%pure-parser
+@BISON_PURE_PARSER@
 
 %start graph
 %%
@@ -817,6 +852,9 @@ element:    IDENTIFIER                    { $$ = gst_element_factory_make ($1, NULL);
                                                }
                                                gst_parse_strfree ($1);
                                               }
+       |       element PRESET            { gst_parse_element_preset ($2, $1, graph);
+                                               $$ = $1;
+                                             }
        |       element ASSIGNMENT            { gst_parse_element_set ($2, $1, graph);
                                                $$ = $1;
                                              }
index a843398..35ed6f2 100644 (file)
@@ -27,6 +27,7 @@ gen_lex = configure_file(input : 'gen_lex.py.in',
   configuration : flex_cdata)
 
 # Find bison, configure grammar generator
+bison_parser_cdata = configuration_data()
 bison_cdata = configuration_data()
 
 bison_min_version='2.4'
@@ -44,7 +45,15 @@ else
   message('bison version @0@ >= @1@: YES'.format(bversion, bison_min_version))
 endif
 
+if bversion.version_compare('>' + '2.5')
+  bison_parser_cdata.set('BISON_PURE_PARSER', '%define api.pure full')
+else
+  bison_parser_cdata.set('BISON_PURE_PARSER', '%pure-parser')
+endif
 
+gen_grammar_file = configure_file(input : 'grammar.y.in',
+  output : 'grammar.y',
+  configuration : bison_parser_cdata)
 
 bison_cdata.set('BISON', bison.path())
 bison_cdata.set('BISON_ARGS', '')
@@ -61,7 +70,7 @@ parser = custom_target('parselex',
 )
 
 grammar = custom_target('parsegrammar',
-  input : 'grammar.y',
+  input : gen_grammar_file,
   output : ['grammar.tab.c', 'grammar.tab.h'],
   command : [python3, gen_grammar, '@OUTPUT0@', '@OUTPUT1@', '@INPUT@'],
   depends : [parser],
index 50acf5c..8d4e97e 100644 (file)
@@ -64,6 +64,8 @@ _url ({_protocol}"://"{_string}|["."{_identifier}]?"/"{_string})|({_protocol}":/
 /* we must do this here, because nearly everything matches a {_string} */ 
 _assignment {_identifier}{_assign}{_string}
 
+_preset @preset{_assign}{_string}
+
 /* get pad/element references and stuff with dots right */
 _padref "."{_identifier}
 _ref {_identifier}"."{_identifier}?
@@ -94,6 +96,16 @@ _link ([!:][[:space:]]*{_caps}([[:space:]]*(";"[[:space:]]*{_caps})*[[:space:]]*
     return ASSIGNMENT;
 }
 
+{_preset} {
+    gchar *pos = yytext;
+    while (*pos && (*pos != '=')) pos++;
+    while (*pos && g_ascii_isspace (*pos)) pos++;
+    PRINT ("PRESET: %s", &pos[1]);
+    yylval->ss = gst_parse_strdup (&pos[1]);
+    BEGIN (INITIAL);
+    return PRESET;
+}
+
 {_padref} {
     yytext++;
     PRINT ("PADREF: %s", yytext);
diff --git a/gst/printf/Makefile.am b/gst/printf/Makefile.am
deleted file mode 100644 (file)
index b730745..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-AM_CPPFLAGS = $(GLIB_CFLAGS) -DSTATIC=G_GNUC_INTERNAL $(WARNING_CFLAGS) $(PRINTF_CFLAGS)
-
-# don't have a need for that and it's not portable so just ignore for now
-AM_CPPFLAGS += -UHAVE_LONG_DOUBLE
-
-# just use internal emulation for printing long longs for now
-AM_CPPFLAGS += -UHAVE_LONG_LONG_FORMAT
-
-# don't need any of this widechar stuff, so just disable it for now
-AM_CPPFLAGS += -UHAVE_WCHAR_T -UHAVE_WCSLEN -UHAVE_WINT_T
-
-# in case anyone wants to add anything else or undo some of the undefs
-AM_CPPFLAGS += $(PRINTF_EXTRA_CFLAGS)
-
-noinst_LTLIBRARIES = libgstprintf.la
-
-libgstprintf_la_CFLAGS = $(EXTRA_CFLAGS) $(VISIBILITY_CFLAGS)
-libgstprintf_la_SOURCES =      \
-       asnprintf.c \
-       printf-args.c \
-       printf-args.h \
-       printf-parse.c \
-       printf-parse.h \
-       vasnprintf.c \
-       vasnprintf.h \
-       printf.c \
-       printf.h \
-       printf-extension.c \
-       printf-extension.h \
-       gst-printf.h
-
-EXTRA_DIST = README
index 105fa2e..ddb7cf2 100644 (file)
@@ -24,7 +24,7 @@ GStreamer is the core module, containing libraries, headers, the basic object
 hierarchy, and a set of media-agnostic core elements.
  </description>
  <category></category>
- <bug-database rdf:resource="http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer&amp;component=gstreamer+%28core%29" />
+ <bug-database rdf:resource="https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/" />
  <screenshots></screenshots>
  <mailing-list rdf:resource="http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel" />
  <programming-language>C</programming-language>
@@ -40,21 +40,61 @@ hierarchy, and a set of media-agnostic core elements.
 
  <release>
   <Version>
-   <revision>1.16.2</revision>
-   <branch>1.16</branch>
+   <revision>1.19.2</revision>
+   <branch>master</branch>
+   <name></name>
+   <created>2021-09-23</created>
+   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.19.2.tar.xz" />
+  </Version>
+ </release>
+
+ <release>
+  <Version>
+   <revision>1.19.1</revision>
+   <branch>master</branch>
+   <name></name>
+   <created>2021-06-01</created>
+   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.19.1.tar.xz" />
+  </Version>
+ </release>
+
+ <release>
+  <Version>
+   <revision>1.18.0</revision>
+   <branch>master</branch>
    <name></name>
-   <created>2019-12-03</created>
-   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.16.2.tar.xz" />
+   <created>2020-09-08</created>
+   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.18.0.tar.xz" />
   </Version>
  </release>
 
  <release>
   <Version>
-   <revision>1.16.1</revision>
-   <branch>1.16</branch>
+   <revision>1.17.90</revision>
+   <branch>master</branch>
+   <name></name>
+   <created>2020-08-20</created>
+   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.17.90.tar.xz" />
+  </Version>
+ </release>
+
+ <release>
+  <Version>
+   <revision>1.17.2</revision>
+   <branch>master</branch>
+   <name></name>
+   <created>2020-07-03</created>
+   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.17.2.tar.xz" />
+  </Version>
+ </release>
+
+ <release>
+  <Version>
+   <revision>1.17.1</revision>
+   <branch>master</branch>
    <name></name>
-   <created>2019-09-23</created>
-   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.16.1.tar.xz" />
+   <created>2020-06-19</created>
+   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.17.1.tar.xz" />
   </Version>
  </release>
 
index 6f17740..a295d2b 100644 (file)
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Check that the code follows a consistent code style
+# Check that the code follows a consistant code style
 #
 
 # Check for existence of indent, and error out if not present.
@@ -81,3 +81,35 @@ echo "==========================================================================
     fi
 done
 echo "--Checking style pass--"
+
+# This is an opt-in check, and can only be run from gst-build's devenv,
+# as outside of it MESON_BUILD_ROOT will not be set.
+#
+# The idea is to build the cache, and check if it has unstaged changes.
+# To accomodate for the git add -p case, where the developer will break
+# down a large change set into multiple commits, this hook will only
+# fail when there are no unstaged changes left to commit, in other
+# cases it will only print a reminder that the cache needs committing.
+if [ -v MESON_BUILD_ROOT ] && [ "$GST_CACHE_HOOK" == "enabled" ]; then
+    echo "--Checking plugin cache--"
+    toplevel=`git rev-parse --show-toplevel`
+    repo_name=`basename $toplevel`
+    target_name=`ninja -C $MESON_BUILD_ROOT -t targets all | grep "\/\<$repo_name\>\/.*\/gst_plugins_cache.json" | cut -d ":" -f 1`
+    ninja -C $MESON_BUILD_ROOT $target_name
+    cache_path=`git ls-files $toplevel/**gst_plugins_cache.json`
+    git diff --quiet --exit-code -- $cache_path
+    has_unstaged_cache_changes=$?
+    git diff --quiet --exit-code -- ':!'$cache_path
+    has_unstaged_non_cache_changes=$?
+
+    if [ $has_unstaged_non_cache_changes != 0 ] ; then
+        if [ $has_unstaged_cache_changes != 0 ]; then
+            echo -e "\033[1;33mUnstaged cache changes, but working directory isn't clean, don't forget to commit the cache when you're done\033[0m"
+        fi
+    elif [ $has_unstaged_cache_changes != 0 ]; then
+        echo -e "\033[1;31mUnstaged cache changes, but the working directory is clean, you must commit the cache\033[0m"
+        exit 1
+    else
+    echo "--Checking plugin cache pass--"
+    fi
+fi
diff --git a/libs/Makefile.am b/libs/Makefile.am
deleted file mode 100644 (file)
index 062cb55..0000000
+++ /dev/null
@@ -1 +0,0 @@
-SUBDIRS = gst
diff --git a/libs/gst/Makefile.am b/libs/gst/Makefile.am
deleted file mode 100644 (file)
index c89aad1..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-if HAVE_CHECK
-SUBDIRS_CHECK = check
-else
-SUBDIRS_CHECK =
-endif
-
-if GST_DISABLE_REGISTRY
-SUBDIRS_HELPERS =
-else
-SUBDIRS_HELPERS = helpers
-endif
-
-SUBDIRS_ALWAYS = base controller net
-
-SUBDIRS = $(SUBDIRS_ALWAYS) $(SUBDIRS_CHECK) $(SUBDIRS_HELPERS)
-DIST_SUBDIRS = $(SUBDIRS_ALWAYS) check helpers
diff --git a/libs/gst/base/.gitignore b/libs/gst/base/.gitignore
deleted file mode 100644 (file)
index 94cedd0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-*.gcno
-*.c.gcov
-*.c.gcov
-*.c.gcov.out
-*.c.gcov
-*.o
-*.lo
-*.la
diff --git a/libs/gst/base/Makefile.am b/libs/gst/base/Makefile.am
deleted file mode 100644 (file)
index 8439ebf..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-lib_LTLIBRARIES = libgstbase-@GST_API_VERSION@.la
-
-libgstbase_@GST_API_VERSION@_la_DEPENDENCIES = \
-       $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la
-libgstbase_@GST_API_VERSION@_la_SOURCES = \
-       gstadapter.c            \
-       gstaggregator.c         \
-       gstbaseparse.c          \
-       gstbasesink.c           \
-       gstbasesrc.c            \
-       gstbasetransform.c      \
-       gstbitreader.c          \
-       gstbitwriter.c          \
-       gstbytereader.c         \
-       gstbytewriter.c         \
-       gstcollectpads.c        \
-       gstdataqueue.c          \
-       gstflowcombiner.c       \
-       gstpushsrc.c            \
-       gstqueuearray.c         \
-       gsttypefindhelper.c
-
-libgstbase_@GST_API_VERSION@_la_CFLAGS = $(GST_OBJ_CFLAGS) -DBUILDING_GST_BASE
-libgstbase_@GST_API_VERSION@_la_LIBADD = $(GST_OBJ_LIBS)
-libgstbase_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
-
-libgstbase_@GST_API_VERSION@includedir =               \
-       $(includedir)/gstreamer-@GST_API_VERSION@/gst/base
-
-libgstbase_@GST_API_VERSION@include_HEADERS =  \
-       base.h                  \
-       base-prelude.h          \
-       gstadapter.h            \
-       gstaggregator.h         \
-       gstbaseparse.h          \
-       gstbasesink.h           \
-       gstbasesrc.h            \
-       gstbasetransform.h      \
-       gstbitreader.h          \
-       gstbitwriter.h          \
-       gstbytereader.h         \
-       gstbytewriter.h         \
-       gstcollectpads.h        \
-       gstdataqueue.h          \
-       gstflowcombiner.h       \
-       gstpushsrc.h            \
-       gstqueuearray.h         \
-       gsttypefindhelper.h
-
-noinst_HEADERS = \
-       gstbytereader-docs.h \
-       gstbytewriter-docs.h \
-       gstbitreader-docs.h \
-       gstbitwriter-docs.h \
-       gstindex.h
-
-EXTRA_DIST = gstindex.c gstmemindex.c
-
-CLEANFILES = *.gcno *.gcda *.gcov
-
-%.c.gcov: .libs/libgstbase_@GST_API_VERSION@_la-%.gcda %.c
-       $(GCOV) -b -f -o $^ > $@.out
-
-gcov: $(libgstbase_@GST_API_VERSION@_la_SOURCES:=.gcov)
-
-if HAVE_INTROSPECTION
-BUILT_GIRSOURCES = GstBase-@GST_API_VERSION@.gir
-
-gir_headers=$(patsubst %,$(srcdir)/%, $(libgstbase_@GST_API_VERSION@include_HEADERS))
-gir_sources=$(patsubst %,$(srcdir)/%, $(libgstbase_@GST_API_VERSION@_la_SOURCES))
-
-GstBase-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstbase-@GST_API_VERSION@.la
-       $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" GI_SCANNER_DISABLE_CACHE=yes\
-               GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_DISABLE=yes \
-               CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" PKG_CONFIG="$(PKG_CONFIG)" DLLTOOL="$(DLLTOOL)" \
-               $(INTROSPECTION_SCANNER) -v --namespace GstBase \
-               --nsversion=@GST_API_VERSION@ \
-               --warn-all \
-               --identifier-prefix=Gst \
-               --symbol-prefix=gst \
-               -I$(top_srcdir) \
-               -I$(top_srcdir)/libs \
-               -I$(top_builddir) \
-               -I$(top_builddir)/libs \
-               --c-include "gst/base/base.h" \
-               --add-include-path=$(top_builddir)/gst \
-               --library-path=$(top_builddir)/gst \
-               --library=libgstbase-@GST_API_VERSION@.la \
-               --include=Gst-@GST_API_VERSION@ \
-               --libtool="${LIBTOOL}" \
-               --pkg gstreamer-@GST_API_VERSION@ \
-               --pkg-export gstreamer-base-@GST_API_VERSION@ \
-               --add-init-section="$(INTROSPECTION_INIT)" \
-               --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
index bedb3e1..33c84f2 100644 (file)
  * since then can be queried with gst_adapter_distance_from_discont().
  *
  * A last thing to note is that while #GstAdapter is pretty optimized,
- * merging buffers still might be an operation that requires a malloc() and
- * memcpy() operation, and these operations are not the fastest. Because of
+ * merging buffers still might be an operation that requires a `malloc()` and
+ * `memcpy()` operation, and these operations are not the fastest. Because of
  * this, some functions like gst_adapter_available_fast() are provided to help
  * speed up such cases should you want to. To avoid repeated memory allocations,
  * gst_adapter_copy() can be used to copy data into a (statically allocated)
@@ -1365,7 +1365,7 @@ gst_adapter_available_fast (GstAdapter * adapter)
 }
 
 /**
- * gst_adapter_get_distance_from_discont:
+ * gst_adapter_distance_from_discont:
  * @adapter: a #GstAdapter
  *
  * Get the distance in bytes since the last buffer with the
index 3e7610e..3945085 100644 (file)
@@ -142,9 +142,7 @@ GST_BASE_API
 gssize                  gst_adapter_masked_scan_uint32_peek  (GstAdapter * adapter, guint32 mask,
                                                          guint32 pattern, gsize offset, gsize size, guint32 * value);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAdapter, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 5cdb852..5a6e30f 100644 (file)
  * Control is given to the subclass when all pads have data.
  *
  *  * Base class for mixers and muxers. Subclasses should at least implement
- *    the #GstAggregatorClass.aggregate() virtual method.
+ *    the #GstAggregatorClass::aggregate virtual method.
  *
  *  * Installs a #GstPadChainFunction, a #GstPadEventFullFunction and a
  *    #GstPadQueryFunction to queue all serialized data packets per sink pad.
  *    Subclasses should not overwrite those, but instead implement
- *    #GstAggregatorClass.sink_event() and #GstAggregatorClass.sink_query() as
+ *    #GstAggregatorClass::sink_event and #GstAggregatorClass::sink_query as
  *    needed.
  *
  *  * When data is queued on all pads, the aggregate vmethod is called.
  *
  *  * One can peek at the data on any given GstAggregatorPad with the
- *    gst_aggregator_pad_peek_buffer () method, and remove it from the pad
+ *    gst_aggregator_pad_peek_buffer() method, and remove it from the pad
  *    with the gst_aggregator_pad_pop_buffer () method. When a buffer
  *    has been taken with pop_buffer (), a new buffer can be queued
  *    on that pad.
  *
+ *  * When gst_aggregator_pad_peek_buffer() or gst_aggregator_pad_has_buffer()
+ *    are called, a reference is taken to the returned buffer, which stays
+ *    valid until either:
+ *
+ *      - gst_aggregator_pad_pop_buffer() is called, in which case the caller
+ *        is guaranteed that the buffer they receive is the same as the peeked
+ *        buffer.
+ *      - gst_aggregator_pad_drop_buffer() is called, in which case the caller
+ *        is guaranteed that the dropped buffer is the one that was peeked.
+ *      - the subclass implementation of #GstAggregatorClass.aggregate returns.
+ *
+ *    Subsequent calls to gst_aggregator_pad_peek_buffer() or
+ *    gst_aggregator_pad_has_buffer() return / check the same buffer that was
+ *    returned / checked, until one of the conditions listed above is met.
+ *
+ *    Subclasses are only allowed to call these methods from the aggregate
+ *    thread.
+ *
  *  * If the subclass wishes to push a buffer downstream in its aggregate
  *    implementation, it should do so through the
- *    gst_aggregator_finish_buffer () method. This method will take care
+ *    gst_aggregator_finish_buffer() method. This method will take care
  *    of sending and ordering mandatory events such as stream start, caps
- *    and segment.
+ *    and segment. Buffer lists can also be pushed out with
+ *    gst_aggregator_finish_buffer_list().
  *
  *  * Same goes for EOS events, which should not be pushed directly by the
  *    subclass, it should instead return GST_FLOW_EOS in its aggregate
@@ -76,7 +95,7 @@
  * @short_description: #GstPad subclass for pads managed by #GstAggregator
  * @see_also: gstcollectpads for historical reasons.
  *
- * Pads managed by a #GstAggregor subclass.
+ * Pads managed by a #GstAggregator subclass.
  *
  * This class used to live in gst-plugins-bad and was moved to core.
  *
 
 #include "gstaggregator.h"
 
-typedef enum
-{
-  GST_AGGREGATOR_START_TIME_SELECTION_ZERO,
-  GST_AGGREGATOR_START_TIME_SELECTION_FIRST,
-  GST_AGGREGATOR_START_TIME_SELECTION_SET
-} GstAggregatorStartTimeSelection;
-
-static GType
+GType
 gst_aggregator_start_time_selection_get_type (void)
 {
   static GType gtype = 0;
 
-  if (gtype == 0) {
+  if (g_once_init_enter (&gtype)) {
     static const GEnumValue values[] = {
       {GST_AGGREGATOR_START_TIME_SELECTION_ZERO,
-          "Start at 0 running time (default)", "zero"},
+          "GST_AGGREGATOR_START_TIME_SELECTION_ZERO", "zero"},
       {GST_AGGREGATOR_START_TIME_SELECTION_FIRST,
-          "Start at first observed input running time", "first"},
+          "GST_AGGREGATOR_START_TIME_SELECTION_FIRST", "first"},
       {GST_AGGREGATOR_START_TIME_SELECTION_SET,
-          "Set start time with start-time property", "set"},
+          "GST_AGGREGATOR_START_TIME_SELECTION_SET", "set"},
       {0, NULL, NULL}
     };
+    GType new_type =
+        g_enum_register_static ("GstAggregatorStartTimeSelection", values);
 
-    gtype = g_enum_register_static ("GstAggregatorStartTimeSelection", values);
+    g_once_init_leave (&gtype, new_type);
   }
   return gtype;
 }
@@ -131,7 +145,7 @@ static GstClockTime gst_aggregator_get_latency_property (GstAggregator * agg);
 static GstClockTime gst_aggregator_get_latency_unlocked (GstAggregator * self);
 
 static void gst_aggregator_pad_buffer_consumed (GstAggregatorPad * pad,
-    GstBuffer * buffer);
+    GstBuffer * buffer, gboolean dequeued);
 
 GST_DEBUG_CATEGORY_STATIC (aggregator_debug);
 #define GST_CAT_DEFAULT aggregator_debug
@@ -234,14 +248,16 @@ struct _GstAggregatorPadPrivate
 {
   /* Following fields are protected by the PAD_LOCK */
   GstFlowReturn flow_return;
-  gboolean pending_flush_start;
-  gboolean pending_flush_stop;
+
+  guint32 last_flush_start_seqnum;
+  guint32 last_flush_stop_seqnum;
 
   gboolean first_buffer;
 
   GQueue data;                  /* buffers, events and queries */
   GstBuffer *clipped_buffer;
   guint num_buffers;
+  GstBuffer *peeked_buffer;
 
   /* used to track fill state of queues, only used with live-src and when
    * latency property is set to > 0 */
@@ -300,6 +316,31 @@ gst_aggregator_pad_flush (GstAggregatorPad * aggpad, GstAggregator * agg)
   return TRUE;
 }
 
+/**
+ * gst_aggregator_peek_next_sample:
+ *
+ * Use this function to determine what input buffers will be aggregated
+ * to produce the next output buffer. This should only be called from
+ * a #GstAggregator::samples-selected handler, and can be used to precisely
+ * control aggregating parameters for a given set of input samples.
+ *
+ * Returns: (nullable) (transfer full): The sample that is about to be aggregated. It may hold a #GstBuffer
+ *   or a #GstBufferList. The contents of its info structure is subclass-dependent,
+ *   and documented on a subclass basis. The buffers held by the sample are
+ *   not writable.
+ * Since: 1.18
+ */
+GstSample *
+gst_aggregator_peek_next_sample (GstAggregator * agg, GstAggregatorPad * aggpad)
+{
+  GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (agg);
+
+  if (klass->peek_next_sample)
+    return (klass->peek_next_sample (agg, aggpad));
+
+  return NULL;
+}
+
 /*************************************
  * GstAggregator implementation  *
  *************************************/
@@ -315,13 +356,14 @@ struct _GstAggregatorPrivate
   /* Our state is >= PAUSED */
   gboolean running;             /* protected by src_lock */
 
-  /* seqnum from seek or segment,
-   * to be applied to synthetic segment/eos events */
-  gint seqnum;
+  /* seqnum from last seek or common seqnum to flush start events received
+   * on all pads, for flushing without a seek */
+  guint32 next_seqnum;
+  /* seqnum to apply to synthetic segment/eos events */
+  guint32 seqnum;
   gboolean send_stream_start;   /* protected by srcpad stream lock */
   gboolean send_segment;
-  gboolean flush_seeking;
-  gboolean pending_flush_start;
+  gboolean flushing;
   gboolean send_eos;            /* protected by srcpad stream lock */
 
   GstCaps *srccaps;             /* protected by the srcpad stream lock */
@@ -341,6 +383,7 @@ struct _GstAggregatorPrivate
 
   /* aggregate */
   GstClockID aggregate_id;      /* protected by src_lock */
+  gboolean selected_samples_called_or_warned;   /* protected by src_lock */
   GMutex src_lock;
   GCond src_cond;
 
@@ -356,6 +399,7 @@ struct _GstAggregatorPrivate
 
   /* properties */
   gint64 latency;               /* protected by both src_lock and all pad locks */
+  gboolean emit_signals;
 };
 
 /* Seek event forwarding helper */
@@ -375,6 +419,7 @@ typedef struct
 #define DEFAULT_MIN_UPSTREAM_LATENCY              0
 #define DEFAULT_START_TIME_SELECTION GST_AGGREGATOR_START_TIME_SELECTION_ZERO
 #define DEFAULT_START_TIME           (-1)
+#define DEFAULT_EMIT_SIGNALS         FALSE
 
 enum
 {
@@ -383,9 +428,18 @@ enum
   PROP_MIN_UPSTREAM_LATENCY,
   PROP_START_TIME_SELECTION,
   PROP_START_TIME,
+  PROP_EMIT_SIGNALS,
   PROP_LAST
 };
 
+enum
+{
+  SIGNAL_SAMPLES_SELECTED,
+  LAST_SIGNAL,
+};
+
+static guint gst_aggregator_signals[LAST_SIGNAL] = { 0 };
+
 static GstFlowReturn gst_aggregator_pad_chain_internal (GstAggregator * self,
     GstAggregatorPad * aggpad, GstBuffer * buffer, gboolean head);
 
@@ -396,8 +450,15 @@ gst_aggregator_pad_queue_is_empty (GstAggregatorPad * pad)
       pad->priv->clipped_buffer == NULL);
 }
 
+/* Will return FALSE if there's no buffer available on every non-EOS pad, or
+ * if at least one of the pads has an event or query at the top of its queue.
+ *
+ * Only returns TRUE if all non-EOS pads have a buffer available at the top of
+ * their queue or a clipped buffer already.
+ */
 static gboolean
-gst_aggregator_check_pads_ready (GstAggregator * self)
+gst_aggregator_check_pads_ready (GstAggregator * self,
+    gboolean * have_event_or_query_ret)
 {
   GstAggregatorPad *pad = NULL;
   GList *l, *sinkpads;
@@ -417,18 +478,30 @@ gst_aggregator_check_pads_ready (GstAggregator * self)
 
     PAD_LOCK (pad);
 
-    if (pad->priv->num_buffers == 0) {
-      if (!gst_aggregator_pad_queue_is_empty (pad))
-        have_event_or_query = TRUE;
-      if (!pad->priv->eos) {
-        have_buffer = FALSE;
+    /* If there's an event or query at the top of the queue and we don't yet
+     * have taken the top buffer out and stored it as clip_buffer, remember
+     * that and exit the loop. We first have to handle all events/queries
+     * before we handle any buffers. */
+    if (!pad->priv->clipped_buffer
+        && (GST_IS_EVENT (g_queue_peek_tail (&pad->priv->data))
+            || GST_IS_QUERY (g_queue_peek_tail (&pad->priv->data)))) {
+      PAD_UNLOCK (pad);
+      have_event_or_query = TRUE;
+      break;
+    }
 
-        /* If not live we need data on all pads, so leave the loop */
-        if (!self->priv->peer_latency_live) {
-          PAD_UNLOCK (pad);
-          goto pad_not_ready;
-        }
-      }
+    /* Otherwise check if we have a clipped buffer or a buffer at the top of
+     * the queue, and if not then this pad is not ready unless it is also EOS */
+    if (!pad->priv->clipped_buffer
+        && !GST_IS_BUFFER (g_queue_peek_tail (&pad->priv->data))) {
+      /* We must not have any buffers at all in this pad then as otherwise we
+       * would've had an event/query at the top of the queue */
+      g_assert (pad->priv->num_buffers == 0);
+
+      /* Only consider this pad as worth waiting for if it's not already EOS.
+       * There's no point in waiting for buffers on EOS pads */
+      if (!pad->priv->eos)
+        have_buffer = FALSE;
     } else if (self->priv->peer_latency_live) {
       /* In live mode, having a single pad with buffers is enough to
        * generate a start time from it. In non-live mode all pads need
@@ -440,7 +513,10 @@ gst_aggregator_check_pads_ready (GstAggregator * self)
     PAD_UNLOCK (pad);
   }
 
-  if (!have_buffer && !have_event_or_query)
+  if (have_event_or_query)
+    goto pad_not_ready_but_event_or_query;
+
+  if (!have_buffer)
     goto pad_not_ready;
 
   if (have_buffer)
@@ -448,23 +524,42 @@ gst_aggregator_check_pads_ready (GstAggregator * self)
 
   GST_OBJECT_UNLOCK (self);
   GST_LOG_OBJECT (self, "pads are ready");
+
+  if (have_event_or_query_ret)
+    *have_event_or_query_ret = have_event_or_query;
+
   return TRUE;
 
 no_sinkpads:
   {
     GST_LOG_OBJECT (self, "pads not ready: no sink pads");
     GST_OBJECT_UNLOCK (self);
+
+    if (have_event_or_query_ret)
+      *have_event_or_query_ret = have_event_or_query;
+
     return FALSE;
   }
 pad_not_ready:
   {
-    if (have_event_or_query)
-      GST_LOG_OBJECT (pad, "pad not ready to be aggregated yet,"
-          " but waking up for serialized event");
-    else
-      GST_LOG_OBJECT (pad, "pad not ready to be aggregated yet");
+    GST_LOG_OBJECT (pad, "pad not ready to be aggregated yet");
+    GST_OBJECT_UNLOCK (self);
+
+    if (have_event_or_query_ret)
+      *have_event_or_query_ret = have_event_or_query;
+
+    return FALSE;
+  }
+pad_not_ready_but_event_or_query:
+  {
+    GST_LOG_OBJECT (pad,
+        "pad not ready to be aggregated yet, need to handle serialized event or query first");
     GST_OBJECT_UNLOCK (self);
-    return have_event_or_query;
+
+    if (have_event_or_query_ret)
+      *have_event_or_query_ret = have_event_or_query;
+
+    return FALSE;
   }
 }
 
@@ -476,6 +571,9 @@ gst_aggregator_reset_flow_values (GstAggregator * self)
   self->priv->send_segment = TRUE;
   gst_segment_init (&GST_AGGREGATOR_PAD (self->srcpad)->segment,
       GST_FORMAT_TIME);
+  /* Initialize to -1 so we set it to the start position once the first buffer
+   * is handled in gst_aggregator_pad_chain_internal() */
+  GST_AGGREGATOR_PAD (self->srcpad)->segment.position = -1;
   self->priv->first_buffer = TRUE;
   GST_OBJECT_UNLOCK (self);
 }
@@ -513,7 +611,7 @@ gst_aggregator_push_mandatory_events (GstAggregator * self)
   }
 
   GST_OBJECT_LOCK (self);
-  if (self->priv->send_segment && !self->priv->flush_seeking) {
+  if (self->priv->send_segment && !self->priv->flushing) {
     segment =
         gst_event_new_segment (&GST_AGGREGATOR_PAD (self->srcpad)->segment);
 
@@ -528,7 +626,7 @@ gst_aggregator_push_mandatory_events (GstAggregator * self)
     GST_DEBUG_OBJECT (self, "pushing segment %" GST_PTR_FORMAT, segment);
   }
 
-  if (priv->tags && priv->tags_changed && !self->priv->flush_seeking) {
+  if (priv->tags && priv->tags_changed && !self->priv->flushing) {
     tags = gst_event_new_tag (gst_tag_list_ref (priv->tags));
     priv->tags_changed = FALSE;
   }
@@ -563,13 +661,13 @@ gst_aggregator_default_finish_buffer (GstAggregator * self, GstBuffer * buffer)
   gst_aggregator_push_mandatory_events (self);
 
   GST_OBJECT_LOCK (self);
-  if (!self->priv->flush_seeking && gst_pad_is_active (self->srcpad)) {
+  if (!self->priv->flushing && gst_pad_is_active (self->srcpad)) {
     GST_TRACE_OBJECT (self, "pushing buffer %" GST_PTR_FORMAT, buffer);
     GST_OBJECT_UNLOCK (self);
     return gst_pad_push (self->srcpad, buffer);
   } else {
     GST_INFO_OBJECT (self, "Not pushing (active: %i, flushing: %i)",
-        self->priv->flush_seeking, gst_pad_is_active (self->srcpad));
+        self->priv->flushing, gst_pad_is_active (self->srcpad));
     GST_OBJECT_UNLOCK (self);
     gst_buffer_unref (buffer);
     return GST_FLOW_OK;
@@ -595,6 +693,48 @@ gst_aggregator_finish_buffer (GstAggregator * aggregator, GstBuffer * buffer)
   return klass->finish_buffer (aggregator, buffer);
 }
 
+static GstFlowReturn
+gst_aggregator_default_finish_buffer_list (GstAggregator * self,
+    GstBufferList * bufferlist)
+{
+  gst_aggregator_push_mandatory_events (self);
+
+  GST_OBJECT_LOCK (self);
+  if (!self->priv->flushing && gst_pad_is_active (self->srcpad)) {
+    GST_TRACE_OBJECT (self, "pushing bufferlist%" GST_PTR_FORMAT, bufferlist);
+    GST_OBJECT_UNLOCK (self);
+    return gst_pad_push_list (self->srcpad, bufferlist);
+  } else {
+    GST_INFO_OBJECT (self, "Not pushing (active: %i, flushing: %i)",
+        self->priv->flushing, gst_pad_is_active (self->srcpad));
+    GST_OBJECT_UNLOCK (self);
+    gst_buffer_list_unref (bufferlist);
+    return GST_FLOW_OK;
+  }
+}
+
+/**
+ * gst_aggregator_finish_buffer_list:
+ * @aggregator: The #GstAggregator
+ * @bufferlist: (transfer full): the #GstBufferList to push.
+ *
+ * This method will push the provided output buffer list downstream. If needed,
+ * mandatory events such as stream-start, caps, and segment events will be
+ * sent before pushing the buffer.
+ *
+ * Since: 1.18
+ */
+GstFlowReturn
+gst_aggregator_finish_buffer_list (GstAggregator * aggregator,
+    GstBufferList * bufferlist)
+{
+  GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (aggregator);
+
+  g_assert (klass->finish_buffer_list != NULL);
+
+  return klass->finish_buffer_list (aggregator, bufferlist);
+}
+
 static void
 gst_aggregator_push_eos (GstAggregator * self)
 {
@@ -628,6 +768,7 @@ gst_aggregator_wait_and_check (GstAggregator * self, gboolean * timeout)
   GstClockTime latency;
   GstClockTime start;
   gboolean res;
+  gboolean have_event_or_query = FALSE;
 
   *timeout = FALSE;
 
@@ -635,13 +776,21 @@ gst_aggregator_wait_and_check (GstAggregator * self, gboolean * timeout)
 
   latency = gst_aggregator_get_latency_unlocked (self);
 
-  if (gst_aggregator_check_pads_ready (self)) {
+  if (gst_aggregator_check_pads_ready (self, &have_event_or_query)) {
     GST_DEBUG_OBJECT (self, "all pads have data");
     SRC_UNLOCK (self);
 
     return TRUE;
   }
 
+  /* If we have an event or query, immediately return FALSE instead of waiting
+   * and handle it immediately */
+  if (have_event_or_query) {
+    GST_DEBUG_OBJECT (self, "Have serialized event or query to handle first");
+    SRC_UNLOCK (self);
+    return FALSE;
+  }
+
   /* Before waiting, check if we're actually still running */
   if (!self->priv->running || !self->priv->send_eos) {
     SRC_UNLOCK (self);
@@ -720,7 +869,7 @@ gst_aggregator_wait_and_check (GstAggregator * self, gboolean * timeout)
     }
   }
 
-  res = gst_aggregator_check_pads_ready (self);
+  res = gst_aggregator_check_pads_ready (self, NULL);
   SRC_UNLOCK (self);
 
   return res;
@@ -771,8 +920,6 @@ gst_aggregator_do_events_and_queries (GstElement * self, GstPad * epad,
         PAD_LOCK (pad);
         if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS) {
           pad->priv->negotiated = ret;
-          if (!ret)
-            pad->priv->flow_return = data->flow_ret = GST_FLOW_NOT_NEGOTIATED;
         }
         if (g_queue_peek_tail (&pad->priv->data) == event)
           gst_event_unref (g_queue_pop_tail (&pad->priv->data));
@@ -814,21 +961,22 @@ gst_aggregator_pad_skip_buffers (GstElement * self, GstPad * epad,
 
   PAD_LOCK (aggpad);
 
-  item = g_queue_peek_head_link (&aggpad->priv->data);
+  item = g_queue_peek_tail_link (&aggpad->priv->data);
   while (item) {
-    GList *next = item->next;
+    GList *prev = item->prev;
 
     if (GST_IS_BUFFER (item->data)
         && klass->skip_buffer (aggpad, agg, item->data)) {
       GST_LOG_OBJECT (aggpad, "Skipping %" GST_PTR_FORMAT, item->data);
-      gst_aggregator_pad_buffer_consumed (aggpad, GST_BUFFER (item->data));
+      gst_aggregator_pad_buffer_consumed (aggpad, GST_BUFFER (item->data),
+          TRUE);
       gst_buffer_unref (item->data);
       g_queue_delete_link (&aggpad->priv->data, item);
     } else {
       break;
     }
 
-    item = next;
+    item = prev;
   }
 
   PAD_UNLOCK (aggpad);
@@ -836,6 +984,22 @@ gst_aggregator_pad_skip_buffers (GstElement * self, GstPad * epad,
   return TRUE;
 }
 
+static gboolean
+gst_aggregator_pad_reset_peeked_buffer (GstElement * self, GstPad * epad,
+    gpointer user_data)
+{
+  GstAggregatorPad *aggpad = (GstAggregatorPad *) epad;
+
+  PAD_LOCK (aggpad);
+
+  gst_buffer_replace (&aggpad->priv->peeked_buffer, NULL);
+
+  PAD_UNLOCK (aggpad);
+
+  return TRUE;
+}
+
+
 static void
 gst_aggregator_pad_set_flushing (GstAggregatorPad * aggpad,
     GstFlowReturn flow_return, gboolean full)
@@ -900,7 +1064,7 @@ gst_aggregator_default_negotiated_src_caps (GstAggregator * agg, GstCaps * caps)
 static gboolean
 gst_aggregator_set_allocation (GstAggregator * self,
     GstBufferPool * pool, GstAllocator * allocator,
-    GstAllocationParams * params, GstQuery * query)
+    const GstAllocationParams * params, GstQuery * query)
 {
   GstAllocator *oldalloc;
   GstBufferPool *oldpool;
@@ -1006,9 +1170,8 @@ no_decide_allocation:
 
 }
 
-/* WITH SRC_LOCK held */
-static GstFlowReturn
-gst_aggregator_update_src_caps (GstAggregator * self)
+static gboolean
+gst_aggregator_default_negotiate (GstAggregator * self)
 {
   GstAggregatorClass *agg_klass = GST_AGGREGATOR_GET_CLASS (self);
   GstCaps *downstream_caps, *template_caps, *caps = NULL;
@@ -1098,6 +1261,47 @@ done:
   if (caps)
     gst_caps_unref (caps);
 
+  return ret >= GST_FLOW_OK || ret == GST_AGGREGATOR_FLOW_NEED_DATA;
+}
+
+/* WITH SRC_LOCK held */
+static gboolean
+gst_aggregator_negotiate_unlocked (GstAggregator * self)
+{
+  GstAggregatorClass *agg_klass = GST_AGGREGATOR_GET_CLASS (self);
+
+  if (agg_klass->negotiate)
+    return agg_klass->negotiate (self);
+
+  return TRUE;
+}
+
+/**
+ * gst_aggregator_negotiate:
+ * @self: a #GstAggregator
+ *
+ * Negotiates src pad caps with downstream elements.
+ * Unmarks GST_PAD_FLAG_NEED_RECONFIGURE in any case. But marks it again
+ * if #GstAggregatorClass::negotiate fails.
+ *
+ * Returns: %TRUE if the negotiation succeeded, else %FALSE.
+ *
+ * Since: 1.18
+ */
+gboolean
+gst_aggregator_negotiate (GstAggregator * self)
+{
+  gboolean ret = TRUE;
+
+  g_return_val_if_fail (GST_IS_AGGREGATOR (self), FALSE);
+
+  GST_PAD_STREAM_LOCK (GST_AGGREGATOR_SRC_PAD (self));
+  gst_pad_check_reconfigure (GST_AGGREGATOR_SRC_PAD (self));
+  ret = gst_aggregator_negotiate_unlocked (self);
+  if (!ret)
+    gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (self));
+  GST_PAD_STREAM_UNLOCK (GST_AGGREGATOR_SRC_PAD (self));
+
   return ret;
 }
 
@@ -1130,26 +1334,21 @@ gst_aggregator_aggregate_func (GstAggregator * self)
 
     /* Ensure we have buffers ready (either in clipped_buffer or at the head of
      * the queue */
-    if (!gst_aggregator_wait_and_check (self, &timeout))
-      continue;
-
-    events_query_data.processed_event = FALSE;
-    events_query_data.flow_ret = GST_FLOW_OK;
-    gst_element_foreach_sink_pad (GST_ELEMENT_CAST (self),
-        gst_aggregator_do_events_and_queries, &events_query_data);
-
-    if ((flow_return = events_query_data.flow_ret) != GST_FLOW_OK)
-      goto handle_error;
-
-    if (events_query_data.processed_event)
+    if (!gst_aggregator_wait_and_check (self, &timeout)) {
+      gst_element_foreach_sink_pad (GST_ELEMENT_CAST (self),
+          gst_aggregator_pad_reset_peeked_buffer, NULL);
       continue;
+    }
 
     if (gst_pad_check_reconfigure (GST_AGGREGATOR_SRC_PAD (self))) {
-      flow_return = gst_aggregator_update_src_caps (self);
-      if (flow_return != GST_FLOW_OK)
+      if (!gst_aggregator_negotiate_unlocked (self)) {
         gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (self));
-      if (flow_return == GST_AGGREGATOR_FLOW_NEED_DATA)
-        flow_return = GST_FLOW_OK;
+        if (GST_PAD_IS_FLUSHING (GST_AGGREGATOR_SRC_PAD (self))) {
+          flow_return = GST_FLOW_FLUSHING;
+        } else {
+          flow_return = GST_FLOW_NOT_NEGOTIATED;
+        }
+      }
     }
 
     if (timeout || flow_return >= GST_FLOW_OK) {
@@ -1157,11 +1356,21 @@ gst_aggregator_aggregate_func (GstAggregator * self)
       flow_return = klass->aggregate (self, timeout);
     }
 
+    gst_element_foreach_sink_pad (GST_ELEMENT_CAST (self),
+        gst_aggregator_pad_reset_peeked_buffer, NULL);
+
+    if (!priv->selected_samples_called_or_warned) {
+      GST_FIXME_OBJECT (self,
+          "Subclass should call gst_aggregator_selected_samples() from its "
+          "aggregate implementation.");
+      priv->selected_samples_called_or_warned = TRUE;
+    }
+
     if (flow_return == GST_AGGREGATOR_FLOW_NEED_DATA)
       continue;
 
     GST_OBJECT_LOCK (self);
-    if (flow_return == GST_FLOW_FLUSHING && priv->flush_seeking) {
+    if (flow_return == GST_FLOW_FLUSHING && priv->flushing) {
       /* We don't want to set the pads to flushing, but we want to
        * stop the thread, so just break here */
       GST_OBJECT_UNLOCK (self);
@@ -1211,6 +1420,10 @@ gst_aggregator_start (GstAggregator * self)
   self->priv->send_eos = TRUE;
   self->priv->srccaps = NULL;
 
+  self->priv->has_peer_latency = FALSE;
+  self->priv->peer_latency_live = FALSE;
+  self->priv->peer_latency_min = self->priv->peer_latency_max = 0;
+
   gst_aggregator_set_allocation (self, NULL, NULL, NULL, NULL);
 
   klass = GST_AGGREGATOR_GET_CLASS (self);
@@ -1224,18 +1437,6 @@ gst_aggregator_start (GstAggregator * self)
 }
 
 static gboolean
-_check_pending_flush_stop (GstAggregatorPad * pad)
-{
-  gboolean res;
-
-  PAD_LOCK (pad);
-  res = (!pad->priv->pending_flush_stop && !pad->priv->pending_flush_start);
-  PAD_UNLOCK (pad);
-
-  return res;
-}
-
-static gboolean
 gst_aggregator_stop_srcpad_task (GstAggregator * self, GstEvent * flush_start)
 {
   gboolean res = TRUE;
@@ -1277,7 +1478,7 @@ gst_aggregator_flush (GstAggregator * self)
   GST_DEBUG_OBJECT (self, "Flushing everything");
   GST_OBJECT_LOCK (self);
   priv->send_segment = TRUE;
-  priv->flush_seeking = FALSE;
+  priv->flushing = FALSE;
   priv->tags_changed = FALSE;
   GST_OBJECT_UNLOCK (self);
   if (klass->flush)
@@ -1290,7 +1491,7 @@ gst_aggregator_flush (GstAggregator * self)
 /* Called with GstAggregator's object lock held */
 
 static gboolean
-gst_aggregator_all_flush_stop_received_locked (GstAggregator * self)
+gst_aggregator_all_flush_stop_received (GstAggregator * self, guint32 seqnum)
 {
   GList *tmp;
   GstAggregatorPad *tmppad;
@@ -1298,9 +1499,25 @@ gst_aggregator_all_flush_stop_received_locked (GstAggregator * self)
   for (tmp = GST_ELEMENT (self)->sinkpads; tmp; tmp = tmp->next) {
     tmppad = (GstAggregatorPad *) tmp->data;
 
-    if (_check_pending_flush_stop (tmppad) == FALSE) {
-      GST_DEBUG_OBJECT (tmppad, "Is not last %i -- %i",
-          tmppad->priv->pending_flush_start, tmppad->priv->pending_flush_stop);
+    if (tmppad->priv->last_flush_stop_seqnum != seqnum)
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+/* Called with GstAggregator's object lock held */
+
+static gboolean
+gst_aggregator_all_flush_start_received (GstAggregator * self, guint32 seqnum)
+{
+  GList *tmp;
+  GstAggregatorPad *tmppad;
+
+  for (tmp = GST_ELEMENT (self)->sinkpads; tmp; tmp = tmp->next) {
+    tmppad = (GstAggregatorPad *) tmp->data;
+
+    if (tmppad->priv->last_flush_start_seqnum != seqnum) {
       return FALSE;
     }
   }
@@ -1314,41 +1531,32 @@ gst_aggregator_flush_start (GstAggregator * self, GstAggregatorPad * aggpad,
 {
   GstAggregatorPrivate *priv = self->priv;
   GstAggregatorPadPrivate *padpriv = aggpad->priv;
+  guint32 seqnum = gst_event_get_seqnum (event);
 
   gst_aggregator_pad_set_flushing (aggpad, GST_FLOW_FLUSHING, FALSE);
 
   PAD_FLUSH_LOCK (aggpad);
   PAD_LOCK (aggpad);
-  if (padpriv->pending_flush_start) {
-    GST_DEBUG_OBJECT (aggpad, "Expecting FLUSH_STOP now");
-
-    padpriv->pending_flush_start = FALSE;
-    padpriv->pending_flush_stop = TRUE;
-  }
+  padpriv->last_flush_start_seqnum = seqnum;
   PAD_UNLOCK (aggpad);
 
   GST_OBJECT_LOCK (self);
-  if (priv->flush_seeking) {
-    /* If flush_seeking we forward the first FLUSH_START */
-    if (priv->pending_flush_start) {
-      priv->pending_flush_start = FALSE;
-      GST_OBJECT_UNLOCK (self);
 
-      GST_INFO_OBJECT (self, "Flushing, pausing srcpad task");
-      gst_aggregator_stop_srcpad_task (self, event);
+  if (!priv->flushing && gst_aggregator_all_flush_start_received (self, seqnum)) {
+    /* Make sure we don't forward more than one FLUSH_START */
+    priv->flushing = TRUE;
+    priv->next_seqnum = seqnum;
+    GST_OBJECT_UNLOCK (self);
 
-      GST_INFO_OBJECT (self, "Getting STREAM_LOCK while seeking");
-      GST_PAD_STREAM_LOCK (self->srcpad);
-      GST_LOG_OBJECT (self, "GOT STREAM_LOCK");
-      event = NULL;
-    } else {
-      GST_OBJECT_UNLOCK (self);
-      gst_event_unref (event);
-    }
+    GST_INFO_OBJECT (self, "Flushing, pausing srcpad task");
+    gst_aggregator_stop_srcpad_task (self, event);
+
+    event = NULL;
   } else {
-    GST_OBJECT_UNLOCK (self);
     gst_event_unref (event);
+    GST_OBJECT_UNLOCK (self);
   }
+
   PAD_FLUSH_UNLOCK (aggpad);
 }
 
@@ -1405,38 +1613,44 @@ gst_aggregator_default_sink_event (GstAggregator * self,
     case GST_EVENT_FLUSH_START:
     {
       gst_aggregator_flush_start (self, aggpad, event);
-      /* We forward only in one case: right after flush_seeking */
+      /* We forward only in one case: right after flushing */
       event = NULL;
       goto eat;
     }
     case GST_EVENT_FLUSH_STOP:
     {
+      guint32 seqnum = gst_event_get_seqnum (event);
+
+      PAD_FLUSH_LOCK (aggpad);
+      PAD_LOCK (aggpad);
+      aggpad->priv->last_flush_stop_seqnum = seqnum;
+      PAD_UNLOCK (aggpad);
+
       gst_aggregator_pad_flush (aggpad, self);
+
       GST_OBJECT_LOCK (self);
-      if (priv->flush_seeking) {
-        g_atomic_int_set (&aggpad->priv->pending_flush_stop, FALSE);
-        if (gst_aggregator_all_flush_stop_received_locked (self)) {
-          GST_OBJECT_UNLOCK (self);
-          /* That means we received FLUSH_STOP/FLUSH_STOP on
-           * all sinkpads -- Seeking is Done... sending FLUSH_STOP */
-          gst_aggregator_flush (self);
-          gst_pad_push_event (self->srcpad, event);
-          event = NULL;
-          SRC_LOCK (self);
-          priv->send_eos = TRUE;
-          SRC_BROADCAST (self);
-          SRC_UNLOCK (self);
-
-          GST_INFO_OBJECT (self, "Releasing source pad STREAM_LOCK");
-          GST_PAD_STREAM_UNLOCK (self->srcpad);
-          gst_aggregator_start_srcpad_task (self);
-        } else {
-          GST_OBJECT_UNLOCK (self);
-        }
+      if (priv->flushing
+          && gst_aggregator_all_flush_stop_received (self, seqnum)) {
+        GST_OBJECT_UNLOCK (self);
+        /* That means we received FLUSH_STOP/FLUSH_STOP on
+         * all sinkpads -- Seeking is Done... sending FLUSH_STOP */
+        gst_aggregator_flush (self);
+        gst_pad_push_event (self->srcpad, event);
+        event = NULL;
+        SRC_LOCK (self);
+        priv->send_eos = TRUE;
+        SRC_BROADCAST (self);
+        SRC_UNLOCK (self);
+
+        GST_INFO_OBJECT (self, "Flush stopped");
+
+        gst_aggregator_start_srcpad_task (self);
       } else {
         GST_OBJECT_UNLOCK (self);
       }
 
+      PAD_FLUSH_UNLOCK (aggpad);
+
       /* We never forward the event */
       goto eat;
     }
@@ -1540,6 +1754,61 @@ eat:
   return res;
 }
 
+/* Queue serialized events and let the others go through directly.
+ * The queued events with be handled from the src-pad task in
+ * gst_aggregator_do_events_and_queries().
+ */
+static GstFlowReturn
+gst_aggregator_default_sink_event_pre_queue (GstAggregator * self,
+    GstAggregatorPad * aggpad, GstEvent * event)
+{
+  GstFlowReturn ret = GST_FLOW_OK;
+
+  if (GST_EVENT_IS_SERIALIZED (event)
+      && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP) {
+    SRC_LOCK (self);
+    PAD_LOCK (aggpad);
+
+    if (aggpad->priv->flow_return != GST_FLOW_OK)
+      goto flushing;
+
+    if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
+      GST_OBJECT_LOCK (aggpad);
+      gst_event_copy_segment (event, &aggpad->priv->head_segment);
+      aggpad->priv->head_position = aggpad->priv->head_segment.position;
+      update_time_level (aggpad, TRUE);
+      GST_OBJECT_UNLOCK (aggpad);
+    }
+
+    GST_DEBUG_OBJECT (aggpad, "Store event in queue: %" GST_PTR_FORMAT, event);
+    g_queue_push_head (&aggpad->priv->data, event);
+    SRC_BROADCAST (self);
+    PAD_UNLOCK (aggpad);
+    SRC_UNLOCK (self);
+  } else {
+    GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self);
+
+    if (!klass->sink_event (self, aggpad, event)) {
+      /* Copied from GstPad to convert boolean to a GstFlowReturn in
+       * the event handling func */
+      ret = GST_FLOW_ERROR;
+    }
+  }
+
+  return ret;
+
+flushing:
+  GST_DEBUG_OBJECT (aggpad, "Pad is %s, dropping event",
+      gst_flow_get_name (aggpad->priv->flow_return));
+  PAD_UNLOCK (aggpad);
+  SRC_UNLOCK (self);
+  if (GST_EVENT_IS_STICKY (event))
+    gst_pad_store_sticky_event (GST_PAD (aggpad), event);
+  gst_event_unref (event);
+
+  return aggpad->priv->flow_return;
+}
+
 static gboolean
 gst_aggregator_stop_pad (GstElement * self, GstPad * epad, gpointer user_data)
 {
@@ -1586,6 +1855,14 @@ gst_aggregator_stop (GstAggregator * agg)
 
   gst_aggregator_set_allocation (agg, NULL, NULL, NULL, NULL);
 
+  if (agg->priv->running) {
+    /* As sinkpads get deactivated after the src pad, we
+     * may have restarted the source pad task after receiving
+     * flush events on one of our sinkpads. Stop our src pad
+     * task again if that is the case */
+    gst_aggregator_stop_srcpad_task (agg, NULL);
+  }
+
   return result;
 }
 
@@ -1601,6 +1878,13 @@ gst_aggregator_change_state (GstElement * element, GstStateChange transition)
       if (!gst_aggregator_start (self))
         goto error_start;
       break;
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+      /* Wake up any waiting as now we have a clock and can do
+       * proper waiting on the clock if necessary */
+      SRC_LOCK (self);
+      SRC_BROADCAST (self);
+      SRC_UNLOCK (self);
+      break;
     default:
       break;
   }
@@ -1618,6 +1902,13 @@ gst_aggregator_change_state (GstElement * element, GstStateChange transition)
         GST_ERROR_OBJECT (self, "Subclass failed to stop.");
       }
       break;
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      /* Wake up any waiting as now clock might be gone and we might
+       * need to wait on the condition variable again */
+      SRC_LOCK (self);
+      SRC_BROADCAST (self);
+      SRC_UNLOCK (self);
+      break;
     default:
       break;
   }
@@ -1647,6 +1938,7 @@ gst_aggregator_release_pad (GstElement * element, GstPad * pad)
 
   SRC_LOCK (self);
   gst_aggregator_pad_set_flushing (aggpad, GST_FLOW_FLUSHING, TRUE);
+  gst_buffer_replace (&aggpad->priv->peeked_buffer, NULL);
   gst_element_remove_pad (element, pad);
 
   self->priv->has_peer_latency = FALSE;
@@ -1743,7 +2035,7 @@ gst_aggregator_request_new_pad (GstElement * element,
   return GST_PAD (agg_pad);
 }
 
-/* Must be called with SRC_LOCK held */
+/* Must be called with SRC_LOCK held, temporarily releases it! */
 
 static gboolean
 gst_aggregator_query_latency_unlocked (GstAggregator * self, GstQuery * query)
@@ -1751,7 +2043,10 @@ gst_aggregator_query_latency_unlocked (GstAggregator * self, GstQuery * query)
   gboolean query_ret, live;
   GstClockTime our_latency, min, max;
 
+  /* Temporarily release the lock to do the query. */
+  SRC_UNLOCK (self);
   query_ret = gst_pad_query_default (self->srcpad, GST_OBJECT (self), query);
+  SRC_LOCK (self);
 
   if (!query_ret) {
     GST_WARNING_OBJECT (self, "Latency query failed");
@@ -1777,10 +2072,12 @@ gst_aggregator_query_latency_unlocked (GstAggregator * self, GstQuery * query)
   }
 
   if (min > max && GST_CLOCK_TIME_IS_VALID (max)) {
+    SRC_UNLOCK (self);
     GST_ELEMENT_WARNING (self, CORE, CLOCK, (NULL),
         ("Impossible to configure latency: max %" GST_TIME_FORMAT " < min %"
             GST_TIME_FORMAT ". Add queues or other buffering elements.",
             GST_TIME_ARGS (max), GST_TIME_ARGS (min)));
+    SRC_LOCK (self);
     return FALSE;
   }
 
@@ -1811,7 +2108,8 @@ gst_aggregator_query_latency_unlocked (GstAggregator * self, GstQuery * query)
 }
 
 /*
- * MUST be called with the src_lock held.
+ * MUST be called with the src_lock held. Temporarily releases the lock inside
+ * gst_aggregator_query_latency_unlocked() to do the actual query!
  *
  * See  gst_aggregator_get_latency() for doc
  */
@@ -1889,7 +2187,7 @@ gst_aggregator_send_event (GstElement * element, GstEvent * event)
     GST_OBJECT_LOCK (self);
     gst_segment_do_seek (&GST_AGGREGATOR_PAD (self->srcpad)->segment, rate, fmt,
         flags, start_type, start, stop_type, stop, NULL);
-    self->priv->seqnum = gst_event_get_seqnum (event);
+    self->priv->next_seqnum = gst_event_get_seqnum (event);
     self->priv->first_buffer = FALSE;
     GST_OBJECT_UNLOCK (self);
 
@@ -1897,7 +2195,6 @@ gst_aggregator_send_event (GstElement * element, GstEvent * event)
   }
   GST_STATE_UNLOCK (element);
 
-
   return GST_ELEMENT_CLASS (aggregator_parent_class)->send_event (element,
       event);
 }
@@ -1973,13 +2270,6 @@ gst_aggregator_event_forward_func (GstPad * pad, gpointer user_data)
 
       gst_query_unref (seeking);
     }
-
-    if (evdata->flush) {
-      PAD_LOCK (aggpad);
-      aggpad->priv->pending_flush_start = FALSE;
-      aggpad->priv->pending_flush_stop = FALSE;
-      PAD_UNLOCK (aggpad);
-    }
   } else {
     evdata->one_actually_seeked = TRUE;
   }
@@ -2000,24 +2290,6 @@ gst_aggregator_forward_event_to_all_sinkpads (GstAggregator * self,
   evdata->result = TRUE;
   evdata->one_actually_seeked = FALSE;
 
-  /* We first need to set all pads as flushing in a first pass
-   * as flush_start flush_stop is sometimes sent synchronously
-   * while we send the seek event */
-  if (evdata->flush) {
-    GList *l;
-
-    GST_OBJECT_LOCK (self);
-    for (l = GST_ELEMENT_CAST (self)->sinkpads; l != NULL; l = l->next) {
-      GstAggregatorPad *pad = l->data;
-
-      PAD_LOCK (pad);
-      pad->priv->pending_flush_start = TRUE;
-      pad->priv->pending_flush_stop = FALSE;
-      PAD_UNLOCK (pad);
-    }
-    GST_OBJECT_UNLOCK (self);
-  }
-
   gst_pad_forward (self->srcpad, gst_aggregator_event_forward_func, evdata);
 
   gst_event_unref (evdata->event);
@@ -2043,18 +2315,35 @@ gst_aggregator_do_seek (GstAggregator * self, GstEvent * event)
   flush = flags & GST_SEEK_FLAG_FLUSH;
 
   GST_OBJECT_LOCK (self);
-  if (flush) {
-    priv->pending_flush_start = TRUE;
-    priv->flush_seeking = TRUE;
+
+  if (gst_event_get_seqnum (event) == self->priv->next_seqnum) {
+    evdata.result = TRUE;
+    GST_DEBUG_OBJECT (self, "Dropping duplicated seek event with seqnum %d",
+        self->priv->next_seqnum);
+    GST_OBJECT_UNLOCK (self);
+    goto done;
   }
 
+  self->priv->next_seqnum = gst_event_get_seqnum (event);
+
   gst_segment_do_seek (&GST_AGGREGATOR_PAD (self->srcpad)->segment, rate, fmt,
       flags, start_type, start, stop_type, stop, NULL);
 
   /* Seeking sets a position */
   self->priv->first_buffer = FALSE;
+
+  if (flush)
+    priv->flushing = TRUE;
+
   GST_OBJECT_UNLOCK (self);
 
+  if (flush) {
+    GstEvent *event = gst_event_new_flush_start ();
+
+    gst_event_set_seqnum (event, self->priv->next_seqnum);
+    gst_aggregator_stop_srcpad_task (self, event);
+  }
+
   /* forward the seek upstream */
   evdata.event = event;
   evdata.flush = flush;
@@ -2064,11 +2353,19 @@ gst_aggregator_do_seek (GstAggregator * self, GstEvent * event)
 
   if (!evdata.result || !evdata.one_actually_seeked) {
     GST_OBJECT_LOCK (self);
-    priv->flush_seeking = FALSE;
-    priv->pending_flush_start = FALSE;
+    priv->flushing = FALSE;
     GST_OBJECT_UNLOCK (self);
+
+    /* No flush stop is inbound for us to forward */
+    if (flush) {
+      GstEvent *event = gst_event_new_flush_stop (TRUE);
+
+      gst_event_set_seqnum (event, self->priv->next_seqnum);
+      gst_pad_push_event (self->srcpad, event);
+    }
   }
 
+done:
   GST_INFO_OBJECT (self, "seek done, result: %d", evdata.result);
 
   return evdata.result;
@@ -2150,6 +2447,7 @@ gst_aggregator_src_pad_activate_mode_func (GstPad * pad,
 
   /* deactivating */
   GST_INFO_OBJECT (self, "Deactivating srcpad");
+
   gst_aggregator_stop_srcpad_task (self, FALSE);
 
   return TRUE;
@@ -2203,6 +2501,58 @@ gst_aggregator_default_sink_query (GstAggregator * self,
   return gst_pad_query_default (pad, GST_OBJECT (self), query);
 }
 
+static gboolean
+gst_aggregator_default_sink_query_pre_queue (GstAggregator * self,
+    GstAggregatorPad * aggpad, GstQuery * query)
+{
+  if (GST_QUERY_IS_SERIALIZED (query)) {
+    GstStructure *s;
+    gboolean ret = FALSE;
+
+    SRC_LOCK (self);
+    PAD_LOCK (aggpad);
+
+    if (aggpad->priv->flow_return != GST_FLOW_OK) {
+      SRC_UNLOCK (self);
+      goto flushing;
+    }
+
+    g_queue_push_head (&aggpad->priv->data, query);
+    SRC_BROADCAST (self);
+    SRC_UNLOCK (self);
+
+    while (!gst_aggregator_pad_queue_is_empty (aggpad)
+        && aggpad->priv->flow_return == GST_FLOW_OK) {
+      GST_DEBUG_OBJECT (aggpad, "Waiting for buffer to be consumed");
+      PAD_WAIT_EVENT (aggpad);
+    }
+
+    s = gst_query_writable_structure (query);
+    if (gst_structure_get_boolean (s, "gst-aggregator-retval", &ret))
+      gst_structure_remove_field (s, "gst-aggregator-retval");
+    else
+      g_queue_remove (&aggpad->priv->data, query);
+
+    if (aggpad->priv->flow_return != GST_FLOW_OK)
+      goto flushing;
+
+    PAD_UNLOCK (aggpad);
+
+    return ret;
+  } else {
+    GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self);
+
+    return klass->sink_query (self, aggpad, query);
+  }
+
+flushing:
+  GST_DEBUG_OBJECT (aggpad, "Pad is %s, dropping query",
+      gst_flow_get_name (aggpad->priv->flow_return));
+  PAD_UNLOCK (aggpad);
+
+  return FALSE;
+}
+
 static void
 gst_aggregator_finalize (GObject * object)
 {
@@ -2310,6 +2660,9 @@ gst_aggregator_set_property (GObject * object, guint prop_id,
     case PROP_START_TIME:
       agg->priv->start_time = g_value_get_uint64 (value);
       break;
+    case PROP_EMIT_SIGNALS:
+      agg->priv->emit_signals = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -2337,6 +2690,9 @@ gst_aggregator_get_property (GObject * object, guint prop_id,
     case PROP_START_TIME:
       g_value_set_uint64 (value, agg->priv->start_time);
       break;
+    case PROP_EMIT_SIGNALS:
+      g_value_set_boolean (value, agg->priv->emit_signals);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -2359,6 +2715,7 @@ gst_aggregator_class_init (GstAggregatorClass * klass)
     g_type_class_adjust_private_offset (klass, &aggregator_private_offset);
 
   klass->finish_buffer = gst_aggregator_default_finish_buffer;
+  klass->finish_buffer_list = gst_aggregator_default_finish_buffer_list;
 
   klass->sink_event = gst_aggregator_default_sink_event;
   klass->sink_query = gst_aggregator_default_sink_query;
@@ -2371,6 +2728,11 @@ gst_aggregator_class_init (GstAggregatorClass * klass)
   klass->fixate_src_caps = gst_aggregator_default_fixate_src_caps;
   klass->negotiated_src_caps = gst_aggregator_default_negotiated_src_caps;
 
+  klass->negotiate = gst_aggregator_default_negotiate;
+
+  klass->sink_event_pre_queue = gst_aggregator_default_sink_event_pre_queue;
+  klass->sink_query_pre_queue = gst_aggregator_default_sink_query_pre_queue;
+
   gstelement_class->request_new_pad =
       GST_DEBUG_FUNCPTR (gst_aggregator_request_new_pad);
   gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_aggregator_send_event);
@@ -2423,6 +2785,40 @@ gst_aggregator_class_init (GstAggregatorClass * klass)
           "Start time to use if start-time-selection=set", 0,
           G_MAXUINT64,
           DEFAULT_START_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstAggregator:emit-signals:
+   *
+   * Enables the emission of signals such as #GstAggregator::samples-selected
+   *
+   * Since: 1.18
+   */
+  g_object_class_install_property (gobject_class, PROP_EMIT_SIGNALS,
+      g_param_spec_boolean ("emit-signals", "Emit signals",
+          "Send signals", DEFAULT_EMIT_SIGNALS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstAggregator::samples-selected:
+   * @aggregator: The #GstAggregator that emitted the signal
+   * @segment: The #GstSegment the next output buffer is part of
+   * @pts: The presentation timestamp of the next output buffer
+   * @dts: The decoding timestamp of the next output buffer
+   * @duration: The duration of the next output buffer
+   * @info: (nullable): a #GstStructure containing additional information
+   *
+   * Signals that the #GstAggregator subclass has selected the next set
+   * of input samples it will aggregate. Handlers may call
+   * gst_aggregator_peek_next_sample() at that point.
+   *
+   * Since: 1.18
+   */
+  gst_aggregator_signals[SIGNAL_SAMPLES_SELECTED] =
+      g_signal_new ("samples-selected", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 5,
+      GST_TYPE_SEGMENT | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_CLOCK_TIME,
+      GST_TYPE_CLOCK_TIME, GST_TYPE_CLOCK_TIME,
+      GST_TYPE_STRUCTURE | G_SIGNAL_TYPE_STATIC_SCOPE);
 }
 
 static inline gpointer
@@ -2490,7 +2886,7 @@ gst_aggregator_init (GstAggregator * self, GstAggregatorClass * klass)
 GType
 gst_aggregator_get_type (void)
 {
-  static volatile gsize type = 0;
+  static gsize type = 0;
 
   if (g_once_init_enter (&type)) {
     GType _type;
@@ -2521,6 +2917,8 @@ gst_aggregator_get_type (void)
 static gboolean
 gst_aggregator_pad_has_space (GstAggregator * self, GstAggregatorPad * aggpad)
 {
+  guint64 max_time_level;
+
   /* Empty queue always has space */
   if (aggpad->priv->num_buffers == 0 && aggpad->priv->clipped_buffer == NULL)
     return TRUE;
@@ -2534,8 +2932,13 @@ gst_aggregator_pad_has_space (GstAggregator * self, GstAggregatorPad * aggpad)
   if (self->priv->latency == 0)
     return FALSE;
 
+  /* On top of our latency, we also want to allow buffering up to the
+   * minimum upstream latency to allow queue free sources with lower then
+   * upstream latency. */
+  max_time_level = self->priv->latency + self->priv->upstream_latency_min;
+
   /* Allow no more buffers than the latency */
-  return (aggpad->priv->time_level <= self->priv->latency);
+  return (aggpad->priv->time_level <= max_time_level);
 }
 
 /* Must be called with the PAD_LOCK held */
@@ -2713,111 +3116,23 @@ gst_aggregator_pad_query_func (GstPad * pad, GstObject * parent,
     GstQuery * query)
 {
   GstAggregator *self = GST_AGGREGATOR (parent);
+  GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self);
   GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
 
-  if (GST_QUERY_IS_SERIALIZED (query)) {
-    GstStructure *s;
-    gboolean ret = FALSE;
-
-    SRC_LOCK (self);
-    PAD_LOCK (aggpad);
-
-    if (aggpad->priv->flow_return != GST_FLOW_OK) {
-      SRC_UNLOCK (self);
-      goto flushing;
-    }
-
-    g_queue_push_head (&aggpad->priv->data, query);
-    SRC_BROADCAST (self);
-    SRC_UNLOCK (self);
-
-    while (!gst_aggregator_pad_queue_is_empty (aggpad)
-        && aggpad->priv->flow_return == GST_FLOW_OK) {
-      GST_DEBUG_OBJECT (aggpad, "Waiting for buffer to be consumed");
-      PAD_WAIT_EVENT (aggpad);
-    }
-
-    s = gst_query_writable_structure (query);
-    if (gst_structure_get_boolean (s, "gst-aggregator-retval", &ret))
-      gst_structure_remove_field (s, "gst-aggregator-retval");
-    else
-      g_queue_remove (&aggpad->priv->data, query);
-
-    if (aggpad->priv->flow_return != GST_FLOW_OK)
-      goto flushing;
-
-    PAD_UNLOCK (aggpad);
-
-    return ret;
-  } else {
-    GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (parent);
-
-    return klass->sink_query (self, aggpad, query);
-  }
-
-flushing:
-  GST_DEBUG_OBJECT (aggpad, "Pad is %s, dropping query",
-      gst_flow_get_name (aggpad->priv->flow_return));
-  PAD_UNLOCK (aggpad);
-
-  return FALSE;
+  g_assert (klass->sink_query_pre_queue);
+  return klass->sink_query_pre_queue (self, aggpad, query);
 }
 
-/* Queue serialized events and let the others go through directly.
- * The queued events with be handled from the src-pad task in
- * gst_aggregator_do_events_and_queries().
- */
 static GstFlowReturn
 gst_aggregator_pad_event_func (GstPad * pad, GstObject * parent,
     GstEvent * event)
 {
-  GstFlowReturn ret = GST_FLOW_OK;
   GstAggregator *self = GST_AGGREGATOR (parent);
+  GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self);
   GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
 
-  if (GST_EVENT_IS_SERIALIZED (event)
-      && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP) {
-    SRC_LOCK (self);
-    PAD_LOCK (aggpad);
-
-    if (aggpad->priv->flow_return != GST_FLOW_OK)
-      goto flushing;
-
-    if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
-      GST_OBJECT_LOCK (aggpad);
-      gst_event_copy_segment (event, &aggpad->priv->head_segment);
-      aggpad->priv->head_position = aggpad->priv->head_segment.position;
-      update_time_level (aggpad, TRUE);
-      GST_OBJECT_UNLOCK (aggpad);
-    }
-
-    GST_DEBUG_OBJECT (aggpad, "Store event in queue: %" GST_PTR_FORMAT, event);
-    g_queue_push_head (&aggpad->priv->data, event);
-    SRC_BROADCAST (self);
-    PAD_UNLOCK (aggpad);
-    SRC_UNLOCK (self);
-  } else {
-    GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (parent);
-
-    if (!klass->sink_event (self, aggpad, event)) {
-      /* Copied from GstPad to convert boolean to a GstFlowReturn in
-       * the event handling func */
-      ret = GST_FLOW_ERROR;
-    }
-  }
-
-  return ret;
-
-flushing:
-  GST_DEBUG_OBJECT (aggpad, "Pad is %s, dropping event",
-      gst_flow_get_name (aggpad->priv->flow_return));
-  PAD_UNLOCK (aggpad);
-  SRC_UNLOCK (self);
-  if (GST_EVENT_IS_STICKY (event))
-    gst_pad_store_sticky_event (pad, event);
-  gst_event_unref (event);
-
-  return aggpad->priv->flow_return;
+  g_assert (klass->sink_event_pre_queue);
+  return klass->sink_event_pre_queue (self, aggpad, event);
 }
 
 static gboolean
@@ -2885,6 +3200,7 @@ gst_aggregator_pad_finalize (GObject * object)
 {
   GstAggregatorPad *pad = (GstAggregatorPad *) object;
 
+  gst_buffer_replace (&pad->priv->peeked_buffer, NULL);
   g_cond_clear (&pad->priv->event_cond);
   g_mutex_clear (&pad->priv->flush_lock);
   g_mutex_clear (&pad->priv->lock);
@@ -2947,6 +3263,8 @@ gst_aggregator_pad_class_init (GstAggregatorPadClass * klass)
 
   /**
    * GstAggregatorPad:buffer-consumed:
+   * @aggregator: The #GstAggregator that emitted the signal
+   * @buffer: The buffer that was consumed
    *
    * Signals that a buffer was consumed. As aggregator pads store buffers
    * in an internal queue, there is no direct match between input and output
@@ -2957,8 +3275,7 @@ gst_aggregator_pad_class_init (GstAggregatorPadClass * klass)
    */
   gst_aggregator_pad_signals[PAD_SIGNAL_BUFFER_CONSUMED] =
       g_signal_new ("buffer-consumed", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_generic,
-      G_TYPE_NONE, 1, GST_TYPE_BUFFER);
+      G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_BUFFER);
 
   /**
    * GstAggregatorPad:emit-signals:
@@ -2991,10 +3308,12 @@ gst_aggregator_pad_init (GstAggregatorPad * pad)
 
 /* Must be called with the PAD_LOCK held */
 static void
-gst_aggregator_pad_buffer_consumed (GstAggregatorPad * pad, GstBuffer * buffer)
+gst_aggregator_pad_buffer_consumed (GstAggregatorPad * pad, GstBuffer * buffer,
+    gboolean dequeued)
 {
-  pad->priv->num_buffers--;
-  GST_TRACE_OBJECT (pad, "Consuming buffer %" GST_PTR_FORMAT, buffer);
+  if (dequeued)
+    pad->priv->num_buffers--;
+
   if (buffer && pad->priv->emit_signals) {
     g_signal_emit (pad, gst_aggregator_pad_signals[PAD_SIGNAL_BUFFER_CONSUMED],
         0, buffer);
@@ -3035,7 +3354,7 @@ gst_aggregator_pad_clip_buffer_unlocked (GstAggregatorPad * pad)
       buffer = aggclass->clip (self, pad, buffer);
 
       if (buffer == NULL) {
-        gst_aggregator_pad_buffer_consumed (pad, buffer);
+        gst_aggregator_pad_buffer_consumed (pad, buffer, TRUE);
         GST_TRACE_OBJECT (pad, "Clipping consumed the buffer");
       }
     }
@@ -3053,28 +3372,50 @@ gst_aggregator_pad_clip_buffer_unlocked (GstAggregatorPad * pad)
  *
  * Steal the ref to the buffer currently queued in @pad.
  *
- * Returns: (transfer full): The buffer in @pad or NULL if no buffer was
+ * Returns: (nullable) (transfer full): The buffer in @pad or NULL if no buffer was
  *   queued. You should unref the buffer after usage.
  */
 GstBuffer *
 gst_aggregator_pad_pop_buffer (GstAggregatorPad * pad)
 {
-  GstBuffer *buffer;
+  GstBuffer *buffer = NULL;
 
   PAD_LOCK (pad);
 
-  if (pad->priv->flow_return != GST_FLOW_OK) {
-    PAD_UNLOCK (pad);
-    return NULL;
+  /* If the subclass has already peeked a buffer, we guarantee
+   * that it receives the same buffer, no matter if the pad has
+   * errored out / been flushed in the meantime.
+   */
+  if (pad->priv->peeked_buffer) {
+    buffer = pad->priv->peeked_buffer;
+    goto done;
   }
 
-  gst_aggregator_pad_clip_buffer_unlocked (pad);
+  if (pad->priv->flow_return != GST_FLOW_OK)
+    goto done;
 
+  gst_aggregator_pad_clip_buffer_unlocked (pad);
   buffer = pad->priv->clipped_buffer;
 
+done:
   if (buffer) {
-    pad->priv->clipped_buffer = NULL;
-    gst_aggregator_pad_buffer_consumed (pad, buffer);
+    if (pad->priv->clipped_buffer != NULL) {
+      /* Here we still hold a reference to both the clipped buffer
+       * and possibly the peeked buffer, we transfer the first and
+       * potentially release the second
+       */
+      gst_aggregator_pad_buffer_consumed (pad, buffer, TRUE);
+      pad->priv->clipped_buffer = NULL;
+      gst_buffer_replace (&pad->priv->peeked_buffer, NULL);
+    } else {
+      /* Here our clipped buffer has already been released, for
+       * example because of a flush. We thus transfer the reference
+       * to the peeked buffer to the caller, and we don't decrement
+       * pad.num_buffers as it has already been done elsewhere
+       */
+      gst_aggregator_pad_buffer_consumed (pad, buffer, FALSE);
+      pad->priv->peeked_buffer = NULL;
+    }
     GST_DEBUG_OBJECT (pad, "Consumed: %" GST_PTR_FORMAT, buffer);
   }
 
@@ -3109,31 +3450,36 @@ gst_aggregator_pad_drop_buffer (GstAggregatorPad * pad)
  * gst_aggregator_pad_peek_buffer:
  * @pad: the pad to get buffer from
  *
- * Returns: (transfer full): A reference to the buffer in @pad or
+ * Returns: (nullable) (transfer full): A reference to the buffer in @pad or
  * NULL if no buffer was queued. You should unref the buffer after
  * usage.
  */
 GstBuffer *
 gst_aggregator_pad_peek_buffer (GstAggregatorPad * pad)
 {
-  GstBuffer *buffer;
+  GstBuffer *buffer = NULL;
 
   PAD_LOCK (pad);
 
-  if (pad->priv->flow_return != GST_FLOW_OK) {
-    PAD_UNLOCK (pad);
-    return NULL;
+  if (pad->priv->peeked_buffer) {
+    buffer = gst_buffer_ref (pad->priv->peeked_buffer);
+    goto done;
   }
 
+  if (pad->priv->flow_return != GST_FLOW_OK)
+    goto done;
+
   gst_aggregator_pad_clip_buffer_unlocked (pad);
 
   if (pad->priv->clipped_buffer) {
     buffer = gst_buffer_ref (pad->priv->clipped_buffer);
+    pad->priv->peeked_buffer = gst_buffer_ref (buffer);
   } else {
     buffer = NULL;
   }
-  PAD_UNLOCK (pad);
 
+done:
+  PAD_UNLOCK (pad);
   return buffer;
 }
 
@@ -3155,8 +3501,15 @@ gst_aggregator_pad_has_buffer (GstAggregatorPad * pad)
   gboolean has_buffer;
 
   PAD_LOCK (pad);
-  gst_aggregator_pad_clip_buffer_unlocked (pad);
-  has_buffer = (pad->priv->clipped_buffer != NULL);
+
+  if (pad->priv->peeked_buffer) {
+    has_buffer = TRUE;
+  } else {
+    gst_aggregator_pad_clip_buffer_unlocked (pad);
+    has_buffer = (pad->priv->clipped_buffer != NULL);
+    if (has_buffer)
+      pad->priv->peeked_buffer = gst_buffer_ref (pad->priv->clipped_buffer);
+  }
   PAD_UNLOCK (pad);
 
   return has_buffer;
@@ -3261,7 +3614,7 @@ gst_aggregator_set_latency (GstAggregator * self,
  * gst_aggregator_get_buffer_pool:
  * @self: a #GstAggregator
  *
- * Returns: (transfer full): the instance of the #GstBufferPool used
+ * Returns: (transfer full) (nullable): the instance of the #GstBufferPool used
  * by @trans; free it after use it
  */
 GstBufferPool *
@@ -3283,9 +3636,9 @@ gst_aggregator_get_buffer_pool (GstAggregator * self)
 /**
  * gst_aggregator_get_allocator:
  * @self: a #GstAggregator
- * @allocator: (out) (allow-none) (transfer full): the #GstAllocator
+ * @allocator: (out) (optional) (nullable) (transfer full): the #GstAllocator
  * used
- * @params: (out) (allow-none) (transfer full): the
+ * @params: (out caller-allocates) (optional): the
  * #GstAllocationParams of @allocator
  *
  * Lets #GstAggregator sub-classes get the memory @allocator
@@ -3311,7 +3664,7 @@ gst_aggregator_get_allocator (GstAggregator * self,
  * gst_aggregator_simple_get_next_time:
  * @self: A #GstAggregator
  *
- * This is a simple #GstAggregator::get_next_time implementation that
+ * This is a simple #GstAggregatorClass::get_next_time implementation that
  * just looks at the #GstSegment on the srcpad of the aggregator and bases
  * the next time on the running time there.
  *
@@ -3343,3 +3696,69 @@ gst_aggregator_simple_get_next_time (GstAggregator * self)
 
   return next_time;
 }
+
+/**
+ * gst_aggregator_update_segment:
+ *
+ * Subclasses should use this to update the segment on their
+ * source pad, instead of directly pushing new segment events
+ * downstream.
+ *
+ * Subclasses MUST call this before gst_aggregator_selected_samples(),
+ * if it is used at all.
+ *
+ * Since: 1.18
+ */
+void
+gst_aggregator_update_segment (GstAggregator * self, const GstSegment * segment)
+{
+  g_return_if_fail (GST_IS_AGGREGATOR (self));
+  g_return_if_fail (segment != NULL);
+
+  GST_INFO_OBJECT (self, "Updating srcpad segment: %" GST_SEGMENT_FORMAT,
+      segment);
+
+  GST_OBJECT_LOCK (self);
+  GST_AGGREGATOR_PAD (self->srcpad)->segment = *segment;
+  self->priv->send_segment = TRUE;
+  /* we have a segment from the subclass now and really shouldn't override
+   * anything in that segment anymore, like the segment.position */
+  self->priv->first_buffer = FALSE;
+  GST_OBJECT_UNLOCK (self);
+}
+
+/**
+ * gst_aggregator_selected_samples:
+ * @pts: The presentation timestamp of the next output buffer
+ * @dts: The decoding timestamp of the next output buffer
+ * @duration: The duration of the next output buffer
+ * @info: (nullable): a #GstStructure containing additional information
+ *
+ * Subclasses should call this when they have prepared the
+ * buffers they will aggregate for each of their sink pads, but
+ * before using any of the properties of the pads that govern
+ * *how* aggregation should be performed, for example z-index
+ * for video aggregators.
+ *
+ * If gst_aggregator_update_segment() is used by the subclass,
+ * it MUST be called before gst_aggregator_selected_samples().
+ *
+ * This function MUST only be called from the #GstAggregatorClass::aggregate()
+ * function.
+ *
+ * Since: 1.18
+ */
+void
+gst_aggregator_selected_samples (GstAggregator * self,
+    GstClockTime pts, GstClockTime dts, GstClockTime duration,
+    GstStructure * info)
+{
+  g_return_if_fail (GST_IS_AGGREGATOR (self));
+
+  if (self->priv->emit_signals) {
+    g_signal_emit (self, gst_aggregator_signals[SIGNAL_SAMPLES_SELECTED], 0,
+        &GST_AGGREGATOR_PAD (self->srcpad)->segment, pts, dts, duration, info);
+  }
+
+  self->priv->selected_samples_called_or_warned = TRUE;
+}
index 09bbb9b..86fc70f 100644 (file)
@@ -235,6 +235,14 @@ struct _GstAggregator
  *                     downstream allocation query.
  * @propose_allocation: Optional.
  *                     Allows the subclass to handle the allocation query from upstream.
+ * @negotiate: Optional.
+ *             Negotiate the caps with the peer (Since: 1.18).
+ * @sink_event_pre_queue: Optional.
+ *                        Called when an event is received on a sink pad before queueing up
+ *                        serialized events. The subclass should always chain up (Since: 1.18).
+ * @sink_query_pre_queue: Optional.
+ *                        Called when a query is received on a sink pad before queueing up
+ *                        serialized queries. The subclass should always chain up (Since: 1.18).
  *
  * The aggregator base class will handle in a thread-safe way all manners of
  * concurrent flushes, seeks, pad additions and removals, leaving to the
@@ -311,8 +319,39 @@ struct _GstAggregatorClass {
                                            GstAggregatorPad * pad,
                                            GstQuery * decide_query,
                                            GstQuery * query);
+
+  gboolean          (*negotiate) (GstAggregator * self);
+
+  GstFlowReturn     (*sink_event_pre_queue)     (GstAggregator    *  aggregator,
+                                                 GstAggregatorPad *  aggregator_pad,
+                                                 GstEvent         *  event);
+
+  gboolean          (*sink_query_pre_queue)     (GstAggregator    *  aggregator,
+                                                 GstAggregatorPad *  aggregator_pad,
+                                                 GstQuery         *  query);
+
+  /**
+   * GstAggregatorClass::finish_buffer_list:
+   *
+   * Optional. Equivalent of #GstAggregatorClass::finish_buffer for
+   * buffer lists.
+   *
+   * Since: 1.18
+   */
+  GstFlowReturn     (*finish_buffer_list) (GstAggregator    * aggregator,
+                                           GstBufferList    * bufferlist);
+  /**
+   * GstAggregatorClass::peek_next_sample:
+   *
+   * See gst_aggregator_peek_next_sample().
+   *
+   * Since: 1.18
+   */
+  GstSample *       (*peek_next_sample)         (GstAggregator *aggregator,
+                                                 GstAggregatorPad * aggregator_pad);
+
   /*< private >*/
-  gpointer          _gst_reserved[GST_PADDING_LARGE];
+  gpointer          _gst_reserved[GST_PADDING_LARGE-5];
 };
 
 /************************************
@@ -338,10 +377,17 @@ GstFlowReturn  gst_aggregator_finish_buffer         (GstAggregator
                                                      GstBuffer                    *  buffer);
 
 GST_BASE_API
+GstFlowReturn  gst_aggregator_finish_buffer_list    (GstAggregator                *  aggregator,
+                                                     GstBufferList                *  bufferlist);
+
+GST_BASE_API
 void           gst_aggregator_set_src_caps          (GstAggregator                *  self,
                                                      GstCaps                      *  caps);
 
 GST_BASE_API
+gboolean        gst_aggregator_negotiate            (GstAggregator                * self);
+
+GST_BASE_API
 void           gst_aggregator_set_latency           (GstAggregator                *  self,
                                                      GstClockTime                    min_latency,
                                                      GstClockTime                    max_latency);
@@ -363,12 +409,44 @@ void            gst_aggregator_get_allocator       (GstAggregator
 GST_BASE_API
 GstClockTime    gst_aggregator_simple_get_next_time (GstAggregator                * self);
 
+GST_BASE_API
+void            gst_aggregator_update_segment       (GstAggregator                * self,
+                                                     const GstSegment             * segment);
+
+GST_BASE_API
+GstSample     * gst_aggregator_peek_next_sample     (GstAggregator *self,
+                                                     GstAggregatorPad * pad);
+
+GST_BASE_API
+void            gst_aggregator_selected_samples     (GstAggregator                * self,
+                                                     GstClockTime                   pts,
+                                                     GstClockTime                   dts,
+                                                     GstClockTime                   duration,
+                                                     GstStructure                 * info);
+
+/**
+ * GstAggregatorStartTimeSelection:
+ * @GST_AGGREGATOR_START_TIME_SELECTION_ZERO: Start at running time 0.
+ * @GST_AGGREGATOR_START_TIME_SELECTION_FIRST: Start at the running time of
+ * the first buffer that is received.
+ * @GST_AGGREGATOR_START_TIME_SELECTION_SET: Start at the running time
+ * selected by the `start-time` property.
+ *
+ * Since: 1.18
+ */
+typedef enum
+{
+  GST_AGGREGATOR_START_TIME_SELECTION_ZERO,
+  GST_AGGREGATOR_START_TIME_SELECTION_FIRST,
+  GST_AGGREGATOR_START_TIME_SELECTION_SET
+} GstAggregatorStartTimeSelection;
+
+GST_BASE_API
+GType           gst_aggregator_start_time_selection_get_type (void);
 
 G_END_DECLS
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAggregator, gst_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAggregatorPad, gst_object_unref)
-#endif
 
 #endif /* __GST_AGGREGATOR_H__ */
index f7d540a..f0d489e 100644 (file)
  *
  * ## Set-up phase
  *
- *  * #GstBaseParse calls #GstBaseParseClass.start() to inform subclass
+ *  * #GstBaseParse calls #GstBaseParseClass::start to inform subclass
  *    that data processing is about to start now.
  *
- *  * #GstBaseParse class calls #GstBaseParseClass.set_sink_caps() to
+ *  * #GstBaseParse class calls #GstBaseParseClass::set_sink_caps to
  *    inform the subclass about incoming sinkpad caps. Subclass could
  *    already set the srcpad caps accordingly, but this might be delayed
  *    until calling gst_base_parse_finish_frame() with a non-queued frame.
  *    #GstAdapter.
  *
  *  * A buffer of (at least) min_frame_size bytes is passed to subclass
- *    with #GstBaseParseClass.handle_frame(). Subclass checks the contents
+ *    with #GstBaseParseClass::handle_frame. Subclass checks the contents
  *    and can optionally return #GST_FLOW_OK along with an amount of data
  *    to be skipped to find a valid frame (which will result in a
  *    subsequent DISCONT).  If, otherwise, the buffer does not hold a
- *    complete frame, #GstBaseParseClass.handle_frame() can merely return
+ *    complete frame, #GstBaseParseClass::handle_frame can merely return
  *    and will be called again when additional data is available.  In push
  *    mode this amounts to an additional input buffer (thus minimal
  *    additional latency), in pull mode this amounts to some arbitrary
@@ -88,7 +88,7 @@
  *    data while simultaneously providing custom output data.  Note that
  *    baseclass performs some processing (such as tracking overall consumed
  *    data rate versus duration) for each finished frame, but other state
- *    is only updated upon each call to #GstBaseParseClass.handle_frame()
+ *    is only updated upon each call to #GstBaseParseClass::handle_frame
  *    (such as tracking upstream input timestamp).
  *
  *    Subclass is also responsible for setting the buffer metadata
  *    duration obtained from configuration (see below), and offset
  *    if meaningful (in pull mode).
  *
- *    Note that #GstBaseParseClass.handle_frame() might receive any small
+ *    Note that #GstBaseParseClass::handle_frame might receive any small
  *    amount of input data when leftover data is being drained (e.g. at
  *    EOS).
  *
  *  * As part of finish frame processing, just prior to actually pushing
  *    the buffer in question, it is passed to
- *    #GstBaseParseClass.pre_push_frame() which gives subclass yet one last
+ *    #GstBaseParseClass::pre_push_frame which gives subclass yet one last
  *    chance to examine buffer metadata, or to send some custom (tag)
  *    events, or to perform custom (segment) filtering.
  *
  *  * During the parsing process #GstBaseParseClass will handle both srcpad
  *    and sinkpad events. They will be passed to subclass if
- *    #GstBaseParseClass.event() or #GstBaseParseClass.src_event()
+ *    #GstBaseParseClass::sink_event or #GstBaseParseClass::src_event
  *    implementations have been provided.
  *
  * ## Shutdown phase
  *
- * * #GstBaseParse class calls #GstBaseParseClass.stop() to inform the
+ * * #GstBaseParse class calls #GstBaseParseClass::stop to inform the
  *   subclass that data parsing will be stopped.
  *
  * Subclass is responsible for providing pad template caps for source and
  * sink pads. The pads need to be named "sink" and "src". It also needs to
  * set the fixed caps on srcpad, when the format is ensured (e.g.  when
- * base class calls subclass' #GstBaseParseClass.set_sink_caps() function).
+ * base class calls subclass' #GstBaseParseClass::set_sink_caps function).
  *
  * This base class uses %GST_FORMAT_DEFAULT as a meaning of frames. So,
  * subclass conversion routine needs to know that conversion from
  * * Inform base class how big data chunks should be retrieved. This is
  *   done with gst_base_parse_set_min_frame_size() function.
  * * Examine data chunks passed to subclass with
- *   #GstBaseParseClass.handle_frame() and pass proper frame(s) to
+ *   #GstBaseParseClass::handle_frame and pass proper frame(s) to
  *   gst_base_parse_finish_frame(), and setting src pad caps and timestamps
  *   on frame.
  * * Provide conversion functions
  *   metadata (which will be taken from upstream as much as
  *   possible). Internally keeping track of frame durations and respective
  *   sizes that have been pushed provides #GstBaseParse with an estimated
- *   bitrate. A default #GstBaseParseClass.convert() (used if not
+ *   bitrate. A default #GstBaseParseClass::convert (used if not
  *   overridden) will then use these rates to perform obvious conversions.
  *   These rates are also used to update (estimated) duration at regular
  *   frame intervals.
@@ -391,7 +391,7 @@ static void gst_base_parse_init (GstBaseParse * parse,
 GType
 gst_base_parse_get_type (void)
 {
-  static volatile gsize base_parse_type = 0;
+  static gsize base_parse_type = 0;
 
   if (g_once_init_enter (&base_parse_type)) {
     static const GTypeInfo base_parse_info = {
@@ -702,8 +702,9 @@ gst_base_parse_get_property (GObject * object, guint prop_id, GValue * value,
  * Copies a #GstBaseParseFrame.
  *
  * Returns: A copy of @frame
+ *
+ * Since: 1.12.1
  */
-
 GstBaseParseFrame *
 gst_base_parse_frame_copy (GstBaseParseFrame * frame)
 {
@@ -1014,15 +1015,60 @@ static GstFlowReturn
 gst_base_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
 {
   GstBuffer *buffer = frame->buffer;
+  gboolean must_approximate_pts = !GST_BUFFER_PTS_IS_VALID (buffer)
+      && GST_CLOCK_TIME_IS_VALID (parse->priv->next_pts);
+  gboolean must_approximate_dts = !GST_BUFFER_DTS_IS_VALID (buffer)
+      && GST_CLOCK_TIME_IS_VALID (parse->priv->next_dts);
 
-  if (!GST_BUFFER_PTS_IS_VALID (buffer) &&
-      GST_CLOCK_TIME_IS_VALID (parse->priv->next_pts)) {
+  if (must_approximate_pts) {
     GST_BUFFER_PTS (buffer) = parse->priv->next_pts;
+    if (!must_approximate_dts
+        && GST_BUFFER_DTS (buffer) > parse->priv->next_pts
+        && GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS (buffer))) {
+      /* Can't present a frame before it's decoded: change the pts! This can
+       * happen, for example, when accumulating rounding errors from the
+       * buffer durations. Assume DTS is correct because only PTS is
+       * approximated here */
+      GST_LOG_OBJECT (parse,
+          "Found DTS (%" GST_TIME_FORMAT ") > PTS (%" GST_TIME_FORMAT
+          "), set PTS = DTS", GST_TIME_ARGS (GST_BUFFER_DTS (buffer)),
+          GST_TIME_ARGS (GST_BUFFER_PTS (buffer)));
+      GST_BUFFER_PTS (buffer) = GST_BUFFER_DTS (buffer);
+    }
+  }
+
+  if (must_approximate_dts) {
+    if (!must_approximate_pts
+        && GST_BUFFER_PTS (buffer) < parse->priv->next_dts) {
+      /* Can't present a frame before it's decoded: change the dts! This can
+       * happen, for example, when accumulating rounding errors from the
+       * buffer durations. Assume PTS is correct because only DTS is
+       * approximated here */
+      GST_LOG_OBJECT (parse,
+          "Found DTS (%" GST_TIME_FORMAT ") > PTS (%" GST_TIME_FORMAT
+          "), set DTS = PTS", GST_TIME_ARGS (GST_BUFFER_DTS (buffer)),
+          GST_TIME_ARGS (GST_BUFFER_PTS (buffer)));
+      GST_BUFFER_DTS (buffer) = GST_BUFFER_PTS (buffer);
+    } else {
+      GST_BUFFER_DTS (buffer) = parse->priv->next_dts;
+    }
   }
-  if (!GST_BUFFER_DTS_IS_VALID (buffer) &&
-      GST_CLOCK_TIME_IS_VALID (parse->priv->next_dts)) {
-    GST_BUFFER_DTS (buffer) = parse->priv->next_dts;
+
+  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (buffer))
+      && GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS (buffer))
+      && GST_BUFFER_PTS (buffer) < GST_BUFFER_DTS (buffer)) {
+    /* Can't present a frame before it's decoded: change the pts! This can
+     * happen, for example, when accumulating rounding errors from the buffer
+     * durations. PTS and DTS are either both approximated or both from the
+     * original buffer timestamp. Set PTS = DTS because the opposite has been
+     * observed to cause DTS going backwards */
+    GST_LOG_OBJECT (parse,
+        "Found DTS (%" GST_TIME_FORMAT ") > PTS (%" GST_TIME_FORMAT
+        "), set PTS = DTS", GST_TIME_ARGS (GST_BUFFER_DTS (buffer)),
+        GST_TIME_ARGS (GST_BUFFER_PTS (buffer)));
+    GST_BUFFER_PTS (buffer) = GST_BUFFER_DTS (buffer);
   }
+
   if (!GST_BUFFER_DURATION_IS_VALID (buffer) &&
       GST_CLOCK_TIME_IS_VALID (parse->priv->frame_duration)) {
     GST_BUFFER_DURATION (buffer) = parse->priv->frame_duration;
@@ -1095,8 +1141,11 @@ update_upstream_provided (GQuark field_id, const GValue * value,
   caps_size = gst_caps_get_size (default_caps);
   for (i = 0; i < caps_size; i++) {
     GstStructure *structure = gst_caps_get_structure (default_caps, i);
-    if (gst_structure_id_has_field (structure, field_id))
+    if (!gst_structure_id_has_field (structure, field_id)) {
       gst_structure_id_set_value (structure, field_id, value);
+    }
+    /* XXX: maybe try to fixate better than gst_caps_fixate() the
+     * downstream caps based on upstream values if possible */
   }
 
   return TRUE;
@@ -1309,7 +1358,7 @@ gst_base_parse_sink_event_default (GstBaseParse * parse, GstEvent * event)
         /* not considered BYTE seekable if it is talking to us in TIME,
          * whatever else it might claim */
         parse->priv->upstream_seekable = FALSE;
-        next_dts = in_segment->start;
+        next_dts = GST_CLOCK_TIME_NONE;
         gst_event_copy_segment (event, &out_segment);
       }
 
@@ -1717,7 +1766,7 @@ gst_base_parse_src_event_default (GstBaseParse * parse, GstEvent * event)
  * @dest_format: #GstFormat defining the converted format.
  * @dest_value: (out): Pointer where the conversion result will be put.
  *
- * Default implementation of #GstBaseParseClass.convert().
+ * Default implementation of #GstBaseParseClass::convert.
  *
  * Returns: %TRUE if conversion was successful.
  */
@@ -1984,6 +2033,8 @@ gst_base_parse_add_index_entry (GstBaseParse * parse, guint64 offset,
   gboolean ret = FALSE;
   GstIndexAssociation associations[2];
 
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (ts), FALSE);
+
   GST_LOG_OBJECT (parse, "Adding key=%d index entry %" GST_TIME_FORMAT
       " @ offset 0x%08" G_GINT64_MODIFIER "x", key, GST_TIME_ARGS (ts), offset);
 
@@ -2537,43 +2588,6 @@ gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
   /* Push pending events, including SEGMENT events */
   gst_base_parse_push_pending_events (parse);
 
-  /* 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_PAD_MODE_PULL ||
-          parse->priv->upstream_seekable)) {
-    /* handle gaps */
-    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.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))) {
-        GstEvent *topush;
-
-        GST_DEBUG_OBJECT (parse,
-            "Gap of %" G_GINT64_FORMAT " ns detected in stream " "(%"
-            GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "). "
-            "Sending updated SEGMENT events", diff,
-            GST_TIME_ARGS (parse->segment.position),
-            GST_TIME_ARGS (last_start));
-
-        /* skip gap FIXME */
-        topush = gst_event_new_segment (&parse->segment);
-        if (parse->priv->segment_seqnum != GST_SEQNUM_INVALID)
-          gst_event_set_seqnum (topush, parse->priv->segment_seqnum);
-        gst_pad_push_event (parse->srcpad, topush);
-
-        parse->segment.position = last_start;
-      }
-    }
-  }
-
   /* update bitrates and optionally post corresponding tags
    * (following newsegment) */
   gst_base_parse_update_bitrates (parse, frame);
@@ -3155,6 +3169,7 @@ gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
       GST_DEBUG ("All the buffer is skipped");
       parse->priv->offset += bsize;
       parse->priv->sync_offset = parse->priv->offset;
+      gst_buffer_unref (buffer);
       return GST_FLOW_OK;
     }
     buffer = gst_buffer_make_writable (buffer);
@@ -3376,7 +3391,6 @@ done:
   return ret;
 }
 
-#ifdef TIZEN_FEATURE_UPSTREAM
 /* Return the number of bytes available in the cached
  * read buffer, if any */
 static guint
@@ -3392,7 +3406,6 @@ gst_base_parse_get_cached_available (GstBaseParse * parse)
   }
   return 0;
 }
-#endif
 
 /* pull @size bytes at current offset,
  * i.e. at least try to and possibly return a shorter buffer if near the end */
@@ -3401,9 +3414,8 @@ gst_base_parse_pull_range (GstBaseParse * parse, guint size,
     GstBuffer ** buffer)
 {
   GstFlowReturn ret = GST_FLOW_OK;
-#ifdef TIZEN_FEATURE_UPSTREAM
   guint read_size;
-#endif
+
   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
 
   /* Caching here actually makes much less difference than one would expect.
@@ -3417,11 +3429,9 @@ gst_base_parse_pull_range (GstBaseParse * parse, guint size,
       *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;
-#ifdef TIZEN_FEATURE_UPSTREAM
       GST_LOG_OBJECT (parse,
           "Satisfying read request of %u bytes from cached buffer with offset %"
           G_GINT64_FORMAT, size, cache_offset);
-#endif
       return GST_FLOW_OK;
     }
     /* not enough data in the cache, free cache and get a new one */
@@ -3430,7 +3440,6 @@ gst_base_parse_pull_range (GstBaseParse * parse, guint size,
   }
 
   /* refill the cache */
-#ifdef TIZEN_FEATURE_UPSTREAM
   read_size = MAX (64 * 1024, size);
   GST_LOG_OBJECT (parse,
       "Reading cache buffer of %u bytes from offset %" G_GINT64_FORMAT,
@@ -3438,11 +3447,6 @@ gst_base_parse_pull_range (GstBaseParse * parse, guint size,
   ret =
       gst_pad_pull_range (parse->sinkpad, parse->priv->offset, read_size,
       &parse->priv->cache);
-#else
-  ret =
-      gst_pad_pull_range (parse->sinkpad, parse->priv->offset, MAX (size,
-          64 * 1024), &parse->priv->cache);
-#endif
   if (ret != GST_FLOW_OK) {
     parse->priv->cache = NULL;
     return ret;
@@ -3459,9 +3463,7 @@ gst_base_parse_pull_range (GstBaseParse * parse, guint size,
     return GST_FLOW_OK;
   }
 
-#ifdef TIZEN_FEATURE_UPSTREAM
   GST_BUFFER_OFFSET (parse->priv->cache) = parse->priv->offset;
-#endif
 
   *buffer =
       gst_buffer_copy_region (parse->priv->cache, GST_BUFFER_COPY_ALL, 0, size);
@@ -3534,7 +3536,7 @@ exit:
 
 /* PULL mode:
  * pull and scan for next frame starting from current offset
- * ajusts sync, drain and offset going along */
+ * adjusts sync, drain and offset going along */
 static GstFlowReturn
 gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass)
 {
@@ -3547,7 +3549,6 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass)
   GST_LOG_OBJECT (parse, "scanning for frame at offset %" G_GUINT64_FORMAT
       " (%#" G_GINT64_MODIFIER "x)", parse->priv->offset, parse->priv->offset);
 
-#ifdef TIZEN_FEATURE_UPSTREAM
   /* let's make this efficient for all subclass once and for all;
    * maybe it does not need this much, but in the latter case, we know we are
    * in pull mode here and might as well try to read and supply more anyway,
@@ -3556,19 +3557,13 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass)
   fsize = gst_base_parse_get_cached_available (parse);
   if (fsize < 1024)
     fsize = 64 * 1024;
-#else
-  /* let's make this efficient for all subclass once and for all;
-   * maybe it does not need this much, but in the latter case, we know we are
-   * in pull mode here and might as well try to read and supply more anyway
-   * (so does the buffer caching mechanism) */
-  fsize = 64 * 1024;
-#endif
 
   while (TRUE) {
     min_size = MAX (parse->priv->min_frame_size, fsize);
 
     GST_LOG_OBJECT (parse, "reading buffer size %u", min_size);
 
+    parse->priv->drain = FALSE;
     ret = gst_base_parse_pull_range (parse, min_size, &buffer);
     if (ret != GST_FLOW_OK)
       goto done;
@@ -3590,12 +3585,8 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass)
           GST_ERROR_OBJECT (parse, "Failed to detect format but draining");
           return GST_FLOW_ERROR;
         } else {
-#ifdef TIZEN_FEATURE_UPSTREAM
           /* Double our frame size, or increment by at most 64KB */
           fsize += MIN (fsize, 64 * 1024);
-#else
-          fsize += 64 * 1024;
-#endif
           gst_buffer_unref (buffer);
           continue;
         }
@@ -3626,19 +3617,7 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass)
       GST_LOG_OBJECT (parse, "frame finished, breaking loop");
       break;
     }
-#ifndef TIZEN_FEATURE_UPSTREAM
-    if (!skip && parse->priv->drain) {
-      /* nothing flushed, no skip and draining, so nothing left to do */
-      GST_LOG_OBJECT (parse, "no activity or result when draining; "
-          "breaking loop and marking EOS");
-      ret = GST_FLOW_EOS;
-      break;
-    }
-    /* otherwise, get some more data
-     * note that is checked this does not happen indefinitely */
-#endif
     if (!skip) {
-#ifdef TIZEN_FEATURE_UPSTREAM
       if (parse->priv->drain) {
         /* nothing flushed, no skip and draining, so nothing left to do */
         GST_LOG_OBJECT (parse, "no activity or result when draining; "
@@ -3648,16 +3627,11 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass)
       }
       /* otherwise, get some more data
        * note that is checked this does not happen indefinitely */
-#endif
       GST_LOG_OBJECT (parse, "getting some more data");
-#ifdef TIZEN_FEATURE_UPSTREAM
+
       /* Double our frame size, or increment by at most 64KB */
       fsize += MIN (fsize, 64 * 1024);
-#else
-      fsize += 64 * 1024;
-#endif
     }
-    parse->priv->drain = FALSE;
   }
 
 done:
@@ -3899,7 +3873,12 @@ gst_base_parse_sink_activate_mode (GstPad * pad, GstObject * parent,
     case GST_PAD_MODE_PULL:
       if (active) {
         GstEvent *ev = gst_event_new_segment (&parse->segment);
-        parse->priv->segment_seqnum = gst_event_get_seqnum (ev);
+
+        if (parse->priv->segment_seqnum != GST_SEQNUM_INVALID)
+          gst_event_set_seqnum (ev, parse->priv->segment_seqnum);
+        else
+          parse->priv->segment_seqnum = gst_event_get_seqnum (ev);
+
         parse->priv->pending_events =
             g_list_prepend (parse->priv->pending_events, ev);
         result = TRUE;
@@ -3943,6 +3922,8 @@ void
 gst_base_parse_set_duration (GstBaseParse * parse,
     GstFormat fmt, gint64 duration, gint interval)
 {
+  gint64 old_duration;
+
   g_return_if_fail (parse != NULL);
 
   if (parse->priv->upstream_has_duration) {
@@ -3950,14 +3931,8 @@ gst_base_parse_set_duration (GstBaseParse * parse,
     goto exit;
   }
 
-  if (duration != parse->priv->duration) {
-    GstMessage *m;
-
-    m = gst_message_new_duration_changed (GST_OBJECT (parse));
-    gst_element_post_message (GST_ELEMENT (parse), m);
+  old_duration = parse->priv->duration;
 
-    /* TODO: what about duration tag? */
-  }
   parse->priv->duration = duration;
   parse->priv->duration_fmt = fmt;
   GST_DEBUG_OBJECT (parse, "set duration: %" G_GINT64_FORMAT, duration);
@@ -3969,6 +3944,14 @@ gst_base_parse_set_duration (GstBaseParse * parse,
   }
   GST_DEBUG_OBJECT (parse, "set update interval: %d", interval);
   parse->priv->update_interval = interval;
+  if (duration != old_duration) {
+    GstMessage *m;
+
+    m = gst_message_new_duration_changed (GST_OBJECT (parse));
+    gst_element_post_message (GST_ELEMENT (parse), m);
+
+    /* TODO: what about duration tag? */
+  }
 exit:
   return;
 }
@@ -4108,10 +4091,10 @@ gst_base_parse_set_syncable (GstBaseParse * parse, gboolean syncable)
  * Set if the nature of the format or configuration does not allow (much)
  * parsing, and the parser should operate in passthrough mode (which only
  * applies when operating in push mode). That is, incoming buffers are
- * pushed through unmodified, i.e. no #GstBaseParseClass.handle_frame()
- * will be invoked, but #GstBaseParseClass.pre_push_frame() will still be
+ * pushed through unmodified, i.e. no #GstBaseParseClass::handle_frame
+ * will be invoked, but #GstBaseParseClass::pre_push_frame will still be
  * invoked, so subclass can perform as much or as little is appropriate for
- * passthrough semantics in #GstBaseParseClass.pre_push_frame().
+ * passthrough semantics in #GstBaseParseClass::pre_push_frame.
  */
 void
 gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough)
@@ -4170,7 +4153,7 @@ void
 gst_base_parse_set_latency (GstBaseParse * parse, GstClockTime min_latency,
     GstClockTime max_latency)
 {
-  g_return_if_fail (min_latency != GST_CLOCK_TIME_NONE);
+  g_return_if_fail (GST_CLOCK_TIME_IS_VALID (min_latency));
   g_return_if_fail (min_latency <= max_latency);
 
   GST_OBJECT_LOCK (parse);
@@ -4673,6 +4656,7 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
   gst_event_parse_seek (event, &rate, &format, &flags,
       &start_type, &start, &stop_type, &stop);
   seqnum = gst_event_get_seqnum (event);
+  parse->priv->segment_seqnum = seqnum;
 
   GST_DEBUG_OBJECT (parse, "seek to format %s, rate %f, "
       "start type %d at %" GST_TIME_FORMAT ", end type %d at %"
index 24fd907..a86edf2 100644 (file)
@@ -55,8 +55,8 @@ G_BEGIN_DECLS
  * GST_BASE_PARSE_FLOW_DROPPED:
  *
  * A #GstFlowReturn that can be returned from
- * #GstBaseParseClass.handle_frame() to indicate that no output buffer was
- * generated, or from #GstBaseParseClass.pre_push_frame() to to forego
+ * #GstBaseParseClass::handle_frame to indicate that no output buffer was
+ * generated, or from #GstBaseParseClass::pre_push_frame to to forego
  * pushing buffer.
  */
 #define GST_BASE_PARSE_FLOW_DROPPED     GST_FLOW_CUSTOM_SUCCESS
@@ -361,13 +361,9 @@ void            gst_base_parse_merge_tags       (GstBaseParse  * parse,
                                                  GstTagList    * tags,
                                                  GstTagMergeMode mode);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBaseParseFrame, gst_base_parse_frame_free)
-#endif
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBaseParse, gst_object_unref)
-#endif
 
 #ifdef TIZEN_FEATURE_BASEPARSE_MODIFICATION
 GST_BASE_API
index 4368c1a..0a116d6 100644 (file)
  * #GstBaseSink will handle the prerolling correctly. This means that it will
  * return %GST_STATE_CHANGE_ASYNC from a state change to PAUSED until the first
  * buffer arrives in this element. The base class will call the
- * #GstBaseSinkClass.preroll() vmethod with this preroll buffer and will then
+ * #GstBaseSinkClass::preroll vmethod with this preroll buffer and will then
  * commit the state change to the next asynchronously pending state.
  *
  * When the element is set to PLAYING, #GstBaseSink will synchronise on the
- * clock using the times returned from #GstBaseSinkClass.get_times(). If this
+ * clock using the times returned from #GstBaseSinkClass::get_times. If this
  * function returns %GST_CLOCK_TIME_NONE for the start time, no synchronisation
  * will be done. Synchronisation can be disabled entirely by setting the object
  * #GstBaseSink:sync property to %FALSE.
  *
- * After synchronisation the virtual method #GstBaseSinkClass.render() will be
+ * After synchronisation the virtual method #GstBaseSinkClass::render will be
  * called. Subclasses should minimally implement this method.
  *
- * Subclasses that synchronise on the clock in the #GstBaseSinkClass.render()
+ * Subclasses that synchronise on the clock in the #GstBaseSinkClass::render
  * method are supported as well. These classes typically receive a buffer in
  * the render method and can then potentially block on the clock while
  * rendering. A typical example is an audiosink.
@@ -80,7 +80,7 @@
  *
  * Upon receiving the EOS event in the PLAYING state, #GstBaseSink will wait
  * for the clock to reach the time indicated by the stop time of the last
- * #GstBaseSinkClass.get_times() call before posting an EOS message. When the
+ * #GstBaseSinkClass::get_times call before posting an EOS message. When the
  * element receives EOS in PAUSED, preroll completes, the event is queued and an
  * EOS message is posted when going to PLAYING.
  *
  * If no clock has been set on the element, the query will be forwarded
  * upstream.
  *
- * The #GstBaseSinkClass.set_caps() function will be called when the subclass
+ * The #GstBaseSinkClass::set_caps function will be called when the subclass
  * should configure itself to process a specific media type.
  *
- * The #GstBaseSinkClass.start() and #GstBaseSinkClass.stop() virtual methods
+ * The #GstBaseSinkClass::start and #GstBaseSinkClass::stop virtual methods
  * will be called when resources should be allocated. Any
- * #GstBaseSinkClass.preroll(), #GstBaseSinkClass.render() and
- * #GstBaseSinkClass.set_caps() function will be called between the
- * #GstBaseSinkClass.start() and #GstBaseSinkClass.stop() calls.
+ * #GstBaseSinkClass::preroll, #GstBaseSinkClass::render and
+ * #GstBaseSinkClass::set_caps function will be called between the
+ * #GstBaseSinkClass::start and #GstBaseSinkClass::stop calls.
  *
- * The #GstBaseSinkClass.event() virtual method will be called when an event is
+ * The #GstBaseSinkClass::event virtual method will be called when an event is
  * received by #GstBaseSink. Normally this method should only be overridden by
  * very specific elements (such as file sinks) which need to handle the
  * newsegment event specially.
  *
- * The #GstBaseSinkClass.unlock() method is called when the elements should
+ * 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
- * #GstBaseSinkClass.render() method performs a blocking write on a file
+ * #GstBaseSinkClass::render method. This is mostly useful when the
+ * #GstBaseSinkClass::render method performs a blocking write on a file
  * descriptor, for example.
  *
  * The #GstBaseSink:max-lateness property affects how the sink deals with
  * If the frame is later than max-lateness, the sink will drop the buffer
  * without calling the render method.
  * This feature is disabled if sync is disabled, the
- * #GstBaseSinkClass.get_times() method does not return a valid start time or
+ * #GstBaseSinkClass::get_times method does not return a valid start time or
  * max-lateness is set to -1 (the default).
  * Subclasses can use gst_base_sink_set_max_lateness() to configure the
  * max-lateness value.
@@ -245,6 +245,25 @@ struct _GstBaseSinkPrivate
   GstStepInfo current_step;
   GstStepInfo pending_step;
 
+  /* instant rate change state */
+  /* seqnum of the last instant-rate-sync-time event
+   * received. %GST_SEQNUM_INVALID if there isn't one */
+  guint32 instant_rate_sync_seqnum;
+  /* Active instant-rate multipler. 0.0 if nothing pending */
+  gdouble instant_rate_multiplier;
+  /* seqnum of the last instant-rate event.
+   * %GST_SEQNUM_INVALID if there isn't one */
+  guint32 last_instant_rate_seqnum;
+  guint32 segment_seqnum;
+  GstSegment upstream_segment;
+  /* Running time at the start of the last segment event
+   * or instant-rate switch in *our* segment, not upstream */
+  GstClockTime last_anchor_running_time;
+  /* Difference between upstream running time and our own running time
+   * at the last segment event or instant-rate switch:
+   * upstream + offset = ours */
+  GstClockTimeDiff instant_rate_offset;
+
   /* Cached GstClockID */
   GstClockID cached_clock_id;
 
@@ -305,6 +324,7 @@ enum
   PROP_THROTTLE_TIME,
   PROP_MAX_BITRATE,
   PROP_PROCESSING_DEADLINE,
+  PROP_STATS,
   PROP_LAST
 };
 
@@ -318,7 +338,7 @@ static void gst_base_sink_finalize (GObject * object);
 GType
 gst_base_sink_get_type (void)
 {
-  static volatile gsize base_sink_type = 0;
+  static gsize base_sink_type = 0;
 
   if (g_once_init_enter (&base_sink_type)) {
     GType _type;
@@ -550,10 +570,28 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
    */
   g_object_class_install_property (gobject_class, PROP_PROCESSING_DEADLINE,
       g_param_spec_uint64 ("processing-deadline", "Processing deadline",
-          "Maximum processing deadline in nanoseconds", 0, G_MAXUINT64,
-          DEFAULT_PROCESSING_DEADLINE,
+          "Maximum processing time for a buffer in nanoseconds", 0,
+          G_MAXUINT64, DEFAULT_PROCESSING_DEADLINE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+
+  /**
+   * GstBaseSink:stats:
+   *
+   * Various #GstBaseSink statistics. This property returns a #GstStructure
+   * with name `application/x-gst-base-sink-stats` with the following fields:
+   *
+   * - "average-rate"  G_TYPE_DOUBLE   average frame rate
+   * - "dropped" G_TYPE_UINT64   Number of dropped frames
+   * - "rendered" G_TYPE_UINT64   Number of rendered frames
+   *
+   * Since: 1.18
+   */
+  g_object_class_install_property (gobject_class, PROP_STATS,
+      g_param_spec_boxed ("stats", "Statistics",
+          "Sink Statistics", GST_TYPE_STRUCTURE,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_base_sink_change_state);
   gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_base_sink_send_event);
@@ -1184,6 +1222,8 @@ gst_base_sink_query_latency (GstBaseSink * sink, gboolean * live,
   min = 0;
   max = -1;
   us_live = FALSE;
+  us_min = 0;
+  us_max = 0;
 
   if (have_latency) {
     GST_DEBUG_OBJECT (sink, "we are ready for LATENCY query");
@@ -1245,8 +1285,14 @@ gst_base_sink_query_latency (GstBaseSink * sink, gboolean * live,
 
   if (res) {
     GST_DEBUG_OBJECT (sink, "latency query: live: %d, have_latency %d,"
-        " upstream: %d, min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT, l,
-        have_latency, us_live, GST_TIME_ARGS (min), GST_TIME_ARGS (max));
+        " upstream_live %d, min(%" GST_TIME_FORMAT ")=upstream(%"
+        GST_TIME_FORMAT ")+processing_deadline(%" GST_TIME_FORMAT
+        ")+render_delay(%" GST_TIME_FORMAT "), max(%" GST_TIME_FORMAT
+        ")=upstream(%" GST_TIME_FORMAT ")+render_delay(%" GST_TIME_FORMAT ")",
+        l, have_latency, us_live, GST_TIME_ARGS (min), GST_TIME_ARGS (us_min),
+        GST_TIME_ARGS (processing_deadline), GST_TIME_ARGS (render_delay),
+        GST_TIME_ARGS (max), GST_TIME_ARGS (us_max),
+        GST_TIME_ARGS (render_delay));
 
     if (live)
       *live = l;
@@ -1281,6 +1327,7 @@ gst_base_sink_set_render_delay (GstBaseSink * sink, GstClockTime delay)
   GstClockTime old_render_delay;
 
   g_return_if_fail (GST_IS_BASE_SINK (sink));
+  g_return_if_fail (GST_CLOCK_TIME_IS_VALID (delay));
 
   GST_OBJECT_LOCK (sink);
   old_render_delay = sink->priv->render_delay;
@@ -1600,6 +1647,9 @@ gst_base_sink_get_property (GObject * object, guint prop_id, GValue * value,
     case PROP_PROCESSING_DEADLINE:
       g_value_set_uint64 (value, gst_base_sink_get_processing_deadline (sink));
       break;
+    case PROP_STATS:
+      g_value_take_boxed (value, gst_base_sink_get_stats (sink));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1719,6 +1769,9 @@ gst_base_sink_commit_state (GstBaseSink * basesink)
             next, pending, GST_STATE_VOID_PENDING));
   }
 
+  gst_element_post_message (GST_ELEMENT_CAST (basesink),
+      gst_message_new_latency (GST_OBJECT_CAST (basesink)));
+
   GST_STATE_BROADCAST (basesink);
 
   return TRUE;
@@ -1747,6 +1800,9 @@ nothing_pending:
     /* we can report latency queries now */
     basesink->priv->have_latency = TRUE;
     GST_OBJECT_UNLOCK (basesink);
+
+    gst_element_post_message (GST_ELEMENT_CAST (basesink),
+        gst_message_new_latency (GST_OBJECT_CAST (basesink)));
     return TRUE;
   }
 stopping_unlocked:
@@ -2148,6 +2204,17 @@ do_times:
   rstart = gst_segment_to_running_time (segment, format, cstart);
   rstop = gst_segment_to_running_time (segment, format, cstop);
 
+  /* In reverse playback, play from stop to start */
+  if (segment->rate < 0.0 && GST_CLOCK_TIME_IS_VALID (rstop)
+      /* FIXME: Current stepping implemenation expects unmodified rstart/rstop
+       * for reverse playback. Don't swap those values when stepping
+       * unless stepping code is updated as such */
+      && !step->valid) {
+    GstClockTime tmp = rstart;
+    rstart = rstop;
+    rstop = tmp;
+  }
+
   if (GST_CLOCK_TIME_IS_VALID (stop))
     rnext = rstop;
   else
@@ -2249,9 +2316,9 @@ gst_base_sink_adjust_time (GstBaseSink * basesink, GstClockTime time)
  * is no clock, no synchronisation is done and %GST_CLOCK_BADTIME is returned.
  *
  * This function should only be called with the PREROLL_LOCK held, like when
- * receiving an EOS event in the #GstBaseSinkClass.event() vmethod or when
+ * receiving an EOS event in the #GstBaseSinkClass::event vmethod or when
  * receiving a buffer in
- * the #GstBaseSinkClass.render() vmethod.
+ * the #GstBaseSinkClass::render vmethod.
  *
  * The @time argument should be the running_time of when this method should
  * return and is not adjusted with any latency or offset configured in the
@@ -2339,14 +2406,14 @@ no_clock:
  * gst_base_sink_wait_preroll:
  * @sink: the sink
  *
- * If the #GstBaseSinkClass.render() method performs its own synchronisation
+ * If the #GstBaseSinkClass::render method performs its own synchronisation
  * against the clock it must unblock when going from PLAYING to the PAUSED state
  * and call this method before continuing to render the remaining data.
  *
- * If the #GstBaseSinkClass.render() method can block on something else than
+ * If the #GstBaseSinkClass::render method can block on something else than
  * the clock, it must also be ready to unblock immediately on
- * the #GstBaseSinkClass.unlock() method and cause the
- * #GstBaseSinkClass.render() method to immediately call this function.
+ * the #GstBaseSinkClass::unlock method and cause the
+ * #GstBaseSinkClass::render method to immediately call this function.
  * In this case, the subclass must be prepared to continue rendering where it
  * left off if this function returns %GST_FLOW_OK.
  *
@@ -2604,9 +2671,14 @@ gst_base_sink_do_sync (GstBaseSink * basesink,
   GstFlowReturn ret;
   GstStepInfo *current, *pending;
   gboolean stepped;
+  guint32 current_instant_rate_seqnum;
 
   priv = basesink->priv;
 
+  /* remember the currently handled instant-rate sequence number. If this
+   * changes after pre-rolling, we need to goto do_step again for updating
+   * the timing information of the current buffer */
+  current_instant_rate_seqnum = priv->instant_rate_sync_seqnum;
 do_step:
   sstart = sstop = rstart = rstop = rnext = GST_CLOCK_TIME_NONE;
   do_sync = TRUE;
@@ -2675,6 +2747,13 @@ again:
     goto do_step;
   }
 
+  if (G_UNLIKELY (priv->instant_rate_sync_seqnum !=
+          current_instant_rate_seqnum)) {
+    current_instant_rate_seqnum = priv->instant_rate_sync_seqnum;
+    // TODO rename the goto label - it does more these days.
+    goto do_step;
+  }
+
   /* After rendering we store the position of the last buffer so that we can use
    * it to report the position. We need to take the lock here. */
   GST_OBJECT_LOCK (basesink);
@@ -2723,6 +2802,13 @@ again:
   /* check for unlocked by a state change, we are not flushing so
    * we can try to preroll on the current buffer. */
   if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) {
+    if (G_UNLIKELY (priv->instant_rate_sync_seqnum !=
+            current_instant_rate_seqnum)) {
+      current_instant_rate_seqnum = priv->instant_rate_sync_seqnum;
+      // TODO rename
+      goto do_step;
+    }
+
     GST_DEBUG_OBJECT (basesink, "unscheduled, waiting some more");
     priv->call_preroll = TRUE;
     goto again;
@@ -2781,6 +2867,60 @@ 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));
 
+  /* Compensate for any instant-rate-change related running time offset
+   * between upstream and the internal running time of the sink */
+  if (basesink->priv->instant_rate_sync_seqnum != GST_SEQNUM_INVALID) {
+    GstClockTime actual_duration;
+    GstClockTime upstream_duration;
+    GstClockTimeDiff difference;
+    gboolean negative_duration;
+
+    GST_DEBUG_OBJECT (basesink,
+        "Current internal running time %" GST_TIME_FORMAT
+        ", last internal running time %" GST_TIME_FORMAT, GST_TIME_ARGS (time),
+        GST_TIME_ARGS (basesink->priv->last_anchor_running_time));
+
+    /* Calculate how much running time was spent since the last switch/segment
+     * in the "corrected upstream segment", our segment */
+    /* Due to rounding errors and other inaccuracies, it can happen
+     * that our calculated internal running time is before the upstream
+     * running time. We need to compensate for that */
+    if (time < basesink->priv->last_anchor_running_time) {
+      actual_duration = basesink->priv->last_anchor_running_time - time;
+      negative_duration = TRUE;
+    } else {
+      actual_duration = time - basesink->priv->last_anchor_running_time;
+      negative_duration = FALSE;
+    }
+
+    /* Transpose that duration (i.e. what upstream beliefs) */
+    upstream_duration =
+        (actual_duration * basesink->segment.rate) /
+        basesink->priv->upstream_segment.rate;
+
+    /* Add the difference to the previously accumulated correction */
+    if (negative_duration)
+      difference = upstream_duration - actual_duration;
+    else
+      difference = actual_duration - upstream_duration;
+
+    GST_DEBUG_OBJECT (basesink,
+        "Current instant rate correction offset. Actual duration %"
+        GST_TIME_FORMAT ", upstream duration %" GST_TIME_FORMAT
+        ", negative %d, difference %" GST_STIME_FORMAT ", current offset %"
+        GST_STIME_FORMAT, GST_TIME_ARGS (actual_duration),
+        GST_TIME_ARGS (upstream_duration), negative_duration,
+        GST_STIME_ARGS (difference),
+        GST_STIME_ARGS (basesink->priv->instant_rate_offset + difference));
+
+    difference = basesink->priv->instant_rate_offset + difference;
+
+    if (difference > 0 && time < difference)
+      time = 0;
+    else
+      time -= difference;
+  }
+
   event = gst_event_new_qos (type, proportion, diff, time);
 
   /* send upstream */
@@ -3129,8 +3269,17 @@ gst_base_sink_flush_stop (GstBaseSink * basesink, GstPad * pad,
     /* we need new segment info after the flush. */
     basesink->have_newsegment = FALSE;
     if (reset_time) {
+      gst_segment_init (&basesink->priv->upstream_segment,
+          GST_FORMAT_UNDEFINED);
       gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED);
       GST_ELEMENT_START_TIME (basesink) = 0;
+
+      basesink->priv->last_instant_rate_seqnum = GST_SEQNUM_INVALID;
+      basesink->priv->instant_rate_sync_seqnum = GST_SEQNUM_INVALID;
+      basesink->priv->instant_rate_multiplier = 0;
+      basesink->priv->segment_seqnum = GST_SEQNUM_INVALID;
+      basesink->priv->instant_rate_offset = 0;
+      basesink->priv->last_anchor_running_time = 0;
     }
   }
   GST_OBJECT_UNLOCK (basesink);
@@ -3277,21 +3426,140 @@ gst_base_sink_default_event (GstBaseSink * basesink, GstEvent * event)
         gst_caps_unref (current_caps);
       break;
     }
-    case GST_EVENT_SEGMENT:
+    case GST_EVENT_SEGMENT:{
+      guint32 seqnum = gst_event_get_seqnum (event);
+      GstSegment new_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
+      /* the new segment 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_event_copy_segment (event, &new_segment);
+
+      GST_DEBUG_OBJECT (basesink,
+          "received upstream segment %u %" GST_SEGMENT_FORMAT, seqnum,
+          &new_segment);
+
+      /* Make sure that the position stays between start and stop */
+      new_segment.position =
+          CLAMP (new_segment.position, new_segment.start, new_segment.stop);
+
+      if (basesink->priv->instant_rate_sync_seqnum != GST_SEQNUM_INVALID) {
+        GstClockTime upstream_duration;
+        GstClockTime actual_duration;
+        GstClockTime new_segment_running_time;
+        GstClockTimeDiff difference;
+        gboolean negative_duration;
+
+        /* Calculate how much running time upstream believes has passed since
+         * the last switch/segment */
+        new_segment_running_time =
+            gst_segment_to_running_time (&new_segment, GST_FORMAT_TIME,
+            new_segment.position);
+
+        GST_DEBUG_OBJECT (basesink,
+            "Current upstream running time %" GST_TIME_FORMAT
+            ", last upstream running time %" GST_TIME_FORMAT,
+            GST_TIME_ARGS (new_segment_running_time),
+            GST_TIME_ARGS (basesink->priv->last_anchor_running_time -
+                basesink->priv->instant_rate_offset));
+
+        /* Due to rounding errors and other inaccuracies, it can happen
+         * that our calculated internal running time is before the upstream
+         * running time. We need to compensate for that */
+        if (new_segment_running_time <
+            basesink->priv->last_anchor_running_time -
+            basesink->priv->instant_rate_offset) {
+          upstream_duration =
+              basesink->priv->last_anchor_running_time -
+              basesink->priv->instant_rate_offset - new_segment_running_time;
+          negative_duration = TRUE;
+        } else {
+          upstream_duration =
+              new_segment_running_time -
+              basesink->priv->last_anchor_running_time +
+              basesink->priv->instant_rate_offset;
+          negative_duration = FALSE;
+        }
+
+        /* Calculate the actual running-time duration of the previous segment */
+        actual_duration =
+            (upstream_duration * basesink->priv->instant_rate_multiplier);
+
+        if (negative_duration)
+          difference = upstream_duration - actual_duration;
+        else
+          difference = actual_duration - upstream_duration;
+
+        GST_DEBUG_OBJECT (basesink,
+            "Current internal running time %" GST_TIME_FORMAT
+            ", last internal running time %" GST_TIME_FORMAT,
+            GST_TIME_ARGS (new_segment_running_time +
+                basesink->priv->instant_rate_offset + difference),
+            GST_TIME_ARGS (basesink->priv->last_anchor_running_time));
+
+        /* Add the difference to the previously accumulated correction. */
+        basesink->priv->instant_rate_offset += difference;
+
+        GST_DEBUG_OBJECT (basesink,
+            "Updating instant rate correction offset. Actual duration %"
+            GST_TIME_FORMAT ", upstream duration %" GST_TIME_FORMAT
+            ", negative %d, difference %" GST_STIME_FORMAT ", new offset %"
+            GST_STIME_FORMAT, GST_TIME_ARGS (actual_duration),
+            GST_TIME_ARGS (upstream_duration),
+            negative_duration,
+            GST_STIME_ARGS (difference),
+            GST_STIME_ARGS (basesink->priv->instant_rate_offset));
+
+        if (basesink->priv->instant_rate_offset < 0 &&
+            new_segment_running_time < -basesink->priv->instant_rate_offset) {
+          GST_WARNING_OBJECT (basesink,
+              "Upstream current running time %" GST_TIME_FORMAT
+              " is smaller than calculated offset %" GST_STIME_FORMAT,
+              GST_TIME_ARGS (new_segment_running_time),
+              GST_STIME_ARGS (basesink->priv->instant_rate_offset));
+
+          basesink->priv->last_anchor_running_time = 0;
+          basesink->priv->instant_rate_offset = 0;
+        } else {
+          basesink->priv->last_anchor_running_time =
+              new_segment_running_time + basesink->priv->instant_rate_offset;
+        }
+
+        /* Update the segments from the event and with the newly calculated
+         * correction offset */
+        basesink->priv->upstream_segment = new_segment;
+        basesink->segment = new_segment;
+
+        basesink->segment.rate *= basesink->priv->instant_rate_multiplier;
+
+        gst_segment_offset_running_time (&basesink->segment, GST_FORMAT_TIME,
+            basesink->priv->instant_rate_offset);
+
+        GST_DEBUG_OBJECT (basesink,
+            "Adjusted segment is now %" GST_SEGMENT_FORMAT, &basesink->segment);
+      } else {
+        /* otherwise both segments are simply the same, no correction needed */
+        basesink->priv->upstream_segment = new_segment;
+        basesink->segment = new_segment;
+        basesink->priv->last_anchor_running_time =
+            gst_segment_to_running_time (&new_segment, new_segment.format,
+            new_segment.position);
+        basesink->priv->instant_rate_offset = 0;        /* Should already be 0, but to be sure */
+      }
+
       GST_DEBUG_OBJECT (basesink, "configured segment %" GST_SEGMENT_FORMAT,
           &basesink->segment);
+      basesink->priv->segment_seqnum = seqnum;
       basesink->have_newsegment = TRUE;
       gst_base_sink_reset_qos (basesink);
       GST_OBJECT_UNLOCK (basesink);
       break;
+    }
     case GST_EVENT_GAP:
     {
       if (G_UNLIKELY (gst_base_sink_wait_event (basesink,
@@ -3332,6 +3600,41 @@ gst_base_sink_default_event (GstBaseSink * basesink, GstEvent * event)
         gst_element_post_message (GST_ELEMENT_CAST (basesink), msg);
       break;
     }
+    case GST_EVENT_INSTANT_RATE_CHANGE:
+    {
+      GstMessage *msg;
+      gdouble rate_multiplier;
+      guint32 seqnum = gst_event_get_seqnum (event);
+
+      GST_OBJECT_LOCK (basesink);
+      if (G_UNLIKELY (basesink->priv->last_instant_rate_seqnum == seqnum)) {
+        /* Ignore repeated event */
+        GST_LOG_OBJECT (basesink,
+            "Ignoring repeated instant-rate-change event");
+        GST_OBJECT_UNLOCK (basesink);
+        break;
+      }
+      if (basesink->priv->instant_rate_sync_seqnum == seqnum) {
+        /* Ignore if we already received the instant-rate-sync-time event from the pipeline */
+        GST_LOG_OBJECT (basesink,
+            "Ignoring instant-rate-change event for which we already received instant-rate-sync-time");
+        GST_OBJECT_UNLOCK (basesink);
+        break;
+      }
+
+      basesink->priv->last_instant_rate_seqnum = seqnum;
+      GST_OBJECT_UNLOCK (basesink);
+
+      gst_event_parse_instant_rate_change (event, &rate_multiplier, NULL);
+
+      msg =
+          gst_message_new_instant_rate_request (GST_OBJECT_CAST (basesink),
+          rate_multiplier);
+      gst_message_set_seqnum (msg, seqnum);
+      gst_element_post_message (GST_ELEMENT_CAST (basesink), msg);
+
+      break;
+    }
     default:
       break;
   }
@@ -4141,6 +4444,114 @@ gst_base_sink_perform_step (GstBaseSink * sink, GstPad * pad, GstEvent * event)
   return TRUE;
 }
 
+static gboolean
+gst_base_sink_perform_instant_rate_change (GstBaseSink * sink, GstPad * pad,
+    GstEvent * event)
+{
+  GstBaseSinkPrivate *priv;
+  guint32 seqnum;
+  gdouble rate;
+  GstClockTime running_time, upstream_running_time;
+
+  GstClockTime switch_time;
+  gint res;
+
+  priv = sink->priv;
+
+  GST_DEBUG_OBJECT (sink, "performing instant-rate-change with event %p",
+      event);
+
+  seqnum = gst_event_get_seqnum (event);
+  gst_event_parse_instant_rate_sync_time (event, &rate, &running_time,
+      &upstream_running_time);
+
+  GST_DEBUG_OBJECT (sink, "instant-rate-change %u %lf at %" GST_TIME_FORMAT
+      ", upstream %" GST_TIME_FORMAT,
+      seqnum, rate, GST_TIME_ARGS (running_time),
+      GST_TIME_ARGS (upstream_running_time));
+
+  /* Take the preroll lock so we can change the segment. We do not call unlock
+   * like for stepping as that would cause the PLAYING state to be lost and
+   * would get us into prerolling again first
+   *
+   * FIXME: The below potentially blocks until the chain function returns, but
+   * the lock is not taken during all waiting operations inside the chain
+   * function (clock, preroll) so this should be fine in most cases. Only
+   * problem is if the render() or prepare() functions are waiting themselves!
+   *
+   * FIXME: If the subclass is calling gst_base_sink_wait() it will be woken
+   * up but there is no way for it to update the timestamps, or to report back
+   * to the base class that it should recalculate the values. The current
+   * change would not be instantaneous in that case but would wait until the
+   * next buffer.
+   */
+  GST_BASE_SINK_PREROLL_LOCK (sink);
+
+  /* We can safely change the segment and everything here as we hold the
+   * PREROLL_LOCK and it is taken for the whole chain function */
+  sink->priv->instant_rate_sync_seqnum = seqnum;
+  sink->priv->instant_rate_multiplier = rate;
+  sink->priv->instant_rate_offset = running_time - upstream_running_time;
+  sink->priv->last_anchor_running_time = running_time;
+
+  GST_DEBUG_OBJECT (sink, "Current internal running time %" GST_TIME_FORMAT
+      ", last internal running time %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (running_time),
+      GST_TIME_ARGS (sink->priv->last_anchor_running_time));
+
+  /* Calculate the current position in the segment and do a seek with the
+   * new rate. This updates rate, base and offset accordingly */
+  res =
+      gst_segment_position_from_running_time_full (&sink->segment,
+      GST_FORMAT_TIME, running_time, &switch_time);
+
+  GST_DEBUG_OBJECT (sink, "Before adjustment seg is %" GST_SEGMENT_FORMAT
+      " new running_time %" GST_TIME_FORMAT
+      " position %" GST_STIME_FORMAT " res %d", &sink->segment,
+      GST_TIME_ARGS (running_time),
+      GST_STIME_ARGS ((GstClockTimeDiff) switch_time), res);
+
+  if (res < 0) {
+    GST_WARNING_OBJECT (sink,
+        "Negative position calculated. Can't instant-rate change to there");
+    GST_BASE_SINK_PREROLL_UNLOCK (sink);
+    return TRUE;
+  }
+
+  sink->segment.position = switch_time;
+
+  /* Calculate new output rate based on upstream value */
+  rate *= sink->priv->upstream_segment.rate;
+
+  gst_segment_do_seek (&sink->segment, rate, GST_FORMAT_TIME,
+      sink->segment.flags & (~GST_SEEK_FLAG_FLUSH) &
+      GST_SEEK_FLAG_INSTANT_RATE_CHANGE, GST_SEEK_TYPE_NONE, -1,
+      GST_SEEK_TYPE_NONE, -1, NULL);
+
+  GST_DEBUG_OBJECT (sink, "Adjusted segment is now %" GST_SEGMENT_FORMAT,
+      &sink->segment);
+
+  priv->current_sstart = GST_CLOCK_TIME_NONE;
+  priv->current_sstop = GST_CLOCK_TIME_NONE;
+  priv->eos_rtime = GST_CLOCK_TIME_NONE;
+  gst_base_sink_reset_qos (sink);
+
+  if (sink->clock_id) {
+    gst_clock_id_unschedule (sink->clock_id);
+  }
+
+  if (sink->have_preroll) {
+    GST_DEBUG_OBJECT (sink, "signal waiter");
+    /* TODO: Rename this, and GST_FLOW_STEP */
+    priv->step_unlock = TRUE;
+    GST_BASE_SINK_PREROLL_SIGNAL (sink);
+  }
+
+  GST_BASE_SINK_PREROLL_UNLOCK (sink);
+
+  return TRUE;
+}
+
 /* with STREAM_LOCK
  */
 static void
@@ -4594,6 +5005,18 @@ gst_base_sink_send_event (GstElement * element, GstEvent * event)
        * when a particular piece of data will be rendered. */
       break;
     }
+    case GST_EVENT_INSTANT_RATE_SYNC_TIME:
+    {
+      gst_base_sink_perform_instant_rate_change (basesink, pad, event);
+
+      /* Forward the event. If upstream handles it already, it is supposed to
+       * send a SEGMENT event with the same seqnum and the final rate before
+       * the next buffer
+       */
+      forward = TRUE;
+
+      break;
+    }
     case GST_EVENT_SEEK:
       /* in pull mode we will execute the seek */
       if (mode == GST_PAD_MODE_PULL)
@@ -4610,6 +5033,84 @@ gst_base_sink_send_event (GstElement * element, GstEvent * event)
   if (forward) {
     GST_DEBUG_OBJECT (basesink, "sending event %p %" GST_PTR_FORMAT, event,
         event);
+
+    /* Compensate for any instant-rate-change related running time offset
+     * between upstream and the internal running time of the sink */
+    if (basesink->priv->instant_rate_sync_seqnum != GST_SEQNUM_INVALID) {
+      GstClockTime now = GST_CLOCK_TIME_NONE;
+      GstClockTime actual_duration;
+      GstClockTime upstream_duration;
+      GstClockTimeDiff difference;
+      gboolean is_playing, negative_duration;
+
+      GST_OBJECT_LOCK (basesink);
+      is_playing = GST_STATE (basesink) == GST_STATE_PLAYING
+          && (GST_STATE_PENDING (basesink) == GST_STATE_VOID_PENDING ||
+          GST_STATE_PENDING (basesink) == GST_STATE_PLAYING);
+
+      if (is_playing) {
+        GstClockTime base_time, clock_time;
+        GstClock *clock;
+
+        base_time = GST_ELEMENT_CAST (basesink)->base_time;
+        clock = GST_ELEMENT_CLOCK (basesink);
+        GST_OBJECT_UNLOCK (basesink);
+
+        if (clock) {
+          clock_time = gst_clock_get_time (clock);
+          now = clock_time - base_time;
+        }
+      } else {
+        now = GST_ELEMENT_START_TIME (basesink);
+        GST_OBJECT_UNLOCK (basesink);
+      }
+
+      GST_DEBUG_OBJECT (basesink,
+          "Current internal running time %" GST_TIME_FORMAT
+          ", last internal running time %" GST_TIME_FORMAT, GST_TIME_ARGS (now),
+          GST_TIME_ARGS (basesink->priv->last_anchor_running_time));
+
+      if (now != GST_CLOCK_TIME_NONE) {
+        /* Calculate how much running time was spent since the last switch/segment
+         * in the "corrected upstream segment", our segment */
+        /* Due to rounding errors and other inaccuracies, it can happen
+         * that our calculated internal running time is before the upstream
+         * running time. We need to compensate for that */
+        if (now < basesink->priv->last_anchor_running_time) {
+          actual_duration = basesink->priv->last_anchor_running_time - now;
+          negative_duration = TRUE;
+        } else {
+          actual_duration = now - basesink->priv->last_anchor_running_time;
+          negative_duration = FALSE;
+        }
+
+        /* Transpose that duration (i.e. what upstream beliefs) */
+        upstream_duration =
+            (actual_duration * basesink->segment.rate) /
+            basesink->priv->upstream_segment.rate;
+
+        /* Add the difference to the previously accumulated correction */
+        if (negative_duration)
+          difference = upstream_duration - actual_duration;
+        else
+          difference = actual_duration - upstream_duration;
+
+        GST_DEBUG_OBJECT (basesink,
+            "Current instant rate correction offset. Actual duration %"
+            GST_TIME_FORMAT ", upstream duration %" GST_TIME_FORMAT
+            ", negative %d, difference %" GST_STIME_FORMAT ", current offset %"
+            GST_STIME_FORMAT, GST_TIME_ARGS (actual_duration),
+            GST_TIME_ARGS (upstream_duration), negative_duration,
+            GST_STIME_ARGS (difference),
+            GST_STIME_ARGS (basesink->priv->instant_rate_offset + difference));
+
+        difference = basesink->priv->instant_rate_offset + difference;
+
+        event = gst_event_make_writable (event);
+        gst_event_set_running_time_offset (event, -difference);
+      }
+    }
+
     result = gst_pad_push_event (pad, event);
   } else {
     /* not forwarded, unref the event */
@@ -5168,6 +5669,8 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
       GST_DEBUG_OBJECT (basesink, "READY to PAUSED");
       basesink->have_newsegment = FALSE;
       gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED);
+      gst_segment_init (&basesink->priv->upstream_segment,
+          GST_FORMAT_UNDEFINED);
       basesink->offset = 0;
       basesink->have_preroll = FALSE;
       priv->step_unlock = FALSE;
@@ -5185,6 +5688,12 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
       priv->call_preroll = TRUE;
       priv->current_step.valid = FALSE;
       priv->pending_step.valid = FALSE;
+      priv->instant_rate_sync_seqnum = GST_SEQNUM_INVALID;
+      priv->instant_rate_multiplier = 0;
+      priv->last_instant_rate_seqnum = GST_SEQNUM_INVALID;
+      priv->segment_seqnum = GST_SEQNUM_INVALID;
+      priv->instant_rate_offset = 0;
+      priv->last_anchor_running_time = 0;
       if (priv->async_enabled) {
         GST_DEBUG_OBJECT (basesink, "doing async state change");
         /* when async enabled, post async-start message and return ASYNC from
@@ -5194,6 +5703,8 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
             gst_message_new_async_start (GST_OBJECT_CAST (basesink)));
       } else {
         priv->have_latency = TRUE;
+        gst_element_post_message (GST_ELEMENT_CAST (basesink),
+            gst_message_new_latency (GST_OBJECT_CAST (basesink)));
       }
       GST_BASE_SINK_PREROLL_UNLOCK (basesink);
       break;
@@ -5375,3 +5886,31 @@ activate_failed:
     return GST_STATE_CHANGE_FAILURE;
   }
 }
+
+/**
+ * gst_base_sink_get_stats:
+ * @sink: #GstBaseSink
+ *
+ * Return various #GstBaseSink statistics. This function returns a #GstStructure
+ * with name `application/x-gst-base-sink-stats` with the following fields:
+ *
+ * - "average-rate" G_TYPE_DOUBLE   average frame rate
+ * - "dropped" G_TYPE_UINT64   Number of dropped frames
+ * - "rendered" G_TYPE_UINT64   Number of rendered frames
+ *
+ * Returns: (transfer full): pointer to #GstStructure
+ *
+ * Since: 1.18
+ */
+GstStructure *
+gst_base_sink_get_stats (GstBaseSink * sink)
+{
+  GstBaseSinkPrivate *priv = NULL;
+
+  g_return_val_if_fail (sink != NULL, NULL);
+  priv = sink->priv;
+  return gst_structure_new ("application/x-gst-base-sink-stats",
+      "average-rate", G_TYPE_DOUBLE, priv->avg_rate,
+      "dropped", G_TYPE_UINT64, priv->dropped,
+      "rendered", G_TYPE_UINT64, priv->rendered, NULL);
+}
index 0540125..3745fa2 100644 (file)
@@ -125,10 +125,10 @@ struct _GstBaseSink {
  * @unlock: Unlock any pending access to the resource. Subclasses should
  *     unblock any blocked function ASAP and call gst_base_sink_wait_preroll()
  * @unlock_stop: Clear the previous unlock request. Subclasses should clear
- *     any state they set during #GstBaseSinkClass.unlock(), and be ready to
+ *     any state they set during #GstBaseSinkClass::unlock, and be ready to
  *     continue where they left off after gst_base_sink_wait_preroll(),
  *     gst_base_sink_wait() or gst_wait_sink_wait_clock() return or
- *     #GstBaseSinkClass.render() is called again.
+ *     #GstBaseSinkClass::render is called again.
  * @query: perform a #GstQuery on the element.
  * @event: Override this to handle events arriving on the sink pad
  * @wait_event: Override this to implement custom logic to wait for the event
@@ -151,7 +151,12 @@ struct _GstBaseSink {
 struct _GstBaseSinkClass {
   GstElementClass parent_class;
 
-  /* get caps from subclass */
+  /**
+   * GstBaseSink::get_caps:
+   * @filter: (in) (nullable):
+   *
+   * Called to get sink pad caps from the subclass.
+   */
   GstCaps*      (*get_caps)     (GstBaseSink *sink, GstCaps *filter);
   /* notify subclass of new caps */
   gboolean      (*set_caps)     (GstBaseSink *sink, GstCaps *caps);
@@ -324,9 +329,10 @@ GST_BASE_API
 GstFlowReturn   gst_base_sink_wait              (GstBaseSink *sink, GstClockTime time,
                                                  GstClockTimeDiff *jitter);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
+GST_BASE_API
+GstStructure   *gst_base_sink_get_stats (GstBaseSink * sink);
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBaseSink, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index aa9a459..31fb505 100644 (file)
  * conditions are met, it also supports pull mode scheduling:
  *
  *   * The format is set to %GST_FORMAT_BYTES (default).
- *   * #GstBaseSrcClass.is_seekable() returns %TRUE.
+ *   * #GstBaseSrcClass::is_seekable 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
  * %GST_FORMAT_BYTES:
  *
- * * #GstBaseSrcClass.is_seekable() returns %TRUE.
- * * #GstBaseSrcClass.query() can convert all supported seek formats to the
+ * * #GstBaseSrcClass::is_seekable returns %TRUE.
+ * * #GstBaseSrcClass::query can convert all supported seek formats to the
  *   internal format as set with gst_base_src_set_format().
- * * #GstBaseSrcClass.do_seek() is implemented, performs the seek and returns
+ * * #GstBaseSrcClass::do_seek is implemented, performs the seek and returns
  *    %TRUE.
  *
  * When the element does not meet the requirements to operate in pull mode, the
- * offset and length in the #GstBaseSrcClass.create() method should be ignored.
+ * offset and length in the #GstBaseSrcClass::create method should be ignored.
  * It is recommended to subclass #GstPushSrc instead, in this situation. If the
  * element can operate in pull mode but only with specific offsets and
  * lengths, it is allowed to generate an error when the wrong values are passed
- * to the #GstBaseSrcClass.create() function.
+ * to the #GstBaseSrcClass::create function.
  *
  * #GstBaseSrc has support for live sources. Live sources are sources that when
  * paused discard data, such as audio or video capture devices. A typical live
@@ -69,7 +69,7 @@
  * Use gst_base_src_set_live() to activate the live source mode.
  *
  * A live source does not produce data in the PAUSED state. This means that the
- * #GstBaseSrcClass.create() method will not be called in PAUSED but only in
+ * #GstBaseSrcClass::create method will not be called in PAUSED but only in
  * PLAYING. To signal the pipeline that the element will not produce data, the
  * return value from the READY to PAUSED state will be
  * %GST_STATE_CHANGE_NO_PREROLL.
  *
  * Live sources that synchronize and block on the clock (an audio source, for
  * example) can use gst_base_src_wait_playing() when the
- * #GstBaseSrcClass.create() function was interrupted by a state change to
+ * #GstBaseSrcClass::create function was interrupted by a state change to
  * PAUSED.
  *
- * The #GstBaseSrcClass.get_times() method can be used to implement pseudo-live
- * sources. It only makes sense to implement the #GstBaseSrcClass.get_times()
- * function if the source is a live source. The #GstBaseSrcClass.get_times()
+ * The #GstBaseSrcClass::get_times method can be used to implement pseudo-live
+ * sources. It only makes sense to implement the #GstBaseSrcClass::get_times
+ * function if the source is a live source. The #GstBaseSrcClass::get_times
  * function should return timestamps starting from 0, as if it were a non-live
  * source. The base class will make sure that the timestamps are transformed
  * into the current running_time. The base source will then wait for the
@@ -244,8 +244,8 @@ struct _GstBaseSrcPrivate
   GstClockTimeDiff ts_offset;   /* OBJECT_LOCK */
 
   gboolean do_timestamp;        /* OBJECT_LOCK */
-  volatile gint dynamic_size;   /* atomic */
-  volatile gint automatic_eos;  /* atomic */
+  gint dynamic_size;            /* atomic */
+  gint automatic_eos;           /* atomic */
 
   /* stream sequence number */
   guint32 seqnum;               /* STREAM_LOCK */
@@ -253,7 +253,7 @@ struct _GstBaseSrcPrivate
   /* pending events (TAG, CUSTOM_BOTH, CUSTOM_DOWNSTREAM) to be
    * pushed in the data stream */
   GList *pending_events;        /* OBJECT_LOCK */
-  volatile gint have_events;    /* OBJECT_LOCK */
+  gint have_events;             /* OBJECT_LOCK */
 
   /* QoS *//* with LOCK */
   gdouble proportion;           /* OBJECT_LOCK */
@@ -283,7 +283,7 @@ static void gst_base_src_finalize (GObject * object);
 GType
 gst_base_src_get_type (void)
 {
-  static volatile gsize base_src_type = 0;
+  static gsize base_src_type = 0;
 
   if (g_once_init_enter (&base_src_type)) {
     GType _type;
@@ -366,7 +366,7 @@ static GstFlowReturn gst_base_src_getrange (GstPad * pad, GstObject * parent,
 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_negotiate_unlocked (GstBaseSrc * basesrc);
 static gboolean gst_base_src_update_length (GstBaseSrc * src, guint64 offset,
     guint * length, gboolean force);
 
@@ -455,7 +455,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
   g_cond_init (&basesrc->live_cond);
   basesrc->num_buffers = DEFAULT_NUM_BUFFERS;
   basesrc->num_buffers_left = -1;
-  basesrc->priv->automatic_eos = TRUE;
+  g_atomic_int_set (&basesrc->priv->automatic_eos, TRUE);
 
   basesrc->can_activate_push = TRUE;
 
@@ -546,7 +546,7 @@ flushing:
  * gst_base_src_wait_playing:
  * @src: the src
  *
- * If the #GstBaseSrcClass.create() method performs its own synchronisation
+ * If the #GstBaseSrcClass::create method performs its own synchronisation
  * against the clock it must unblock when going from PLAYING to the PAUSED state
  * and call this method before continuing to produce the remaining data.
  *
@@ -627,7 +627,7 @@ gst_base_src_is_live (GstBaseSrc * src)
  * for sending SEGMENT events and for performing seeks.
  *
  * If a format of GST_FORMAT_BYTES is set, the element will be able to
- * operate in pull mode if the #GstBaseSrcClass.is_seekable() returns %TRUE.
+ * operate in pull mode if the #GstBaseSrcClass::is_seekable returns %TRUE.
  *
  * This function must only be called in states < %GST_STATE_PAUSED.
  */
@@ -672,7 +672,7 @@ gst_base_src_set_dynamic_size (GstBaseSrc * src, gboolean dynamic)
  * When @src operates in %GST_FORMAT_TIME, #GstBaseSrc will send an EOS
  * when a buffer outside of the currently configured segment is pushed if
  * @automatic_eos is %TRUE. Since 1.16, if @automatic_eos is %FALSE an
- * EOS will be pushed only when the #GstBaseSrc.create implementation
+ * EOS will be pushed only when the #GstBaseSrcClass::create implementation
  * returns %GST_FLOW_EOS.
  *
  * Since: 1.4
@@ -894,13 +894,15 @@ gst_base_src_get_do_timestamp (GstBaseSrc * src)
  * @time: The new time value for the start of the new segment
  *
  * Prepare a new seamless segment for emission downstream. This function must
- * only be called by derived sub-classes, and only from the create() function,
+ * only be called by derived sub-classes, and only from the #GstBaseSrcClass::create function,
  * as the stream-lock needs to be held.
  *
  * The format for the new segment will be the current format of the source, as
  * configured with gst_base_src_set_format()
  *
  * Returns: %TRUE if preparation of the seamless segment succeeded.
+ *
+ * Deprecated: 1.18: Use gst_base_src_new_segment()
  */
 gboolean
 gst_base_src_new_seamless_segment (GstBaseSrc * src, gint64 start, gint64 stop,
@@ -934,6 +936,61 @@ gst_base_src_new_seamless_segment (GstBaseSrc * src, gint64 start, gint64 stop,
   return res;
 }
 
+/**
+ * gst_base_src_new_segment:
+ * @src: a #GstBaseSrc
+ * @segment: a pointer to a #GstSegment
+ *
+ * Prepare a new segment for emission downstream. This function must
+ * only be called by derived sub-classes, and only from the #GstBaseSrcClass::create function,
+ * as the stream-lock needs to be held.
+ *
+ * The format for the @segment must be identical with the current format
+ * of the source, as configured with gst_base_src_set_format().
+ *
+ * The format of @src must not be %GST_FORMAT_UNDEFINED and the format
+ * should be configured via gst_base_src_set_format() before calling this method.
+ *
+ * Returns: %TRUE if preparation of new segment succeeded.
+ *
+ * Since: 1.18
+ */
+gboolean
+gst_base_src_new_segment (GstBaseSrc * src, const GstSegment * segment)
+{
+  g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
+  g_return_val_if_fail (segment != NULL, FALSE);
+
+  GST_OBJECT_LOCK (src);
+
+  if (src->segment.format == GST_FORMAT_UNDEFINED) {
+    /* subclass must set valid format before calling this method */
+    GST_WARNING_OBJECT (src, "segment format is not configured yet, ignore");
+    GST_OBJECT_UNLOCK (src);
+    return FALSE;
+  }
+
+  if (src->segment.format != segment->format) {
+    GST_WARNING_OBJECT (src, "segment format mismatched, ignore");
+    GST_OBJECT_UNLOCK (src);
+    return FALSE;
+  }
+
+  gst_segment_copy_into (segment, &src->segment);
+
+  /* Mark pending segment. Will be sent before next data */
+  src->priv->segment_pending = TRUE;
+  src->priv->segment_seqnum = gst_util_seqnum_next ();
+
+  GST_DEBUG_OBJECT (src, "Starting new segment %" GST_SEGMENT_FORMAT, segment);
+
+  GST_OBJECT_UNLOCK (src);
+
+  src->running = TRUE;
+
+  return TRUE;
+}
+
 /* called with STREAM_LOCK */
 static gboolean
 gst_base_src_send_stream_start (GstBaseSrc * src)
@@ -1464,8 +1521,11 @@ gst_base_src_default_prepare_seek_segment (GstBaseSrc * src, GstEvent * event,
   }
 
   /* And finally, configure our output segment in the desired format */
-  gst_segment_do_seek (segment, rate, dest_format, flags, start_type, start,
-      stop_type, stop, &update);
+  if (res) {
+    res =
+        gst_segment_do_seek (segment, rate, dest_format, flags, start_type,
+        start, stop_type, stop, &update);
+  }
 
   if (!res)
     goto no_format;
@@ -2912,7 +2972,7 @@ gst_base_src_loop (GstPad * pad)
 
   /* check if we need to renegotiate */
   if (gst_pad_check_reconfigure (pad)) {
-    if (!gst_base_src_negotiate (src)) {
+    if (!gst_base_src_negotiate_unlocked (src)) {
       gst_pad_mark_reconfigure (pad);
       if (GST_PAD_IS_FLUSHING (pad)) {
         GST_LIVE_LOCK (src);
@@ -3023,10 +3083,6 @@ gst_base_src_loop (GstPad * pad)
       if (GST_CLOCK_TIME_IS_VALID (duration)) {
         if (src->segment.rate >= 0.0)
           position += duration;
-        else if (position > duration)
-          position -= duration;
-        else
-          position = 0;
       }
       break;
     }
@@ -3135,10 +3191,9 @@ flushing:
   }
 pause:
   {
-    const gchar *reason = gst_flow_get_name (ret);
     GstEvent *event;
 
-    GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason);
+    GST_DEBUG_OBJECT (src, "pausing task, reason %s", gst_flow_get_name (ret));
     src->running = FALSE;
     gst_pad_pause_task (pad);
     if (ret == GST_FLOW_EOS) {
@@ -3194,7 +3249,7 @@ pause:
 
 static gboolean
 gst_base_src_set_allocation (GstBaseSrc * basesrc, GstBufferPool * pool,
-    GstAllocator * allocator, GstAllocationParams * params)
+    GstAllocator * allocator, const GstAllocationParams * params)
 {
   GstAllocator *oldalloc;
   GstBufferPool *oldpool;
@@ -3490,7 +3545,7 @@ no_caps:
 }
 
 static gboolean
-gst_base_src_negotiate (GstBaseSrc * basesrc)
+gst_base_src_negotiate_unlocked (GstBaseSrc * basesrc)
 {
   GstBaseSrcClass *bclass;
   gboolean result;
@@ -3517,6 +3572,39 @@ gst_base_src_negotiate (GstBaseSrc * basesrc)
   return result;
 }
 
+/**
+ * gst_base_src_negotiate:
+ * @src: base source instance
+ *
+ * Negotiates src pad caps with downstream elements.
+ * Unmarks GST_PAD_FLAG_NEED_RECONFIGURE in any case. But marks it again
+ * if #GstBaseSrcClass::negotiate fails.
+ *
+ * Do not call this in the #GstBaseSrcClass::fill vmethod. Call this in
+ * #GstBaseSrcClass::create or in #GstBaseSrcClass::alloc, _before_ any
+ * buffer is allocated.
+ *
+ * Returns: %TRUE if the negotiation succeeded, else %FALSE.
+ *
+ * Since: 1.18
+ */
+gboolean
+gst_base_src_negotiate (GstBaseSrc * src)
+{
+  gboolean ret = TRUE;
+
+  g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
+
+  GST_PAD_STREAM_LOCK (src->srcpad);
+  gst_pad_check_reconfigure (src->srcpad);
+  ret = gst_base_src_negotiate_unlocked (src);
+  if (!ret)
+    gst_pad_mark_reconfigure (src->srcpad);
+  GST_PAD_STREAM_UNLOCK (src->srcpad);
+
+  return ret;
+}
+
 static gboolean
 gst_base_src_start (GstBaseSrc * basesrc)
 {
@@ -4082,7 +4170,7 @@ failure:
  * gst_base_src_get_buffer_pool:
  * @src: a #GstBaseSrc
  *
- * Returns: (transfer full): the instance of the #GstBufferPool used
+ * Returns: (nullable) (transfer full): the instance of the #GstBufferPool used
  * by the src; unref it after usage.
  */
 GstBufferPool *
@@ -4103,10 +4191,9 @@ gst_base_src_get_buffer_pool (GstBaseSrc * src)
 /**
  * gst_base_src_get_allocator:
  * @src: a #GstBaseSrc
- * @allocator: (out) (allow-none) (transfer full): the #GstAllocator
+ * @allocator: (out) (optional) (nullable) (transfer full): the #GstAllocator
  * used
- * @params: (out) (allow-none) (transfer full): the
- * #GstAllocationParams of @allocator
+ * @params: (out caller-allocates) (optional): the #GstAllocationParams of @allocator
  *
  * Lets #GstBaseSrc sub-classes to know the memory @allocator
  * used by the base class and its @params.
index 225c9ca..9fd9c00 100644 (file)
@@ -135,20 +135,20 @@ struct _GstBaseSrc {
  *     gst_base_src_set_format().
  * @is_seekable: Check if the source can seek
  * @prepare_seek_segment: Prepare the #GstSegment that will be passed to the
- *   #GstBaseSrcClass.do_seek() vmethod for executing a seek
+ *   #GstBaseSrcClass::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.
  * @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
+ *    any blocked function ASAP. In particular, any `create()` function in
  *    progress should be unblocked and should return GST_FLOW_FLUSHING. Any
- *    future #GstBaseSrcClass.create() function call should also return
- *    GST_FLOW_FLUSHING until the #GstBaseSrcClass.unlock_stop() function has
+ *    future #GstBaseSrcClass::create function call should also return
+ *    GST_FLOW_FLUSHING until the #GstBaseSrcClass::unlock_stop function has
  *    been called.
  * @unlock_stop: Clear the previous unlock request. Subclasses should clear any
- *    state they set during #GstBaseSrcClass.unlock(), such as clearing command
+ *    state they set during #GstBaseSrcClass::unlock, such as clearing command
  *    queues.
  * @query: Handle a requested query.
  * @event: Override this to implement custom event handling.
@@ -158,7 +158,7 @@ struct _GstBaseSrc {
  *   buffer should be returned when the return value is different from
  *   GST_FLOW_OK. A return value of GST_FLOW_EOS signifies that the end of
  *   stream is reached. The default implementation will call
- *   #GstBaseSrcClass.alloc() and then call #GstBaseSrcClass.fill().
+ *   #GstBaseSrcClass::alloc and then call #GstBaseSrcClass::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
@@ -174,7 +174,12 @@ struct _GstBaseSrcClass {
   /*< public >*/
   /* virtual methods for subclasses */
 
-  /* get caps from subclass */
+  /**
+   * GstBaseSrcClass::get_caps:
+   * @filter: (in) (nullable):
+   *
+   * Called to get the caps to report.
+   */
   GstCaps*      (*get_caps)     (GstBaseSrc *src, GstCaps *filter);
   /* decide on caps */
   gboolean      (*negotiate)    (GstBaseSrc *src);
@@ -282,6 +287,9 @@ GST_BASE_API
 gboolean        gst_base_src_is_async         (GstBaseSrc *src);
 
 GST_BASE_API
+gboolean        gst_base_src_negotiate        (GstBaseSrc *src);
+
+GST_BASE_API
 void            gst_base_src_start_complete   (GstBaseSrc * basesrc, GstFlowReturn ret);
 
 GST_BASE_API
@@ -307,6 +315,10 @@ GST_BASE_API
 gboolean        gst_base_src_new_seamless_segment (GstBaseSrc *src, gint64 start, gint64 stop, gint64 time);
 
 GST_BASE_API
+gboolean        gst_base_src_new_segment      (GstBaseSrc *src,
+                                               const GstSegment * segment);
+
+GST_BASE_API
 gboolean        gst_base_src_set_caps         (GstBaseSrc *src, GstCaps *caps);
 
 GST_BASE_API
@@ -321,9 +333,7 @@ GST_BASE_API
 void            gst_base_src_submit_buffer_list (GstBaseSrc    * src,
                                                  GstBufferList * buffer_list);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBaseSrc, gst_object_unref)
-#endif
 
 #ifdef TIZEN_PROFILE_TV
 GST_BASE_API
index 5ddad78..e4e7ee6 100644 (file)
@@ -219,7 +219,7 @@ static GstFlowReturn default_generate_output (GstBaseTransform * trans,
 GType
 gst_base_transform_get_type (void)
 {
-  static volatile gsize base_transform_type = 0;
+  static gsize base_transform_type = 0;
 
   if (g_once_init_enter (&base_transform_type)) {
     GType _type;
@@ -306,7 +306,7 @@ static gboolean default_copy_metadata (GstBaseTransform * trans,
     GstBuffer * inbuf, GstBuffer * outbuf);
 static gboolean
 gst_base_transform_default_transform_meta (GstBaseTransform * trans,
-    GstBuffer * inbuf, GstMeta * meta, GstBuffer * outbuf);
+    GstBuffer * outbuf, GstMeta * meta, GstBuffer * inbuf);
 
 /* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
 
@@ -502,7 +502,7 @@ gst_base_transform_transform_caps (GstBaseTransform * trans,
 
 static gboolean
 gst_base_transform_default_transform_meta (GstBaseTransform * trans,
-    GstBuffer * inbuf, GstMeta * meta, GstBuffer * outbuf)
+    GstBuffer * outbuf, GstMeta * meta, GstBuffer * inbuf)
 {
   const GstMetaInfo *info = meta->info;
   const gchar *const *tags;
@@ -636,7 +636,7 @@ gst_base_transform_query_caps (GstBaseTransform * trans, GstPad * pad,
   templ = gst_pad_get_pad_template_caps (pad);
   otempl = gst_pad_get_pad_template_caps (otherpad);
 
-  /* first prepare the filter to be send onwards. We need to filter and
+  /* first prepare the filter to be sent onwards. We need to filter and
    * transform it to valid caps for the otherpad. */
   if (filter) {
     GST_DEBUG_OBJECT (pad, "filter caps  %" GST_PTR_FORMAT, filter);
@@ -652,28 +652,31 @@ gst_base_transform_query_caps (GstBaseTransform * trans, GstPad * pad,
     GST_DEBUG_OBJECT (pad, "transformed  %" GST_PTR_FORMAT, peerfilter);
     gst_caps_unref (temp);
 
-    if (peerfilter && !gst_caps_is_empty (peerfilter)) {
-      /* and filter against the template of the other pad */
-      GST_DEBUG_OBJECT (pad, "our template  %" GST_PTR_FORMAT, otempl);
-      /* We keep the caps sorted like the returned caps */
-      temp =
-          gst_caps_intersect_full (peerfilter, otempl,
-          GST_CAPS_INTERSECT_FIRST);
-      GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
-      gst_caps_unref (peerfilter);
-      peerfilter = temp;
+    if (peerfilter) {
+      if (!gst_caps_is_empty (peerfilter)) {
+        /* and filter against the template of the other pad */
+        GST_DEBUG_OBJECT (pad, "our template  %" GST_PTR_FORMAT, otempl);
+        /* We keep the caps sorted like the returned caps */
+        temp =
+            gst_caps_intersect_full (peerfilter, otempl,
+            GST_CAPS_INTERSECT_FIRST);
+        GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
+        gst_caps_unref (peerfilter);
+        peerfilter = temp;
+      }
+
+      /* If we filter out everything, bail out */
+      if (peerfilter && gst_caps_is_empty (peerfilter)) {
+        GST_DEBUG_OBJECT (pad, "peer filter caps are empty");
+        caps = peerfilter;
+        peerfilter = NULL;
+        goto done;
+      }
     }
   }
 
   GST_DEBUG_OBJECT (pad, "peer filter caps %" GST_PTR_FORMAT, peerfilter);
 
-  if (peerfilter && gst_caps_is_empty (peerfilter)) {
-    GST_DEBUG_OBJECT (pad, "peer filter caps are empty");
-    caps = peerfilter;
-    peerfilter = NULL;
-    goto done;
-  }
-
   /* query the peer with the transformed filter */
   peercaps = gst_pad_peer_query_caps (otherpad, peerfilter);
 
@@ -743,7 +746,7 @@ done:
 static gboolean
 gst_base_transform_set_allocation (GstBaseTransform * trans,
     GstBufferPool * pool, GstAllocator * allocator,
-    GstAllocationParams * params, GstQuery * query)
+    const GstAllocationParams * params, GstQuery * query)
 {
   GstAllocator *oldalloc;
   GstBufferPool *oldpool;
@@ -1176,7 +1179,12 @@ gst_base_transform_find_transform (GstBaseTransform * trans, GstPad * pad,
      * function, it needs to truncate itself */
     othercaps =
         klass->fixate_caps (trans, GST_PAD_DIRECTION (pad), caps, othercaps);
-    is_fixed = gst_caps_is_fixed (othercaps);
+
+    if (!othercaps) {
+      g_critical ("basetransform: second attempt to fixate caps returned "
+          "invalid (NULL) caps on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
+    }
+    is_fixed = othercaps && gst_caps_is_fixed (othercaps);
     GST_DEBUG_OBJECT (trans, "after fixating %" GST_PTR_FORMAT, othercaps);
   }
 
@@ -1402,7 +1410,7 @@ gst_base_transform_default_propose_allocation (GstBaseTransform * trans,
 }
 
 static gboolean
-gst_base_transform_reconfigure (GstBaseTransform * trans)
+gst_base_transform_reconfigure_unlocked (GstBaseTransform * trans)
 {
   gboolean reconfigure, ret = TRUE;
 
@@ -1436,6 +1444,45 @@ done:
   return ret;
 }
 
+/**
+ * gst_base_transform_reconfigure:
+ * @trans: the #GstBaseTransform to set
+ *
+ * Negotiates src pad caps with downstream elements if the source pad is
+ * marked as needing reconfiguring. Unmarks GST_PAD_FLAG_NEED_RECONFIGURE in
+ * any case. But marks it again if negotiation fails.
+ *
+ * Do not call this in the #GstBaseTransformClass::transform or
+ * #GstBaseTransformClass::transform_ip vmethod. Call this in
+ * #GstBaseTransformClass::submit_input_buffer,
+ * #GstBaseTransformClass::prepare_output_buffer or in
+ * #GstBaseTransformClass::generate_output _before_ any output buffer is
+ * allocated.
+ *
+ * It will be default be called when handling an ALLOCATION query or at the
+ * very beginning of the default #GstBaseTransformClass::submit_input_buffer
+ * implementation.
+ *
+ * Returns: %TRUE if the negotiation succeeded, else %FALSE.
+ *
+ * Since: 1.18
+ */
+gboolean
+gst_base_transform_reconfigure (GstBaseTransform * trans)
+{
+  gboolean ret;
+
+  g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), FALSE);
+
+  GST_PAD_STREAM_LOCK (trans->sinkpad);
+  ret = gst_base_transform_reconfigure_unlocked (trans);
+  if (!ret)
+    gst_pad_mark_reconfigure (trans->srcpad);
+  GST_PAD_STREAM_UNLOCK (trans->sinkpad);
+
+  return ret;
+}
+
 static gboolean
 gst_base_transform_default_query (GstBaseTransform * trans,
     GstPadDirection direction, GstQuery * query)
@@ -1464,7 +1511,7 @@ gst_base_transform_default_query (GstBaseTransform * trans,
       if (direction != GST_PAD_SINK)
         goto done;
 
-      ret = gst_base_transform_reconfigure (trans);
+      ret = gst_base_transform_reconfigure_unlocked (trans);
       if (G_UNLIKELY (!ret))
         goto done;
 
@@ -1984,7 +2031,7 @@ default_submit_input_buffer (GstBaseTransform * trans, gboolean is_discont,
   GstClockTime running_time;
   GstClockTime timestamp;
 
-  if (G_UNLIKELY (!gst_base_transform_reconfigure (trans)))
+  if (G_UNLIKELY (!gst_base_transform_reconfigure_unlocked (trans)))
     goto not_negotiated;
 
   if (GST_BUFFER_OFFSET_IS_VALID (inbuf))
@@ -2515,7 +2562,7 @@ gst_base_transform_src_activate_mode (GstPad * pad, GstObject * parent,
  * useful for filters that do not care about negotiation.
  *
  * Always %TRUE for filters which don't implement either a transform
- * or transform_ip method.
+ * or transform_ip or generate_output method.
  *
  * MT safe.
  */
@@ -2531,7 +2578,8 @@ gst_base_transform_set_passthrough (GstBaseTransform * trans,
 
   GST_OBJECT_LOCK (trans);
   if (!passthrough) {
-    if (bclass->transform_ip || bclass->transform)
+    if (bclass->transform_ip || bclass->transform || (bclass->generate_output
+            && bclass->generate_output != default_generate_output))
       trans->priv->passthrough = FALSE;
   } else {
     trans->priv->passthrough = TRUE;
@@ -2547,7 +2595,7 @@ gst_base_transform_set_passthrough (GstBaseTransform * trans,
  *
  * See if @trans is configured as a passthrough transform.
  *
- * Returns: %TRUE is the transform is configured in passthrough mode.
+ * Returns: %TRUE if the transform is configured in passthrough mode.
  *
  * MT safe.
  */
@@ -2611,7 +2659,7 @@ gst_base_transform_set_in_place (GstBaseTransform * trans, gboolean in_place)
  *
  * See if @trans is configured as a in_place transform.
  *
- * Returns: %TRUE is the transform is configured in in_place mode.
+ * Returns: %TRUE if the transform is configured in in_place mode.
  *
  * MT safe.
  */
@@ -2648,6 +2696,7 @@ gst_base_transform_update_qos (GstBaseTransform * trans,
     gdouble proportion, GstClockTimeDiff diff, GstClockTime timestamp)
 {
   g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
+  g_return_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp));
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, trans,
       "qos: proportion: %lf, diff %" G_GINT64_FORMAT ", timestamp %"
@@ -2799,8 +2848,8 @@ gst_base_transform_reconfigure_src (GstBaseTransform * trans)
  * gst_base_transform_get_buffer_pool:
  * @trans: a #GstBaseTransform
  *
- * Returns: (transfer full): the instance of the #GstBufferPool used
- * by @trans; free it after use it
+ * Returns: (nullable) (transfer full): the instance of the #GstBufferPool used
+ * by @trans; free it after use
  */
 GstBufferPool *
 gst_base_transform_get_buffer_pool (GstBaseTransform * trans)
@@ -2816,15 +2865,14 @@ gst_base_transform_get_buffer_pool (GstBaseTransform * trans)
 /**
  * gst_base_transform_get_allocator:
  * @trans: a #GstBaseTransform
- * @allocator: (out) (allow-none) (transfer full): the #GstAllocator
+ * @allocator: (out) (optional) (nullable) (transfer full): the #GstAllocator
  * used
- * @params: (out) (allow-none) (transfer full): the
- * #GstAllocationParams of @allocator
+ * @params: (out caller-allocates) (optional): the #GstAllocationParams of @allocator
  *
- * Lets #GstBaseTransform sub-classes to know the memory @allocator
+ * Lets #GstBaseTransform sub-classes know the memory @allocator
  * used by the base class and its @params.
  *
- * Unref the @allocator after use it.
+ * Unref the @allocator after use.
  */
 void
 gst_base_transform_get_allocator (GstBaseTransform * trans,
@@ -2846,13 +2894,13 @@ gst_base_transform_get_allocator (GstBaseTransform * trans,
  * @updated_caps: An updated version of the srcpad caps to be pushed
  * downstream
  *
- * Updates the srcpad caps and send the caps downstream. This function
+ * Updates the srcpad caps and sends the caps downstream. This function
  * can be used by subclasses when they have already negotiated their caps
  * but found a change in them (or computed new information). This way,
  * they can notify downstream about that change without losing any
  * buffer.
  *
- * Returns: %TRUE if the caps could be send downstream %FALSE otherwise
+ * Returns: %TRUE if the caps could be sent downstream %FALSE otherwise
  *
  * Since: 1.6
  */
index 652361d..0457b89 100644 (file)
@@ -123,10 +123,10 @@ struct _GstBaseTransform {
  *                  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.
+ * @set_caps:       Allows the subclass to be notified of the actual caps set.
  * @query:          Optional.
  *                  Handle a requested query. Subclasses that implement this
- *                  should must chain up to the parent if they didn't handle the
+ *                  must chain up to the parent if they didn't handle the
  *                  query
  * @decide_allocation: Setup the allocation parameters for allocating output
  *                    buffers. The passed in query contains the result of the
@@ -153,7 +153,7 @@ struct _GstBaseTransform {
  *                  The default implementation uses get_unit_size and keeps
  *                  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.
+ *                  Get the size in bytes of one unit for the given caps.
  * @start:          Optional.
  *                  Called when the element starts processing.
  *                  Allows opening external resources.
@@ -181,7 +181,7 @@ struct _GstBaseTransform {
  *                 offsets of the buffer.
  * @transform_meta: Optional. Transform the metadata on the input buffer to the
  *                  output buffer. By default this method copies all meta without
- *                  tags. subclasses can implement this method and return %TRUE if
+ *                  tags. Subclasses can implement this method and return %TRUE if
  *                  the metadata is to be copied.
  * @before_transform: Optional.
  *                    This method is called right before the base class will
@@ -206,7 +206,7 @@ struct _GstBaseTransform {
  *                   @queued_buf variable, generates an output buffer if needed
  *                   by calling the class @prepare_output_buffer, and then
  *                   calls either @transform or @transform_ip. Elements that don't
- *                   do 1-to-1 transformations on input to output buffers can either
+ *                   do 1-to-1 transformations of input to output buffers can either
  *                   return GST_BASE_TRANSFORM_FLOW_DROPPED or simply not generate
  *                   an output buffer until they are ready to do so. (Since: 1.6)
  *
@@ -226,6 +226,10 @@ struct _GstBaseTransformClass {
   GstCaps*     (*transform_caps) (GstBaseTransform *trans,
                                    GstPadDirection direction,
                                    GstCaps *caps, GstCaps *filter);
+  /**
+   * GstBaseTransformClass::fixate_caps:
+   * @othercaps: (transfer full):
+   */
   GstCaps*     (*fixate_caps)    (GstBaseTransform *trans,
                                    GstPadDirection direction, GstCaps *caps,
                                    GstCaps *othercaps);
@@ -266,7 +270,15 @@ struct _GstBaseTransformClass {
   gboolean      (*stop)         (GstBaseTransform *trans);
 
   /* sink and src pad event handlers */
+  /**
+   * GstBaseTransformClass::sink_event:
+   * @event: (transfer full):
+   */
   gboolean      (*sink_event)   (GstBaseTransform *trans, GstEvent *event);
+  /**
+   * GstBaseTransformClass::src_event:
+   * @event: (transfer full):
+   */
   gboolean      (*src_event)    (GstBaseTransform *trans, GstEvent *event);
 
   /**
@@ -350,9 +362,10 @@ GST_BASE_API
 gboolean gst_base_transform_update_src_caps (GstBaseTransform *trans,
                                              GstCaps *updated_caps);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
+GST_BASE_API
+gboolean gst_base_transform_reconfigure (GstBaseTransform * trans);
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBaseTransform, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 9df36d1..db97ad5 100644 (file)
  * SECTION:gstbitreader
  * @title: GstBitReader
  * @short_description: Reads any number of bits from a memory buffer
+ * @symbols:
+ * - gst_bit_reader_skip_unchecked
+ * - gst_bit_reader_skip_to_byte_unchecked
+ * - gst_bit_reader_get_bits_uint8_unchecked
+ * - gst_bit_reader_peek_bits_uint8_unchecked
+ * - gst_bit_reader_get_bits_uint16_unchecked
+ * - gst_bit_reader_peek_bits_uint16_unchecked
+ * - gst_bit_reader_get_bits_uint32_unchecked
+ * - gst_bit_reader_peek_bits_uint32_unchecked
+ * - gst_bit_reader_get_bits_uint64_unchecked
+ * - gst_bit_reader_peek_bits_uint64_unchecked
  *
  * #GstBitReader provides a bit reader that can read any number of bits
  * from a memory buffer. It provides functions for reading any number of bits
index de412b7..7086c3c 100644 (file)
@@ -27,9 +27,7 @@
 #define GST_BIT_WRITER_DISABLE_INLINES
 #include "gstbitwriter.h"
 
-#ifdef TIZEN_FEATURE_UPSTREAM
 #include "gst/glib-compat-private.h"
-#endif /* TIZEN_FEATURE_UPSTREAM */
 
 /**
  * SECTION:gstbitwriter
@@ -88,7 +86,7 @@ gst_bit_writer_new_with_size (guint size, gboolean fixed)
  *
  * Creates a new #GstBitWriter instance with the given memory area. If
  * @initialized is %TRUE it is possible to read @size bits from the
- * #GstBitWriter from the beginnig.
+ * #GstBitWriter from the beginning.
  *
  * Free-function: gst_bit_writer_free
  *
@@ -204,11 +202,7 @@ gst_bit_writer_reset_and_get_data (GstBitWriter * bitwriter)
 
   data = bitwriter->data;
   if (bitwriter->owned)
-#ifdef TIZEN_FEATURE_UPSTREAM
-    data = g_memdup2 (data, bitwriter->bit_size >> 3);
-#else /* TIZEN_FEATURE_UPSTREAM */
-    data = g_memdup (data, bitwriter->bit_size >> 3);
-#endif /* TIZEN_FEATURE_UPSTREAM */
+    data = g_memdup2 (data, GST_ROUND_UP_8 (bitwriter->bit_size) >> 3);
   gst_bit_writer_reset (bitwriter);
 
   return data;
@@ -231,20 +225,19 @@ gst_bit_writer_reset_and_get_buffer (GstBitWriter * bitwriter)
   GstBuffer *buffer;
   gpointer data;
   gsize size;
+  gboolean owned;
 
   g_return_val_if_fail (bitwriter != NULL, NULL);
 
-  size = bitwriter->bit_size >> 3;
+  owned = bitwriter->owned;
+
+  size = GST_ROUND_UP_8 (bitwriter->bit_size) >> 3;
   data = gst_bit_writer_reset_and_get_data (bitwriter);
 
   /* we cannot rely on buffers allocated externally, thus let's dup
    * the data */
-  if (data && !bitwriter->owned)
-#ifdef TIZEN_FEATURE_UPSTREAM
+  if (data && !owned)
     data = g_memdup2 (data, size);
-#else /* TIZEN_FEATURE_UPSTREAM */
-    data = g_memdup (data, size);
-#endif /* TIZEN_FEATURE_UPSTREAM */
 
   buffer = gst_buffer_new ();
   if (data != NULL) {
@@ -353,7 +346,7 @@ gst_bit_writer_get_data (const GstBitWriter * bitwriter)
  * @bitwriter: a #GstBitWriter instance
  * @pos: The new position in bits
  *
- * Set the new postion of data end which should be the new size of @data.
+ * Set the new position of data end which should be the new size of @data.
  *
  * Returns: %TRUE if successful, %FALSE otherwise
  */
index 43e2bca..c0a16ef 100644 (file)
@@ -26,9 +26,7 @@
 #define GST_BYTE_READER_DISABLE_INLINES
 #include "gstbytereader.h"
 
-#ifdef TIZEN_FEATURE_UPSTREAM
 #include "gst/glib-compat-private.h"
-#endif /* TIZEN_FEATURE_UPSTREAM */
 #include <string.h>
 
 /**
  * @title: GstByteReader
  * @short_description: Reads different integer, string and floating point
  *     types from a memory buffer
+ * @symbols:
+ * - gst_byte_reader_skip_unchecked
+ * - gst_byte_reader_get_uint8_unchecked
+ * - gst_byte_reader_peek_uint8_unchecked
+ * - gst_byte_reader_get_int8_unchecked
+ * - gst_byte_reader_peek_int8_unchecked
+ * - gst_byte_reader_get_uint16_le_unchecked
+ * - gst_byte_reader_get_uint16_be_unchecked
+ * - gst_byte_reader_peek_uint16_le_unchecked
+ * - gst_byte_reader_peek_uint16_be_unchecked
+ * - gst_byte_reader_get_int16_le_unchecked
+ * - gst_byte_reader_get_int16_be_unchecked
+ * - gst_byte_reader_peek_int16_le_unchecked
+ * - gst_byte_reader_peek_int16_be_unchecked
+ * - gst_byte_reader_get_uint24_le_unchecked
+ * - gst_byte_reader_get_uint24_be_unchecked
+ * - gst_byte_reader_peek_uint24_le_unchecked
+ * - gst_byte_reader_peek_uint24_be_unchecked
+ * - gst_byte_reader_get_int24_le_unchecked
+ * - gst_byte_reader_get_int24_be_unchecked
+ * - gst_byte_reader_peek_int24_le_unchecked
+ * - gst_byte_reader_peek_int24_be_unchecked
+ * - gst_byte_reader_get_uint32_le_unchecked
+ * - gst_byte_reader_get_uint32_be_unchecked
+ * - gst_byte_reader_peek_uint32_le_unchecked
+ * - gst_byte_reader_peek_uint32_be_unchecked
+ * - gst_byte_reader_get_int32_le_unchecked
+ * - gst_byte_reader_get_int32_be_unchecked
+ * - gst_byte_reader_peek_int32_le_unchecked
+ * - gst_byte_reader_peek_int32_be_unchecked
+ * - gst_byte_reader_get_float32_le_unchecked
+ * - gst_byte_reader_get_float32_be_unchecked
+ * - gst_byte_reader_get_float64_le_unchecked
+ * - gst_byte_reader_get_float64_be_unchecked
+ * - gst_byte_reader_peek_float32_le_unchecked
+ * - gst_byte_reader_peek_float32_be_unchecked
+ * - gst_byte_reader_peek_float64_le_unchecked
+ * - gst_byte_reader_peek_float64_be_unchecked
+ * - gst_byte_reader_peek_data_unchecked
+ * - gst_byte_reader_get_data_unchecked
+ * - gst_byte_reader_dup_data_unchecked
  *
  * #GstByteReader provides a byte reader that can read different integer and
  * floating point types from a memory buffer. It provides functions for reading
@@ -1170,7 +1209,6 @@ gst_byte_reader_get_string_utf8 (GstByteReader * reader, const gchar ** str)
   return TRUE;
 }
 
-#ifdef TIZEN_FEATURE_UPSTREAM
 #define GST_BYTE_READER_DUP_STRING(bits,type) \
 gboolean \
 gst_byte_reader_dup_string_utf##bits (GstByteReader * reader, type ** str) \
@@ -1189,26 +1227,6 @@ gst_byte_reader_dup_string_utf##bits (GstByteReader * reader, type ** str) \
   reader->byte += size; \
   return TRUE; \
 }
-#else /* TIZEN_FEATURE_UPSTREAM */
-#define GST_BYTE_READER_DUP_STRING(bits,type) \
-gboolean \
-gst_byte_reader_dup_string_utf##bits (GstByteReader * reader, type ** str) \
-{ \
-  guint size; /* size in bytes including the terminator */ \
-  \
-  g_return_val_if_fail (reader != NULL, FALSE); \
-  g_return_val_if_fail (str != NULL, FALSE); \
-  \
-  size = gst_byte_reader_scan_string_utf##bits (reader); \
-  if (size == 0) { \
-    *str = NULL; \
-    return FALSE; \
-  } \
-  *str = g_memdup (reader->data + reader->byte, size); \
-  reader->byte += size; \
-  return TRUE; \
-}
-#endif /* TIZEN_FEATURE_UPSTREAM */
 
 /**
  * gst_byte_reader_dup_string_utf8:
index 52c56ed..2130a8a 100644 (file)
@@ -362,14 +362,10 @@ static inline guint8 *
 gst_byte_reader_dup_data_unchecked (GstByteReader * reader, guint size)
 {
   gconstpointer data = gst_byte_reader_get_data_unchecked (reader, size);
-#ifdef TIZEN_FEATURE_UPSTREAM
   guint8 *dup_data = (guint8 *) g_malloc (size);
 
   memcpy (dup_data, data, size);
   return dup_data;
-#else /* TIZEN_FEATURE_UPSTREAM */
-  return (guint8 *) g_memdup (data, size);
-#endif /* TIZEN_FEATURE_UPSTREAM */
 }
 
 /* Unchecked variants that should not be used */
index feb9d7d..aec1093 100644 (file)
 #define GST_BYTE_WRITER_DISABLE_INLINES
 #include "gstbytewriter.h"
 
-#ifdef TIZEN_FEATURE_UPSTREAM
 #include "gst/glib-compat-private.h"
-#endif /* TIZEN_FEATURE_UPSTREAM */
 
 /**
  * SECTION:gstbytewriter
  * @title: GstByteWriter
  * @short_description: Writes different integer, string and floating point
  *     types to a memory buffer and allows reading
+ * @symbols:
+ * - gst_byte_writer_put_uint8_unchecked
+ * - gst_byte_writer_put_uint16_be_unchecked
+ * - gst_byte_writer_put_uint24_be_unchecked
+ * - gst_byte_writer_put_uint32_be_unchecked
+ * - gst_byte_writer_put_uint64_be_unchecked
+ * - gst_byte_writer_put_uint16_le_unchecked
+ * - gst_byte_writer_put_uint24_le_unchecked
+ * - gst_byte_writer_put_uint32_le_unchecked
+ * - gst_byte_writer_put_uint64_le_unchecked
+ * - gst_byte_writer_put_int8_unchecked
+ * - gst_byte_writer_put_int16_be_unchecked
+ * - gst_byte_writer_put_int24_be_unchecked
+ * - gst_byte_writer_put_int32_be_unchecked
+ * - gst_byte_writer_put_int64_be_unchecked
+ * - gst_byte_writer_put_int16_le_unchecked
+ * - gst_byte_writer_put_int24_le_unchecked
+ * - gst_byte_writer_put_int32_le_unchecked
+ * - gst_byte_writer_put_int64_le_unchecked
+ * - gst_byte_writer_put_float32_be_unchecked
+ * - gst_byte_writer_put_float64_be_unchecked
+ * - gst_byte_writer_put_float32_le_unchecked
+ * - gst_byte_writer_put_float64_le_unchecked
+ * - gst_byte_writer_put_data_unchecked
+ * - gst_byte_writer_fill_unchecked
  *
  * #GstByteWriter provides a byte writer and reader that can write/read different
  * integer and floating point types to/from a memory buffer. It provides functions
@@ -215,11 +238,7 @@ gst_byte_writer_reset_and_get_data (GstByteWriter * writer)
 
   data = (guint8 *) writer->parent.data;
   if (!writer->owned)
-#ifdef TIZEN_FEATURE_UPSTREAM
     data = g_memdup2 (data, writer->parent.size);
-#else /* TIZEN_FEATURE_UPSTREAM */
-    data = g_memdup (data, writer->parent.size);
-#endif /* TIZEN_FEATURE_UPSTREAM */
   writer->parent.data = NULL;
   gst_byte_writer_reset (writer);
 
index 0c412aa..b6f9215 100644 (file)
@@ -24,7 +24,6 @@
  * SECTION:gstcollectpads
  * @title: GstCollectPads
  * @short_description: manages a set of pads that operate in collect mode
- * @see_also:
  *
  * Manages a set of pads that operate in collect mode. This means that control
  * is given to the manager of this object when all pads have data.
@@ -172,16 +171,13 @@ static gboolean gst_collect_pads_query_default_internal (GstCollectPads *
   g_mutex_unlock (GST_COLLECT_PADS_GET_EVT_LOCK (pads));          \
 } G_STMT_END
 #define GST_COLLECT_PADS_EVT_WAIT_TIMED(pads, cookie, timeout) G_STMT_START { \
-  GTimeVal __tv; \
-  \
-  g_get_current_time (&tv); \
-  g_time_val_add (&tv, timeout); \
+  gint64 end_time = g_get_monotonic_time () + timeout; \
   \
   g_mutex_lock (GST_COLLECT_PADS_GET_EVT_LOCK (pads));            \
   /* should work unless a lot of event'ing and thread starvation */\
   while (cookie == ((GstCollectPads *) pads)->priv->evt_cookie)         \
-    g_cond_timed_wait (GST_COLLECT_PADS_GET_EVT_COND (pads),            \
-        GST_COLLECT_PADS_GET_EVT_LOCK (pads), &tv);                    \
+    g_cond_wait_until (GST_COLLECT_PADS_GET_EVT_COND (pads),            \
+        GST_COLLECT_PADS_GET_EVT_LOCK (pads), end_time);                    \
   cookie = ((GstCollectPads *) pads)->priv->evt_cookie;                 \
   g_mutex_unlock (GST_COLLECT_PADS_GET_EVT_LOCK (pads));          \
 } G_STMT_END
@@ -409,7 +405,7 @@ unref_data (GstCollectData * data)
   if (data->priv->destroy_notify)
     data->priv->destroy_notify (data);
 
-  g_object_unref (data->pad);
+  gst_object_unref (data->pad);
   if (data->buffer) {
     gst_buffer_unref (data->buffer);
   }
index 2ddeaf3..13d60a1 100644 (file)
@@ -449,9 +449,7 @@ gboolean        gst_collect_pads_query_default (GstCollectPads * pads, GstCollec
                                                 GstQuery * query, gboolean discard);
 
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstCollectPads, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index d6479bb..ac93b8e 100644 (file)
@@ -156,7 +156,7 @@ gst_data_queue_class_init (GstDataQueueClass * klass)
   gst_data_queue_signals[SIGNAL_EMPTY] =
       g_signal_new ("empty", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
       G_STRUCT_OFFSET (GstDataQueueClass, empty), NULL, NULL,
-      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+      NULL, G_TYPE_NONE, 0);
 
   /**
    * GstDataQueue::full: (skip)
@@ -170,7 +170,7 @@ gst_data_queue_class_init (GstDataQueueClass * klass)
   gst_data_queue_signals[SIGNAL_FULL] =
       g_signal_new ("full", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
       G_STRUCT_OFFSET (GstDataQueueClass, full), NULL, NULL,
-      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+      NULL, G_TYPE_NONE, 0);
 
   /* properties */
   g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_BYTES,
index 4492e6d..e814a2b 100644 (file)
@@ -177,9 +177,7 @@ void           gst_data_queue_get_level      (GstDataQueue * queue, GstDataQueue
 GST_BASE_API
 void           gst_data_queue_limits_changed (GstDataQueue * queue);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstDataQueue, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 8b64a46..d353eae 100644 (file)
@@ -72,7 +72,7 @@ struct _GstFlowCombiner
   GQueue pads;
 
   GstFlowReturn last_ret;
-  volatile gint ref_count;
+  gint ref_count;
 };
 
 GST_DEBUG_CATEGORY_STATIC (flowcombiner_dbg);
@@ -99,7 +99,7 @@ gst_flow_combiner_new (void)
 
   g_queue_init (&combiner->pads);
   combiner->last_ret = GST_FLOW_OK;
-  combiner->ref_count = 1;
+  g_atomic_int_set (&combiner->ref_count, 1);
 
   /* Make sure debug category is initialised */
   gst_flow_combiner_get_type ();
@@ -180,6 +180,8 @@ gst_flow_combiner_clear (GstFlowCombiner * combiner)
 
   g_return_if_fail (combiner != NULL);
 
+  GST_DEBUG ("%p clearing", combiner);
+
   while ((pad = g_queue_pop_head (&combiner->pads)))
     gst_object_unref (pad);
   combiner->last_ret = GST_FLOW_OK;
@@ -200,7 +202,7 @@ gst_flow_combiner_reset (GstFlowCombiner * combiner)
 
   g_return_if_fail (combiner != NULL);
 
-  GST_DEBUG ("Reset flow returns");
+  GST_DEBUG ("%p reset flow returns", combiner);
 
   for (iter = combiner->pads.head; iter; iter = iter->next) {
     GST_PAD_LAST_FLOW_RETURN (iter->data) = GST_FLOW_OK;
@@ -217,13 +219,16 @@ gst_flow_combiner_get_flow (GstFlowCombiner * combiner)
   gboolean all_notlinked = TRUE;
   GList *iter;
 
-  GST_DEBUG ("Combining flow returns");
+  GST_DEBUG ("%p Combining flow returns", combiner);
 
   for (iter = combiner->pads.head; iter; iter = iter->next) {
     GstFlowReturn fret = GST_PAD_LAST_FLOW_RETURN (iter->data);
 
+    GST_TRACE ("%p pad %" GST_PTR_FORMAT " has flow return of %s (%d)",
+        combiner, iter->data, gst_flow_get_name (fret), fret);
+
     if (fret <= GST_FLOW_NOT_NEGOTIATED || fret == GST_FLOW_FLUSHING) {
-      GST_DEBUG ("Error flow return found, returning");
+      GST_DEBUG ("%p Error flow return found, returning", combiner);
       cret = fret;
       goto done;
     }
@@ -240,7 +245,8 @@ gst_flow_combiner_get_flow (GstFlowCombiner * combiner)
     cret = GST_FLOW_EOS;
 
 done:
-  GST_DEBUG ("Combined flow return: %s (%d)", gst_flow_get_name (cret), cret);
+  GST_DEBUG ("%p Combined flow return: %s (%d)", combiner,
+      gst_flow_get_name (cret), cret);
   return cret;
 }
 
@@ -266,11 +272,15 @@ gst_flow_combiner_update_flow (GstFlowCombiner * combiner, GstFlowReturn fret)
 
   g_return_val_if_fail (combiner != NULL, GST_FLOW_ERROR);
 
+  GST_DEBUG ("%p updating combiner with flow %s (%d)", combiner,
+      gst_flow_get_name (fret), fret);
+
   if (combiner->last_ret == fret) {
     return fret;
   }
 
-  if (fret <= GST_FLOW_NOT_NEGOTIATED || fret == GST_FLOW_FLUSHING) {
+  if (fret <= GST_FLOW_NOT_NEGOTIATED || fret == GST_FLOW_FLUSHING
+      || !combiner->pads.head) {
     ret = fret;
   } else {
     ret = gst_flow_combiner_get_flow (combiner);
index bd06da8..fa905a9 100644 (file)
@@ -75,9 +75,7 @@ void              gst_flow_combiner_reset (GstFlowCombiner * combiner);
 GST_BASE_API
 GType             gst_flow_combiner_get_type (void);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstFlowCombiner, gst_flow_combiner_free)
-#endif
 
 G_END_DECLS
 
index a77a550..964508e 100644 (file)
@@ -39,7 +39,7 @@
  * The application that wants to index the stream will create a new index object
  * using gst_index_new() or gst_index_factory_make(). The index is assigned to a
  * specific element, a bin or the whole pipeline. This will cause indexable
- * elements to add entires to the index while playing.
+ * elements to add entries to the index while playing.
  */
 
 /* FIXME: complete gobject annotations */
@@ -61,9 +61,7 @@
 #endif
 
 #include <gst/gst.h>
-#ifdef TIZEN_FEATURE_UPSTREAM
 #include "gst/glib-compat-private.h"
-#endif /* TIZEN_FEATURE_UPSTREAM */
 
 /* Index signals and args */
 enum
@@ -164,7 +162,7 @@ gst_index_class_init (GstIndexClass * klass)
   gst_index_signals[ENTRY_ADDED] =
       g_signal_new ("entry-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstIndexClass, entry_added), NULL, NULL,
-      g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_INDEX_ENTRY);
+      NULL, G_TYPE_NONE, 1, GST_TYPE_INDEX_ENTRY);
 
   gobject_class->set_property = gst_index_set_property;
   gobject_class->get_property = gst_index_get_property;
@@ -801,11 +799,7 @@ gst_index_add_associationv (GstIndex * index, gint id,
   entry->type = GST_INDEX_ENTRY_ASSOCIATION;
   entry->id = id;
   entry->data.assoc.flags = flags;
-#ifdef TIZEN_FEATURE_UPSTREAM
   entry->data.assoc.assocs = g_memdup2 (list, sizeof (GstIndexAssociation) * n);
-#else /* TIZEN_FEATURE_UPSTREAM */
-  entry->data.assoc.assocs = g_memdup (list, sizeof (GstIndexAssociation) * n);
-#endif /* TIZEN_FEATURE_UPSTREAM */
   entry->data.assoc.nassocs = n;
 
   gst_index_add_entry (index, entry);
index 89e6776..7dd53b6 100644 (file)
@@ -85,9 +85,7 @@ struct _GstPushSrcClass {
 GST_BASE_API
 GType gst_push_src_get_type (void);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPushSrc, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 4d0c4e9..d289376 100644 (file)
@@ -51,9 +51,17 @@ gst_base = library('gstbase-@0@'.format(apiversion),
   dependencies : [gobject_dep, glib_dep, gst_dep],
 )
 
+pkgconfig.generate(gst_base,
+  libraries : [libgst],
+  variables : pkgconfig_variables,
+  subdirs : pkgconfig_subdirs,
+  name : 'gstreamer-base-1.0',
+  description : 'Base classes for GStreamer elements',
+)
+
 if build_gir
   gst_gir_extra_args = gir_init_section + [ '--c-include=gst/base/base.h' ]
-  gst_base_gen_sources += [gnome.generate_gir(gst_base,
+  gst_base_gir = gnome.generate_gir(gst_base,
     sources : gst_base_sources + gst_base_headers,
     namespace : 'GstBase',
     nsversion : apiversion,
@@ -65,7 +73,9 @@ if build_gir
     includes : ['GLib-2.0', 'GObject-2.0', 'GModule-2.0', 'Gst-1.0'],
     install : true,
     extra_args : gst_gir_extra_args,
-  )]
+  )
+
+  gst_base_gen_sources += [gst_base_gir]
 endif
 
 gst_base_dep = declare_dependency(link_with : gst_base,
@@ -73,6 +83,8 @@ gst_base_dep = declare_dependency(link_with : gst_base,
   dependencies : [gst_dep],
   sources : gst_base_gen_sources)
 
+meson.override_dependency('gstreamer-base-1.0', gst_base_dep)
+
 install_headers('base.h',
   'base-prelude.h',
   'gstadapter.h',
diff --git a/libs/gst/check/.gitignore b/libs/gst/check/.gitignore
deleted file mode 100644 (file)
index b887a81..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-*.c.gcov.out
-*.c.gcov.out
-*.o
-*.lo
-*.la
-internal-check.h
-exports.sym
-libcheck/check.h
diff --git a/libs/gst/check/Makefile.am b/libs/gst/check/Makefile.am
deleted file mode 100644 (file)
index 335f5ad..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-lib_LTLIBRARIES = libgstcheck-@GST_API_VERSION@.la
-
-SYMBOLS_FILE = exports.sym
-
-libgstcheck_@GST_API_VERSION@_la_DEPENDENCIES = \
-       $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la \
-       $(SYMBOLS_FILE)
-libgstcheck_@GST_API_VERSION@_la_SOURCES =     \
-       gstbufferstraw.c                        \
-       gstcheck.c                              \
-       gstconsistencychecker.c                 \
-       gstharness.c                            \
-       gsttestclock.c
-
-libgstcheck_@GST_API_VERSION@_la_CFLAGS = $(GST_OBJ_CFLAGS) \
-       -UG_DISABLE_ASSERT \
-       -DBUILDING_GST_CHECK \
-       -I$(top_builddir)/libs \
-       -I$(top_builddir)/libs/gst/check \
-       -I$(top_builddir)/libs/gst/check/libcheck
-libgstcheck_@GST_API_VERSION@_la_LIBADD = $(GST_OBJ_LIBS) \
-       $(top_builddir)/libs/gst/check/libcheck/libcheckinternal.la \
-       $(LIBM)
-libgstcheck_@GST_API_VERSION@_la_LDFLAGS = \
-       -export-symbols $(SYMBOLS_FILE) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
-
-libgstcheck_@GST_API_VERSION@includedir =              \
-       $(includedir)/gstreamer-@GST_API_VERSION@/gst/check
-
-libgstcheck_@GST_API_VERSION@include_HEADERS = \
-       check.h                                 \
-       check-prelude.h                         \
-       gstbufferstraw.h                        \
-       gstcheck.h                              \
-       gstconsistencychecker.h                 \
-       gstharness.h                            \
-       gsttestclock.h
-
-nodist_libgstcheck_@GST_API_VERSION@include_HEADERS =  \
-       internal-check.h
-
-CLEANFILES = *.gcno *.gcda *.gcov $(SYMBOLS_FILE)
-
-%.c.gcov: .libs/libgstcheck_@GST_API_VERSION@_la-%.gcda %.c
-       $(GCOV) -b -f -o $^ > $@.out
-
-gcov: $(libgstcheck_@GST_API_VERSION@_la_SOURCES:=.gcov)
-
-SUBDIRS = libcheck
-
-LIBGSTCHECK_EXPORTED_VARS = \
-       _gst_check_threads_running \
-       _gst_check_raised_critical \
-       _gst_check_raised_warning \
-       _gst_check_expecting_log \
-       _gst_check_list_tests \
-       buffers \
-       check_cond \
-       check_debug \
-       check_mutex \
-       mutex \
-       start_cond \
-       sync_cond \
-       thread_list
-
-LIBGSTCHECK_EXPORTED_FUNCS = \
-       _gst_check_run_test_func \
-       gst_buffer_straw_get_buffer \
-       gst_buffer_straw_start_pipeline \
-       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 \
-       gst_check_element_push_buffer_list \
-       gst_check_init \
-       gst_check_add_log_filter \
-       gst_check_remove_log_filter \
-       gst_check_clear_log_filter \
-       gst_check_message_error \
-       gst_check_run_suite \
-       gst_check_setup_element \
-       gst_check_setup_events \
-       gst_check_setup_events_with_stream_id \
-       gst_check_setup_sink_pad \
-       gst_check_setup_sink_pad_from_template \
-       gst_check_setup_sink_pad_by_name \
-       gst_check_setup_sink_pad_by_name_from_template \
-       gst_check_setup_src_pad \
-       gst_check_setup_src_pad_from_template \
-       gst_check_setup_src_pad_by_name \
-       gst_check_setup_src_pad_by_name_from_template \
-       gst_check_teardown_element \
-       gst_check_teardown_pad_by_name \
-       gst_check_teardown_sink_pad \
-       gst_check_teardown_src_pad \
-       gst_check_objects_destroyed_on_unref \
-       gst_check_object_destroyed_on_unref \
-       gst_consistency_checker_add_pad \
-       gst_consistency_checker_new \
-       gst_consistency_checker_reset \
-       gst_consistency_checker_free \
-       gst_harness_add_element_full \
-       gst_harness_add_element_src_pad \
-       gst_harness_add_element_sink_pad \
-       gst_harness_add_parse \
-       gst_harness_add_probe \
-       gst_harness_add_propose_allocation_meta \
-       gst_harness_add_sink \
-       gst_harness_add_sink_harness \
-       gst_harness_add_sink_parse \
-       gst_harness_add_src \
-       gst_harness_add_src_harness \
-       gst_harness_add_src_parse \
-       gst_harness_buffers_in_queue \
-       gst_harness_buffers_received \
-       gst_harness_crank_multiple_clock_waits \
-       gst_harness_crank_single_clock_wait \
-       gst_harness_create_buffer \
-       gst_harness_dump_to_file \
-       gst_harness_events_in_queue \
-       gst_harness_events_received \
-       gst_harness_find_element \
-       gst_harness_get \
-       gst_harness_get_allocator \
-       gst_harness_get_last_pushed_timestamp \
-       gst_harness_get_testclock \
-       gst_harness_new \
-       gst_harness_new_empty \
-       gst_harness_new_full \
-       gst_harness_new_parse \
-       gst_harness_new_with_element \
-       gst_harness_new_with_padnames \
-       gst_harness_new_with_templates \
-       gst_harness_play \
-       gst_harness_pull \
-       gst_harness_pull_event \
-       gst_harness_pull_upstream_event \
-       gst_harness_push \
-       gst_harness_push_and_pull \
-       gst_harness_push_event \
-       gst_harness_push_from_src \
-       gst_harness_push_to_sink \
-       gst_harness_query_latency \
-       gst_harness_push_upstream_event \
-       gst_harness_set \
-       gst_harness_set_caps \
-       gst_harness_set_caps_str \
-       gst_harness_set_drop_buffers \
-       gst_harness_set_blocking_push_mode \
-       gst_harness_set_forwarding \
-       gst_harness_set_propose_allocator \
-       gst_harness_set_sink_caps \
-       gst_harness_set_src_caps \
-       gst_harness_set_src_caps_str \
-       gst_harness_set_sink_caps_str \
-       gst_harness_set_time \
-       gst_harness_set_upstream_latency \
-       gst_harness_sink_push_many \
-       gst_harness_src_crank_and_push_many \
-       gst_harness_src_push_event \
-       gst_harness_stress_custom_start \
-       gst_harness_stress_property_start_full \
-       gst_harness_stress_push_buffer_start_full \
-       gst_harness_stress_push_buffer_with_cb_start_full \
-       gst_harness_stress_push_event_start_full \
-       gst_harness_stress_push_event_with_cb_start_full \
-       gst_harness_stress_push_upstream_event_start_full \
-       gst_harness_stress_push_upstream_event_with_cb_start_full \
-       gst_harness_stress_requestpad_start_full \
-       gst_harness_stress_statechange_start_full \
-       gst_harness_stress_thread_stop \
-       gst_harness_take_all_data \
-       gst_harness_take_all_data_as_buffer \
-       gst_harness_take_all_data_as_bytes \
-       gst_harness_teardown \
-       gst_harness_try_pull \
-       gst_harness_try_pull_event \
-       gst_harness_try_pull_upstream_event \
-       gst_harness_upstream_events_in_queue \
-       gst_harness_upstream_events_received \
-       gst_harness_use_systemclock \
-       gst_harness_use_testclock \
-       gst_harness_wait_for_clock_id_waits \
-       gst_test_clock_advance_time \
-       gst_test_clock_crank \
-       gst_test_clock_get_next_entry_time \
-       gst_test_clock_get_type \
-       gst_test_clock_has_id \
-       gst_test_clock_id_list_get_latest_time \
-       gst_test_clock_new \
-       gst_test_clock_new_with_start_time \
-       gst_test_clock_peek_id_count \
-       gst_test_clock_peek_next_pending_id \
-       gst_test_clock_process_id_list \
-       gst_test_clock_process_next_clock_id \
-       gst_test_clock_set_time \
-       gst_test_clock_wait_for_multiple_pending_ids \
-       gst_test_clock_wait_for_next_pending_id \
-       gst_test_clock_wait_for_pending_id_count
-
-# For backwards compatibility with GStreamer < 1.5
-LIBGSTCHECK_EXPORTED_COMPAT_FUNCS = \
-       _fail_unless
-
-LIBGSTCHECK_EXPORTED_SYMBOLS = \
-       $(LIBGSTCHECK_EXPORTED_VARS) \
-       $(LIBGSTCHECK_EXPORTED_FUNCS) \
-       $(LIBGSTCHECK_EXPORTED_COMPAT_FUNCS)
-
-# Please do not even think about changing the alphabet below into A-Za-z.
-# It is there for purpose. (Bug #602093)
-CHECK_SYMS=`$(SED) -n -e 's/^..*CK_EXPORT[ ]\{1,\}\([_0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]\{1,\}\)..*$$/\1/p' @top_srcdir@/libs/gst/check/libcheck/check.h.in`
-print-check-symbols:
-       @for s in $(CHECK_SYMS); do \
-         echo $$s; \
-       done;
-
-$(SYMBOLS_FILE): $(libgstcheck_@GST_API_VERSION@include_HEADERS) internal-check.h
-       $(AM_V_GEN)rm -f $(SYMBOLS_FILE) 2>/dev/null; \
-       for s in $(LIBGSTCHECK_EXPORTED_SYMBOLS) $(CHECK_SYMS); do \
-         echo $$s >> $(SYMBOLS_FILE); \
-       done
-
-if HAVE_INTROSPECTION
-BUILT_GIRSOURCES = GstCheck-@GST_API_VERSION@.gir
-
-gir_headers=$(patsubst %,$(srcdir)/%, $(libgstcheck_@GST_API_VERSION@include_HEADERS))
-gir_sources=$(patsubst %,$(srcdir)/%, $(libgstcheck_@GST_API_VERSION@_la_SOURCES))
-
-GstCheck-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstcheck-@GST_API_VERSION@.la
-       $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" GI_SCANNER_DISABLE_CACHE=yes\
-               GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_DISABLE=yes \
-               CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" PKG_CONFIG="$(PKG_CONFIG)" DLLTOOL="$(DLLTOOL)" \
-               $(INTROSPECTION_SCANNER) -v --namespace GstCheck \
-               --nsversion=@GST_API_VERSION@ \
-               --identifier-prefix=Gst \
-               --symbol-prefix=gst \
-               --warn-all \
-               -I$(top_srcdir) \
-               -I$(top_srcdir)/libs \
-               -I$(top_builddir) \
-               -I$(top_builddir)/libs \
-               --c-include "gst/check/check.h" \
-               --add-include-path=$(top_builddir)/gst \
-               --library-path=$(top_builddir)/gst \
-               --library=libgstcheck-@GST_API_VERSION@.la \
-               --include=Gst-@GST_API_VERSION@ \
-               --libtool="${LIBTOOL}" \
-               --pkg gstreamer-@GST_API_VERSION@ \
-               --pkg-export gstreamer-check-@GST_API_VERSION@ \
-               --add-init-section="$(INTROSPECTION_INIT)" \
-               --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
index 9b2227a..68b4cd3 100644 (file)
@@ -434,6 +434,12 @@ gst_check_message_error (GstMessage * message, GstMessageType type,
 }
 
 /* helper functions */
+/**
+ * gst_check_chain_func:
+ *
+ * A fake chain function that appends the buffer to the internal list of
+ * buffers.
+ */
 GstFlowReturn
 gst_check_chain_func (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
@@ -590,14 +596,12 @@ gst_check_setup_src_pad_by_name_from_template (GstElement * element,
 
   sinkpad = gst_element_get_static_pad (element, name);
   if (sinkpad == NULL)
-    sinkpad = gst_element_get_request_pad (element, name);
+    sinkpad = gst_element_request_pad_simple (element, name);
   fail_if (sinkpad == NULL, "Could not get sink pad from %s",
       GST_ELEMENT_NAME (element));
-  ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2);
   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK,
       "Could not link source and %s sink pads", GST_ELEMENT_NAME (element));
   gst_object_unref (sinkpad);   /* because we got it higher up */
-  ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 1);
 
   return srcpad;
 }
@@ -622,14 +626,9 @@ gst_check_teardown_pad_by_name (GstElement * element, const gchar * name)
       gst_pad_unlink (pad_element, pad_peer);
   }
 
-  /* pad refs held by both creator and this function (through _get) */
-  ASSERT_OBJECT_REFCOUNT (pad_element, "element pad_element", 2);
   gst_object_unref (pad_element);
-  /* one more ref is held by element itself */
 
   if (pad_peer) {
-    /* pad refs held by both creator and this function (through _get_peer) */
-    ASSERT_OBJECT_REFCOUNT (pad_peer, "check pad_peer", 2);
     gst_object_unref (pad_peer);
     gst_object_unref (pad_peer);
   }
@@ -722,7 +721,7 @@ gst_check_setup_sink_pad_by_name_from_template (GstElement * element,
 
   srcpad = gst_element_get_static_pad (element, name);
   if (srcpad == NULL)
-    srcpad = gst_element_get_request_pad (element, name);
+    srcpad = gst_element_request_pad_simple (element, name);
   fail_if (srcpad == NULL, "Could not get source pad from %s",
       GST_ELEMENT_NAME (element));
   gst_pad_set_chain_function (sinkpad, gst_check_chain_func);
@@ -731,9 +730,8 @@ gst_check_setup_sink_pad_by_name_from_template (GstElement * element,
   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK,
       "Could not link %s source and sink pads", GST_ELEMENT_NAME (element));
   gst_object_unref (srcpad);    /* because we got it higher up */
-  ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1);
 
-  GST_DEBUG_OBJECT (element, "set up srcpad, refcount is 1");
+  GST_DEBUG_OBJECT (element, "set up srcpad");
   return sinkpad;
 }
 
@@ -795,6 +793,10 @@ gst_check_buffer_data (GstBuffer * buffer, gconstpointer data, gsize size)
   fail_unless (gst_buffer_map (buffer, &info, GST_MAP_READ));
   GST_MEMDUMP ("Converted data", info.data, info.size);
   GST_MEMDUMP ("Expected data", data, size);
+  if (info.size != size) {
+    fail ("buffer sizes not equal: expected %" G_GSIZE_FORMAT " got %"
+        G_GSIZE_FORMAT, size, info.size);
+  }
   if (memcmp (info.data, data, size) != 0) {
     g_print ("\nConverted data:\n");
     gst_util_dump_mem (info.data, info.size);
@@ -1001,6 +1003,15 @@ gst_check_element_push_buffer (const gchar * element_name,
       GST_FLOW_OK);
 }
 
+/**
+ * gst_check_abi_list:
+ * @list: A list of GstCheckABIStruct to be verified
+ * @have_abi_sizes: Whether there is a reference ABI size already specified,
+ * if it is %FALSE and the `GST_ABI` environment variable is set, usable code
+ * for @list will be printed.
+ *
+ * Verifies that reference values and current values are equals in @list.
+ */
 void
 gst_check_abi_list (GstCheckABIStruct list[], gboolean have_abi_sizes)
 {
@@ -1079,6 +1090,7 @@ gst_check_run_suite (Suite * suite, const gchar * name, const gchar * fname)
   g_timer_destroy (timer);
   g_free (xmlfilename);
   srunner_free (sr);
+  g_thread_pool_stop_unused_threads ();
   return nf;
 }
 
@@ -1202,7 +1214,7 @@ weak_notify (DestroyedObjectStruct * destroyed, GObject ** object)
  *
  * Unrefs @object_to_unref and checks that is has properly been
  * destroyed, also checks that the other objects passed in
- * parametter have been destroyed as a concequence of
+ * parameter have been destroyed as a concequence of
  * unrefing @object_to_unref. Last variable argument should be NULL.
  *
  * Since: 1.6
index f59f400..b7ec2c4 100644 (file)
@@ -57,6 +57,12 @@ GST_CHECK_API GList * buffers;
 GST_CHECK_API GMutex check_mutex;
 GST_CHECK_API GCond check_cond;
 
+/**
+ * GstCheckABIStruct:
+ * @name: The name of the structure
+ * @size: The current size of a structure
+ * @abi_size: The reference size of the structure
+ */
 typedef struct
 {
   const char *name;
@@ -65,6 +71,12 @@ typedef struct
 }
 GstCheckABIStruct;
 
+/**
+ * GstCheckLogFilter:
+ *
+ * Opaque structure containing data about a log filter
+ * function.
+ */
 typedef struct _GstCheckLogFilter GstCheckLogFilter;
 
 /**
@@ -194,6 +206,8 @@ void gst_check_objects_destroyed_on_unref (gpointer object_to_unref, gpointer fi
 GST_CHECK_API
 void gst_check_object_destroyed_on_unref (gpointer object_to_unref);
 
+#ifndef __GI_SCANNER__
+
 #define fail_unless_message_error(msg, domain, code)            \
 gst_check_message_error (msg, GST_MESSAGE_ERROR,                \
   GST_ ## domain ## _ERROR, GST_ ## domain ## _ERROR_ ## code)
@@ -416,7 +430,7 @@ G_STMT_START {                                                              \
  * @a: a string literal or expression
  * @b: a string literal or expression
  *
- * This macro checks that @a and @b are equal (as per strcmp) and aborts if
+ * This macro checks that @a and @b are equal (as per g_strcmp0()) and aborts if
  * this is not the case, printing both expressions and the values they
  * evaluated to. This macro is for use in unit tests.
  */
@@ -432,7 +446,7 @@ G_STMT_START {                                                      \
  * @a: a string literal or expression
  * @b: a string literal or expression
  *
- * This macro checks that @a and @b are equal (as per strcmp) and aborts if
+ * This macro checks that @a and @b are equal (as per g_strcmp0()) and aborts if
  * this is not the case, printing both expressions and the values they
  * evaluated to. This macro is for use in unit tests.
  */
@@ -610,8 +624,7 @@ G_STMT_START {                                                  \
 
 #define THREAD_SWITCH()                                         \
 G_STMT_START {                                                  \
-  /* a minimal sleep is a context switch */                     \
-  g_usleep (1);                                                 \
+  g_thread_yield ();                                            \
 } G_STMT_END;
 
 #define THREAD_TEST_RUNNING()   (!!_gst_check_threads_running)
@@ -736,6 +749,8 @@ G_STMT_START {                                                  \
 #define tcase_skip_broken_loop_test(chain,test_func,a,b)        \
   tcase_skip_broken_test (chain, test_func)
 
+#endif /* !__GI_SCANNER__ */
+
 G_END_DECLS
 
 #endif /* __GST_CHECK_H__ */
index aff1875..08f720e 100644 (file)
 struct _GstStreamConsistency
 {
   /* FIXME: do we want to track some states per pad? */
-  volatile gboolean flushing;
-  volatile gboolean segment;
-  volatile gboolean eos;
-  volatile gboolean expect_flush;
-  volatile gboolean saw_serialized_event;
-  volatile gboolean saw_stream_start;
+  gboolean flushing;
+  gboolean segment;
+  gboolean eos;
+  gboolean expect_flush;
+  gboolean saw_serialized_event;
+  gboolean saw_stream_start;
   GstObject *parent;
   GList *pads;
 };
index b276100..fc1ab0d 100644 (file)
@@ -172,9 +172,9 @@ struct _GstHarnessPrivate
   GstPad *sink_forward_pad;
   GstTestClock *testclock;
 
-  volatile gint recv_buffers;
-  volatile gint recv_events;
-  volatile gint recv_upstream_events;
+  gint recv_buffers;
+  gint recv_events;
+  gint recv_upstream_events;
 
   GAsyncQueue *buffer_queue;
   GAsyncQueue *src_event_queue;
@@ -182,6 +182,8 @@ struct _GstHarnessPrivate
 
   GstClockTime latency_min;
   GstClockTime latency_max;
+  gboolean is_live;
+
   gboolean has_clock_wait;
   gboolean drop_buffers;
   GstClockTime last_push_ts;
@@ -199,6 +201,10 @@ struct _GstHarnessPrivate
   GMutex blocking_push_mutex;
   GMutex priv_mutex;
 
+  GCond buf_or_eos_cond;
+  GMutex buf_or_eos_mutex;
+  gboolean eos_received;
+
   GPtrArray *stress;
 };
 
@@ -212,10 +218,15 @@ gst_harness_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
   g_mutex_lock (&priv->blocking_push_mutex);
   g_atomic_int_inc (&priv->recv_buffers);
 
-  if (priv->drop_buffers)
+  if (priv->drop_buffers) {
     gst_buffer_unref (buffer);
-  else
+  } else {
+    g_mutex_lock (&priv->buf_or_eos_mutex);
     g_async_queue_push (priv->buffer_queue, buffer);
+    g_cond_signal (&priv->buf_or_eos_cond);
+    g_mutex_unlock (&priv->buf_or_eos_mutex);
+  }
+
 
   if (priv->blocking_push_mode) {
     g_cond_wait (&priv->blocking_push_cond, &priv->blocking_push_mutex);
@@ -268,6 +279,12 @@ gst_harness_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
     gst_object_unref (fwdpad);
     HARNESS_LOCK (h);
   } else {
+    if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
+      g_mutex_lock (&priv->buf_or_eos_mutex);
+      priv->eos_received = TRUE;
+      g_cond_signal (&priv->buf_or_eos_cond);
+      g_mutex_unlock (&priv->buf_or_eos_mutex);
+    }
     g_async_queue_push (priv->sink_event_queue, event);
   }
   HARNESS_UNLOCK (h);
@@ -344,7 +361,8 @@ gst_harness_negotiate (GstHarness * h)
     gst_harness_decide_allocation (h, caps);
     gst_caps_unref (caps);
   } else {
-    GST_FIXME_OBJECT (h, "Cannot negotiate allocation because caps is not set");
+    GST_FIXME_OBJECT (h->srcpad,
+        "Cannot negotiate allocation because caps is not set");
   }
 }
 
@@ -360,7 +378,8 @@ gst_harness_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_LATENCY:
-      gst_query_set_latency (query, TRUE, priv->latency_min, priv->latency_max);
+      gst_query_set_latency (query, priv->is_live, priv->latency_min,
+          priv->latency_max);
       break;
     case GST_QUERY_CAPS:
     {
@@ -420,6 +439,19 @@ gst_harness_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
       HARNESS_UNLOCK (h);
       break;
     }
+    case GST_QUERY_CONTEXT:
+      HARNESS_LOCK (h);
+      if (priv->forwarding && priv->sink_forward_pad != NULL) {
+        GstPad *peer = gst_pad_get_peer (priv->sink_forward_pad);
+        g_assert (peer != NULL);
+        HARNESS_UNLOCK (h);
+        res = gst_pad_query (peer, query);
+        gst_object_unref (peer);
+      } else {
+        HARNESS_UNLOCK (h);
+        res = gst_pad_query_default (pad, parent, query);
+      }
+      break;
     default:
       res = gst_pad_query_default (pad, parent, query);
   }
@@ -437,7 +469,8 @@ gst_harness_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_LATENCY:
-      gst_query_set_latency (query, TRUE, priv->latency_min, priv->latency_max);
+      gst_query_set_latency (query, priv->is_live, priv->latency_min,
+          priv->latency_max);
       break;
     case GST_QUERY_CAPS:
     {
@@ -507,7 +540,7 @@ gst_harness_link_element_srcpad (GstHarness * h,
       element_srcpad_name);
   GstPadLinkReturn link;
   if (srcpad == NULL)
-    srcpad = gst_element_get_request_pad (h->element, element_srcpad_name);
+    srcpad = gst_element_request_pad_simple (h->element, element_srcpad_name);
   g_assert (srcpad);
   link = gst_pad_link (srcpad, h->sinkpad);
   g_assert_cmpint (link, ==, GST_PAD_LINK_OK);
@@ -526,7 +559,7 @@ gst_harness_link_element_sinkpad (GstHarness * h,
       element_sinkpad_name);
   GstPadLinkReturn link;
   if (sinkpad == NULL)
-    sinkpad = gst_element_get_request_pad (h->element, element_sinkpad_name);
+    sinkpad = gst_element_request_pad_simple (h->element, element_sinkpad_name);
   g_assert (sinkpad);
   link = gst_pad_link (h->srcpad, sinkpad);
   g_assert_cmpint (link, ==, GST_PAD_LINK_OK);
@@ -540,13 +573,9 @@ static void
 gst_harness_setup_src_pad (GstHarness * h,
     GstStaticPadTemplate * src_tmpl, const gchar * element_sinkpad_name)
 {
-  GstHarnessPrivate *priv = h->priv;
   g_assert (src_tmpl);
   g_assert (h->srcpad == NULL);
 
-  priv->src_event_queue =
-      g_async_queue_new_full ((GDestroyNotify) gst_event_unref);
-
   /* sending pad */
   h->srcpad = gst_pad_new_from_static_template (src_tmpl, "src");
   g_assert (h->srcpad);
@@ -565,15 +594,9 @@ static void
 gst_harness_setup_sink_pad (GstHarness * h,
     GstStaticPadTemplate * sink_tmpl, const gchar * element_srcpad_name)
 {
-  GstHarnessPrivate *priv = h->priv;
   g_assert (sink_tmpl);
   g_assert (h->sinkpad == NULL);
 
-  priv->buffer_queue = g_async_queue_new_full (
-      (GDestroyNotify) gst_buffer_unref);
-  priv->sink_event_queue = g_async_queue_new_full (
-      (GDestroyNotify) gst_event_unref);
-
   /* receiving pad */
   h->sinkpad = gst_pad_new_from_static_template (sink_tmpl, "sink");
   g_assert (h->sinkpad);
@@ -661,13 +684,21 @@ gst_harness_new_empty (void)
   h->priv = g_new0 (GstHarnessPrivate, 1);
   priv = h->priv;
 
-  GST_DEBUG_OBJECT (h, "about to create new harness %p", h);
+  GST_DEBUG ("about to create new harness %p", h);
   priv->last_push_ts = GST_CLOCK_TIME_NONE;
   priv->latency_min = 0;
   priv->latency_max = GST_CLOCK_TIME_NONE;
+  priv->is_live = TRUE;
   priv->drop_buffers = FALSE;
   priv->testclock = GST_TEST_CLOCK_CAST (gst_test_clock_new ());
 
+  priv->buffer_queue = g_async_queue_new_full (
+      (GDestroyNotify) gst_buffer_unref);
+  priv->src_event_queue = g_async_queue_new_full (
+      (GDestroyNotify) gst_event_unref);
+  priv->sink_event_queue = g_async_queue_new_full (
+      (GDestroyNotify) gst_event_unref);
+
   priv->propose_allocator = NULL;
   gst_allocation_params_init (&priv->propose_allocation_params);
 
@@ -675,6 +706,10 @@ gst_harness_new_empty (void)
   g_cond_init (&priv->blocking_push_cond);
   g_mutex_init (&priv->priv_mutex);
 
+  g_mutex_init (&priv->buf_or_eos_mutex);
+  g_cond_init (&priv->buf_or_eos_cond);
+  priv->eos_received = FALSE;
+
   priv->stress = g_ptr_array_new_with_free_func (
       (GDestroyNotify) gst_harness_stress_free);
 
@@ -760,7 +795,7 @@ gst_harness_add_element_full (GstHarness * h, GstElement * element,
 
   gst_harness_element_ref (h);
 
-  GST_DEBUG_OBJECT (h, "added element to harness %p "
+  GST_DEBUG ("added element to harness %p "
       "with element_srcpad_name (%p, %s, %s) and element_sinkpad_name (%p, %s, %s)",
       h, h->srcpad, GST_DEBUG_PAD_NAME (h->srcpad),
       h->sinkpad, GST_DEBUG_PAD_NAME (h->sinkpad));
@@ -1034,20 +1069,17 @@ gst_harness_teardown (GstHarness * h)
     g_mutex_unlock (&priv->blocking_push_mutex);
   }
 
-  if (h->src_harness) {
+  if (h->src_harness)
     gst_harness_teardown (h->src_harness);
-  }
+  h->src_harness = NULL;
 
+  HARNESS_LOCK (h);
   gst_object_replace ((GstObject **) & priv->sink_forward_pad, NULL);
-  if (h->sink_harness) {
-    gst_harness_teardown (h->sink_harness);
-  }
-
-  if (priv->src_caps)
-    gst_caps_unref (priv->src_caps);
+  HARNESS_UNLOCK (h);
 
-  if (priv->sink_caps)
-    gst_caps_unref (priv->sink_caps);
+  if (h->sink_harness)
+    gst_harness_teardown (h->sink_harness);
+  h->sink_harness = NULL;
 
   if (h->srcpad) {
     if (gst_pad_is_request_pad (GST_PAD_PEER (h->srcpad)))
@@ -1055,10 +1087,17 @@ gst_harness_teardown (GstHarness * h)
     g_free (priv->element_sinkpad_name);
 
     gst_pad_set_active (h->srcpad, FALSE);
-    gst_object_unref (h->srcpad);
 
-    g_async_queue_unref (priv->src_event_queue);
+    /* Make sure our funcs are not called after harness is teared down since
+     * they try to access this harness through pad data */
+    GST_PAD_STREAM_LOCK (h->srcpad);
+    gst_pad_set_event_function (h->srcpad, NULL);
+    gst_pad_set_query_function (h->srcpad, NULL);
+    GST_PAD_STREAM_UNLOCK (h->srcpad);
+
+    gst_object_unref (h->srcpad);
   }
+  h->srcpad = NULL;
 
   if (h->sinkpad) {
     if (gst_pad_is_request_pad (GST_PAD_PEER (h->sinkpad)))
@@ -1066,11 +1105,26 @@ gst_harness_teardown (GstHarness * h)
     g_free (priv->element_srcpad_name);
 
     gst_pad_set_active (h->sinkpad, FALSE);
-    gst_object_unref (h->sinkpad);
 
-    g_async_queue_unref (priv->buffer_queue);
-    g_async_queue_unref (priv->sink_event_queue);
+    /* Make sure our funcs are not called after harness is teared down since
+     * they try to access this harness through pad data */
+    GST_PAD_STREAM_LOCK (h->sinkpad);
+    gst_pad_set_chain_function (h->sinkpad, NULL);
+    gst_pad_set_event_function (h->sinkpad, NULL);
+    gst_pad_set_query_function (h->sinkpad, NULL);
+    GST_PAD_STREAM_UNLOCK (h->sinkpad);
+
+    gst_object_unref (h->sinkpad);
   }
+  h->sinkpad = NULL;
+
+  if (priv->src_caps)
+    gst_caps_unref (priv->src_caps);
+  priv->src_caps = NULL;
+
+  if (priv->sink_caps)
+    gst_caps_unref (priv->sink_caps);
+  priv->sink_caps = NULL;
 
   gst_object_replace ((GstObject **) & priv->propose_allocator, NULL);
   gst_object_replace ((GstObject **) & priv->allocator, NULL);
@@ -1078,9 +1132,10 @@ gst_harness_teardown (GstHarness * h)
 
   if (priv->propose_allocation_metas)
     g_array_unref (priv->propose_allocation_metas);
+  priv->propose_allocation_metas = NULL;
 
   /* if we hold the last ref, set to NULL */
-  if (gst_harness_element_unref (h) == 0) {
+  if (h->element != NULL && gst_harness_element_unref (h) == 0) {
     gboolean state_change;
     GstState state, pending;
     state_change = gst_element_set_state (h->element, GST_STATE_NULL);
@@ -1094,13 +1149,29 @@ gst_harness_teardown (GstHarness * h)
   g_mutex_clear (&priv->blocking_push_mutex);
   g_mutex_clear (&priv->priv_mutex);
 
+  g_mutex_clear (&priv->buf_or_eos_mutex);
+  g_cond_clear (&priv->buf_or_eos_cond);
+  priv->eos_received = FALSE;
+
+  g_async_queue_unref (priv->buffer_queue);
+  priv->buffer_queue = NULL;
+  g_async_queue_unref (priv->src_event_queue);
+  priv->src_event_queue = NULL;
+  g_async_queue_unref (priv->sink_event_queue);
+  priv->sink_event_queue = NULL;
+
   g_ptr_array_unref (priv->stress);
+  priv->stress = NULL;
 
-  gst_object_unref (h->element);
+  if (h->element) {
+    gst_object_unref (h->element);
+    h->element = NULL;
+  }
 
   gst_object_replace ((GstObject **) & priv->testclock, NULL);
 
   g_free (h->priv);
+  h->priv = NULL;
   g_free (h);
 }
 
@@ -1517,13 +1588,14 @@ gst_harness_set_forwarding (GstHarness * h, gboolean forwarding)
     gst_harness_set_forwarding (h->sink_harness, forwarding);
 }
 
+/*
+* Call with HARNESS_LOCK
+*/
 static void
 gst_harness_set_forward_pad (GstHarness * h, GstPad * fwdpad)
 {
-  HARNESS_LOCK (h);
   gst_object_replace ((GstObject **) & h->priv->sink_forward_pad,
       (GstObject *) fwdpad);
-  HARNESS_UNLOCK (h);
 }
 
 /**
@@ -1554,8 +1626,7 @@ gst_harness_create_buffer (GstHarness * h, gsize size)
     flow = gst_buffer_pool_acquire_buffer (priv->pool, &ret, NULL);
     g_assert_cmpint (flow, ==, GST_FLOW_OK);
     if (gst_buffer_get_size (ret) != size) {
-      GST_DEBUG_OBJECT (h,
-          "use fallback, pool is configured with a different size (%"
+      GST_DEBUG ("use fallback, pool is configured with a different size (%"
           G_GSIZE_FORMAT " != %" G_GSIZE_FORMAT ")",
           size, gst_buffer_get_size (ret));
       gst_buffer_unref (ret);
@@ -1626,6 +1697,40 @@ gst_harness_pull (GstHarness * h)
 }
 
 /**
+ * gst_harness_pull_until_eos:
+ * @h: a #GstHarness
+ * @buf: (out) (transfer full): A #GstBuffer, or %NULL if EOS or timeout occures
+ *   first.
+ *
+ * Pulls a #GstBuffer from the #GAsyncQueue on the #GstHarness sinkpad. The pull
+ * will block until an EOS event is received, or timeout in 60 seconds.
+ * MT safe.
+ *
+ * Returns: %TRUE on success, %FALSE on timeout.
+ *
+ * Since: 1.18
+ */
+gboolean
+gst_harness_pull_until_eos (GstHarness * h, GstBuffer ** buf)
+{
+  GstHarnessPrivate *priv = h->priv;
+  gboolean success = TRUE;
+  gint64 end_time = g_get_monotonic_time () + 60 * G_TIME_SPAN_SECOND;
+
+  g_mutex_lock (&priv->buf_or_eos_mutex);
+  while (success) {
+    *buf = g_async_queue_try_pop (priv->buffer_queue);
+    if (*buf || priv->eos_received)
+      break;
+    success = g_cond_wait_until (&priv->buf_or_eos_cond,
+        &priv->buf_or_eos_mutex, end_time);
+  }
+  g_mutex_unlock (&priv->buf_or_eos_mutex);
+
+  return success;
+}
+
+/**
  * gst_harness_try_pull:
  * @h: a #GstHarness
  *
@@ -2121,8 +2226,26 @@ gst_harness_query_latency (GstHarness * h)
 void
 gst_harness_set_upstream_latency (GstHarness * h, GstClockTime latency)
 {
+  g_return_if_fail (GST_CLOCK_TIME_IS_VALID (latency));
+
+  h->priv->latency_min = latency;
+}
+
+/**
+ * gst_harness_set_live:
+ * @h: a #GstHarness
+ * @is_live: %TRUE for live, %FALSE for non-live
+ *
+ * Sets the liveness reported by #GstHarness when receiving a latency-query.
+ * The default is %TRUE.
+ *
+ * Since: 1.20
+ */
+void
+gst_harness_set_live (GstHarness * h, gboolean is_live)
+{
   GstHarnessPrivate *priv = h->priv;
-  priv->latency_min = latency;
+  priv->is_live = is_live;
 }
 
 /**
@@ -2235,7 +2358,11 @@ gst_harness_add_src_harness (GstHarness * h,
   if (h->src_harness)
     gst_harness_teardown (h->src_harness);
   h->src_harness = src_harness;
+
+  HARNESS_LOCK (h->src_harness);
   gst_harness_set_forward_pad (h->src_harness, h->srcpad);
+  HARNESS_UNLOCK (h->src_harness);
+
   h->src_harness->priv->has_clock_wait = has_clock_wait;
   gst_harness_set_forwarding (h->src_harness, h->priv->forwarding);
 }
@@ -2396,8 +2523,8 @@ gst_harness_src_push_event (GstHarness * h)
 static gboolean
 forward_sticky_events (GstPad * pad, GstEvent ** ev, gpointer user_data)
 {
-  GstHarness *h = user_data;
-  return gst_pad_push_event (h->priv->sink_forward_pad, gst_event_ref (*ev));
+  GstPad *fwdpad = user_data;
+  return gst_pad_push_event (fwdpad, gst_event_ref (*ev));
 }
 
 /**
@@ -2421,17 +2548,35 @@ forward_sticky_events (GstPad * pad, GstEvent ** ev, gpointer user_data)
 void
 gst_harness_add_sink_harness (GstHarness * h, GstHarness * sink_harness)
 {
-  GstHarnessPrivate *priv = h->priv;
+  GstHarnessPrivate *priv;
+  GstPad *fwdpad;
+
+  HARNESS_LOCK (h);
+  priv = h->priv;
 
   if (h->sink_harness) {
     gst_harness_set_forward_pad (h, NULL);
     gst_harness_teardown (h->sink_harness);
   }
   h->sink_harness = sink_harness;
-  gst_harness_set_forward_pad (h, h->sink_harness->srcpad);
-  if (priv->forwarding && h->sinkpad)
-    gst_pad_sticky_events_foreach (h->sinkpad, forward_sticky_events, h);
+
+  fwdpad = h->sink_harness->srcpad;
+  if (fwdpad)
+    gst_object_ref (fwdpad);
+
+  if (priv->forwarding && h->sinkpad && fwdpad) {
+    HARNESS_UNLOCK (h);
+    gst_pad_sticky_events_foreach (h->sinkpad, forward_sticky_events, fwdpad);
+    HARNESS_LOCK (h);
+  }
+
+  gst_harness_set_forward_pad (h, fwdpad);
+  if (fwdpad)
+    gst_object_unref (fwdpad);
+
   gst_harness_set_forwarding (h->sink_harness, priv->forwarding);
+
+  HARNESS_UNLOCK (h);
 }
 
 /**
index 416d472..160fdb0 100644 (file)
@@ -189,6 +189,9 @@ GST_CHECK_API
 GstBuffer *    gst_harness_try_pull (GstHarness * h);
 
 GST_CHECK_API
+gboolean       gst_harness_pull_until_eos (GstHarness * h, GstBuffer ** buf);
+
+GST_CHECK_API
 GstBuffer *    gst_harness_push_and_pull (GstHarness * h, GstBuffer * buffer);
 
 GST_CHECK_API
@@ -257,6 +260,9 @@ GstClockTime gst_harness_query_latency (GstHarness * h);
 GST_CHECK_API
 void         gst_harness_set_upstream_latency (GstHarness * h, GstClockTime latency);
 
+GST_CHECK_API
+void         gst_harness_set_live (GstHarness * h, gboolean is_live);
+
 /* allocation query parameters */
 
 GST_CHECK_API
@@ -331,12 +337,12 @@ GstElement *  gst_harness_find_element (GstHarness * h,
 GST_CHECK_API
 void          gst_harness_set (GstHarness  * h,
                                const gchar * element_name,
-                               const gchar * first_property_name, ...);
+                               const gchar * first_property_name, ...) G_GNUC_NULL_TERMINATED;
 
 GST_CHECK_API
 void          gst_harness_get (GstHarness  * h,
                                const gchar * element_name,
-                               const gchar * first_property_name, ...);
+                               const gchar * first_property_name, ...) G_GNUC_NULL_TERMINATED;
 
 GST_CHECK_API
 void          gst_harness_add_probe (GstHarness        * h,
index e25893d..83aadc4 100644 (file)
@@ -923,7 +923,7 @@ gst_test_clock_wait_for_pending_id_count (GstTestClock * test_clock,
  *
  * MT safe.
  *
- * Returns: (transfer full): a #GstClockID containing the next pending clock
+ * Returns: (transfer full) (nullable): a #GstClockID containing the next pending clock
  * notification.
  *
  * Since: 1.2
@@ -1083,6 +1083,43 @@ gst_test_clock_timed_wait_for_multiple_pending_ids (GstTestClock * test_clock,
   return ret;
 }
 
+
+/**
+ * gst_test_clock_process_id:
+ * @test_clock: #GstTestClock for which to process the pending IDs
+ * @pending_id: (transfer full): #GstClockID
+ *
+ * Processes and releases the pending ID.
+ *
+ * MT safe.
+ *
+ * Since: 1.18
+ */
+gboolean
+gst_test_clock_process_id (GstTestClock * test_clock, GstClockID pending_id)
+{
+  GstClockEntryContext *ctx;
+
+  gboolean result = FALSE;
+
+  g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), FALSE);
+
+  GST_OBJECT_LOCK (test_clock);
+
+  ctx = gst_test_clock_lookup_entry_context (test_clock, pending_id);
+  g_assert (ctx);
+
+  if (ctx) {
+    process_entry_context_unlocked (test_clock, ctx);
+    result = TRUE;
+    gst_clock_id_unref (pending_id);
+  }
+
+  GST_OBJECT_UNLOCK (test_clock);
+
+  return result;
+}
+
 /**
  * gst_test_clock_process_id_list:
  * @test_clock: #GstTestClock for which to process the pending IDs
@@ -1153,7 +1190,8 @@ gst_test_clock_id_list_get_latest_time (const GList * pending_list)
  *
  * A "crank" consists of three steps:
  * 1: Wait for a #GstClockID to be registered with the #GstTestClock.
- * 2: Advance the #GstTestClock to the time the #GstClockID is waiting for.
+ * 2: Advance the #GstTestClock to the time the #GstClockID is waiting, unless
+ *    the clock time is already passed the clock id (Since: 1.18).
  * 3: Release the #GstClockID wait.
  * A "crank" can be though of as the notion of
  * manually driving the clock forward to its next logical step.
@@ -1168,10 +1206,13 @@ gboolean
 gst_test_clock_crank (GstTestClock * test_clock)
 {
   GstClockID res, pending;
+  GstClockTime now;
   gboolean result;
 
   gst_test_clock_wait_for_next_pending_id (test_clock, &pending);
-  gst_test_clock_set_time (test_clock, gst_clock_id_get_time (pending));
+  now = gst_clock_get_time (GST_CLOCK (test_clock));
+  if (gst_clock_id_get_time (pending) > now)
+    gst_test_clock_set_time (test_clock, gst_clock_id_get_time (pending));
   res = gst_test_clock_process_next_clock_id (test_clock);
   if (G_LIKELY (res == pending)) {
     GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
index 3016aea..a1c1f5a 100644 (file)
@@ -128,6 +128,10 @@ gboolean      gst_test_clock_timed_wait_for_multiple_pending_ids (GstTestClock *
                                                                   GList       ** pending_list);
 
 GST_CHECK_API
+gboolean      gst_test_clock_process_id (GstTestClock * test_clock,
+                                         GstClockID pending_id);
+
+GST_CHECK_API
 guint         gst_test_clock_process_id_list (GstTestClock * test_clock,
                                               const GList  * pending_list);
 
@@ -137,9 +141,7 @@ GstClockTime  gst_test_clock_id_list_get_latest_time (const GList * pending_list
 GST_CHECK_API
 gboolean      gst_test_clock_crank (GstTestClock * test_clock);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTestClock, gst_object_unref)
-#endif
 
 G_END_DECLS
 
diff --git a/libs/gst/check/libcheck/Makefile.am b/libs/gst/check/libcheck/Makefile.am
deleted file mode 100644 (file)
index 4b90803..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-noinst_LTLIBRARIES     = libcheckinternal.la
-
-EXTRA_DIST = check.h.in
-
-CFILES =\
-       check.c         \
-       check_error.c   \
-       check_list.c    \
-       check_log.c     \
-       check_msg.c     \
-       check_pack.c    \
-       check_print.c   \
-       check_run.c     \
-       check_str.c     \
-       libcompat/libcompat.c
-
-if !HAVE_ALARM
-CFILES += libcompat/alarm.c
-endif
-
-if !HAVE_CLOCK_GETTIME
-CFILES += libcompat/clock_gettime.c
-endif
-
-if !HAVE_GETTIMEOFDAY
-CFILES += libcompat/gettimeofday.c
-endif
-
-if !HAVE_LOCALTIME_R
-CFILES += libcompat/localtime_r.c
-endif
-
-if !HAVE_STRSIGNAL
-CFILES += libcompat/strsignal.c
-endif
-
-if !HAVE_STRDUP
-CFILES += libcompat/strdup.c
-endif
-
-if !HAVE_GETLINE
-CFILES += libcompat/getline.c
-endif
-
-if !HAVE_TIMER_CREATE_SETTIME_DELETE
-CFILES +=\
-       libcompat/timer_create.c        \
-       libcompat/timer_settime.c       \
-       libcompat/timer_delete.c
-endif
-
-HFILES =\
-       check_error.h   \
-       check_impl.h    \
-       check_list.h    \
-       check_log.h     \
-       check_msg.h     \
-       check_pack.h    \
-       check_print.h   \
-       check_str.h     \
-       libcompat/libcompat.h
-
-noinst_HEADERS = $(HFILES)
-
-libcheckinternal_la_SOURCES    = $(CFILES) $(HFILES)
-
-libcheckinternal_la_CFLAGS     = -I$(top_builddir)/libs/gst/check
-libcheckinternal_la_LIBADD     =
-
-# define HAVE_PTHREAD here as well so we keep changes to the code to a minimum
-if HAVE_PTHREAD
-libcheckinternal_la_CFLAGS     += $(PTHREAD_CFLAGS) -D_GNU_SOURCE -DHAVE_PTHREAD
-libcheckinternal_la_LIBADD     += $(PTHREAD_LIBS)
-else
-libcheckinternal_la_CFLAGS     += -D_GNU_SOURCE
-endif
-
-# Don't want libcompat to think we don't have these and substitute replacements
-# See libcompat/libcompat.h
-libcheckinternal_la_CFLAGS     += -DHAVE_SNPRINTF -DHAVE_VSNPRINTF -DHAVE_MALLOC -DHAVE_REALLOC
index 3bf7bfe..8ef3b62 100644 (file)
@@ -26,6 +26,8 @@
 #include <stdarg.h>
 #include <math.h>
 
+#include <glib.h>
+
 #include "internal-check.h"
 #include "check_error.h"
 #include "check_list.h"
@@ -384,13 +386,13 @@ _ck_assert_failed (const char *file, int line, const char *expr, ...)
 
   va_end (ap);
   send_failure_info (to_send);
-  if (cur_fork_status () == CK_FORK) {
 #if defined(HAVE_FORK) && HAVE_FORK==1
+  if (cur_fork_status () == CK_FORK) {
+    g_thread_pool_stop_unused_threads ();
     _exit (1);
-#endif /* HAVE_FORK */
-  } else {
-    longjmp (error_jmp_buffer, 1);
   }
+#endif /* HAVE_FORK */
+  longjmp (error_jmp_buffer, 1);
 }
 
 SRunner *
index 754de91..d52abc5 100644 (file)
@@ -422,20 +422,10 @@ static void __testname (int _i CK_ATTRIBUTE_UNUSED)\
 
 /*
  * This is called whenever an assertion fails.
- * Note that it only has the noreturn modifier when
- * using fork. If fork is unavailable, the function
- * calls longjmp() when a test assertion fails. Marking
- * the function as noreturn causes gcc to make assumptions
- * which are not valid, as longjmp() is like a return.
  */
-#if @HAVE_FORK@
 CK_DLL_EXP void CK_EXPORT
 _ck_assert_failed (const char *file, int line, const char *expr, ...)
     CK_ATTRIBUTE_NORETURN;
-#else
-CK_DLL_EXP void CK_EXPORT _ck_assert_failed (const char *file, int line,
-    const char *expr, ...);
-#endif
 
 /**
  * Fail the test if expression is false
index 146a584..4925d88 100644 (file)
@@ -461,7 +461,7 @@ punpack (FILE * fdes)
 
   rmsg = rcvmsg_create ();
 
-  /* Allcate a buffer */
+  /* Allocate a buffer */
   buf = (char *) emalloc (CK_MAX_MSG_SIZE);
   /* Fill the buffer from the file */
   nread = read_buf (fdes, CK_MAX_MSG_SIZE, buf);
index f686ca0..a97379c 100644 (file)
@@ -29,6 +29,8 @@
 #include <signal.h>
 #include <setjmp.h>
 
+#include <glib.h>
+
 #include "internal-check.h"
 #include "check_error.h"
 #include "check_list.h"
@@ -466,6 +468,7 @@ tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tfun, int i)
     clock_gettime (check_get_clockid (), &ts_end);
     tcase_run_checked_teardown (tc);
     send_duration_info (DIFF_IN_USEC (ts_start, ts_end));
+    g_thread_pool_stop_unused_threads ();
     exit (EXIT_SUCCESS);
   } else {
     group_pid = pid;
@@ -784,9 +787,11 @@ check_waitpid_and_exit (pid_t pid CK_ATTRIBUTE_UNUSED)
     }
     while (pid_w == -1);
     if (waserror (status, 0)) {
+      g_thread_pool_stop_unused_threads ();
       exit (EXIT_FAILURE);
     }
   }
+  g_thread_pool_stop_unused_threads ();
   exit (EXIT_SUCCESS);
 #else /* HAVE_FORK */
   eprintf ("This version does not support fork", __FILE__, __LINE__);
index 17d3f01..c6d496d 100644 (file)
@@ -72,7 +72,9 @@ foreach arg : [
   '-Wno-missing-prototypes',
   '-Wno-missing-declarations',
   '-Wno-old-style-definition',
-  '-Wno-declaration-after-statement']
+  '-Wno-declaration-after-statement',
+  '-Wno-format-nonliteral',
+  '-Wno-tautological-constant-out-of-range-compare']
   if cc.has_argument(arg)
     no_warn_args += [arg]
   endif
@@ -81,7 +83,7 @@ endforeach
 libcheck = static_library('check',
   libcheck_files,
   include_directories : [configinc, internal_check_h_inc],
-  dependencies : [rt_lib, mathlib],
+  dependencies : [rt_lib, mathlib, glib_dep],
   c_args: gst_c_args + libcheck_visibility_args + no_warn_args +
          # Don't want libcompat to think we don't have these and substitute
          # replacements since we don't check for or define these. See libcompat.h
index 1be0865..316465a 100644 (file)
@@ -48,11 +48,23 @@ gst_check = library('gstcheck-@0@'.format(apiversion),
   dependencies : [gobject_dep, glib_dep, gst_dep],
 )
 
+pkgconfig.generate(gst_check,
+  libraries : [libgst],
+  # FIXME: Add manually libcheck's dependencies because it's an uninstalled static
+  # library and Meson <0.56.0 does not handle them correctly.
+  # See https://github.com/mesonbuild/meson/pull/7488.
+  libraries_private: [rt_lib, mathlib],
+  variables : pkgconfig_variables,
+  subdirs : pkgconfig_subdirs,
+  name : 'gstreamer-check-1.0',
+  description : 'Unit testing helper library for GStreamer modules',
+)
+
 gst_check_gen_sources = []
 
 if build_gir
   gst_gir_extra_args = gir_init_section + [ '--c-include=gst/check/check.h' ]
-  gst_check_gen_sources += [gnome.generate_gir(gst_check,
+  gst_check_gir = gnome.generate_gir(gst_check,
     sources : gst_check_sources + gst_check_headers,
     namespace : 'GstCheck',
     nsversion : apiversion,
@@ -64,10 +76,13 @@ if build_gir
     includes : ['GLib-2.0', 'GObject-2.0', 'GModule-2.0', 'Gst-1.0'],
     install : true,
     extra_args : gst_gir_extra_args,
-  )]
+  )
+  gst_check_gen_sources += gst_check_gir
 endif
 
 gst_check_dep = declare_dependency(link_with : gst_check,
   include_directories : [libsinc],
   dependencies : [gst_dep],
   sources : gst_check_gen_sources)
+
+meson.override_dependency('gstreamer-check-1.0', gst_check_dep)
diff --git a/libs/gst/controller/.gitignore b/libs/gst/controller/.gitignore
deleted file mode 100644 (file)
index dc3e21b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-*.bb
-*.bbg
-*.da
-*.def
-*.gcno
-*.o
-*.lo
-*.la
diff --git a/libs/gst/controller/Makefile.am b/libs/gst/controller/Makefile.am
deleted file mode 100644 (file)
index f5bdcac..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-lib_LTLIBRARIES = libgstcontroller-@GST_API_VERSION@.la
-
-glib_enum_headers= \
-       gstinterpolationcontrolsource.h \
-       gstlfocontrolsource.h
-
-glib_enum_define = GST_CONTROLLER
-glib_gen_prefix = gst
-glib_gen_basename = controller
-glib_gen_decl_banner=GST_CONTROLLER_API
-glib_gen_decl_include=\#include <gst/controller/controller-prelude.h>
-
-built_sources = controller-enumtypes.c
-built_headers = controller-enumtypes.h
-BUILT_SOURCES = $(built_sources) $(built_headers)
-
-libgstcontroller_@GST_API_VERSION@_includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/controller
-libgstcontroller_@GST_API_VERSION@_include_HEADERS = \
-       controller.h \
-       controller-prelude.h \
-       gstargbcontrolbinding.h \
-       gstdirectcontrolbinding.h \
-       gsttimedvaluecontrolsource.h \
-       gstinterpolationcontrolsource.h \
-       gstproxycontrolbinding.h \
-       gsttriggercontrolsource.h \
-       gstlfocontrolsource.h
-
-nodist_libgstcontroller_@GST_API_VERSION@_include_HEADERS = \
-       controller-enumtypes.h
-
-libgstcontroller_@GST_API_VERSION@_la_SOURCES = \
-       gstargbcontrolbinding.c \
-       gstdirectcontrolbinding.c \
-       gsttimedvaluecontrolsource.c \
-       gstinterpolationcontrolsource.c \
-       gstproxycontrolbinding.c \
-       gsttriggercontrolsource.c \
-       gstlfocontrolsource.c
-
-nodist_libgstcontroller_@GST_API_VERSION@_la_SOURCES = $(BUILT_SOURCES)
-
-libgstcontroller_@GST_API_VERSION@_la_CFLAGS = $(GST_OBJ_CFLAGS) -DBUILDING_GST_CONTROLLER
-libgstcontroller_@GST_API_VERSION@_la_LIBADD = $(GST_OBJ_LIBS) $(LIBM)
-libgstcontroller_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
-
-CLEANFILES = *.gcno *.gcda *.gcov $(BUILT_SOURCES)
-
-%.c.gcov: .libs/libgstcontroller_@GST_API_VERSION@_la-%.gcda %.c
-       $(GCOV) -b -f -o $^ > $@.out
-
-gcov: $(libgstcontroller_@GST_API_VERSION@_la_SOURCES:=.gcov)
-
-include $(top_srcdir)/common/gst-glib-gen.mak
-
-if HAVE_INTROSPECTION
-BUILT_GIRSOURCES = GstController-@GST_API_VERSION@.gir
-
-gir_headers=$(patsubst %,$(srcdir)/%, $(libgstcontroller_@GST_API_VERSION@_include_HEADERS))
-gir_headers+=$(patsubst %,$(builddir)/%, $(nodist_libgstcontroller_@GST_API_VERSION@_include_HEADERS))
-gir_sources=$(patsubst %,$(srcdir)/%, $(libgstcontroller_@GST_API_VERSION@_la_SOURCES))
-gir_sources+=$(patsubst %,$(builddir)/%, $(nodist_libgstcontroller_@GST_API_VERSION@_la_SOURCES))
-
-GstController-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstcontroller-@GST_API_VERSION@.la
-       $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" GI_SCANNER_DISABLE_CACHE=yes\
-               GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_DISABLE=yes \
-               CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" PKG_CONFIG="$(PKG_CONFIG)" DLLTOOL="$(DLLTOOL)" \
-               $(INTROSPECTION_SCANNER) -v --namespace GstController \
-               --nsversion=@GST_API_VERSION@ \
-               --warn-all \
-               --identifier-prefix=Gst \
-               --symbol-prefix=gst \
-               -I$(top_srcdir) \
-               -I$(top_srcdir)/libs \
-               -I$(top_builddir) \
-               -I$(top_builddir)/libs \
-               --c-include "gst/controller/controller.h" \
-               --add-include-path=$(top_builddir)/gst \
-               --library-path=$(top_builddir)/gst \
-               --library=libgstcontroller-@GST_API_VERSION@.la \
-               --include=Gst-@GST_API_VERSION@ \
-               --libtool="${LIBTOOL}" \
-               --pkg gstreamer-@GST_API_VERSION@ \
-               --pkg-export gstreamer-controller-@GST_API_VERSION@ \
-               --add-init-section="$(INTROSPECTION_INIT)" \
-               --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
index caabed3..3d1c8ba 100644 (file)
@@ -96,9 +96,7 @@ GstControlBinding * gst_argb_control_binding_new   (GstObject * object, const gc
                                                             GstControlSource * cs_a, GstControlSource * cs_r,
                                                             GstControlSource * cs_g, GstControlSource * cs_b);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstARGBControlBinding, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index bcc872e..0c4d589 100644 (file)
@@ -215,6 +215,7 @@ gst_direct_control_binding_class_init (GstDirectControlBindingClass * klass)
 static void
 gst_direct_control_binding_init (GstDirectControlBinding * self)
 {
+  self->last_value = G_MAXDOUBLE;
 }
 
 static GObject *
@@ -427,7 +428,7 @@ gst_direct_control_binding_get_value_array (GstControlBinding * _self,
     gpointer values_)
 {
   GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (_self);
-  gint i;
+  guint i;
   gdouble *src_val;
   gboolean res = FALSE;
   GstDirectControlBindingConvertValue convert;
@@ -470,7 +471,7 @@ gst_direct_control_binding_get_g_value_array (GstControlBinding * _self,
     GValue * values)
 {
   GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (_self);
-  gint i;
+  guint i;
   gdouble *src_val;
   gboolean res = FALSE;
   GType type;
index c84b870..549d124 100644 (file)
@@ -122,9 +122,7 @@ GST_CONTROLLER_API
 GstControlBinding * gst_direct_control_binding_new_absolute (GstObject * object, const gchar * property_name, 
                                                     GstControlSource * cs);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstDirectControlBinding, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 6ee44bb..a3da267 100644 (file)
@@ -97,9 +97,7 @@ GType gst_interpolation_control_source_get_type (void);
 GST_CONTROLLER_API
 GstControlSource * gst_interpolation_control_source_new (void);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstInterpolationControlSource, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 41bc100..cc09d49 100644 (file)
@@ -95,9 +95,7 @@ GType gst_lfo_control_source_get_type (void);
 GST_CONTROLLER_API
 GstControlSource *gst_lfo_control_source_new (void);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstLFOControlSource, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 660a3df..ddff085 100644 (file)
@@ -170,7 +170,7 @@ gst_proxy_control_binding_class_init (GstProxyControlBindingClass * klass)
  *              #GstControlBinding requests to
  * @ref_property_name: the property_name in @ref_object to control
  *
- * #GstProxyControlBinding forwards all access to data or sync_values()
+ * #GstProxyControlBinding forwards all access to data or `sync_values()`
  * requests from @property_name on @object to the control binding at
  * @ref_property_name on @ref_object.
  *
index b39e760..42e8fd9 100644 (file)
@@ -79,9 +79,7 @@ GstControlBinding *     gst_proxy_control_binding_new (GstObject * object,
                                                        GstObject * ref_object,
                                                        const gchar * ref_property_name);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstProxyControlBinding, gst_object_unref)
-#endif
 G_END_DECLS
 
 #endif /* __GST_PROXY_CONTROL_BINDING_H__ */
index 66c82a9..1f9c599 100644 (file)
@@ -81,6 +81,14 @@ gst_control_point_free (GstControlPoint * cp)
   g_slice_free (GstControlPoint, cp);
 }
 
+/**
+ * gst_control_point_copy:
+ * @cp: The control point to copy
+ *
+ * Copies a #GstControlPoint
+ *
+ * Returns: A copy of @cp
+ */
 GstControlPoint *
 gst_control_point_copy (GstControlPoint * cp)
 {
@@ -90,7 +98,7 @@ gst_control_point_copy (GstControlPoint * cp)
 GType
 gst_control_point_get_type (void)
 {
-  static volatile gsize type_id = 0;
+  static gsize type_id = 0;
 
   if (g_once_init_enter (&type_id)) {
     GType tmp =
@@ -473,8 +481,7 @@ gst_timed_value_control_source_class_init (GstTimedValueControlSourceClass
   gst_timed_value_control_source_signals[VALUE_CHANGED_SIGNAL] =
       g_signal_new ("value-changed", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_FIRST, 0, NULL,
-      NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1,
-      gst_control_point_get_type ());
+      NULL, NULL, G_TYPE_NONE, 1, gst_control_point_get_type ());
 
   /**
    * GstTimedValueControlSource::value-added
@@ -489,8 +496,7 @@ gst_timed_value_control_source_class_init (GstTimedValueControlSourceClass
   gst_timed_value_control_source_signals[VALUE_ADDED_SIGNAL] =
       g_signal_new ("value-added", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_FIRST, 0, NULL,
-      NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1,
-      gst_control_point_get_type ());
+      NULL, NULL, G_TYPE_NONE, 1, gst_control_point_get_type ());
 
   /**
    * GstTimedValueControlSource::value-removed
@@ -505,8 +511,7 @@ gst_timed_value_control_source_class_init (GstTimedValueControlSourceClass
   gst_timed_value_control_source_signals[VALUE_REMOVED_SIGNAL] =
       g_signal_new ("value-removed", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_FIRST, 0, NULL,
-      NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1,
-      gst_control_point_get_type ());
+      NULL, NULL, G_TYPE_NONE, 1, gst_control_point_get_type ());
 
 
   gobject_class->finalize = gst_timed_value_control_source_finalize;
index 65ba373..2baa369 100644 (file)
@@ -153,9 +153,7 @@ void            gst_control_point_free (GstControlPoint * cp);
 GST_CONTROLLER_API
 GstControlPoint * gst_control_point_copy (GstControlPoint * cp);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTimedValueControlSource, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index f98bed7..431456b 100644 (file)
@@ -80,9 +80,7 @@ GType gst_trigger_control_source_get_type (void);
 GST_CONTROLLER_API
 GstControlSource *gst_trigger_control_source_new (void);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTriggerControlSource, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index e592b81..08857ca 100644 (file)
@@ -48,6 +48,14 @@ gst_controller = library('gstcontroller-@0@'.format(apiversion),
   dependencies : [gobject_dep, glib_dep, mathlib, gst_dep],
 )
 
+pkgconfig.generate(gst_controller,
+  libraries : [libgst],
+  variables : pkgconfig_variables,
+  subdirs : pkgconfig_subdirs,
+  name : 'gstreamer-controller-1.0',
+  description : 'Dynamic parameter control for GStreamer elements',
+)
+
 if build_gir
   gst_gir_extra_args = gir_init_section + [ '--c-include=gst/controller/controller.h' ]
   gst_controller_gir = gnome.generate_gir(gst_controller,
@@ -70,3 +78,5 @@ gst_controller_dep = declare_dependency(link_with : gst_controller,
   include_directories : [libsinc],
   sources: gst_controller_gen_sources,
   dependencies : [gst_dep])
+
+meson.override_dependency('gstreamer-controller-1.0', gst_controller_dep)
diff --git a/libs/gst/helpers/.gitignore b/libs/gst/helpers/.gitignore
deleted file mode 100644 (file)
index 87c36bf..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-gst-plugin-scanner
-gst-completion-helper
-gst-ptp-helper
-libgstreamer-gdb.py
-*.o
diff --git a/libs/gst/helpers/Makefile.am b/libs/gst/helpers/Makefile.am
deleted file mode 100644 (file)
index 276b406..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-helpers_PROGRAMS = gst-plugin-scanner
-helpersdir=$(libexecdir)/gstreamer-$(GST_API_VERSION)
-
-gst_plugin_scanner_SOURCES = gst-plugin-scanner.c
-gst_plugin_scanner_CFLAGS = $(GST_OBJ_CFLAGS) -fPIE
-gst_plugin_scanner_LDADD = $(GST_OBJ_LIBS)
-gst_plugin_scanner_LDFLAGS = -pie
-
-if ENABLE_BASH_COMPLETION
-helpers_PROGRAMS += gst-completion-helper
-gst_completion_helper_SOURCES = gst-completion-helper.c
-gst_completion_helper_CFLAGS = $(GST_OBJ_CFLAGS)
-gst_completion_helper_LDADD = $(GST_OBJ_LIBS)
-endif
-
-if HAVE_PTP
-helpers_PROGRAMS += gst-ptp-helper
-gst_ptp_helper_SOURCES = gst-ptp-helper.c
-gst_ptp_helper_CFLAGS = $(GST_OBJ_CFLAGS) $(GIO_CFLAGS) -fPIE
-gst_ptp_helper_LDADD = $(GST_OBJ_LIBS) $(GIO_LIBS) $(CAP_LIBS)
-gst_ptp_helper_LDFLAGS = -pie
-endif
-
-install-data-hook:
-if HAVE_PTP
-if HAVE_PTP_HELPER_SETUID
-       - chown root $(DESTDIR)$(helpersdir)/gst-ptp-helper
-       - chmod u+s $(DESTDIR)$(helpersdir)/gst-ptp-helper
-endif
-if HAVE_PTP_HELPER_CAPABILITIES
-       - $(SETCAP) cap_net_bind_service,cap_net_admin+ep $(DESTDIR)$(helpersdir)/gst-ptp-helper
-endif
-endif
-
-EXTRA_DIST = ptp_helper_post_install.sh
-
-DISTCLEANFILES = libgstreamer-gdb.py
-
-# install gdb scripts
-gdbdir = $(datadir)/gstreamer-@GST_API_VERSION@/gdb
-dist_gdb_DATA = gst_gdb.py glib_gobject_helper.py
-
-install-data-hook:
-       $(INSTALL) -d $(DESTDIR)$(datadir)/gdb/auto-load$(libdir)
-       $(INSTALL) $(builddir)/libgstreamer-gdb.py $(DESTDIR)$(datadir)/gdb/auto-load$(libdir)/libgstreamer-@GST_API_VERSION@.so.0.$(GST_CURRENT).$(GST_REVISION)-gdb.py
-
-uninstall-hook:
-       rm -f "$(DESTDIR)$(datadir)/gdb/auto-load$(libdir)/libgstreamer-@GST_API_VERSION@.so.0.$(GST_CURRENT).$(GST_REVISION)-gdb.py"
index 64b4dd2..a89312c 100644 (file)
@@ -92,6 +92,38 @@ class GstObjectPrettyPrinter:
             return "0x%x" % long(self.val)
 
 
+GST_SECOND = 1000000000
+GST_CLOCK_TIME_NONE = 2**64-1
+GST_CLOCK_STIME_NONE = -2**63
+
+
+def format_time(n, signed=False):
+    prefix = ""
+    invalid = False
+    if signed:
+        if n == GST_CLOCK_STIME_NONE:
+            invalid = True
+        prefix = "+" if n >= 0 else "-"
+        n = abs(n)
+    else:
+        if n == GST_CLOCK_TIME_NONE:
+            invalid = True
+
+    if invalid:
+        return "99:99:99.999999999"
+
+    return "%s%u:%02u:%02u.%09u" % (
+        prefix,
+        n / (GST_SECOND * 60 * 60),
+        (n / (GST_SECOND * 60)) % 60,
+        (n / GST_SECOND) % 60,
+        n % GST_SECOND)
+
+
+def format_time_value(val):
+    return format_time(int(val), str(val.type) == "GstClockTimeDiff")
+
+
 class GstClockTimePrinter:
     "Prints a GstClockTime / GstClockTimeDiff"
 
@@ -99,30 +131,7 @@ class GstClockTimePrinter:
         self.val = val
 
     def to_string(self):
-        GST_SECOND = 1000000000
-        GST_CLOCK_TIME_NONE = 2**64-1
-        GST_CLOCK_STIME_NONE = -2**63
-        n = int(self.val)
-        prefix = ""
-        invalid = False
-        if str(self.val.type) == "GstClockTimeDiff":
-            if n == GST_CLOCK_STIME_NONE:
-                invalid = True
-            prefix = "+" if n >= 0 else "-"
-            n = abs(n)
-        else:
-            if n == GST_CLOCK_TIME_NONE:
-                invalid = True
-
-        if invalid:
-            return str(n) + " [99:99:99.999999999]"
-
-        return str(n) + " [%s%u:%02u:%02u.%09u]" % (
-            prefix,
-            n / (GST_SECOND * 60 * 60),
-            (n / (GST_SECOND * 60)) % 60,
-            (n / GST_SECOND) % 60,
-            n % GST_SECOND)
+        return "%d [%s]" % (int(self.val), format_time_value(self.val))
 
 
 def gst_pretty_printer_lookup(val):
@@ -243,6 +252,60 @@ def _g_value_get_value(val):
     return val["data"].cast(t).dereference()
 
 
+def gst_object_from_value(value):
+    if value.type.code != gdb.TYPE_CODE_PTR:
+        value = value.address
+
+    if not is_gst_type(value, "GstObject"):
+        raise Exception("'%s' is not a GstObject" % args[0])
+
+    return value.cast(gdb.lookup_type("GstObject").pointer())
+
+
+def gst_object_pipeline(obj):
+    try:
+        while obj["parent"] != 0:
+            tmp = obj["parent"]
+            # sanity checks to handle memory corruption
+            if g_inherits_type(obj, "GstElement") and \
+               GdbGstElement(obj) not in GdbGstElement(tmp).children():
+                break
+            if g_inherits_type(obj, "GstPad"):
+                pad = GdbGstPad(obj)
+                if g_inherits_type(tmp, "GstElement"):
+                    if pad not in GdbGstElement(tmp).pads():
+                        break
+                elif g_inherits_type(tmp, "GstProxyPad"):
+                    t = gdb.lookup_type("GstProxyPad").pointer()
+                    if pad != GdbGstPad(tmp.cast(t)["priv"]["internal"]):
+                        break
+            obj = tmp
+    except gdb.MemoryError:
+        pass
+
+    if not g_inherits_type(obj, "GstElement"):
+        raise Exception("Toplevel parent is not a GstElement")
+    return obj.cast(gdb.lookup_type("GstElement").pointer())
+
+
+def element_state_to_name(state):
+    names = [
+        "VOID_PENDING",
+        "NULL",
+        "READY",
+        "PAUSED",
+        "PLAYING"]
+    return names[state] if state < len(names) else "UNKNOWN"
+
+
+def task_state_to_name(state):
+    names = [
+        "STARTED",
+        "STOPPED",
+        "PAUSED"]
+    return names[state] if state < len(names) else "UNKNOWN"
+
+
 def _gdb_write(indent, text):
     gdb.write("%s%s\n" % ("  " * indent, text))
 
@@ -388,6 +451,10 @@ class GdbGValue:
                     v += " " if v == "<" else ", "
                     v += str(GdbGValue(l))
                 v += " >"
+            elif tname in ("GEnum"):
+                v = "%s(%s)" % (
+                    g_type_to_name(g_type_to_typenode(self.val["g_type"])),
+                    value["v_int"])
             else:
                 try:
                     v = value.string()
@@ -395,7 +462,7 @@ class GdbGValue:
                     # it is not a string-like type
                     if gvalue_type.fields()[1].type == value.type:
                         # don't print the raw GValue union
-                        v = "<unkown type: %s>" % tname
+                        v = "<unknown type: %s>" % tname
                     else:
                         v = str(value)
         except gdb.MemoryError:
@@ -416,11 +483,12 @@ class GdbGstStructure:
 
     @save_memory_access(0)
     def size(self):
-        return int(self.val["fields"]["len"])
+        return int(self.val["fields_len"])
 
     def values(self):
-        for f in _g_array_iter(self.val["fields"],
-                               gdb.lookup_type("GstStructureField")):
+        item = self.val["fields"].cast(gdb.lookup_type("GstStructureField").pointer())
+        for i in range(self.size()):
+            f = item[i]
             key = g_quark_to_string(f["name"])
             value = GdbGValue(f["value"])
             yield(key, value)
@@ -458,11 +526,49 @@ class GdbGstStructure:
         if prefix is not None:
             _gdb_write(indent, "%s: %s" % (prefix, self.name()))
         else:
-            _gdb_write(indent, "%s:" % (prefix, self.name()))
+            _gdb_write(indent, "%s:" % (self.name()))
         for (key, value) in self.values():
             _gdb_write(indent+1, "%s: %s" % (key, str(value)))
 
 
+class GdbGstSegment:
+    def __init__(self, val):
+        self.val = val
+        self.fmt = str(self.val["format"]).split("_")[-1].lower()
+
+    def format_value(self, n):
+        if self.fmt == "time":
+            return format_time(n, False)
+        else:
+            return str(n)
+
+    def print_optional(self, indent, key, skip=None):
+        value = int(self.val[key])
+        if skip is None or value != skip:
+            _gdb_write(indent, "%s:%s %s" %
+                       (key, (8-len(key))*" ", self.format_value(value)))
+
+    def print(self, indent, seqnum=None):
+        s = "segment:"
+        if seqnum:
+            s += "(seqnum: %s)" % seqnum
+        _gdb_write(indent, s)
+        rate = float(self.val["rate"])
+        applied_rate = float(self.val["applied_rate"])
+        if applied_rate != 1.0:
+            applied = "(applied rate: %g)" % applied_rate
+        else:
+            applied = ""
+        _gdb_write(indent+1, "rate: %g%s" % (rate, applied))
+        self.print_optional(indent+1, "base", 0)
+        self.print_optional(indent+1, "offset", 0)
+        self.print_optional(indent+1, "start")
+        self.print_optional(indent+1, "stop", GST_CLOCK_TIME_NONE)
+        self.print_optional(indent+1, "time")
+        self.print_optional(indent+1, "position")
+        self.print_optional(indent+1, "duration", GST_CLOCK_TIME_NONE)
+
+
 class GdbGstEvent:
     def __init__(self, val):
         self.val = val.cast(gdb.lookup_type("GstEventImpl").pointer())
@@ -485,24 +591,17 @@ class GdbGstEvent:
     @save_memory_access_print("<inaccessible memory>")
     def print(self, indent):
         typestr = self.typestr()
+        seqnum = self.val["event"]["seqnum"]
         if typestr == "caps":
             caps = GdbGstCaps(self.structure().value("caps").value())
-            caps.print(indent, "caps:")
+            caps.print(indent, "caps (seqnum: %s):" % seqnum)
         elif typestr == "stream-start":
             stream_id = self.structure().value("stream-id").value()
-            _gdb_write(indent, "stream-start:")
+            _gdb_write(indent, "stream-start: (seqnum %s)"  % seqnum)
             _gdb_write(indent + 1, "stream-id: %s" % stream_id.string())
         elif typestr == "segment":
             segment = self.structure().value("segment").value()
-            fmt = str(segment["format"]).split("_")[-1].lower()
-            _gdb_write(indent, "segment: %s" % fmt)
-            rate = float(segment["rate"])
-            applied_rate = float(segment["applied_rate"])
-            if applied_rate != 1.0:
-                applied = "(applied rate: %g)" % applied_rate
-            else:
-                applied = ""
-            _gdb_write(indent+1, "rate: %g%s" % (rate, applied))
+            GdbGstSegment(segment).print(indent, seqnum)
         elif typestr == "tag":
             struct = self.structure()
             # skip 'GstTagList-'
@@ -510,11 +609,76 @@ class GdbGstEvent:
             t = gdb.lookup_type("GstTagListImpl").pointer()
             s = struct.value("taglist").value().cast(t)["structure"]
             structure = GdbGstStructure(s)
-            _gdb_write(indent, "tag: %s" % name)
+            _gdb_write(indent, "tag: %s (seqnum: %s)" % (name, seqnum))
             for (key, value) in structure.values():
                 _gdb_write(indent+1, "%s: %s" % (key, str(value)))
         else:
-            self.structure().print(indent, typestr)
+            self.structure().print(indent, "%s (seqnum: %s)" % (typestr, seqnum))
+
+
+class GdbGstBuffer:
+    def __init__(self, val):
+        self.val = val.cast(gdb.lookup_type("GstBuffer").pointer())
+
+    def print_optional(self, indent, key, skip=None, format_func=str):
+        value = int(self.val[key])
+        if skip is None or value != skip:
+            _gdb_write(indent, "%s:%s %s" %
+                       (key, (8-len(key))*" ", format_func(value)))
+
+    @save_memory_access_print("<inaccessible memory>")
+    def print(self, indent):
+        _gdb_write(indent, "GstBuffer: (0x%x)" % self.val)
+        indent += 1
+        self.print_optional(indent, "pool", 0)
+        self.print_optional(indent, "pts", GST_CLOCK_TIME_NONE, format_time)
+        self.print_optional(indent, "dts", GST_CLOCK_TIME_NONE, format_time)
+        self.print_optional(indent, "duration", GST_CLOCK_TIME_NONE, format_time)
+        self.print_optional(indent, "offset", GST_CLOCK_TIME_NONE)
+        self.print_optional(indent, "offset_end", GST_CLOCK_TIME_NONE)
+
+        impl = self.val.cast(gdb.lookup_type("GstBufferImpl").pointer())
+        meta_item = impl['item']
+        if meta_item:
+            _gdb_write(indent, "Metas:")
+            indent += 1
+            while meta_item:
+                meta = meta_item['meta']
+                meta_type_name = g_type_to_name(meta['info']['type'])
+                _gdb_write(indent, "%s:" % meta_type_name)
+                indent += 1
+                meta_info = str(meta.cast(gdb.lookup_type(meta_type_name)))
+                for l in meta_info.split('\n'):
+                    _gdb_write(indent, l)
+                indent -= 1
+                meta_item = meta_item['next']
+        else:
+            _gdb_write(indent, "(No meta)")
+
+
+class GdbGstQuery:
+    def __init__(self, val):
+        self.val = val.cast(gdb.lookup_type("GstQueryImpl").pointer())
+
+    @save_memory_access("<inaccessible memory>")
+    def typestr(self):
+        t = self.val["query"]["type"]
+        (query_quarks, _) = gdb.lookup_symbol("query_quarks")
+        query_quarks = query_quarks.value()
+        i = 0
+        while query_quarks[i]["name"] != 0:
+            if t == query_quarks[i]["type"]:
+                return query_quarks[i]["name"].string()
+            i += 1
+        return None
+
+    def structure(self):
+        return GdbGstStructure(self.val["structure"])
+
+    @save_memory_access_print("<inaccessible memory>")
+    def print(self, indent):
+        typestr = self.typestr()
+        self.structure().print(indent, typestr)
 
 
 class GdbGstObject:
@@ -526,6 +690,10 @@ class GdbGstObject:
         obj = self.val.cast(gdb.lookup_type("GstObject").pointer())
         return obj["name"].string()
 
+    def full_name(self):
+        parent = self.parent_element()
+        return "%s%s" % (parent.name() + ":" if parent else "", self.name())
+
     def dot_name(self):
         ptr = self.val.cast(gdb.lookup_type("void").pointer())
         return re.sub('[^a-zA-Z0-9<>]', '_', "%s_%s" % (self.name(), str(ptr)))
@@ -541,6 +709,13 @@ class GdbGstObject:
             return GdbGstElement(element)
         return None
 
+    def parent_pad(self):
+        p = self.parent()
+        if p != 0 and g_inherits_type(p, "GstPad"):
+            pad = p.cast(gdb.lookup_type("GstPad").pointer())
+            return GdbGstPad(pad)
+        return None
+
 
 class GdbGstPad(GdbGstObject):
     def __init__(self, val):
@@ -599,6 +774,29 @@ class GdbGstPad(GdbGstObject):
                 _gdb_write(indent+1, "events:")
                 first = False
             ev.print(indent+2)
+
+        if self.is_linked():
+            real = self.peer().parent_pad()
+            _gdb_write(indent+1, "peer: %s" %
+                       (real.full_name() if real else self.peer().full_name()))
+
+        if g_inherits_type(self.val, "GstGhostPad"):
+            t = gdb.lookup_type("GstProxyPad").pointer()
+            internal = GdbGstPad(self.val.cast(t)["priv"]["internal"])
+            if internal and internal.peer():
+                _gdb_write(indent+1, "inner peer: %s" %
+                           internal.peer().full_name())
+
+        task = self.val["task"]
+        if long(task) != 0:
+            _gdb_write(indent+1, "task: %s" %
+                       task_state_to_name(int(task["state"])))
+
+        offset = long(self.val["offset"])
+        if offset != 0:
+            _gdb_write(indent+1, "offset: %d [%s]" %
+                       (offset, format_time(offset, True)))
+
         _gdb_write(indent, "}")
 
     def _dot(self, color, pname, indent):
@@ -752,8 +950,35 @@ class GdbGstElement(GdbGstObject):
                    (g_type_name_from_instance(self.val), self.name()))
         for p in self.pads():
             p.print(indent+2)
+
+        first = True
+        for child in self.children():
+            if first:
+                _gdb_write(indent+2, "children:")
+                first = False
+            _gdb_write(indent+3, child.name())
+
+        current_state = self.val["current_state"]
+        s = "state: %s" % element_state_to_name(current_state)
+        for var in ("pending", "target"):
+            state = self.val[var + "_state"]
+            if state > 0 and state != current_state:
+                s += ", %s: %s" % (var, element_state_to_name(state))
+        _gdb_write(indent+2, s)
+
+        _gdb_write(indent+2, "base_time: %s" %
+                   format_time_value(self.val["base_time"]))
+        _gdb_write(indent+2, "start_time: %s" %
+                   format_time_value(self.val["start_time"]))
+
         _gdb_write(indent, "}")
 
+    @save_memory_access_print("<inaccessible memory>")
+    def print_tree(self, indent):
+        _gdb_write(indent, "%s(%s)" % (self.name(), self.val))
+        for child in self.children():
+            child.print_tree(indent+1)
+
     def _dot(self, indent=0):
         spc = "  " * indent
 
@@ -886,30 +1111,8 @@ Usage: gst-dot <gst-object> <file-name>"""
         if not value:
             raise Exception("'%s' is not a valid object" % args[0])
 
-        if value.type.code != gdb.TYPE_CODE_PTR:
-            value = value.address
-
-        if not is_gst_type(value, "GstObject"):
-            raise Exception("'%s' is not a GstObject" % args[0])
-
-        value = value.cast(gdb.lookup_type("GstObject").pointer())
-        try:
-            while value["parent"] != 0:
-                tmp = value["parent"]
-                # sanity checks to handle memory corruption
-                if g_inherits_type(value, "GstElement") and \
-                   GdbGstElement(value) not in GdbGstElement(tmp).children():
-                    break
-                if g_inherits_type(value, "GstPad") and \
-                   GdbGstPad(value) not in GdbGstElement(tmp).pads():
-                    break
-                value = tmp
-        except gdb.MemoryError:
-            pass
-
-        if not g_inherits_type(value, "GstElement"):
-            raise Exception("Toplevel parent is not a GstElement")
-        value = value.cast(gdb.lookup_type("GstElement").pointer())
+        value = gst_object_from_value(value)
+        value = gst_object_pipeline(value)
 
         dot = GdbGstElement(value).pipeline_dot()
         file = open(args[1], "w")
@@ -935,7 +1138,7 @@ Usage gst-print <gstreamer-object>"""
     def invoke(self, arg, from_tty):
         value = gdb.parse_and_eval(arg)
         if not value:
-            raise Exception("'%s' is not a valid object" % args[0])
+            raise Exception("'%s' is not a valid object" % arg)
 
         if value.type.code != gdb.TYPE_CODE_PTR:
             value = value.address
@@ -947,21 +1150,129 @@ Usage gst-print <gstreamer-object>"""
         elif g_inherits_type(value, "GstCaps"):
             obj = GdbGstCaps(value)
         elif g_inherits_type(value, "GstEvent"):
-            obj = GdbGstCaps(value)
+            obj = GdbGstEvent(value)
+        elif g_inherits_type(value, "GstQuery"):
+            obj = GdbGstQuery(value)
+        elif g_inherits_type(value, "GstBuffer"):
+            obj = GdbGstBuffer(value)
+        elif is_gst_type(value, "GstStructure"):
+            obj = GdbGstStructure(value)
         else:
-            raise Exception("'%s' has an unkown type" % arg)
+            raise Exception("'%s' has an unknown type (%s)" % (arg, value))
 
         obj.print(0)
 
 
+class GstPipelineTree(gdb.Command):
+    """\
+Usage: gst-pipeline-tree <gst-object>"""
+    def __init__(self):
+        super(GstPipelineTree, self).__init__("gst-pipeline-tree",
+                                              gdb.COMPLETE_SYMBOL)
+
+    def invoke(self, arg, from_tty):
+        self.dont_repeat()
+        args = gdb.string_to_argv(arg)
+        if len(args) != 1:
+            raise Exception("Usage: gst-pipeline-tree <gst-object>")
+
+        value = gdb.parse_and_eval(args[0])
+        if not value:
+            raise Exception("'%s' is not a valid object" % args[0])
+
+        value = gst_object_from_value(value)
+        value = gst_object_pipeline(value)
+        GdbGstElement(value).print_tree(0)
+
+
 GstDot()
 GstPrint()
+GstPipelineTree()
+
+
+class GstPipeline(gdb.Function):
+    """\
+Find the top-level pipeline for the given element"""
+
+    def __init__(self):
+        super(GstPipeline, self).__init__("gst_pipeline")
+
+    def invoke(self, arg):
+        value = gst_object_from_value(arg)
+        return gst_object_pipeline(value)
+
+
+class GstBinGet(gdb.Function):
+    """\
+Find a child element with the given name"""
+
+    def __init__(self):
+        super(GstBinGet, self).__init__("gst_bin_get")
+
+    def find(self, obj, name, recurse):
+        for child in obj.children():
+            if child.name() == name:
+                return child.val
+            if recurse:
+                result = self.find(child, name, recurse)
+                if result is not None:
+                    return result
+
+    def invoke(self, element, arg):
+        value = gst_object_from_value(element)
+        if not g_inherits_type(value, "GstElement"):
+            raise Exception("'%s' is not a GstElement" %
+                            str(value.address))
+
+        try:
+            name = arg.string()
+        except gdb.error:
+            raise Exception("Usage: $gst_bin_get(<gst-object>, \"<name>\")")
+
+        obj = GdbGstElement(value)
+        child = self.find(obj, name, False)
+        if child is None:
+            child = self.find(obj, name, True)
+        if child is None:
+            raise Exception("No child named '%s' found." % name)
+        return child
+
+
+class GstElementPad(gdb.Function):
+    """\
+Get the pad with the given name"""
+
+    def __init__(self):
+        super(GstElementPad, self).__init__("gst_element_pad")
+
+    def invoke(self, element, arg):
+        value = gst_object_from_value(element)
+        if not g_inherits_type(value, "GstElement"):
+            raise Exception("'%s' is not a GstElement" %
+                            str(value.address))
+
+        try:
+            name = arg.string()
+        except gdb.error:
+            raise Exception("Usage: $gst_element_pad(<gst-object>, \"<pad-name>\")")
+
+        obj = GdbGstElement(value)
+        for pad in obj.pads():
+            if pad.name() == name:
+                return pad.val
+
+        raise Exception("No pad named '%s' found." % name)
+
+
+GstPipeline()
+GstBinGet()
+GstElementPad()
 
 
 def register(obj):
     if obj is None:
         obj = gdb
 
-    # Make sure this is always used befor the glib lookup function.
+    # Make sure this is always used before the glib lookup function.
     # Otherwise the gobject pretty printer is used for GstObjects
     obj.pretty_printers.insert(0, gst_pretty_printer_lookup)
index 672ccba..b34423f 100644 (file)
@@ -29,9 +29,11 @@ elif host_system == 'windows'
   message('PTP not supported on Windows, not ported yet.')
 elif host_system == 'ios'
   message('PTP not supported on iOS because of permissions.')
-elif ['linux', 'darwin', 'netbsd', 'freebsd', 'openbsd', 'kfreebsd', 'dragonfly', 'solaris'].contains(host_system)
+elif ['linux', 'darwin', 'netbsd', 'freebsd', 'openbsd', 'kfreebsd', 'dragonfly', 'sunos', 'gnu', 'gnu/kfreebsd'].contains(host_system)
   message('PTP supported on ' + host_system + '.')
   have_ptp = true
+else
+  message('PTP not supported on ' + host_system + ', not ported yet.')
 endif
 
 if have_ptp
@@ -64,16 +66,8 @@ if have_ptp
       description : 'getifaddrs() and AF_LINK is available')
   endif
 
-  gst_ptp_have_cap = false
-  cap_dep = []
-  if cc.has_header('sys/capability.h')
-    cap_dep = cc.find_library('cap', required : false)
-    if cap_dep.found() and cc.has_function('cap_init', dependencies : cap_dep)
-      gst_ptp_have_cap = true
-    endif
-  endif
-
-  setcap = find_program('setcap', '/usr/sbin/setcap', '/sbin/setcap', required : false)
+  setcap_prog = find_program('setcap', '/usr/sbin/setcap', '/sbin/setcap', required : false)
+  cap_dep = dependency('libcap', required: false)
 
   # user/group to change to in gst-ptp-helper
   ptp_helper_setuid_user = get_option('ptp-helper-setuid-user')
@@ -90,7 +84,7 @@ if have_ptp
   # how to install gst-ptp-helper
   with_ptp_helper_permissions = get_option('ptp-helper-permissions')
   if with_ptp_helper_permissions == 'auto'
-    if gst_ptp_have_cap and setcap.found()
+    if setcap_prog.found() and cap_dep.found()
       with_ptp_helper_permissions = 'capabilities'
     else
       with_ptp_helper_permissions = 'setuid-root'
@@ -104,8 +98,10 @@ if have_ptp
     cdata.set('HAVE_PTP_HELPER_SETUID', 1,
         description : 'Use setuid-root for permissions in PTP helper')
   elif with_ptp_helper_permissions == 'capabilities'
-    if not setcap.found()
+    if not setcap_prog.found()
       error('capabilities-based ptp-helper-permissions requested, but could not find setcap tool.')
+    elif not cap_dep.found()
+      error('capabilities-based ptp-helper-permissions requested, but could not find libcap.')
     endif
     cdata.set('HAVE_PTP_HELPER_CAPABILITIES', 1,
         description : 'Use capabilities for permissions in PTP helper')
@@ -122,7 +118,7 @@ if have_ptp
 
   meson.add_install_script('ptp_helper_post_install.sh',
       helpers_install_dir, with_ptp_helper_permissions,
-      setcap.found() ? setcap.path() : '')
+      setcap_prog.found() ? setcap_prog.path() : '')
 endif
 
 install_data(['gst_gdb.py', 'glib_gobject_helper.py'],
index eefe1c9..4370acd 100644 (file)
@@ -20,6 +20,9 @@ case "$with_ptp_helper_permissions" in
     echo "Calling $setcap cap_net_bind_service,cap_net_admin+ep $ptp_helper"
     $setcap cap_net_bind_service,cap_net_admin+ep "$ptp_helper" || true
     ;;
+  none)
+    echo "No perms/caps to set for $ptp_helper"
+    ;;
   *)
     echo "$0 ERROR: unexpected permissions value '$with_ptp_helper_permissions'";
     exit 2;
diff --git a/libs/gst/net/.gitignore b/libs/gst/net/.gitignore
deleted file mode 100644 (file)
index cf19bd8..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-*.o
-*.lo
-*.la
diff --git a/libs/gst/net/Makefile.am b/libs/gst/net/Makefile.am
deleted file mode 100644 (file)
index c0eab7a..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-lib_LTLIBRARIES = libgstnet-@GST_API_VERSION@.la
-
-libgstnet_@GST_API_VERSION@_includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/net
-libgstnet_@GST_API_VERSION@_include_HEADERS = \
-    net.h \
-    net-prelude.h \
-    gstnet.h \
-    gstnetaddressmeta.h \
-    gstnetclientclock.h \
-    gstnetcontrolmessagemeta.h \
-    gstnettimepacket.h \
-    gstnettimeprovider.h \
-    gstptpclock.h
-
-libgstnet_@GST_API_VERSION@_la_SOURCES = \
-    gstnetaddressmeta.c \
-    gstnetclientclock.c \
-    gstnetcontrolmessagemeta.c \
-    gstnettimepacket.c \
-    gstnettimeprovider.c \
-    gstptpclock.c \
-    gstntppacket.c \
-    gstnetutils.c
-
-noinst_HEADERS = gstptp_private.h gstntppacket.h gstnetutils.h
-
-libgstnet_@GST_API_VERSION@_la_CFLAGS = $(GST_OBJ_CFLAGS) $(GIO_CFLAGS) -DBUILDING_GST_NET
-libgstnet_@GST_API_VERSION@_la_LIBADD = $(GST_OBJ_LIBS) $(GIO_LIBS) \
-       $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la
-libgstnet_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
-
-# try to prevent packaging errors
-check-libexecdir-consistency:
-       @if test "${GST_PTP_HELPER_INSTALLED}" != "${libexecdir}/gstreamer-$(GST_API_VERSION)/gst-ptp-helper"; then \
-         echo "*** Inconsistent libexecdir! Please use ./configure --libexecdir=/foo/bar"; \
-         echo "*** to set the libexecdir and not make libexecdir=/foo/bar or the like."; \
-         echo "*** The same goes for prefix, libdir etc."; \
-         echo "*** ${GST_PTP_HELPER_INSTALLED} != ${libexecdir}/gstreamer-$(GST_API_VERSION)/gst-ptp-helper"; \
-         exit 1; \
-       fi
-
-all-local: check-libexecdir-consistency
-
-CLEANFILES = *.gcno *.gcda *.gcov
-
-%.c.gcov: .libs/libgstnet_@GST_API_VERSION@_la-%.gcda %.c
-       $(GCOV) -b -f -o $^ > $@.out
-
-gcov: $(libgstnet_@GST_API_VERSION@_la_SOURCES:=.gcov)
-
-
-if HAVE_INTROSPECTION
-BUILT_GIRSOURCES = GstNet-@GST_API_VERSION@.gir
-
-gir_headers=$(patsubst %,$(srcdir)/%, $(libgstnet_@GST_API_VERSION@_include_HEADERS))
-gir_sources=$(patsubst %,$(srcdir)/%, $(libgstnet_@GST_API_VERSION@_la_SOURCES))
-gir_cincludes=--c-include="gst/net/net.h"
-
-GstNet-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstnet-@GST_API_VERSION@.la
-       $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" GI_SCANNER_DISABLE_CACHE=yes\
-               GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_DISABLE=yes \
-               CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" PKG_CONFIG="$(PKG_CONFIG)" DLLTOOL="$(DLLTOOL)" \
-               $(INTROSPECTION_SCANNER) -v --namespace GstNet \
-               --identifier-prefix=Gst \
-               --symbol-prefix=gst \
-               --warn-all \
-               --nsversion=@GST_API_VERSION@ \
-               -I$(top_srcdir) \
-               -I$(top_srcdir)/libs \
-               -I$(top_builddir) \
-               -I$(top_builddir)/libs \
-               $(gir_cincludes) \
-               --add-include-path=$(top_builddir)/gst \
-               --library-path=$(top_builddir)/gst \
-               --library=libgstnet-@GST_API_VERSION@.la \
-               --include=Gst-@GST_API_VERSION@ \
-               --include=Gio-2.0 \
-               --libtool="${LIBTOOL}" \
-               --pkg gstreamer-@GST_API_VERSION@ \
-               --pkg gio-2.0 \
-               --pkg-export="gstreamer-net-@GST_API_VERSION@" \
-               --add-init-section="$(INTROSPECTION_INIT)" \
-               --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
index 262c578..9867cac 100644 (file)
@@ -72,7 +72,7 @@ net_address_meta_free (GstMeta * meta, GstBuffer * buffer)
 GType
 gst_net_address_meta_api_get_type (void)
 {
-  static volatile GType type;
+  static GType type;
   static const gchar *tags[] = { "origin", NULL };
 
   if (g_once_init_enter (&type)) {
index e0a04d2..13ff013 100644 (file)
@@ -677,7 +677,7 @@ gst_net_client_internal_clock_thread (gpointer data)
         /* before next sending check if need to change QoS */
         new_qos_dscp = self->qos_dscp;
         if (cur_qos_dscp != new_qos_dscp &&
-            gst_net_utils_set_socket_dscp (socket, new_qos_dscp)) {
+            gst_net_utils_set_socket_tos (socket, new_qos_dscp)) {
           GST_DEBUG_OBJECT (self, "changed QoS DSCP to: %d", new_qos_dscp);
           cur_qos_dscp = new_qos_dscp;
         }
@@ -1415,7 +1415,7 @@ gst_net_client_clock_get_internal_time (GstClock * clock)
  * @remote_port: the port of the remote clock provider
  * @base_time: initial time of the clock
  *
- * Create a new #GstNetClientInternalClock that will report the time
+ * Create a new #GstNetClientClock that will report the time
  * provided by the #GstNetTimeProvider on @remote_address and
  * @remote_port.
  *
index b741e6b..506270c 100644 (file)
@@ -97,13 +97,9 @@ GST_NET_API
 GstClock*      gst_ntp_clock_new               (const gchar *name, const gchar *remote_address,
                                                  gint remote_port, GstClockTime base_time);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstNetClientClock, gst_object_unref)
-#endif
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstNtpClock, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 4f24834..f4d2a29 100644 (file)
@@ -75,7 +75,7 @@ net_control_message_meta_free (GstMeta * meta, GstBuffer * buffer)
 GType
 gst_net_control_message_meta_api_get_type (void)
 {
-  static volatile GType type;
+  static GType type;
   static const gchar *tags[] = { "origin", NULL };
 
   if (g_once_init_enter (&type)) {
index a04ea03..a8f2f66 100644 (file)
@@ -73,9 +73,7 @@ gboolean                gst_net_time_packet_send        (const GstNetTimePacket
                                                          GSocketAddress         * dest_address,
                                                          GError                ** error);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstNetTimePacket, gst_net_time_packet_free)
-#endif
 
 G_END_DECLS
 
index d323bf4..1df6959 100644 (file)
@@ -214,7 +214,7 @@ gst_net_time_provider_thread (gpointer data)
     /* before next sending check if need to change QoS */
     new_qos_dscp = self->priv->qos_dscp;
     if (cur_qos_dscp != new_qos_dscp &&
-        gst_net_utils_set_socket_dscp (socket, new_qos_dscp)) {
+        gst_net_utils_set_socket_tos (socket, new_qos_dscp)) {
       GST_DEBUG_OBJECT (self, "changed QoS DSCP to: %d", new_qos_dscp);
       cur_qos_dscp = new_qos_dscp;
     }
@@ -252,7 +252,7 @@ gst_net_time_provider_set_property (GObject * object, guint prop_id,
       if (g_value_get_string (value) == NULL)
         self->priv->address = g_strdup (DEFAULT_ADDRESS);
       else
-        self->priv->address = g_strdup (g_value_get_string (value));
+        self->priv->address = g_value_dup_string (value);
       break;
     case PROP_CLOCK:
       gst_object_replace ((GstObject **) clock_p,
index d1f6de3..40eeef3 100644 (file)
@@ -71,9 +71,7 @@ GstNetTimeProvider*     gst_net_time_provider_new       (GstClock *clock,
                                                          const gchar *address,
                                                          gint port);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstNetTimeProvider, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index a8a99d9..3390e7d 100644 (file)
  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
  * Boston, MA 02110-1301, USA.
  */
+/**
+ * SECTION:gstnetutils
+ * @title: GstNetUtils
+ * @short_description: Network utility functions.
+ *
+ * GstNetUtils gathers network utility functions, enabling use for all
+ * gstreamer plugins.
+ *
+ * Since: 1.18
+ *
+ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 /**
- * gst_net_time_packet_util_set_dscp:
+ * gst_net_utils_set_socket_tos:
  * @socket: Socket to configure
  * @qos_dscp: QoS DSCP value
  *
  * Configures IP_TOS value of socket, i.e. sets QoS DSCP.
  *
  * Returns: TRUE if successful, FALSE in case an error occurred.
+ *
+ * Since: 1.18
  */
 gboolean
-gst_net_utils_set_socket_dscp (GSocket * socket, gint qos_dscp)
+gst_net_utils_set_socket_tos (GSocket * socket, gint qos_dscp)
 {
   gboolean ret = FALSE;
 
@@ -60,6 +73,15 @@ gst_net_utils_set_socket_dscp (GSocket * socket, gint qos_dscp)
   } else {
     ret = TRUE;
   }
+#ifdef IPV6_TCLASS
+  if (g_socket_get_family (socket) == G_SOCKET_FAMILY_IPV6) {
+    if (setsockopt (fd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof (tos)) < 0) {
+      GST_ERROR ("could not set TCLASS: %s", g_strerror (errno));
+    } else {
+      ret = TRUE;
+    }
+  }
+#endif
 #endif
 
   return ret;
index 053f187..d2b4043 100644 (file)
 
 #include <glib.h>
 #include <gio/gio.h>
+#include <gst/net/net-prelude.h>
 
 G_BEGIN_DECLS
 
-G_GNUC_INTERNAL
-gboolean    gst_net_utils_set_socket_dscp (GSocket  * socket,
-                                           gint       qos_dscp);
+GST_NET_API
+gboolean    gst_net_utils_set_socket_tos (GSocket  * socket,
+                                          gint       qos_dscp);
 
 G_END_DECLS
 
index c2d0915..19b90e5 100644 (file)
@@ -772,6 +772,7 @@ select_best_master_clock (PtpDomainData * domain, GstClockTime now)
     if (!best || compare_announce_message (msg, best) < 0)
       best = msg;
   }
+  g_clear_pointer (&qualified_messages, g_list_free);
 
   if (domain->have_master_clock
       && compare_clock_identity (&domain->master_clock_identity,
index 06ca5cf..3182431 100644 (file)
@@ -153,9 +153,7 @@ GST_NET_API
 GstClock*       gst_ptp_clock_new                  (const gchar *name,
                                                     guint domain);
 
-#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPtpClock, gst_object_unref)
-#endif
 
 G_END_DECLS
 
index 1e63164..f63ae28 100644 (file)
@@ -16,6 +16,7 @@ gst_net_headers = [
  'gstnetcontrolmessagemeta.h',
  'gstnettimepacket.h',
  'gstnettimeprovider.h',
+ 'gstnetutils.h',
  'gstptpclock.h',
  'net-prelude.h',
  'net.h',
@@ -34,6 +35,14 @@ gst_net = library('gstnet-@0@'.format(apiversion),
   dependencies : [gio_dep, gst_base_dep],
 )
 
+pkgconfig.generate(gst_net,
+  libraries : [libgst],
+  variables : pkgconfig_variables,
+  subdirs : pkgconfig_subdirs,
+  name : 'gstreamer-net-1.0',
+  description : 'Network-enabled GStreamer plug-ins and clocking',
+)
+
 if build_gir
   gst_gir_extra_args = gir_init_section + [ '--c-include=gst/net/net.h' ]
   gst_net_gir = gnome.generate_gir(gst_net,
@@ -56,3 +65,5 @@ gst_net_dep = declare_dependency(link_with : gst_net,
   include_directories : [libsinc],
   sources: gst_net_gen_sources,
   dependencies : [gst_base_dep])
+
+meson.override_dependency('gstreamer-net-1.0', gst_net_dep)
index 2575af5..4a11a94 100644 (file)
@@ -30,6 +30,7 @@
 #include <gst/net/gstnetclientclock.h>
 #include <gst/net/gstnettimepacket.h>
 #include <gst/net/gstnettimeprovider.h>
+#include <gst/net/gstnetutils.h>
 #include <gst/net/gstptpclock.h>
 
 #endif /* __GST_NET__H__ */
diff --git a/m4/.gitignore b/m4/.gitignore
deleted file mode 100644 (file)
index 588dd02..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-codeset.m4
-gettext.m4
-glibc*.m4
-iconv.m4
-intdiv0.m4
-intl.m4
-intldir.m4
-intlmacosx.m4
-intmax.m4
-inttypes-pri.m4
-inttypes.m4
-inttypes_h.m4
-isc-posix.m4
-lcmessage.m4
-lib-ld.m4
-lib-link.m4
-lib-prefix.m4
-libtool.m4
-lock.m4
-longlong.m4
-ltoptions.m4
-ltsugar.m4
-ltversion.m4
-lt~obsolete.m4
-nls.m4
-po.m4
-printf-posix.m4
-progtest.m4
-size_max.m4
-stdint_h.m4
-uintmax_t.m4
-ulonglong.m4
-visibility.m4
-wchar_t.m4
-wint_t.m4
-xsize.m4
diff --git a/m4/Makefile.am b/m4/Makefile.am
deleted file mode 100644 (file)
index af864e3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-EXTRA_DIST = $(wildcard *.m4)
diff --git a/m4/check-checks.m4 b/m4/check-checks.m4
deleted file mode 100644 (file)
index 44baca4..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-dnl Check for things that check needs/wants and that we don't check for already
-dnl AM_GST_CHECK_CHECKS()
-
-AC_DEFUN([AG_GST_CHECK_CHECKS],
-[
-AC_MSG_NOTICE([Running check unit test framework checks now...])
-
-CHECK_MAJOR_VERSION=0
-CHECK_MINOR_VERSION=10
-CHECK_MICRO_VERSION=0
-CHECK_VERSION=$CHECK_MAJOR_VERSION.$CHECK_MINOR_VERSION.$CHECK_MICRO_VERSION
-
-AC_SUBST(CHECK_MAJOR_VERSION)
-AC_SUBST(CHECK_MINOR_VERSION)
-AC_SUBST(CHECK_MICRO_VERSION)
-AC_SUBST(CHECK_VERSION)
-
-dnl Checks for header files and declarations
-AC_CHECK_HEADERS([unistd.h sys/wait.h sys/time.h], [], [], [AC_INCLUDES_DEFAULT])
-
-dnl Check for localtime_r()
-AC_CHECK_FUNCS([localtime_r])
-AM_CONDITIONAL(HAVE_LOCALTIME_R, test "x$ac_cv_func_localtime_r" = "xyes")
-
-dnl Check for gettimeofday()
-AC_CHECK_FUNCS([gettimeofday])
-AM_CONDITIONAL(HAVE_GETTIMEOFDAY, test "x$ac_cv_func_gettimeofday" = "xyes")
-
-dnl Check for getpid() and _getpid()
-AC_CHECK_FUNCS([getpid _getpid])
-
-dnl Check for strdup() and _strdup()
-AC_CHECK_DECLS([strdup])
-AC_CHECK_FUNCS([_strdup])
-AM_CONDITIONAL(HAVE_STRDUP, test "x$ac_cv_have_decl_strdup" = "xyes" -o "x$ac_cv_func__strdup" = "xyes")
-
-dnl Check for getline()
-AC_CHECK_FUNCS([getline])
-AM_CONDITIONAL(HAVE_GETLINE, test "x$ac_cv_func_getline" = "xyes")
-
-dnl Check for mkstemp
-AC_CHECK_FUNCS([mkstemp])
-
-dnl Check for fork
-AC_CHECK_FUNCS([fork], HAVE_FORK=1, HAVE_FORK=0)
-AC_SUBST(HAVE_FORK)
-
-dnl Check for alarm, localtime_r and strsignal
-dnl First check for time.h as it might be used by localtime_r
-AC_CHECK_HEADERS([time.h])
-AC_CHECK_DECLS([alarm, localtime_r, strsignal], [], [], [
-    AC_INCLUDES_DEFAULT
-#if HAVE_TIME_H
-#include <time.h>
-#endif /* HAVE_TIME_H */
-])
-AC_CHECK_FUNCS([alarm setitimer strsignal])
-AM_CONDITIONAL(HAVE_ALARM, test "x$ac_cv_func_alarm" = "xyes")
-AM_CONDITIONAL(HAVE_LOCALTIME_R, test "x$ac_cv_func_localtime_r" = "xyes")
-AM_CONDITIONAL(HAVE_STRSIGNAL, test "x$ac_cv_func_strsignal" = "xyes")
-
-dnl Check if struct timespec/itimerspec are defined in time.h. If not, we need
-dnl to define it in libs/gst/check/libcheck/libcompat.h. Note the optional
-dnl inclusion of pthread.h. On MinGW(-w64), the pthread.h file contains the
-dnl timespec/itimerspec definitions.
-AC_CHECK_MEMBERS([struct timespec.tv_sec, struct timespec.tv_nsec], [],
-  [AC_DEFINE_UNQUOTED(STRUCT_TIMESPEC_DEFINITION_MISSING, 1,
-    [Need to define the timespec structure])], [
-#include <time.h>
-#if HAVE_PTHREAD
-#include <pthread.h>
-#endif /* HAVE_PTHREAD */
-])
-AC_CHECK_MEMBERS([struct itimerspec.it_interval, struct itimerspec.it_value],
-  [], [AC_DEFINE_UNQUOTED(STRUCT_ITIMERSPEC_DEFINITION_MISSING, 1,
-    [Need to define the itimerspec structure])], [
-#include <time.h>
-#if HAVE_PTHREAD
-#include <pthread.h>
-#endif /* HAVE_PTHREAD */
-])
-
-dnl Check if types timer_t/clockid_t are defined. If not, we need to define it
-dnl in libs/gst/check/libcheck/libcompat/libcompat.h. Note the optional
-dnl inclusion of pthread.h. On MinGW(-w64), the pthread.h file contains the
-dnl timer_t/clockid_t definitions.
-AC_CHECK_TYPE(timer_t, [], [
-    AC_DEFINE([timer_t], [int], [timer_t])
-  ], [
-    AC_INCLUDES_DEFAULT
-#if HAVE_PTHREAD
-#include <pthread.h>
-#endif /* HAVE_PTHREAD */
-])
-AC_CHECK_TYPE(clockid_t, [], [
-    AC_DEFINE([clockid_t], [int], [clockid_t])
-  ], [
-    AC_INCLUDES_DEFAULT
-#if HAVE_PTHREAD
-#include <pthread.h>
-#endif /* HAVE_PTHREAD */
-])
-
-dnl Check for POSIX timer functions in librt
-AC_CHECK_LIB([rt], [timer_create, timer_settime, timer_delete])
-AM_CONDITIONAL(HAVE_TIMER_CREATE_SETTIME_DELETE, test "x$ac_cv_lib_rt_timer_create__timer_settime__timer_delete" = "xyes")
-
-dnl Allow for checking HAVE_CLOCK_GETTIME in automake files
-AM_CONDITIONAL(HAVE_CLOCK_GETTIME, test "x$CLOCK_GETTIME_FOUND" = "xyes")
-
-dnl Create _stdint.h in the top-level directory
-AX_CREATE_STDINT_H
-
-dnl Disable subunit support for the time being
-enable_subunit=false
-
-if test xfalse = x"$enable_subunit"; then
-ENABLE_SUBUNIT="0"
-else
-ENABLE_SUBUNIT="1"
-fi
-AC_SUBST(ENABLE_SUBUNIT)
-AC_DEFINE_UNQUOTED(ENABLE_SUBUNIT, $ENABLE_SUBUNIT, [Subunit protocol result output])
-
-AM_CONDITIONAL(SUBUNIT, test x"$enable_subunit" != "xfalse")
-
-])
index 0442535..bed8c4e 100644 (file)
@@ -1,6 +1,6 @@
 project('gstreamer', 'c',
-  version : '1.16.2',
-  meson_version : '>= 0.47',
+  version : '1.19.2',
+  meson_version : '>= 0.54',
   default_options : [ 'warning_level=1',
                       'buildtype=debugoptimized' ])
 
@@ -28,6 +28,7 @@ osxversion = curversion + 1
 
 prefix = get_option('prefix')
 
+datadir = join_paths(prefix, get_option('datadir'))
 libexecdir = get_option('libexecdir')
 helpers_install_dir = join_paths(libexecdir, 'gstreamer-1.0')
 
@@ -35,18 +36,24 @@ cc = meson.get_compiler('c')
 
 cdata = configuration_data()
 
-# Ignore several spurious warnings for things gstreamer does very commonly
-# If a warning is completely useless and spammy, use '/wdXXXX' to suppress it
-# If a warning is harmless but hard to fix, use '/woXXXX' so it's shown once
-# NOTE: Only add warnings here if you are sure they're spurious
 if cc.get_id() == 'msvc'
-  add_project_arguments(
+  msvc_args = [
+      # Ignore several spurious warnings for things gstreamer does very commonly
+      # If a warning is completely useless and spammy, use '/wdXXXX' to suppress it
+      # If a warning is harmless but hard to fix, use '/woXXXX' so it's shown once
+      # NOTE: Only add warnings here if you are sure they're spurious
       '/wd4018', # implicit signed/unsigned conversion
       '/wd4146', # unary minus on unsigned (beware INT_MIN)
       '/wd4244', # lossy type conversion (e.g. double -> int)
       '/wd4305', # truncating type conversion (e.g. double -> float)
       cc.get_supported_arguments(['/utf-8']), # set the input encoding to utf-8
-      language : 'c')
+
+      # Enable some warnings on MSVC to match GCC/Clang behaviour
+      '/w14062', # enumerator 'identifier' in switch of enum 'enumeration' is not handled
+      '/w14101', # 'identifier' : unreferenced local variable
+      '/w14189', # 'identifier' : local variable is initialized but not referenced
+  ]
+  add_project_arguments(msvc_args, language: 'c')
 elif cc.has_link_argument('-Wl,-Bsymbolic-functions')
   # FIXME: Add an option for this if people ask for it
   add_project_link_arguments('-Wl,-Bsymbolic-functions', language : 'c')
@@ -97,7 +104,7 @@ if glib_checks.disabled() or (glib_checks.auto() and not gst_version_is_dev)
 endif
 
 cdata.set_quoted('GST_API_VERSION', apiversion)
-cdata.set_quoted('GST_DATADIR', join_paths(prefix, get_option('datadir')))
+cdata.set_quoted('GST_DATADIR', datadir)
 cdata.set_quoted('LOCALEDIR', join_paths(prefix, get_option('localedir')))
 cdata.set_quoted('LIBDIR', join_paths(prefix, get_option('libdir')))
 cdata.set_quoted('GST_API_VERSION', '1.0')
@@ -107,7 +114,7 @@ cdata.set_quoted('PACKAGE', 'gstreamer')
 cdata.set_quoted('PACKAGE_NAME', 'GStreamer')
 cdata.set_quoted('PACKAGE_STRING', 'GStreamer @0@'.format(gst_version))
 cdata.set_quoted('PACKAGE_TARNAME', 'gstreamer')
-cdata.set_quoted('PACKAGE_BUGREPORT', 'http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer')
+cdata.set_quoted('PACKAGE_BUGREPORT', 'https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/new')
 cdata.set_quoted('PACKAGE_URL', '')
 cdata.set_quoted('PACKAGE_VERSION', gst_version)
 cdata.set_quoted('PLUGINDIR', join_paths(get_option('prefix'), get_option('libdir'), 'gstreamer-1.0'))
@@ -171,7 +178,7 @@ host_defines = [
   [ 's390', 'HAVE_CPU_S390' ],
 ]
 foreach h : host_defines
-  if h.get(0) == host_machine.cpu()
+  if h.get(0) == host_machine.cpu_family()
     cdata.set(h.get(1), 1)
   endif
 endforeach
@@ -199,8 +206,8 @@ check_headers = [
   'sys/wait.h',
   'ucontext.h',
   'unistd.h',
-  'valgrind/valgrind.h',
   'sys/resource.h',
+  'sys/uio.h',
 ]
 
 if host_system == 'windows'
@@ -229,6 +236,8 @@ check_functions = [
   'pselect',
   'getpagesize',
   'clock_gettime',
+  'clock_nanosleep',
+  'strnlen',
   # These are needed by libcheck
   'getline',
   'mkstemp',
@@ -255,8 +264,25 @@ if cc.links('''#include <pthread.h>
                }''', name : 'pthread_setname_np(const char*)')
   cdata.set('HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID', 1)
 endif
+if cc.has_header_symbol('pthread.h', 'pthread_condattr_setclock')
+  cdata.set('HAVE_PTHREAD_CONDATTR_SETCLOCK', 1)
+endif
+if cc.has_header_symbol('pthread.h', 'pthread_cond_timedwait_relative_np')
+  cdata.set('HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP', 1)
+endif
 
-# Check for posix timers and the monotonic clock
+# Check for futex(2)
+if cc.links('''#include <linux/futex.h>
+               #include <sys/syscall.h>
+               #include <unistd.h>
+               int main (int argc, char ** argv) {
+                 syscall (__NR_futex, NULL, FUTEX_WAKE, FUTEX_WAIT);
+                 return 0;
+               }''', name : 'futex(2) system call')
+  cdata.set('HAVE_FUTEX', 1)
+endif
+
+# Check for posix timers and monotonic clock
 time_prefix = '#include <time.h>\n'
 if cdata.has('HAVE_UNISTD_H')
   time_prefix += '#include <unistd.h>'
@@ -347,24 +373,54 @@ if host_system == 'windows'
   platform_deps = [cc.find_library('ws2_32')]
 endif
 
+building_for_uwp = false
+if host_system == 'windows'
+  # Check whether we're building for UWP apps
+  code = '''
+  #include <windows.h>
+  #if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
+  #error "Not building for UWP"
+  #endif'''
+  if cc.compiles(code, name : 'building for UWP')
+    building_for_uwp = true
+  endif
+endif
+
 backtrace_deps = []
 unwind_dep = dependency('libunwind', required : get_option('libunwind'))
 dw_dep = dependency('libdw', required: get_option('libdw'))
-dbghelp_dep = dependency('DbgHelp', required : get_option('dbghelp'))
-backtrace_deps = [unwind_dep, dw_dep, dbghelp_dep]
-if unwind_dep.found()
+dbghelp_option = get_option('dbghelp')
+if dbghelp_option.enabled() and building_for_uwp
+  error('DbgHelp is not supported for UWP')
+endif
+have_dbghelp = cc.has_header('dbghelp.h', required: dbghelp_option) and cc.has_header('tlhelp32.h', required: dbghelp_option)
+backtrace_deps = [unwind_dep, dw_dep]
+backtrace_source_info = false
+backtrace_minimal = false
+# MSVC debug stack trace support
+if host_system == 'windows' and have_dbghelp and not building_for_uwp
+  cdata.set('HAVE_DBGHELP', 1)
+  backtrace_source_info = true
+# DWARF stack trace support with libunwind and elf-utils
+elif unwind_dep.found()
   cdata.set('HAVE_UNWIND', 1)
   if dw_dep.found()
     cdata.set('HAVE_DW', 1)
-  else
-    message('Support for backtraces is partial only.')
+    backtrace_source_info = true
   endif
+  backtrace_minimal = true
+# Basic backtrace() stack trace support
 elif cc.has_function('backtrace')
   cdata.set('HAVE_BACKTRACE', 1)
-elif dbghelp_dep.found()
-  cdata.set('HAVE_DBGHELP', 1)
-else
-  message('NO backtraces support.')
+  backtrace_minimal = true
+endif
+# Print messages about what was enabled
+if not backtrace_source_info
+  if not backtrace_minimal
+    message('NO support for stack traces.')
+  else
+    message('Minimal support for stack traces, no source info.')
+  endif
 endif
 
 if cc.has_header('execinfo.h')
@@ -421,7 +477,7 @@ test_deps = [gmp_dep, gsl_dep, gslcblas_dep]
 # Used by gstinfo.c
 dl_dep = cc.find_library('dl', required : false)
 cdata.set('HAVE_DLADDR', cc.has_function('dladdr', dependencies : dl_dep))
-cdata.set('GST_ENABLE_EXTRA_CHECKS', get_option('extra-checks'))
+cdata.set('GST_ENABLE_EXTRA_CHECKS', not get_option('extra-checks').disabled())
 cdata.set('USE_POISONING', get_option('poisoning'))
 
 configinc = include_directories('.')
@@ -429,7 +485,7 @@ libsinc = include_directories('libs')
 privinc = include_directories('gst')
 
 # Find dependencies
-glib_dep = dependency('glib-2.0', version : '>=2.40.0',
+glib_dep = dependency('glib-2.0', version : '>=2.56.0',
   fallback: ['glib', 'libglib_dep'])
 gobject_dep = dependency('gobject-2.0',
   fallback: ['glib', 'libgobject_dep'])
@@ -453,7 +509,7 @@ rt_lib = cc.find_library('rt', required : false)
 gir = find_program('g-ir-scanner', required : get_option('introspection'))
 gnome = import('gnome')
 
-build_gir = gir.found() and not meson.is_cross_build()
+build_gir = gir.found() and (not meson.is_cross_build() or get_option('introspection').enabled())
 
 gir_init_section = [ '--add-init-section=extern void gst_init(gint*,gchar**);' + \
     'g_setenv("GST_REGISTRY_DISABLE", "yes", TRUE);' + \
@@ -482,7 +538,8 @@ bash_helpers_dir = ''
 bashcomp_found = false
 if bashcomp_dep.found()
   bashcomp_found = true
-  bash_completions_dir = bashcomp_dep.get_pkgconfig_variable('completionsdir', define_variable: ['prefix', '.'])
+  bashcomp_dir_override = bashcomp_dep.version().version_compare('>= 2.10') ? ['datadir', datadir] : ['prefix', prefix]
+  bash_completions_dir = bashcomp_dep.get_pkgconfig_variable('completionsdir', define_variable: bashcomp_dir_override)
   if bash_completions_dir == ''
     msg = 'Found bash-completion but the .pc file did not set \'completionsdir\'.'
     if bashcomp_option.enabled()
@@ -493,7 +550,7 @@ if bashcomp_dep.found()
     bashcomp_found = false
   endif
 
-  bash_helpers_dir = bashcomp_dep.get_pkgconfig_variable('helpersdir', define_variable: ['prefix', '.'])
+  bash_helpers_dir = bashcomp_dep.get_pkgconfig_variable('helpersdir', define_variable: bashcomp_dir_override)
   if bash_helpers_dir == ''
     msg = 'Found bash-completion, but the .pc file did not set \'helpersdir\'.'
     if bashcomp_option.enabled()
@@ -513,6 +570,20 @@ if get_option('default_library') == 'shared'
   # If we don't build static plugins there is no need to generate pc files
   plugins_pkgconfig_install_dir = disabler()
 endif
+pkgconfig_variables = ['exec_prefix=${prefix}',
+    'toolsdir=${exec_prefix}/bin',
+    'pluginsdir=${libdir}/gstreamer-1.0',
+    'datarootdir=${prefix}/share',
+    'datadir=${datarootdir}',
+    'girdir=${datadir}/gir-1.0',
+    'typelibdir=${libdir}/girepository-1.0',
+    'libexecdir=${prefix}/libexec',
+    'pluginscannerdir=${libexecdir}/gstreamer-1.0']
+pkgconfig_uninstalled_variables = ['exec_prefix=${prefix}',
+       'gstreamerdir=${prefix}/subprojects/gstreamer',
+    'bashhelpersdir=${gstreamerdir}/data/bash-completion/helpers',
+    'helpersdir=${gstreamerdir}/libs/gst/helpers']
+pkgconfig_subdirs = ['gstreamer-1.0']
 
 subdir('gst')
 subdir('libs')
@@ -520,9 +591,9 @@ subdir('plugins')
 if not get_option('tools').disabled()
   subdir('tools')
 endif
-subdir('pkgconfig')
 subdir('tests')
 subdir('data')
+subdir('docs')
 
 # xgettext is optional (on Windows for instance)
 if find_program('xgettext', required : get_option('nls')).found()
@@ -530,18 +601,37 @@ if find_program('xgettext', required : get_option('nls')).found()
   subdir('po')
 endif
 
-configure_file(output : 'config.h', configuration : cdata)
+subdir('scripts')
 
-if build_machine.system() == 'windows'
-  message('Disabling gtk-doc while building on Windows')
-else
-  if find_program('gtkdoc-scan', required : get_option('gtk_doc')).found()
-    subdir('docs')
+# Set release date
+if gst_version_nano == 0
+  extract_release_date = find_program('scripts/extract-release-date-from-doap-file.py')
+  run_result = run_command(extract_release_date, gst_version, files('gstreamer.doap'))
+  if run_result.returncode() == 0
+    release_date = run_result.stdout().strip()
+    cdata.set_quoted('GST_PACKAGE_RELEASE_DATETIME', release_date)
+    message('Package release date: ' + release_date)
   else
-    message('Not building documentation as gtk-doc was not found')
+    # Error out if our release can't be found in the .doap file
+    error(run_result.stderr())
   endif
 endif
 
+configure_file(output : 'config.h', configuration : cdata)
 run_command(python3, '-c', 'import shutil; shutil.copy("hooks/pre-commit.hook", ".git/hooks/pre-commit")')
-
 install_data('gst-element-check-1.0.m4', install_dir : join_paths(get_option('datadir'), 'aclocal'))
+
+if meson.version().version_compare('>= 0.54')
+  plugin_names = []
+  foreach plugin: plugins
+    # FIXME: Use str.subtring() when we can depend on Meson 0.56
+    split = plugin.name().split('gst')
+    if split.length() == 2
+      plugin_names += [split[1]]
+    else
+      warning('Need substring API in meson >= 0.56 to properly parse plugin name: ' + plugin.name())
+      plugin_names += [plugin.name()]
+    endif
+  endforeach
+  summary({'Plugins':plugin_names}, list_sep: ', ')
+endif
index e7ff7ba..7363bdb 100644 (file)
@@ -2,14 +2,13 @@ option('gst_debug', type : 'boolean', value : true)
 option('gst_parse', type : 'boolean', value : true,
        description: 'Enable pipeline string parser')
 option('registry', type : 'boolean', value : true)
-option('tracer_hooks', type : 'boolean', value : true)
+option('tracer_hooks', type : 'boolean', value : true, description: 'Enable tracer usage')
 option('ptp-helper-setuid-user', type : 'string',
        description : 'User to switch to when installing gst-ptp-helper setuid root')
 option('ptp-helper-setuid-group', type : 'string',
        description : 'Group to switch to when installing gst-ptp-helper setuid root')
 option('ptp-helper-permissions', type : 'combo',
        choices : ['none', 'setuid-root', 'capabilities', 'auto'], value : 'auto')
-option('extra-checks', type : 'boolean', value : true, description : 'Enable extra runtime checks')
 option('option-parsing', type : 'boolean', value : true,
        description: 'Enable command line option parsing')
 option('poisoning', type : 'boolean', value : false, description : 'Enable poisoning of deallocated objects')
@@ -23,13 +22,13 @@ option('libunwind', type : 'feature', value : 'auto', description : 'Use libunwi
 option('libdw', type : 'feature', value : 'auto', description : 'Use libdw to generate better backtraces from libunwind')
 option('dbghelp', type : 'feature', value : 'auto', description : 'Use dbghelp to generate backtraces')
 option('bash-completion', type : 'feature', value : 'auto', description : 'Install bash completion files')
+option('coretracers', type : 'feature', value : 'auto', description : 'Build coretracers plugin')
 
 # Common feature options
 option('examples', type : 'feature', value : 'auto', yield : true)
 option('tests', type : 'feature', value : 'auto', yield : true)
 option('benchmarks', type : 'feature', value : 'auto', yield : true)
 option('tools', type : 'feature', value : 'auto', yield : true)
-option('gtk_doc', type : 'feature', value : 'auto', yield : true, description : 'Generate API documentation with gtk-doc')
 option('introspection', type : 'feature', value : 'auto', yield : true, description : 'Generate gobject-introspection bindings')
 option('nls', type : 'feature', value : 'auto', yield: true, description : 'Enable native language support (translations)')
 option('gobject-cast-checks', type : 'feature', value : 'auto', yield : true,
@@ -38,9 +37,12 @@ option('glib-asserts', type : 'feature', value : 'enabled', yield : true,
        description: 'Enable GLib assertion (auto = enabled for development, disabled for stable releases)')
 option('glib-checks', type : 'feature', value : 'enabled', yield : true,
        description: 'Enable GLib checks such as API guards (auto = enabled for development, disabled for stable releases)')
+option('extra-checks', type : 'feature', value : 'enabled', yield : true, description : 'Enable extra runtime checks')
 
 # Common options
 option('package-name', type : 'string', yield : true,
        description : 'package name to use in plugins')
 option('package-origin', type : 'string', value : 'Unknown package origin', yield : true,
        description : 'package origin URL to use in plugins')
+option('doc', type : 'feature', value : 'auto', yield: true,
+       description: 'Enable documentation.')
index 5a126f9..39e489c 100644 (file)
@@ -1,14 +1,15 @@
 %define gst_branch 1.0
 
 Name:           gstreamer
-Version:        1.16.2
-Release:        5
+Version:        1.19.2
+Release:        0
 Summary:        Streaming-Media Framework Runtime
 License:        LGPL-2.0+
 Group:          Multimedia/Framework
 Url:            http://gstreamer.freedesktop.org/
 Source0:        http://gstreamer.freedesktop.org/src/gstreamer/gstreamer-%{version}.tar.xz
 Source100:      common.tar.gz
+BuildRequires:  meson >= 0.48.0
 BuildRequires:  bison
 BuildRequires:  gettext-tools
 BuildRequires:  check-devel
@@ -61,10 +62,6 @@ to develop applications that require these.
 %setup -q -T -D -a 100
 
 %build
-# FIXME: GTKDOC_CFLAGS, GST_OBJ_CFLAGS:
-# Silently ignored compilation of uninstalled gtk-doc scanners without RPM_OPT_FLAGS.
-export V=1
-NOCONFIGURE=1 ./autogen.sh
 export CFLAGS="%{optflags} \
        -DTIZEN_FEATURE_QUEUE2_MODIFICATION\
        -DTIZEN_FEATURE_FILESINK_MODIFICATION\
@@ -87,25 +84,18 @@ export CFLAGS="%{optflags} \
        -Wl,-z,relro\
        -D_FORTIFY_SOURCE=2"
 
-%configure\
-%if %{with introspection}
-        --enable-introspection\
-%endif
-        --disable-static\
-        --disable-docbook\
-        --disable-gtk-doc\
-        --enable-dlog\
-%if "%{tizen_profile_name}" == "tv"
-        --enable-tv-profile\
-%endif
-        --disable-examples\
-        --disable-tests\
-        --with-ptp-helper-permissions=none
+%meson --auto-feature=auto \
+  -D bash-completion=disabled \
+  -D check=disabled \
+  -D examples=disabled \
+  -D tests=disabled \
+  -D doc=disabled \
+  -D ptp-helper-permissions=none
 
-make %{?_smp_mflags}
+%meson_build
 
 %install
-%make_install
+%meson_install
 mkdir -p %{buildroot}%{_datadir}/gstreamer-%{gst_branch}/presets
 mkdir -p %{buildroot}%{_docdir}/%{name}
 %find_lang %{name}-%{gst_branch}
@@ -135,7 +125,7 @@ mkdir -p %{buildroot}%{_datadir}/gstreamer-%{gst_branch}/presets
 %{_libdir}/*.so.*
 %{_libdir}/girepository-1.0/Gst-1.0.typelib
 %{_libdir}/girepository-1.0/GstBase-1.0.typelib
-%{_libdir}/girepository-1.0/GstCheck-1.0.typelib
+#%{_libdir}/girepository-1.0/GstCheck-1.0.typelib
 %{_libdir}/girepository-1.0/GstController-1.0.typelib
 %{_libdir}/girepository-1.0/GstNet-1.0.typelib
 %{_datadir}/gdb/auto-load/usr/%{_lib}/libgstreamer*-gdb.py
diff --git a/pkgconfig/.gitignore b/pkgconfig/.gitignore
deleted file mode 100644 (file)
index 6fd0ef0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-*.pc
diff --git a/pkgconfig/Makefile.am b/pkgconfig/Makefile.am
deleted file mode 100644 (file)
index 78a1e65..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-### all of the standard pc files we need to generate
-if HAVE_CHECK
-CHECK_PC_I = gstreamer-check-@GST_API_VERSION@.pc
-CHECK_PC_U = gstreamer-check-@GST_API_VERSION@-uninstalled.pc
-else
-CHECK_PC_I =
-CHECK_PC_U =
-endif
-
-pcfiles =                                                      \
-       gstreamer-@GST_API_VERSION@.pc                          \
-       gstreamer-base-@GST_API_VERSION@.pc                     \
-       $(CHECK_PC_I)                                           \
-       gstreamer-controller-@GST_API_VERSION@.pc               \
-       gstreamer-net-@GST_API_VERSION@.pc
-
-pcfiles_uninstalled =                                          \
-       gstreamer-@GST_API_VERSION@-uninstalled.pc              \
-       gstreamer-base-@GST_API_VERSION@-uninstalled.pc         \
-       $(CHECK_PC_U)                                           \
-       gstreamer-controller-@GST_API_VERSION@-uninstalled.pc   \
-       gstreamer-net-@GST_API_VERSION@-uninstalled.pc
-
-all-local: $(pcfiles) $(pcfiles_uninstalled)
-
-cp_verbose = $(cp_verbose_$(V))
-cp_verbose_ = $(cp_verbose_$(AM_DEFAULT_VERBOSITY))
-cp_verbose_0 = @echo "  CP     $@";
-
-### how to generate pc files
-%-@GST_API_VERSION@.pc: %.pc
-       $(cp_verbose_0)cp $< $@
-%-@GST_API_VERSION@-uninstalled.pc: %-uninstalled.pc
-### the uninstalled libdir is depend of the build system used so set it here
-### rather than hardcoding it in the file directly.
-       $(AM_V_GEN) sed \
-               -e "s|[@]gstlibdir[@]|$(abs_top_builddir)/gst/.libs|" \
-               -e "s|[@]checklibdir[@]|$(abs_top_builddir)/libs/gst/check/.libs|" \
-               -e "s|[@]baselibdir[@]|$(abs_top_builddir)/libs/gst/base/.libs|" \
-               -e "s|[@]netlibdir[@]|$(abs_top_builddir)/libs/gst/net/.libs|" \
-               -e "s|[@]controllerlibdir[@]|$(abs_top_builddir)/libs/gst/controller/.libs|" \
-               $< > $@.tmp && mv $@.tmp $@
-
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = $(pcfiles)
-
-EXTRA_DIST =                                                   \
-       gstreamer.pc.in                                         \
-       gstreamer-uninstalled.pc.in                             \
-       gstreamer-base.pc.in                                    \
-       gstreamer-base-uninstalled.pc.in                        \
-       gstreamer-check.pc.in                                   \
-       gstreamer-check-uninstalled.pc.in                       \
-       gstreamer-controller.pc.in                              \
-       gstreamer-controller-uninstalled.pc.in                  \
-       gstreamer-net.pc.in                                     \
-       gstreamer-net-uninstalled.pc.in
-
-CLEANFILES = $(pcfiles) $(pcfiles_uninstalled)
diff --git a/pkgconfig/gstreamer-base-uninstalled.pc.in b/pkgconfig/gstreamer-base-uninstalled.pc.in
deleted file mode 100644 (file)
index 08759f1..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# the standard variables don't make sense for an uninstalled copy
-prefix=
-exec_prefix=
-libdir=@baselibdir@
-includedir=
-girdir=@abs_top_builddir@/libs/gst/base
-typelibdir=@abs_top_builddir@/libs/gst/base
-
-Name: GStreamer base classes, uninstalled
-Description: Base classes for GStreamer elements, Not Installed
-Requires: gstreamer-@GST_API_VERSION@ = @VERSION@
-Version: @VERSION@
-
-Libs: -L${libdir} -lgstbase-@GST_API_VERSION@
-Cflags: -I@abs_top_srcdir@/libs -I@abs_top_builddir@/libs
diff --git a/pkgconfig/gstreamer-base.pc.in b/pkgconfig/gstreamer-base.pc.in
deleted file mode 100644 (file)
index e24e050..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@/gstreamer-@GST_API_VERSION@
-datarootdir=${prefix}/share
-datadir=${datarootdir}
-girdir=${datadir}/gir-1.0
-typelibdir=${libdir}/girepository-1.0
-
-Name: GStreamer base classes
-Description: Base classes for GStreamer elements
-Requires: gstreamer-@GST_API_VERSION@
-Version: @VERSION@
-Libs: -L${libdir} -lgstbase-@GST_API_VERSION@
-Cflags: -I${includedir}
diff --git a/pkgconfig/gstreamer-check-uninstalled.pc.in b/pkgconfig/gstreamer-check-uninstalled.pc.in
deleted file mode 100644 (file)
index 85c2903..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# the standard variables don't make sense for an uninstalled copy
-prefix=
-exec_prefix=
-libdir=@checklibdir@
-includedir=
-girdir=@abs_top_builddir@/libs/gst/check
-typelibdir=@abs_top_builddir@/libs/gst/check
-
-Name: GStreamer check unit testing, uninstalled
-Description: Unit testing helper library for GStreamer modules, Not Installed
-Requires: gstreamer-@GST_API_VERSION@ = @VERSION@
-Version: @VERSION@
-
-Libs: -L${libdir} -lgstcheck-@GST_API_VERSION@ @LIBM@
-Cflags: -I@abs_top_srcdir@/libs -I@abs_top_builddir@/libs
diff --git a/pkgconfig/gstreamer-check.pc.in b/pkgconfig/gstreamer-check.pc.in
deleted file mode 100644 (file)
index 8c3a129..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@/gstreamer-@GST_API_VERSION@
-datarootdir=${prefix}/share
-datadir=${datarootdir}
-girdir=${datadir}/gir-1.0
-typelibdir=${libdir}/girepository-1.0
-
-Name: GStreamer check unit testing
-Description: Unit testing helper library for GStreamer modules
-Requires: gstreamer-@GST_API_VERSION@
-Version: @VERSION@
-Libs: -L${libdir} -lgstcheck-@GST_API_VERSION@ @LIBM@
-Cflags: -I${includedir}
diff --git a/pkgconfig/gstreamer-controller-uninstalled.pc.in b/pkgconfig/gstreamer-controller-uninstalled.pc.in
deleted file mode 100644 (file)
index 97983e7..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# the standard variables don't make sense for an uninstalled copy
-prefix=
-exec_prefix=
-libdir=@controllerlibdir@
-includedir=
-girdir=@abs_top_builddir@/libs/gst/controller
-typelibdir=@abs_top_builddir@/libs/gst/controller
-
-Name: GStreamer controller, uninstalled
-Description: Dynamic parameter control for GStreamer elements, Not Installed
-Requires: gstreamer-@GST_API_VERSION@ = @VERSION@
-Version: @VERSION@
-
-Libs: -L${libdir} -lgstcontroller-@GST_API_VERSION@
-Cflags: -I@abs_top_srcdir@/libs -I@abs_top_builddir@/libs
diff --git a/pkgconfig/gstreamer-controller.pc.in b/pkgconfig/gstreamer-controller.pc.in
deleted file mode 100644 (file)
index 5118de4..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@/gstreamer-@GST_API_VERSION@
-datarootdir=${prefix}/share
-datadir=${datarootdir}
-girdir=${datadir}/gir-1.0
-typelibdir=${libdir}/girepository-1.0
-
-Name: GStreamer controller
-Description: Dynamic parameter control for GStreamer elements
-Requires: gstreamer-@GST_API_VERSION@
-Version: @VERSION@
-Libs: -L${libdir} -lgstcontroller-@GST_API_VERSION@
-Cflags: -I${includedir}
diff --git a/pkgconfig/gstreamer-net-uninstalled.pc.in b/pkgconfig/gstreamer-net-uninstalled.pc.in
deleted file mode 100644 (file)
index 5d390c2..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# the standard variables don't make sense for an uninstalled copy
-prefix=
-exec_prefix=
-libdir=@netlibdir@
-includedir=
-girdir=@abs_top_builddir@/libs/gst/net
-typelibdir=@abs_top_builddir@/libs/gst/net
-
-Name: GStreamer networking library, uninstalled
-Description: Network-enabled GStreamer plug-ins and clocking, uninstalled
-Requires: gstreamer-@GST_API_VERSION@ = @VERSION@ gio-2.0
-Version: @VERSION@
-
-Libs: -L${libdir} -lgstnet-@GST_API_VERSION@
-Cflags: -I@abs_top_srcdir@/libs -I@abs_top_builddir@/libs
diff --git a/pkgconfig/gstreamer-net.pc.in b/pkgconfig/gstreamer-net.pc.in
deleted file mode 100644 (file)
index aa4c3ab..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@/gstreamer-@GST_API_VERSION@
-datarootdir=${prefix}/share
-datadir=${datarootdir}
-girdir=${datadir}/gir-1.0
-typelibdir=${libdir}/girepository-1.0
-
-Name: GStreamer networking library
-Description: Network-enabled GStreamer plug-ins and clocking
-Requires: gstreamer-@GST_API_VERSION@ gio-2.0
-Version: @VERSION@
-Libs: -L${libdir} -lgstnet-@GST_API_VERSION@
-Cflags: -I${includedir}
diff --git a/pkgconfig/gstreamer-uninstalled.pc.in b/pkgconfig/gstreamer-uninstalled.pc.in
deleted file mode 100644 (file)
index 30c703d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# the standard variables don't make sense for an uninstalled copy
-prefix=
-exec_prefix=
-libdir=@gstlibdir@
-# includedir is builddir because it is used to find gstconfig.h in places
-includedir=@abs_top_builddir@
-toolsdir=@abs_top_builddir@/tools
-pluginsdir=@abs_top_builddir@/plugins
-girdir=@abs_top_builddir@/gst
-bashhelpersdir=@abs_top_builddir@/data/bash-completion/helpers
-helpersdir=@abs_top_builddir@/libs/gst/helpers
-typelibdir=@abs_top_builddir@/gst
-
-Name: GStreamer Uninstalled
-Description: Streaming media framework, Not Installed
-Version: @VERSION@
-Requires: glib-2.0, gobject-2.0
-Requires.private: gmodule-no-export-2.0 @UNWIND_REQUIRE@ @DW_REQUIRE@
-Libs: -L${libdir} -lgstreamer-@GST_API_VERSION@
-Cflags: -I@abs_top_srcdir@ -I@abs_top_srcdir@/libs -I@abs_top_builddir@ -I@abs_top_builddir@/libs
diff --git a/pkgconfig/gstreamer.pc.in b/pkgconfig/gstreamer.pc.in
deleted file mode 100644 (file)
index 2e1eeb1..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@/gstreamer-@GST_API_VERSION@
-toolsdir=${exec_prefix}/bin
-pluginsdir=@libdir@/gstreamer-@GST_API_VERSION@
-datarootdir=${prefix}/share
-datadir=${datarootdir}
-girdir=${datadir}/gir-1.0
-typelibdir=${libdir}/girepository-1.0
-
-Name: GStreamer
-Description: Streaming media framework
-Version: @VERSION@
-Requires: glib-2.0, gobject-2.0
-Requires.private: gmodule-no-export-2.0 @UNWIND_REQUIRE@ @DW_REQUIRE@
-Libs: -L${libdir} -lgstreamer-@GST_API_VERSION@
-Cflags: -I${includedir} @HAVE_TV_PROFILE@ -DTIZEN_FEATURE_UPSTREAM
diff --git a/pkgconfig/meson.build b/pkgconfig/meson.build
deleted file mode 100644 (file)
index 9843772..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-pkgconf = configuration_data()
-
-pkgconf.set('prefix', join_paths(get_option('prefix')))
-pkgconf.set('exec_prefix', '${prefix}')
-pkgconf.set('libdir', '${prefix}/@0@'.format(get_option('libdir')))
-pkgconf.set('includedir', '${prefix}/@0@'.format(get_option('includedir')))
-pkgconf.set('GST_API_VERSION', apiversion)
-pkgconf.set('VERSION', gst_version)
-pkgconf.set('LIBM', mathlib.found() ? '-lm' : '')
-
-# Requires.private
-pkgconf.set('UNWIND_REQUIRE', cdata.has('HAVE_UNWIND') ? 'libunwind' : '')
-pkgconf.set('DW_REQUIRE', cdata.has('HAVE_DW') ? 'libdw' : '')
-
-# needed for generating -uninstalled.pc files
-pkgconf.set('abs_top_builddir', join_paths(meson.current_build_dir(), '..'))
-pkgconf.set('abs_top_srcdir', join_paths(meson.current_source_dir(), '..'))
-pkgconf.set('gstlibdir', join_paths(meson.build_root(), libgst.outdir()))
-pkgconf.set('baselibdir', join_paths(meson.build_root(), gst_base.outdir()))
-pkgconf.set('controllerlibdir', join_paths(meson.build_root(), gst_controller.outdir()))
-pkgconf.set('netlibdir', join_paths(meson.build_root(), gst_net.outdir()))
-
-pkg_install_dir = '@0@/pkgconfig'.format(get_option('libdir'))
-
-pkg_files = [
-  'gstreamer-base',
-  'gstreamer-controller',
-  'gstreamer-net',
-  'gstreamer'
-]
-
-if not get_option('check').disabled()
-  pkg_files += ['gstreamer-check']
-  pkgconf.set('checklibdir', join_paths(meson.build_root(), gst_check.outdir()))
-endif
-
-foreach p : pkg_files
-  infile = p + '.pc.in'
-  outfile = p + '-1.0.pc'
-  configure_file(input : infile,
-    output : outfile,
-    configuration : pkgconf,
-    install_dir : pkg_install_dir)
-
-  infile = p + '-uninstalled.pc.in'
-  outfile = p + '-1.0-uninstalled.pc'
-  configure_file(input : infile,
-    output : outfile,
-    configuration : pkgconf)
-endforeach
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
deleted file mode 100644 (file)
index 48a31fc..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-SUBDIRS = elements
-
-if !GST_DISABLE_GST_TRACER_HOOKS
-SUBDIRS += tracers
-endif
-
-DIST_SUBDIRS = elements tracers
diff --git a/plugins/elements/.gitignore b/plugins/elements/.gitignore
deleted file mode 100644 (file)
index dc1483e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-Makefile
-Makefile.in
-*.o
-*.lo
-*.la
-.deps
-.libs
-*.bb
-*.bbg
-*.da
-*.def
-*.gcno
diff --git a/plugins/elements/Makefile.am b/plugins/elements/Makefile.am
deleted file mode 100644 (file)
index dd81c1b..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-
-plugin_LTLIBRARIES = libgstcoreelements.la
-
-libgstcoreelements_la_DEPENDENCIES = $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la
-libgstcoreelements_la_SOURCES =        \
-       gstcapsfilter.c         \
-       gstclocksync.c          \
-       gstconcat.c             \
-       gstdataurisrc.c         \
-       gstdownloadbuffer.c     \
-       gstelements.c           \
-       gstelements_private.c   \
-       gstfakesrc.c            \
-       gstfakesink.c           \
-       gstfdsrc.c              \
-       gstfdsink.c             \
-       gstfilesink.c           \
-       gstfilesrc.c            \
-       gstfunnel.c             \
-       gstidentity.c           \
-       gstinputselector.c      \
-       gstoutputselector.c     \
-       gstmultiqueue.c         \
-       gstqueue.c              \
-       gstqueue2.c             \
-       gstsparsefile.c         \
-       gsttee.c                \
-       gsttypefindelement.c    \
-       gststreamiddemux.c      \
-       gstvalve.c
-
-libgstcoreelements_la_CFLAGS = $(GST_OBJ_CFLAGS)
-libgstcoreelements_la_LIBADD = \
-       $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \
-       $(GST_OBJ_LIBS)
-libgstcoreelements_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-
-noinst_HEADERS =               \
-       gstcapsfilter.h         \
-       gstclocksync.h          \
-       gstconcat.h             \
-       gstdataurisrc.h         \
-       gstdownloadbuffer.h     \
-       gstelements_private.h   \
-       gstfakesink.h           \
-       gstfakesrc.h            \
-       gstfdsrc.h              \
-       gstfdsink.h             \
-       gstfilesink.h           \
-       gstfilesrc.h            \
-       gstfunnel.h             \
-       gstidentity.h           \
-       gstinputselector.h      \
-       gstoutputselector.h     \
-       gstmultiqueue.h         \
-       gstqueue.h              \
-       gstqueue2.h             \
-       gstsparsefile.h         \
-       gsttee.h                \
-       gsttypefindelement.h    \
-       gststreamiddemux.h      \
-       gstvalve.h
-
-EXTRA_DIST = gstfdsrc.c \
-            gstfdsink.c
-
-
-CLEANFILES = *.gcno *.gcda *.gcov *.gcov.out
-
-%.c.gcov: .libs/libgstcoreelements_la-%.gcda %.c
-       $(GCOV) -b -f -o $^ > $@.out
-
-gcov: $(libgstcoreelements_la_SOURCES:=.gcov)
index 05d8b6c..438f6e1 100644 (file)
@@ -22,9 +22,9 @@
 /**
  * SECTION:element-capsfilter
  * @title: capsfilter
+ * @short_description: enforce limitations on the data format
  *
- * The element does not modify data as such, but can enforce limitations on the
- * data format.
+ * The element does not modify data as such, but can enforce limitations on the data format.
  *
  * ## Example launch line
  * |[
@@ -42,6 +42,7 @@
 
 #include "../../gst/gst-i18n-lib.h"
 #include "gstcapsfilter.h"
+#include "gstcoreelementselements.h"
 
 enum
 {
@@ -93,6 +94,8 @@ gst_caps_filter_caps_change_mode_get_type (void)
 G_DEFINE_TYPE_WITH_CODE (GstCapsFilter, gst_capsfilter, GST_TYPE_BASE_TRANSFORM,
     _do_init);
 
+GST_ELEMENT_REGISTER_DEFINE (capsfilter, "capsfilter", GST_RANK_NONE,
+    GST_TYPE_CAPS_FILTER);
 
 static void gst_capsfilter_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
@@ -157,6 +160,8 @@ gst_capsfilter_class_init (GstCapsFilterClass * klass)
       GST_DEBUG_FUNCPTR (gst_capsfilter_prepare_buf);
   trans_class->sink_event = GST_DEBUG_FUNCPTR (gst_capsfilter_sink_event);
   trans_class->stop = GST_DEBUG_FUNCPTR (gst_capsfilter_stop);
+
+  gst_type_mark_as_plugin_api (GST_TYPE_CAPS_FILTER_CAPS_CHANGE_MODE, 0);
 }
 
 static void
index fb5efbe..05258ab 100644 (file)
 #include <gst/gst.h>
 
 #include "gstclocksync.h"
+#include "gstcoreelementselements.h"
 
 GST_DEBUG_CATEGORY_STATIC (gst_clock_sync_debug);
 #define GST_CAT_DEFAULT gst_clock_sync_debug
 
-/* ClockSync signals and args */
-enum
-{
-  SIGNAL_HANDOFF,
-  SIGNAL_HANDOFF_LIST,
-  /* FILL ME */
-  LAST_SIGNAL
-};
-
+/* ClockSync args */
 #define DEFAULT_SYNC                    TRUE
 #define DEFAULT_TS_OFFSET               0
-#define DEFAULT_SIGNAL_HANDOFFS         FALSE
+#define DEFAULT_SYNC_TO_FIRST           FALSE
 
 enum
 {
   PROP_0,
   PROP_SYNC,
   PROP_TS_OFFSET,
-  PROP_SIGNAL_HANDOFFS,
+  PROP_SYNC_TO_FIRST,
+  PROP_LAST
 };
 
+static GParamSpec *properties[PROP_LAST];
+
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
@@ -90,6 +86,8 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
 #define gst_clock_sync_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstClockSync, gst_clock_sync, GST_TYPE_ELEMENT,
     _do_init);
+GST_ELEMENT_REGISTER_DEFINE (clocksync, "clocksync", GST_RANK_NONE,
+    GST_TYPE_CLOCKSYNC);
 
 static void gst_clock_sync_finalize (GObject * object);
 
@@ -108,8 +106,7 @@ static gboolean gst_clock_sync_src_query (GstPad * pad, GstObject * parent,
     GstQuery * query);
 static GstStateChangeReturn gst_clocksync_change_state (GstElement * element,
     GstStateChange transition);
-
-static guint gst_clocksync_signals[LAST_SIGNAL] = { 0 };
+static GstClock *gst_clocksync_provide_clock (GstElement * element);
 
 static void
 gst_clock_sync_class_init (GstClockSyncClass * klass)
@@ -124,55 +121,47 @@ gst_clock_sync_class_init (GstClockSyncClass * klass)
   gobject_class->get_property = gst_clock_sync_get_property;
   gobject_class->finalize = gst_clock_sync_finalize;
 
-  g_object_class_install_property (gobject_class, PROP_SYNC,
+  properties[PROP_SYNC] =
       g_param_spec_boolean ("sync", "Synchronize",
-          "Synchronize to pipeline clock", DEFAULT_SYNC,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_TS_OFFSET,
+      "Synchronize to pipeline clock", DEFAULT_SYNC,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  properties[PROP_TS_OFFSET] =
       g_param_spec_int64 ("ts-offset", "Timestamp offset for synchronisation",
-          "Timestamp offset in nanoseconds for synchronisation, negative for earlier sync",
-          G_MININT64, G_MAXINT64, DEFAULT_TS_OFFSET,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  /**
-   * GstClockSync::signal-handoffs
-   *
-   * If set to %TRUE, the clocksync will emit a handoff signal when handling a buffer.
-   * When set to %FALSE, no signal will be emitted, which might improve performance.
-   */
-  g_object_class_install_property (gobject_class, PROP_SIGNAL_HANDOFFS,
-      g_param_spec_boolean ("signal-handoffs",
-          "Signal handoffs", "Send a signal before pushing the buffer",
-          DEFAULT_SIGNAL_HANDOFFS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+      "Timestamp offset in nanoseconds for synchronisation, negative for earlier sync",
+      G_MININT64, G_MAXINT64, DEFAULT_TS_OFFSET,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
   /**
-   * GstClockSync::handoff:
-   * @clocksync: the clocksync instance
-   * @buffer: the buffer that just has been received
-   * @pad: the pad that received it
+   * GstClockSync:sync-to-first:
    *
-   * This signal gets emitted before passing the buffer downstream.
-   */
-  gst_clocksync_signals[SIGNAL_HANDOFF] =
-      g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstClockSyncClass, handoff), NULL, NULL,
-      NULL, G_TYPE_NONE, 1, GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE);
-
-  /**
-   * GstClockSync::handoff-list:
-   * @clocksync: the clocksync instance
-   * @buffer_list: the buffer list that just has been received
-   * @pad: the pad that received it
+   * When enabled, clocksync elemenet will adjust "ts-offset" value
+   * automatically by using given timestamp of the first buffer and running
+   * time of pipeline, so that clocksync element can output the first buffer
+   * immediately without clock waiting.
    *
-   * This signal gets emitted before passing the buffer list downstream.
+   * Since: 1.20
    */
-  gst_clocksync_signals[SIGNAL_HANDOFF_LIST] =
-      g_signal_new ("handoff-list", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstClockSyncClass, handoff_list),
-      NULL, NULL, NULL, G_TYPE_NONE, 1,
-      GST_TYPE_BUFFER_LIST | G_SIGNAL_TYPE_STATIC_SCOPE);
+  properties[PROP_SYNC_TO_FIRST] =
+      g_param_spec_boolean ("sync-to-first",
+      "Sync to first",
+      "Automatically set ts-offset based on running time of the first "
+      "buffer and pipeline's running time "
+      "(i.e., ts-offset = \"pipeline running time\" - \"buffer running time\"). "
+      "When enabled, clocksync element will update ts-offset on the first "
+      "buffer per flush event or READY to PAUSED state change. "
+      "This property can be useful in case that buffer timestamp does not "
+      "necessarily have to be synchronized with pipeline's running time, "
+      "but duration of the buffer through clocksync element needs to be "
+      "synchronized with the amount of clock time go. "
+      "Note that mixed use of ts-offset and this property would be racy "
+      "if clocksync element is running already.",
+      DEFAULT_SYNC_TO_FIRST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  g_object_class_install_properties (gobject_class, PROP_LAST, properties);
 
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_clocksync_change_state);
+  gstelement_class->provide_clock =
+      GST_DEBUG_FUNCPTR (gst_clocksync_provide_clock);
 
   gst_element_class_set_static_metadata (gstelement_class,
       "ClockSync",
@@ -213,10 +202,13 @@ gst_clock_sync_init (GstClockSync * clocksync)
   GST_PAD_SET_PROXY_CAPS (clocksync->srcpad);
   gst_element_add_pad (GST_ELEMENT (clocksync), clocksync->srcpad);
 
-  clocksync->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
   clocksync->ts_offset = DEFAULT_TS_OFFSET;
   clocksync->sync = DEFAULT_SYNC;
+  clocksync->sync_to_first = DEFAULT_SYNC_TO_FIRST;
   g_cond_init (&clocksync->blocked_cond);
+
+  GST_OBJECT_FLAG_SET (clocksync, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
+  GST_OBJECT_FLAG_SET (clocksync, GST_ELEMENT_FLAG_REQUIRE_CLOCK);
 }
 
 static void
@@ -224,16 +216,37 @@ gst_clock_sync_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
   GstClockSync *clocksync = GST_CLOCKSYNC (object);
+  GstMessage *clock_message = NULL;
+  gboolean sync;
 
   switch (prop_id) {
     case PROP_SYNC:
       clocksync->sync = g_value_get_boolean (value);
+      sync = g_value_get_boolean (value);
+      GST_OBJECT_LOCK (clocksync);
+      if (sync != clocksync->sync) {
+        clocksync->sync = sync;
+        if (sync) {
+          GST_OBJECT_FLAG_SET (clocksync, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
+          clock_message =
+              gst_message_new_clock_provide (GST_OBJECT_CAST (clocksync),
+              gst_system_clock_obtain (), TRUE);
+        } else {
+          GST_OBJECT_FLAG_UNSET (clocksync, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
+          clock_message =
+              gst_message_new_clock_lost (GST_OBJECT_CAST (clocksync),
+              gst_system_clock_obtain ());
+        }
+      }
+      GST_OBJECT_UNLOCK (clocksync);
+      if (clock_message)
+        gst_element_post_message (GST_ELEMENT_CAST (clocksync), clock_message);
       break;
     case PROP_TS_OFFSET:
       clocksync->ts_offset = g_value_get_int64 (value);
       break;
-    case PROP_SIGNAL_HANDOFFS:
-      clocksync->signal_handoffs = g_value_get_boolean (value);
+    case PROP_SYNC_TO_FIRST:
+      clocksync->sync_to_first = g_value_get_boolean (value);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -254,8 +267,8 @@ gst_clock_sync_get_property (GObject * object, guint prop_id,
     case PROP_TS_OFFSET:
       g_value_set_int64 (value, clocksync->ts_offset);
       break;
-    case PROP_SIGNAL_HANDOFFS:
-      g_value_set_boolean (value, clocksync->signal_handoffs);
+    case PROP_SYNC_TO_FIRST:
+      g_value_set_boolean (value, clocksync->sync_to_first);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -297,23 +310,43 @@ gst_clocksync_do_sync (GstClockSync * clocksync, GstClockTime running_time)
     GstClockReturn cret;
     GstClockTime timestamp;
     GstClockTimeDiff ts_offset = clocksync->ts_offset;
+    GstClockTimeDiff jitter;
 
     timestamp = running_time + GST_ELEMENT (clocksync)->base_time +
         clocksync->upstream_latency;
+
+    GST_DEBUG_OBJECT (clocksync,
+        "running time: %" GST_TIME_FORMAT " base time: %" GST_TIME_FORMAT
+        " upstream latency: %" GST_TIME_FORMAT, GST_TIME_ARGS (running_time),
+        GST_TIME_ARGS (GST_ELEMENT (clocksync)->base_time),
+        GST_TIME_ARGS (clocksync->upstream_latency));
+
+    GST_DEBUG_OBJECT (clocksync,
+        "Waiting for clock time %" GST_TIME_FORMAT " ts offset: %"
+        GST_STIME_FORMAT, GST_TIME_ARGS (timestamp),
+        GST_STIME_ARGS (ts_offset));
+
     if (ts_offset < 0) {
       ts_offset = -ts_offset;
       if (ts_offset < timestamp)
         timestamp -= ts_offset;
       else
         timestamp = 0;
-    } else
+    } else {
       timestamp += ts_offset;
+    }
+
+    GST_DEBUG_OBJECT (clocksync, "Offset clock time %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (timestamp));
 
     /* save id if we need to unlock */
     clocksync->clock_id = gst_clock_new_single_shot_id (clock, timestamp);
     GST_OBJECT_UNLOCK (clocksync);
 
-    cret = gst_clock_id_wait (clocksync->clock_id, NULL);
+    cret = gst_clock_id_wait (clocksync->clock_id, &jitter);
+
+    GST_DEBUG_OBJECT (clocksync, "Clock returned %d, jitter %" GST_STIME_FORMAT,
+        cret, GST_STIME_ARGS (jitter));
 
     GST_OBJECT_LOCK (clocksync);
     if (clocksync->clock_id) {
@@ -361,7 +394,7 @@ gst_clock_sync_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
     case GST_EVENT_FLUSH_START:
       GST_OBJECT_LOCK (clocksync);
       clocksync->flushing = TRUE;
-      g_cond_broadcast (&clocksync->blocked_cond);
+      g_cond_signal (&clocksync->blocked_cond);
       if (clocksync->clock_id) {
         GST_DEBUG_OBJECT (clocksync, "unlock clock wait");
         gst_clock_id_unschedule (clocksync->clock_id);
@@ -373,6 +406,8 @@ gst_clock_sync_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
       clocksync->flushing = FALSE;
       gst_segment_init (&clocksync->segment, GST_FORMAT_UNDEFINED);
       GST_OBJECT_UNLOCK (clocksync);
+      clocksync->is_first = TRUE;
+      break;
     default:
       break;
   }
@@ -382,6 +417,42 @@ gst_clock_sync_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
   return ret;
 }
 
+static void
+gst_clock_sync_update_ts_offset (GstClockSync * clocksync,
+    GstClockTime runtimestamp)
+{
+  GstClock *clock;
+  GstClockTimeDiff ts_offset = 0;
+  GstClockTime running_time;
+
+  if (!clocksync->sync_to_first || !clocksync->is_first || !clocksync->sync)
+    return;
+
+  GST_OBJECT_LOCK (clocksync);
+  clock = GST_ELEMENT_CLOCK (clocksync);
+  if (!clock) {
+    GST_DEBUG_OBJECT (clocksync, "We have no clock");
+    GST_OBJECT_UNLOCK (clocksync);
+    return;
+  }
+
+  running_time = gst_clock_get_time (clock) -
+      GST_ELEMENT_CAST (clocksync)->base_time;
+  ts_offset = GST_CLOCK_DIFF (runtimestamp, running_time);
+  GST_OBJECT_UNLOCK (clocksync);
+
+  GST_DEBUG_OBJECT (clocksync, "Running time %" GST_TIME_FORMAT
+      ", running time stamp %" GST_TIME_FORMAT ", calculated ts-offset %"
+      GST_STIME_FORMAT, GST_TIME_ARGS (running_time),
+      GST_TIME_ARGS (runtimestamp), GST_STIME_ARGS (ts_offset));
+
+  clocksync->is_first = FALSE;
+  if (ts_offset != clocksync->ts_offset) {
+    clocksync->ts_offset = ts_offset;
+    g_object_notify_by_pspec (G_OBJECT (clocksync), properties[PROP_TS_OFFSET]);
+  }
+}
+
 static GstFlowReturn
 gst_clock_sync_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
 {
@@ -394,16 +465,29 @@ gst_clock_sync_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
     GstClockTime runtimestamp = 0;
     GstClockTime rundts, runpts;
 
-    rundts = gst_segment_to_running_time (&clocksync->segment,
-        GST_FORMAT_TIME, GST_BUFFER_DTS (buf));
-    runpts = gst_segment_to_running_time (&clocksync->segment,
-        GST_FORMAT_TIME, GST_BUFFER_PTS (buf));
+    if (clocksync->segment.rate > 0.0) {
+      rundts = gst_segment_to_running_time (&clocksync->segment,
+          GST_FORMAT_TIME, GST_BUFFER_DTS (buf));
+      runpts = gst_segment_to_running_time (&clocksync->segment,
+          GST_FORMAT_TIME, GST_BUFFER_PTS (buf));
+    } else {
+      runpts = gst_segment_to_running_time (&clocksync->segment,
+          GST_FORMAT_TIME, GST_CLOCK_TIME_IS_VALID (buf->duration)
+          && GST_CLOCK_TIME_IS_VALID (buf->pts) ? buf->pts +
+          buf->duration : buf->pts);
+      rundts = gst_segment_to_running_time (&clocksync->segment,
+          GST_FORMAT_TIME, GST_CLOCK_TIME_IS_VALID (buf->duration)
+          && GST_CLOCK_TIME_IS_VALID (buf->dts) ? buf->dts +
+          buf->duration : buf->dts);
+    }
 
     if (GST_CLOCK_TIME_IS_VALID (rundts))
       runtimestamp = rundts;
     else if (GST_CLOCK_TIME_IS_VALID (runpts))
       runtimestamp = runpts;
 
+    gst_clock_sync_update_ts_offset (clocksync, runtimestamp);
+
     ret = gst_clocksync_do_sync (clocksync, runtimestamp);
     if (ret != GST_FLOW_OK) {
       GST_LOG_OBJECT (clocksync,
@@ -413,9 +497,6 @@ gst_clock_sync_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
     }
   }
 
-  if (clocksync->signal_handoffs)
-    g_signal_emit (clocksync, gst_clocksync_signals[SIGNAL_HANDOFF], 0, buf);
-
   /* Forward the buffer */
   return gst_pad_push (clocksync->srcpad, buf);
 }
@@ -450,6 +531,8 @@ gst_clock_sync_chain_list (GstPad * pad, GstObject * parent,
     else if (GST_CLOCK_TIME_IS_VALID (runpts))
       runtimestamp = runpts;
 
+    gst_clock_sync_update_ts_offset (clocksync, runtimestamp);
+
     ret = gst_clocksync_do_sync (clocksync, runtimestamp);
     if (ret != GST_FLOW_OK) {
       gst_buffer_list_unref (buffer_list);
@@ -457,10 +540,6 @@ gst_clock_sync_chain_list (GstPad * pad, GstObject * parent,
     }
   }
 
-  if (clocksync->signal_handoffs)
-    g_signal_emit (clocksync, gst_clocksync_signals[SIGNAL_HANDOFF_LIST], 0,
-        buffer_list);
-
   /* Forward the buffer list */
 done:
   return gst_pad_push_list (clocksync->srcpad, buffer_list);
@@ -535,11 +614,12 @@ gst_clocksync_change_state (GstElement * element, GstStateChange transition)
       GST_OBJECT_UNLOCK (clocksync);
       if (clocksync->sync)
         no_preroll = TRUE;
+      clocksync->is_first = TRUE;
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
       GST_OBJECT_LOCK (clocksync);
       clocksync->blocked = FALSE;
-      g_cond_broadcast (&clocksync->blocked_cond);
+      g_cond_signal (&clocksync->blocked_cond);
       GST_OBJECT_UNLOCK (clocksync);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
@@ -550,7 +630,7 @@ gst_clocksync_change_state (GstElement * element, GstStateChange transition)
         gst_clock_id_unschedule (clocksync->clock_id);
       }
       clocksync->blocked = FALSE;
-      g_cond_broadcast (&clocksync->blocked_cond);
+      g_cond_signal (&clocksync->blocked_cond);
       GST_OBJECT_UNLOCK (clocksync);
       break;
     default:
@@ -581,3 +661,15 @@ gst_clocksync_change_state (GstElement * element, GstStateChange transition)
 
   return ret;
 }
+
+/* FIXME: GStreamer 2.0 */
+static GstClock *
+gst_clocksync_provide_clock (GstElement * element)
+{
+  GstClockSync *clocksync = GST_CLOCKSYNC (element);
+
+  if (!clocksync->sync)
+    return NULL;
+
+  return gst_system_clock_obtain ();
+}
index 44ab48e..647d73e 100644 (file)
@@ -51,8 +51,6 @@ struct _GstClockSync
   /*< private >*/
   GstPad *sinkpad, *srcpad;
 
-  gboolean       signal_handoffs;
-
   GstSegment     segment;
   GstClockID     clock_id;
   gboolean       flushing;
@@ -61,17 +59,15 @@ struct _GstClockSync
   GCond          blocked_cond;
   gboolean       blocked;
   GstClockTimeDiff  ts_offset;
+  gboolean sync_to_first;
+  gboolean is_first;
 
   GstClockTime   upstream_latency;
 };
 
-struct _GstClockSyncClass 
+struct _GstClockSyncClass
 {
   GstElementClass parent_class;
-
-  /* signals */
-  void (*handoff) (GstElement *element, GstBuffer *buf);
-  void (*handoff_list) (GstElement *element, GstBufferList *buffer_list);
 };
 
 GType gst_clock_sync_get_type (void);
index 0495546..35f68eb 100644 (file)
@@ -50,6 +50,7 @@
 #endif
 
 #include "gstconcat.h"
+#include "gstcoreelementselements.h"
 
 GST_DEBUG_CATEGORY_STATIC (gst_concat_debug);
 #define GST_CAT_DEFAULT gst_concat_debug
@@ -118,6 +119,7 @@ enum
   GST_DEBUG_CATEGORY_INIT (gst_concat_debug, "concat", 0, "concat element");
 #define gst_concat_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstConcat, gst_concat, GST_TYPE_ELEMENT, _do_init);
+GST_ELEMENT_REGISTER_DEFINE (concat, "concat", GST_RANK_NONE, GST_TYPE_CONCAT);
 
 static void gst_concat_dispose (GObject * object);
 static void gst_concat_finalize (GObject * object);
@@ -163,7 +165,7 @@ gst_concat_class_init (GstConcatClass * klass)
   gobject_class->set_property = gst_concat_set_property;
 
   pspec_active_pad = g_param_spec_object ("active-pad", "Active pad",
-      "Currently active src pad", GST_TYPE_PAD, G_PARAM_READABLE |
+      "Currently active sink pad", GST_TYPE_PAD, G_PARAM_READABLE |
       G_PARAM_STATIC_STRINGS);
   g_object_class_install_property (gobject_class, PROP_ACTIVE_PAD,
       pspec_active_pad);
@@ -522,28 +524,29 @@ gst_concat_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
   GstConcat *self = GST_CONCAT (parent);
   GstConcatPad *spad = GST_CONCAT_PAD_CAST (pad);
   gboolean ret = TRUE;
+  gboolean adjust_base;
 
   GST_LOG_OBJECT (pad, "received event %" GST_PTR_FORMAT, event);
 
+  g_mutex_lock (&self->lock);
+  adjust_base = self->adjust_base;
+  g_mutex_unlock (&self->lock);
+
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_STREAM_START:{
       if (!gst_concat_pad_wait (spad, self)) {
         ret = FALSE;
-        gst_event_unref (event);
-      } else {
-        ret = gst_pad_event_default (pad, parent, event);
+        gst_event_replace (&event, NULL);
       }
       break;
     }
     case GST_EVENT_SEGMENT:{
-      gboolean adjust_base;
-
+      guint32 seqnum = gst_event_get_seqnum (event);
       /* Drop segment event, we create our own one */
       gst_event_copy_segment (event, &spad->segment);
-      gst_event_unref (event);
+      gst_event_replace (&event, NULL);
 
       g_mutex_lock (&self->lock);
-      adjust_base = self->adjust_base;
       if (self->format == GST_FORMAT_UNDEFINED) {
         if (spad->segment.format != GST_FORMAT_TIME
             && spad->segment.format != GST_FORMAT_BYTES) {
@@ -556,7 +559,6 @@ gst_concat_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
         self->format = spad->segment.format;
         GST_DEBUG_OBJECT (self, "Operating in %s format",
             gst_format_get_name (self->format));
-        g_mutex_unlock (&self->lock);
       } else if (self->format != spad->segment.format) {
         g_mutex_unlock (&self->lock);
         GST_ELEMENT_ERROR (self, CORE, FAILED, (NULL),
@@ -564,15 +566,17 @@ gst_concat_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
                 gst_format_get_name (self->format),
                 gst_format_get_name (spad->segment.format)));
         ret = FALSE;
-      } else {
-        g_mutex_unlock (&self->lock);
+        break;
       }
 
+      g_mutex_unlock (&self->lock);
+
       if (!gst_concat_pad_wait (spad, self)) {
         ret = FALSE;
       } else {
         GstSegment segment = spad->segment;
-        GstEvent *topush;
+
+        g_mutex_lock (&self->lock);
 
         if (adjust_base) {
           /* We know no duration */
@@ -604,15 +608,15 @@ gst_concat_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
             }
           }
         }
-        topush = gst_event_new_segment (&segment);
-        gst_event_set_seqnum (topush, gst_event_get_seqnum (event));
+        event = gst_event_new_segment (&segment);
+        gst_event_set_seqnum (event, seqnum);
 
-        gst_pad_push_event (self->srcpad, topush);
+        g_mutex_unlock (&self->lock);
       }
       break;
     }
     case GST_EVENT_EOS:{
-      gst_event_unref (event);
+      gst_event_replace (&event, NULL);
 
       if (!gst_concat_pad_wait (spad, self)) {
         ret = FALSE;
@@ -627,7 +631,7 @@ gst_concat_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
         gst_concat_notify_active_pad (self);
 
         if (!next) {
-          gst_pad_push_event (self->srcpad, gst_event_new_eos ());
+          event = gst_event_new_eos ();
         } else {
           gst_element_post_message (GST_ELEMENT_CAST (self),
               gst_message_new_duration_changed (GST_OBJECT_CAST (self)));
@@ -646,10 +650,8 @@ gst_concat_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
         forward = TRUE;
       g_mutex_unlock (&self->lock);
 
-      if (forward)
-        ret = gst_pad_event_default (pad, parent, event);
-      else
-        gst_event_unref (event);
+      if (!forward)
+        gst_event_replace (&event, NULL);
       break;
     }
     case GST_EVENT_FLUSH_STOP:{
@@ -674,24 +676,36 @@ gst_concat_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
           self->current_start_offset = 0;
           self->last_stop = GST_CLOCK_TIME_NONE;
         }
-        ret = gst_pad_event_default (pad, parent, event);
       } else {
-        gst_event_unref (event);
+        gst_event_replace (&event, NULL);
       }
       break;
     }
     default:{
       /* Wait for other serialized events before forwarding */
       if (GST_EVENT_IS_SERIALIZED (event) && !gst_concat_pad_wait (spad, self)) {
-        gst_event_unref (event);
+        gst_event_replace (&event, NULL);
         ret = FALSE;
-      } else {
-        ret = gst_pad_event_default (pad, parent, event);
       }
       break;
     }
   }
 
+  if (event) {
+    g_mutex_lock (&self->lock);
+    if (self->adjust_base && self->format == GST_FORMAT_TIME) {
+      gint64 offset;
+
+      event = gst_event_make_writable (event);
+      offset = gst_event_get_running_time_offset (event);
+      offset += self->current_start_offset;
+
+      gst_event_set_running_time_offset (event, offset);
+    }
+    g_mutex_unlock (&self->lock);
+    ret = gst_pad_event_default (pad, parent, event);
+  }
+
   return ret;
 }
 
@@ -723,13 +737,12 @@ gst_concat_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   GstConcat *self = GST_CONCAT (parent);
   gboolean ret = TRUE;
+  GstPad *sinkpad = NULL;
 
   GST_LOG_OBJECT (pad, "received event %" GST_PTR_FORMAT, event);
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_SEEK:{
-      GstPad *sinkpad = NULL;
-
       g_mutex_lock (&self->lock);
       if ((sinkpad = self->current_sinkpad))
         gst_object_ref (sinkpad);
@@ -738,20 +751,13 @@ gst_concat_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
         sinkpad = gst_object_ref (self->sinkpads->data);
       }
       g_mutex_unlock (&self->lock);
-      if (sinkpad) {
-        ret = gst_pad_push_event (sinkpad, event);
-        gst_object_unref (sinkpad);
-      } else {
-        gst_event_unref (event);
+      if (!sinkpad) {
+        gst_event_replace (&event, NULL);
         ret = FALSE;
       }
       break;
     }
     case GST_EVENT_QOS:{
-      GstQOSType type;
-      GstClockTimeDiff diff;
-      GstClockTime timestamp;
-      gdouble proportion;
       GstPad *sinkpad = NULL;
 
       g_mutex_lock (&self->lock);
@@ -759,21 +765,9 @@ gst_concat_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
         gst_object_ref (sinkpad);
       g_mutex_unlock (&self->lock);
 
-      if (sinkpad) {
-        gst_event_parse_qos (event, &type, &proportion, &diff, &timestamp);
-        gst_event_unref (event);
 
-        if (timestamp != GST_CLOCK_TIME_NONE
-            && timestamp > self->current_start_offset) {
-          timestamp -= self->current_start_offset;
-          event = gst_event_new_qos (type, proportion, diff, timestamp);
-          ret = gst_pad_push_event (self->current_sinkpad, event);
-        } else {
-          ret = FALSE;
-        }
-        gst_object_unref (sinkpad);
-      } else {
-        gst_event_unref (event);
+      if (!sinkpad) {
+        gst_event_replace (&event, NULL);
         ret = FALSE;
       }
       break;
@@ -787,15 +781,34 @@ gst_concat_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
             "resetting start offset to 0 after flushing with reset_time = TRUE");
         self->current_start_offset = 0;
       }
-
-      ret = gst_pad_event_default (pad, parent, event);
       break;
     }
     default:
-      ret = gst_pad_event_default (pad, parent, event);
       break;
   }
 
+  if (event) {
+    g_mutex_lock (&self->lock);
+    if (self->adjust_base && self->format == GST_FORMAT_TIME) {
+      gint64 offset;
+
+      event = gst_event_make_writable (event);
+      offset = gst_event_get_running_time_offset (event);
+      offset -= self->current_start_offset;
+
+      gst_event_set_running_time_offset (event, offset);
+    }
+    g_mutex_unlock (&self->lock);
+
+    if (sinkpad)
+      ret = gst_pad_push_event (sinkpad, event);
+    else
+      ret = gst_pad_event_default (pad, parent, event);
+  }
+
+  if (sinkpad)
+    gst_object_unref (sinkpad);
+
   return ret;
 }
 
diff --git a/plugins/elements/gstcoreelementselements.h b/plugins/elements/gstcoreelementselements.h
new file mode 100644 (file)
index 0000000..fa930aa
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ *   @Author: Stéphane Cerveau <scerveau@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_CORE_ELEMENTS_ELEMENTS_H__
+#define __GST_CORE_ELEMENTS_ELEMENTS_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+GST_ELEMENT_REGISTER_DECLARE (capsfilter);
+GST_ELEMENT_REGISTER_DECLARE (clocksync);
+GST_ELEMENT_REGISTER_DECLARE (concat);
+GST_ELEMENT_REGISTER_DECLARE (dataurisrc);
+GST_ELEMENT_REGISTER_DECLARE (downloadbuffer);
+GST_ELEMENT_REGISTER_DECLARE (fakesink);
+GST_ELEMENT_REGISTER_DECLARE (fakesrc);
+#if defined(HAVE_SYS_SOCKET_H) || defined(_MSC_VER)
+GST_ELEMENT_REGISTER_DECLARE (fdsrc);
+GST_ELEMENT_REGISTER_DECLARE (fdsink);
+#endif
+GST_ELEMENT_REGISTER_DECLARE (filesink);
+GST_ELEMENT_REGISTER_DECLARE (filesrc);
+GST_ELEMENT_REGISTER_DECLARE (funnel);
+GST_ELEMENT_REGISTER_DECLARE (identity);
+GST_ELEMENT_REGISTER_DECLARE (input_selector);
+GST_ELEMENT_REGISTER_DECLARE (multiqueue);
+GST_ELEMENT_REGISTER_DECLARE (output_selector);
+GST_ELEMENT_REGISTER_DECLARE (queue);
+GST_ELEMENT_REGISTER_DECLARE (queue2);
+GST_ELEMENT_REGISTER_DECLARE (streamiddemux);
+GST_ELEMENT_REGISTER_DECLARE (tee);
+GST_ELEMENT_REGISTER_DECLARE (typefind);
+GST_ELEMENT_REGISTER_DECLARE (valve);
+
+G_END_DECLS
+
+#endif /* __GST_CORE_ELEMENTS_ELEMENTS_H__ */
diff --git a/plugins/elements/gstcoreelementsplugin.c b/plugins/elements/gstcoreelementsplugin.c
new file mode 100644 (file)
index 0000000..82ea0d5
--- /dev/null
@@ -0,0 +1,72 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wtay@chello.be>
+ *
+ * gstelementsplugin.c:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+/**
+ * plugin-coreelements:
+ *
+ * GStreamer core elements
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstcoreelementselements.h"
+
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  gboolean ret = FALSE;
+
+  ret |= GST_ELEMENT_REGISTER (capsfilter, plugin);
+  ret |= GST_ELEMENT_REGISTER (clocksync, plugin);
+  ret |= GST_ELEMENT_REGISTER (concat, plugin);
+  ret |= GST_ELEMENT_REGISTER (dataurisrc, plugin);
+  ret |= GST_ELEMENT_REGISTER (downloadbuffer, plugin);
+  ret |= GST_ELEMENT_REGISTER (fakesrc, plugin);
+  ret |= GST_ELEMENT_REGISTER (fakesink, plugin);
+#if defined(HAVE_SYS_SOCKET_H) || defined(_MSC_VER)
+  ret |= GST_ELEMENT_REGISTER (fdsrc, plugin);
+  ret |= GST_ELEMENT_REGISTER (fdsink, plugin);
+#endif
+  ret |= GST_ELEMENT_REGISTER (filesrc, plugin);
+  ret |= GST_ELEMENT_REGISTER (funnel, plugin);
+  ret |= GST_ELEMENT_REGISTER (identity, plugin);
+  ret |= GST_ELEMENT_REGISTER (input_selector, plugin);
+  ret |= GST_ELEMENT_REGISTER (output_selector, plugin);
+  ret |= GST_ELEMENT_REGISTER (queue, plugin);
+  ret |= GST_ELEMENT_REGISTER (queue2, plugin);
+  ret |= GST_ELEMENT_REGISTER (filesink, plugin);
+  ret |= GST_ELEMENT_REGISTER (tee, plugin);
+  ret |= GST_ELEMENT_REGISTER (typefind, plugin);
+  ret |= GST_ELEMENT_REGISTER (multiqueue, plugin);
+  ret |= GST_ELEMENT_REGISTER (valve, plugin);
+  ret |= GST_ELEMENT_REGISTER (streamiddemux, plugin);
+
+  return ret;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, coreelements,
+    "GStreamer core elements", plugin_init, VERSION, GST_LICENSE,
+    GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
index e35d012..a6132b5 100644 (file)
@@ -38,6 +38,7 @@
 #endif
 
 #include "gstdataurisrc.h"
+#include "gstcoreelementselements.h"
 
 #include <string.h>
 #include <gst/base/gsttypefindhelper.h>
@@ -82,6 +83,8 @@ static gboolean gst_data_uri_src_set_uri (GstURIHandler * handler,
 G_DEFINE_TYPE_WITH_CODE (GstDataURISrc, gst_data_uri_src, GST_TYPE_BASE_SRC,
     G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER,
         gst_data_uri_src_handler_init));
+GST_ELEMENT_REGISTER_DEFINE (dataurisrc, "dataurisrc", GST_RANK_PRIMARY,
+    GST_TYPE_DATA_URI_SRC);
 
 static void
 gst_data_uri_src_class_init (GstDataURISrcClass * klass)
@@ -334,7 +337,7 @@ gst_data_uri_src_set_uri (GstURIHandler * handler, const gchar * uri,
   /* uri must be an URI as defined in RFC 2397
    * data:[<mediatype>][;base64],<data>
    */
-  if (strncmp ("data:", uri, 5) != 0)
+  if (g_ascii_strncasecmp ("data:", uri, 5) != 0)
     goto invalid_uri;
 
   uri += 5;
@@ -344,6 +347,9 @@ gst_data_uri_src_set_uri (GstURIHandler * handler, const gchar * uri,
   if (data_start == NULL)
     goto invalid_uri;
 
+  if (parameters_start > data_start)
+    parameters_start = NULL;
+
   if (data_start != uri && parameters_start != uri)
     mimetype =
         g_strndup (uri,
@@ -385,7 +391,7 @@ gst_data_uri_src_set_uri (GstURIHandler * handler, const gchar * uri,
     bdata = g_uri_unescape_string (data_start, NULL);
     if (bdata == NULL)
       goto invalid_uri_encoded_data;
-    bsize = strlen (bdata) + 1;
+    bsize = strlen (bdata);
   }
   /* Convert to UTF8 */
   if (strcmp ("text/plain", mimetype) == 0 &&
@@ -396,7 +402,7 @@ gst_data_uri_src_set_uri (GstURIHandler * handler, const gchar * uri,
     gpointer data;
 
     data =
-        g_convert_with_fallback (bdata, -1, "UTF-8", charset, (char *) "*",
+        g_convert_with_fallback (bdata, bsize, "UTF-8", charset, (char *) "*",
         &read, &written, NULL);
     g_free (bdata);
 
index 2bdc43d..6d01bf9 100644 (file)
  * allocated filename.
  *
  * When the downloadbuffer has completely downloaded the media, it will
- * post an application message named  <classname>&quot;GstCacheDownloadComplete&quot;</classname>
+ * post an application message named `GstCacheDownloadComplete`
  * with the following information:
  *
- * *
- *   G_TYPE_STRING
- *   <classname>&quot;location&quot;</classname>:
- *   the location of the completely downloaded file.
+ * * G_TYPE_STRING `location`: the location of the completely downloaded file.
  *
  */
 
@@ -56,6 +53,7 @@
 #endif
 
 #include "gstdownloadbuffer.h"
+#include "gstcoreelementselements.h"
 
 #include <glib/gstdio.h>
 
@@ -173,6 +171,8 @@ enum
 #define gst_download_buffer_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstDownloadBuffer, gst_download_buffer,
     GST_TYPE_ELEMENT, _do_init);
+GST_ELEMENT_REGISTER_DEFINE (downloadbuffer, "downloadbuffer", GST_RANK_NONE,
+    GST_TYPE_DOWNLOAD_BUFFER);
 
 static GstMessage *update_buffering (GstDownloadBuffer * dlbuf);
 
@@ -235,12 +235,14 @@ gst_download_buffer_class_init (GstDownloadBufferClass * klass)
 
   g_object_class_install_property (gobject_class, PROP_LOW_PERCENT,
       g_param_spec_int ("low-percent", "Low percent",
-          "Low threshold for buffering to start. Only used if use-buffering is True",
+          "Low threshold for buffering to start. "
+          "Emits GST_MESSAGE_BUFFERING with a value of 0%",
           0, 100, DEFAULT_LOW_PERCENT,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_HIGH_PERCENT,
       g_param_spec_int ("high-percent", "High percent",
-          "High threshold for buffering to finish. Only used if use-buffering is True",
+          "High threshold for buffering to finish. "
+          "Emits GST_MESSAGE_BUFFERING with a value of 100%",
           0, 100, DEFAULT_HIGH_PERCENT,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
@@ -866,7 +868,7 @@ read_error:
     gst_buffer_unmap (buf, &info);
     if (*buffer == NULL)
       gst_buffer_unref (buf);
-    return ret;
+    return GST_FLOW_ERROR;
   }
 }
 
@@ -961,15 +963,17 @@ gst_download_buffer_close_temp_location_file (GstDownloadBuffer * dlbuf)
 
   GST_DEBUG_OBJECT (dlbuf, "closing sparse file");
 
+  gst_sparse_file_free (dlbuf->file);
+  dlbuf->file = NULL;
+  /* fd was closed by gst_sparse_file_free's fclose() */
+  dlbuf->temp_fd = -1;
+
   if (dlbuf->temp_remove) {
     if (remove (dlbuf->temp_location) < 0) {
       GST_WARNING_OBJECT (dlbuf, "Failed to remove temporary file %s: %s",
           dlbuf->temp_location, g_strerror (errno));
     }
   }
-  gst_sparse_file_free (dlbuf->file);
-  close (dlbuf->temp_fd);
-  dlbuf->file = NULL;
 }
 
 static void
@@ -1318,6 +1322,10 @@ gst_download_buffer_loop (GstPad * pad)
   /* have to lock for thread-safety */
   GST_DOWNLOAD_BUFFER_MUTEX_LOCK_CHECK (dlbuf, dlbuf->srcresult, out_flushing);
 
+  ret = gst_download_buffer_read_buffer (dlbuf, -1, -1, &buffer);
+  if (ret != GST_FLOW_OK)
+    goto out_flushing;
+
   if (dlbuf->stream_start_event != NULL) {
     gst_pad_push_event (dlbuf->srcpad, dlbuf->stream_start_event);
     dlbuf->stream_start_event = NULL;
@@ -1327,9 +1335,6 @@ gst_download_buffer_loop (GstPad * pad)
     dlbuf->segment_event = NULL;
   }
 
-  ret = gst_download_buffer_read_buffer (dlbuf, -1, -1, &buffer);
-  if (ret != GST_FLOW_OK)
-    goto out_flushing;
 
   /* update the buffering */
   msg = update_buffering (dlbuf);
diff --git a/plugins/elements/gstelements.c b/plugins/elements/gstelements.c
deleted file mode 100644 (file)
index e559803..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wtay@chello.be>
- *
- * gstelements.c:
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include <gst/gst.h>
-
-#include "gstcapsfilter.h"
-#include "gstclocksync.h"
-#include "gstconcat.h"
-#include "gstdataurisrc.h"
-#include "gstdownloadbuffer.h"
-#include "gstfakesink.h"
-#include "gstfakesrc.h"
-#include "gstfdsrc.h"
-#include "gstfdsink.h"
-#include "gstfilesink.h"
-#include "gstfilesrc.h"
-#include "gstfunnel.h"
-#include "gstidentity.h"
-#include "gstinputselector.h"
-#include "gstoutputselector.h"
-#include "gstmultiqueue.h"
-#include "gstqueue.h"
-#include "gstqueue2.h"
-#include "gsttee.h"
-#include "gsttypefindelement.h"
-#include "gstvalve.h"
-#include "gststreamiddemux.h"
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  if (!gst_element_register (plugin, "capsfilter", GST_RANK_NONE,
-          gst_capsfilter_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "clocksync", GST_RANK_NONE,
-          gst_clock_sync_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "concat", GST_RANK_NONE,
-          gst_concat_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "dataurisrc", GST_RANK_PRIMARY,
-          gst_data_uri_src_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "downloadbuffer", GST_RANK_NONE,
-          gst_download_buffer_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "fakesrc", GST_RANK_NONE,
-          gst_fake_src_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "fakesink", GST_RANK_NONE,
-          gst_fake_sink_get_type ()))
-    return FALSE;
-#if defined(HAVE_SYS_SOCKET_H) || defined(_MSC_VER)
-  if (!gst_element_register (plugin, "fdsrc", GST_RANK_NONE,
-          gst_fd_src_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "fdsink", GST_RANK_NONE,
-          gst_fd_sink_get_type ()))
-    return FALSE;
-#endif
-  if (!gst_element_register (plugin, "filesrc", GST_RANK_PRIMARY,
-          gst_file_src_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "funnel", GST_RANK_NONE,
-          gst_funnel_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "identity", GST_RANK_NONE,
-          gst_identity_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "input-selector", GST_RANK_NONE,
-          gst_input_selector_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "output-selector", GST_RANK_NONE,
-          gst_output_selector_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "queue", GST_RANK_NONE,
-          gst_queue_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "queue2", GST_RANK_NONE,
-          gst_queue2_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "filesink", GST_RANK_PRIMARY,
-          gst_file_sink_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "tee", GST_RANK_NONE, gst_tee_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "typefind", GST_RANK_NONE,
-          gst_type_find_element_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "multiqueue", GST_RANK_NONE,
-          gst_multi_queue_get_type ()))
-    return FALSE;
-  if (!gst_element_register (plugin, "valve", GST_RANK_NONE,
-          gst_valve_get_type ()))
-    return FALSE;
-
-  if (!gst_element_register (plugin, "streamiddemux", GST_RANK_PRIMARY,
-          gst_streamid_demux_get_type ()))
-    return FALSE;
-
-  return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, coreelements,
-    "GStreamer core elements", plugin_init, VERSION, GST_LICENSE,
-    GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
index 64350d9..75cdcfd 100644 (file)
@@ -32,6 +32,7 @@
 #ifdef HAVE_SYS_UIO_H
 #include <sys/uio.h>
 #endif
+#include <sys/types.h>
 #include <errno.h>
 #include <string.h>
 #include <string.h>
 #include "gstelements_private.h"
 
 #ifdef G_OS_WIN32
+#  include <io.h>               /* lseek, open, close, read */
+#  undef lseek
+#  define lseek _lseeki64
+#  undef off_t
+#  define off_t guint64
 #  define WIN32_LEAN_AND_MEAN   /* prevents from including too many things */
 #  include <windows.h>
 #  undef WIN32_LEAN_AND_MEAN
@@ -161,7 +167,7 @@ gst_writev (gint fd, const struct iovec *iov, gint iovcnt, gsize total_bytes)
      * cases, and it's not clear how that can be reconciled with the
      * possibility of short writes, so in any case we might want to
      * simplify this later or just remove it. */
-    if (total_bytes <= FDSINK_MAX_MALLOC_SIZE) {
+    if (iovcnt > 1 && total_bytes <= FDSINK_MAX_MALLOC_SIZE) {
       gchar *mem, *p;
 
       if (total_bytes <= FDSINK_MAX_ALLOCA_SIZE)
@@ -200,67 +206,34 @@ gst_writev (gint fd, const struct iovec *iov, gint iovcnt, gsize total_bytes)
   return written;
 }
 
-static gsize
-fill_vectors (struct iovec *vecs, GstMapInfo * maps, guint n, GstBuffer * buf)
+static GstFlowReturn
+gst_writev_iovecs (GstObject * sink, gint fd, GstPoll * fdset,
+    struct iovec *vecs, guint n_vecs, gsize bytes_to_write,
+    guint64 * bytes_written, gint max_transient_error_timeout,
+    guint64 current_position, gboolean * flushing)
 {
-  GstMemory *mem;
-  gsize size = 0;
-  guint i;
-
-  g_assert (gst_buffer_n_memory (buf) == n);
-
-  for (i = 0; i < n; ++i) {
-    mem = gst_buffer_peek_memory (buf, i);
-    if (gst_memory_map (mem, &maps[i], GST_MAP_READ)) {
-      vecs[i].iov_base = maps[i].data;
-      vecs[i].iov_len = maps[i].size;
-    } else {
-      GST_WARNING ("Failed to map memory %p for reading", mem);
-      vecs[i].iov_base = (void *) "";
-      vecs[i].iov_len = 0;
-    }
-    size += vecs[i].iov_len;
-  }
-
-  return size;
-}
-
-GstFlowReturn
-gst_writev_buffers (GstObject * sink, gint fd, GstPoll * fdset,
-    GstBuffer ** buffers, guint num_buffers, guint8 * mem_nums,
-    guint total_mem_num, guint64 * bytes_written, guint64 skip)
-{
-  struct iovec *vecs;
-  GstMapInfo *map_infos;
   GstFlowReturn flow_ret;
-  gsize size = 0;
-  guint i, j;
-
-  GST_LOG_OBJECT (sink, "%u buffers, %u memories", num_buffers, total_mem_num);
+  gint64 start_time = 0;
 
-  vecs = g_newa (struct iovec, total_mem_num);
-  map_infos = g_newa (GstMapInfo, total_mem_num);
+  *bytes_written = 0;
+  max_transient_error_timeout *= 1000;
+  if (max_transient_error_timeout)
+    start_time = g_get_monotonic_time ();
 
-  /* populate output vectors */
-  for (i = 0, j = 0; i < num_buffers; ++i) {
-    size += fill_vectors (&vecs[j], &map_infos[j], mem_nums[i], buffers[i]);
-    j += mem_nums[i];
-  }
+  GST_LOG_OBJECT (sink, "%u iovecs", n_vecs);
 
   /* now write it all out! */
   {
     gssize ret, left;
-    guint n_vecs = total_mem_num;
 
-    left = size;
-
-    if (skip) {
-      ret = skip;
-      errno = 0;
-      goto skip_first;
-    }
+    left = bytes_to_write;
 
     do {
+      if (flushing != NULL && g_atomic_int_get (flushing)) {
+        GST_DEBUG_OBJECT (sink, "Flushing, exiting loop");
+        flow_ret = GST_FLOW_FLUSHING;
+        goto out;
+      }
 #ifndef HAVE_WIN32
       if (fdset != NULL) {
         do {
@@ -281,34 +254,49 @@ gst_writev_buffers (GstObject * sink, gint fd, GstPoll * fdset,
       ret = gst_writev (fd, vecs, n_vecs, left);
 
       if (ret > 0) {
-        if (bytes_written)
-          *bytes_written += ret;
-      }
-
-    skip_first:
-
-      if (ret == left)
+        /* Wrote something, allow the caller to update the vecs passed here */
+        *bytes_written = ret;
         break;
+      }
 
-      if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
+      if (errno == EAGAIN || errno == EWOULDBLOCK || ret == 0) {
         /* do nothing, try again */
-      } else if (ret < 0) {
-        goto write_error;
-      } else if (ret < left) {
-        /* skip vectors that have been written in full */
-        while (ret >= vecs[0].iov_len) {
-          ret -= vecs[0].iov_len;
-          left -= vecs[0].iov_len;
-          ++vecs;
-          --n_vecs;
+        if (max_transient_error_timeout)
+          start_time = g_get_monotonic_time ();
+      } else if (errno == EACCES && max_transient_error_timeout > 0) {
+        /* seek back to where we started writing and try again after sleeping
+         * for 10ms.
+         *
+         * Some network file systems report EACCES spuriously, presumably
+         * because at the same time another client is reading the file.
+         * It happens at least on Linux and macOS on SMB/CIFS and NFS file
+         * systems.
+         *
+         * Note that NFS does not check access permissions during open()
+         * but only on write()/read() according to open(2), so we would
+         * loop here in case of NFS.
+         */
+        if (g_get_monotonic_time () > start_time + max_transient_error_timeout) {
+          GST_ERROR_OBJECT (sink, "Got EACCES for more than %dms, failing",
+              max_transient_error_timeout);
+          goto write_error;
         }
-        g_assert (n_vecs > 0);
-        /* skip partially written vector data */
-        if (ret > 0) {
-          vecs[0].iov_len -= ret;
-          vecs[0].iov_base = ((guint8 *) vecs[0].iov_base) + ret;
-          left -= ret;
+        GST_DEBUG_OBJECT (sink, "got EACCES, retry after 10ms sleep");
+        g_assert (current_position != -1);
+        g_usleep (10000);
+
+        /* Seek back to the current position, sometimes a partial write
+         * happened and we have no idea how much and if what was written
+         * is actually correct (it sometimes isn't)
+         */
+        ret = lseek (fd, current_position, SEEK_SET);
+        if (ret < 0 || ret != current_position) {
+          GST_ERROR_OBJECT (sink,
+              "failed to seek back to current write position");
+          goto write_error;
         }
+      } else {
+        goto write_error;
       }
 #ifdef HAVE_WIN32
       /* do short sleep on windows where we don't use gst_poll(),
@@ -316,7 +304,6 @@ gst_writev_buffers (GstObject * sink, gint fd, GstPoll * fdset,
       if (fdset != NULL)
         g_usleep (1000);
 #endif
-
     }
     while (left > 0);
   }
@@ -325,9 +312,6 @@ gst_writev_buffers (GstObject * sink, gint fd, GstPoll * fdset,
 
 out:
 
-  for (i = 0; i < total_mem_num; ++i)
-    gst_memory_unmap (map_infos[i].memory, &map_infos[i]);
-
   return flow_ret;
 
 /* ERRORS */
@@ -363,3 +347,293 @@ write_error:
     goto out;
   }
 }
+
+GstFlowReturn
+gst_writev_buffer (GstObject * sink, gint fd, GstPoll * fdset,
+    GstBuffer * buffer,
+    guint64 * bytes_written, guint64 skip,
+    gint max_transient_error_timeout, guint64 current_position,
+    gboolean * flushing)
+{
+  GstFlowReturn flow_ret = GST_FLOW_OK;
+  struct iovec *vecs;
+  GstMapInfo *maps;
+  guint i, num_mem, num_vecs;
+  gsize left = 0;
+
+  /* Buffers can contain up to 16 memories, so we can safely directly call
+   * writev() here without splitting up */
+  g_assert (gst_buffer_get_max_memory () <= GST_IOV_MAX);
+
+  num_mem = num_vecs = gst_buffer_n_memory (buffer);
+
+  GST_DEBUG ("Writing buffer %p with %u memories and %" G_GSIZE_FORMAT " bytes",
+      buffer, num_mem, gst_buffer_get_size (buffer));
+
+  vecs = g_newa (struct iovec, num_mem);
+  maps = g_newa (GstMapInfo, num_mem);
+
+  /* Map all memories */
+  {
+    GstMemory *mem;
+    guint i;
+
+    for (i = 0; i < num_mem; ++i) {
+      mem = gst_buffer_peek_memory (buffer, i);
+      if (gst_memory_map (mem, &maps[i], GST_MAP_READ)) {
+        vecs[i].iov_base = maps[i].data;
+        vecs[i].iov_len = maps[i].size;
+      } else {
+        GST_WARNING ("Failed to map memory %p for reading", mem);
+        vecs[i].iov_base = (void *) "";
+        vecs[i].iov_len = 0;
+      }
+      left += vecs[i].iov_len;
+    }
+  }
+
+  do {
+    guint64 bytes_written_local = 0;
+
+    flow_ret =
+        gst_writev_iovecs (sink, fd, fdset, vecs, num_vecs, left,
+        &bytes_written_local, max_transient_error_timeout, current_position,
+        flushing);
+
+    GST_DEBUG ("Wrote %" G_GUINT64_FORMAT " bytes of %" G_GSIZE_FORMAT ": %s",
+        bytes_written_local, left, gst_flow_get_name (flow_ret));
+
+    if (flow_ret != GST_FLOW_OK) {
+      g_assert (bytes_written_local == 0);
+      break;
+    }
+
+    if (bytes_written)
+      *bytes_written += bytes_written_local;
+
+    /* Done, no need to do bookkeeping */
+    if (bytes_written_local == left)
+      break;
+
+    /* skip vectors that have been written in full */
+    while (bytes_written_local >= vecs[0].iov_len) {
+      bytes_written_local -= vecs[0].iov_len;
+      left -= vecs[0].iov_len;
+      ++vecs;
+      --num_vecs;
+    }
+    g_assert (num_vecs > 0);
+    /* skip partially written vector data */
+    if (bytes_written_local > 0) {
+      vecs[0].iov_len -= bytes_written_local;
+      vecs[0].iov_base = ((guint8 *) vecs[0].iov_base) + bytes_written_local;
+      left -= bytes_written_local;
+    }
+  } while (left > 0);
+
+  for (i = 0; i < num_mem; i++)
+    gst_memory_unmap (maps[i].memory, &maps[i]);
+
+  return flow_ret;
+}
+
+GstFlowReturn
+gst_writev_mem (GstObject * sink, gint fd, GstPoll * fdset,
+    const guint8 * data, guint size,
+    guint64 * bytes_written, guint64 skip,
+    gint max_transient_error_timeout, guint64 current_position,
+    gboolean * flushing)
+{
+  GstFlowReturn flow_ret = GST_FLOW_OK;
+  struct iovec vec;
+  gsize left;
+
+  GST_DEBUG ("Writing memory %p with %u bytes", data, size);
+
+  vec.iov_len = size;
+  vec.iov_base = (guint8 *) data;
+  left = size;
+
+  do {
+    guint64 bytes_written_local = 0;
+
+    flow_ret =
+        gst_writev_iovecs (sink, fd, fdset, &vec, 1, left,
+        &bytes_written_local, max_transient_error_timeout, current_position,
+        flushing);
+
+    GST_DEBUG ("Wrote %" G_GUINT64_FORMAT " bytes of %" G_GSIZE_FORMAT ": %s",
+        bytes_written_local, left, gst_flow_get_name (flow_ret));
+
+    if (flow_ret != GST_FLOW_OK) {
+      g_assert (bytes_written_local == 0);
+      break;
+    }
+
+    if (bytes_written)
+      *bytes_written += bytes_written_local;
+
+    /* All done, no need for bookkeeping */
+    if (bytes_written_local == left)
+      break;
+
+    /* skip partially written vector data */
+    if (bytes_written_local < left) {
+      vec.iov_len -= bytes_written_local;
+      vec.iov_base = ((guint8 *) vec.iov_base) + bytes_written_local;
+      left -= bytes_written_local;
+    }
+  } while (left > 0);
+
+  return flow_ret;
+}
+
+GstFlowReturn
+gst_writev_buffer_list (GstObject * sink, gint fd, GstPoll * fdset,
+    GstBufferList * buffer_list,
+    guint64 * bytes_written, guint64 skip,
+    gint max_transient_error_timeout, guint64 current_position,
+    gboolean * flushing)
+{
+  GstFlowReturn flow_ret = GST_FLOW_OK;
+  struct iovec *vecs;
+  GstMapInfo *maps;
+  guint num_bufs, current_buf_idx = 0, current_buf_mem_idx = 0;
+  guint i, num_vecs;
+  gsize left = 0;
+
+  num_bufs = gst_buffer_list_length (buffer_list);
+  num_vecs = 0;
+
+  GST_DEBUG ("Writing buffer list %p with %u buffers", buffer_list, num_bufs);
+
+  vecs = g_newa (struct iovec, GST_IOV_MAX);
+  maps = g_newa (GstMapInfo, GST_IOV_MAX);
+
+  /* Map the first GST_IOV_MAX memories */
+  {
+    GstBuffer *buf;
+    GstMemory *mem;
+    guint j = 0;
+
+    for (i = 0; i < num_bufs && num_vecs < GST_IOV_MAX; i++) {
+      guint num_mem;
+
+      buf = gst_buffer_list_get (buffer_list, i);
+      num_mem = gst_buffer_n_memory (buf);
+
+      for (j = 0; j < num_mem && num_vecs < GST_IOV_MAX; j++) {
+        mem = gst_buffer_peek_memory (buf, j);
+        if (gst_memory_map (mem, &maps[num_vecs], GST_MAP_READ)) {
+          vecs[num_vecs].iov_base = maps[num_vecs].data;
+          vecs[num_vecs].iov_len = maps[num_vecs].size;
+        } else {
+          GST_WARNING ("Failed to map memory %p for reading", mem);
+          vecs[num_vecs].iov_base = (void *) "";
+          vecs[num_vecs].iov_len = 0;
+        }
+        left += vecs[num_vecs].iov_len;
+        num_vecs++;
+      }
+      current_buf_mem_idx = j;
+      if (j == num_mem)
+        current_buf_mem_idx = 0;
+    }
+    current_buf_idx = i;
+  }
+
+  do {
+    guint64 bytes_written_local = 0;
+    guint vecs_written = 0;
+
+    flow_ret =
+        gst_writev_iovecs (sink, fd, fdset, vecs, num_vecs, left,
+        &bytes_written_local, max_transient_error_timeout, current_position,
+        flushing);
+
+    GST_DEBUG ("Wrote %" G_GUINT64_FORMAT " bytes of %" G_GSIZE_FORMAT ": %s",
+        bytes_written_local, left, gst_flow_get_name (flow_ret));
+
+    if (flow_ret != GST_FLOW_OK) {
+      g_assert (bytes_written_local == 0);
+      break;
+    }
+
+    if (flow_ret != GST_FLOW_OK) {
+      g_assert (bytes_written_local == 0);
+      break;
+    }
+
+    if (bytes_written)
+      *bytes_written += bytes_written_local;
+
+    /* All done, no need for bookkeeping */
+    if (bytes_written_local == left && current_buf_idx == num_bufs)
+      break;
+
+    /* skip vectors that have been written in full */
+    while (vecs_written < num_vecs
+        && bytes_written_local >= vecs[vecs_written].iov_len) {
+      bytes_written_local -= vecs[vecs_written].iov_len;
+      left -= vecs[vecs_written].iov_len;
+      vecs_written++;
+    }
+    g_assert (vecs_written < num_vecs || bytes_written_local == 0);
+    /* skip partially written vector data */
+    if (bytes_written_local > 0) {
+      vecs[vecs_written].iov_len -= bytes_written_local;
+      vecs[vecs_written].iov_base =
+          ((guint8 *) vecs[0].iov_base) + bytes_written_local;
+      left -= bytes_written_local;
+    }
+
+    /* If we have buffers left, fill them in now */
+    if (current_buf_idx < num_bufs) {
+      GstBuffer *buf;
+      GstMemory *mem;
+      guint j = current_buf_mem_idx;
+
+      /* Unmap the first vecs_written memories now */
+      for (i = 0; i < vecs_written; i++)
+        gst_memory_unmap (maps[i].memory, &maps[i]);
+      /* Move upper remaining vecs and maps back to the beginning */
+      memmove (vecs, &vecs[vecs_written],
+          (num_vecs - vecs_written) * sizeof (vecs[0]));
+      memmove (maps, &maps[vecs_written],
+          (num_vecs - vecs_written) * sizeof (maps[0]));
+      num_vecs -= vecs_written;
+
+      /* And finally refill */
+      for (i = current_buf_idx; i < num_bufs && num_vecs < GST_IOV_MAX; i++) {
+        guint num_mem;
+
+        buf = gst_buffer_list_get (buffer_list, i);
+        num_mem = gst_buffer_n_memory (buf);
+
+        for (j = current_buf_mem_idx; j < num_mem && num_vecs < GST_IOV_MAX;
+            j++) {
+          mem = gst_buffer_peek_memory (buf, j);
+          if (gst_memory_map (mem, &maps[num_vecs], GST_MAP_READ)) {
+            vecs[num_vecs].iov_base = maps[num_vecs].data;
+            vecs[num_vecs].iov_len = maps[num_vecs].size;
+          } else {
+            GST_WARNING ("Failed to map memory %p for reading", mem);
+            vecs[num_vecs].iov_base = (void *) "";
+            vecs[num_vecs].iov_len = 0;
+          }
+          left += vecs[num_vecs].iov_len;
+          num_vecs++;
+        }
+        current_buf_mem_idx = j;
+        if (current_buf_mem_idx == num_mem)
+          current_buf_mem_idx = 0;
+      }
+      current_buf_idx = i;
+    }
+  } while (left > 0);
+
+  for (i = 0; i < num_vecs; i++)
+    gst_memory_unmap (maps[i].memory, &maps[i]);
+
+  return flow_ret;
+}
index d196594..0352943 100644 (file)
@@ -34,10 +34,25 @@ G_GNUC_INTERNAL
 gchar *   gst_buffer_get_meta_string (GstBuffer * buffer);
 
 G_GNUC_INTERNAL
-GstFlowReturn  gst_writev_buffers (GstObject * sink, gint fd, GstPoll * fdset,
-                                   GstBuffer ** buffers, guint num_buffers,
-                                   guint8 * mem_nums, guint total_mem_num,
-                                   guint64 * bytes_written, guint64 skip);
+GstFlowReturn  gst_writev_buffer (GstObject * sink, gint fd, GstPoll * fdset,
+                                  GstBuffer * buffer,
+                                  guint64 * bytes_written, guint64 skip,
+                                  gint max_transient_error_timeout, guint64 current_position,
+                                  gboolean * flushing);
+
+G_GNUC_INTERNAL
+GstFlowReturn  gst_writev_buffer_list (GstObject * sink, gint fd, GstPoll * fdset,
+                                       GstBufferList * buffer_list,
+                                       guint64 * bytes_written, guint64 skip,
+                                       gint max_transient_error_timeout, guint64 current_position,
+                                       gboolean * flushing);
+
+G_GNUC_INTERNAL
+GstFlowReturn  gst_writev_mem         (GstObject * sink, gint fd, GstPoll * fdset,
+                                       const guint8 *data, guint size,
+                                       guint64 * bytes_written, guint64 skip,
+                                       gint max_transient_error_timeout, guint64 current_position,
+                                       gboolean * flushing);
 
 G_END_DECLS
 
index 27f83f7..eb91f91 100644 (file)
 #  include "config.h"
 #endif
 
+#include <string.h>
+
 #include "gstelements_private.h"
 #include "gstfakesink.h"
-#include <string.h>
+#include "gstcoreelementselements.h"
 
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
@@ -120,6 +122,8 @@ gst_fake_sink_state_error_get_type (void)
 #define _do_init \
     GST_DEBUG_CATEGORY_INIT (gst_fake_sink_debug, "fakesink", 0, "fakesink element");
 #define gst_fake_sink_parent_class parent_class
+GST_ELEMENT_REGISTER_DEFINE (fakesink, "fakesink", GST_RANK_NONE,
+    GST_TYPE_FAKE_SINK);
 G_DEFINE_TYPE_WITH_CODE (GstFakeSink, gst_fake_sink, GST_TYPE_BASE_SINK,
     _do_init);
 
@@ -216,8 +220,8 @@ gst_fake_sink_class_init (GstFakeSinkClass * klass)
   gst_fake_sink_signals[SIGNAL_HANDOFF] =
       g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstFakeSinkClass, handoff), NULL, NULL,
-      g_cclosure_marshal_generic, G_TYPE_NONE, 2,
-      GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD);
+      NULL, G_TYPE_NONE, 2, GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE,
+      GST_TYPE_PAD);
 
   /**
    * GstFakeSink::preroll-handoff:
@@ -230,7 +234,7 @@ gst_fake_sink_class_init (GstFakeSinkClass * klass)
   gst_fake_sink_signals[SIGNAL_PREROLL_HANDOFF] =
       g_signal_new ("preroll-handoff", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstFakeSinkClass, preroll_handoff),
-      NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2,
+      NULL, NULL, NULL, G_TYPE_NONE, 2,
       GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD);
 
   gst_element_class_set_static_metadata (gstelement_class,
@@ -254,6 +258,8 @@ gst_fake_sink_class_init (GstFakeSinkClass * klass)
   gstbase_sink_class->set_caps = GST_DEBUG_FUNCPTR (gst_fake_sink_set_caps);
   gstbase_sink_class->get_times = GST_DEBUG_FUNCPTR (gst_fake_sink_get_times);
 #endif
+
+  gst_type_mark_as_plugin_api (GST_TYPE_FAKE_SINK_STATE_ERROR, 0);
 }
 
 static void
index 14f3226..24c2766 100644 (file)
@@ -28,7 +28,7 @@
  * a wide range of buffers and can operate in various scheduling modes.
  *
  * It is mostly used as a testing element, one trivial example for testing
- * basic <application>GStreamer</application> core functionality is:
+ * basic GStreamer core functionality is:
  *
  * ## Example launch line
  * |[
@@ -51,6 +51,7 @@
 
 #include "gstelements_private.h"
 #include "gstfakesrc.h"
+#include "gstcoreelementselements.h"
 
 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
@@ -203,6 +204,8 @@ gst_fake_src_filltype_get_type (void)
     GST_DEBUG_CATEGORY_INIT (gst_fake_src_debug, "fakesrc", 0, "fakesrc element");
 #define gst_fake_src_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstFakeSrc, gst_fake_src, GST_TYPE_BASE_SRC, _do_init);
+GST_ELEMENT_REGISTER_DEFINE (fakesrc, "fakesrc", GST_RANK_NONE,
+    GST_TYPE_FAKE_SRC);
 
 static void gst_fake_src_finalize (GObject * object);
 static void gst_fake_src_set_property (GObject * object, guint prop_id,
@@ -332,8 +335,8 @@ gst_fake_src_class_init (GstFakeSrcClass * klass)
   gst_fake_src_signals[SIGNAL_HANDOFF] =
       g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstFakeSrcClass, handoff), NULL, NULL,
-      g_cclosure_marshal_generic, G_TYPE_NONE, 2,
-      GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD);
+      NULL, G_TYPE_NONE, 2, GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE,
+      GST_TYPE_PAD);
 
   gst_element_class_set_static_metadata (gstelement_class,
       "Fake Source",
@@ -348,6 +351,10 @@ gst_fake_src_class_init (GstFakeSrcClass * klass)
   gstbase_src_class->event = GST_DEBUG_FUNCPTR (gst_fake_src_event_handler);
   gstbase_src_class->get_times = GST_DEBUG_FUNCPTR (gst_fake_src_get_times);
   gstbase_src_class->create = GST_DEBUG_FUNCPTR (gst_fake_src_create);
+
+  gst_type_mark_as_plugin_api (GST_TYPE_FAKE_SRC_DATA, 0);
+  gst_type_mark_as_plugin_api (GST_TYPE_FAKE_SRC_SIZETYPE, 0);
+  gst_type_mark_as_plugin_api (GST_TYPE_FAKE_SRC_FILLTYPE, 0);
 }
 
 static void
index 7641cde..ad69ec0 100644 (file)
@@ -60,6 +60,7 @@
 
 #include "gstfdsink.h"
 #include "gstelements_private.h"
+#include "gstcoreelementselements.h"
 
 #ifdef G_OS_WIN32
 #include <io.h>                 /* lseek, open, close, read */
 #define off_t guint64
 #endif
 
+#define struct_stat struct stat
+
 #if defined(__BIONIC__)         /* Android */
 #if defined(__ANDROID_API__) && __ANDROID_API__ >= 21
 #undef fstat
 #define fstat fstat64
+#undef struct_stat
+#define struct_stat struct stat64
 #endif
 #endif
 
@@ -106,6 +111,9 @@ static void gst_fd_sink_uri_handler_init (gpointer g_iface,
   GST_DEBUG_CATEGORY_INIT (gst_fd_sink__debug, "fdsink", 0, "fdsink element");
 #define gst_fd_sink_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstFdSink, gst_fd_sink, GST_TYPE_BASE_SINK, _do_init);
+#if defined(HAVE_SYS_SOCKET_H) || defined(_MSC_VER)
+GST_ELEMENT_REGISTER_DEFINE (fdsink, "fdsink", GST_RANK_NONE, GST_TYPE_FD_SINK);
+#endif
 
 static void gst_fd_sink_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
@@ -166,7 +174,6 @@ gst_fd_sink_init (GstFdSink * fdsink)
 {
   fdsink->fd = 1;
   fdsink->uri = g_strdup_printf ("fd://%d", fdsink->fd);
-  fdsink->bytes_written = 0;
   fdsink->current_pos = 0;
 
   gst_base_sink_set_sync (GST_BASE_SINK (fdsink), FALSE);
@@ -239,23 +246,29 @@ gst_fd_sink_query (GstBaseSink * bsink, GstQuery * query)
 }
 
 static GstFlowReturn
-gst_fd_sink_render_buffers (GstFdSink * sink, GstBuffer ** buffers,
-    guint num_buffers, guint8 * mem_nums, guint total_mems)
+gst_fd_sink_render_list (GstBaseSink * bsink, GstBufferList * buffer_list)
 {
+  GstFdSink *sink;
   GstFlowReturn ret;
   guint64 skip = 0;
+  guint num_buffers;
+
+  sink = GST_FD_SINK_CAST (bsink);
+
+  num_buffers = gst_buffer_list_length (buffer_list);
+  if (num_buffers == 0)
+    goto no_data;
 
   for (;;) {
     guint64 bytes_written = 0;
 
-    ret = gst_writev_buffers (GST_OBJECT_CAST (sink), sink->fd, sink->fdset,
-        buffers, num_buffers, mem_nums, total_mems, &bytes_written, skip);
+    ret = gst_writev_buffer_list (GST_OBJECT_CAST (sink), sink->fd, sink->fdset,
+        buffer_list, &bytes_written, skip, 0, -1, NULL);
 
-    sink->bytes_written += bytes_written;
     sink->current_pos += bytes_written;
     skip += bytes_written;
 
-    if (!sink->unlock)
+    if (!sink->unlock || ret != GST_FLOW_FLUSHING)
       break;
 
     ret = gst_base_sink_wait_preroll (GST_BASE_SINK (sink));
@@ -264,38 +277,6 @@ gst_fd_sink_render_buffers (GstFdSink * sink, GstBuffer ** buffers,
   }
 
   return ret;
-}
-
-static GstFlowReturn
-gst_fd_sink_render_list (GstBaseSink * bsink, GstBufferList * buffer_list)
-{
-  GstFlowReturn flow;
-  GstBuffer **buffers;
-  GstFdSink *sink;
-  guint8 *mem_nums;
-  guint total_mems;
-  guint i, num_buffers;
-
-  sink = GST_FD_SINK_CAST (bsink);
-
-  num_buffers = gst_buffer_list_length (buffer_list);
-  if (num_buffers == 0)
-    goto no_data;
-
-  /* extract buffers from list and count memories */
-  buffers = g_newa (GstBuffer *, num_buffers);
-  mem_nums = g_newa (guint8, num_buffers);
-  for (i = 0, total_mems = 0; i < num_buffers; ++i) {
-    buffers[i] = gst_buffer_list_get (buffer_list, i);
-    mem_nums[i] = gst_buffer_n_memory (buffers[i]);
-    total_mems += mem_nums[i];
-  }
-
-  flow =
-      gst_fd_sink_render_buffers (sink, buffers, num_buffers, mem_nums,
-      total_mems);
-
-  return flow;
 
 no_data:
   {
@@ -307,26 +288,36 @@ no_data:
 static GstFlowReturn
 gst_fd_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
 {
-  GstFlowReturn flow;
   GstFdSink *sink;
-  guint8 n_mem;
+  GstFlowReturn ret;
+  guint64 skip = 0;
 
   sink = GST_FD_SINK_CAST (bsink);
 
-  n_mem = gst_buffer_n_memory (buffer);
+  for (;;) {
+    guint64 bytes_written = 0;
+
+    ret = gst_writev_buffer (GST_OBJECT_CAST (sink), sink->fd, sink->fdset,
+        buffer, &bytes_written, skip, 0, -1, NULL);
 
-  if (n_mem > 0)
-    flow = gst_fd_sink_render_buffers (sink, &buffer, 1, &n_mem, n_mem);
-  else
-    flow = GST_FLOW_OK;
+    sink->current_pos += bytes_written;
+    skip += bytes_written;
+
+    if (!sink->unlock || ret != GST_FLOW_FLUSHING)
+      break;
+
+    ret = gst_base_sink_wait_preroll (GST_BASE_SINK (sink));
+    if (ret != GST_FLOW_OK)
+      return ret;
+  }
 
-  return flow;
+  return ret;
 }
 
 static gboolean
 gst_fd_sink_check_fd (GstFdSink * fdsink, int fd, GError ** error)
 {
-  struct stat stat_results;
+  struct_stat stat_results;
   off_t result;
 
   /* see that it is a valid file descriptor */
@@ -384,7 +375,6 @@ gst_fd_sink_start (GstBaseSink * basesink)
   gst_poll_add_fd (fdsink->fdset, &fd);
   gst_poll_fd_ctl_write (fdsink->fdset, &fd, TRUE);
 
-  fdsink->bytes_written = 0;
   fdsink->current_pos = 0;
 
   fdsink->seekable = gst_fd_sink_do_seek (fdsink, 0);
index c038ce0..e0ab006 100644 (file)
@@ -58,7 +58,6 @@ struct _GstFdSink {
   GstPoll *fdset;
 
   int fd;
-  guint64 bytes_written;
   guint64 current_pos;
 
   gboolean seekable;
index 6d61efe..f88d38e 100644 (file)
@@ -31,7 +31,7 @@
  * The above mentioned pipeline should dump data packets to the console.
  *
  * If the #GstFdSrc:timeout property is set to a value bigger than 0, fdsrc will
- * generate an element message named <classname>&quot;GstFdSrcTimeout&quot;</classname>
+ * generate an element message named `GstFdSrcTimeout`
  * if no data was received in the given timeout.
  *
  * The message's structure contains one field:
 #include <errno.h>
 
 #include "gstfdsrc.h"
+#include "gstcoreelementselements.h"
+
+#define struct_stat struct stat
 
 #ifdef __BIONIC__               /* Android */
 #if defined(__ANDROID_API__) && __ANDROID_API__ >= 21
 #undef fstat
 #define fstat fstat64
+#undef struct_stat
+#define struct_stat struct stat64
 #endif
 #endif
 
@@ -115,6 +120,9 @@ static void gst_fd_src_uri_handler_init (gpointer g_iface, gpointer iface_data);
   GST_DEBUG_CATEGORY_INIT (gst_fd_src_debug, "fdsrc", 0, "fdsrc element");
 #define gst_fd_src_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstFdSrc, gst_fd_src, GST_TYPE_PUSH_SRC, _do_init);
+#if defined(HAVE_SYS_SOCKET_H) || defined(_MSC_VER)
+GST_ELEMENT_REGISTER_DEFINE (fdsrc, "fdsrc", GST_RANK_NONE, GST_TYPE_FD_SRC);
+#endif
 
 static void gst_fd_src_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
@@ -208,7 +216,7 @@ gst_fd_src_dispose (GObject * obj)
 static void
 gst_fd_src_update_fd (GstFdSrc * src, guint64 size)
 {
-  struct stat stat_results;
+  struct_stat stat_results;
 
   GST_DEBUG_OBJECT (src, "fdset %p, old_fd %d, new_fd %d", src->fdset, src->fd,
       src->new_fd);
@@ -544,7 +552,7 @@ static gboolean
 gst_fd_src_get_size (GstBaseSrc * bsrc, guint64 * size)
 {
   GstFdSrc *src = GST_FD_SRC (bsrc);
-  struct stat stat_results;
+  struct_stat stat_results;
 
   if (src->size != -1) {
     *size = src->size;
index 90e4fa8..8023880 100644 (file)
@@ -41,6 +41,7 @@
 #include "../../gst/gst-i18n-lib.h"
 
 #include <gst/gst.h>
+#include <glib/gstdio.h>
 #include <stdio.h>              /* for fseeko() */
 #ifdef HAVE_STDIO_EXT_H
 #include <stdio_ext.h>          /* for __fbufsize, for debugging */
@@ -49,6 +50,7 @@
 #include "gstfilesink.h"
 #include <string.h>
 #include <sys/types.h>
+#include <fcntl.h>
 
 #ifdef G_OS_WIN32
 #include <io.h>                 /* lseek, open, close, read */
@@ -72,6 +74,7 @@
 
 #include "gstelements_private.h"
 #include "gstfilesink.h"
+#include "gstcoreelementselements.h"
 
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
@@ -106,6 +109,8 @@ GST_DEBUG_CATEGORY_STATIC (gst_file_sink_debug);
 #define DEFAULT_BUFFER_MODE    GST_FILE_SINK_BUFFER_MODE_DEFAULT
 #define DEFAULT_BUFFER_SIZE    64 * 1024
 #define DEFAULT_APPEND         FALSE
+#define DEFAULT_O_SYNC         FALSE
+#define DEFAULT_MAX_TRANSIENT_ERROR_TIMEOUT    0
 
 enum
 {
@@ -117,6 +122,8 @@ enum
 #ifdef TIZEN_FEATURE_FILESINK_MODIFICATION
   PROP_CURRENT_BYTES,
 #endif
+  PROP_O_SYNC,
+  PROP_MAX_TRANSIENT_ERROR_TIMEOUT,
   PROP_LAST
 };
 
@@ -124,37 +131,33 @@ enum
  * use the 'file pointer' opened in glib (and returned from this function)
  * in this library, as they may have unrelated C runtimes. */
 static FILE *
-gst_fopen (const gchar * filename, const gchar * mode)
+gst_fopen (const gchar * filename, const gchar * mode, gboolean o_sync)
 {
-#ifdef G_OS_WIN32
-  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
-  wchar_t *wmode;
   FILE *retval;
-  int save_errno;
-
-  if (wfilename == NULL) {
-    errno = EINVAL;
-    return NULL;
-  }
-
-  wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
+#ifdef G_OS_WIN32
+  retval = g_fopen (filename, mode);
+  return retval;
+#else
+  int fd;
+  int flags = O_CREAT | O_WRONLY;
 
-  if (wmode == NULL) {
-    g_free (wfilename);
-    errno = EINVAL;
-    return NULL;
-  }
+  /* NOTE: below code is for handing spurious EACCES return on write
+   * See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/143
+   */
+  if (strcmp (mode, "wb") == 0)
+    flags |= O_TRUNC;
+  else if (strcmp (mode, "ab") == 0)
+    flags |= O_APPEND;
+  else
+    g_assert_not_reached ();
 
-  retval = _wfopen (wfilename, wmode);
-  save_errno = errno;
+  if (o_sync)
+    flags |= O_SYNC;
 
-  g_free (wfilename);
-  g_free (wmode);
+  fd = open (filename, flags, 0666);
 
-  errno = save_errno;
+  retval = fdopen (fd, mode);
   return retval;
-#else
-  return fopen (filename, mode);
 #endif
 }
 
@@ -175,6 +178,8 @@ static GstFlowReturn gst_file_sink_render (GstBaseSink * sink,
     GstBuffer * buffer);
 static GstFlowReturn gst_file_sink_render_list (GstBaseSink * sink,
     GstBufferList * list);
+static gboolean gst_file_sink_unlock (GstBaseSink * sink);
+static gboolean gst_file_sink_unlock_stop (GstBaseSink * sink);
 
 static gboolean gst_file_sink_do_seek (GstFileSink * filesink,
     guint64 new_offset);
@@ -194,6 +199,8 @@ static GstFlowReturn gst_file_sink_flush_buffer (GstFileSink * filesink);
 #define gst_file_sink_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstFileSink, gst_file_sink, GST_TYPE_BASE_SINK,
     _do_init);
+GST_ELEMENT_REGISTER_DEFINE (filesink, "filesink", GST_RANK_PRIMARY,
+    GST_TYPE_FILE_SINK);
 
 static void
 gst_file_sink_class_init (GstFileSinkClass * klass)
@@ -240,6 +247,19 @@ gst_file_sink_class_init (GstFileSinkClass * klass)
           "Append to an already existing file", DEFAULT_APPEND,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_class, PROP_O_SYNC,
+      g_param_spec_boolean ("o-sync", "Synchronous IO",
+          "Open the file with O_SYNC for enabling synchronous IO",
+          DEFAULT_O_SYNC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class,
+      PROP_MAX_TRANSIENT_ERROR_TIMEOUT,
+      g_param_spec_int ("max-transient-error-timeout",
+          "Max Transient Error Timeout",
+          "Retry up to this many ms on transient errors (currently EACCES)", 0,
+          G_MAXINT, DEFAULT_MAX_TRANSIENT_ERROR_TIMEOUT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   gst_element_class_set_static_metadata (gstelement_class,
       "File Sink",
       "Sink/File", "Write stream to a file",
@@ -253,11 +273,16 @@ gst_file_sink_class_init (GstFileSinkClass * klass)
   gstbasesink_class->render_list =
       GST_DEBUG_FUNCPTR (gst_file_sink_render_list);
   gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_file_sink_event);
+  gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_file_sink_unlock);
+  gstbasesink_class->unlock_stop =
+      GST_DEBUG_FUNCPTR (gst_file_sink_unlock_stop);
 
   if (sizeof (off_t) < 8) {
     GST_LOG ("No large file support, sizeof (off_t) = %" G_GSIZE_FORMAT "!",
         sizeof (off_t));
   }
+
+  gst_type_mark_as_plugin_api (GST_TYPE_FILE_SINK_BUFFER_MODE, 0);
 }
 
 static void
@@ -340,6 +365,12 @@ gst_file_sink_set_property (GObject * object, guint prop_id,
     case PROP_APPEND:
       sink->append = g_value_get_boolean (value);
       break;
+    case PROP_O_SYNC:
+      sink->o_sync = g_value_get_boolean (value);
+      break;
+    case PROP_MAX_TRANSIENT_ERROR_TIMEOUT:
+      sink->max_transient_error_timeout = g_value_get_int (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -370,6 +401,12 @@ gst_file_sink_get_property (GObject * object, guint prop_id, GValue * value,
       g_value_set_uint64(value, sink->current_pos);
       break;
 #endif
+    case PROP_O_SYNC:
+      g_value_set_boolean (value, sink->o_sync);
+      break;
+    case PROP_MAX_TRANSIENT_ERROR_TIMEOUT:
+      g_value_set_int (value, sink->max_transient_error_timeout);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -384,9 +421,9 @@ gst_file_sink_open_file (GstFileSink * sink)
     goto no_filename;
 
   if (sink->append)
-    sink->file = gst_fopen (sink->filename, "ab");
+    sink->file = gst_fopen (sink->filename, "ab", sink->o_sync);
   else
-    sink->file = gst_fopen (sink->filename, "wb");
+    sink->file = gst_fopen (sink->filename, "wb", sink->o_sync);
   if (sink->file == NULL)
     goto open_failed;
 
@@ -395,15 +432,24 @@ gst_file_sink_open_file (GstFileSink * sink)
   sink->seekable = gst_file_sink_do_seek (sink, 0);
 
   if (sink->buffer)
-    gst_buffer_list_unref (sink->buffer);
+    g_free (sink->buffer);
   sink->buffer = NULL;
+  if (sink->buffer_list)
+    gst_buffer_list_unref (sink->buffer_list);
+  sink->buffer_list = NULL;
+
   if (sink->buffer_mode != GST_FILE_SINK_BUFFER_MODE_UNBUFFERED) {
     if (sink->buffer_size == 0) {
       sink->buffer_size = DEFAULT_BUFFER_SIZE;
       g_object_notify (G_OBJECT (sink), "buffer-size");
     }
 
-    sink->buffer = gst_buffer_list_new ();
+    if (sink->buffer_mode == GST_FILE_SINK_BUFFER_MODE_FULL) {
+      sink->buffer = g_malloc (sink->buffer_size);
+      sink->allocated_buffer_size = sink->buffer_size;
+    } else {
+      sink->buffer_list = gst_buffer_list_new ();
+    }
     sink->current_buffer_size = 0;
   }
 
@@ -445,9 +491,15 @@ gst_file_sink_close_file (GstFileSink * sink)
   }
 
   if (sink->buffer) {
-    gst_buffer_list_unref (sink->buffer);
+    g_free (sink->buffer);
     sink->buffer = NULL;
   }
+  sink->allocated_buffer_size = 0;
+
+  if (sink->buffer_list) {
+    gst_buffer_list_unref (sink->buffer_list);
+    sink->buffer_list = NULL;
+  }
   sink->current_buffer_size = 0;
 }
 
@@ -597,11 +649,11 @@ gst_file_sink_event (GstBaseSink * sink, GstEvent * event)
         if (ftruncate (fileno (filesink->file), 0))
           goto truncate_failed;
       }
-      if (filesink->buffer) {
-        gst_buffer_list_unref (filesink->buffer);
-        filesink->buffer = gst_buffer_list_new ();
-        filesink->current_buffer_size = 0;
+      if (filesink->buffer_list) {
+        gst_buffer_list_unref (filesink->buffer_list);
+        filesink->buffer_list = gst_buffer_list_new ();
       }
+      filesink->current_buffer_size = 0;
       break;
     case GST_EVENT_EOS:
       if (gst_file_sink_flush_buffer (filesink) != GST_FLOW_OK)
@@ -664,46 +716,40 @@ gst_file_sink_get_current_offset (GstFileSink * filesink, guint64 * p_pos)
 }
 
 static GstFlowReturn
-gst_file_sink_render_buffers (GstFileSink * sink, GstBuffer ** buffers,
-    guint num_buffers, guint8 * mem_nums, guint total_mems, gsize size)
-{
-  GST_DEBUG_OBJECT (sink,
-      "writing %u buffers (%u memories, %" G_GSIZE_FORMAT
-      " bytes) at position %" G_GUINT64_FORMAT, num_buffers, total_mems, size,
-      sink->current_pos);
-
-  return gst_writev_buffers (GST_OBJECT_CAST (sink), fileno (sink->file), NULL,
-      buffers, num_buffers, mem_nums, total_mems, &sink->current_pos, 0);
-}
-
-static GstFlowReturn
 gst_file_sink_render_list_internal (GstFileSink * sink,
     GstBufferList * buffer_list)
 {
   GstFlowReturn flow;
-  GstBuffer **buffers;
-  guint8 *mem_nums;
-  guint total_mems;
-  gsize total_size = 0;
-  guint i, num_buffers;
+  guint num_buffers;
+  guint64 skip = 0;
 
   num_buffers = gst_buffer_list_length (buffer_list);
   if (num_buffers == 0)
     goto no_data;
 
-  /* extract buffers from list and count memories */
-  buffers = g_newa (GstBuffer *, num_buffers);
-  mem_nums = g_newa (guint8, num_buffers);
-  for (i = 0, total_mems = 0; i < num_buffers; ++i) {
-    buffers[i] = gst_buffer_list_get (buffer_list, i);
-    mem_nums[i] = gst_buffer_n_memory (buffers[i]);
-    total_mems += mem_nums[i];
-    total_size += gst_buffer_get_size (buffers[i]);
-  }
+  GST_DEBUG_OBJECT (sink,
+      "writing %u buffers at position %" G_GUINT64_FORMAT, num_buffers,
+      sink->current_pos);
+
+  for (;;) {
+    guint64 bytes_written = 0;
+
+    flow =
+        gst_writev_buffer_list (GST_OBJECT_CAST (sink), fileno (sink->file),
+        NULL, buffer_list, &bytes_written, skip,
+        sink->max_transient_error_timeout, sink->current_pos, &sink->flushing);
+
+    sink->current_pos += bytes_written;
+    skip += bytes_written;
+
+    if (flow != GST_FLOW_FLUSHING)
+      break;
+
+    flow = gst_base_sink_wait_preroll (GST_BASE_SINK (sink));
 
-  flow =
-      gst_file_sink_render_buffers (sink, buffers, num_buffers, mem_nums,
-      total_mems, total_size);
+    if (flow != GST_FLOW_OK)
+      return flow;
+  }
 
   return flow;
 
@@ -719,23 +765,47 @@ gst_file_sink_flush_buffer (GstFileSink * filesink)
 {
   GstFlowReturn flow_ret = GST_FLOW_OK;
 
-  if (filesink->buffer) {
+  GST_DEBUG_OBJECT (filesink, "Flushing out buffer of size %" G_GSIZE_FORMAT,
+      filesink->current_buffer_size);
+
+  if (filesink->buffer && filesink->current_buffer_size) {
+    guint64 skip = 0;
+
+    for (;;) {
+      guint64 bytes_written = 0;
+
+      flow_ret =
+          gst_writev_mem (GST_OBJECT_CAST (filesink), fileno (filesink->file),
+          NULL, filesink->buffer, filesink->current_buffer_size, &bytes_written,
+          skip, filesink->max_transient_error_timeout, filesink->current_pos,
+          &filesink->flushing);
+
+      filesink->current_pos += bytes_written;
+      skip += bytes_written;
+
+      if (flow_ret != GST_FLOW_FLUSHING)
+        break;
+
+      flow_ret = gst_base_sink_wait_preroll (GST_BASE_SINK (filesink));
+      if (flow_ret != GST_FLOW_OK)
+        break;
+    }
+  } else if (filesink->buffer_list && filesink->current_buffer_size) {
     guint length;
 
-    length = gst_buffer_list_length (filesink->buffer);
+    length = gst_buffer_list_length (filesink->buffer_list);
 
     if (length > 0) {
-      GST_DEBUG_OBJECT (filesink, "Flushing out buffer of size %u",
-          filesink->current_buffer_size);
       flow_ret =
-          gst_file_sink_render_list_internal (filesink, filesink->buffer);
+          gst_file_sink_render_list_internal (filesink, filesink->buffer_list);
       /* Remove all buffers from the list but keep the list. This ensures that
        * we don't re-allocate the array storing the buffers all the time */
-      gst_buffer_list_remove (filesink->buffer, 0, length);
-      filesink->current_buffer_size = 0;
+      gst_buffer_list_remove (filesink->buffer_list, 0, length);
     }
   }
 
+  filesink->current_buffer_size = 0;
+
   return flow_ret;
 }
 
@@ -763,12 +833,42 @@ accumulate_size (GstBuffer ** buffer, guint idx, gpointer user_data)
 }
 
 static GstFlowReturn
+render_buffer (GstFileSink * filesink, GstBuffer * buffer)
+{
+  GstFlowReturn flow;
+  guint64 bytes_written = 0;
+  guint64 skip = 0;
+
+  for (;;) {
+    flow =
+        gst_writev_buffer (GST_OBJECT_CAST (filesink),
+        fileno (filesink->file), NULL, buffer, &bytes_written, skip,
+        filesink->max_transient_error_timeout, filesink->current_pos,
+        &filesink->flushing);
+
+    filesink->current_pos += bytes_written;
+    skip += bytes_written;
+
+    if (flow != GST_FLOW_FLUSHING)
+      break;
+
+    flow = gst_base_sink_wait_preroll (GST_BASE_SINK (filesink));
+
+    if (flow != GST_FLOW_OK)
+      break;
+  }
+
+  return flow;
+}
+
+static GstFlowReturn
 gst_file_sink_render_list (GstBaseSink * bsink, GstBufferList * buffer_list)
 {
   GstFlowReturn flow;
   GstFileSink *sink;
   guint i, num_buffers;
   gboolean sync_after = FALSE;
+  gint fsync_ret;
 
   sink = GST_FILE_SINK_CAST (bsink);
 
@@ -778,7 +878,7 @@ gst_file_sink_render_list (GstBaseSink * bsink, GstBufferList * buffer_list)
 
   gst_buffer_list_foreach (buffer_list, has_sync_after_buffer, &sync_after);
 
-  if (sync_after || !sink->buffer) {
+  if (sync_after || (!sink->buffer && !sink->buffer_list)) {
     flow = gst_file_sink_flush_buffer (sink);
     if (flow == GST_FLOW_OK)
       flow = gst_file_sink_render_list_internal (sink, buffer_list);
@@ -791,19 +891,51 @@ gst_file_sink_render_list (GstBaseSink * bsink, GstBufferList * buffer_list)
         G_GUINT64_FORMAT, size, num_buffers,
         sink->current_pos + sink->current_buffer_size);
 
-    for (i = 0; i < num_buffers; ++i)
-      gst_buffer_list_add (sink->buffer,
-          gst_buffer_ref (gst_buffer_list_get (buffer_list, i)));
-    sink->current_buffer_size += size;
-
-    if (sink->current_buffer_size > sink->buffer_size)
-      flow = gst_file_sink_flush_buffer (sink);
-    else
+    if (sink->buffer) {
       flow = GST_FLOW_OK;
+      for (i = 0; i < num_buffers && flow == GST_FLOW_OK; i++) {
+        GstBuffer *buffer = gst_buffer_list_get (buffer_list, i);
+        gsize buffer_size = gst_buffer_get_size (buffer);
+
+        if (sink->current_buffer_size + buffer_size >
+            sink->allocated_buffer_size) {
+          flow = gst_file_sink_flush_buffer (sink);
+          if (flow != GST_FLOW_OK)
+            return flow;
+        }
+
+        if (buffer_size > sink->allocated_buffer_size) {
+          GST_DEBUG_OBJECT (sink,
+              "writing buffer ( %" G_GSIZE_FORMAT
+              " bytes) at position %" G_GUINT64_FORMAT,
+              buffer_size, sink->current_pos);
+
+          flow = render_buffer (sink, buffer);
+        } else {
+          sink->current_buffer_size +=
+              gst_buffer_extract (buffer, 0,
+              sink->buffer + sink->current_buffer_size, buffer_size);
+          flow = GST_FLOW_OK;
+        }
+      }
+    } else {
+      for (i = 0; i < num_buffers; ++i)
+        gst_buffer_list_add (sink->buffer_list,
+            gst_buffer_ref (gst_buffer_list_get (buffer_list, i)));
+      sink->current_buffer_size += size;
+
+      if (sink->current_buffer_size > sink->buffer_size)
+        flow = gst_file_sink_flush_buffer (sink);
+      else
+        flow = GST_FLOW_OK;
+    }
   }
 
   if (flow == GST_FLOW_OK && sync_after) {
-    if (fsync (fileno (sink->file))) {
+    do {
+      fsync_ret = fsync (fileno (sink->file));
+    } while (fsync_ret < 0 && errno == EINTR);
+    if (fsync_ret) {
       GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
           (_("Error while writing to file \"%s\"."), sink->filename),
           ("%s", g_strerror (errno)));
@@ -827,6 +959,7 @@ gst_file_sink_render (GstBaseSink * sink, GstBuffer * buffer)
   GstFlowReturn flow;
   guint8 n_mem;
   gboolean sync_after;
+  gint fsync_ret;
 
   filesink = GST_FILE_SINK_CAST (sink);
 
@@ -834,31 +967,59 @@ gst_file_sink_render (GstBaseSink * sink, GstBuffer * buffer)
 
   n_mem = gst_buffer_n_memory (buffer);
 
-  if (n_mem > 0 && (sync_after || !filesink->buffer)) {
+  if (n_mem > 0 && (sync_after || (!filesink->buffer
+              && !filesink->buffer_list))) {
     flow = gst_file_sink_flush_buffer (filesink);
-    if (flow == GST_FLOW_OK)
-      flow =
-          gst_file_sink_render_buffers (filesink, &buffer, 1, &n_mem, n_mem,
-          gst_buffer_get_size (buffer));
+    if (flow == GST_FLOW_OK) {
+      flow = render_buffer (filesink, buffer);
+    }
   } else if (n_mem > 0) {
+    gsize size = gst_buffer_get_size (buffer);
+
     GST_DEBUG_OBJECT (filesink,
         "Queueing buffer of %" G_GSIZE_FORMAT " bytes at offset %"
-        G_GUINT64_FORMAT, gst_buffer_get_size (buffer),
+        G_GUINT64_FORMAT, size,
         filesink->current_pos + filesink->current_buffer_size);
 
-    filesink->current_buffer_size += gst_buffer_get_size (buffer);
-    gst_buffer_list_add (filesink->buffer, gst_buffer_ref (buffer));
+    if (filesink->buffer) {
+      if (filesink->current_buffer_size + size >
+          filesink->allocated_buffer_size) {
+        flow = gst_file_sink_flush_buffer (filesink);
+        if (flow != GST_FLOW_OK)
+          return flow;
+      }
 
-    if (filesink->current_buffer_size > filesink->buffer_size)
-      flow = gst_file_sink_flush_buffer (filesink);
-    else
-      flow = GST_FLOW_OK;
+      if (size > filesink->allocated_buffer_size) {
+        GST_DEBUG_OBJECT (sink,
+            "writing buffer ( %" G_GSIZE_FORMAT
+            " bytes) at position %" G_GUINT64_FORMAT,
+            size, filesink->current_pos);
+
+        flow = render_buffer (filesink, buffer);
+      } else {
+        filesink->current_buffer_size +=
+            gst_buffer_extract (buffer, 0,
+            filesink->buffer + filesink->current_buffer_size, size);
+        flow = GST_FLOW_OK;
+      }
+    } else {
+      filesink->current_buffer_size += gst_buffer_get_size (buffer);
+      gst_buffer_list_add (filesink->buffer_list, gst_buffer_ref (buffer));
+
+      if (filesink->current_buffer_size > filesink->buffer_size)
+        flow = gst_file_sink_flush_buffer (filesink);
+      else
+        flow = GST_FLOW_OK;
+    }
   } else {
     flow = GST_FLOW_OK;
   }
 
   if (flow == GST_FLOW_OK && sync_after) {
-    if (fsync (fileno (filesink->file))) {
+    do {
+      fsync_ret = fsync (fileno (filesink->file));
+    } while (fsync_ret < 0 && errno == EINTR);
+    if (fsync_ret) {
       GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
           (_("Error while writing to file \"%s\"."), filesink->filename),
           ("%s", g_strerror (errno)));
@@ -872,13 +1033,44 @@ gst_file_sink_render (GstBaseSink * sink, GstBuffer * buffer)
 static gboolean
 gst_file_sink_start (GstBaseSink * basesink)
 {
-  return gst_file_sink_open_file (GST_FILE_SINK (basesink));
+  GstFileSink *filesink;
+
+  filesink = GST_FILE_SINK_CAST (basesink);
+
+  g_atomic_int_set (&filesink->flushing, FALSE);
+  return gst_file_sink_open_file (filesink);
 }
 
 static gboolean
 gst_file_sink_stop (GstBaseSink * basesink)
 {
-  gst_file_sink_close_file (GST_FILE_SINK (basesink));
+  GstFileSink *filesink;
+
+  filesink = GST_FILE_SINK_CAST (basesink);
+
+  gst_file_sink_close_file (filesink);
+  return TRUE;
+}
+
+static gboolean
+gst_file_sink_unlock (GstBaseSink * basesink)
+{
+  GstFileSink *filesink;
+
+  filesink = GST_FILE_SINK_CAST (basesink);
+  g_atomic_int_set (&filesink->flushing, TRUE);
+
+  return TRUE;
+}
+
+static gboolean
+gst_file_sink_unlock_stop (GstBaseSink * basesink)
+{
+  GstFileSink *filesink;
+
+  filesink = GST_FILE_SINK_CAST (basesink);
+  g_atomic_int_set (&filesink->flushing, FALSE);
+
   return TRUE;
 }
 
index c41a9a2..bc479c5 100644 (file)
@@ -81,10 +81,21 @@ struct _GstFileSink {
   gint    buffer_mode;
   guint   buffer_size;
 
-  GstBufferList *buffer;
-  guint   current_buffer_size;
+  /* For default buffer mode */
+  GstBufferList *buffer_list;
+
+  /* For full buffer mode */
+  guint8 *buffer;
+  gsize   allocated_buffer_size;
+
+  /* For default/full buffer mode */
+  gsize current_buffer_size;
 
   gboolean append;
+  gboolean o_sync;
+  gint max_transient_error_timeout;
+
+  gboolean flushing;
 };
 
 struct _GstFileSinkClass {
index 76ab12c..62ffb20 100644 (file)
 #endif
 
 #include <gst/gst.h>
+#include <glib/gstdio.h>
 #include "gstfilesrc.h"
+#include "gstcoreelementselements.h"
 
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #ifdef G_OS_WIN32
+#include <windows.h>
 #include <io.h>                 /* lseek, open, close, read */
 /* On win32, stat* default to 32 bit; we need the 64-bit
  * variants, so explicitly define it that way. */
-#undef stat
-#define stat __stat64
-#undef fstat
-#define fstat _fstat64
 #undef lseek
 #define lseek _lseeki64
 #undef off_t
  * _stat*, since we're explicitly overriding that */
 #undef _INC_STAT_INL
 #endif
+
 #include <fcntl.h>
 
 #ifdef HAVE_UNISTD_H
 #  include <unistd.h>
 #endif
 
+#define struct_stat struct stat
+
 #ifdef __BIONIC__               /* Android */
 #if defined(__ANDROID_API__) && __ANDROID_API__ >= 21
 #undef fstat
 #define fstat fstat64
+#undef struct_stat
+#define struct_stat struct stat64
 #endif
 #endif
 
@@ -95,36 +99,6 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
 #define O_BINARY (0)
 #endif
 
-/* Copy of glib's g_open due to win32 libc/cross-DLL brokenness: we can't
- * use the 'file descriptor' opened in glib (and returned from this function)
- * in this library, as they may have unrelated C runtimes. */
-static int
-gst_open (const gchar * filename, int flags, int mode)
-{
-#ifdef G_OS_WIN32
-  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
-  int retval;
-  int save_errno;
-
-  if (wfilename == NULL) {
-    errno = EINVAL;
-    return -1;
-  }
-
-  retval = _wopen (wfilename, flags, mode);
-  save_errno = errno;
-
-  g_free (wfilename);
-
-  errno = save_errno;
-  return retval;
-#elif defined (__BIONIC__)
-  return open (filename, flags | O_LARGEFILE, mode);
-#else
-  return open (filename, flags, mode);
-#endif
-}
-
 GST_DEBUG_CATEGORY_STATIC (gst_file_src_debug);
 #define GST_CAT_DEFAULT gst_file_src_debug
 
@@ -166,6 +140,8 @@ static void gst_file_src_uri_handler_init (gpointer g_iface,
   GST_DEBUG_CATEGORY_INIT (gst_file_src_debug, "filesrc", 0, "filesrc element");
 #define gst_file_src_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstFileSrc, gst_file_src, GST_TYPE_BASE_SRC, _do_init);
+GST_ELEMENT_REGISTER_DEFINE (filesrc, "filesrc", GST_RANK_PRIMARY,
+    GST_TYPE_FILE_SRC);
 
 static void
 gst_file_src_class_init (GstFileSrcClass * klass)
@@ -430,7 +406,6 @@ gst_file_src_is_seekable (GstBaseSrc * basesrc)
 static gboolean
 gst_file_src_get_size (GstBaseSrc * basesrc, guint64 * size)
 {
-  struct stat stat_results;
   GstFileSrc *src;
 
   src = GST_FILE_SRC (basesrc);
@@ -440,11 +415,30 @@ gst_file_src_get_size (GstBaseSrc * basesrc, guint64 * size)
      * succeed, and wrongly say our length is zero. */
     return FALSE;
   }
+#ifdef G_OS_WIN32
+  {
+    HANDLE h = (HANDLE) _get_osfhandle (src->fd);
+    LARGE_INTEGER file_size;
+
+    if (h == INVALID_HANDLE_VALUE)
+      goto could_not_stat;
+
+    if (!GetFileSizeEx (h, &file_size)) {
+      goto could_not_stat;
+    }
+
+    *size = file_size.QuadPart;
+  }
+#else
+  {
+    struct_stat stat_results;
 
-  if (fstat (src->fd, &stat_results) < 0)
-    goto could_not_stat;
+    if (fstat (src->fd, &stat_results) < 0)
+      goto could_not_stat;
 
-  *size = stat_results.st_size;
+    *size = stat_results.st_size;
+  }
+#endif
 
   return TRUE;
 
@@ -460,7 +454,10 @@ static gboolean
 gst_file_src_start (GstBaseSrc * basesrc)
 {
   GstFileSrc *src = GST_FILE_SRC (basesrc);
-  struct stat stat_results;
+  int flags = O_RDONLY | O_BINARY;
+#if defined (__BIONIC__)
+  flags |= O_LARGEFILE;
+#endif
 
   if (src->filename == NULL || src->filename[0] == '\0')
     goto no_filename;
@@ -468,26 +465,50 @@ gst_file_src_start (GstBaseSrc * basesrc)
   GST_INFO_OBJECT (src, "opening file %s", src->filename);
 
   /* open the file */
-  src->fd = gst_open (src->filename, O_RDONLY | O_BINARY, 0);
+  src->fd = g_open (src->filename, flags, 0);
 
   if (src->fd < 0)
     goto open_failed;
 
-  /* check if it is a regular file, otherwise bail out */
-  if (fstat (src->fd, &stat_results) < 0)
-    goto no_stat;
+#ifdef G_OS_WIN32
+  {
+    HANDLE h = (HANDLE) _get_osfhandle (src->fd);
+    FILE_STANDARD_INFO file_info;
 
-  if (S_ISDIR (stat_results.st_mode))
-    goto was_directory;
+    if (h == INVALID_HANDLE_VALUE)
+      goto no_stat;
 
-  if (S_ISSOCK (stat_results.st_mode))
-    goto was_socket;
+    if (!GetFileInformationByHandleEx (h, FileStandardInfo, &file_info,
+            sizeof (FILE_STANDARD_INFO)))
+      goto no_stat;
 
-  src->read_position = 0;
+    if (file_info.Directory)
+      goto was_directory;
 
-  /* record if it's a regular (hence seekable and lengthable) file */
-  if (S_ISREG (stat_results.st_mode))
+    /* everything's a regular file on Windows */
     src->is_regular = TRUE;
+  }
+#else
+  {
+    struct_stat stat_results;
+
+    /* check if it is a regular file, otherwise bail out */
+    if (fstat (src->fd, &stat_results) < 0)
+      goto no_stat;
+
+    if (S_ISDIR (stat_results.st_mode))
+      goto was_directory;
+
+    if (S_ISSOCK (stat_results.st_mode))
+      goto was_socket;
+
+    /* record if it's a regular (hence seekable and lengthable) file */
+    if (S_ISREG (stat_results.st_mode))
+      src->is_regular = TRUE;
+  }
+#endif
+
+  src->read_position = 0;
 
   /* We need to check if the underlying file is seekable. */
   {
@@ -552,12 +573,14 @@ was_directory:
         (_("\"%s\" is a directory."), src->filename), (NULL));
     goto error_close;
   }
+#ifndef G_OS_WIN32
 was_socket:
   {
     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
         (_("File \"%s\" is a socket."), src->filename), (NULL));
     goto error_close;
   }
+#endif
 lseek_wonky:
   {
     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
@@ -578,7 +601,7 @@ gst_file_src_stop (GstBaseSrc * basesrc)
   GstFileSrc *src = GST_FILE_SRC (basesrc);
 
   /* close the file */
-  close (src->fd);
+  g_close (src->fd, NULL);
 
   /* zero out a lot of our state */
   src->fd = 0;
index af52f38..cdb22c9 100644 (file)
  *
  * Takes packets from various input sinks into one output source.
  *
- * funnel always outputs a single, open ended segment from
- * 0 with in %GST_FORMAT_TIME and outputs the buffers of the
- * different sinkpads with timestamps that are set to the
- * running time for that stream. funnel does not synchronize
- * the different input streams but simply forwards all buffers
- * immediately when they arrive.
- *
+ * #GstFunnel will forward sticky events from its first active sink pad
+ * and, if #GstFunnel:forward-sticky-events is set to true, it will
+ * forward sticky events each time a pad becomes active.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -42,6 +38,7 @@
 #endif
 
 #include "gstfunnel.h"
+#include "gstcoreelementselements.h"
 
 GST_DEBUG_CATEGORY_STATIC (gst_funnel_debug);
 #define GST_CAT_DEFAULT gst_funnel_debug
@@ -110,6 +107,7 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
   GST_DEBUG_CATEGORY_INIT (gst_funnel_debug, "funnel", 0, "funnel element");
 #define gst_funnel_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstFunnel, gst_funnel, GST_TYPE_ELEMENT, _do_init);
+GST_ELEMENT_REGISTER_DEFINE (funnel, "funnel", GST_RANK_NONE, GST_TYPE_FUNNEL);
 
 static GstStateChangeReturn gst_funnel_change_state (GstElement * element,
     GstStateChange transition);
index 8da7cf0..25bdae9 100644 (file)
@@ -38,6 +38,7 @@
 #include "gstelements_private.h"
 #include "../../gst/gst-i18n-lib.h"
 #include "gstidentity.h"
+#include "gstcoreelementselements.h"
 
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
@@ -95,7 +96,8 @@ enum
   PROP_CHECK_IMPERFECT_OFFSET,
   PROP_SIGNAL_HANDOFFS,
   PROP_DROP_ALLOCATION,
-  PROP_EOS_AFTER
+  PROP_EOS_AFTER,
+  PROP_STATS
 };
 
 
@@ -104,6 +106,8 @@ enum
 #define gst_identity_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstIdentity, gst_identity, GST_TYPE_BASE_TRANSFORM,
     _do_init);
+GST_ELEMENT_REGISTER_DEFINE (identity, "identity", GST_RANK_NONE,
+    GST_TYPE_IDENTITY);
 
 static void gst_identity_finalize (GObject * object);
 static void gst_identity_set_property (GObject * object, guint prop_id,
@@ -113,6 +117,8 @@ static void gst_identity_get_property (GObject * object, guint prop_id,
 
 static gboolean gst_identity_sink_event (GstBaseTransform * trans,
     GstEvent * event);
+static gboolean gst_identity_src_event (GstBaseTransform * trans,
+    GstEvent * event);
 static GstFlowReturn gst_identity_transform_ip (GstBaseTransform * trans,
     GstBuffer * buf);
 static gboolean gst_identity_start (GstBaseTransform * trans);
@@ -123,6 +129,7 @@ static gboolean gst_identity_accept_caps (GstBaseTransform * base,
     GstPadDirection direction, GstCaps * caps);
 static gboolean gst_identity_query (GstBaseTransform * base,
     GstPadDirection direction, GstQuery * query);
+static GstClock *gst_identity_provide_clock (GstElement * element);
 
 static guint gst_identity_signals[LAST_SIGNAL] = { 0 };
 
@@ -262,8 +269,37 @@ gst_identity_class_init (GstIdentityClass * klass)
   gst_identity_signals[SIGNAL_HANDOFF] =
       g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstIdentityClass, handoff), NULL, NULL,
-      g_cclosure_marshal_generic, G_TYPE_NONE, 1,
-      GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE);
+      NULL, G_TYPE_NONE, 1, GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+  /**
+   * GstIdentity:stats:
+
+   * Various statistics. This property returns a GstStructure
+   * with name application/x-identity-stats with the following fields:
+   *
+   * <itemizedlist>
+   * <listitem>
+   *   <para>
+   *   #guint64
+   *   <classname>&quot;num-buffers&quot;</classname>:
+   *   the number of buffers that passed through.
+   *   </para>
+   * </listitem>
+   * <listitem>
+   *   <para>
+   *   #guint64
+   *   <classname>&quot;num-bytes&quot;</classname>:
+   *   the number of bytes that passed through.
+   *   </para>
+   * </listitem>
+   * </itemizedlist>
+   *
+   * Since: 1.20
+   */
+  g_object_class_install_property (gobject_class, PROP_STATS,
+      g_param_spec_boxed ("stats", "Statistics",
+          "Statistics", GST_TYPE_STRUCTURE,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   gobject_class->finalize = gst_identity_finalize;
 
@@ -276,8 +312,11 @@ gst_identity_class_init (GstIdentityClass * klass)
 
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_identity_change_state);
+  gstelement_class->provide_clock =
+      GST_DEBUG_FUNCPTR (gst_identity_provide_clock);
 
   gstbasetrans_class->sink_event = GST_DEBUG_FUNCPTR (gst_identity_sink_event);
+  gstbasetrans_class->src_event = GST_DEBUG_FUNCPTR (gst_identity_src_event);
   gstbasetrans_class->transform_ip =
       GST_DEBUG_FUNCPTR (gst_identity_transform_ip);
   gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_identity_start);
@@ -310,6 +349,8 @@ gst_identity_init (GstIdentity * identity)
   identity->eos_after_counter = DEFAULT_EOS_AFTER;
 
   gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM_CAST (identity), TRUE);
+
+  GST_OBJECT_FLAG_SET (identity, GST_ELEMENT_FLAG_REQUIRE_CLOCK);
 }
 
 static void
@@ -334,7 +375,7 @@ gst_identity_do_sync (GstIdentity * identity, GstClockTime running_time)
       return GST_FLOW_FLUSHING;
     }
 
-    while (identity->blocked)
+    while (identity->blocked && !identity->flushing)
       g_cond_wait (&identity->blocked_cond, GST_OBJECT_GET_LOCK (identity));
 
     if (identity->flushing) {
@@ -421,7 +462,14 @@ gst_identity_sink_event (GstBaseTransform * trans, GstEvent * event)
 
       /* This is the first segment, send out a (0, -1) segment */
       gst_segment_init (&segment, segment.format);
+      if (identity->seek_segment.format != GST_FORMAT_UNDEFINED) {
+        segment.time = identity->seek_segment.time;
+        segment.base = identity->seek_segment.base;
+        gst_segment_init (&identity->seek_segment, GST_FORMAT_UNDEFINED);
+      }
+
       news = gst_event_new_segment (&segment);
+      GST_EVENT_SEQNUM (news) = GST_EVENT_SEQNUM (event);
 
       gst_pad_event_default (trans->sinkpad, GST_OBJECT_CAST (trans), news);
     } else {
@@ -460,27 +508,73 @@ gst_identity_sink_event (GstBaseTransform * trans, GstEvent * event)
     /* eat up segments */
     gst_event_unref (event);
     ret = TRUE;
-  } else {
-    if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START) {
+    goto done;
+  }
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_FLUSH_START:
       GST_OBJECT_LOCK (identity);
       identity->flushing = TRUE;
+      g_cond_signal (&identity->blocked_cond);
       if (identity->clock_id) {
         GST_DEBUG_OBJECT (identity, "unlock clock wait");
         gst_clock_id_unschedule (identity->clock_id);
       }
       GST_OBJECT_UNLOCK (identity);
-    } else if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
+      break;
+    case GST_EVENT_FLUSH_STOP:
       GST_OBJECT_LOCK (identity);
       identity->flushing = FALSE;
+      trans->have_segment = FALSE;
       GST_OBJECT_UNLOCK (identity);
-    }
-
-    ret = GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event);
+      break;
+    default:
+      break;
   }
 
+  ret = GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event);
+
+done:
   return ret;
 }
 
+static gboolean
+gst_identity_src_event (GstBaseTransform * trans, GstEvent * event)
+{
+  GstIdentity *identity = GST_IDENTITY (trans);
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_SEEK:
+    {
+      gdouble rate;
+      GstFormat fmt;
+      GstSeekFlags flags;
+      GstSeekType start_type, stop_type;
+      gint64 start, stop;
+      gst_event_parse_seek (event, &rate, &fmt, &flags, &start_type,
+          &start, &stop_type, &stop);
+
+      GST_OBJECT_LOCK (identity);
+      gst_segment_init (&identity->seek_segment, fmt);
+      if (!gst_segment_do_seek (&identity->seek_segment, rate, fmt,
+              flags, start_type, start, stop_type, stop, NULL)) {
+        GST_WARNING_OBJECT (identity, "Could not run seek %" GST_PTR_FORMAT,
+            event);
+        GST_OBJECT_UNLOCK (identity);
+
+        return FALSE;
+      }
+      GST_OBJECT_UNLOCK (identity);
+
+      break;
+    }
+    default:
+      break;
+  }
+
+  return GST_BASE_TRANSFORM_CLASS (parent_class)->src_event (trans, event);
+}
+
 static void
 gst_identity_check_imperfect_timestamp (GstIdentity * identity, GstBuffer * buf)
 {
@@ -612,6 +706,8 @@ gst_identity_update_last_message_for_buffer (GstIdentity * identity,
       GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf),
       GST_BUFFER_FLAGS (buf), flag_str, meta_str ? meta_str : "none", buf);
   g_free (flag_str);
+  g_free (meta_str);
+  GST_TRACE_OBJECT (identity, "%s", identity->last_message);
 
   GST_OBJECT_UNLOCK (identity);
 
@@ -686,10 +782,21 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
     g_signal_emit (identity, gst_identity_signals[SIGNAL_HANDOFF], 0, buf);
 
   if (trans->segment.format == GST_FORMAT_TIME) {
-    rundts = gst_segment_to_running_time (&trans->segment,
-        GST_FORMAT_TIME, GST_BUFFER_DTS (buf));
-    runpts = gst_segment_to_running_time (&trans->segment,
-        GST_FORMAT_TIME, GST_BUFFER_PTS (buf));
+    if (trans->segment.rate > 0) {
+      runpts = gst_segment_to_running_time (&trans->segment,
+          GST_FORMAT_TIME, GST_BUFFER_PTS (buf));
+      rundts = gst_segment_to_running_time (&trans->segment,
+          GST_FORMAT_TIME, GST_BUFFER_DTS (buf));
+    } else {
+      runpts = gst_segment_to_running_time (&trans->segment,
+          GST_FORMAT_TIME, GST_CLOCK_TIME_IS_VALID (buf->duration)
+          && GST_CLOCK_TIME_IS_VALID (buf->pts) ? buf->pts +
+          buf->duration : buf->pts);
+      rundts = gst_segment_to_running_time (&trans->segment,
+          GST_FORMAT_TIME, GST_CLOCK_TIME_IS_VALID (buf->duration)
+          && GST_CLOCK_TIME_IS_VALID (buf->dts) ? buf->dts +
+          buf->duration : buf->dts);
+    }
   }
 
   if (GST_CLOCK_TIME_IS_VALID (rundts))
@@ -713,6 +820,11 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
     GST_BUFFER_OFFSET_END (buf) = GST_CLOCK_TIME_NONE;
   }
 
+  GST_OBJECT_LOCK (trans);
+  identity->num_bytes += gst_buffer_get_size (buf);
+  identity->num_buffers++;
+  GST_OBJECT_UNLOCK (trans);
+
   return ret;
 
   /* ERRORS */
@@ -751,6 +863,8 @@ gst_identity_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
   GstIdentity *identity;
+  GstMessage *clock_message = NULL;
+  gboolean sync;
 
   identity = GST_IDENTITY (object);
 
@@ -780,7 +894,25 @@ gst_identity_set_property (GObject * object, guint prop_id,
       identity->datarate = g_value_get_int (value);
       break;
     case PROP_SYNC:
-      identity->sync = g_value_get_boolean (value);
+      sync = g_value_get_boolean (value);
+      GST_OBJECT_LOCK (identity);
+      if (sync != identity->sync) {
+        identity->sync = sync;
+        if (sync) {
+          GST_OBJECT_FLAG_SET (identity, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
+          clock_message =
+              gst_message_new_clock_provide (GST_OBJECT_CAST (identity),
+              gst_system_clock_obtain (), TRUE);
+        } else {
+          GST_OBJECT_FLAG_UNSET (identity, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
+          clock_message =
+              gst_message_new_clock_lost (GST_OBJECT_CAST (identity),
+              gst_system_clock_obtain ());
+        }
+      }
+      GST_OBJECT_UNLOCK (identity);
+      if (clock_message)
+        gst_element_post_message (GST_ELEMENT_CAST (identity), clock_message);
       break;
     case PROP_TS_OFFSET:
       identity->ts_offset = g_value_get_int64 (value);
@@ -810,6 +942,20 @@ gst_identity_set_property (GObject * object, guint prop_id,
     gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (identity), TRUE);
 }
 
+static GstStructure *
+gst_identity_create_stats (GstIdentity * identity)
+{
+  GstStructure *s;
+
+  GST_OBJECT_LOCK (identity);
+  s = gst_structure_new ("application/x-identity-stats",
+      "num-bytes", G_TYPE_UINT64, identity->num_bytes,
+      "num-buffers", G_TYPE_UINT64, identity->num_buffers, NULL);
+  GST_OBJECT_UNLOCK (identity);
+
+  return s;
+}
+
 static void
 gst_identity_get_property (GObject * object, guint prop_id, GValue * value,
     GParamSpec * pspec)
@@ -869,6 +1015,9 @@ gst_identity_get_property (GObject * object, guint prop_id, GValue * value,
     case PROP_EOS_AFTER:
       g_value_set_int (value, identity->eos_after);
       break;
+    case PROP_STATS:
+      g_value_take_boxed (value, gst_identity_create_stats (identity));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1007,11 +1156,13 @@ gst_identity_change_state (GstElement * element, GstStateChange transition)
       GST_OBJECT_UNLOCK (identity);
       if (identity->sync)
         no_preroll = TRUE;
+      identity->num_bytes = 0;
+      identity->num_buffers = 0;
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
       GST_OBJECT_LOCK (identity);
       identity->blocked = FALSE;
-      g_cond_broadcast (&identity->blocked_cond);
+      g_cond_signal (&identity->blocked_cond);
       GST_OBJECT_UNLOCK (identity);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
@@ -1022,7 +1173,7 @@ gst_identity_change_state (GstElement * element, GstStateChange transition)
         gst_clock_id_unschedule (identity->clock_id);
       }
       identity->blocked = FALSE;
-      g_cond_broadcast (&identity->blocked_cond);
+      g_cond_signal (&identity->blocked_cond);
       GST_OBJECT_UNLOCK (identity);
       break;
     default:
@@ -1053,3 +1204,15 @@ gst_identity_change_state (GstElement * element, GstStateChange transition)
 
   return ret;
 }
+
+/* FIXME: GStreamer 2.0 */
+static GstClock *
+gst_identity_provide_clock (GstElement * element)
+{
+  GstIdentity *identity = GST_IDENTITY (element);
+
+  if (!identity->sync)
+    return NULL;
+
+  return gst_system_clock_obtain ();
+}
index 19bf29f..20b4727 100644 (file)
@@ -67,6 +67,7 @@ struct _GstIdentity {
   gboolean      check_imperfect_timestamp;
   gboolean      check_imperfect_offset;
   gboolean      single_segment;
+  GstSegment seek_segment;
   GstBufferFlags drop_buffer_flags;
   GstClockTime   prev_timestamp;
   GstClockTime   prev_duration;
@@ -82,6 +83,8 @@ struct _GstIdentity {
   gboolean       drop_allocation;
   gint           eos_after;
   gint           eos_after_counter;
+  guint64        num_bytes;
+  guint64        num_buffers;
 };
 
 struct _GstIdentityClass {
index 838e9b0..e9e1541 100644 (file)
@@ -48,6 +48,7 @@
 #include <string.h>
 
 #include "gstinputselector.h"
+#include "gstcoreelementselements.h"
 
 #define DEBUG_CACHED_BUFFERS 0
 
@@ -917,7 +918,6 @@ gst_input_selector_cleanup_old_cached_buffers (GstInputSelector * sel,
   GST_DEBUG_OBJECT (sel, "Cleaning up old cached buffers");
   for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = g_list_next (walk)) {
     GstSelectorPad *selpad;
-    GstSegment *seg;
     GstSelectorPadCachedBuffer *cached_buffer;
     GSList *maybe_remove;
     guint queue_position;
@@ -926,13 +926,12 @@ gst_input_selector_cleanup_old_cached_buffers (GstInputSelector * sel,
     if (!selpad->cached_buffers)
       continue;
 
-    seg = &selpad->segment;
-
     maybe_remove = NULL;
     queue_position = 0;
     while ((cached_buffer = g_queue_peek_nth (selpad->cached_buffers,
                 queue_position))) {
       GstBuffer *buffer = cached_buffer->buffer;
+      GstSegment *seg = &cached_buffer->segment;
       GstClockTime running_time;
       GSList *l;
 
@@ -1217,6 +1216,8 @@ static gboolean gst_input_selector_query (GstPad * pad, GstObject * parent,
 #define gst_input_selector_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstInputSelector, gst_input_selector, GST_TYPE_ELEMENT,
     _do_init);
+GST_ELEMENT_REGISTER_DEFINE (input_selector, "input-selector", GST_RANK_NONE,
+    GST_TYPE_INPUT_SELECTOR);
 
 static void
 gst_input_selector_class_init (GstInputSelectorClass * klass)
@@ -1308,6 +1309,9 @@ gst_input_selector_class_init (GstInputSelectorClass * klass)
   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;
+
+  gst_type_mark_as_plugin_api (GST_TYPE_SELECTOR_PAD, 0);
+  gst_type_mark_as_plugin_api (GST_TYPE_INPUT_SELECTOR_SYNC_MODE, 0);
 }
 
 static void
@@ -1431,6 +1435,7 @@ gst_input_selector_set_property (GObject * object, guint prop_id,
 
       GST_INPUT_SELECTOR_LOCK (sel);
 
+      sel->active_sinkpad_from_user = ! !pad;
 #if DEBUG_CACHED_BUFFERS
       gst_input_selector_debug_cached_buffers (sel);
 #endif
@@ -1546,6 +1551,19 @@ gst_input_selector_event (GstPad * pad, GstObject * parent, GstEvent * event)
   /* Send upstream events to all sinkpads */
   iter = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (sel));
 
+  GST_INPUT_SELECTOR_LOCK (sel);
+  if (sel->active_sinkpad) {
+    eventpad = gst_object_ref (sel->active_sinkpad);
+    GST_INPUT_SELECTOR_UNLOCK (sel);
+
+    gst_event_ref (event);
+    result |= gst_pad_push_event (eventpad, event);
+    pushed_pads = g_list_append (pushed_pads, eventpad);
+    gst_object_unref (eventpad);
+  } else {
+    GST_INPUT_SELECTOR_UNLOCK (sel);
+  }
+
   /* This is now essentially a copy of gst_pad_event_default_dispatch
    * with a different iterator */
   while (!done) {
@@ -1561,6 +1579,7 @@ gst_input_selector_event (GstPad * pad, GstObject * parent, GstEvent * event)
 
         gst_event_ref (event);
         result |= gst_pad_push_event (eventpad, event);
+        pushed_pads = g_list_append (pushed_pads, eventpad);
 
         g_value_reset (&item);
         break;
@@ -1798,8 +1817,8 @@ gst_input_selector_request_new_pad (GstElement * element,
   GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_CAPS);
   GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_ALLOCATION);
   gst_pad_set_active (sinkpad, TRUE);
-  gst_element_add_pad (GST_ELEMENT (sel), sinkpad);
   GST_INPUT_SELECTOR_UNLOCK (sel);
+  gst_element_add_pad (GST_ELEMENT (sel), sinkpad);
 
   return sinkpad;
 }
@@ -1807,9 +1826,11 @@ gst_input_selector_request_new_pad (GstElement * element,
 static void
 gst_input_selector_release_pad (GstElement * element, GstPad * pad)
 {
+  GstSelectorPad *selpad;
   GstInputSelector *sel;
 
   sel = GST_INPUT_SELECTOR (element);
+  selpad = GST_SELECTOR_PAD (pad);
   GST_LOG_OBJECT (sel, "Releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad));
 
   GST_INPUT_SELECTOR_LOCK (sel);
@@ -1818,7 +1839,15 @@ gst_input_selector_release_pad (GstElement * element, GstPad * pad)
     GST_DEBUG_OBJECT (sel, "Deactivating pad %s:%s", GST_DEBUG_PAD_NAME (pad));
     gst_object_unref (sel->active_sinkpad);
     sel->active_sinkpad = NULL;
+    sel->active_sinkpad_from_user = FALSE;
   }
+
+  /* wake up the pad if it's currently waiting for EOS or a running time to be
+   * reached. Otherwise we'll deadlock on the streaming thread further below
+   * when deactivating the pad. */
+  selpad->flushing = TRUE;
+  GST_INPUT_SELECTOR_BROADCAST (sel);
+
   sel->n_pads--;
   GST_INPUT_SELECTOR_UNLOCK (sel);
 
@@ -1833,7 +1862,7 @@ gst_input_selector_reset (GstInputSelector * sel)
 
   GST_INPUT_SELECTOR_LOCK (sel);
   /* clear active pad */
-  if (sel->active_sinkpad) {
+  if (sel->active_sinkpad && !sel->active_sinkpad_from_user) {
     gst_object_unref (sel->active_sinkpad);
     sel->active_sinkpad = NULL;
   }
index 3dff175..9d2eb6a 100644 (file)
@@ -65,7 +65,8 @@ struct _GstInputSelector {
 
   GstPad *srcpad;
 
-  GstPad *active_sinkpad;
+  gboolean active_sinkpad_from_user;
+  GstPad* active_sinkpad;
   guint n_pads;           /* number of pads */
   guint padcount;         /* sequence number for pads */
   gboolean sync_streams;
index 2b01a33..f40200b 100644 (file)
 #endif
 
 #include <gst/gst.h>
+#include <gst/glib-compat-private.h>
 #include <stdio.h>
+
 #include "gstmultiqueue.h"
-#include <gst/glib-compat-private.h>
+#include "gstcoreelementselements.h"
 
-/**
- * GstSingleQueue:
+/* GstSingleQueue:
  * @sinkpad: associated sink #GstPad
  * @srcpad: associated source #GstPad
  *
@@ -111,16 +112,17 @@ typedef struct _GstSingleQueue GstSingleQueue;
 
 struct _GstSingleQueue
 {
+  gint refcount;
+
   /* unique identifier of the queue */
   guint id;
   /* group of streams to which this queue belongs to */
   guint groupid;
   GstClockTimeDiff group_high_time;
 
-  GstMultiQueue *mqueue;
-
-  GstPad *sinkpad;
-  GstPad *srcpad;
+  GWeakRef mqueue;
+  GWeakRef sinkpad;
+  GWeakRef srcpad;
 
   /* flowreturn of previous srcpad push */
   GstFlowReturn srcresult;
@@ -173,7 +175,6 @@ struct _GstSingleQueue
   GstClockTime interleave;      /* Calculated interleve within the thread */
 };
 
-
 /* Extension of GstDataQueueItem structure for our usage */
 typedef struct _GstMultiQueueItem GstMultiQueueItem;
 
@@ -191,7 +192,8 @@ struct _GstMultiQueueItem
 };
 
 static GstSingleQueue *gst_single_queue_new (GstMultiQueue * mqueue, guint id);
-static void gst_single_queue_free (GstSingleQueue * squeue);
+static void gst_single_queue_unref (GstSingleQueue * squeue);
+static GstSingleQueue *gst_single_queue_ref (GstSingleQueue * squeue);
 
 static void wake_up_next_non_linked (GstMultiQueue * mq);
 static void compute_high_id (GstMultiQueue * mq);
@@ -280,6 +282,7 @@ enum
   PROP_USE_INTERLEAVE,
   PROP_UNLINKED_CACHE_TIME,
   PROP_MINIMUM_INTERLEAVE,
+  PROP_STATS,
   PROP_LAST
 };
 
@@ -317,6 +320,9 @@ enum
 {
   PROP_PAD_0,
   PROP_PAD_GROUP_ID,
+  PROP_CURRENT_LEVEL_BUFFERS,
+  PROP_CURRENT_LEVEL_BYTES,
+  PROP_CURRENT_LEVEL_TIME,
 };
 
 #define GST_TYPE_MULTIQUEUE_PAD            (gst_multiqueue_pad_get_type())
@@ -326,6 +332,22 @@ enum
 #define GST_IS_MULTIQUEUE_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_MULTIQUEUE_PAD))
 #define GST_MULTIQUEUE_PAD_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_MULTIQUEUE_PAD,GstMultiQueuePadClass))
 
+#define GST_MULTI_QUEUE_MUTEX_LOCK(q) G_STMT_START {                          \
+  g_mutex_lock (&q->qlock);                                              \
+} G_STMT_END
+
+#define GST_MULTI_QUEUE_MUTEX_UNLOCK(q) G_STMT_START {                        \
+  g_mutex_unlock (&q->qlock);                                            \
+} G_STMT_END
+
+#define SET_PERCENT(mq, perc) G_STMT_START {                             \
+  if (perc != mq->buffering_percent) {                                   \
+    mq->buffering_percent = perc;                                        \
+    mq->buffering_percent_changed = TRUE;                                \
+    GST_DEBUG_OBJECT (mq, "buffering %d percent", perc);                 \
+  }                                                                      \
+} G_STMT_END
+
 struct _GstMultiQueuePad
 {
   GstPad parent;
@@ -341,6 +363,110 @@ struct _GstMultiQueuePadClass
 GType gst_multiqueue_pad_get_type (void);
 
 G_DEFINE_TYPE (GstMultiQueuePad, gst_multiqueue_pad, GST_TYPE_PAD);
+
+static guint
+gst_multiqueue_pad_get_group_id (GstMultiQueuePad * pad)
+{
+  guint ret = 0;
+  GstMultiQueue *mq;
+
+  if (!pad->sq)
+    return 0;
+
+  mq = g_weak_ref_get (&pad->sq->mqueue);
+
+  if (mq) {
+    GST_OBJECT_LOCK (mq);
+  }
+
+  ret = pad->sq->groupid;
+
+  if (mq) {
+    GST_OBJECT_UNLOCK (mq);
+    gst_object_unref (mq);
+  }
+
+  return ret;
+}
+
+static guint
+gst_multiqueue_pad_get_current_level_buffers (GstMultiQueuePad * pad)
+{
+  GstSingleQueue *sq = pad->sq;
+  GstDataQueueSize level;
+  GstMultiQueue *mq;
+
+  if (!sq)
+    return 0;
+
+  mq = g_weak_ref_get (&pad->sq->mqueue);
+
+  if (mq) {
+    GST_MULTI_QUEUE_MUTEX_LOCK (mq);
+  }
+
+  gst_data_queue_get_level (sq->queue, &level);
+
+  if (mq) {
+    GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
+    gst_object_unref (mq);
+  }
+
+  return level.visible;
+}
+
+static guint
+gst_multiqueue_pad_get_current_level_bytes (GstMultiQueuePad * pad)
+{
+  GstSingleQueue *sq = pad->sq;
+  GstDataQueueSize level;
+  GstMultiQueue *mq;
+
+  if (!sq)
+    return 0;
+
+  mq = g_weak_ref_get (&pad->sq->mqueue);
+
+  if (mq) {
+    GST_MULTI_QUEUE_MUTEX_LOCK (mq);
+  }
+
+  gst_data_queue_get_level (sq->queue, &level);
+
+  if (mq) {
+    GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
+    gst_object_unref (mq);
+  }
+
+  return level.bytes;
+}
+
+static guint64
+gst_multiqueue_pad_get_current_level_time (GstMultiQueuePad * pad)
+{
+  GstSingleQueue *sq = pad->sq;
+  GstMultiQueue *mq;
+  guint64 ret;
+
+  if (!sq)
+    return 0;
+
+  mq = g_weak_ref_get (&pad->sq->mqueue);
+
+  if (mq) {
+    GST_MULTI_QUEUE_MUTEX_LOCK (mq);
+  }
+
+  ret = sq->cur_time;
+
+  if (mq) {
+    GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
+    gst_object_unref (mq);
+  }
+
+  return ret;
+}
+
 static void
 gst_multiqueue_pad_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec)
@@ -349,9 +475,23 @@ gst_multiqueue_pad_get_property (GObject * object, guint prop_id,
 
   switch (prop_id) {
     case PROP_PAD_GROUP_ID:
-      if (pad->sq)
-        g_value_set_uint (value, pad->sq->groupid);
+      g_value_set_uint (value, gst_multiqueue_pad_get_group_id (pad));
+      break;
+    case PROP_CURRENT_LEVEL_BUFFERS:{
+      g_value_set_uint (value,
+          gst_multiqueue_pad_get_current_level_buffers (pad));
+      break;
+    }
+    case PROP_CURRENT_LEVEL_BYTES:{
+      g_value_set_uint (value,
+          gst_multiqueue_pad_get_current_level_bytes (pad));
+      break;
+    }
+    case PROP_CURRENT_LEVEL_TIME:{
+      g_value_set_uint64 (value,
+          gst_multiqueue_pad_get_current_level_time (pad));
       break;
+    }
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -366,10 +506,19 @@ gst_multiqueue_pad_set_property (GObject * object, guint prop_id,
 
   switch (prop_id) {
     case PROP_PAD_GROUP_ID:
-      GST_OBJECT_LOCK (pad);
-      if (pad->sq)
+      if (pad->sq) {
+        GstMultiQueue *mqueue = g_weak_ref_get (&pad->sq->mqueue);
+
+        if (mqueue)
+          GST_OBJECT_LOCK (mqueue);
+
         pad->sq->groupid = g_value_get_uint (value);
-      GST_OBJECT_UNLOCK (pad);
+
+        if (mqueue) {
+          GST_OBJECT_UNLOCK (mqueue);
+          gst_object_unref (mqueue);
+        }
+      }
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -378,12 +527,24 @@ gst_multiqueue_pad_set_property (GObject * object, guint prop_id,
 }
 
 static void
+gst_multiqueue_pad_finalize (GObject * object)
+{
+  GstMultiQueuePad *pad = GST_MULTIQUEUE_PAD (object);
+
+  if (pad->sq)
+    gst_single_queue_unref (pad->sq);
+
+  G_OBJECT_CLASS (gst_multiqueue_pad_parent_class)->finalize (object);
+}
+
+static void
 gst_multiqueue_pad_class_init (GstMultiQueuePadClass * klass)
 {
   GObjectClass *gobject_class = (GObjectClass *) klass;
 
   gobject_class->set_property = gst_multiqueue_pad_set_property;
   gobject_class->get_property = gst_multiqueue_pad_get_property;
+  gobject_class->finalize = gst_multiqueue_pad_finalize;
 
   /**
    * GstMultiQueuePad:group-id:
@@ -396,6 +557,42 @@ gst_multiqueue_pad_class_init (GstMultiQueuePadClass * klass)
       g_param_spec_uint ("group-id", "Group ID",
           "Group to which this pad belongs", 0, G_MAXUINT32,
           DEFAULT_PAD_GROUP_ID, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstMultiQueuePad:current-level-buffers:
+   *
+   * The corresponding queue's current level of buffers.
+   *
+   * Since: 1.18
+   */
+  g_object_class_install_property (gobject_class, PROP_CURRENT_LEVEL_BUFFERS,
+      g_param_spec_uint ("current-level-buffers", "Current level buffers",
+          "Current level buffers", 0, G_MAXUINT32,
+          0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstMultiQueuePad:current-level-bytes:
+   *
+   * The corresponding queue's current level of bytes.
+   *
+   * Since: 1.18
+   */
+  g_object_class_install_property (gobject_class, PROP_CURRENT_LEVEL_BYTES,
+      g_param_spec_uint ("current-level-bytes", "Current level bytes",
+          "Current level bytes", 0, G_MAXUINT32,
+          0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstMultiQueuePad:current-level-time:
+   *
+   * The corresponding queue's current level of time.
+   *
+   * Since: 1.18
+   */
+  g_object_class_install_property (gobject_class, PROP_CURRENT_LEVEL_TIME,
+      g_param_spec_uint64 ("current-level-time", "Current level time",
+          "Current level time", 0, G_MAXUINT64,
+          0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -405,22 +602,6 @@ gst_multiqueue_pad_init (GstMultiQueuePad * pad)
 }
 
 
-#define GST_MULTI_QUEUE_MUTEX_LOCK(q) G_STMT_START {                          \
-  g_mutex_lock (&q->qlock);                                              \
-} G_STMT_END
-
-#define GST_MULTI_QUEUE_MUTEX_UNLOCK(q) G_STMT_START {                        \
-  g_mutex_unlock (&q->qlock);                                            \
-} G_STMT_END
-
-#define SET_PERCENT(mq, perc) G_STMT_START {                             \
-  if (perc != mq->buffering_percent) {                                   \
-    mq->buffering_percent = perc;                                        \
-    mq->buffering_percent_changed = TRUE;                                \
-    GST_DEBUG_OBJECT (mq, "buffering %d percent", perc);                 \
-  }                                                                      \
-} G_STMT_END
-
 /* Convenience function */
 static inline GstClockTimeDiff
 my_segment_to_running_time (GstSegment * segment, GstClockTime val)
@@ -457,6 +638,8 @@ static void gst_multi_queue_loop (GstPad * pad);
 #define gst_multi_queue_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstMultiQueue, gst_multi_queue, GST_TYPE_ELEMENT,
     _do_init);
+GST_ELEMENT_REGISTER_DEFINE (multiqueue, "multiqueue", GST_RANK_NONE,
+    GST_TYPE_MULTI_QUEUE);
 
 static guint gst_multi_queue_signals[LAST_SIGNAL] = { 0 };
 
@@ -483,7 +666,7 @@ gst_multi_queue_class_init (GstMultiQueueClass * klass)
   gst_multi_queue_signals[SIGNAL_UNDERRUN] =
       g_signal_new ("underrun", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
       G_STRUCT_OFFSET (GstMultiQueueClass, underrun), NULL, NULL,
-      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+      NULL, G_TYPE_NONE, 0);
 
   /**
    * GstMultiQueue::overrun:
@@ -499,7 +682,7 @@ gst_multi_queue_class_init (GstMultiQueueClass * klass)
   gst_multi_queue_signals[SIGNAL_OVERRUN] =
       g_signal_new ("overrun", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
       G_STRUCT_OFFSET (GstMultiQueueClass, overrun), NULL, NULL,
-      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+      NULL, G_TYPE_NONE, 0);
 
   /* PROPERTIES */
 
@@ -554,7 +737,8 @@ gst_multi_queue_class_init (GstMultiQueueClass * klass)
    */
   g_object_class_install_property (gobject_class, PROP_USE_BUFFERING,
       g_param_spec_boolean ("use-buffering", "Use buffering",
-          "Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds",
+          "Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds "
+          "(0% = low-watermark, 100% = high-watermark)",
           DEFAULT_USE_BUFFERING, G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
           G_PARAM_STATIC_STRINGS));
   /**
@@ -638,6 +822,25 @@ gst_multi_queue_class_init (GstMultiQueueClass * klass)
           G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
           G_PARAM_STATIC_STRINGS));
 
+  /**
+   * GstMultiQueue:stats:
+   *
+   * Various #GstMultiQueue statistics. This property returns a #GstStructure
+   * with name "application/x-gst-multi-queue-stats" with the following fields:
+   *
+   * - "queues" GST_TYPE_ARRAY    Contains one GstStructure named "queue_%d"
+   *   (where \%d is the queue's ID) per internal queue:
+   *   - "buffers" G_TYPE_UINT    The queue's current level of buffers
+   *   - "bytes" G_TYPE_UINT    The queue's current level of bytes
+   *   - "time" G_TYPE_UINT64    The queue's current level of time
+   *
+   * Since: 1.18
+   */
+  g_object_class_install_property (gobject_class, PROP_STATS,
+      g_param_spec_boxed ("stats", "Stats",
+          "Multiqueue Statistics",
+          GST_TYPE_STRUCTURE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
   gobject_class->finalize = gst_multi_queue_finalize;
 
   gst_element_class_set_static_metadata (gstelement_class,
@@ -645,7 +848,8 @@ gst_multi_queue_class_init (GstMultiQueueClass * klass)
       "Generic", "Multiple data queue", "Edward Hervey <edward@fluendo.com>");
   gst_element_class_add_static_pad_template_with_gtype (gstelement_class,
       &sinktemplate, GST_TYPE_MULTIQUEUE_PAD);
-  gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
+  gst_element_class_add_static_pad_template_with_gtype (gstelement_class,
+      &srctemplate, GST_TYPE_MULTIQUEUE_PAD);
 
   gstelement_class->request_new_pad =
       GST_DEBUG_FUNCPTR (gst_multi_queue_request_new_pad);
@@ -653,6 +857,8 @@ gst_multi_queue_class_init (GstMultiQueueClass * klass)
       GST_DEBUG_FUNCPTR (gst_multi_queue_release_pad);
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_multi_queue_change_state);
+
+  gst_type_mark_as_plugin_api (GST_TYPE_MULTIQUEUE_PAD, 0);
 }
 
 static void
@@ -691,8 +897,7 @@ gst_multi_queue_finalize (GObject * object)
 {
   GstMultiQueue *mqueue = GST_MULTI_QUEUE (object);
 
-  g_list_foreach (mqueue->queues, (GFunc) gst_single_queue_free, NULL);
-  g_list_free (mqueue->queues);
+  g_list_free_full (mqueue->queues, (GDestroyNotify) gst_single_queue_unref);
   mqueue->queues = NULL;
   mqueue->queues_cookie++;
 
@@ -858,6 +1063,44 @@ get_current_size_bytes (GstMultiQueue * mq)
 }
 #endif
 
+/* Called with mutex held */
+static GstStructure *
+gst_multi_queue_get_stats (GstMultiQueue * mq)
+{
+  GstStructure *ret =
+      gst_structure_new_empty ("application/x-gst-multi-queue-stats");
+  GList *tmp;
+  GstSingleQueue *sq;
+
+  if (mq->queues != NULL) {
+    GValue queues = G_VALUE_INIT;
+    GValue v = G_VALUE_INIT;
+
+    g_value_init (&queues, GST_TYPE_ARRAY);
+
+    for (tmp = mq->queues; tmp; tmp = g_list_next (tmp)) {
+      GstDataQueueSize level;
+      GstStructure *s;
+      gchar *id;
+      g_value_init (&v, GST_TYPE_STRUCTURE);
+
+      sq = (GstSingleQueue *) tmp->data;
+      gst_data_queue_get_level (sq->queue, &level);
+      id = g_strdup_printf ("queue_%d", sq->id);
+      s = gst_structure_new (id,
+          "buffers", G_TYPE_UINT, level.visible,
+          "bytes", G_TYPE_UINT, level.bytes,
+          "time", G_TYPE_UINT64, sq->cur_time, NULL);
+      g_value_take_boxed (&v, s);
+      gst_value_array_append_and_take_value (&queues, &v);
+      g_free (id);
+    }
+    gst_structure_take_value (ret, "queues", &queues);
+  }
+
+  return ret;
+}
+
 static void
 gst_multi_queue_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec)
@@ -919,6 +1162,9 @@ gst_multi_queue_get_property (GObject * object, guint prop_id,
     case PROP_MINIMUM_INTERLEAVE:
       g_value_set_uint64 (value, mq->min_interleave_time);
       break;
+    case PROP_STATS:
+      g_value_take_boxed (value, gst_multi_queue_get_stats (mq));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -931,22 +1177,31 @@ static GstIterator *
 gst_multi_queue_iterate_internal_links (GstPad * pad, GstObject * parent)
 {
   GstIterator *it = NULL;
-  GstPad *opad;
+  GstPad *opad, *sinkpad, *srcpad;
   GstSingleQueue *squeue;
   GstMultiQueue *mq = GST_MULTI_QUEUE (parent);
   GValue val = { 0, };
 
   GST_MULTI_QUEUE_MUTEX_LOCK (mq);
-  squeue = gst_pad_get_element_private (pad);
+  squeue = GST_MULTIQUEUE_PAD (pad)->sq;
   if (!squeue)
     goto out;
 
-  if (squeue->sinkpad == pad)
-    opad = gst_object_ref (squeue->srcpad);
-  else if (squeue->srcpad == pad)
-    opad = gst_object_ref (squeue->sinkpad);
-  else
+  srcpad = g_weak_ref_get (&squeue->srcpad);
+  sinkpad = g_weak_ref_get (&squeue->sinkpad);
+  if (sinkpad == pad && srcpad) {
+    opad = srcpad;
+    gst_clear_object (&sinkpad);
+
+  } else if (srcpad == pad && sinkpad) {
+    opad = sinkpad;
+    gst_clear_object (&srcpad);
+
+  } else {
+    gst_clear_object (&srcpad);
+    gst_clear_object (&sinkpad);
     goto out;
+  }
 
   g_value_init (&val, GST_TYPE_PAD);
   g_value_set_object (&val, opad);
@@ -983,7 +1238,10 @@ gst_multi_queue_request_new_pad (GstElement * element, GstPadTemplate * temp,
   /* Create a new single queue, add the sink and source pad and return the sink pad */
   squeue = gst_single_queue_new (mqueue, temp_id);
 
-  new_pad = squeue ? squeue->sinkpad : NULL;
+  new_pad = squeue ? g_weak_ref_get (&squeue->sinkpad) : NULL;
+  /* request pad assumes the element is owning the ref of the pad it returns */
+  if (new_pad)
+    gst_object_unref (new_pad);
 
   GST_DEBUG_OBJECT (mqueue, "Returning pad %" GST_PTR_FORMAT, new_pad);
 
@@ -993,6 +1251,7 @@ gst_multi_queue_request_new_pad (GstElement * element, GstPadTemplate * temp,
 static void
 gst_multi_queue_release_pad (GstElement * element, GstPad * pad)
 {
+  GstPad *sinkpad = NULL, *srcpad = NULL;
   GstMultiQueue *mqueue = GST_MULTI_QUEUE (element);
   GstSingleQueue *sq = NULL;
   GList *tmp;
@@ -1003,12 +1262,19 @@ gst_multi_queue_release_pad (GstElement * element, GstPad * pad)
   /* Find which single queue it belongs to, knowing that it should be a sinkpad */
   for (tmp = mqueue->queues; tmp; tmp = g_list_next (tmp)) {
     sq = (GstSingleQueue *) tmp->data;
+    sinkpad = g_weak_ref_get (&sq->sinkpad);
 
-    if (sq->sinkpad == pad)
+    if (sinkpad == pad) {
+      srcpad = g_weak_ref_get (&sq->srcpad);
       break;
+    }
+
+    gst_object_unref (sinkpad);
   }
 
   if (!tmp) {
+    gst_clear_object (&sinkpad);
+    gst_clear_object (&srcpad);
     GST_WARNING_OBJECT (mqueue, "That pad doesn't belong to this element ???");
     GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue);
     return;
@@ -1027,13 +1293,12 @@ gst_multi_queue_release_pad (GstElement * element, GstPad * pad)
   /* delete SingleQueue */
   gst_data_queue_set_flushing (sq->queue, TRUE);
 
-  gst_pad_set_active (sq->srcpad, FALSE);
-  gst_pad_set_active (sq->sinkpad, FALSE);
-  gst_pad_set_element_private (sq->srcpad, NULL);
-  gst_pad_set_element_private (sq->sinkpad, NULL);
-  gst_element_remove_pad (element, sq->srcpad);
-  gst_element_remove_pad (element, sq->sinkpad);
-  gst_single_queue_free (sq);
+  gst_pad_set_active (srcpad, FALSE);
+  gst_pad_set_active (sinkpad, FALSE);
+  gst_element_remove_pad (element, srcpad);
+  gst_element_remove_pad (element, sinkpad);
+  gst_object_unref (srcpad);
+  gst_object_unref (sinkpad);
 }
 
 static GstStateChangeReturn
@@ -1105,18 +1370,32 @@ gst_multi_queue_change_state (GstElement * element, GstStateChange transition)
 static gboolean
 gst_single_queue_start (GstMultiQueue * mq, GstSingleQueue * sq)
 {
+  gboolean res = FALSE;
+  GstPad *srcpad = g_weak_ref_get (&sq->srcpad);
+
   GST_LOG_OBJECT (mq, "SingleQueue %d : starting task", sq->id);
-  return gst_pad_start_task (sq->srcpad,
-      (GstTaskFunction) gst_multi_queue_loop, sq->srcpad, NULL);
+
+  if (srcpad) {
+    res = gst_pad_start_task (srcpad,
+        (GstTaskFunction) gst_multi_queue_loop, srcpad, NULL);
+    gst_object_unref (srcpad);
+  }
+
+  return res;
 }
 
 static gboolean
 gst_single_queue_pause (GstMultiQueue * mq, GstSingleQueue * sq)
 {
-  gboolean result;
+  gboolean result = FALSE;
+  GstPad *srcpad = g_weak_ref_get (&sq->srcpad);
 
   GST_LOG_OBJECT (mq, "SingleQueue %d : pausing task", sq->id);
-  result = gst_pad_pause_task (sq->srcpad);
+  if (srcpad) {
+    result = gst_pad_pause_task (srcpad);
+    gst_object_unref (srcpad);
+  }
+
   sq->sink_tainted = sq->src_tainted = TRUE;
   return result;
 }
@@ -1124,10 +1403,14 @@ gst_single_queue_pause (GstMultiQueue * mq, GstSingleQueue * sq)
 static gboolean
 gst_single_queue_stop (GstMultiQueue * mq, GstSingleQueue * sq)
 {
-  gboolean result;
+  gboolean result = FALSE;
+  GstPad *srcpad = g_weak_ref_get (&sq->srcpad);
 
   GST_LOG_OBJECT (mq, "SingleQueue %d : stopping task", sq->id);
-  result = gst_pad_stop_task (sq->srcpad);
+  if (srcpad) {
+    result = gst_pad_stop_task (srcpad);
+    gst_object_unref (srcpad);
+  }
   sq->sink_tainted = sq->src_tainted = TRUE;
   return result;
 }
@@ -1160,7 +1443,7 @@ gst_single_queue_flush (GstMultiQueue * mq, GstSingleQueue * sq, gboolean flush,
     gst_segment_init (&sq->sink_segment, GST_FORMAT_TIME);
     gst_segment_init (&sq->src_segment, GST_FORMAT_TIME);
     sq->has_src_segment = FALSE;
-    /* All pads start off not-linked for a smooth kick-off */
+    /* All pads start off OK for a smooth kick-off */
     sq->srcresult = GST_FLOW_OK;
     sq->pushed = FALSE;
     sq->cur_time = 0;
@@ -1189,14 +1472,14 @@ gst_single_queue_flush (GstMultiQueue * mq, GstSingleQueue * sq, gboolean flush,
 
 /* WITH LOCK TAKEN */
 static gint
-get_buffering_level (GstSingleQueue * sq)
+get_buffering_level (GstMultiQueue * mq, GstSingleQueue * sq)
 {
   GstDataQueueSize size;
   gint buffering_level, tmp;
 
   gst_data_queue_get_level (sq->queue, &size);
 
-  GST_DEBUG_OBJECT (sq->mqueue,
+  GST_DEBUG_OBJECT (mq,
       "queue %d: visible %u/%u, bytes %u/%u, time %" G_GUINT64_FORMAT "/%"
       G_GUINT64_FORMAT, sq->id, size.visible, sq->max_size.visible,
       size.bytes, sq->max_size.bytes, sq->cur_time, sq->max_size.time);
@@ -1235,22 +1518,27 @@ update_buffering (GstMultiQueue * mq, GstSingleQueue * sq)
     return;
 
 #ifdef TIZEN_FEATURE_MQ_SKIP_BUFFERING
-  GstCaps *caps = gst_pad_get_current_caps(sq->sinkpad);
-  GstStructure *s;
-
-  if (caps) {
-    /* skip buffering except audio and video */
-    if ((s = gst_caps_get_structure (caps, 0)) &&
-        (!g_strrstr (gst_structure_get_name (s), "video")) &&
-        (!g_strrstr (gst_structure_get_name (s), "audio"))) {
-        gst_caps_unref(caps);
-        return;
+  GstPad *sinkpad = g_weak_ref_get (&sq->sinkpad);
+  if (sinkpad) {
+    GstCaps *caps = gst_pad_get_current_caps (sinkpad);
+    GstStructure *s;
+
+    if (caps) {
+      /* skip buffering except audio and video */
+      if ((s = gst_caps_get_structure (caps, 0)) &&
+          (!g_strrstr (gst_structure_get_name (s), "video")) &&
+          (!g_strrstr (gst_structure_get_name (s), "audio"))) {
+          gst_caps_unref (caps);
+          gst_clear_object (&sinkpad);
+          return;
+      }
+      gst_caps_unref (caps);
     }
-    gst_caps_unref(caps);
   }
+  gst_clear_object (&sinkpad);
 #endif
 
-  buffering_level = get_buffering_level (sq);
+  buffering_level = get_buffering_level (mq, sq);
 
   /* scale so that if buffering_level equals the high watermark,
    * the percentage is 100% */
@@ -1274,7 +1562,7 @@ update_buffering (GstMultiQueue * mq, GstSingleQueue * sq)
     for (iter = mq->queues; iter; iter = g_list_next (iter)) {
       GstSingleQueue *oq = (GstSingleQueue *) iter->data;
 
-      if (get_buffering_level (oq) >= mq->high_watermark) {
+      if (get_buffering_level (mq, oq) >= mq->high_watermark) {
         is_buffering = FALSE;
 
         break;
@@ -1610,6 +1898,10 @@ apply_gap (GstMultiQueue * mq, GstSingleQueue * sq, GstEvent * event,
       timestamp += duration;
     }
 
+    GST_DEBUG_OBJECT (mq, "queue %d, %s position updated to %" GST_TIME_FORMAT,
+        sq->id, segment == &sq->sink_segment ? "sink" : "src",
+        GST_TIME_ARGS (timestamp));
+
     segment->position = timestamp;
 
     if (segment == &sq->sink_segment)
@@ -1672,6 +1964,14 @@ get_running_time (GstSegment * segment, GstMiniObject * object, gboolean end)
             my_segment_to_running_time ((GstSegment *) new_segment,
             new_segment->start);
       }
+    } else if (GST_EVENT_TYPE (event) == GST_EVENT_GAP) {
+      GstClockTime ts, dur;
+      gst_event_parse_gap (event, &ts, &dur);
+      if (GST_CLOCK_TIME_IS_VALID (ts)) {
+        if (GST_CLOCK_TIME_IS_VALID (dur))
+          ts += dur;
+        time = my_segment_to_running_time (segment, ts);
+      }
     }
   }
 
@@ -1684,6 +1984,13 @@ gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq,
     GstMiniObject * object, gboolean * allow_drop)
 {
   GstFlowReturn result = sq->srcresult;
+  GstPad *srcpad = g_weak_ref_get (&sq->srcpad);
+
+  if (!srcpad) {
+    GST_INFO_OBJECT (mq,
+        "Pushing while corresponding sourcepad has been cleared");
+    return GST_FLOW_FLUSHING;
+  }
 
   if (GST_IS_BUFFER (object)) {
     GstBuffer *buffer;
@@ -1707,7 +2014,7 @@ gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq,
       GST_DEBUG_OBJECT (mq,
           "SingleQueue %d : Pushing buffer %p with ts %" GST_TIME_FORMAT,
           sq->id, buffer, GST_TIME_ARGS (timestamp));
-      result = gst_pad_push (sq->srcpad, buffer);
+      result = gst_pad_push (srcpad, buffer);
     }
   } else if (GST_IS_EVENT (object)) {
     GstEvent *event;
@@ -1756,7 +2063,7 @@ gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq,
           "SingleQueue %d : Pushing event %p of type %s",
           sq->id, event, GST_EVENT_TYPE_NAME (event));
 
-      gst_pad_push_event (sq->srcpad, event);
+      gst_pad_push_event (srcpad, event);
     }
   } else if (GST_IS_QUERY (object)) {
     GstQuery *query;
@@ -1770,7 +2077,7 @@ gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq,
       gst_query_unref (query);
       res = FALSE;
     } else {
-      res = gst_pad_peer_query (sq->srcpad, query);
+      res = gst_pad_peer_query (srcpad, query);
     }
 
     GST_MULTI_QUEUE_MUTEX_LOCK (mq);
@@ -1782,6 +2089,8 @@ gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq,
     g_warning ("Unexpected object in singlequeue %u (refcounting problem?)",
         sq->id);
   }
+
+  gst_object_unref (srcpad);
   return result;
 
   /* ERRORS */
@@ -1861,9 +2170,14 @@ gst_multi_queue_loop (GstPad * pad)
   gboolean is_buffer;
   gboolean do_update_buffering = FALSE;
   gboolean dropping = FALSE;
+  GstPad *srcpad = NULL;
 
-  sq = (GstSingleQueue *) gst_pad_get_element_private (pad);
-  mq = sq->mqueue;
+  sq = GST_MULTIQUEUE_PAD (pad)->sq;
+  mq = g_weak_ref_get (&sq->mqueue);
+  srcpad = g_weak_ref_get (&sq->srcpad);
+
+  if (!mq || !srcpad)
+    goto out_flushing;
 
 next:
   GST_DEBUG_OBJECT (mq, "SingleQueue %d : trying to pop an object", sq->id);
@@ -2097,11 +2411,11 @@ next:
   gst_multi_queue_post_buffering (mq);
 
   GST_LOG_OBJECT (mq, "sq:%d AFTER PUSHING sq->srcresult: %s (is_eos:%d)",
-      sq->id, gst_flow_get_name (sq->srcresult), GST_PAD_IS_EOS (sq->srcpad));
+      sq->id, gst_flow_get_name (sq->srcresult), GST_PAD_IS_EOS (srcpad));
 
   /* Need to make sure wake up any sleeping pads when we exit */
   GST_MULTI_QUEUE_MUTEX_LOCK (mq);
-  if (mq->numwaiting > 0 && (GST_PAD_IS_EOS (sq->srcpad)
+  if (mq->numwaiting > 0 && (GST_PAD_IS_EOS (srcpad)
           || sq->srcresult == GST_FLOW_EOS)) {
     compute_high_time (mq, sq->groupid);
     compute_high_id (mq);
@@ -2116,6 +2430,10 @@ next:
       && result != GST_FLOW_EOS)
     goto out_flushing;
 
+done:
+  gst_clear_object (&mq);
+  gst_clear_object (&srcpad);
+
   return;
 
 out_flushing:
@@ -2146,11 +2464,11 @@ out_flushing:
     gst_single_queue_flush_queue (sq, FALSE);
     single_queue_underrun_cb (sq->queue, sq);
     gst_data_queue_set_flushing (sq->queue, TRUE);
-    gst_pad_pause_task (sq->srcpad);
+    gst_pad_pause_task (srcpad);
     GST_CAT_LOG_OBJECT (multi_queue_debug, mq,
         "SingleQueue[%d] task paused, reason:%s",
         sq->id, gst_flow_get_name (sq->srcresult));
-    return;
+    goto done;
   }
 }
 
@@ -2166,12 +2484,15 @@ gst_multi_queue_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   GstSingleQueue *sq;
   GstMultiQueue *mq;
-  GstMultiQueueItem *item;
+  GstMultiQueueItem *item = NULL;
   guint32 curid;
   GstClockTime timestamp, duration;
 
-  sq = gst_pad_get_element_private (pad);
-  mq = sq->mqueue;
+  sq = GST_MULTIQUEUE_PAD (pad)->sq;
+  mq = g_weak_ref_get (&sq->mqueue);
+
+  if (!mq)
+    goto flushing;
 
   /* if eos, we are always full, so avoid hanging incoming indefinitely */
   if (sq->is_eos)
@@ -2224,6 +2545,7 @@ gst_multi_queue_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
   apply_buffer (mq, sq, timestamp, duration, &sq->sink_segment);
 
 done:
+  gst_clear_object (&mq);
   return sq->srcresult;
 
   /* ERRORS */
@@ -2231,13 +2553,15 @@ flushing:
   {
     GST_LOG_OBJECT (mq, "SingleQueue %d : exit because task paused, reason: %s",
         sq->id, gst_flow_get_name (sq->srcresult));
-    gst_multi_queue_item_destroy (item);
+    if (item)
+      gst_multi_queue_item_destroy (item);
     goto done;
   }
 was_eos:
   {
     GST_DEBUG_OBJECT (mq, "we are EOS, dropping buffer, return EOS");
     gst_buffer_unref (buffer);
+    gst_object_unref (mq);
     return GST_FLOW_EOS;
   }
 }
@@ -2250,7 +2574,7 @@ gst_multi_queue_sink_activate_mode (GstPad * pad, GstObject * parent,
   GstSingleQueue *sq;
   GstMultiQueue *mq;
 
-  sq = (GstSingleQueue *) gst_pad_get_element_private (pad);
+  sq = GST_MULTIQUEUE_PAD (pad)->sq;
   mq = (GstMultiQueue *) gst_pad_get_parent (pad);
 
   /* mq is NULL if the pad is activated/deactivated before being
@@ -2310,9 +2634,19 @@ gst_multi_queue_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
   GstFlowReturn flowret = GST_FLOW_OK;
   GstEventType type;
   GstEvent *sref = NULL;
+  GstPad *srcpad;
+
 
-  sq = (GstSingleQueue *) gst_pad_get_element_private (pad);
+  sq = GST_MULTIQUEUE_PAD (pad)->sq;
   mq = (GstMultiQueue *) parent;
+  srcpad = g_weak_ref_get (&sq->srcpad);
+
+  if (!srcpad) {
+    GST_INFO_OBJECT (pad, "Pushing while corresponding sourcepad has been"
+        " removed already");
+
+    return GST_FLOW_FLUSHING;
+  }
 
   type = GST_EVENT_TYPE (event);
 
@@ -2338,7 +2672,7 @@ gst_multi_queue_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
       GST_DEBUG_OBJECT (mq, "SingleQueue %d : received flush start event",
           sq->id);
 
-      res = gst_pad_push_event (sq->srcpad, event);
+      res = gst_pad_push_event (srcpad, event);
 
       gst_single_queue_flush (mq, sq, TRUE, FALSE);
       gst_single_queue_pause (mq, sq);
@@ -2348,7 +2682,7 @@ gst_multi_queue_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
       GST_DEBUG_OBJECT (mq, "SingleQueue %d : received flush stop event",
           sq->id);
 
-      res = gst_pad_push_event (sq->srcpad, event);
+      res = gst_pad_push_event (srcpad, event);
 
       gst_single_queue_flush (mq, sq, FALSE, FALSE);
       gst_single_queue_start (mq, sq);
@@ -2394,7 +2728,7 @@ gst_multi_queue_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
 
     default:
       if (!(GST_EVENT_IS_SERIALIZED (event))) {
-        res = gst_pad_push_event (sq->srcpad, event);
+        res = gst_pad_push_event (srcpad, event);
         goto done;
       }
       break;
@@ -2468,6 +2802,8 @@ gst_multi_queue_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
   }
 
 done:
+
+  gst_object_unref (srcpad);
   if (res == FALSE)
     flowret = GST_FLOW_ERROR;
   GST_DEBUG_OBJECT (mq, "SingleQueue %d : returning %s", sq->id,
@@ -2476,6 +2812,7 @@ done:
 
 flushing:
   {
+    gst_object_unref (srcpad);
     GST_LOG_OBJECT (mq, "SingleQueue %d : exit because task paused, reason: %s",
         sq->id, gst_flow_get_name (sq->srcresult));
     if (sref)
@@ -2485,6 +2822,7 @@ flushing:
   }
 was_eos:
   {
+    gst_object_unref (srcpad);
     GST_DEBUG_OBJECT (mq, "we are EOS, dropping event, return GST_FLOW_EOS");
     gst_event_unref (event);
     return GST_FLOW_EOS;
@@ -2498,7 +2836,7 @@ gst_multi_queue_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
   GstSingleQueue *sq;
   GstMultiQueue *mq;
 
-  sq = (GstSingleQueue *) gst_pad_get_element_private (pad);
+  sq = GST_MULTIQUEUE_PAD (pad)->sq;
   mq = (GstMultiQueue *) parent;
 
   switch (GST_QUERY_TYPE (query)) {
@@ -2580,8 +2918,14 @@ gst_multi_queue_src_activate_mode (GstPad * pad, GstObject * parent,
   GstSingleQueue *sq;
   gboolean result;
 
-  sq = (GstSingleQueue *) gst_pad_get_element_private (pad);
-  mq = sq->mqueue;
+  sq = GST_MULTIQUEUE_PAD (pad)->sq;
+  mq = g_weak_ref_get (&sq->mqueue);
+
+  if (!mq) {
+    GST_ERROR_OBJECT (pad, "No multique set anymore, can't activate pad");
+
+    return FALSE;
+  }
 
   GST_DEBUG_OBJECT (mq, "SingleQueue %d", sq->id);
 
@@ -2599,15 +2943,25 @@ gst_multi_queue_src_activate_mode (GstPad * pad, GstObject * parent,
       result = FALSE;
       break;
   }
+  gst_object_unref (mq);
   return result;
 }
 
 static gboolean
 gst_multi_queue_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
-  GstSingleQueue *sq = gst_pad_get_element_private (pad);
-  GstMultiQueue *mq = sq->mqueue;
+  GstSingleQueue *sq = GST_MULTIQUEUE_PAD (pad)->sq;
+  GstMultiQueue *mq = g_weak_ref_get (&sq->mqueue);
   gboolean ret;
+  GstPad *sinkpad = g_weak_ref_get (&sq->sinkpad);
+
+  if (!mq || !sinkpad) {
+    gst_clear_object (&sinkpad);
+    gst_clear_object (&mq);
+    GST_INFO_OBJECT (pad, "No multique/sinkpad set anymore, flushing");
+
+    return FALSE;
+  }
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_RECONFIGURE:
@@ -2618,13 +2972,16 @@ gst_multi_queue_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
       }
       GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
 
-      ret = gst_pad_push_event (sq->sinkpad, event);
+      ret = gst_pad_push_event (sinkpad, event);
       break;
     default:
-      ret = gst_pad_push_event (sq->sinkpad, event);
+      ret = gst_pad_push_event (sinkpad, event);
       break;
   }
 
+  gst_object_unref (sinkpad);
+  gst_object_unref (mq);
+
   return ret;
 }
 
@@ -2702,26 +3059,36 @@ compute_high_id (GstMultiQueue * mq)
 
   for (tmp = mq->queues; tmp; tmp = g_list_next (tmp)) {
     GstSingleQueue *sq = (GstSingleQueue *) tmp->data;
+    GstPad *srcpad = g_weak_ref_get (&sq->srcpad);
+
+    if (!srcpad) {
+      GST_INFO_OBJECT (mq,
+          "srcpad has been removed already... ignoring single queue");
+
+      continue;
+    }
 
     GST_LOG_OBJECT (mq, "inspecting sq:%d , nextid:%d, oldid:%d, srcresult:%s",
         sq->id, sq->nextid, sq->oldid, gst_flow_get_name (sq->srcresult));
 
-    if (sq->srcresult == GST_FLOW_NOT_LINKED) {
-      /* No need to consider queues which are not waiting */
-      if (sq->nextid == 0) {
-        GST_LOG_OBJECT (mq, "sq:%d is not waiting - ignoring", sq->id);
-        continue;
-      }
+    /* No need to consider queues which are not waiting */
+    if (sq->nextid == 0) {
+      GST_LOG_OBJECT (mq, "sq:%d is not waiting - ignoring", sq->id);
+      gst_object_unref (srcpad);
+      continue;
+    }
 
+    if (sq->srcresult == GST_FLOW_NOT_LINKED) {
       if (sq->nextid < lowest)
         lowest = sq->nextid;
-    } else if (!GST_PAD_IS_EOS (sq->srcpad) && sq->srcresult != GST_FLOW_EOS) {
+    } else if (!GST_PAD_IS_EOS (srcpad) && 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 output is at EOS */
       if ((highid == G_MAXUINT32) || (sq->oldid > highid))
         highid = sq->oldid;
     }
+    gst_object_unref (srcpad);
   }
 
   if (highid == G_MAXUINT32 || lowest < highid)
@@ -2755,6 +3122,14 @@ compute_high_time (GstMultiQueue * mq, guint groupid)
 
   for (tmp = mq->queues; tmp; tmp = tmp->next) {
     GstSingleQueue *sq = (GstSingleQueue *) tmp->data;
+    GstPad *srcpad = g_weak_ref_get (&sq->srcpad);
+
+    if (!srcpad) {
+      GST_INFO_OBJECT (mq,
+          "srcpad has been removed already... ignoring single queue");
+
+      continue;
+    }
 
     GST_LOG_OBJECT (mq,
         "inspecting sq:%d (group:%d) , next_time:%" GST_STIME_FORMAT
@@ -2769,6 +3144,7 @@ compute_high_time (GstMultiQueue * mq, guint groupid)
       /* No need to consider queues which are not waiting */
       if (!GST_CLOCK_STIME_IS_VALID (sq->next_time)) {
         GST_LOG_OBJECT (mq, "sq:%d is not waiting - ignoring", sq->id);
+        gst_object_unref (srcpad);
         continue;
       }
 
@@ -2777,7 +3153,7 @@ compute_high_time (GstMultiQueue * mq, guint groupid)
       if (sq->groupid == groupid && (group_low == GST_CLOCK_STIME_NONE
               || sq->next_time < group_low))
         group_low = sq->next_time;
-    } else if (!GST_PAD_IS_EOS (sq->srcpad) && sq->srcresult != GST_FLOW_EOS) {
+    } else if (!GST_PAD_IS_EOS (srcpad) && sq->srcresult != GST_FLOW_EOS) {
       /* If we don't have a global high time, or the global high time
        * is lower than this single queue's last outputted time, store
        * the queue's one, unless the singlequeue output is at EOS. */
@@ -2796,6 +3172,8 @@ compute_high_time (GstMultiQueue * mq, guint groupid)
       GST_LOG_OBJECT (mq,
           "grouphigh %" GST_STIME_FORMAT " grouplow %" GST_STIME_FORMAT,
           GST_STIME_ARGS (group_high), GST_STIME_ARGS (group_low));
+
+    gst_object_unref (srcpad);
   }
 
   if (highest == GST_CLOCK_STIME_NONE)
@@ -2838,11 +3216,17 @@ compute_high_time (GstMultiQueue * mq, guint groupid)
 static void
 single_queue_overrun_cb (GstDataQueue * dq, GstSingleQueue * sq)
 {
-  GstMultiQueue *mq = sq->mqueue;
   GList *tmp;
   GstDataQueueSize size;
   gboolean filled = TRUE;
   gboolean empty_found = FALSE;
+  GstMultiQueue *mq = g_weak_ref_get (&sq->mqueue);
+
+  if (!mq) {
+    GST_ERROR ("No multique set anymore, not doing anything");
+
+    return;
+  }
 
   gst_data_queue_get_level (sq->queue, &size);
 
@@ -2895,6 +3279,7 @@ single_queue_overrun_cb (GstDataQueue * dq, GstSingleQueue * sq)
 
 done:
   GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
+  gst_object_unref (mq);
 
   /* Overrun is always forwarded, since this is blocking the upstream element */
   if (filled) {
@@ -2907,11 +3292,18 @@ static void
 single_queue_underrun_cb (GstDataQueue * dq, GstSingleQueue * sq)
 {
   gboolean empty = TRUE;
-  GstMultiQueue *mq = sq->mqueue;
+  GstMultiQueue *mq = g_weak_ref_get (&sq->mqueue);
   GList *tmp;
 
+  if (!mq) {
+    GST_ERROR ("No multique set anymore, not doing anything");
+
+    return;
+  }
+
   if (sq->srcresult == GST_FLOW_NOT_LINKED) {
     GST_LOG_OBJECT (mq, "Single Queue %d is empty but not-linked", sq->id);
+    gst_object_unref (mq);
     return;
   } else {
     GST_LOG_OBJECT (mq,
@@ -2938,6 +3330,7 @@ single_queue_underrun_cb (GstDataQueue * dq, GstSingleQueue * sq)
       empty = FALSE;
   }
   GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
+  gst_object_unref (mq);
 
   if (empty) {
     GST_DEBUG_OBJECT (mq, "All queues are empty, signalling it");
@@ -2950,7 +3343,13 @@ single_queue_check_full (GstDataQueue * dataq, guint visible, guint bytes,
     guint64 time, GstSingleQueue * sq)
 {
   gboolean res;
-  GstMultiQueue *mq = sq->mqueue;
+  GstMultiQueue *mq = g_weak_ref_get (&sq->mqueue);
+
+  if (!mq) {
+    GST_ERROR ("No multique set anymore, let's say we are full");
+
+    return TRUE;
+  }
 
   GST_DEBUG_OBJECT (mq,
       "queue %d: visible %u/%u, bytes %u/%u, time %" G_GUINT64_FORMAT "/%"
@@ -2958,12 +3357,16 @@ single_queue_check_full (GstDataQueue * dataq, guint visible, guint bytes,
       sq->max_size.bytes, sq->cur_time, sq->max_size.time);
 
   /* we are always filled on EOS */
-  if (sq->is_eos || sq->is_segment_done)
-    return TRUE;
+  if (sq->is_eos || sq->is_segment_done) {
+    res = TRUE;
+    goto done;
+  }
 
   /* we never go past the max visible items unless we are in buffering mode */
-  if (!mq->use_buffering && IS_FILLED (sq, visible, visible))
-    return TRUE;
+  if (!mq->use_buffering && IS_FILLED (sq, visible, visible)) {
+    res = TRUE;
+    goto done;
+  }
 
   /* check time or bytes */
 #ifdef TIZEN_FEATURE_MQ_MODIFICATION_EXTRA_SIZE_TIME
@@ -2983,6 +3386,8 @@ single_queue_check_full (GstDataQueue * dataq, guint visible, guint bytes,
     } else
       res |= IS_FILLED (sq, time, sq->cur_time);
   }
+done:
+  gst_object_unref (mq);
 
   return res;
 }
@@ -2993,6 +3398,8 @@ gst_single_queue_flush_queue (GstSingleQueue * sq, gboolean full)
   GstDataQueueItem *sitem;
   GstMultiQueueItem *mitem;
   gboolean was_flushing = FALSE;
+  GstPad *srcpad = g_weak_ref_get (&sq->srcpad);
+  GstMultiQueue *mq = g_weak_ref_get (&sq->mqueue);
 
   while (!gst_data_queue_is_empty (sq->queue)) {
     GstMiniObject *data;
@@ -3012,41 +3419,59 @@ gst_single_queue_flush_queue (GstSingleQueue * sq, gboolean full)
     data = sitem->object;
 
     if (!full && !mitem->is_query && GST_IS_EVENT (data)
-        && GST_EVENT_IS_STICKY (data)
+        && srcpad && GST_EVENT_IS_STICKY (data)
         && GST_EVENT_TYPE (data) != GST_EVENT_SEGMENT
         && GST_EVENT_TYPE (data) != GST_EVENT_EOS) {
-      gst_pad_store_sticky_event (sq->srcpad, GST_EVENT_CAST (data));
+      gst_pad_store_sticky_event (srcpad, GST_EVENT_CAST (data));
     }
 
     sitem->destroy (sitem);
   }
+  gst_clear_object (&srcpad);
 
   gst_data_queue_flush (sq->queue);
   if (was_flushing)
     gst_data_queue_set_flushing (sq->queue, TRUE);
 
-  GST_MULTI_QUEUE_MUTEX_LOCK (sq->mqueue);
-  update_buffering (sq->mqueue, sq);
-  GST_MULTI_QUEUE_MUTEX_UNLOCK (sq->mqueue);
-  gst_multi_queue_post_buffering (sq->mqueue);
+  if (mq) {
+    GST_MULTI_QUEUE_MUTEX_LOCK (mq);
+    update_buffering (mq, sq);
+    GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
+    gst_multi_queue_post_buffering (mq);
+    gst_object_unref (mq);
+  }
 }
 
 static void
-gst_single_queue_free (GstSingleQueue * sq)
+gst_single_queue_unref (GstSingleQueue * sq)
 {
-  /* DRAIN QUEUE */
-  gst_data_queue_flush (sq->queue);
-  g_object_unref (sq->queue);
-  g_cond_clear (&sq->turn);
-  g_cond_clear (&sq->query_handled);
-  g_free (sq);
+  if (g_atomic_int_dec_and_test (&sq->refcount)) {
+    /* DRAIN QUEUE */
+    gst_data_queue_flush (sq->queue);
+    g_object_unref (sq->queue);
+    g_cond_clear (&sq->turn);
+    g_cond_clear (&sq->query_handled);
+    g_weak_ref_clear (&sq->sinkpad);
+    g_weak_ref_clear (&sq->srcpad);
+    g_weak_ref_clear (&sq->mqueue);
+    g_free (sq);
+  }
+}
+
+
+static GstSingleQueue *
+gst_single_queue_ref (GstSingleQueue * squeue)
+{
+  g_atomic_int_inc (&squeue->refcount);
+
+  return squeue;
 }
 
 static GstSingleQueue *
 gst_single_queue_new (GstMultiQueue * mqueue, guint id)
 {
+  GstPad *srcpad, *sinkpad;
   GstSingleQueue *sq;
-  GstMultiQueuePad *mqpad;
   GstPadTemplate *templ;
   gchar *name;
   GList *tmp;
@@ -3073,6 +3498,8 @@ gst_single_queue_new (GstMultiQueue * mqueue, guint id)
   }
 
   sq = g_new0 (GstSingleQueue, 1);
+  g_atomic_int_set (&sq->refcount, 1);
+
   mqueue->nbqueues++;
   sq->id = temp_id;
   sq->groupid = DEFAULT_PAD_GROUP_ID;
@@ -3093,7 +3520,7 @@ gst_single_queue_new (GstMultiQueue * mqueue, guint id)
 
   GST_DEBUG_OBJECT (mqueue, "Creating GstSingleQueue id:%d", sq->id);
 
-  sq->mqueue = mqueue;
+  g_weak_ref_init (&sq->mqueue, mqueue);
   sq->srcresult = GST_FLOW_FLUSHING;
   sq->pushed = FALSE;
   sq->queue = gst_data_queue_new ((GstDataQueueCheckFullFunction)
@@ -3121,55 +3548,58 @@ gst_single_queue_new (GstMultiQueue * mqueue, guint id)
 
   name = g_strdup_printf ("sink_%u", sq->id);
   templ = gst_static_pad_template_get (&sinktemplate);
-  sq->sinkpad = g_object_new (GST_TYPE_MULTIQUEUE_PAD, "name", name,
+  sinkpad = g_object_new (GST_TYPE_MULTIQUEUE_PAD, "name", name,
       "direction", templ->direction, "template", templ, NULL);
+  g_weak_ref_init (&sq->sinkpad, sinkpad);
   gst_object_unref (templ);
   g_free (name);
 
-  mqpad = (GstMultiQueuePad *) sq->sinkpad;
-  mqpad->sq = sq;
+  GST_MULTIQUEUE_PAD (sinkpad)->sq = sq;
 
-  gst_pad_set_chain_function (sq->sinkpad,
+  gst_pad_set_chain_function (sinkpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_chain));
-  gst_pad_set_activatemode_function (sq->sinkpad,
+  gst_pad_set_activatemode_function (sinkpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_sink_activate_mode));
-  gst_pad_set_event_full_function (sq->sinkpad,
+  gst_pad_set_event_full_function (sinkpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_sink_event));
-  gst_pad_set_query_function (sq->sinkpad,
+  gst_pad_set_query_function (sinkpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_sink_query));
-  gst_pad_set_iterate_internal_links_function (sq->sinkpad,
+  gst_pad_set_iterate_internal_links_function (sinkpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_iterate_internal_links));
-  GST_OBJECT_FLAG_SET (sq->sinkpad, GST_PAD_FLAG_PROXY_CAPS);
+  GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_CAPS);
 
   name = g_strdup_printf ("src_%u", sq->id);
-  sq->srcpad = gst_pad_new_from_static_template (&srctemplate, name);
+  templ = gst_static_pad_template_get (&srctemplate);
+  srcpad = g_object_new (GST_TYPE_MULTIQUEUE_PAD, "name", name,
+      "direction", templ->direction, "template", templ, NULL);
+  g_weak_ref_init (&sq->srcpad, srcpad);
+  gst_object_unref (templ);
   g_free (name);
 
-  gst_pad_set_activatemode_function (sq->srcpad,
+  GST_MULTIQUEUE_PAD (srcpad)->sq = gst_single_queue_ref (sq);
+
+  gst_pad_set_activatemode_function (srcpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_src_activate_mode));
-  gst_pad_set_event_function (sq->srcpad,
+  gst_pad_set_event_function (srcpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_src_event));
-  gst_pad_set_query_function (sq->srcpad,
+  gst_pad_set_query_function (srcpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_src_query));
-  gst_pad_set_iterate_internal_links_function (sq->srcpad,
+  gst_pad_set_iterate_internal_links_function (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);
+  GST_OBJECT_FLAG_SET (srcpad, GST_PAD_FLAG_PROXY_CAPS);
 
   GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue);
 
   /* only activate the pads when we are not in the NULL state
-   * and add the pad under the state_lock to prevend state changes
+   * and add the pad under the state_lock to prevent state changes
    * between activating and adding */
   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_pad_set_active (srcpad, TRUE);
+    gst_pad_set_active (sinkpad, TRUE);
   }
-  gst_element_add_pad (GST_ELEMENT (mqueue), sq->srcpad);
-  gst_element_add_pad (GST_ELEMENT (mqueue), sq->sinkpad);
+  gst_element_add_pad (GST_ELEMENT (mqueue), srcpad);
+  gst_element_add_pad (GST_ELEMENT (mqueue), sinkpad);
   if (GST_STATE_TARGET (mqueue) != GST_STATE_NULL) {
     gst_single_queue_start (mqueue, sq);
   }
index 2b97b98..1a1a3fb 100644 (file)
@@ -32,6 +32,7 @@
 #include <string.h>
 
 #include "gstoutputselector.h"
+#include "gstcoreelementselements.h"
 
 GST_DEBUG_CATEGORY_STATIC (output_selector_debug);
 #define GST_CAT_DEFAULT output_selector_debug
@@ -85,6 +86,8 @@ GST_DEBUG_CATEGORY_INIT (output_selector_debug, \
 #define gst_output_selector_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstOutputSelector, gst_output_selector,
     GST_TYPE_ELEMENT, _do_init);
+GST_ELEMENT_REGISTER_DEFINE (output_selector, "output-selector", GST_RANK_NONE,
+    GST_TYPE_OUTPUT_SELECTOR);
 
 static void gst_output_selector_dispose (GObject * object);
 static void gst_output_selector_set_property (GObject * object,
@@ -147,6 +150,9 @@ gst_output_selector_class_init (GstOutputSelectorClass * klass)
       GST_DEBUG_FUNCPTR (gst_output_selector_release_pad);
 
   gstelement_class->change_state = gst_output_selector_change_state;
+
+  gst_type_mark_as_plugin_api (GST_TYPE_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE,
+      0);
 }
 
 static void
@@ -189,6 +195,7 @@ gst_output_selector_reset (GstOutputSelector * osel)
     gst_buffer_unref (osel->latest_buffer);
     osel->latest_buffer = NULL;
   }
+  osel->segment_seqnum = GST_SEQNUM_INVALID;
   GST_OBJECT_UNLOCK (osel);
   gst_segment_init (&osel->segment, GST_FORMAT_UNDEFINED);
 }
@@ -320,6 +327,38 @@ forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
   return TRUE;
 }
 
+static gboolean
+gst_output_selector_srcpad_event_func (GstPad * pad, GstObject * parent,
+    GstEvent * event)
+{
+  GstOutputSelector *osel = GST_OUTPUT_SELECTOR (parent);
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_SEEK:
+    {
+      guint32 seqnum = gst_event_get_seqnum (event);
+
+      GST_OBJECT_LOCK (osel);
+      if (seqnum == osel->segment_seqnum) {
+        GST_OBJECT_UNLOCK (osel);
+
+        GST_DEBUG_OBJECT (pad,
+            "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
+        gst_event_unref (event);
+        return TRUE;
+      }
+
+      osel->segment_seqnum = seqnum;
+      GST_OBJECT_UNLOCK (osel);
+      break;
+    }
+    default:
+      break;
+  }
+
+  return gst_pad_event_default (pad, parent, event);
+}
+
 static GstPad *
 gst_output_selector_request_new_pad (GstElement * element,
     GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
@@ -337,6 +376,7 @@ gst_output_selector_request_new_pad (GstElement * element,
   srcpad = gst_pad_new_from_template (templ, padname);
   GST_OBJECT_UNLOCK (osel);
 
+  gst_pad_set_event_function (srcpad, gst_output_selector_srcpad_event_func);
   gst_pad_set_active (srcpad, TRUE);
 
   /* Forward sticky events to the new srcpad */
index c39c5b1..7eb1b7d 100644 (file)
@@ -50,6 +50,7 @@ struct _GstOutputSelector {
   gint pad_negotiation_mode;
 
   GstSegment segment;
+  guint32 segment_seqnum;
 
   /* resend latest buffer after switch */
   gboolean resend_latest;
index 85680b6..2ca6673 100644 (file)
@@ -60,6 +60,7 @@
 
 #include <gst/gst.h>
 #include "gstqueue.h"
+#include "gstcoreelementselements.h"
 
 #include "../../gst/gst-i18n-lib.h"
 #include "../../gst/glib-compat-private.h"
@@ -190,6 +191,7 @@ enum
         "dataflow inside the queue element");
 #define gst_queue_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstQueue, gst_queue, GST_TYPE_ELEMENT, _do_init);
+GST_ELEMENT_REGISTER_DEFINE (queue, "queue", GST_RANK_NONE, GST_TYPE_QUEUE);
 
 static void gst_queue_finalize (GObject * object);
 static void gst_queue_set_property (GObject * object,
@@ -276,7 +278,7 @@ gst_queue_class_init (GstQueueClass * klass)
   gst_queue_signals[SIGNAL_UNDERRUN] =
       g_signal_new ("underrun", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
       G_STRUCT_OFFSET (GstQueueClass, underrun), NULL, NULL,
-      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+      NULL, G_TYPE_NONE, 0);
   /**
    * GstQueue::running:
    * @queue: the queue instance
@@ -288,7 +290,7 @@ gst_queue_class_init (GstQueueClass * klass)
   gst_queue_signals[SIGNAL_RUNNING] =
       g_signal_new ("running", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
       G_STRUCT_OFFSET (GstQueueClass, running), NULL, NULL,
-      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+      NULL, G_TYPE_NONE, 0);
   /**
    * GstQueue::overrun:
    * @queue: the queue instance
@@ -301,7 +303,7 @@ gst_queue_class_init (GstQueueClass * klass)
   gst_queue_signals[SIGNAL_OVERRUN] =
       g_signal_new ("overrun", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
       G_STRUCT_OFFSET (GstQueueClass, overrun), NULL, NULL,
-      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+      NULL, G_TYPE_NONE, 0);
   /**
    * GstQueue::pushing:
    * @queue: the queue instance
@@ -312,7 +314,7 @@ gst_queue_class_init (GstQueueClass * klass)
   gst_queue_signals[SIGNAL_PUSHING] =
       g_signal_new ("pushing", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
       G_STRUCT_OFFSET (GstQueueClass, pushing), NULL, NULL,
-      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+      NULL, G_TYPE_NONE, 0);
 
   /* properties */
   g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_BYTES,
@@ -393,7 +395,7 @@ gst_queue_class_init (GstQueueClass * klass)
 #endif /* TIZEN_FEATURE_QUEUE_MODIFICATION */
 
   /**
-   * GstQueue:flush-on-eos
+   * queue:flush-on-eos:
    *
    * Discard all data in the queue when an EOS event is received, and pass
    * on the EOS event as soon as possible (instead of waiting until all
@@ -429,6 +431,8 @@ gst_queue_class_init (GstQueueClass * klass)
   GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_src_query);
   GST_DEBUG_REGISTER_FUNCPTR (gst_queue_chain);
   GST_DEBUG_REGISTER_FUNCPTR (gst_queue_chain_list);
+
+  gst_type_mark_as_plugin_api (GST_TYPE_QUEUE_LEAKY, 0);
 }
 
 static void
@@ -1266,10 +1270,10 @@ gst_queue_chain_buffer_or_list (GstPad * pad, GstObject * parent,
             "queue is full, waiting for free space");
 
         /* don't leak. Instead, wait for space to be available */
-        do {
-          /* for as long as the queue is filled, wait till an item was deleted. */
+        /* for as long as the queue is filled, wait till an item was deleted. */
+        while (gst_queue_is_filled (queue)) {
           GST_QUEUE_WAIT_DEL_CHECK (queue, out_flushing);
-        } while (gst_queue_is_filled (queue));
+        };
 
         GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, "queue is not full");
 
@@ -1694,7 +1698,7 @@ gst_queue_handle_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
           && queue->leaky == GST_QUEUE_NO_LEAK)
         max += queue->max_size.time;
       else if (queue->max_size.time > 0 && queue->leaky != GST_QUEUE_NO_LEAK)
-        max = MIN (queue->max_size.time, max);
+        max = MAX (queue->max_size.time, max);
       else
         max = -1;
 
index 950bef0..4dffc9b 100644 (file)
  *
  * The temp-location property will be used to notify the application of the
  * allocated filename.
+ *
+ * If the #GstQueue2:use-buffering property is set to TRUE, and any writable
+ * property is modified, #GstQueue2 will attempt to post a buffering message
+ * if the changes to the properties also cause the buffering percentage to be
+ * changed (for example, because the queue's capacity was changed and it already
+ * contains some data).
  */
 
 #ifdef HAVE_CONFIG_H
@@ -56,6 +62,7 @@
 #endif
 
 #include "gstqueue2.h"
+#include "gstcoreelementselements.h"
 
 #include <glib/gstdio.h>
 
@@ -148,6 +155,7 @@ enum
 #endif
   PROP_LAST
 };
+static GParamSpec *obj_props[PROP_LAST] = { NULL, };
 
 /* Explanation for buffer levels and percentages:
  *
@@ -266,6 +274,7 @@ enum
         "dataflow inside the queue element");
 #define gst_queue2_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstQueue2, gst_queue2, GST_TYPE_ELEMENT, _do_init);
+GST_ELEMENT_REGISTER_DEFINE (queue2, "queue2", GST_RANK_NONE, GST_TYPE_QUEUE2);
 
 static void gst_queue2_finalize (GObject * object);
 
@@ -308,7 +317,9 @@ static gboolean gst_queue2_is_filled (GstQueue2 * queue);
 
 static void update_cur_level (GstQueue2 * queue, GstQueue2Range * range);
 static void update_in_rates (GstQueue2 * queue, gboolean force);
-static GstMessage *gst_queue2_get_buffering_message (GstQueue2 * queue);
+static GstMessage *gst_queue2_get_buffering_message (GstQueue2 * queue,
+    gint * percent);
+static void update_buffering (GstQueue2 * queue);
 static void gst_queue2_post_buffering (GstQueue2 * queue);
 
 typedef enum
@@ -338,104 +349,93 @@ gst_queue2_class_init (GstQueue2Class * klass)
   gobject_class->get_property = gst_queue2_get_property;
 
   /* properties */
-  g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_BYTES,
-      g_param_spec_uint ("current-level-bytes", "Current level (kB)",
-          "Current amount of data in the queue (bytes)",
-          0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_BUFFERS,
+  obj_props[PROP_CUR_LEVEL_BYTES] = g_param_spec_uint ("current-level-bytes",
+      "Current level (kB)", "Current amount of data in the queue (bytes)",
+      0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+  obj_props[PROP_CUR_LEVEL_BUFFERS] =
       g_param_spec_uint ("current-level-buffers", "Current level (buffers)",
-          "Current number of buffers in the queue",
-          0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_TIME,
-      g_param_spec_uint64 ("current-level-time", "Current level (ns)",
-          "Current amount of data in the queue (in ns)",
-          0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_property (gobject_class, PROP_MAX_SIZE_BYTES,
-      g_param_spec_uint ("max-size-bytes", "Max. size (kB)",
-          "Max. amount of data in the queue (bytes, 0=disable)",
-          0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES,
-          G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
-          G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_MAX_SIZE_BUFFERS,
-      g_param_spec_uint ("max-size-buffers", "Max. size (buffers)",
-          "Max. number of buffers in the queue (0=disable)", 0, G_MAXUINT,
-          DEFAULT_MAX_SIZE_BUFFERS,
-          G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
-          G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_MAX_SIZE_TIME,
-      g_param_spec_uint64 ("max-size-time", "Max. size (ns)",
-          "Max. amount of data in the queue (in ns, 0=disable)", 0, G_MAXUINT64,
-          DEFAULT_MAX_SIZE_TIME, G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
-          G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_property (gobject_class, PROP_USE_BUFFERING,
-      g_param_spec_boolean ("use-buffering", "Use buffering",
-          "Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds",
-          DEFAULT_USE_BUFFERING, G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
-          G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_USE_TAGS_BITRATE,
-      g_param_spec_boolean ("use-tags-bitrate", "Use bitrate from tags",
-          "Use a bitrate from upstream tags to estimate buffer duration if not provided",
-          DEFAULT_USE_TAGS_BITRATE,
-          G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
-          G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_USE_RATE_ESTIMATE,
-      g_param_spec_boolean ("use-rate-estimate", "Use Rate Estimate",
-          "Estimate the bitrate of the stream to calculate time level",
-          DEFAULT_USE_RATE_ESTIMATE,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_LOW_PERCENT,
-      g_param_spec_int ("low-percent", "Low percent",
-          "Low threshold for buffering to start. Only used if use-buffering is True "
-          "(Deprecated: use low-watermark instead)",
-          0, 100, DEFAULT_LOW_WATERMARK * 100,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_HIGH_PERCENT,
-      g_param_spec_int ("high-percent", "High percent",
-          "High threshold for buffering to finish. Only used if use-buffering is True "
-          "(Deprecated: use high-watermark instead)",
-          0, 100, DEFAULT_HIGH_WATERMARK * 100,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_LOW_WATERMARK,
-      g_param_spec_double ("low-watermark", "Low watermark",
-          "Low threshold for buffering to start. Only used if use-buffering is True",
-          0.0, 1.0, DEFAULT_LOW_WATERMARK,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_HIGH_WATERMARK,
-      g_param_spec_double ("high-watermark", "High watermark",
-          "High threshold for buffering to finish. Only used if use-buffering is True",
-          0.0, 1.0, DEFAULT_HIGH_WATERMARK,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_property (gobject_class, PROP_TEMP_TEMPLATE,
-      g_param_spec_string ("temp-template", "Temporary File Template",
-          "File template to store temporary files in, should contain directory "
-          "and XXXXXX. (NULL == disabled)",
-          NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_property (gobject_class, PROP_TEMP_LOCATION,
-      g_param_spec_string ("temp-location", "Temporary File Location",
-          "Location to store temporary files in (Only read this property, "
-          "use temp-template to configure the name template)",
-          NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_USE_BITRATE_QUERY,
-      g_param_spec_boolean ("use-bitrate-query",
-          "Use bitrate from downstream query",
-          "Use a bitrate from a downstream query to estimate buffer duration if not provided",
-          DEFAULT_USE_BITRATE_QUERY,
-          G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
-          G_PARAM_STATIC_STRINGS));
+      "Current number of buffers in the queue",
+      0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+  obj_props[PROP_CUR_LEVEL_TIME] = g_param_spec_uint64 ("current-level-time",
+      "Current level (ns)", "Current amount of data in the queue (in ns)",
+      0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+  obj_props[PROP_MAX_SIZE_BYTES] = g_param_spec_uint ("max-size-bytes",
+      "Max. size (kB)", "Max. amount of data in the queue (bytes, 0=disable)",
+      0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES,
+      G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
+  obj_props[PROP_MAX_SIZE_BUFFERS] = g_param_spec_uint ("max-size-buffers",
+      "Max. size (buffers)", "Max. number of buffers in the queue (0=disable)",
+      0, G_MAXUINT, DEFAULT_MAX_SIZE_BUFFERS,
+      G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
+  obj_props[PROP_MAX_SIZE_TIME] = g_param_spec_uint64 ("max-size-time",
+      "Max. size (ns)", "Max. amount of data in the queue (in ns, 0=disable)",
+      0, G_MAXUINT64, DEFAULT_MAX_SIZE_TIME,
+      G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
+
+  obj_props[PROP_USE_BUFFERING] = g_param_spec_boolean ("use-buffering",
+      "Use buffering",
+      "Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds "
+      "(0% = low-watermark, 100% = high-watermark)",
+      DEFAULT_USE_BUFFERING,
+      G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
+  obj_props[PROP_USE_TAGS_BITRATE] = g_param_spec_boolean ("use-tags-bitrate",
+      "Use bitrate from tags",
+      "Use a bitrate from upstream tags to estimate buffer duration if not provided",
+      DEFAULT_USE_TAGS_BITRATE,
+      G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
+  obj_props[PROP_USE_RATE_ESTIMATE] = g_param_spec_boolean ("use-rate-estimate",
+      "Use Rate Estimate",
+      "Estimate the bitrate of the stream to calculate time level",
+      DEFAULT_USE_RATE_ESTIMATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  obj_props[PROP_LOW_PERCENT] = g_param_spec_int ("low-percent", "Low percent",
+      "Low threshold for buffering to start. Only used if use-buffering is True "
+      "(Deprecated: use low-watermark instead)",
+      0, 100, DEFAULT_LOW_WATERMARK * 100,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  obj_props[PROP_HIGH_PERCENT] = g_param_spec_int ("high-percent",
+      "High percent",
+      "High threshold for buffering to finish. Only used if use-buffering is True "
+      "(Deprecated: use high-watermark instead)",
+      0, 100, DEFAULT_HIGH_WATERMARK * 100,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  obj_props[PROP_LOW_WATERMARK] = g_param_spec_double ("low-watermark",
+      "Low watermark",
+      "Low threshold for buffering to start. Only used if use-buffering is True",
+      0.0, 1.0, DEFAULT_LOW_WATERMARK,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  obj_props[PROP_HIGH_WATERMARK] = g_param_spec_double ("high-watermark",
+      "High watermark",
+      "High threshold for buffering to finish. Only used if use-buffering is True",
+      0.0, 1.0, DEFAULT_HIGH_WATERMARK,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  obj_props[PROP_TEMP_TEMPLATE] = g_param_spec_string ("temp-template",
+      "Temporary File Template",
+      "File template to store temporary files in, should contain directory "
+      "and XXXXXX. (NULL == disabled)",
+      NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  obj_props[PROP_TEMP_LOCATION] = g_param_spec_string ("temp-location",
+      "Temporary File Location",
+      "Location to store temporary files in (Only read this property, "
+      "use temp-template to configure the name template)",
+      NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+  obj_props[PROP_USE_BITRATE_QUERY] = g_param_spec_boolean ("use-bitrate-query",
+      "Use bitrate from downstream query",
+      "Use a bitrate from a downstream query to estimate buffer duration if not provided",
+      DEFAULT_USE_BITRATE_QUERY,
+      G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
 
   /**
    * GstQueue2:temp-remove
    *
    * When temp-template is set, remove the temporary file when going to READY.
    */
-  g_object_class_install_property (gobject_class, PROP_TEMP_REMOVE,
-      g_param_spec_boolean ("temp-remove", "Remove the Temporary File",
-          "Remove the temp-location after use",
-          DEFAULT_TEMP_REMOVE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  obj_props[PROP_TEMP_REMOVE] = g_param_spec_boolean ("temp-remove",
+      "Remove the Temporary File", "Remove the temp-location after use",
+      DEFAULT_TEMP_REMOVE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
   /**
    * GstQueue2:ring-buffer-max-size
@@ -443,22 +443,21 @@ gst_queue2_class_init (GstQueue2Class * klass)
    * The maximum size of the ring buffer in bytes. If set to 0, the ring
    * buffer is disabled. Default 0.
    */
-  g_object_class_install_property (gobject_class, PROP_RING_BUFFER_MAX_SIZE,
+  obj_props[PROP_RING_BUFFER_MAX_SIZE] =
       g_param_spec_uint64 ("ring-buffer-max-size",
-          "Max. ring buffer size (bytes)",
-          "Max. amount of data in the ring buffer (bytes, 0 = disabled)",
-          0, G_MAXUINT64, DEFAULT_RING_BUFFER_MAX_SIZE,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+      "Max. ring buffer size (bytes)",
+      "Max. amount of data in the ring buffer (bytes, 0 = disabled)",
+      0, G_MAXUINT64, DEFAULT_RING_BUFFER_MAX_SIZE,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
   /**
    * GstQueue2:avg-in-rate
    *
    * The average input data rate.
    */
-  g_object_class_install_property (gobject_class, PROP_AVG_IN_RATE,
-      g_param_spec_int64 ("avg-in-rate", "Input data rate (bytes/s)",
-          "Average input data rate (bytes/s)",
-          0, G_MAXINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+  obj_props[PROP_AVG_IN_RATE] = g_param_spec_int64 ("avg-in-rate",
+      "Input data rate (bytes/s)", "Average input data rate (bytes/s)",
+      0, G_MAXINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
 
   /**
    * GstQueue2:bitrate
@@ -467,10 +466,11 @@ gst_queue2_class_init (GstQueue2Class * klass)
    * the size of the queue.  Values are taken from either the upstream tags
    * or from the downstream bitrate query.
    */
-  g_object_class_install_property (gobject_class, PROP_BITRATE,
-      g_param_spec_uint64 ("bitrate", "Bitrate (bits/s)",
-          "Conversion value between data size and time",
-          0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+  obj_props[PROP_BITRATE] = g_param_spec_uint64 ("bitrate", "Bitrate (bits/s)",
+      "Conversion value between data size and time",
+      0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
 
 #ifdef TIZEN_FEATURE_RTSPSRC_MODIFICATION
   /**
@@ -855,6 +855,7 @@ query_downstream_bitrate (GstQueue2 * queue)
 {
   GstQuery *query = gst_query_new_bitrate ();
   guint downstream_bitrate = 0;
+  gboolean changed;
 
   if (gst_pad_peer_query (queue->srcpad, query)) {
     gst_query_parse_bitrate (query, &downstream_bitrate);
@@ -867,10 +868,17 @@ query_downstream_bitrate (GstQueue2 * queue)
   gst_query_unref (query);
 
   GST_QUEUE2_MUTEX_LOCK (queue);
+  changed = queue->downstream_bitrate != downstream_bitrate;
   queue->downstream_bitrate = downstream_bitrate;
   GST_QUEUE2_MUTEX_UNLOCK (queue);
 
-  g_object_notify (G_OBJECT (queue), "bitrate");
+  if (changed) {
+    if (queue->use_buffering)
+      update_buffering (queue);
+    gst_queue2_post_buffering (queue);
+
+    g_object_notify_by_pspec (G_OBJECT (queue), obj_props[PROP_BITRATE]);
+  }
 }
 
 /* take a buffer and update segment, updating the time level of the queue. */
@@ -1154,7 +1162,7 @@ get_buffering_stats (GstQueue2 * queue, gint percent, GstBufferingMode * mode,
 
 /* Called with the lock taken */
 static GstMessage *
-gst_queue2_get_buffering_message (GstQueue2 * queue)
+gst_queue2_get_buffering_message (GstQueue2 * queue, gint * percent)
 {
   GstMessage *msg = NULL;
   if (queue->percent_changed) {
@@ -1171,17 +1179,14 @@ gst_queue2_get_buffering_message (GstQueue2 * queue)
      * the queue becomes empty for a short period of time. */
     if (!queue->waiting_del
         && queue->last_posted_buffering_percent != queue->buffering_percent) {
-      gint percent = queue->buffering_percent;
+      *percent = queue->buffering_percent;
 
-      GST_DEBUG_OBJECT (queue, "Going to post buffering: %d%%", percent);
-      msg = gst_message_new_buffering (GST_OBJECT_CAST (queue), percent);
+      GST_DEBUG_OBJECT (queue, "Going to post buffering: %d%%", *percent);
+      msg = gst_message_new_buffering (GST_OBJECT_CAST (queue), *percent);
 
       gst_message_set_buffering_stats (msg, queue->mode, queue->avg_in,
           queue->avg_out, queue->buffering_left);
-
-      queue->last_posted_buffering_percent = percent;
     }
-    queue->percent_changed = FALSE;
   }
 
   return msg;
@@ -1191,14 +1196,29 @@ static void
 gst_queue2_post_buffering (GstQueue2 * queue)
 {
   GstMessage *msg = NULL;
+  gint percent = -1;
 
   g_mutex_lock (&queue->buffering_post_lock);
   GST_QUEUE2_MUTEX_LOCK (queue);
-  msg = gst_queue2_get_buffering_message (queue);
+  msg = gst_queue2_get_buffering_message (queue, &percent);
   GST_QUEUE2_MUTEX_UNLOCK (queue);
 
-  if (msg != NULL)
-    gst_element_post_message (GST_ELEMENT_CAST (queue), msg);
+  if (msg != NULL) {
+    if (gst_element_post_message (GST_ELEMENT_CAST (queue), msg)) {
+      GST_QUEUE2_MUTEX_LOCK (queue);
+      /* Set these states only if posting the message succeeded. Otherwise,
+       * this post attempt failed, and the next one won't be done, because
+       * gst_queue2_get_buffering_message() checks these states and decides
+       * based on their values that it won't produce a message. */
+      queue->last_posted_buffering_percent = percent;
+      if (percent == queue->buffering_percent)
+        queue->percent_changed = FALSE;
+      GST_QUEUE2_MUTEX_UNLOCK (queue);
+      GST_DEBUG_OBJECT (queue, "successfully posted %d%% buffering message",
+          percent);
+    } else
+      GST_DEBUG_OBJECT (queue, "could not post buffering message");
+  }
 
   g_mutex_unlock (&queue->buffering_post_lock);
 }
@@ -1211,7 +1231,6 @@ update_buffering (GstQueue2 * queue)
   /* Ensure the variables used to calculate buffering state are up-to-date. */
   if (queue->current)
     update_cur_level (queue, queue->current);
-
   update_in_rates (queue, FALSE);
 
   if (!get_buffering_level (queue, NULL, &buffering_level))
@@ -1476,7 +1495,6 @@ gst_queue2_have_data (GstQueue2 * queue, guint64 offset, guint length)
   } else {
     GST_INFO_OBJECT (queue, "not found in any range off %" G_GUINT64_FORMAT
         " len %u", offset, length);
-
     /* we don't have the range, see how far away we are */
     if (!queue->is_eos && queue->current) {
       guint64 threshold = get_seek_threshold (queue);
@@ -1655,13 +1673,11 @@ gst_queue2_create_read (GstQueue2 * queue, guint64 offset, guint length,
     /* set range reading_pos to actual reading position for this read */
     queue->current->reading_pos = rpos;
 
-
     /* configure how much and from where to read */
     if (QUEUE_IS_USING_RING_BUFFER (queue)) {
       file_offset =
           (queue->current->rb_offset + (rpos -
               queue->current->offset)) % rb_size;
-
       if (file_offset + read_length > rb_size) {
         block_length = rb_size - file_offset;
       } else {
@@ -1760,7 +1776,6 @@ gst_queue2_read_item_from_file (GstQueue2 * queue)
     GstBuffer *buffer = NULL;
     guint64 reading_pos;
 
-
     reading_pos = queue->current->reading_pos;
 
     ret =
@@ -1825,7 +1840,7 @@ gst_queue2_open_temp_location_file (GstQueue2 * queue)
   GST_QUEUE2_MUTEX_UNLOCK (queue);
 
   /* we can't emit the notify with the lock */
-  g_object_notify (G_OBJECT (queue), "temp-location");
+  g_object_notify_by_pspec (G_OBJECT (queue), obj_props[PROP_TEMP_LOCATION]);
 
   GST_QUEUE2_MUTEX_LOCK (queue);
 
@@ -2253,14 +2268,33 @@ gst_queue2_create_write (GstQueue2 * queue, GstBuffer * buffer)
     /* update the buffering status */
     if (queue->use_buffering) {
       GstMessage *msg;
+      gint percent = -1;
       update_buffering (queue);
-      msg = gst_queue2_get_buffering_message (queue);
+      msg = gst_queue2_get_buffering_message (queue, &percent);
       if (msg) {
+        gboolean post_ok;
+
         GST_QUEUE2_MUTEX_UNLOCK (queue);
+
         g_mutex_lock (&queue->buffering_post_lock);
-        gst_element_post_message (GST_ELEMENT_CAST (queue), msg);
-        g_mutex_unlock (&queue->buffering_post_lock);
+        post_ok = gst_element_post_message (GST_ELEMENT_CAST (queue), msg);
+
         GST_QUEUE2_MUTEX_LOCK (queue);
+
+        if (post_ok) {
+          /* Set these states only if posting the message succeeded. Otherwise,
+           * this post attempt failed, and the next one won't be done, because
+           * gst_queue2_get_buffering_message() checks these states and decides
+           * based on their values that it won't produce a message. */
+          queue->last_posted_buffering_percent = percent;
+          if (percent == queue->buffering_percent)
+            queue->percent_changed = FALSE;
+          GST_DEBUG_OBJECT (queue, "successfully posted %d%% buffering message",
+              percent);
+        } else {
+          GST_DEBUG_OBJECT (queue, "could not post buffering message");
+        }
+        g_mutex_unlock (&queue->buffering_post_lock);
       }
     }
 
@@ -2678,7 +2712,7 @@ gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent,
 
         gst_event_unref (event);
       }
-      g_object_notify (G_OBJECT (queue), "bitrate");
+      g_object_notify_by_pspec (G_OBJECT (queue), obj_props[PROP_BITRATE]);
       break;
     }
     case GST_EVENT_TAG:{
@@ -2693,7 +2727,7 @@ gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent,
           queue->sink_tags_bitrate = bitrate;
           GST_QUEUE2_MUTEX_UNLOCK (queue);
           GST_LOG_OBJECT (queue, "Sink pad bitrate from tags now %u", bitrate);
-          g_object_notify (G_OBJECT (queue), "bitrate");
+          g_object_notify_by_pspec (G_OBJECT (queue), obj_props[PROP_BITRATE]);
         }
       }
       /* Fall-through */
@@ -2762,7 +2796,7 @@ gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent,
         GST_QUEUE2_MUTEX_UNLOCK (queue);
         gst_queue2_post_buffering (queue);
         if (bitrate_changed)
-          g_object_notify (G_OBJECT (queue), "bitrate");
+          g_object_notify_by_pspec (G_OBJECT (queue), obj_props[PROP_BITRATE]);
       } else {
         /* non-serialized events are passed downstream. */
         ret = gst_pad_push_event (queue->srcpad, event);
@@ -2821,10 +2855,14 @@ gst_queue2_handle_sink_query (GstPad * pad, GstObject * parent,
          * be pushed for sure) or we are not buffering. If we are buffering,
          * the pipeline waits to unblock downstream until our queue fills up
          * completely, which can not happen if we block on the query..
-         * Therefore we only potentially block when we are not buffering. */
+         * Therefore we only potentially block when we are not buffering.
+         *
+         * Update: Edward Hervey 2021: Realistically when posting buffering
+         * messages there are no safe places where we can block and forward a
+         * serialized query due to the potential of causing deadlocks. We
+         * therefore refuse any serialized queries in such cases. */
         GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->sinkresult, out_flushing);
-        if (QUEUE_IS_USING_QUEUE (queue) && (gst_queue2_is_empty (queue)
-                || !queue->use_buffering)) {
+        if (QUEUE_IS_USING_QUEUE (queue) && !queue->use_buffering) {
           if (!g_atomic_int_get (&queue->downstream_may_block)) {
             gst_queue2_locked_enqueue (queue, query,
                 GST_QUEUE2_ITEM_TYPE_QUERY);
@@ -2843,7 +2881,7 @@ gst_queue2_handle_sink_query (GstPad * pad, GstObject * parent,
           }
         } else {
           GST_DEBUG_OBJECT (queue,
-              "refusing query, we are not using the queue");
+              "refusing query, we are not using the queue or we are posting buffering messages");
           res = FALSE;
         }
         GST_QUEUE2_MUTEX_UNLOCK (queue);
@@ -2891,7 +2929,11 @@ gst_queue2_is_filled (GstQueue2 * queue)
   if (queue->is_eos)
     return TRUE;
 
-#define CHECK_FILLED(format,alt_max) ((queue->max_level.format) > 0 && \
+  /* Check the levels if non-null */
+#define CHECK_FILLED_REAL(format) \
+  ((queue->max_level.format) > 0 && (queue->cur_level.format) >= ((queue->max_level.format)))
+  /* Check the levels if non-null (use the alternative max if non-zero) */
+#define CHECK_FILLED_ALT(format,alt_max) ((queue->max_level.format) > 0 && \
     (queue->cur_level.format) >= ((alt_max) ? \
       MIN ((queue->max_level.format), (alt_max)) : (queue->max_level.format)))
 
@@ -2902,7 +2944,7 @@ gst_queue2_is_filled (GstQueue2 * queue)
     GST_DEBUG_OBJECT (queue,
         "max bytes %u, rb size %" G_GUINT64_FORMAT ", cur bytes %u",
         queue->max_level.bytes, rb_size, queue->cur_level.bytes);
-    return CHECK_FILLED (bytes, rb_size);
+    return CHECK_FILLED_ALT (bytes, rb_size);
   }
 
   /* if using file, we're never filled if we don't have EOS */
@@ -2914,15 +2956,16 @@ gst_queue2_is_filled (GstQueue2 * queue)
     return FALSE;
 
   /* we are filled if one of the current levels exceeds the max */
-  res = CHECK_FILLED (buffers, 0) || CHECK_FILLED (bytes, 0)
-      || CHECK_FILLED (time, 0);
+  res = CHECK_FILLED_REAL (buffers) || CHECK_FILLED_REAL (bytes)
+      || CHECK_FILLED_REAL (time);
 
   /* if we need to, use the rate estimate to check against the max time we are
    * allowed to queue */
   if (queue->use_rate_estimate)
-    res |= CHECK_FILLED (rate_time, 0);
+    res |= CHECK_FILLED_REAL (rate_time);
 
-#undef CHECK_FILLED
+#undef CHECK_FILLED_REAL
+#undef CHECK_FILLED_ALT
   return res;
 }
 
@@ -3094,6 +3137,11 @@ next:
   GST_QUEUE2_MUTEX_UNLOCK (queue);
   gst_queue2_post_buffering (queue);
 
+  if (gst_pad_check_reconfigure (queue->srcpad)) {
+    /* If the pad was reconfigured, do a new bitrate query */
+    query_downstream_bitrate (queue);
+  }
+
   if (item_type == GST_QUEUE2_ITEM_TYPE_BUFFER) {
     GstBuffer *buffer;
 
@@ -3128,7 +3176,7 @@ next:
           queue->src_tags_bitrate = bitrate;
           GST_QUEUE2_MUTEX_UNLOCK (queue);
           GST_LOG_OBJECT (queue, "src pad bitrate from tags now %u", bitrate);
-          g_object_notify (G_OBJECT (queue), "bitrate");
+          g_object_notify_by_pspec (G_OBJECT (queue), obj_props[PROP_BITRATE]);
         }
       }
     }
@@ -3327,6 +3375,10 @@ gst_queue2_handle_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
       GST_QUEUE2_MUTEX_LOCK (queue);
       /* assume downstream is linked now and try to push again */
       if (queue->srcresult == GST_FLOW_NOT_LINKED) {
+        /* Mark the pad as needing reconfiguration, and
+         * the loop will re-query downstream bitrate
+         */
+        gst_pad_mark_reconfigure (pad);
         queue->srcresult = GST_FLOW_OK;
         queue->sinkresult = GST_FLOW_OK;
         if (GST_PAD_MODE (pad) == GST_PAD_MODE_PUSH) {
@@ -3337,9 +3389,6 @@ gst_queue2_handle_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
       }
       GST_QUEUE2_MUTEX_UNLOCK (queue);
 
-      /* force a new bitrate query to be performed */
-      query_downstream_bitrate (queue);
-
       res = gst_pad_push_event (queue->sinkpad, event);
       break;
     default:
@@ -3538,14 +3587,20 @@ gst_queue2_handle_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
     {
       gboolean pull_mode;
       GstSchedulingFlags flags = 0;
+      GstQuery *upstream;
+
+      upstream = gst_query_new_scheduling ();
 #ifdef TIZEN_FEATURE_QUEUE2_MODIFICATION
-      if ((!QUEUE_IS_USING_QUEUE (queue)) && !gst_pad_peer_query (queue->sinkpad, query))
+      if (!(QUEUE_IS_USING_QUEUE (queue)) && !gst_pad_peer_query (queue->sinkpad, upstream)) {
 #else
-      if (!gst_pad_peer_query (queue->sinkpad, query))
+      if (!gst_pad_peer_query (queue->sinkpad, upstream)) {
 #endif
+        gst_query_unref (upstream);
         goto peer_failed;
+      }
 
-      gst_query_parse_scheduling (query, &flags, NULL, NULL, NULL);
+      gst_query_parse_scheduling (upstream, &flags, NULL, NULL, NULL);
+      gst_query_unref (upstream);
 
 #ifdef TIZEN_FEATURE_QUEUE2_MODIFICATION
       if (!(flags & GST_SCHEDULING_FLAG_SEEKABLE)) {
@@ -3863,7 +3918,10 @@ gst_queue2_change_state (GstElement * element, GstStateChange transition)
       queue->starting_segment = NULL;
       gst_event_replace (&queue->stream_start_event, NULL);
       GST_QUEUE2_MUTEX_UNLOCK (queue);
-      query_downstream_bitrate (queue);
+
+      /* Mark the srcpad as reconfigured to trigger querying
+       * the downstream bitrate next time it tries to push */
+      gst_pad_mark_reconfigure (queue->srcpad);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
 #ifdef TIZEN_FEATURE_QUEUE2_MODIFICATION
index 4f45a46..5466b56 100644 (file)
@@ -165,7 +165,7 @@ struct _GstQueue2
   guint64 ring_buffer_max_size;
   guint8 * ring_buffer;
 
-  volatile gint downstream_may_block;
+  gint downstream_may_block;
 
   GstBufferingMode mode;
   gint64 buffering_left;
index 0ff6b16..201f84a 100644 (file)
@@ -28,8 +28,8 @@
 
 #ifdef G_OS_WIN32
 #include <io.h>                 /* lseek, open, close, read */
-#undef lseek
-#define lseek _lseeki64
+#undef fseek
+#define fseek _fseeki64
 #undef off_t
 #define off_t guint64
 #else
@@ -38,7 +38,7 @@
 
 #ifdef HAVE_FSEEKO
 #define FSEEK_FILE(file,offset)  (fseeko (file, (off_t) offset, SEEK_SET) != 0)
-#elif defined (G_OS_UNIX) || defined (G_OS_WIN32)
+#elif defined (G_OS_UNIX)
 #define FSEEK_FILE(file,offset)  (lseek (fileno (file), (off_t) offset, SEEK_SET) == (off_t) -1)
 #else
 #define FSEEK_FILE(file,offset)  (fseek (file, offset, SEEK_SET) != 0)
@@ -67,6 +67,7 @@ struct _GstSparseFile
   gint fd;
   FILE *file;
   gsize current_pos;
+  gboolean was_writing;
 
   GstSparseRange *ranges;
   guint n_ranges;
@@ -191,14 +192,11 @@ gst_sparse_file_clear (GstSparseFile * file)
 {
   g_return_if_fail (file != NULL);
 
-  if (file->file) {
-    fclose (file->file);
-    file->file = fdopen (file->fd, "wb+");
-  }
   g_slice_free_chain (GstSparseRange, file->ranges, next);
   file->current_pos = 0;
   file->ranges = NULL;
   file->n_ranges = 0;
+  file->was_writing = FALSE;
 }
 
 /**
@@ -255,7 +253,10 @@ gst_sparse_file_write (GstSparseFile * file, gsize offset, gconstpointer data,
       GST_DEBUG ("seeking to %" G_GSIZE_FORMAT, offset);
       if (FSEEK_FILE (file->file, offset))
         goto error;
+    } else if (!file->was_writing) {
+      fflush (file->file);
     }
+    file->was_writing = TRUE;
     if (fwrite (data, count, 1, file->file) != 1)
       goto error;
   }
@@ -341,7 +342,10 @@ gst_sparse_file_read (GstSparseFile * file, gsize offset, gpointer data,
           file->current_pos, offset);
       if (FSEEK_FILE (file->file, offset))
         goto error;
+    } else if (file->was_writing) {
+      fflush (file->file);
     }
+    file->was_writing = FALSE;
     res = fread (data, 1, count, file->file);
     if (G_UNLIKELY (res < count))
       goto error;
index f0b1dd2..fdc5636 100644 (file)
@@ -47,6 +47,7 @@
 #include <string.h>
 
 #include "gststreamiddemux.h"
+#include "gstcoreelementselements.h"
 
 GST_DEBUG_CATEGORY_STATIC (streamid_demux_debug);
 #define GST_CAT_DEFAULT streamid_demux_debug
@@ -76,6 +77,8 @@ GST_DEBUG_CATEGORY_INIT (streamid_demux_debug, \
 #define gst_streamid_demux_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstStreamidDemux, gst_streamid_demux,
     GST_TYPE_ELEMENT, _do_init);
+GST_ELEMENT_REGISTER_DEFINE (streamiddemux, "streamiddemux", GST_RANK_PRIMARY,
+    GST_TYPE_STREAMID_DEMUX);
 
 static void gst_streamid_demux_dispose (GObject * object);
 static void gst_streamid_demux_get_property (GObject * object, guint prop_id,
index 0ff7527..dd90c38 100644 (file)
@@ -50,6 +50,7 @@
 #endif
 
 #include "gsttee.h"
+#include "gstcoreelementselements.h"
 #include "gst/glib-compat-private.h"
 
 #include <string.h>
@@ -109,6 +110,7 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src_%u",
     GST_DEBUG_CATEGORY_INIT (gst_tee_debug, "tee", 0, "tee element");
 #define gst_tee_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstTee, gst_tee, GST_TYPE_ELEMENT, _do_init);
+GST_ELEMENT_REGISTER_DEFINE (tee, "tee", GST_RANK_NONE, GST_TYPE_TEE);
 
 static GParamSpec *pspec_last_message = NULL;
 static GParamSpec *pspec_alloc_pad = NULL;
@@ -297,6 +299,8 @@ gst_tee_class_init (GstTeeClass * klass)
   gstelement_class->request_new_pad =
       GST_DEBUG_FUNCPTR (gst_tee_request_new_pad);
   gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_tee_release_pad);
+
+  gst_type_mark_as_plugin_api (GST_TYPE_TEE_PULL_MODE, 0);
 }
 
 static void
index 67110e3..ad4e7b1 100644 (file)
@@ -73,6 +73,7 @@
 #include "gst/gst_private.h"
 
 #include "gsttypefindelement.h"
+#include "gstcoreelementselements.h"
 #include "gst/gst-i18n-lib.h"
 #include "gst/base/gsttypefindhelper.h"
 
@@ -136,6 +137,8 @@ enum
 #define gst_type_find_element_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstTypeFindElement, gst_type_find_element,
     GST_TYPE_ELEMENT, _do_init);
+GST_ELEMENT_REGISTER_DEFINE (typefind, "typefind", GST_RANK_NONE,
+    GST_TYPE_TYPE_FIND_ELEMENT);
 
 static void gst_type_find_element_dispose (GObject * object);
 static void gst_type_find_element_set_property (GObject * object,
@@ -279,7 +282,7 @@ gst_type_find_element_class_init (GstTypeFindElementClass * typefind_class)
   gst_type_find_element_signals[HAVE_TYPE] = g_signal_new ("have-type",
       G_TYPE_FROM_CLASS (typefind_class), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstTypeFindElementClass, have_type), NULL, NULL,
-      g_cclosure_marshal_generic, G_TYPE_NONE, 2,
+      NULL, G_TYPE_NONE, 2,
       G_TYPE_UINT, GST_TYPE_CAPS | G_SIGNAL_TYPE_STATIC_SCOPE);
 
   typefind_class->have_type =
@@ -534,6 +537,7 @@ gst_type_find_element_seek (GstTypeFindElement * typefind, GstEvent * event)
   }
 
   typefind->need_segment = TRUE;
+  typefind->seqnum = gst_event_get_seqnum (event);
 
   /* restart our task since it might have been stopped when we did the
    * flush. */
@@ -1179,9 +1183,12 @@ gst_type_find_element_loop (GstPad * pad)
     GstBuffer *outbuf = NULL;
 
     if (typefind->need_segment) {
+      GstEvent *event;
       typefind->need_segment = FALSE;
-      gst_pad_push_event (typefind->src,
-          gst_event_new_segment (&typefind->segment));
+      event = gst_event_new_segment (&typefind->segment);
+      if (typefind->seqnum != 0)
+        gst_event_set_seqnum (event, typefind->seqnum);
+      gst_pad_push_event (typefind->src, event);
     }
 
     /* Pull 4k blocks and send downstream */
@@ -1260,6 +1267,7 @@ gst_type_find_element_activate_sink_mode (GstPad * pad, GstObject * parent,
         typefind->need_segment = TRUE;
         typefind->need_stream_start = TRUE;
         typefind->offset = 0;
+        typefind->seqnum = 0;
         res = TRUE;
       } else {
         res = gst_pad_stop_task (pad);
index 0152622..b0af0d5 100644 (file)
@@ -65,6 +65,7 @@ struct _GstTypeFindElement {
   gboolean need_stream_start;
   GstSegment segment;
   guint64 offset;
+  guint32 seqnum;
 };
 
 struct _GstTypeFindElementClass {
index 9dbc7a6..bbb3527 100644 (file)
 #endif
 
 #include "gstvalve.h"
+#include "gstcoreelementselements.h"
 
 #include <string.h>
 
 GST_DEBUG_CATEGORY_STATIC (valve_debug);
 #define GST_CAT_DEFAULT (valve_debug)
 
+#define GST_TYPE_VALVE_DROP_MODE (gst_valve_drop_mode_get_type ())
+static GType
+gst_valve_drop_mode_get_type (void)
+{
+  static GType drop_mode_type = 0;
+  static const GEnumValue drop_mode[] = {
+    {GST_VALVE_DROP_MODE_DROP_ALL, "Drop all buffers and events", "drop-all"},
+    {GST_VALVE_DROP_MODE_FORWARD_STICKY_EVENTS,
+        "Drop all buffers but forward sticky events", "forward-sticky-events"},
+    {GST_VALVE_DROP_MODE_TRANSFORM_TO_GAP,
+          "Convert all dropped buffers into gap events and forward sticky events",
+        "transform-to-gap"},
+    {0, NULL, NULL},
+  };
+
+  if (!drop_mode_type) {
+    drop_mode_type = g_enum_register_static ("GstValveDropMode", drop_mode);
+  }
+  return drop_mode_type;
+}
+
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
@@ -56,10 +78,12 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
 enum
 {
   PROP_0,
-  PROP_DROP
+  PROP_DROP,
+  PROP_DROP_MODE
 };
 
 #define DEFAULT_DROP FALSE
+#define DEFAULT_DROP_MODE GST_VALVE_DROP_MODE_DROP_ALL
 
 static void gst_valve_set_property (GObject * object,
     guint prop_id, const GValue * value, GParamSpec * pspec);
@@ -77,6 +101,7 @@ static gboolean gst_valve_query (GstPad * pad, GstObject * parent,
   GST_DEBUG_CATEGORY_INIT (valve_debug, "valve", 0, "Valve");
 #define gst_valve_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstValve, gst_valve, GST_TYPE_ELEMENT, _do_init);
+GST_ELEMENT_REGISTER_DEFINE (valve, "valve", GST_RANK_NONE, GST_TYPE_VALVE);
 
 static void
 gst_valve_class_init (GstValveClass * klass)
@@ -96,18 +121,35 @@ gst_valve_class_init (GstValveClass * klass)
           DEFAULT_DROP, G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
           G_PARAM_STATIC_STRINGS));
 
+  /**
+   * GstValve:drop-mode
+   *
+   * Drop mode to use. By default all buffers and events are dropped.
+   *
+   * Since: 1.20
+   */
+  g_object_class_install_property (gobject_class, PROP_DROP_MODE,
+      g_param_spec_enum ("drop-mode", "Drop mode",
+          "The drop mode to use", GST_TYPE_VALVE_DROP_MODE,
+          DEFAULT_DROP_MODE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+          GST_PARAM_MUTABLE_READY));
+
   gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
   gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate);
 
   gst_element_class_set_static_metadata (gstelement_class, "Valve element",
       "Filter", "Drops buffers and events or lets them through",
       "Olivier Crete <olivier.crete@collabora.co.uk>");
+
+  gst_type_mark_as_plugin_api (GST_TYPE_VALVE_DROP_MODE, 0);
 }
 
 static void
 gst_valve_init (GstValve * valve)
 {
   valve->drop = FALSE;
+  valve->drop_mode = DEFAULT_DROP;
   valve->discont = FALSE;
 
   valve->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
@@ -140,6 +182,9 @@ gst_valve_set_property (GObject * object,
       g_atomic_int_set (&valve->drop, g_value_get_boolean (value));
       gst_pad_push_event (valve->sinkpad, gst_event_new_reconfigure ());
       break;
+    case PROP_DROP_MODE:
+      valve->drop_mode = g_value_get_enum (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -156,6 +201,9 @@ gst_valve_get_property (GObject * object,
     case PROP_DROP:
       g_value_set_boolean (value, g_atomic_int_get (&valve->drop));
       break;
+    case PROP_DROP_MODE:
+      g_value_set_enum (value, valve->drop_mode);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -188,6 +236,11 @@ gst_valve_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
   GstFlowReturn ret = GST_FLOW_OK;
 
   if (g_atomic_int_get (&valve->drop)) {
+    if (valve->drop_mode == GST_VALVE_DROP_MODE_TRANSFORM_TO_GAP) {
+      GstEvent *ev = gst_event_new_gap (GST_BUFFER_PTS (buffer),
+          GST_BUFFER_DURATION (buffer));
+      gst_pad_push_event (valve->srcpad, ev);
+    }
     gst_buffer_unref (buffer);
     valve->discont = TRUE;
   } else {
@@ -213,17 +266,39 @@ gst_valve_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
   return ret;
 }
 
+static inline gboolean
+gst_valve_event_needs_dropping (GstValve * valve, GstEvent * event)
+{
+  if (!g_atomic_int_get (&valve->drop))
+    return FALSE;
+
+  switch (valve->drop_mode) {
+    case GST_VALVE_DROP_MODE_DROP_ALL:
+      return TRUE;
+    case GST_VALVE_DROP_MODE_FORWARD_STICKY_EVENTS:
+      return !GST_EVENT_IS_STICKY (event);
+    case GST_VALVE_DROP_MODE_TRANSFORM_TO_GAP:
+      return (!GST_EVENT_IS_STICKY (event) &&
+          GST_EVENT_TYPE (event) != GST_EVENT_GAP);
+    default:
+      g_assert_not_reached ();
+      break;
+  }
+
+  return FALSE;
+}
 
 static gboolean
 gst_valve_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
-  GstValve *valve;
+  GstValve *valve = GST_VALVE (parent);
+  gboolean needs_dropping = gst_valve_event_needs_dropping (valve, event);
   gboolean is_sticky = GST_EVENT_IS_STICKY (event);
   gboolean ret = TRUE;
 
   valve = GST_VALVE (parent);
 
-  if (g_atomic_int_get (&valve->drop)) {
+  if (needs_dropping) {
     valve->need_repush_sticky |= is_sticky;
     gst_event_unref (event);
   } else {
@@ -233,10 +308,11 @@ gst_valve_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
   }
 
   /* Ignore errors if "drop" was changed while the thread was blocked
-   * downwards.
+   * downwards, or if we're dropping but forwarding sticky events nonetheless.
    */
   if (g_atomic_int_get (&valve->drop)) {
-    valve->need_repush_sticky |= is_sticky;
+    if (valve->drop_mode == GST_VALVE_DROP_MODE_DROP_ALL)
+      valve->need_repush_sticky |= is_sticky;
     ret = TRUE;
   }
 
index eb3c29e..34f48f4 100644 (file)
@@ -45,6 +45,23 @@ typedef struct _GstValve GstValve;
 typedef struct _GstValveClass GstValveClass;
 
 /**
+ * GstValveDropMode:
+ * @GST_VALVE_DROP_MODE_DROP_ALL: Drop all buffers, buffer lists and events.
+ * @GST_VALVE_DROP_MODE_FORWARD_STICKY_EVENTS: Drop all buffers, buffer lists
+ *     and non-sticky events but forward sticky events.
+ * @GST_VALVE_DROP_MODE_TRANSFORM_TO_GAP: Drop all buffers, buffer lists and
+ *     non-sticky events but forward sticky events and forward GAP events for each
+ *     dropped buffer.
+ *
+ * Since: 1.20
+ */
+typedef enum {
+  GST_VALVE_DROP_MODE_DROP_ALL,
+  GST_VALVE_DROP_MODE_FORWARD_STICKY_EVENTS,
+  GST_VALVE_DROP_MODE_TRANSFORM_TO_GAP,
+} GstValveDropMode;
+
+/**
  * GstValve:
  *
  * The private valve structure
@@ -55,7 +72,9 @@ struct _GstValve
   GstElement parent;
 
   /* atomic boolean */
-  volatile gint drop;
+  gint drop;
+
+  GstValveDropMode drop_mode;
 
   /* Protected by the stream lock */
   gboolean discont;
index 3efb0b5..574ee87 100644 (file)
@@ -4,7 +4,7 @@ gst_elements_sources = [
   'gstconcat.c',
   'gstdataurisrc.c',
   'gstdownloadbuffer.c',
-  'gstelements.c',
+  'gstcoreelementsplugin.c',
   'gstelements_private.c',
   'gstfakesink.c',
   'gstfakesrc.c',
@@ -35,3 +35,5 @@ gst_elements = library('gstcoreelements',
   install_dir : plugins_install_dir,
 )
 pkgconfig.generate(gst_elements, install_dir : plugins_pkgconfig_install_dir)
+
+plugins += [gst_elements]
index 4725ced..ddb3a6e 100644 (file)
@@ -1,4 +1,5 @@
+plugins = []
 subdir('elements')
-if tracer_hooks
+if not get_option('coretracers').disabled()
   subdir('tracers')
 endif
diff --git a/plugins/tracers/.gitignore b/plugins/tracers/.gitignore
deleted file mode 100644 (file)
index dc1483e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-Makefile
-Makefile.in
-*.o
-*.lo
-*.la
-.deps
-.libs
-*.bb
-*.bbg
-*.da
-*.def
-*.gcno
diff --git a/plugins/tracers/Makefile.am b/plugins/tracers/Makefile.am
deleted file mode 100644 (file)
index 576ccd5..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-
-plugin_LTLIBRARIES = libgstcoretracers.la
-
-if HAVE_GETRUSAGE
-RUSAGE_SOURCES = gstrusage.c
-else
-RUSAGE_SOURCES =
-endif
-
-if GST_DISABLE_GST_DEBUG
-LOG_SOURCES =
-else
-LOG_SOURCES = gstlog.c
-endif
-
-libgstcoretracers_la_DEPENDENCIES = $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la
-libgstcoretracers_la_SOURCES = \
-  gstlatency.c \
-  gstleaks.c \
-  $(LOG_SOURCES) \
-  $(RUSAGE_SOURCES) \
-  gststats.c \
-  gsttracers.c
-
-libgstcoretracers_la_CFLAGS = $(GST_OBJ_CFLAGS) \
-  -DGST_USE_UNSTABLE_API
-libgstcoretracers_la_LIBADD = $(GST_OBJ_LIBS)
-libgstcoretracers_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-
-noinst_HEADERS = \
-  gstlatency.h \
-  gstleaks.h \
-  gstlog.h \
-  gstrusage.h \
-  gststats.h
-
-CLEANFILES = *.gcno *.gcda *.gcov *.gcov.out
-
-%.c.gcov: .libs/libgstcoretracers_la-%.gcda %.c
-       $(GCOV) -b -f -o $^ > $@.out
-
-gcov: $(libgstcoretracers_la_SOURCES:=.gcov)
-
diff --git a/plugins/tracers/gstfactories.c b/plugins/tracers/gstfactories.c
new file mode 100644 (file)
index 0000000..fbb2505
--- /dev/null
@@ -0,0 +1,187 @@
+/* GStreamer
+ * Copyright (C) 2021 Collabora Ltd.
+ *  @author: Olivier Crete <olivier.crete@collabora.com>
+ *
+ * gstfactories.c: A trace to log which plugin & factories are being used
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+/**
+ * SECTION:tracer-factories
+ * @short_description: log plugin and factories
+ *
+ * A tracing module that logs which plugins and factories are being used.
+ *
+ * This tracing module is particularly useful in conjuction with the `gst-stats`
+ * program to generate a list of plugins and elements that are loaded by a
+ * particular application to generate a minimal custom build of GStreamer.
+ *
+ * As a very simple example, you can run your application like this:
+ * ```
+ * $ GST_TRACERS=factories GST_DEBUG=GST_TRACER:7 gst-launch-1.0 audiotestsrc num-buffers=10 ! fakesink 2> log.txt
+ * ...
+ * $ gst-stats-1.0 log.txt
+ * Plugins used: audiotestsrc;coreelements
+ * Elements: audiotestsrc:audiotestsrc;coreelements:fakesink
+ * Device-providers:
+ * Typefinds:
+ * Dynamic-types:
+ * ```
+ *
+ * Based on this information, one can build a minimal, yet sufficient
+ * build of GStreamer using gst-build with a configuration like this one:
+ * ```
+ * meson setup builddir -Dgst-full-elements="audiotestsrc:audiotestsrc;coreelements:fakesink"
+ * ```
+ *
+ * Since: 1.20
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include "gstfactories.h"
+
+G_DEFINE_TYPE (GstFactoriesTracer, gst_factories_tracer, GST_TYPE_TRACER);
+
+static GstTracerRecord *tr_factory_used;
+
+static void
+do_element_new (GstFactoriesTracer * self, GstClockTime ts,
+    GstElement * element)
+{
+  const gchar *plugin_name;
+  const gchar *factory_name;
+  GstPluginFeature *feature;
+  GstElementFactory *factory = gst_element_get_factory (element);
+  const gchar *source_module_name = "Unknown";
+  GstPlugin *plugin;
+
+  if (factory == NULL)
+    return;
+
+  feature = GST_PLUGIN_FEATURE (factory);
+
+  factory_name = gst_plugin_feature_get_name (feature);
+  plugin_name = gst_plugin_feature_get_plugin_name (feature);
+
+  if (factory_name == NULL)
+    factory_name = "";
+  if (plugin_name == NULL)
+    plugin_name = "";
+
+  plugin = gst_plugin_feature_get_plugin (feature);
+  if (plugin)
+    source_module_name = gst_plugin_get_source (plugin);
+
+  gst_tracer_record_log (tr_factory_used,
+      (guint64) (guintptr) g_thread_self (), ts, "element", factory_name,
+      plugin_name, source_module_name);
+
+  g_clear_object (&plugin);
+}
+
+static void
+do_plugin_feature_loaded (GstFactoriesTracer * self, GstClockTime ts,
+    GstPluginFeature * feature)
+{
+  const gchar *plugin_name;
+  const gchar *factory_name;
+  const gchar *factory_type;
+  const gchar *source_module_name = "Unknown";
+  GstPlugin *plugin;
+
+  /* Only care about elements when one is created */
+  if (GST_IS_ELEMENT_FACTORY (feature))
+    return;
+
+  if (GST_IS_TYPE_FIND_FACTORY (feature))
+    factory_type = "typefind";
+  else if (GST_IS_DEVICE_PROVIDER_FACTORY (feature))
+    factory_type = "device-provider";
+  else if (GST_IS_DYNAMIC_TYPE_FACTORY (feature))
+    factory_type = "dynamic-type";
+  else
+    g_assert_not_reached ();
+
+  factory_name = gst_plugin_feature_get_name (feature);
+  plugin_name = gst_plugin_feature_get_plugin_name (feature);
+
+  if (factory_name == NULL)
+    factory_name = "";
+  if (plugin_name == NULL)
+    plugin_name = "";
+
+  plugin = gst_plugin_feature_get_plugin (feature);
+  if (plugin)
+    source_module_name = gst_plugin_get_source (plugin);
+  if (source_module_name == NULL)
+    source_module_name = "";
+
+  gst_tracer_record_log (tr_factory_used,
+      (guint64) (guintptr) g_thread_self (), ts, factory_type, factory_name,
+      plugin_name, source_module_name);
+
+  g_clear_object (&plugin);
+}
+
+static void
+gst_factories_tracer_class_init (GstFactoriesTracerClass * klass)
+{
+  /* announce trace formats */
+  /* *INDENT-OFF* */
+  tr_factory_used = gst_tracer_record_new ("factory-used.class",
+      "thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
+          "type", G_TYPE_GTYPE, G_TYPE_UINT64,
+          "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_THREAD,
+          NULL),
+      "ts", GST_TYPE_STRUCTURE, gst_structure_new ("value",
+          "type", G_TYPE_GTYPE, G_TYPE_UINT64,
+          "description", G_TYPE_STRING, "event ts",
+          NULL),
+      "factory-type", GST_TYPE_STRUCTURE, gst_structure_new ("value",
+          "type", G_TYPE_GTYPE, G_TYPE_STRING,
+          "description", G_TYPE_STRING, "type name of the factory",
+          NULL),
+      "factory", GST_TYPE_STRUCTURE, gst_structure_new ("value",
+          "type", G_TYPE_GTYPE, G_TYPE_STRING,
+          "description", G_TYPE_STRING, "name of the object factory",
+          NULL),
+      "plugin", GST_TYPE_STRUCTURE, gst_structure_new ("value",
+          "type", G_TYPE_GTYPE, G_TYPE_STRING,
+          "description", G_TYPE_STRING, "name of the plugin",
+          NULL),
+      "source-module", GST_TYPE_STRUCTURE, gst_structure_new ("value",
+          "type", G_TYPE_GTYPE, G_TYPE_STRING,
+          "description", G_TYPE_STRING, "name of the source module this feature is from",
+          NULL),
+     NULL);
+  /* *INDENT-ON* */
+
+  GST_OBJECT_FLAG_SET (tr_factory_used, GST_OBJECT_FLAG_MAY_BE_LEAKED);
+}
+
+static void
+gst_factories_tracer_init (GstFactoriesTracer * self)
+{
+  GstTracer *tracer = GST_TRACER (self);
+
+  gst_tracing_register_hook (tracer, "element-new",
+      G_CALLBACK (do_element_new));
+  gst_tracing_register_hook (tracer, "plugin-feature-loaded",
+      G_CALLBACK (do_plugin_feature_loaded));
+}
similarity index 55%
rename from docs/random/LICENSE
rename to plugins/tracers/gstfactories.h
index 696b1c1..9505515 100644 (file)
@@ -1,5 +1,8 @@
 /* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ * Copyright (C) 2021 Collabora Ltd.
+ *  @author: Olivier Crete <olivier.crete@collabora.com>
+ *
+ * gstfactories.h: A trace to log which plugin & factories are being used
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
  * Boston, MA 02110-1301, USA.
  */
+
+#ifndef __GST_FACTORIES_TRACER_H__
+#define __GST_FACTORIES_TRACER_H__
+
+#include <gst/gst.h>
+#include <gst/gsttracer.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE(GstFactoriesTracer, gst_factories_tracer, GST,
+    FACTORIES_TRACER, GstTracer)
+/**
+ * GstFactoriesTracer:
+ *
+ * Opaque #GstFactoriesTracer data structure
+ */
+struct _GstFactoriesTracer {
+  GstTracer     parent;
+
+  /*< private >*/
+};
+
+G_END_DECLS
+
+#endif /* __GST_FACTORIES_TRACER_H__ */
index e2f0889..5cfb551 100644 (file)
@@ -19,7 +19,7 @@
  * Boston, MA 02110-1301, USA.
  */
 /**
- * SECTION:element-latencytracer
+ * SECTION:tracer-latency
  * @short_description: log processing latency stats
  *
  * A tracing module that determines src-to-sink latencies by injecting custom
@@ -105,12 +105,15 @@ get_real_pad_parent (GstPad * pad)
   if (!pad)
     return NULL;
 
-  parent = GST_OBJECT_PARENT (pad);
+  parent = gst_object_get_parent (GST_OBJECT_CAST (pad));
 
   /* if parent of pad is a ghost-pad, then pad is a proxy_pad */
   if (parent && GST_IS_GHOST_PAD (parent)) {
+    GstObject *tmp;
     pad = GST_PAD_CAST (parent);
-    parent = GST_OBJECT_PARENT (pad);
+    tmp = gst_object_get_parent (GST_OBJECT_CAST (pad));
+    gst_object_unref (parent);
+    parent = tmp;
   }
   return GST_ELEMENT_CAST (parent);
 }
@@ -176,6 +179,9 @@ log_latency (const GstStructure * data, GstElement * sink_parent,
   const GValue *value;
   gchar *sink, *element_sink, *id_element_sink;
 
+  g_return_if_fail (sink_parent);
+  g_return_if_fail (sink_pad);
+
   value = gst_structure_id_get_value (data, latency_probe_ts);
   src_ts = g_value_get_uint64 (value);
 
@@ -207,6 +213,9 @@ log_element_latency (const GstStructure * data, GstElement * parent,
   gchar *pad_name, *element_name, *element_id;
   const GValue *value;
 
+  g_return_if_fail (parent);
+  g_return_if_fail (pad);
+
   element_id = g_strdup_printf ("%p", parent);
   element_name = gst_element_get_name (parent);
   pad_name = gst_pad_get_name (pad);
@@ -228,7 +237,7 @@ static void
 send_latency_probe (GstLatencyTracer * self, GstElement * parent, GstPad * pad,
     guint64 ts)
 {
-  GstPad *peer_pad = GST_PAD_PEER (pad);
+  GstPad *peer_pad = gst_pad_get_peer (pad);
   GstElement *peer_parent = get_real_pad_parent (peer_pad);
 
   /* allow for non-parented pads to send latency probes as used in e.g.
@@ -237,7 +246,7 @@ send_latency_probe (GstLatencyTracer * self, GstElement * parent, GstPad * pad,
     gchar *pad_name, *element_name, *element_id;
     GstEvent *latency_probe;
 
-    if (self->flags & GST_LATENCY_TRACER_FLAG_PIPELINE &&
+    if (parent && self->flags & GST_LATENCY_TRACER_FLAG_PIPELINE &&
         GST_OBJECT_FLAG_IS_SET (parent, GST_ELEMENT_FLAG_SOURCE)) {
       element_id = g_strdup_printf ("%p", parent);
       element_name = gst_element_get_name (parent);
@@ -259,7 +268,8 @@ send_latency_probe (GstLatencyTracer * self, GstElement * parent, GstPad * pad,
       gst_pad_push_event (pad, latency_probe);
     }
 
-    if (self->flags & GST_LATENCY_TRACER_FLAG_ELEMENT) {
+    if (peer_parent && peer_pad &&
+        self->flags & GST_LATENCY_TRACER_FLAG_ELEMENT) {
       element_id = g_strdup_printf ("%p", peer_parent);
       element_name = gst_element_get_name (peer_parent);
       pad_name = gst_pad_get_name (peer_pad);
@@ -280,36 +290,44 @@ send_latency_probe (GstLatencyTracer * self, GstElement * parent, GstPad * pad,
       g_free (element_id);
     }
   }
+  if (peer_pad)
+    gst_object_unref (peer_pad);
+  if (peer_parent)
+    gst_object_unref (peer_parent);
 }
 
 static void
 calculate_latency (GstElement * parent, GstPad * pad, guint64 ts)
 {
-  GstElement *peer_parent = get_real_pad_parent (GST_PAD_PEER (pad));
-
   if (parent && (!GST_IS_BIN (parent)) &&
       (!GST_OBJECT_FLAG_IS_SET (parent, GST_ELEMENT_FLAG_SOURCE))) {
     GstEvent *ev;
+    GstPad *peer_pad = gst_pad_get_peer (pad);
+    GstElement *peer_parent = get_real_pad_parent (peer_pad);
 
-    /* FIXME unsafe use of peer */
-    if (GST_OBJECT_FLAG_IS_SET (peer_parent, GST_ELEMENT_FLAG_SINK)) {
+    /* Protect against element being unlinked */
+    if (peer_pad && peer_parent &&
+        GST_OBJECT_FLAG_IS_SET (peer_parent, GST_ELEMENT_FLAG_SINK)) {
       ev = g_object_get_qdata ((GObject *) pad, latency_probe_id);
-      GST_DEBUG ("%s_%s: Should log full lantency now (event %p)",
+      GST_DEBUG ("%s_%s: Should log full latency now (event %p)",
           GST_DEBUG_PAD_NAME (pad), ev);
       if (ev) {
-        log_latency (gst_event_get_structure (ev), peer_parent,
-            GST_PAD_PEER (pad), ts);
+        log_latency (gst_event_get_structure (ev), peer_parent, peer_pad, ts);
         g_object_set_qdata ((GObject *) pad, latency_probe_id, NULL);
       }
     }
 
     ev = g_object_get_qdata ((GObject *) pad, sub_latency_probe_id);
-    GST_DEBUG ("%s_%s: Should log sub lantency now (event %p)",
+    GST_DEBUG ("%s_%s: Should log sub latency now (event %p)",
         GST_DEBUG_PAD_NAME (pad), ev);
     if (ev) {
       log_element_latency (gst_event_get_structure (ev), parent, pad, ts);
       g_object_set_qdata ((GObject *) pad, sub_latency_probe_id, NULL);
     }
+    if (peer_pad)
+      gst_object_unref (peer_pad);
+    if (peer_parent)
+      gst_object_unref (peer_parent);
   }
 }
 
@@ -321,6 +339,9 @@ do_push_buffer_pre (GstTracer * tracer, guint64 ts, GstPad * pad)
 
   send_latency_probe (self, parent, pad, ts);
   calculate_latency (parent, pad, ts);
+
+  if (parent)
+    gst_object_unref (parent);
 }
 
 static void
@@ -331,6 +352,9 @@ do_pull_range_pre (GstTracer * tracer, guint64 ts, GstPad * pad)
   GstElement *parent = get_real_pad_parent (peer_pad);
 
   send_latency_probe (self, parent, peer_pad, ts);
+
+  if (parent)
+    gst_object_unref (parent);
 }
 
 static void
@@ -339,6 +363,9 @@ do_pull_range_post (GstTracer * self, guint64 ts, GstPad * pad)
   GstElement *parent = get_real_pad_parent (pad);
 
   calculate_latency (parent, pad, ts);
+
+  if (parent)
+    gst_object_unref (parent);
 }
 
 static GstPadProbeReturn
@@ -352,12 +379,11 @@ do_drop_sub_latency_event (GstPad * pad, GstPadProbeInfo * info,
     const GstStructure *data = gst_event_get_structure (ev);
 
     if (gst_structure_get_name_id (data) == sub_latency_probe_id) {
-      /* FIXME unsafe peer pad usage */
-      GstPad *peer_pad = GST_PAD_PEER (pad);
+      GstPad *peer_pad = gst_pad_get_peer (pad);
       GstElement *peer_parent = get_real_pad_parent (peer_pad);
       const GValue *value;
       gchar *element_id = g_strdup_printf ("%p", peer_parent);
-      gchar *pad_name = gst_pad_get_name (peer_pad);
+      gchar *pad_name = peer_pad ? gst_pad_get_name (peer_pad) : NULL;
       const gchar *value_element_id, *value_pad_name;
 
       /* Get the element id, element name and pad name from data */
@@ -366,7 +392,8 @@ do_drop_sub_latency_event (GstPad * pad, GstPadProbeInfo * info,
       value = gst_structure_id_get_value (data, latency_probe_pad);
       value_pad_name = g_value_get_string (value);
 
-      if (!g_str_equal (value_element_id, element_id) ||
+      if (pad_name == NULL ||
+          !g_str_equal (value_element_id, element_id) ||
           !g_str_equal (value_pad_name, pad_name)) {
         GST_DEBUG ("%s_%s: Dropping sub-latency event",
             GST_DEBUG_PAD_NAME (pad));
@@ -375,6 +402,11 @@ do_drop_sub_latency_event (GstPad * pad, GstPadProbeInfo * info,
 
       g_free (pad_name);
       g_free (element_id);
+
+      if (peer_pad)
+        gst_object_unref (peer_pad);
+      if (peer_parent)
+        gst_object_unref (peer_parent);
     }
   }
 
@@ -385,13 +417,13 @@ static void
 do_push_event_pre (GstTracer * self, guint64 ts, GstPad * pad, GstEvent * ev)
 {
   GstElement *parent = get_real_pad_parent (pad);
-  GstPad *peer_pad = GST_PAD_PEER (pad);
-  GstElement *peer_parent = get_real_pad_parent (peer_pad);
 
   if (parent && (!GST_IS_BIN (parent)) &&
       (!GST_OBJECT_FLAG_IS_SET (parent, GST_ELEMENT_FLAG_SOURCE)) &&
       GST_EVENT_TYPE (ev) == GST_EVENT_CUSTOM_DOWNSTREAM) {
     const GstStructure *data = gst_event_get_structure (ev);
+    GstPad *peer_pad = gst_pad_get_peer (pad);
+    GstElement *peer_parent = get_real_pad_parent (peer_pad);
 
     /* if not set yet, add a pad probe that prevents sub-latency event from
      * flowing further */
@@ -406,8 +438,8 @@ do_push_event_pre (GstTracer * self, guint64 ts, GstPad * pad, GstEvent * ev)
             (gpointer) 1);
       }
 
-      /* FIXME unsafe peer access */
-      if (GST_OBJECT_FLAG_IS_SET (peer_parent, GST_ELEMENT_FLAG_SINK)) {
+      if (peer_parent == NULL
+          || GST_OBJECT_FLAG_IS_SET (peer_parent, GST_ELEMENT_FLAG_SINK)) {
         /* store event so that we can calculate latency when the buffer that
          * follows has been processed */
         g_object_set_qdata_full ((GObject *) pad, latency_probe_id,
@@ -418,7 +450,7 @@ do_push_event_pre (GstTracer * self, guint64 ts, GstPad * pad, GstEvent * ev)
     if (gst_structure_get_name_id (data) == sub_latency_probe_id) {
       const GValue *value;
       gchar *element_id = g_strdup_printf ("%p", peer_parent);
-      gchar *pad_name = gst_pad_get_name (peer_pad);
+      gchar *pad_name = peer_pad ? gst_pad_get_name (peer_pad) : NULL;
       const gchar *value_element_id, *value_pad_name;
 
       /* Get the element id, element name and pad name from data */
@@ -428,7 +460,7 @@ do_push_event_pre (GstTracer * self, guint64 ts, GstPad * pad, GstEvent * ev)
       value_pad_name = g_value_get_string (value);
 
       if (!g_str_equal (value_element_id, element_id) ||
-          !g_str_equal (value_pad_name, pad_name)) {
+          g_strcmp0 (value_pad_name, pad_name) != 0) {
         GST_DEBUG ("%s_%s: Storing sub-latency event",
             GST_DEBUG_PAD_NAME (pad));
         g_object_set_qdata_full ((GObject *) pad, sub_latency_probe_id,
@@ -438,7 +470,13 @@ do_push_event_pre (GstTracer * self, guint64 ts, GstPad * pad, GstEvent * ev)
       g_free (pad_name);
       g_free (element_id);
     }
+    if (peer_pad)
+      gst_object_unref (peer_pad);
+    if (peer_parent)
+      gst_object_unref (peer_parent);
   }
+  if (parent)
+    gst_object_unref (parent);
 }
 
 static void
@@ -453,7 +491,16 @@ do_query_post (GstLatencyTracer * tracer, GstClockTime ts, GstPad * pad,
     gchar *element_name, *element_id;
     struct LatencyQueryTableValue *value;
     GstElement *element = get_real_pad_parent (pad);
-    GstElement *peer_element = get_real_pad_parent (GST_PAD_PEER (pad));
+    GstPad *peer_pad = gst_pad_get_peer (pad);
+    GstElement *peer_element = get_real_pad_parent (peer_pad);
+
+    /* If something is being removed/unlinked, cleanup the stack so we can
+     * ignore this query in the trace. */
+    if (!element || !peer_element || !peer_pad) {
+      while ((value = local_latency_query_stack_pop ()))
+        latency_query_table_value_destroy (value);
+      return;
+    }
 
     /* Parse the query */
     gst_query_parse_latency (query, &live, &min, &max);
@@ -463,8 +510,11 @@ do_query_post (GstLatencyTracer * tracer, GstClockTime ts, GstPad * pad,
     while (value && value->peer_element == element) {
       min_prev = MAX (value->min, min_prev);
       max_prev = MAX (value->max, max_prev);
+      latency_query_table_value_destroy (value);
       value = local_latency_query_stack_pop ();
     }
+    if (value)
+      latency_query_table_value_destroy (value);
 
     /* Push to stack */
     value = g_new0 (struct LatencyQueryTableValue, 1);
@@ -485,6 +535,10 @@ do_query_post (GstLatencyTracer * tracer, GstClockTime ts, GstPad * pad,
     /* Clean up */
     g_free (element_name);
     g_free (element_id);
+
+    gst_object_unref (peer_pad);
+    gst_object_unref (peer_element);
+    gst_object_unref (element);
   }
 }
 
@@ -506,9 +560,15 @@ gst_latency_tracer_constructed (GObject * object)
   params_struct = gst_structure_from_string (tmp, NULL);
   g_free (tmp);
 
-  /* Read the flags if available */
   if (params_struct) {
-    const gchar *flags = gst_structure_get_string (params_struct, "flags");
+    const gchar *name, *flags;
+    /* Set the name if assigned */
+    name = gst_structure_get_string (params_struct, "name");
+    if (name)
+      gst_object_set_name (GST_OBJECT (self), name);
+
+    /* Read the flags if available */
+    flags = gst_structure_get_string (params_struct, "flags");
 
     self->flags = 0;
 
index f95b7c7..e05bb47 100644 (file)
@@ -1,5 +1,6 @@
 /* GStreamer
  * Copyright (C) 2016 Collabora Ltd. <guillaume.desmottes@collabora.co.uk>
+ * Copyright (C) 2019 Nirbheek Chauhan <nirbheek@centricular.com>
  *
  * gstleaks.c: tracing module detecting object leaks
  *
  * Boston, MA 02110-1301, USA.
  */
 /**
- * SECTION:element-leakstracer
+ * SECTION:tracer-leaks
  * @short_description: detect GstObject and GstMiniObject leaks
  *
- * A tracing module tracking the lifetime of objects by logging those still
- * alive when program is exiting and raising a warning.
- * The type of objects tracked can be filtered using the parameters of the
- * tracer, for example: GST_TRACERS=leaks(filters="GstEvent,GstMessage",stack-traces-flags=full)
+ * This tracing module tracks the lifetimes of #GstObject and #GstMiniObject
+ * objects and prints a list of leaks to the debug log under `GST_TRACER:7` when
+ * gst_deinit() is called, and also prints a g_warning().
+ *
+ * Starting with GStreamer 1.18, you can also use action signals on the tracer
+ * object to fetch leak information. Use gst_tracing_get_active_tracers() to
+ * get a list of all active tracers and find the right one by name.
+ *
+ * You can activate this tracer in the usual way by adding the string 'leaks'
+ * to the environment variable `GST_TRACERS`. Such as: `GST_TRACERS=leaks`
+ *
+ * Note that the values are separated by semicolon (`;`), such as:
+ * `GST_TRACERS=leaks;latency`, and multiple instances of the same tracer can be
+ * active at the same time.
+ *
+ * Parameters can also be passed to each tracer. The leaks tracer currently
+ * accepts five params:
+ * 1. filters: (string) to filter which objects to record
+ * 2. check-refs: (boolean) whether to record every location where a leaked
+ *    object was reffed and unreffed
+ * 3. stack-traces-flags: (string) full or none; see: #GstStackTraceFlags
+ * 4. name: (string) set a name for the tracer object itself
+ * 5. log-leaks-on-deinit: (boolean) whether to report all leaks on
+ *    gst_deinit() by printing them in the debug log; "true" by default
+ *
+ * Examples:
+ * ```
+ * GST_TRACERS='leaks(filters="GstEvent,GstMessage",stack-traces-flags=none)'
+ * ```
+ * ```
+ * GST_TRACERS='leaks(filters="GstBuffer",stack-traces-flags=full,check-refs=true);leaks(name=all-leaks)'
+ * ```
  */
 
 #ifdef HAVE_CONFIG_H
 #include "gstleaks.h"
 
 #ifdef G_OS_UNIX
-#include <signal.h>
+#include <glib-unix.h>
+#include <pthread.h>
 #endif /* G_OS_UNIX */
 
 GST_DEBUG_CATEGORY_STATIC (gst_leaks_debug);
 #define GST_CAT_DEFAULT gst_leaks_debug
 
+enum
+{
+  /* actions */
+  SIGNAL_GET_LIVE_OBJECTS,
+  SIGNAL_LOG_LIVE_OBJECTS,
+  SIGNAL_ACTIVITY_START_TRACKING,
+  SIGNAL_ACTIVITY_GET_CHECKPOINT,
+  SIGNAL_ACTIVITY_LOG_CHECKPOINT,
+  SIGNAL_ACTIVITY_STOP_TRACKING,
+
+  LAST_SIGNAL
+};
+
+#define DEFAULT_LOG_LEAKS TRUE  /* for backwards-compat */
+
 #define _do_init \
     GST_DEBUG_CATEGORY_INIT (gst_leaks_debug, "leaks", 0, "leaks tracer");
 #define gst_leaks_tracer_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstLeaksTracer, gst_leaks_tracer,
     GST_TYPE_TRACER, _do_init);
 
+static GstStructure *gst_leaks_tracer_get_live_objects (GstLeaksTracer * self);
+static void gst_leaks_tracer_log_live_objects (GstLeaksTracer * self);
+static void gst_leaks_tracer_activity_start_tracking (GstLeaksTracer * self);
+static GstStructure *gst_leaks_tracer_activity_get_checkpoint (GstLeaksTracer *
+    self);
+static void gst_leaks_tracer_activity_log_checkpoint (GstLeaksTracer * self);
+static void gst_leaks_tracer_activity_stop_tracking (GstLeaksTracer * self);
+
+#ifdef G_OS_UNIX
+static void gst_leaks_tracer_setup_signals (GstLeaksTracer * leaks);
+static void gst_leaks_tracer_cleanup_signals (GstLeaksTracer * leaks);
+#endif
+
 static GstTracerRecord *tr_alive;
 static GstTracerRecord *tr_refings;
-#ifdef G_OS_UNIX
 static GstTracerRecord *tr_added = NULL;
 static GstTracerRecord *tr_removed = NULL;
-#endif /* G_OS_UNIX */
 static GQueue instances = G_QUEUE_INIT;
+static guint gst_leaks_tracer_signals[LAST_SIGNAL] = { 0 };
+
+G_LOCK_DEFINE_STATIC (instances);
 
 typedef struct
 {
@@ -102,7 +161,7 @@ set_print_stack_trace_from_string (GstLeaksTracer * self, const gchar * str)
   if (g_strcmp0 (str, "full") == 0)
     self->trace_flags = GST_STACK_TRACE_SHOW_FULL;
   else
-    self->trace_flags = 0;
+    self->trace_flags = GST_STACK_TRACE_SHOW_NONE;
 }
 
 static void
@@ -158,11 +217,18 @@ set_filters (GstLeaksTracer * self, const gchar * filters)
 static void
 set_params_from_structure (GstLeaksTracer * self, GstStructure * params)
 {
-  const gchar *filters = gst_structure_get_string (params, "filters");
+  const gchar *filters, *name;
 
+  filters = gst_structure_get_string (params, "filters");
   if (filters)
     set_filters (self, filters);
+
+  name = gst_structure_get_string (params, "name");
+  if (name)
+    gst_object_set_name (GST_OBJECT (self), name);
+
   gst_structure_get_boolean (params, "check-refs", &self->check_refs);
+  gst_structure_get_boolean (params, "log-leaks-on-deinit", &self->log_leaks);
 }
 
 static void
@@ -241,7 +307,6 @@ should_handle_object_type (GstLeaksTracer * self, GType object_type)
   return FALSE;
 }
 
-#ifdef G_OS_UNIX
 /* The object may be destroyed when we log it using the checkpointing system so
  * we have to save its type name */
 typedef struct
@@ -250,17 +315,24 @@ typedef struct
   const gchar *type_name;
 } ObjectLog;
 
+static inline gboolean
+object_is_gst_mini_object (gpointer obj)
+{
+  return (G_TYPE_IS_DERIVED (GST_MINI_OBJECT_TYPE (obj)) &&
+      G_TYPE_FUNDAMENTAL (GST_MINI_OBJECT_TYPE (obj)) == G_TYPE_BOXED);
+}
+
 static ObjectLog *
 object_log_new (gpointer obj)
 {
-  ObjectLog *o = g_slice_new (ObjectLog);
+  ObjectLog *o = g_new (ObjectLog, 1);
 
   o->object = obj;
 
-  if (G_IS_OBJECT (obj))
-    o->type_name = G_OBJECT_TYPE_NAME (obj);
-  else
+  if (object_is_gst_mini_object (obj))
     o->type_name = g_type_name (GST_MINI_OBJECT_TYPE (obj));
+  else
+    o->type_name = G_OBJECT_TYPE_NAME (obj);
 
   return o;
 }
@@ -268,9 +340,8 @@ object_log_new (gpointer obj)
 static void
 object_log_free (ObjectLog * obj)
 {
-  g_slice_free (ObjectLog, obj);
+  g_free (obj);
 }
-#endif /* G_OS_UNIX */
 
 static void
 handle_object_destroyed (GstLeaksTracer * self, gpointer object)
@@ -284,10 +355,8 @@ handle_object_destroyed (GstLeaksTracer * self, gpointer object)
   }
 
   g_hash_table_remove (self->objects, object);
-#ifdef G_OS_UNIX
   if (self->removed)
     g_hash_table_add (self->removed, object_log_new (object));
-#endif /* G_OS_UNIX */
 out:
   GST_OBJECT_UNLOCK (self);
 }
@@ -331,10 +400,8 @@ handle_object_created (GstLeaksTracer * self, gpointer object, GType type,
 
   g_hash_table_insert (self->objects, object, infos);
 
-#ifdef G_OS_UNIX
   if (self->added)
     g_hash_table_add (self->added, object_log_new (object));
-#endif /* G_OS_UNIX */
   GST_OBJECT_UNLOCK (self);
 }
 
@@ -361,8 +428,8 @@ object_created_cb (GstTracer * tracer, GstClockTime ts, GstObject * object)
 }
 
 static void
-handle_object_reffed (GstLeaksTracer * self, gpointer object, gint new_refcount,
-    gboolean reffed, GstClockTime ts)
+handle_object_reffed (GstLeaksTracer * self, gpointer object, GType type,
+    gint new_refcount, gboolean reffed, GstClockTime ts)
 {
   ObjectRefingInfos *infos;
   ObjectRefingInfo *refinfo;
@@ -370,6 +437,9 @@ handle_object_reffed (GstLeaksTracer * self, gpointer object, gint new_refcount,
   if (!self->check_refs)
     return;
 
+  if (!should_handle_object_type (self, type))
+    return;
+
   GST_OBJECT_LOCK (self);
   infos = g_hash_table_lookup (self->objects, object);
   if (!infos)
@@ -394,7 +464,8 @@ object_reffed_cb (GstTracer * tracer, GstClockTime ts, GstObject * object,
 {
   GstLeaksTracer *self = GST_LEAKS_TRACER_CAST (tracer);
 
-  handle_object_reffed (self, object, new_refcount, TRUE, ts);
+  handle_object_reffed (self, object, G_OBJECT_TYPE (object), new_refcount,
+      TRUE, ts);
 }
 
 static void
@@ -403,7 +474,8 @@ object_unreffed_cb (GstTracer * tracer, GstClockTime ts, GstObject * object,
 {
   GstLeaksTracer *self = GST_LEAKS_TRACER_CAST (tracer);
 
-  handle_object_reffed (self, object, new_refcount, FALSE, ts);
+  handle_object_reffed (self, object, G_OBJECT_TYPE (object), new_refcount,
+      FALSE, ts);
 }
 
 static void
@@ -412,7 +484,8 @@ mini_object_reffed_cb (GstTracer * tracer, GstClockTime ts,
 {
   GstLeaksTracer *self = GST_LEAKS_TRACER_CAST (tracer);
 
-  handle_object_reffed (self, object, new_refcount, TRUE, ts);
+  handle_object_reffed (self, object, GST_MINI_OBJECT_TYPE (object),
+      new_refcount, TRUE, ts);
 }
 
 static void
@@ -421,16 +494,28 @@ mini_object_unreffed_cb (GstTracer * tracer, GstClockTime ts,
 {
   GstLeaksTracer *self = GST_LEAKS_TRACER_CAST (tracer);
 
-  handle_object_reffed (self, object, new_refcount, FALSE, ts);
+  handle_object_reffed (self, object, GST_MINI_OBJECT_TYPE (object),
+      new_refcount, FALSE, ts);
 }
 
 static void
 gst_leaks_tracer_init (GstLeaksTracer * self)
 {
+  self->log_leaks = DEFAULT_LOG_LEAKS;
   self->objects = g_hash_table_new_full (NULL, NULL, NULL,
       (GDestroyNotify) object_refing_infos_free);
 
+  if (g_getenv ("GST_LEAKS_TRACER_SIG")) {
+#ifdef G_OS_UNIX
+    gst_leaks_tracer_setup_signals (self);
+#else
+    g_warning ("System doesn't support POSIX signals");
+#endif /* G_OS_UNIX */
+  }
+
+  G_LOCK (instances);
   g_queue_push_tail (&instances, self);
+  G_UNLOCK (instances);
 }
 
 static void
@@ -467,7 +552,7 @@ gst_leaks_tracer_constructed (GObject * object)
 typedef struct
 {
   gpointer obj;
-  const gchar *type_name;
+  GType type;
   guint ref_count;
   gchar *desc;
   ObjectRefingInfos *infos;
@@ -478,10 +563,10 @@ typedef struct
 static Leak *
 leak_new (gpointer obj, GType type, guint ref_count, ObjectRefingInfos * infos)
 {
-  Leak *leak = g_slice_new (Leak);
+  Leak *leak = g_new (Leak, 1);
 
   leak->obj = obj;
-  leak->type_name = g_type_name (type);
+  leak->type = type;
   leak->ref_count = ref_count;
   leak->desc = gst_info_strdup_printf ("%" GST_PTR_FORMAT, obj);
   leak->infos = infos;
@@ -493,7 +578,7 @@ static void
 leak_free (Leak * leak)
 {
   g_free (leak->desc);
-  g_slice_free (Leak, leak);
+  g_free (leak);
 }
 
 static gint
@@ -501,7 +586,7 @@ sort_leaks (gconstpointer _a, gconstpointer _b)
 {
   const Leak *a = _a, *b = _b;
 
-  return g_strcmp0 (a->type_name, b->type_name);
+  return g_strcmp0 (g_type_name (a->type), g_type_name (b->type));
 }
 
 static GList *
@@ -516,18 +601,18 @@ create_leaks_list (GstLeaksTracer * self)
     GType type;
     guint ref_count;
 
-    if (GST_IS_OBJECT (obj)) {
-      if (GST_OBJECT_FLAG_IS_SET (obj, GST_OBJECT_FLAG_MAY_BE_LEAKED))
-        continue;
-
-      type = G_OBJECT_TYPE (obj);
-      ref_count = ((GObject *) obj)->ref_count;
-    } else {
+    if (object_is_gst_mini_object (obj)) {
       if (GST_MINI_OBJECT_FLAG_IS_SET (obj, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED))
         continue;
 
       type = GST_MINI_OBJECT_TYPE (obj);
       ref_count = ((GstMiniObject *) obj)->refcount;
+    } else {
+      if (GST_OBJECT_FLAG_IS_SET (obj, GST_OBJECT_FLAG_MAY_BE_LEAKED))
+        continue;
+
+      type = G_OBJECT_TYPE (obj);
+      ref_count = ((GObject *) obj)->ref_count;
     }
 
     l = g_list_prepend (l, leak_new (obj, type, ref_count, infos));
@@ -537,47 +622,102 @@ create_leaks_list (GstLeaksTracer * self)
    * easier to read */
   l = g_list_sort (l, sort_leaks);
 
-  return l;
+  /* Reverse list to sort objects by creation time; this is needed because we
+   * prepended objects into this list earlier, and because g_list_sort() above
+   * is stable so the creation order is preserved when sorting by type name. */
+  return g_list_reverse (l);
+}
+
+static void
+process_leak (Leak * leak, GValue * ret_leaks)
+{
+  GstStructure *r, *s = NULL;
+  GList *ref;
+  GValue refings = G_VALUE_INIT;
+
+  if (!ret_leaks) {
+    /* log to the debug log */
+    gst_tracer_record_log (tr_alive, g_type_name (leak->type), leak->obj,
+        leak->desc, leak->ref_count,
+        leak->infos->creation_trace ? leak->infos->creation_trace : "");
+  } else {
+    GValue s_value = G_VALUE_INIT;
+    GValue obj_value = G_VALUE_INIT;
+    /* for leaked objects, we take ownership of the object instead of
+     * reffing ("collecting") it to avoid deadlocks */
+    g_value_init (&obj_value, leak->type);
+    if (object_is_gst_mini_object (leak->obj))
+      g_value_take_boxed (&obj_value, leak->obj);
+    else
+      g_value_take_object (&obj_value, leak->obj);
+    s = gst_structure_new_empty ("object-alive");
+    gst_structure_take_value (s, "object", &obj_value);
+    gst_structure_set (s, "ref-count", G_TYPE_UINT, leak->ref_count,
+        "trace", G_TYPE_STRING, leak->infos->creation_trace, NULL);
+    /* avoid copy of structure */
+    g_value_init (&s_value, GST_TYPE_STRUCTURE);
+    g_value_take_boxed (&s_value, s);
+    gst_value_list_append_and_take_value (ret_leaks, &s_value);
+  }
+
+  /* store refinfo if available */
+  if (leak->infos->refing_infos)
+    g_value_init (&refings, GST_TYPE_LIST);
+
+  /* iterate the list from last to first to correct the order */
+  for (ref = g_list_last (leak->infos->refing_infos); ref; ref = ref->prev) {
+    ObjectRefingInfo *refinfo = (ObjectRefingInfo *) ref->data;
+
+    if (!ret_leaks) {
+      /* log to the debug log */
+      gst_tracer_record_log (tr_refings, refinfo->ts, g_type_name (leak->type),
+          leak->obj, refinfo->reffed ? "reffed" : "unreffed",
+          refinfo->new_refcount, refinfo->trace ? refinfo->trace : "");
+    } else {
+      GValue r_value = G_VALUE_INIT;
+      r = gst_structure_new_empty ("object-refings");
+      gst_structure_set (r, "ts", GST_TYPE_CLOCK_TIME, refinfo->ts,
+          "desc", G_TYPE_STRING, refinfo->reffed ? "reffed" : "unreffed",
+          "ref-count", G_TYPE_UINT, refinfo->new_refcount,
+          "trace", G_TYPE_STRING, refinfo->trace, NULL);
+      /* avoid copy of structure */
+      g_value_init (&r_value, GST_TYPE_STRUCTURE);
+      g_value_take_boxed (&r_value, r);
+      gst_value_list_append_and_take_value (&refings, &r_value);
+    }
+  }
+
+  if (ret_leaks && leak->infos->refing_infos)
+    gst_structure_take_value (s, "ref-infos", &refings);
 }
 
-/* Return TRUE if at least one leaked object has been logged */
+/* Return TRUE if at least one leaked object was found */
 static gboolean
-log_leaked (GstLeaksTracer * self)
+process_leaks (GstLeaksTracer * self, GValue * ret_leaks)
 {
-  GList *ref, *leaks, *l;
+  GList *leaks, *l;
   gboolean ret = FALSE;
 
-  GST_TRACE_OBJECT (self, "start listing currently alive objects");
+  if (!ret_leaks)
+    GST_TRACE_OBJECT (self, "start listing currently alive objects");
 
   leaks = create_leaks_list (self);
   if (!leaks) {
-    GST_TRACE_OBJECT (self, "No objects alive currently");
+    if (!ret_leaks)
+      GST_TRACE_OBJECT (self, "No objects alive currently");
     goto done;
   }
 
-  for (l = leaks; l != NULL; l = g_list_next (l)) {
-    Leak *leak = l->data;
-
-    gst_tracer_record_log (tr_alive, leak->type_name, leak->obj, leak->desc,
-        leak->ref_count,
-        leak->infos->creation_trace ? leak->infos->creation_trace : "");
-
-    leak->infos->refing_infos = g_list_reverse (leak->infos->refing_infos);
-    for (ref = leak->infos->refing_infos; ref; ref = ref->next) {
-      ObjectRefingInfo *refinfo = (ObjectRefingInfo *) ref->data;
-
-      gst_tracer_record_log (tr_refings, refinfo->ts, leak->type_name,
-          leak->obj, refinfo->reffed ? "reffed" : "unreffed",
-          refinfo->new_refcount, refinfo->trace ? refinfo->trace : "");
-    }
-  }
+  for (l = leaks; l; l = l->next)
+    process_leak (l->data, ret_leaks);
 
   g_list_free_full (leaks, (GDestroyNotify) leak_free);
 
   ret = TRUE;
 
 done:
-  GST_TRACE_OBJECT (self, "done listing currently alive objects");
+  if (!ret_leaks)
+    GST_TRACE_OBJECT (self, "done listing currently alive objects");
 
   return ret;
 }
@@ -586,24 +726,27 @@ static void
 gst_leaks_tracer_finalize (GObject * object)
 {
   GstLeaksTracer *self = GST_LEAKS_TRACER (object);
-  gboolean leaks;
+  gboolean leaks = FALSE;
   GHashTableIter iter;
   gpointer obj;
 
+  GST_DEBUG_OBJECT (self, "destroying tracer, checking for leaks");
+
   self->done = TRUE;
 
   /* Tracers are destroyed as part of gst_deinit() so now is a good time to
    * report all the objects which are still alive. */
-  leaks = log_leaked (self);
+  if (self->log_leaks)
+    leaks = process_leaks (self, NULL);
 
   /* Remove weak references */
   g_hash_table_iter_init (&iter, self->objects);
   while (g_hash_table_iter_next (&iter, &obj, NULL)) {
-    if (GST_IS_OBJECT (obj))
-      g_object_weak_unref (obj, object_weak_cb, self);
-    else
+    if (object_is_gst_mini_object (obj))
       gst_mini_object_weak_unref (GST_MINI_OBJECT_CAST (obj),
           mini_object_weak_cb, self);
+    else
+      g_object_weak_unref (obj, object_weak_cb, self);
   }
 
   g_clear_pointer (&self->objects, g_hash_table_unref);
@@ -613,10 +756,16 @@ gst_leaks_tracer_finalize (GObject * object)
   g_clear_pointer (&self->removed, g_hash_table_unref);
   g_clear_pointer (&self->unhandled_filter, g_hash_table_unref);
 
+  G_LOCK (instances);
   g_queue_remove (&instances, self);
+  G_UNLOCK (instances);
+
+#ifdef G_OS_UNIX
+  gst_leaks_tracer_cleanup_signals (self);
+#endif
 
   if (leaks)
-    g_warning ("Leaks detected");
+    g_warning ("Leaks detected and logged under GST_DEBUG=GST_TRACER:7");
 
   ((GObjectClass *) gst_leaks_tracer_parent_class)->finalize (object);
 }
@@ -624,120 +773,322 @@ gst_leaks_tracer_finalize (GObject * object)
 #define RECORD_FIELD_TYPE_TS \
     "ts", GST_TYPE_STRUCTURE, gst_structure_new ("value", \
         "type", G_TYPE_GTYPE, GST_TYPE_CLOCK_TIME, \
-        "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PROCESS, \
         NULL)
 #define RECORD_FIELD_TYPE_NAME \
     "type-name", GST_TYPE_STRUCTURE, gst_structure_new ("value", \
         "type", G_TYPE_GTYPE, G_TYPE_STRING, \
-        "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PROCESS, \
         NULL)
 #define RECORD_FIELD_ADDRESS \
     "address", GST_TYPE_STRUCTURE, gst_structure_new ("value", \
         "type", G_TYPE_GTYPE, G_TYPE_POINTER, \
-        "related-to", GST_TYPE_TRACER_VALUE_SCOPE, \
-        GST_TRACER_VALUE_SCOPE_PROCESS, \
         NULL)
 #define RECORD_FIELD_DESC \
     "description", GST_TYPE_STRUCTURE, gst_structure_new ("value", \
         "type", G_TYPE_GTYPE, G_TYPE_STRING, \
-        "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PROCESS, \
         NULL)
 #define RECORD_FIELD_REF_COUNT \
     "ref-count", GST_TYPE_STRUCTURE, gst_structure_new ("value", \
         "type", G_TYPE_GTYPE, G_TYPE_UINT, \
-        "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PROCESS, \
         NULL)
 #define RECORD_FIELD_TRACE \
     "trace", GST_TYPE_STRUCTURE, gst_structure_new ("value", \
         "type", G_TYPE_GTYPE, G_TYPE_STRING, \
-        "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PROCESS, \
         NULL)
 
 #ifdef G_OS_UNIX
+static gboolean
+sig_usr1_handler (gpointer data)
+{
+  G_LOCK (instances);
+  g_queue_foreach (&instances, (GFunc) gst_leaks_tracer_log_live_objects, NULL);
+  G_UNLOCK (instances);
+
+  return G_SOURCE_CONTINUE;
+}
+
 static void
-sig_usr1_handler_foreach (gpointer data, gpointer user_data)
+sig_usr2_handler_foreach (gpointer data, gpointer user_data)
 {
   GstLeaksTracer *tracer = data;
 
-  GST_OBJECT_LOCK (tracer);
-  log_leaked (tracer);
-  GST_OBJECT_UNLOCK (tracer);
+  if (!tracer->added) {
+    GST_TRACE_OBJECT (tracer, "First checkpoint, start tracking objects");
+    gst_leaks_tracer_activity_start_tracking (tracer);
+  } else {
+    gst_leaks_tracer_activity_log_checkpoint (tracer);
+  }
+}
+
+static gboolean
+sig_usr2_handler (gpointer data)
+{
+  G_LOCK (instances);
+  g_queue_foreach (&instances, sig_usr2_handler_foreach, NULL);
+  G_UNLOCK (instances);
+
+  return G_SOURCE_CONTINUE;
+}
+
+struct signal_thread_data
+{
+  GMutex lock;
+  GCond cond;
+  gboolean ready;
+};
+
+static GMainLoop *signal_loop;  /* NULL */
+static GThread *signal_thread;  /* NULL */
+static gint signal_thread_users;        /* 0 */
+G_LOCK_DEFINE_STATIC (signal_thread);
+
+static gboolean
+unlock_mutex (gpointer data)
+{
+  g_mutex_unlock ((GMutex *) data);
+
+  return G_SOURCE_REMOVE;
+}
+
+static gpointer
+gst_leaks_tracer_signal_thread (struct signal_thread_data *data)
+{
+  static GMainContext *signal_ctx;
+  GSource *source1, *source2, *unlock_source;
+
+  signal_ctx = g_main_context_new ();
+  signal_loop = g_main_loop_new (signal_ctx, FALSE);
+
+  unlock_source = g_idle_source_new ();
+  g_source_set_callback (unlock_source, unlock_mutex, &data->lock, NULL);
+  g_source_attach (unlock_source, signal_ctx);
+
+  source1 = g_unix_signal_source_new (SIGUSR1);
+  g_source_set_callback (source1, sig_usr1_handler, NULL, NULL);
+  g_source_attach (source1, signal_ctx);
+
+  source2 = g_unix_signal_source_new (SIGUSR2);
+  g_source_set_callback (source2, sig_usr2_handler, NULL, NULL);
+  g_source_attach (source2, signal_ctx);
+
+  g_mutex_lock (&data->lock);
+  data->ready = TRUE;
+  g_cond_broadcast (&data->cond);
+
+  g_main_loop_run (signal_loop);
+
+  g_source_destroy (source1);
+  g_source_destroy (source2);
+  g_main_loop_unref (signal_loop);
+  signal_loop = NULL;
+  g_main_context_unref (signal_ctx);
+  signal_ctx = NULL;
+
+  return NULL;
 }
 
 static void
-sig_usr1_handler (G_GNUC_UNUSED int signal)
+atfork_prepare (void)
 {
-  g_queue_foreach (&instances, sig_usr1_handler_foreach, NULL);
+  G_LOCK (signal_thread);
 }
 
 static void
-log_checkpoint (GHashTable * hash, GstTracerRecord * record)
+atfork_parent (void)
 {
-  GHashTableIter iter;
-  gpointer o;
+  G_UNLOCK (signal_thread);
+}
 
-  g_hash_table_iter_init (&iter, hash);
-  while (g_hash_table_iter_next (&iter, &o, NULL)) {
-    ObjectLog *obj = o;
+static void
+atfork_child (void)
+{
+  signal_thread_users = 0;
+  signal_thread = NULL;
+  G_UNLOCK (signal_thread);
+}
+
+static void
+gst_leaks_tracer_setup_signals (GstLeaksTracer * leaks)
+{
+  struct signal_thread_data data;
+
+  G_LOCK (signal_thread);
+  signal_thread_users++;
+  if (signal_thread_users == 1) {
+    gint res;
+
+    GST_INFO_OBJECT (leaks, "Setting up signal handling");
+
+    /* If application is forked, the child process won't inherit the extra thread.
+     * As a result we need to reset the child process thread state accordingly.
+     * This is typically needed when running tests as libcheck fork the tests.
+     *
+     * See https://pubs.opengroup.org/onlinepubs/007904975/functions/pthread_atfork.html
+     * for details. */
+    res = pthread_atfork (atfork_prepare, atfork_parent, atfork_child);
+    if (!res) {
+      GST_WARNING_OBJECT (leaks, "pthread_atfork() failed (%d)", res);
+    }
+
+    data.ready = FALSE;
+    g_mutex_init (&data.lock);
+    g_cond_init (&data.cond);
+    signal_thread = g_thread_new ("gstleak-signal",
+        (GThreadFunc) gst_leaks_tracer_signal_thread, &data);
 
-    gst_tracer_record_log (record, obj->type_name, obj->object);
+    g_mutex_lock (&data.lock);
+    while (!data.ready)
+      g_cond_wait (&data.cond, &data.lock);
+    g_mutex_unlock (&data.lock);
+
+    g_mutex_clear (&data.lock);
+    g_cond_clear (&data.cond);
   }
+  G_UNLOCK (signal_thread);
 }
 
 static void
-do_checkpoint (GstLeaksTracer * self)
+gst_leaks_tracer_cleanup_signals (GstLeaksTracer * leaks)
 {
-  GST_TRACE_OBJECT (self, "listing objects created since last checkpoint");
-  log_checkpoint (self->added, tr_added);
-  GST_TRACE_OBJECT (self, "listing objects removed since last checkpoint");
-  log_checkpoint (self->removed, tr_removed);
+  G_LOCK (signal_thread);
+  signal_thread_users--;
+  if (signal_thread_users == 0) {
+    GST_INFO_OBJECT (leaks, "Cleaning up signal handling");
+    g_main_loop_quit (signal_loop);
+    g_thread_join (signal_thread);
+    signal_thread = NULL;
+    gst_object_unref (tr_added);
+    tr_added = NULL;
+    gst_object_unref (tr_removed);
+    tr_removed = NULL;
+  }
+  G_UNLOCK (signal_thread);
+}
 
-  g_hash_table_remove_all (self->added);
-  g_hash_table_remove_all (self->removed);
+#else
+#define setup_signals() g_warning ("System doesn't support POSIX signals");
+#endif /* G_OS_UNIX */
+
+static GstStructure *
+gst_leaks_tracer_get_live_objects (GstLeaksTracer * self)
+{
+  GstStructure *info;
+  GValue live_objects = G_VALUE_INIT;
+
+  g_value_init (&live_objects, GST_TYPE_LIST);
+
+  GST_OBJECT_LOCK (self);
+  process_leaks (self, &live_objects);
+  GST_OBJECT_UNLOCK (self);
+
+  info = gst_structure_new_empty ("live-objects-info");
+  gst_structure_take_value (info, "live-objects-list", &live_objects);
+
+  return info;
 }
 
 static void
-sig_usr2_handler_foreach (gpointer data, gpointer user_data)
+gst_leaks_tracer_log_live_objects (GstLeaksTracer * self)
 {
-  GstLeaksTracer *tracer = data;
+  GST_OBJECT_LOCK (self);
+  process_leaks (self, NULL);
+  GST_OBJECT_UNLOCK (self);
+}
 
-  GST_OBJECT_LOCK (tracer);
+static void
+gst_leaks_tracer_activity_start_tracking (GstLeaksTracer * self)
+{
+  GST_OBJECT_LOCK (self);
+  if (self->added) {
+    GST_ERROR_OBJECT (self, "tracking is already in progress");
+    return;
+  }
 
-  if (!tracer->added) {
-    GST_TRACE_OBJECT (tracer, "First checkpoint, start tracking objects");
+  self->added = g_hash_table_new_full (NULL, NULL,
+      (GDestroyNotify) object_log_free, NULL);
+  self->removed = g_hash_table_new_full (NULL, NULL,
+      (GDestroyNotify) object_log_free, NULL);
+  GST_OBJECT_UNLOCK (self);
+}
 
-    tracer->added = g_hash_table_new_full (NULL, NULL,
-        (GDestroyNotify) object_log_free, NULL);
-    tracer->removed = g_hash_table_new_full (NULL, NULL,
-        (GDestroyNotify) object_log_free, NULL);
-  } else {
-    do_checkpoint (tracer);
+/* When @ret is %NULL, this simply logs the activities */
+static void
+process_checkpoint (GstTracerRecord * record, const gchar * record_type,
+    GHashTable * hash, GValue * ret)
+{
+  GHashTableIter iter;
+  gpointer o;
+
+  g_hash_table_iter_init (&iter, hash);
+  while (g_hash_table_iter_next (&iter, &o, NULL)) {
+    ObjectLog *obj = o;
+
+    if (!ret) {
+      /* log to the debug log */
+      gst_tracer_record_log (record, obj->type_name, obj->object);
+    } else {
+      GValue s_value = G_VALUE_INIT;
+      GValue addr_value = G_VALUE_INIT;
+      gchar *address = g_strdup_printf ("%p", obj->object);
+      GstStructure *s = gst_structure_new_empty (record_type);
+      /* copy type_name because it's owned by @obj */
+      gst_structure_set (s, "type-name", G_TYPE_STRING, obj->type_name, NULL);
+      /* avoid copy of @address */
+      g_value_init (&addr_value, G_TYPE_STRING);
+      g_value_take_string (&addr_value, address);
+      gst_structure_take_value (s, "address", &addr_value);
+      /* avoid copy of the structure */
+      g_value_init (&s_value, GST_TYPE_STRUCTURE);
+      g_value_take_boxed (&s_value, s);
+      gst_value_list_append_and_take_value (ret, &s_value);
+    }
   }
+}
+
+static GstStructure *
+gst_leaks_tracer_activity_get_checkpoint (GstLeaksTracer * self)
+{
+  GValue added = G_VALUE_INIT;
+  GValue removed = G_VALUE_INIT;
+  GstStructure *s = gst_structure_new_empty ("activity-checkpoint");
+
+  g_value_init (&added, GST_TYPE_LIST);
+  g_value_init (&removed, GST_TYPE_LIST);
+
+  GST_OBJECT_LOCK (self);
+  process_checkpoint (tr_added, "objects-created", self->added, &added);
+  process_checkpoint (tr_removed, "objects-removed", self->removed, &removed);
+
+  g_hash_table_remove_all (self->added);
+  g_hash_table_remove_all (self->removed);
+  GST_OBJECT_UNLOCK (self);
+
+  gst_structure_take_value (s, "objects-created-list", &added);
+  gst_structure_take_value (s, "objects-removed-list", &removed);
 
-  GST_OBJECT_UNLOCK (tracer);
+  return s;
 }
 
 static void
-sig_usr2_handler (G_GNUC_UNUSED int signal)
+gst_leaks_tracer_activity_log_checkpoint (GstLeaksTracer * self)
 {
-  g_queue_foreach (&instances, sig_usr2_handler_foreach, NULL);
+  GST_OBJECT_LOCK (self);
+  GST_TRACE_OBJECT (self, "listing objects created since last checkpoint");
+  process_checkpoint (tr_added, NULL, self->added, NULL);
+  GST_TRACE_OBJECT (self, "listing objects removed since last checkpoint");
+  process_checkpoint (tr_removed, NULL, self->removed, NULL);
+  g_hash_table_remove_all (self->added);
+  g_hash_table_remove_all (self->removed);
+  GST_OBJECT_UNLOCK (self);
 }
 
 static void
-setup_signals (void)
+gst_leaks_tracer_activity_stop_tracking (GstLeaksTracer * self)
 {
-  tr_added = gst_tracer_record_new ("object-added.class",
-      RECORD_FIELD_TYPE_NAME, RECORD_FIELD_ADDRESS, NULL);
-  GST_OBJECT_FLAG_SET (tr_added, GST_OBJECT_FLAG_MAY_BE_LEAKED);
-
-  tr_removed = gst_tracer_record_new ("object-removed.class",
-      RECORD_FIELD_TYPE_NAME, RECORD_FIELD_ADDRESS, NULL);
-  GST_OBJECT_FLAG_SET (tr_removed, GST_OBJECT_FLAG_MAY_BE_LEAKED);
-
-  signal (SIGUSR1, sig_usr1_handler);
-  signal (SIGUSR2, sig_usr2_handler);
+  GST_OBJECT_LOCK (self);
+  g_clear_pointer (&self->added, g_hash_table_destroy);
+  g_clear_pointer (&self->removed, g_hash_table_destroy);
+  GST_OBJECT_UNLOCK (self);
 }
-#endif /* G_OS_UNIX */
 
 static void
 gst_leaks_tracer_class_init (GstLeaksTracerClass * klass)
@@ -757,11 +1108,170 @@ gst_leaks_tracer_class_init (GstLeaksTracerClass * klass)
       RECORD_FIELD_DESC, RECORD_FIELD_REF_COUNT, RECORD_FIELD_TRACE, NULL);
   GST_OBJECT_FLAG_SET (tr_alive, GST_OBJECT_FLAG_MAY_BE_LEAKED);
 
-  if (g_getenv ("GST_LEAKS_TRACER_SIG")) {
-#ifdef G_OS_UNIX
-    setup_signals ();
-#else
-    g_warning ("System doesn't support POSIX signals");
-#endif /* G_OS_UNIX */
-  }
+  tr_added = gst_tracer_record_new ("object-added.class",
+      RECORD_FIELD_TYPE_NAME, RECORD_FIELD_ADDRESS, NULL);
+  GST_OBJECT_FLAG_SET (tr_added, GST_OBJECT_FLAG_MAY_BE_LEAKED);
+
+  tr_removed = gst_tracer_record_new ("object-removed.class",
+      RECORD_FIELD_TYPE_NAME, RECORD_FIELD_ADDRESS, NULL);
+  GST_OBJECT_FLAG_SET (tr_removed, GST_OBJECT_FLAG_MAY_BE_LEAKED);
+
+  /**
+   * GstLeaksTracer::get-live-objects:
+   * @leakstracer: the leaks tracer object to emit this signal on
+   *
+   * Returns a #GstStructure containing a #GValue of type #GST_TYPE_LIST which
+   * is a list of #GstStructure objects containing information about the
+   * objects that are still alive, which is useful for detecting leaks. Each
+   * #GstStructure object has the following fields:
+   *
+   * `object`: containing the leaked object itself
+   * `ref-count`: the current reference count of the object
+   * `trace`: the allocation stack trace for the object, only available if the
+   *          `stack-traces-flags` param is set to `full`
+   * `ref-infos`: a #GValue of type #GST_TYPE_LIST which is a list of
+   *             #GstStructure objects containing information about the
+   *             ref/unref history of the object; only available if the
+   *             `check-refs` param is set to `true`
+   *
+   * Each `ref-infos` #GstStructure has the following fields:
+   *
+   * `ts`: the timestamp for the ref/unref
+   * `desc`: either "reffed" or "unreffed"
+   * `ref-count`: the reference count after the ref/unref
+   * `trace`: the stack trace for the ref/unref
+   *
+   * **Notes on usage**: This action signal is supposed to be called at the
+   * end of an application before it exits, or at the end of an execution run
+   * when all streaming has stopped and all pipelines have been freed. It is
+   * assumed that at this point any GStreamer object that is still alive is
+   * leaked, and there are no legitimate owners any more. As such, ownership
+   * of the leaked objects is transferred to you then, assuming no other code
+   * still retrains references to them.
+   *
+   * If that's not the case, and there is code somewhere still holding
+   * a reference, then the application behaviour is undefined after this
+   * function is called, since we will have stolen some other code's valid
+   * reference and when the returned #GstStructure is freed that code will be
+   * holding a reference to an invalid object, which will most likely crash
+   * sooner or later.
+   *
+   * If you don't want to just check for leaks at the end of a program, the
+   * activity checkpoint action signals might be a better fit for your use
+   * case.
+   *
+   * Returns: (transfer full): a newly-allocated #GstStructure
+   *
+   * Since: 1.18
+   */
+  gst_leaks_tracer_signals[SIGNAL_GET_LIVE_OBJECTS] =
+      g_signal_new ("get-live-objects", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstLeaksTracerClass,
+          get_live_objects), NULL, NULL, NULL, GST_TYPE_STRUCTURE, 0,
+      G_TYPE_NONE);
+
+  /**
+   * GstLeaksTracer::log-live-objects:
+   * @leakstracer: the leaks tracer object to emit this signal on
+   *
+   * Logs all objects that are still alive to the debug log in the same format
+   * as the logging during gst_deinit().
+   *
+   * Since: 1.18
+   */
+  gst_leaks_tracer_signals[SIGNAL_LOG_LIVE_OBJECTS] =
+      g_signal_new ("log-live-objects", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstLeaksTracerClass,
+          log_live_objects), NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE);
+
+  /**
+   * GstLeaksTracer:::activity-start-tracking
+   * @leakstracer: the leaks tracer object to emit this signal on
+   *
+   * Start storing information about all objects that are being created or
+   * removed. Call `stop-tracking` to stop.
+   *
+   * NOTE: You do not need to call this to use the *-live-objects action
+   * signals listed above.
+   *
+   * Since: 1.18
+   */
+  gst_leaks_tracer_signals[SIGNAL_ACTIVITY_START_TRACKING] =
+      g_signal_new ("activity-start-tracking", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstLeaksTracerClass,
+          activity_start_tracking), NULL, NULL, NULL, G_TYPE_NONE, 0,
+      G_TYPE_NONE);
+
+  /**
+   * GstLeaksTracer:::activity-get-checkpoint
+   * @leakstracer: the leaks tracer object to emit this signal on
+   *
+   * You must call this after calling `activity-start-tracking` and you should
+   * call `activity-stop-tracking` when you are done tracking.
+   *
+   * Returns a #GstStructure with two fields: `"objects-created-list"` and
+   * `"objects-removed-list"`, each of which is a #GValue of type #GST_TYPE_LIST
+   * containing all objects that were created/removed since the last
+   * checkpoint, or since tracking started if this is the first checkpoint.
+   *
+   * The list elements are in order of creation/removal. Each list element is
+   * a #GValue containing a #GstStructure with the following fields:
+   *
+   * `type-name`: a string representing the type of the object
+   * `address`: a string representing the address of the object; the object
+   *            itself cannot be returned since we don't own it and it may be
+   *            freed at any moment, or it may already have been freed
+   *
+   * Returns: (transfer full): a newly-allocated #GstStructure
+   *
+   * Since: 1.18
+   */
+  gst_leaks_tracer_signals[SIGNAL_ACTIVITY_GET_CHECKPOINT] =
+      g_signal_new ("activity-get-checkpoint", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstLeaksTracerClass,
+          activity_get_checkpoint), NULL, NULL, NULL, GST_TYPE_STRUCTURE, 0,
+      G_TYPE_NONE);
+
+  /**
+   * GstLeaksTracer:::activity-log-checkpoint
+   * @leakstracer: the leaks tracer object to emit this signal on
+   *
+   * You must call this after calling `activity-start-tracking` and you should
+   * call `activity-stop-tracking` when you are done tracking.
+   *
+   * List all objects that were created or removed since the last checkpoint,
+   * or since tracking started if this is the first checkpoint.
+   *
+   * This action signal is equivalent to `activity-get-checkpoint` except that
+   * the checkpoint data will be printed to the debug log under `GST_TRACER:7`.
+   *
+   * Since: 1.18
+   */
+  gst_leaks_tracer_signals[SIGNAL_ACTIVITY_LOG_CHECKPOINT] =
+      g_signal_new ("activity-log-checkpoint", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstLeaksTracerClass,
+          activity_log_checkpoint), NULL, NULL, NULL, G_TYPE_NONE, 0,
+      G_TYPE_NONE);
+
+  /**
+   * GstLeaksTracer:::activity-stop-tracking
+   * @leakstracer: the leaks tracer object to emit this signal on
+   *
+   * Stop tracking all objects that are being created or removed, undoes the
+   * effects of the `start-tracking` signal.
+   *
+   * Since: 1.18
+   */
+  gst_leaks_tracer_signals[SIGNAL_ACTIVITY_STOP_TRACKING] =
+      g_signal_new ("activity-stop-tracking", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstLeaksTracerClass,
+          activity_stop_tracking), NULL, NULL, NULL, G_TYPE_NONE, 0,
+      G_TYPE_NONE);
+
+  klass->get_live_objects = gst_leaks_tracer_get_live_objects;
+  klass->log_live_objects = gst_leaks_tracer_log_live_objects;
+  klass->activity_start_tracking = gst_leaks_tracer_activity_start_tracking;
+  klass->activity_get_checkpoint = gst_leaks_tracer_activity_get_checkpoint;
+  klass->activity_log_checkpoint = gst_leaks_tracer_activity_log_checkpoint;
+  klass->activity_stop_tracking = gst_leaks_tracer_activity_stop_tracking;
 }
index 71277b8..6eaf850 100644 (file)
@@ -69,12 +69,21 @@ struct _GstLeaksTracer {
   gboolean done;
 
   gboolean check_refs;
+  gboolean log_leaks;
 
   GstStackTraceFlags trace_flags;
 };
 
 struct _GstLeaksTracerClass {
   GstTracerClass parent_class;
+
+  /* actions */
+  GstStructure * (*get_live_objects)            (GstLeaksTracer *tracer);
+  void           (*log_live_objects)            (GstLeaksTracer *tracer);
+  void           (*activity_start_tracking)     (GstLeaksTracer *tracer);
+  GstStructure * (*activity_get_checkpoint)     (GstLeaksTracer *tracer);
+  void           (*activity_log_checkpoint)     (GstLeaksTracer *tracer);
+  void           (*activity_stop_tracking)      (GstLeaksTracer *tracer);
 };
 
 G_GNUC_INTERNAL GType gst_leaks_tracer_get_type (void);
index 06f3cdb..9649998 100644 (file)
@@ -19,7 +19,7 @@
  * Boston, MA 02110-1301, USA.
  */
 /**
- * SECTION:element-logtracer
+ * SECTION:tracer-log
  * @short_description: log hook event
  *
  * A tracing module that logs all data from all hooks.
@@ -310,8 +310,37 @@ do_pad_unlink_post (GstTracer * self, guint64 ts, GstPad * src,
 /* tracer class */
 
 static void
+gst_log_tracer_constructed (GObject * object)
+{
+  GstLogTracer *self = GST_LOG_TRACER (object);
+  gchar *params, *tmp;
+  const gchar *name;
+  GstStructure *params_struct = NULL;
+
+  g_object_get (self, "params", &params, NULL);
+
+  if (!params)
+    return;
+
+  tmp = g_strdup_printf ("log,%s", params);
+  params_struct = gst_structure_from_string (tmp, NULL);
+  g_free (tmp);
+  if (!params_struct)
+    return;
+
+  /* Set the name if assigned */
+  name = gst_structure_get_string (params_struct, "name");
+  if (name)
+    gst_object_set_name (GST_OBJECT (self), name);
+  gst_structure_free (params_struct);
+}
+
+static void
 gst_log_tracer_class_init (GstLogTracerClass * klass)
 {
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->constructed = gst_log_tracer_constructed;
 }
 
 static void
index 6817815..9976ddf 100644 (file)
  * Boston, MA 02110-1301, USA.
  */
 /**
- * SECTION:element-rusagetracer
+ * SECTION:tracer-rusage
  * @short_description: log resource usage stats
  *
- * A tracing module that take rusage() snapshots and logs them.
+ * A tracing module that take `rusage()` snapshots and logs them.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -60,11 +60,15 @@ static GstTracerRecord *tr_proc, *tr_thread;
 
 typedef struct
 {
-  /* time spend in this thread */
+  /* time spent in this thread */
   GstClockTime tthread;
   GstTraceValues *tvs_thread;
 } GstThreadStats;
 
+static void free_thread_stats (gpointer data);
+
+static GPrivate thread_stats_key = G_PRIVATE_INIT (free_thread_stats);
+
 /* data helper */
 
 static void
@@ -140,12 +144,13 @@ update_trace_value (GstTraceValues * self, GstClockTime nts,
   return ret;
 }
 
-
 static void
 free_thread_stats (gpointer data)
 {
-  free_trace_values (((GstThreadStats *) data)->tvs_thread);
-  g_slice_free (GstThreadStats, data);
+  GstThreadStats *stats = data;
+
+  free_trace_values (stats->tvs_thread);
+  g_free (stats);
 }
 
 static void
@@ -199,10 +204,10 @@ do_stats (GstTracer * obj, guint64 ts)
 #endif
 #endif
   /* get stats record for current thread */
-  if (!(stats = g_hash_table_lookup (self->threads, thread_id))) {
-    stats = g_slice_new0 (GstThreadStats);
+  if (!(stats = g_private_get (&thread_stats_key))) {
+    stats = g_new0 (GstThreadStats, 1);
     stats->tvs_thread = make_trace_values (GST_SECOND);
-    g_hash_table_insert (self->threads, thread_id, stats);
+    g_private_set (&thread_stats_key, stats);
   }
   stats->tthread = tthread;
 
@@ -257,11 +262,37 @@ do_stats (GstTracer * obj, guint64 ts)
 /* tracer class */
 
 static void
+gst_rusage_tracer_constructed (GObject * object)
+{
+  GstRUsageTracer *self = GST_RUSAGE_TRACER (object);
+  gchar *params, *tmp;
+  const gchar *name;
+  GstStructure *params_struct = NULL;
+
+  g_object_get (self, "params", &params, NULL);
+
+  if (!params)
+    return;
+
+  tmp = g_strdup_printf ("rusage,%s", params);
+  g_free (params);
+  params_struct = gst_structure_from_string (tmp, NULL);
+  g_free (tmp);
+  if (!params_struct)
+    return;
+
+  /* Set the name if assigned */
+  name = gst_structure_get_string (params_struct, "name");
+  if (name)
+    gst_object_set_name (GST_OBJECT (self), name);
+  gst_structure_free (params_struct);
+}
+
+static void
 gst_rusage_tracer_finalize (GObject * obj)
 {
   GstRUsageTracer *self = GST_RUSAGE_TRACER (obj);
 
-  g_hash_table_destroy (self->threads);
   free_trace_values (self->tvs_proc);
 
   G_OBJECT_CLASS (parent_class)->finalize (obj);
@@ -272,6 +303,7 @@ gst_rusage_tracer_class_init (GstRUsageTracerClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
+  gobject_class->constructed = gst_rusage_tracer_constructed;
   gobject_class->finalize = gst_rusage_tracer_finalize;
 
   if ((num_cpus = sysconf (_SC_NPROCESSORS_ONLN)) == -1) {
@@ -371,7 +403,6 @@ gst_rusage_tracer_init (GstRUsageTracer * self)
     gst_tracing_register_hook (tracer, hooks[i], G_CALLBACK (do_stats));
   }
 
-  self->threads = g_hash_table_new_full (NULL, NULL, NULL, free_thread_stats);
   self->tvs_proc = make_trace_values (GST_SECOND);
   self->main_thread_id = g_thread_self ();
 
index b5abbca..fe84aa6 100644 (file)
@@ -62,8 +62,7 @@ typedef struct
 struct _GstRUsageTracer {
   GstTracer     parent;
 
-  /*< private >*/        
-  GHashTable *threads;
+  /*< private >*/
   GstTraceValues *tvs_proc;
 
   /* for ts calibration */
index 2fba4fa..72edd2a 100644 (file)
@@ -19,7 +19,7 @@
  * Boston, MA 02110-1301, USA.
  */
 /**
- * SECTION:element-statstracer
+ * SECTION:tracer-stats
  * @short_description: log event stats
  *
  * A tracing module that builds usage statistic for elements and pads.
@@ -521,8 +521,38 @@ do_query_post (GstStatsTracer * self, guint64 ts, GstPad * this_pad,
 /* tracer class */
 
 static void
+gst_stats_tracer_constructed (GObject * object)
+{
+  GstStatsTracer *self = GST_STATS_TRACER (object);
+  gchar *params, *tmp;
+  const gchar *name;
+  GstStructure *params_struct = NULL;
+
+  g_object_get (self, "params", &params, NULL);
+
+  if (!params)
+    return;
+
+  tmp = g_strdup_printf ("stats,%s", params);
+  params_struct = gst_structure_from_string (tmp, NULL);
+  g_free (tmp);
+  if (!params_struct)
+    return;
+
+  /* Set the name if assigned */
+  name = gst_structure_get_string (params_struct, "name");
+  if (name)
+    gst_object_set_name (GST_OBJECT (self), name);
+  gst_structure_free (params_struct);
+}
+
+static void
 gst_stats_tracer_class_init (GstStatsTracerClass * klass)
 {
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->constructed = gst_stats_tracer_constructed;
+
   /* announce trace formats */
   /* *INDENT-OFF* */
   tr_buffer = gst_tracer_record_new ("buffer.class",
index b03e25a..e5fe5d0 100644 (file)
@@ -29,6 +29,7 @@
 #include "gstrusage.h"
 #include "gststats.h"
 #include "gstleaks.h"
+#include "gstfactories.h"
 
 static gboolean
 plugin_init (GstPlugin * plugin)
@@ -47,6 +48,9 @@ plugin_init (GstPlugin * plugin)
     return FALSE;
   if (!gst_tracer_register (plugin, "leaks", gst_leaks_tracer_get_type ()))
     return FALSE;
+  if (!gst_tracer_register (plugin, "factories",
+          gst_factories_tracer_get_type ()))
+    return FALSE;
   return TRUE;
 }
 
index 26cd3ab..8039c9b 100644 (file)
@@ -1,8 +1,16 @@
+if not tracer_hooks
+  if get_option('coretracers').enabled()
+    error('coretracers plugin enabled but not tracer_hooks')
+  endif
+  subdir_done()
+endif
+
 gst_tracers_sources = [
   'gstlatency.c',
   'gstleaks.c',
   'gststats.c',
   'gsttracers.c',
+  'gstfactories.c'
 ]
 
 if gst_debug
@@ -13,14 +21,15 @@ if cdata.has('HAVE_GETRUSAGE')
   gst_tracers_sources += ['gstrusage.c']
 endif
 
-tracers_args = gst_c_args + ['-DGST_USE_UNSTABLE_API']
+thread_dep = dependency('threads', required : false)
 
 gst_tracers = library('gstcoretracers',
   gst_tracers_sources,
-  c_args : tracers_args,
+  c_args : gst_c_args,
   include_directories : [configinc],
-  dependencies : [gst_dep],
+  dependencies : [gst_dep, thread_dep],
   install : true,
   install_dir : plugins_install_dir,
 )
 pkgconfig.generate(gst_tracers, install_dir : plugins_pkgconfig_install_dir)
+plugins += [gst_tracers]
diff --git a/po/.gitignore b/po/.gitignore
deleted file mode 100644 (file)
index b2b4af5..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-*.gmo
-remove-potcdate.sed
-stamp-po
-POTFILES
-cat-id-tbl.c
-gstreamer-*.pot
-Makefile.in.in
-Makefile.in.in.orig
-Makevars.template
-Rules-quot
-boldquot.sed
-en@boldquot.header
-en@quot.header
-insert-header.sin
-quot.sed
diff --git a/po/Makevars b/po/Makevars
deleted file mode 100644 (file)
index 8f4e7d0..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-# Makefile variables for PO directory in any package using GNU gettext.
-
-# Usually the message domain is the same as the package name.
-DOMAIN = gstreamer-1.0
-
-# These two variables depend on the location of this directory.
-subdir = po
-top_builddir = ..
-
-# These options get passed to xgettext.
-XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
-
-# This is the copyright holder that gets inserted into the header of the
-# $(DOMAIN).pot file.  Set this to the copyright holder of the surrounding
-# package.  (Note that the msgstr strings, extracted from the package's
-# sources, belong to the copyright holder of the package.)  Translators are
-# expected to transfer the copyright for their translations to this person
-# or entity, or to disclaim their copyright.  The empty string stands for
-# the public domain; in this case the translators are expected to disclaim
-# their copyright.
-COPYRIGHT_HOLDER =
-
-# This is the email address or URL to which the translators shall report
-# bugs in the untranslated strings:
-# - Strings which are not entire sentences, see the maintainer guidelines
-#   in the GNU gettext documentation, section 'Preparing Strings'.
-# - Strings which use unclear terms or require additional context to be
-#   understood.
-# - Strings which make invalid assumptions about notation of date, time or
-#   money.
-# - Pluralisation problems.
-# - Incorrect English spelling.
-# - Incorrect formatting.
-# It can be your email address, or a mailing list address where translators
-# can write to without being subscribed, or the URL of a web page through
-# which the translators can contact you.
-MSGID_BUGS_ADDRESS = http://bugzilla.gnome.org/
-
-# This is the list of locale categories, beyond LC_MESSAGES, for which the
-# message catalogs shall be used.  It is usually empty.
-EXTRA_LOCALE_CATEGORIES =
-
-# Avoid line numbers in *.po, but keep them in *.pot.
-MSGMERGE = msgmerge --no-location
-MSGMERGE_UPDATE = msgmerge --no-location --update --backup=off
-MSGFILTER = msgfilter --no-location
-
similarity index 96%
rename from po/POTFILES.in
rename to po/POTFILES
index fe3d9c6..8aa43a0 100644 (file)
@@ -9,7 +9,7 @@ gst/gstregistry.c
 gst/gsttaglist.c
 gst/gsturi.c
 gst/gstutils.c
-gst/parse/grammar.y
+gst/parse/grammar.y.in
 libs/gst/base/gstbasesink.c
 libs/gst/base/gstbasesrc.c
 plugins/elements/gstcapsfilter.c
diff --git a/po/README b/po/README
deleted file mode 100644 (file)
index 6572b9a..0000000
--- a/po/README
+++ /dev/null
@@ -1,30 +0,0 @@
-The idiot's guide to managing this directory
-
-Q: How do I add source files to be translated ? 
-A: - Make sure the source file includes either gst-i18n-lib.h (if it's a part
-     of a library/plugin) or gst-i18n-app.h (if it's an application)
-   - Add the file path, relative to the top of the module, to POTFILES.in
-
-Q: How do I add/mark strings to be translated ?
-A: - Use N_(...) to mark for translation.
-   - Use _(...) to get a translated string
-   - run "make gstreamer-1.0.pot-update" to update the .pot file
-     and check if your new strings got added
-
-Q: How do I add a language ?
-A: - copy gstreamer-1.0.pot to your new language.po
-   - add the language code to LINGUAS
-   - edit the header of this language.po file and make it match one of
-     the existing .po files
-   - translate the strings
-
-Q: How do I update a language ?
-A: - run make language.po-update to update your .po file
-     (replace language with your language code)
-   - edit the .po file, and translate the untranslated strings
-   - run make install from the .po dir (so the updated strings get installed
-     and will be used in the lib/app) and test if the new strings are
-     translated
-     (To check, you need to export LANG=ll_LL.  Make sure you add the last
-      bit; ie. for Dutch you need export LANG=nl_NL)
-   - commit
diff --git a/po/remove-potcdate.sin b/po/remove-potcdate.sin
deleted file mode 100644 (file)
index 2436c49..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-# Sed script that remove the POT-Creation-Date line in the header entry
-# from a POT file.
-#
-# The distinction between the first and the following occurrences of the
-# pattern is achieved by looking at the hold space.
-/^"POT-Creation-Date: .*"$/{
-x
-# Test if the hold space is empty.
-s/P/P/
-ta
-# Yes it was empty. First occurrence. Remove the line.
-g
-d
-bb
-:a
-# The hold space was nonempty. Following occurrences. Do nothing.
-x
-:b
-}
diff --git a/scripts/create-uninstalled-setup.sh b/scripts/create-uninstalled-setup.sh
deleted file mode 100755 (executable)
index 05aa7a1..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-#!/bin/sh
-# ----------------------------------------------------------------------------
-#
-# create-uninstalled-setup.sh
-#
-# Little shell script that creates a fresh GStreamer uninstalled setup in
-# your home directory.
-#
-# This is the legacy uninstalled setup for autotools. There is also the
-# gst-build module which provides the same using the meson build system.
-#
-# ----------------------------------------------------------------------------
-#
-# Copyright (C) 2011-2015 Tim-Philipp Müller <tim centricular net>
-#
-# This script is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
-# Boston, MA 02110-1301, USA.
-#
-# ----------------------------------------------------------------------------
-
-set -e
-
-# set BRANCH to e.g. "1.2" to track the stable 1.2 branch instead of master
-BRANCH="master"
-
-# set to "ssh" if you have a developer account and ssh access
-GIT_ACCESS="anongit"
-
-# extra clone options
-#CLONE_OPTS="--depth=1 --no-single-branch"
-
-# re-use and reference local master branch checkout if one already exists
-# (saves network bandwidth)
-REUSE_EXISTING_MASTER_CHECKOUT="true"
-
-# git modules to clone
-MODULES="gstreamer gst-plugins-base gst-plugins-good gst-plugins-ugly gst-plugins-bad gst-libav"
-
-# note: we use ~/gst because that's what the gst-uninstalled script
-# uses by default, so don't just change that to something else
-UNINSTALLED_ROOT=~/gst
-
-echo "==========================================================================================="
-echo "Creating new GStreamer uninstalled environment for branch $BRANCH in $UNINSTALLED_ROOT ... "
-echo "==========================================================================================="
-
-mkdir -p $UNINSTALLED_ROOT
-mkdir -p $UNINSTALLED_ROOT/$BRANCH
-
-mkdir -p $UNINSTALLED_ROOT/$BRANCH/prefix
-
-
-echo ""
-echo "Checking basic build tools and dependencies are installed..."
-echo ""
-
-if ! pkg-config --version 2>/dev/null >/dev/null; then
-  DEPS_OK="no"
-elif ! pkg-config --exists glib-2.0 orc-0.4 2>/dev/null >/dev/null; then
-  DEPS_OK="no"
-elif ! bison --version 2>/dev/null >/dev/null; then
-  DEPS_OK="no"
-elif ! flex --version 2>/dev/null >/dev/null; then
-  DEPS_OK="no"
-elif ! git --version 2>/dev/null >/dev/null; then
-  DEPS_OK="no"
-else
-  DEPS_OK="yes"
-fi
-
-if test "$DEPS_OK" != "yes"; then
-echo "==========================================================================================="
-echo ""
-echo "  Some very basic build tools or dependencies are missing."
-echo ""
-echo "  Please install the following tools: pkg-config, bison, flex, git"
-echo ""
-echo "  and the following libraries: GLib (libglib2.0-dev or glib2-devel)"
-echo "                           and Orc  (liborc-0.4-dev or orc-devel)"
-#echo "  Please visit"
-#echo ""
-#echo "      http://gstreamer.freedesktop.org/wiki/BuildDependenciesDebianUbuntu"
-#echo ""
-#echo "         or"
-#echo ""
-#echo "      http://gstreamer.freedesktop.org/wiki/Fedora"
-#echo ""
-#echo "  for instructions how to install them on Debian/Ubuntu-based systems."
-echo ""
-echo "==========================================================================================="
-exit 1
-fi
-
-
-cd $UNINSTALLED_ROOT/$BRANCH
-
-for m in $MODULES
-do
-  REF=""
-  if test "$BRANCH" != "master" \
-    -a "x$REUSE_EXISTING_MASTER_CHECKOUT" = "xtrue" \
-    -a -d ../master/$m; then
-      REF="--reference=../master/$m"
-  fi
-
-  if test "$GIT_ACCESS" = "ssh"; then
-    git clone $CLONE_OPTS $REF git@gitlab.freedesktop.org:gstreamer/$m
-  else
-    git clone $CLONE_OPTS $REF https://gitlab.freedesktop.org/gstreamer/$m.git
-  fi
-
-  cd $m
-  if test "$BRANCH" != "master"; then
-    git checkout -b $BRANCH origin/$BRANCH
-  fi
-  git submodule init && git submodule update
-  cd ..
-done
-
-cd $UNINSTALLED_ROOT
-ln -s $BRANCH/gstreamer/scripts/gst-uninstalled gst-$BRANCH
-chmod +x gst-$BRANCH
-
-cd ~
-
-echo "==========================================================================================="
-echo
-echo "Done. Created new GStreamer uninstalled environment for branch $BRANCH in $UNINSTALLED_ROOT"
-echo
-echo "To enter the uninstalled environment do: cd $UNINSTALLED_ROOT; ./gst-$BRANCH"
-echo
-echo "To leave the uninstalled environment do: exit"
-echo
-echo "To check the uninstalled environment do: printenv | grep GST"
-echo "    (loads of output = you're in the uninstalled environment)"
-echo
-echo "==========================================================================================="
-echo
-echo "Now compile all GStreamer modules one by one by first switching into"
-echo "the uninstalled environment and then doing:"
-echo
-echo "    cd <MODULE>; ./autogen.sh; make"
-echo
-echo "First gstreamer, then gst-plugins-base, then the other modules."
-echo "You do not need to do 'make install'"
-echo
-echo "==========================================================================================="
-echo
-echo "If your system GLib is too old, you can install a newer version"
-echo "into --prefix=$UNINSTALLED_ROOT/$BRANCH/prefix and it should be picked up"
-echo "by autogen.sh/configure"
-echo
-echo "==========================================================================================="
-
diff --git a/scripts/dist-translations.py b/scripts/dist-translations.py
new file mode 100755 (executable)
index 0000000..65148d6
--- /dev/null
@@ -0,0 +1,42 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2020 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., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+import os
+import subprocess
+import shutil
+import tempfile
+
+if __name__ == "__main__":
+    dist_root = os.environ['MESON_DIST_ROOT']
+    build_root = os.environ['MESON_BUILD_ROOT']
+    source_root = os.environ['MESON_SOURCE_ROOT']
+    pwd = os.environ['PWD']
+    tmpdir = tempfile.gettempdir()
+
+    module = os.path.basename(os.path.normpath(source_root))
+
+    # Generate pot file
+    print('Generating pot file ...')
+    subprocess.run(['ninja', '-C', build_root, module + '-1.0-pot'], check=True)
+
+    # Dist pot file in tarball
+    print('Copying pot file into dist staging directory ...')
+    pot_src = os.path.join(source_root, 'po', module + '-1.0.pot')
+    dist_po_dir = os.path.join(dist_root, 'po')
+    shutil.copy2(pot_src, dist_po_dir)
diff --git a/scripts/extract-release-date-from-doap-file.py b/scripts/extract-release-date-from-doap-file.py
new file mode 100755 (executable)
index 0000000..f09b60e
--- /dev/null
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+#
+# extract-release-date-from-doap-file.py VERSION DOAP-FILE
+#
+# Extract release date for the given release version from a DOAP file
+#
+# Copyright (C) 2020 Tim-Philipp Müller <tim centricular 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., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+import sys
+import xml.etree.ElementTree as ET
+
+if len(sys.argv) != 3:
+  sys.exit('Usage: {} VERSION DOAP-FILE'.format(sys.argv[0]))
+
+release_version = sys.argv[1]
+doap_fn = sys.argv[2]
+
+tree = ET.parse(doap_fn)
+root = tree.getroot()
+
+namespaces = {'doap': 'http://usefulinc.com/ns/doap#'}
+
+for v in root.findall('doap:release/doap:Version', namespaces=namespaces):
+  if v.findtext('doap:revision', namespaces=namespaces) == release_version:
+    release_date = v.findtext('doap:created', namespaces=namespaces)
+    if release_date:
+      print(release_date)
+      sys.exit(0)
+
+sys.exit('Could not find a release with version {} in {}'.format(release_version, doap_fn))
diff --git a/scripts/five-bugs-a-day.pl b/scripts/five-bugs-a-day.pl
deleted file mode 100755 (executable)
index 7a4b284..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-#!/usr/bin/env perl
-#
-# ----------------------------------------------------------------------------
-#
-# five-bugs-a-day.pl
-#
-# Little script that outputs a list of N random open bugs from bugzilla
-# for a certain bugzilla product
-#
-# ----------------------------------------------------------------------------
-#
-# Copyright (C) 2011-2012 Tim-Philipp Muller <tim centricular net>
-#
-# This script is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
-# Boston, MA 02110-1301, USA.
-#
-# ----------------------------------------------------------------------------
-#
-# You can use it to send yourself an e-mail with a few bugs to check up on
-# every day, just put it into your crontab on a computer of your choice
-# (with proper e-mail forwarding configured in some way):
-#
-# $ crontab -e
-#
-# add:
-#
-#   MAILTO=you@nowhere.org
-#   # send ten random buglinks every day at 16.30
-#   30 16 * * *  /usr/bin/perl  /path/to/five-bugs-a-day.pl
-#
-#
-# Yes, it's PERL, sorry.
-#
-# Yes, I know the default is 10 bugs.
-#
-# ----------------------------------------------------------------------------
-
-# ----------------------------------------------------------------------------
-#    subroutines
-# ----------------------------------------------------------------------------
-
-sub shuffle
-{
-    my $array = shift;
-    my $i = @$array;
-    while ( --$i )
-    {
-        my $j = int rand( $i+1 );
-        @$array[$i,$j] = @$array[$j,$i];
-    }
-
-    return @$array;
-}
-
-# ----------------------------------------------------------------------------
-#    main
-# ----------------------------------------------------------------------------
-
-my $NUM_BUGS = 10;
-
-my $PRODUCT = "GStreamer";
-
-# ----- command line options -----
-
-if (@ARGV) {
-  $NUM_BUGS = shift @ARGV;
-}
-
-if (@ARGV) {
-  $PRODUCT = shift @ARGV;
-}
-
-
-my $QUERY_URL = "https://bugzilla.gnome.org/buglist.cgi?product=$PRODUCT&" .
-                'bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&' .
-                'bug_status=REOPENED&' .
-                'query_format=advanced&ctype=csv';
-
-my $COL_ID;
-my $COL_DESC;
-
-my %BUGS;
-
-# for testing/debugging:
-# unless (@lines = `cat bugs.csv`) {
-unless (@lines = `wget --no-check-certificate --quiet -O - '$QUERY_URL'`) {
-  die 'Could not download bug list';
-}
-
-# ----- parse column headers -----
-
-my $headers;
-
-# get first line which contains the field names
-$headers = shift @lines;
-
-# get rid of newline at end
-chop $headers;
-
-my @fields = split (/,/, $headers);
-my $num_fields = scalar(@fields);
-
-for (my $c = 0; $c < $num_fields; $c++) {
-  #print "$c $fields[$c] \n";
-  if ($fields[$c] =~ m/bug_id/) {
-    $COL_ID = $c;
-  } elsif ($fields[$c] =~ m/short_desc/) {
-    $COL_DESC = $c;
-  }
-}
-
-die "Could not find bug_id column in CVS file" if not defined ($COL_ID);
-die "Could not find short_desc column in CVS file" if not defined ($COL_DESC);
-
-#print "bugid is column $COL_ID\n";
-#print "desc  is column $COL_DESC\n";
-
-foreach (@lines) {
-  if (m/,/) {
-    chop;
-
-    # We specify num_fields as limit here, because the short_desc field
-    # might contain commas as well, and we don't want it to get cut off.
-    # This is a hack for the fact that we don't handle quoted fields
-    # (12345,"UNCONFIRMED","foo, bar: errors out") properly. As long as the
-    # short_desc field is the last one, that should be ok. (FIXME)
-    my @vals = split (/,/, $_, $num_fields);
-    my $id = $vals[$COL_ID];
-    my $desc = $vals[$COL_DESC];
-
-    $desc =~ s/^"(.*)"$/$1/;
-    $BUGS{$id} = $desc;
-  }
-}
-
-my @all_bugs = keys %BUGS;
-my @bugs = shuffle (\@all_bugs);
-
-# only want first NUM_BUGS bugs
-@bugs = splice (@bugs, 0, $NUM_BUGS);
-
-print "\n";
-print "$NUM_BUGS random bugs:\n";
-print "\n";
-
-for my $bug_id ( @bugs ) {
-  print "$BUGS{$bug_id}\n";
-  print "https://bugzilla.gnome.org/show_bug.cgi?id=$bug_id\n";
-  print "\n";
-}
-
-print "\n";
-print "More bugs at:\n";
-print "  - http://gstreamer.freedesktop.org/bugs/\n";
-print "  - https://bugzilla.gnome.org/browse.cgi?product=GStreamer\n";
-print "\n";
diff --git a/scripts/git-update.sh b/scripts/git-update.sh
deleted file mode 100755 (executable)
index 25cb7cc..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/bin/bash
-
-# update all known gstreamer modules
-# build them one by one
-# report failures at the end
-# run this from a directory that contains the checkouts for each of the
-# modules
-
-PIDS=
-
-CORE="\
-    gstreamer gst-plugins-base"
-MODULES="\
-    gst-plugins-good gst-plugins-ugly gst-plugins-bad \
-    gst-libav"
-EXTRA_MODULES="\
-    gst-editing-services \
-    gst-rtsp-server \
-    gst-python"
-
-tmp=${TMPDIR-/tmp}
-tmp=$tmp/git-update.$(date +%Y%m%d-%H%M-).$RANDOM.$RANDOM.$RANDOM.$$
-
-(umask 077 && mkdir "$tmp") || {
-  echo "Could not create temporary directory! Exiting." 1>&2
-  exit 1
-}
-
-ERROR_LOG="$tmp/failures.log"
-ERROR_RETURN=255
-
-CPUCORES=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || sysctl -n hw.ncpu  2>/dev/null || echo "1")
-
-for m in $CORE $MODULES $EXTRA_MODULES; do
-  if test -d $m; then
-    echo "+ updating $m"
-    cd $m
-
-    git pull --rebase
-    if test $? -ne 0
-    then
-      echo "$m: update (trying stash, pull, stash apply)" >> $ERROR_LOG
-      git stash
-      git pull --rebase
-      if test $? -ne 0
-      then 
-        echo "$m: update" >> $ERROR_LOG
-        cd ..
-        continue
-      fi
-      git stash apply
-    fi
-
-    git submodule update
-    if test $? -ne 0
-    then
-      echo "$m: update (submodule)" >> $ERROR_LOG
-      cd ..
-      continue
-    fi
-    cd ..
-  fi
-done
-
-build()
-{
-  if test -d $1; then
-    cd $1
-    if test ! -e Makefile
-    then
-      if test -e autoregen.sh
-      then
-        echo "+ $1: autoregen.sh"
-        ./autoregen.sh > "$tmp/$1-regen.log" 2>&1
-        if test $? -ne 0
-        then
-          echo "$1: autoregen.sh [$tmp/$1-regen.log]" >> $ERROR_LOG
-          cd ..
-          return $ERROR_RETURN
-        fi
-        echo "+ $1: autoregen.sh done"
-      else
-        echo "+ $1: autogen.sh"
-        ./autogen.sh > "$tmp/$1-gen.log" 2>&1
-        if test $? -ne 0
-        then
-          echo "$1: autogen.sh [$tmp/$1-gen.log]" >> $ERROR_LOG
-          cd ..
-          return $ERROR_RETURN
-        fi
-        echo "+ $1: autogen.sh done"
-      fi
-    fi
-
-    echo "+ $1: make"
-    MAKEFLAGS="-j$CPUCORES $MAKEFLAGS" make > "$tmp/$1-make.log" 2>&1
-    if test $? -ne 0
-    then
-      echo "$1: make [$tmp/$1-make.log]" >> $ERROR_LOG
-      cd ..
-      return $ERROR_RETURN
-    fi
-    echo "+ $1: make done"
-
-    if test "x$CHECK" != "x"; then
-      echo "+ $1: make check"
-      make check > "$tmp/$1-check.log" 2>&1
-      if test $? -ne 0
-      then
-        echo "$1: check [$tmp/$1-check.log]" >> $ERROR_LOG
-        cd ..
-        return
-      fi
-      echo "+ $1: make check done"
-    fi
-    cd ..
-  fi
-}
-
-beach()
-{
-if test -e $ERROR_LOG;  then
-  echo "Failures:"
-  echo
-  cat $ERROR_LOG
-else
-  echo "Update done"
-  rm -rf "$tmp"
-fi
-exit
-}
-
-# build core and base plugins sequentially
-# exit if build fails (excluding checks)
-for m in $CORE; do
-  build $m
-  if [ $? -eq $ERROR_RETURN ]; then
-  beach
-  fi
-done
-
-# build other modules in parallel
-for m in $MODULES $EXTRA_MODULES; do
-  build $m &
-  PIDS="$PIDS $!"
-done
-wait $PIDS
-
-beach
-
diff --git a/scripts/gst-uninstalled b/scripts/gst-uninstalled
deleted file mode 100755 (executable)
index 24c2481..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-#!/bin/bash -i
-#
-# this script is in git as gstreamer/scripts/gst-uninstalled
-#
-# It will set up the environment to use and develop gstreamer and projects
-# that use gstreamer with an uninstalled git checkout of gstreamer and the
-# plugin modules.
-#
-# It will set up LD_LIBRARY_PATH, DYLD_LIBRARY_PATH, PKG_CONFIG_PATH,
-# GST_PLUGIN_PATH, GST_PLUGIN_SYSTEM_PATH, GST_REGISTRY, MANPATH, PYTHONPATH
-# to prefer the uninstalled versions but also contain the installed ones.
-# The only exception to this is, that no system installed plugins will be
-# used but only the uninstalled ones.
-#
-# This script assumes that the relevant modules are checked out one by one
-# under a given tree specified below in MYGST.
-#
-# Symlink this script in a directory in your path (for example $HOME/bin). You
-# must name the symlink gst-something, where something is the subdirectory
-# of MYGST that contains your gstreamer module checkouts.
-#
-# e.g.:
-# - mkdir $HOME/gst/head
-# - ln -sf gst-uninstalled $HOME/bin/gst-head
-# - checkout copies of gstreamer modules in $HOME/gst/head
-# - gst-head
-
-# This script is run -i so that PS1 doesn't get cleared
-
-if [ -z $GST_UNINSTALLED_ROOT ];
-then
-    # Change this variable to the location of your gstreamer git checkouts
-    MYGST=$HOME/gst
-
-    #
-    # Everything below this line shouldn't be edited!
-    #
-
-    # extract version from $0
-    # if this script is called "gst-head" then version will be "head"
-    VERSION=`echo $0 | sed s/.*gst-//g`
-
-    # base path under which dirs are installed
-    GST=$MYGST/$VERSION
-else
-    # Alternatively, you can set the GST_UNINSTALLED_ROOT environment variable to the
-    # location of your checkout and call this script directly.
-    #
-    # Ex: GST_UNINSTALLED_ROOT=$HOME/checkout/location gst-uninstalled
-
-    GST=$GST_UNINSTALLED_ROOT
-fi
-
-GST_PREFIX=$GST/prefix
-if test ! -e $GST; then
-  echo "$GST does not exist !"
-  exit
-fi
-
-# set up a bunch of paths
-PATH="\
-$GST/gstreamer/tools:\
-$GST/gst-plugins-base/tools:\
-$GST/gst-player/src:\
-$GST/gst-editor/src:\
-$GST/gstreamer-sharp/tools:\
-$GST/orc/tools:\
-$GST_PREFIX/bin:\
-$PATH"
-
-# /some/path: makes the dynamic linker look in . too, so avoid this
-LD_LIBRARY_PATH=$GST_PREFIX/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
-DYLD_LIBRARY_PATH=$GST_PREFIX/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}
-GI_TYPELIB_PATH=$GST_PREFIX/share/gir-1.0${GI_TYPELIB_PATH:+:$GI_TYPELIB_PATH}
-
-# Nice
-LD_LIBRARY_PATH=$GST/libnice/nice/.libs:$LD_LIBRARY_PATH
-DYLD_LIBRARY_PATH=$GST/libnice/nice/.libs:$DYLD_LIBRARY_PATH
-
-# ORC
-LD_LIBRARY_PATH=$GST/orc/orc/.libs:$GST/orc/orc-test/.libs:$LD_LIBRARY_PATH
-DYLD_LIBRARY_PATH=$GST/orc/orc/.libs:$GST/orc/orc-test/.libs:$DYLD_LIBRARY_PATH
-
-# GStreamer rtsp server library
-LD_LIBRARY_PATH=$GST/gst-rtsp-server/gst/rtsp-server/.libs:$LD_LIBRARY_PATH
-DYLD_LIBRARY_PATH=$GST/gst-rtsp-server/gst/rtsp-server/.libs:$DYLD_LIBRARY_PATH
-GI_TYPELIB_PATH=$GST/gst-rtsp-server/gst/rtsp-server:$GI_TYPELIB_PATH
-
-# GStreamer Editing Services library
-LD_LIBRARY_PATH=$GST/gst-editing-services/ges/.libs:$LD_LIBRARY_PATH
-DYLD_LIBRARY_PATH=$GST/gst-editing-services/ges/.libs:$DYLD_LIBRARY_PATH
-GI_TYPELIB_PATH=$GST/gst-editing-services/ges:$GI_TYPELIB_PATH
-PATH=$GST/gst-editing-services/tools:$PATH
-
-# GStreamer plugins vaapi libraries
-LD_LIBRARY_PATH=$GST/gstreamer-vaapi/gst-libs/gst/vaapi/.libs:$LD_LIBRARY_PATH
-DYLD_LIBRARY_PATH=$GST/gstreamer-vaapi/gst-libs/gst/vaapi/.libs:$DYLD_LIBRARY_PATH
-
-# GStreamer plugins base libraries
-for path in allocators app audio fft gl pbutils riff rtp rtsp sdp tag utils video
-do
-  LD_LIBRARY_PATH=$GST/gst-plugins-base/gst-libs/gst/$path/.libs:$LD_LIBRARY_PATH
-  DYLD_LIBRARY_PATH=$GST/gst-plugins-base/gst-libs/gst/$path/.libs:$DYLD_LIBRARY_PATH
-  GI_TYPELIB_PATH=$GST/gst-plugins-base/gst-libs/gst/$path:$GI_TYPELIB_PATH
-done
-
-# GStreamer plugins bad libraries
-for path in adaptivedemux audio basecamerabinsrc codecparsers insertbin interfaces mpegts opencv player uridownloader video wayland webrtc
-do
-  LD_LIBRARY_PATH=$GST/gst-plugins-bad/gst-libs/gst/$path/.libs:$LD_LIBRARY_PATH
-  DYLD_LIBRARY_PATH=$GST/gst-plugins-bad/gst-libs/gst/$path/.libs:$DYLD_LIBRARY_PATH
-  GI_TYPELIB_PATH=$GST/gst-plugins-bad/gst-libs/gst/$path:$GI_TYPELIB_PATH
-done
-export GST_HAAR_CASCADES_PATH=$GST/gst-plugins-bad/ext/opencv/
-
-# GStreamer core libraries
-for path in base check controller net
-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
-  GI_TYPELIB_PATH=$GST/gstreamer/libs/gst/$path:$GI_TYPELIB_PATH
-done
-LD_LIBRARY_PATH=$GST/gstreamer/gst/.libs:$LD_LIBRARY_PATH
-DYLD_LIBRARY_PATH=$GST/gstreamer/gst/.libs:$DYLD_LIBRARY_PATH
-GI_TYPELIB_PATH=$GST/gstreamer/gst:$GI_TYPELIB_PATH
-export LD_LIBRARY_PATH
-export DYLD_LIBRARY_PATH
-export GI_TYPELIB_PATH
-  
-export PKG_CONFIG_PATH="\
-$GST_PREFIX/lib/pkgconfig\
-:$GST/gstreamer/pkgconfig\
-:$GST/gst-plugins-base/pkgconfig\
-:$GST/gst-plugins-good/pkgconfig\
-:$GST/gst-plugins-ugly/pkgconfig\
-:$GST/gst-plugins-bad/pkgconfig\
-:$GST/gst-libav/pkgconfig\
-:$GST/gst-ffmpeg/pkgconfig\
-:$GST/gst-python/pkgconfig\
-:$GST/gst-rtsp-server/pkgconfig\
-:$GST/gst-editing-services/pkgconfig\
-:$GST/gstreamer-sharp/pkgconfig\
-:$GST/gstreamer-vaapi/pkgconfig\
-:$GST/orc\
-:$GST/farsight2\
-:$GST/libnice/nice\
-${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}"
-
-export GST_PLUGIN_PATH="\
-$GST/gstreamer/plugins\
-:$GST/gst-plugins-base/ext\
-:$GST/gst-plugins-base/gst\
-:$GST/gst-plugins-base/sys\
-:$GST/gst-plugins-good/ext\
-:$GST/gst-plugins-good/gst\
-:$GST/gst-plugins-good/sys\
-:$GST/gst-plugins-ugly/ext\
-:$GST/gst-plugins-ugly/gst\
-:$GST/gst-plugins-ugly/sys\
-:$GST/gst-plugins-bad/ext\
-:$GST/gst-plugins-bad/gst\
-:$GST/gst-plugins-bad/sys\
-:$GST/gst-libav/ext/\
-:$GST/gst-ffmpeg/ext/\
-:$GST/gst-omx/omx/.libs\
-:$GST/clutter-gst/clutter-gst/.libs\
-:$GST/gstreamer-vaapi/gst/vaapi/.libs\
-:$GST/plugins\
-:$GST/farsight2/gst\
-:$GST/farsight2/transmitters\
-:$GST/libnice/gst\
-:$GST/gst-rpicamsrc/src/.libs\
-:$GST/gst-rtsp-server/gst/rtsp-sink/.libs\
-:$GST/gst-editing-services/plugins/nle/.libs\
-:$GST/prefix/lib/gstreamer-1.0\
-${GST_PLUGIN_PATH:+:$GST_PLUGIN_PATH}"
-
-export GST_PRESET_PATH="\
-$GST/gst-plugins-good/gst/equalizer/\
-:$GST/gst-plugins-good/gst/equalizer\
-:$GST/gst-plugins-good/ext/vpx/\
-:$GST/gst-plugins-ugly/ext/x264\
-:$GST/gst-plugins-ugly/ext/amrnb\
-:$GST/gst-plugins-bad/gst/freeverb\
-:$GST/gst-plugins-bad/ext/voamrwbenc\
-${GST_PRESET_PATH:+:$GST_PRESET_PATH}"
-
-# don't use any system-installed plug-ins at all
-export GST_PLUGIN_SYSTEM_PATH=
-# set our registry somewhere else so we don't mess up the registry generated
-# by an installed copy
-rm -f $GST/gstreamer/registry.xml 2>/dev/null
-export GST_REGISTRY=$GST/gstreamer/registry.dat
-# Point at the uninstalled plugin scanner
-export GST_PLUGIN_SCANNER=$GST/gstreamer/libs/gst/helpers/gst-plugin-scanner
-# Point at the uninstalled PTP helper
-export GST_PTP_HELPER=$GST/gstreamer/libs/gst/helpers/.libs/gst-ptp-helper
-
-# once MANPATH is set, it needs at least an "empty"component to keep pulling
-# in the system-configured man paths from man.config
-# this still doesn't make it work for the uninstalled case, since man goes
-# look for a man directory "nearby" instead of the directory I'm telling it to
-export MANPATH=$GST/gstreamer/tools:$GST_PREFIX/share/man:$GST/gst-editing-services/docs/man/:$MANPATH
-if [ -z "$PYTHON" ]; then PYTHON="python3"; fi
-pythonver=`$PYTHON -c "import sys; print (sys.version[:3])"`
-pythonsites=`$PYTHON -c "import site; print(':'.join(site.getsitepackages()))"`
-export PYTHONPATH="${PYTHONPATH}:${pythonsites}:${GST}/gst-python"
-
-# clutter-gst
-export PKG_CONFIG_PATH=$GST/clutter-gst:$PKG_CONFIG_PATH
-export LD_LIBRARY_PATH=$GST/clutter-gst/clutter-gst/.libs:$LD_LIBRARY_PATH
-export DYLD_LIBRARY_PATH=$GST/clutter-gst/clutter-gst/.libs:$DYLD_LIBRARY_PATH
-
-# totem-pl-parser
-export PKG_CONFIG_PATH=$GST/totem-pl-parser:$PKG_CONFIG_PATH
-export LD_LIBRARY_PATH=$GST/totem-pl-parser/plparse/.libs:$LD_LIBRARY_PATH
-export DYLD_LIBRARY_PATH=$GST/totem-pl-parser/plparse/.libs:$DYLD_LIBRARY_PATH
-
-# totem
-export PATH=$GST/totem/src:$PATH
-
-# gstreamer-sharp
-export MONO_PATH=$GST/gstreamer-sharp/gstreamer-sharp:$MONO_PATH
-export LD_LIBRARY_PATH=$GST/gstreamer-sharp/gstreamer-sharp/glue/.libs:$LD_LIBRARY_PATH
-export DYLD_LIBRARY_PATH=$GST/gstreamer-sharp/gstreamer-sharp/glue/.libs:$DYLD_LIBRARY_PATH
-
-# gst-devtools/validate
-export PATH=$GST/gst-devtools/validate/tools:$PATH
-export PKG_CONFIG_PATH=$GST/gst-devtools/validate/pkgconfig:$PKG_CONFIG_PATH
-export GST_VALIDATE_SCENARIOS_PATH=$GST/gst-devtools/validate/data/scenarios:$GST_VALIDATE_SCENARIOS_PATH
-export GST_VALIDATE_APPS_DIR=$GST_VALIDATE_APPS_DIR:$GST/gst-editing-services/tests/validate/
-export GST_VALIDATE_PLUGIN_PATH=$GST_VALIDATE_PLUGIN_PATH:$GST/gst-devtools/validate/plugins/
-export GIO_EXTRA_MODULES=$GST/prefix/lib/gio/modules:$GIO_EXTRA_MODULES
-
-if [ -d "$GST/gst-libav" -a -d "$GST/gst-ffmpeg" ]; then
-  echo
-  echo "====================================================================="
-  echo " You have both an uninstalled gst-ffmpeg checkout and a gst-libav"
-  echo " checkout. You need to remove one of those. You should remove"
-  echo
-  echo "   $GST/gst-ffmpeg"
-  echo
-  echo " since gst-libav replaces gst-ffmpeg."
-  echo "====================================================================="
-  echo
-fi
-
-# if we got a command, run it, else start a shell
-if test ! -z "$1";
-then
-  $@
-  exit $?
-fi
-
-# set up prompt to help us remember we're in a subshell, cd to
-# the gstreamer base dir and start $SHELL
-cd $GST
-shell=$SHELL
-if test "x$SHELL" = "x/bin/bash"
-then
-  # debian/ubuntu resets our PS1.  bastards.
-  shell="$SHELL --noprofile"
-fi
-PS1="[gst-$VERSION] $PS1" $shell
-
diff --git a/scripts/meson.build b/scripts/meson.build
new file mode 100644 (file)
index 0000000..f5d9106
--- /dev/null
@@ -0,0 +1,4 @@
+# dist scripts
+if not meson.is_subproject()
+  meson.add_dist_script('dist-translations.py')
+endif
diff --git a/stamp.h.in b/stamp.h.in
deleted file mode 100644 (file)
index 9788f70..0000000
+++ /dev/null
@@ -1 +0,0 @@
-timestamp
diff --git a/tests/.gitignore b/tests/.gitignore
deleted file mode 100644 (file)
index 9e672fd..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-Makefile
-Makefile.in
-*.o
-*.lo
-*.la
-.deps
-.libs
-*.xml
-*.gst
-init
-mass_elements
-*.bb
-*.bbg
-*.da
-*.data
-*.ps
-/examples/streamiddemux/streamiddemux-stream
diff --git a/tests/Makefile.am b/tests/Makefile.am
deleted file mode 100644 (file)
index 9fe291c..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-EXTRA_DIST = README
-
-# Build misc unless both --disable-examples and --disable-benchmarks were passed
-
-if BUILD_BENCHMARKS
-SUBDIRS_BENCHMARKS = benchmarks
-SUBDIRS_MISC = misc
-else
-SUBDIRS_BENCHMARKS =
-endif
-
-if BUILD_TESTS
-## SUBDIRS_TESTS = tests testsuite
-## FIXME: write tests from scratch
-SUBDIRS_TESTS =
-if HAVE_CHECK
-SUBDIRS_CHECK = check
-else
-SUBDIRS_CHECK =
-endif
-else
-SUBDIRS_TESTS =
-SUBDIRS_CHECK =
-endif
-
-if BUILD_EXAMPLES
-SUBDIRS_EXAMPLES = examples
-SUBDIRS_MISC = misc
-else
-SUBDIRS_EXAMPLES =
-endif
-
-SUBDIRS = \
-       $(SUBDIRS_BENCHMARKS) \
-       $(SUBDIRS_CHECK) \
-       $(SUBDIRS_MISC) \
-       $(SUBDIRS_TESTS) \
-       $(SUBDIRS_EXAMPLES)
-
-# These are all the possible subdirs
-DIST_SUBDIRS = \
-       benchmarks \
-       check \
-       examples \
-       misc
diff --git a/tests/benchmarks/.gitignore b/tests/benchmarks/.gitignore
deleted file mode 100644 (file)
index dd796d4..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-Makefile
-Makefile.in
-caps
-capsnego
-complexity
-controller
-gstbufferstress
-gstclockstress
-gstpollstress
-gstpoolstress
-mass-elements
-tracerserialize
-*.gcno
diff --git a/tests/benchmarks/Makefile.am b/tests/benchmarks/Makefile.am
deleted file mode 100644 (file)
index 3d769f5..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-if !GST_DISABLE_GST_DEBUG
-TRACER_BENCH = tracerserialize
-else
-TRACER_BENCH =
-endif
-
-noinst_PROGRAMS = \
-        caps \
-        capsnego \
-        complexity \
-        controller \
-        init \
-        mass-elements \
-        gstpollstress \
-        gstpoolstress \
-        gstclockstress \
-        gstbufferstress \
-        $(TRACER_BENCH)
-
-LDADD = $(GST_OBJ_LIBS)
-AM_CFLAGS = $(GST_OBJ_CFLAGS)
-
-controller_CFLAGS  = $(GST_OBJ_CFLAGS) -I$(top_builddir)/libs
-controller_LDADD = $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la $(LDADD)
-
index 2cf1dc8..0ceb64c 100644 (file)
@@ -121,7 +121,7 @@ main (gint argc, gchar * argv[])
       GST_TIME_ARGS (end - start));
 
   start = gst_util_get_timestamp ();
-  g_object_unref (pipeline);
+  gst_object_unref (pipeline);
   end = gst_util_get_timestamp ();
   g_print ("%" GST_TIME_FORMAT " - unreffing pipeline\n",
       GST_TIME_ARGS (end - start));
index cfe6c85..add8f41 100644 (file)
@@ -109,7 +109,7 @@ main (gint argc, gchar * argv[])
       GST_TIME_ARGS (end - start));
 
   start = gst_util_get_timestamp ();
-  g_object_unref (pipeline);
+  gst_object_unref (pipeline);
   end = gst_util_get_timestamp ();
   g_print ("%" GST_TIME_FORMAT " - unreffing pipeline\n",
       GST_TIME_ARGS (end - start));
diff --git a/tests/check/.gitignore b/tests/check/.gitignore
deleted file mode 100644 (file)
index a14a3ec..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-test-registry.*
-*.gcno
-*.gcda
-
-tools/.dirstamp
-tools/gstinspect
diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am
deleted file mode 100644 (file)
index 4c9d344..0000000
+++ /dev/null
@@ -1,313 +0,0 @@
-include $(top_srcdir)/common/check.mak
-
-CHECK_REGISTRY = $(top_builddir)/tests/check/test-registry.reg
-
-GST_TOOLS_DIR = $(top_builddir)/tools
-
-REGISTRY_ENVIRONMENT = \
-       GST_REGISTRY=$(CHECK_REGISTRY)
-
-AM_TESTS_ENVIRONMENT += \
-        GST_STATE_IGNORE_ELEMENTS="$(STATE_IGNORE_ELEMENTS)"   \
-        $(REGISTRY_ENVIRONMENT)                                        \
-        GST_PLUGIN_SCANNER_1_0=$(top_builddir)/libs/gst/helpers/gst-plugin-scanner \
-        GST_PLUGIN_SYSTEM_PATH_1_0=                                    \
-        GST_PLUGIN_PATH_1_0=$(top_builddir)/plugins
-
-plugindir = $(libdir)/gstreamer-@GST_API_VERSION@
-
-# override to _not_ install the test plugins
-install-pluginLTLIBRARIES:
-
-# the core dumps of some machines have PIDs appended, test registry and
-# profiling data
-CLEANFILES = core core.* test-registry.* *.gcno *.gcda
-
-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
-PARSE_CHECKS = pipelines/simple-launch-lines pipelines/cleanup pipelines/parse-launch
-endif
-
-# Do not run the abi test in case any option which causes the API to change has
-# been used
-if !GST_DISABLE_REGISTRY
-ABI_CHECKS = gst/gstabi
-endif
-
-if !GST_DISABLE_GST_DEBUG
-PRINTF_CHECKS = gst/gstprintf
-else
-PRINTF_CHECKS =
-endif
-
-LIBSABI_CHECKS = libs/libsabi
-
-if HAVE_CXX
-CXX_CHECKS = gst/gstcpp libs/gstlibscpp
-else
-CXX_CHECKS =
-endif
-
-# if it's calling gst_element_factory_make(), it will probably not work without
-# a registry
-if GST_DISABLE_REGISTRY
-REGISTRY_CHECKS =
-else
-REGISTRY_CHECKS =                              \
-       gst/gst                                 \
-       gst/gstbin                              \
-       gst/gstchildproxy                       \
-       gst/gstcontext                          \
-       gst/gstcontroller                       \
-       gst/gstelement                          \
-       gst/gstelementfactory                   \
-       gst/gstevent                            \
-       gst/gstghostpad                         \
-       gst/gstplugin                           \
-       gst/gstpreset                           \
-       gst/gstprotection                       \
-       gst/gstquery                            \
-       gst/gstregistry                         \
-       gst/gsturi                              \
-       gst/gstutils                            \
-       generic/sinks                           \
-       elements/capsfilter                     \
-       elements/concat                         \
-       elements/dataurisrc                     \
-       elements/fakesink                       \
-       elements/fakesrc                        \
-       elements/fdsrc                          \
-       elements/filesink                       \
-       elements/filesrc                        \
-       elements/funnel                         \
-       elements/identity                       \
-       elements/multiqueue                     \
-       elements/selector                       \
-       elements/tee                            \
-       elements/queue                          \
-       elements/queue2                         \
-       elements/valve                          \
-       elements/streamiddemux                  \
-       libs/baseparse                          \
-       libs/basesrc                            \
-       libs/basesink                           \
-       libs/sparsefile                         \
-       libs/controller                         \
-       libs/queuearray                         \
-       libs/typefindhelper                     \
-       pipelines/seek                          \
-       pipelines/stress                        \
-       pipelines/queue-error
-endif
-
-check_PROGRAMS =                               \
-       $(ABI_CHECKS)                           \
-       gst/gstatomicqueue                      \
-       gst/gstbuffer                           \
-       gst/gstbufferlist                       \
-       gst/gstbufferpool                       \
-       gst/gstmeta                             \
-       gst/gstmemory                           \
-       gst/gstbus                              \
-       gst/gstcaps                             \
-       gst/gstcapsfeatures                     \
-       $(CXX_CHECKS)                           \
-       gst/gstdatetime                         \
-       gst/gstdeinit                           \
-       gst/gstdevice                           \
-       gst/gstinfo                             \
-       gst/gstiterator                         \
-       gst/gstmessage                          \
-       gst/gstminiobject                       \
-       gst/gstobject                           \
-       gst/gstpad                              \
-       gst/gstparamspecs                       \
-       gst/gstpipeline                         \
-       gst/gstpoll                             \
-       gst/gstprotection                       \
-       $(PRINTF_CHECKS)                        \
-       gst/gstpromise                          \
-       gst/gstsegment                          \
-       gst/gstsystemclock                      \
-       gst/gstclock                            \
-       gst/gststream                           \
-       gst/gststructure                        \
-       gst/gsttag                              \
-       gst/gsttracerrecord                             \
-       gst/gsttagsetter                        \
-       gst/gsttask                             \
-       gst/gsttoc                              \
-       gst/gsttocsetter                        \
-       gst/gstvalue                            \
-       generic/states                          \
-       $(PARSE_CHECKS)                         \
-       $(REGISTRY_CHECKS)                      \
-       $(LIBSABI_CHECKS)                       \
-       libs/adapter                            \
-       libs/aggregator                         \
-       libs/bitreader                          \
-       libs/bitwriter                          \
-       libs/bytereader                         \
-       libs/bytewriter                         \
-       libs/bitreader-noinline         \
-       libs/bytereader-noinline        \
-       libs/bytewriter-noinline        \
-       libs/flowcombiner                       \
-       libs/sparsefile                         \
-       libs/collectpads                        \
-       libs/gstharness                         \
-       libs/gstnetclientclock                  \
-       libs/gstnettimeprovider                 \
-       libs/gsttestclock                       \
-       libs/transform1                         \
-       libs/transform2                         \
-       tools/gstinspect
-
-# failing tests
-noinst_PROGRAMS =
-
-# elements to ignore for the state tests
-# STATE_IGNORE_ELEMENTS =
-
-TESTS = $(check_PROGRAMS)
-
-noinst_HEADERS = \
-       gst/capslist.h \
-       gst/struct_arm.h \
-       gst/struct_i386.h \
-       gst/struct_i386w.h \
-       gst/struct_hppa.h \
-       gst/struct_ppc32.h \
-       gst/struct_ppc64.h \
-       gst/struct_sparc.h \
-       gst/struct_x86_64.h \
-       gst/struct_x86_64w.h \
-       libs/struct_arm.h \
-       libs/struct_i386.h \
-       libs/struct_hppa.h \
-       libs/struct_ppc32.h \
-       libs/struct_ppc64.h \
-       libs/struct_sparc.h \
-       libs/struct_x86_64.h
-
-EXTRA_DIST = \
-       libs/test_transform.c
-
-AM_CFLAGS = $(PTHREAD_CFLAGS) $(GST_OBJ_CFLAGS) -UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS \
-       -DGST_CHECK_TEST_ENVIRONMENT_BEACON="\"GST_STATE_IGNORE_ELEMENTS\""
-AM_CXXFLAGS = $(GST_OBJ_CXXFLAGS) -UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS \
-       -DGST_CHECK_TEST_ENVIRONMENT_BEACON="\"GST_STATE_IGNORE_ELEMENTS\""
-LDADD = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \
-       $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \
-       $(GST_OBJ_LIBS)
-
-gst_gstcpp_SOURCES = gst/gstcpp.cc
-
-libs_gstlibscpp_SOURCES = libs/gstlibscpp.cc
-
-gst_gsttracerrecord_CFLAGS = $(GST_OBJ_CFLAGS) $(AM_CFLAGS) -DGST_USE_UNSTABLE_API
-
-gst_gstutils_LDADD = $(LDADD) $(GSL_LIBS) $(GMP_LIBS)
-
-gst_gstprintf_LDADD = \
-       $(top_builddir)/gst/printf/libgstprintf.la \
-       $(LDADD)
-
-elements_fdsrc_CFLAGS=$(GST_OBJ_CFLAGS) $(AM_CFLAGS) \
-       -DTESTFILE=\"$(top_srcdir)/configure.ac\"
-elements_filesrc_CFLAGS=$(GST_OBJ_CFLAGS) $(AM_CFLAGS) \
-       -DTESTFILE=\"$(top_srcdir)/configure.ac\"
-
-libs_controller_LDADD = \
-       $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \
-       $(LDADD)
-libs_gstnetclientclock_LDADD = \
-       $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \
-       $(LDADD)
-libs_gstnettimeprovider_LDADD = \
-       $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \
-       $(GIO_LIBS) $(LDADD)
-
-# valgrind testing
-# these just need valgrind fixing, period
-VALGRIND_TO_FIX = \
-       gst/gstinfo \
-       gst/gsttracerrecord \
-       tools/gstinspect
-
-VALGRIND_IGNORE = \
-       pipelines/stress
-
-# these need fixing because the threads cause segfaults under valgrind
-TESTS_THREADED =                               \
-       gst/gstminiobject                       \
-       gst/gstobject
-
-VALGRIND_TESTS_DISABLE =                                       \
-       $(TESTS_THREADED)                                       \
-       $(VALGRIND_IGNORE)                                      \
-       $(VALGRIND_TO_FIX)
-
-# indexers does not get tested yet
-COVERAGE_DIRS = \
-       gst \
-       libs/gst/base \
-       libs/gst/controller \
-       libs/gst/check \
-       libs/gst/net \
-       plugins/elements
-COVERAGE_FILES = $(foreach dir,$(COVERAGE_DIRS),$(wildcard $(top_builddir)/$(dir)/*.gcov))
-COVERAGE_FILES_REL = $(subst $(top_builddir)/,,$(COVERAGE_FILES))
-COVERAGE_OUT_FILES = $(foreach dir,$(COVERAGE_DIRS),$(wildcard $(top_builddir)/$(dir)/*.gcov.out))
-COVERAGE_OUT_FILES_REL = $(subst $(top_builddir)/,,$(COVERAGE_OUT_FILES))
-
-debug:
-       echo $(COVERAGE_FILES)
-       echo $(COVERAGE_FILES_REL)
-
-.PHONY: coverage
-if GST_GCOV_ENABLED
-# we rebuild a registry and do gst-inspect so that all the get/set codepaths
-# are also covered
-coverage:
-       for file in `find $(top_builddir) -name '*.gcda'`; do rm $$file; done
-       -rm $(CHECK_REGISTRY)
-       echo "Inspecting all elements"
-       for e in `$(GST_INSPECT) | head -n -2 | cut -d: -f2`; do $(GST_INSPECT) $$e > /dev/null 2>&1; done
-       make check
-       make coverage-report
-else
-coverage:
-       echo "You need to configure with --enable-gcov to get coverage data"
-       exit 1
-endif
-
-coverage-report:
-       rm -r coverage
-       for dir in $(COVERAGE_DIRS); do                                 \
-         mkdir -p coverage/$$dir;                                      \
-         make -C $(top_builddir)/$$dir gcov;                           \
-        done
-       for dir in $(COVERAGE_DIRS); do                                 \
-           files="`ls $(top_builddir)/$$dir/*.gcov.out 2> /dev/null`"; \
-          if test ! -z "$$files"; then                                 \
-           perl $(top_srcdir)/common/coverage/coverage-report.pl       \
-             $(top_builddir)/$$dir/*.gcov.out >                        \
-             coverage/$$dir/index.xml;                                 \
-           xsltproc $(top_srcdir)/common/coverage/coverage-report.xsl  \
-             coverage/$$dir/index.xml > coverage/$$dir/index.html;     \
-         fi; \
-        done
-       for file in $(COVERAGE_FILES_REL); do                           \
-         echo Generating coverage/$$file.html;                         \
-         perl $(top_srcdir)/common/coverage/coverage-report-entry.pl   \
-           $(top_builddir)/$$file > coverage/$$file.html;              \
-       done
diff --git a/tests/check/elements/.gitignore b/tests/check/elements/.gitignore
deleted file mode 100644 (file)
index 2027456..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-.dirstamp
-capsfilter
-concat
-dataurisrc
-fakesrc
-fakesink
-fdsrc
-filesink
-filesrc
-funnel
-identity
-multiqueue
-queue
-queue2
-selector
-streamiddemux
-tee
-valve
-*.check.xml
index c9d4fb6..df04b6b 100644 (file)
@@ -58,53 +58,6 @@ GST_START_TEST (test_one_buffer)
 
 GST_END_TEST;
 
-static void
-handoff_func (GstElement * clocksync, GstBuffer * buf, GstBuffer ** ret)
-{
-  (void) clocksync;
-  *ret = buf;
-}
-
-GST_START_TEST (test_signal_handoffs)
-{
-  GstHarness *h = gst_harness_new_parse ("clocksync sync=false name=c");
-  GstBuffer *buffer_in;
-  GstBuffer *buffer_signaled = NULL;
-  GstElement *c = gst_bin_get_by_name (GST_BIN (h->element), "c");
-
-  gst_harness_set_src_caps_str (h, "mycaps");
-
-  /* connect to the handoff signal */
-  g_signal_connect (c, "handoff", G_CALLBACK (handoff_func), &buffer_signaled);
-
-  /* first, turn off signal-handoffs */
-  g_object_set (c, "signal-handoffs", FALSE, NULL);
-
-  /* then push a buffer */
-  buffer_in = gst_buffer_new_and_alloc (4);
-  fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, buffer_in));
-
-  /* verify that we got no buffer signaled */
-  fail_unless (buffer_signaled == NULL);
-
-  /* now turn on signal-handoffs */
-  g_object_set (c, "signal-handoffs", TRUE, NULL);
-
-  /* then push another buffer */
-  buffer_in = gst_buffer_new_and_alloc (4);
-  fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, buffer_in));
-
-  /* verify the buffer signaled is equal to the one pushed in */
-  fail_unless (buffer_signaled == buffer_in);
-  ASSERT_BUFFER_REFCOUNT (buffer_signaled, "buffer", 1);
-
-  /* cleanup */
-  gst_object_unref (c);
-  gst_harness_teardown (h);
-}
-
-GST_END_TEST;
-
 GST_START_TEST (test_sync_on_timestamp)
 {
   /* the reason to use the queue in front of the clocksync element
@@ -215,6 +168,76 @@ GST_START_TEST (test_stopping_element_unschedules_sync)
 
 GST_END_TEST;
 
+typedef struct
+{
+  guint notify_count;
+  GstClockTimeDiff ts_offset;
+} ClockSyncTestData;
+
+static void
+clock_sync_ts_offset_changed_cb (GstElement * clocksync, GParamSpec * pspec,
+    ClockSyncTestData * data)
+{
+  data->notify_count++;
+  g_object_get (clocksync, "ts-offset", &data->ts_offset, NULL);
+}
+
+GST_START_TEST (test_sync_to_first)
+{
+  /* the reason to use the queue in front of the clocksync element
+     is to effectively make gst_harness_push asynchronous, not locking
+     up the test, waiting for gst_clock_id_wait */
+  GstHarness *h =
+      gst_harness_new_parse ("queue ! clocksync sync-to-first=true");
+  GstBuffer *buf;
+  GstClock *clock;
+  GstClockTime timestamp = 123456789;
+  GstElement *clocksync;
+  ClockSyncTestData data;
+  data.notify_count = 0;
+  data.ts_offset = 0;
+
+  clocksync = gst_harness_find_element (h, "clocksync");
+  g_signal_connect (clocksync, "notify::ts-offset",
+      G_CALLBACK (clock_sync_ts_offset_changed_cb), &data);
+  gst_object_unref (clocksync);
+
+  /* use testclock */
+  gst_harness_use_testclock (h);
+  gst_harness_set_src_caps_str (h, "mycaps");
+
+  /* make a buffer and set the timestamp */
+  buf = gst_buffer_new ();
+  GST_BUFFER_PTS (buf) = timestamp;
+
+  /* push the buffer, and verify it does *not* make it through */
+  gst_harness_push (h, buf);
+  fail_unless_equals_int (0, gst_harness_buffers_in_queue (h));
+
+  /* verify the clocksync element has registered exactly one GstClockID */
+  fail_unless (gst_harness_wait_for_clock_id_waits (h, 1, 42));
+
+  /* crank the clock and pull the buffer */
+  gst_harness_crank_single_clock_wait (h);
+  buf = gst_harness_pull (h);
+
+  /* verify that the buffer has the right timestamp, and that the time on
+     the clock is equal to the timestamp */
+  fail_unless_equals_int64 (timestamp, GST_BUFFER_PTS (buf));
+  clock = gst_element_get_clock (h->element);
+  /* this buffer must be pushed without clock waiting */
+  fail_unless_equals_int64 (gst_clock_get_time (clock), 0);
+  fail_unless_equals_int (data.notify_count, 1);
+  fail_unless_equals_int64 (data.ts_offset, -timestamp);
+
+  /* cleanup */
+  gst_object_unref (clock);
+  gst_buffer_unref (buf);
+  gst_harness_teardown (h);
+}
+
+GST_END_TEST;
+
 static Suite *
 clocksync_suite (void)
 {
@@ -223,10 +246,10 @@ clocksync_suite (void)
 
   suite_add_tcase (s, tc_chain);
   tcase_add_test (tc_chain, test_one_buffer);
-  tcase_add_test (tc_chain, test_signal_handoffs);
   tcase_add_test (tc_chain, test_sync_on_timestamp);
   tcase_add_test (tc_chain, test_stopping_element_unschedules_sync);
   tcase_add_test (tc_chain, test_no_sync_on_timestamp);
+  tcase_add_test (tc_chain, test_sync_to_first);
 
 
   return s;
index 43054dc..a205771 100644 (file)
@@ -120,13 +120,13 @@ GST_START_TEST (test_concat_simple_time)
   concat = gst_element_factory_make ("concat", NULL);
   fail_unless (concat != NULL);
 
-  sink1 = gst_element_get_request_pad (concat, "sink_%u");
+  sink1 = gst_element_request_pad_simple (concat, "sink_%u");
   fail_unless (sink1 != NULL);
 
-  sink2 = gst_element_get_request_pad (concat, "sink_%u");
+  sink2 = gst_element_request_pad_simple (concat, "sink_%u");
   fail_unless (sink2 != NULL);
 
-  sink3 = gst_element_get_request_pad (concat, "sink_%u");
+  sink3 = gst_element_request_pad_simple (concat, "sink_%u");
   fail_unless (sink3 != NULL);
 
   src = gst_element_get_static_pad (concat, "src");
@@ -242,13 +242,13 @@ GST_START_TEST (test_concat_simple_bytes)
   concat = gst_element_factory_make ("concat", NULL);
   fail_unless (concat != NULL);
 
-  sink1 = gst_element_get_request_pad (concat, "sink_%u");
+  sink1 = gst_element_request_pad_simple (concat, "sink_%u");
   fail_unless (sink1 != NULL);
 
-  sink2 = gst_element_get_request_pad (concat, "sink_%u");
+  sink2 = gst_element_request_pad_simple (concat, "sink_%u");
   fail_unless (sink2 != NULL);
 
-  sink3 = gst_element_get_request_pad (concat, "sink_%u");
+  sink3 = gst_element_request_pad_simple (concat, "sink_%u");
   fail_unless (sink3 != NULL);
 
   src = gst_element_get_static_pad (concat, "src");
index decbe61..6404862 100644 (file)
@@ -21,7 +21,7 @@
 #include "config.h"
 #endif
 
-#include <gst/check/gstcheck.h>
+#include <gst/check/check.h>
 
 /* sine wave encoded in ogg/vorbis, created with:
  *   gst-launch-1.0 audiotestsrc num-buffers=110 ! audioconvert ! \
@@ -488,9 +488,7 @@ GST_START_TEST (test_dataurisrc_uri_iface)
       GST_URI_SRC);
   protocols = gst_uri_handler_get_protocols (GST_URI_HANDLER (src));
   fail_unless (protocols != NULL && *protocols != NULL);
-#if GLIB_CHECK_VERSION (2, 44, 0)
   fail_unless (g_strv_contains (protocols, "data"));
-#endif
   fail_if (gst_uri_handler_set_uri (GST_URI_HANDLER (src), "file:///foo",
           NULL));
   fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (src), data_uri, NULL));
@@ -519,6 +517,59 @@ GST_START_TEST (test_dataurisrc_from_uri)
 
 GST_END_TEST;
 
+GST_START_TEST (test_dataurisrc_uris)
+{
+#define STRING_CONTENT(s) s, sizeof(s) - 1
+  static const struct
+  {
+    const char *name;
+    const char *uri;
+    const char *mimetype;
+    const char *contents;
+    gsize contents_len;
+  } tests[] = {
+    /* *INDENT-OFF* */
+    {"simple", "data:,HelloWorld", NULL, STRING_CONTENT ("HelloWorld")},
+    {"nodata", "data:,", NULL, STRING_CONTENT ("")},
+    {"case_sensitive", "dATa:,HelloWorld", NULL, STRING_CONTENT ("HelloWorld")},
+    {"semicolon_after_comma", "data:,;base64", NULL,
+        STRING_CONTENT (";base64")},
+    {"mimetype", "data:image/png,nopng", "image/png", STRING_CONTENT ("nopng")},
+    {"charset_base64",
+          "data:text/plain;charset=ISO-8859-5;base64,wOPh29DdILjW0ePb0OLe0g==",
+        "text/plain", STRING_CONTENT ("Руслан Ижбулатов")},
+    /* *INDENT-ON* */
+  };
+  gint i;
+#undef STRING_CONTENT
+
+  for (i = 0; i < G_N_ELEMENTS (tests); i++) {
+    GstHarness *h;
+    GstElement *src;
+    GstBuffer *buf;
+
+    src = gst_element_factory_make ("dataurisrc", NULL);
+    g_object_set (src, "uri", tests[i].uri, NULL);
+    h = gst_harness_new_with_element (src, NULL, "src");
+    gst_harness_play (h);
+
+    fail_unless (gst_harness_pull_until_eos (h, &buf));
+
+    if (tests[i].contents_len == 0) {
+      fail_unless (buf == NULL);
+    } else {
+      fail_unless (buf);
+      gst_check_buffer_data (buf, tests[i].contents, tests[i].contents_len);
+      gst_buffer_unref (buf);
+    }
+
+    gst_harness_teardown (h);
+    gst_object_unref (src);
+  }
+}
+
+GST_END_TEST;
+
 static Suite *
 dataurisrc_suite (void)
 {
@@ -531,6 +582,7 @@ dataurisrc_suite (void)
   tcase_add_test (tc_chain, test_dataurisrc_push);
   tcase_add_test (tc_chain, test_dataurisrc_uri_iface);
   tcase_add_test (tc_chain, test_dataurisrc_from_uri);
+  tcase_add_test (tc_chain, test_dataurisrc_uris);
 
   return s;
 }
index 2d221fc..d88628e 100644 (file)
@@ -44,11 +44,11 @@ setup_test_objects (struct TestData *td, GstPadChainFunction chain_func)
   td->funnelsrc = gst_element_get_static_pad (td->funnel, "src");
   fail_unless (td->funnelsrc != NULL);
 
-  td->funnelsink11 = gst_element_get_request_pad (td->funnel, "sink_11");
+  td->funnelsink11 = gst_element_request_pad_simple (td->funnel, "sink_11");
   fail_unless (td->funnelsink11 != NULL);
   fail_unless (!strcmp (GST_OBJECT_NAME (td->funnelsink11), "sink_11"));
 
-  td->funnelsink22 = gst_element_get_request_pad (td->funnel, "sink_22");
+  td->funnelsink22 = gst_element_request_pad_simple (td->funnel, "sink_22");
   fail_unless (td->funnelsink22 != NULL);
   fail_unless (!strcmp (GST_OBJECT_NAME (td->funnelsink22), "sink_22"));
 
@@ -197,7 +197,7 @@ GST_START_TEST (test_funnel_eos)
   gst_object_unref (td.funnelsink11);
   fail_unless (num_eos == 2);
 
-  td.funnelsink11 = gst_element_get_request_pad (td.funnel, "sink_11");
+  td.funnelsink11 = gst_element_request_pad_simple (td.funnel, "sink_11");
   fail_unless (td.funnelsink11 != NULL);
   fail_unless (!strcmp (GST_OBJECT_NAME (td.funnelsink11), "sink_11"));
 
@@ -214,7 +214,7 @@ GST_START_TEST (test_funnel_eos)
   fail_unless (num_eos == 2);
 
   /* send only eos to check, it handles empty streams */
-  td.funnelsink11 = gst_element_get_request_pad (td.funnel, "sink_11");
+  td.funnelsink11 = gst_element_request_pad_simple (td.funnel, "sink_11");
   fail_unless (td.funnelsink11 != NULL);
   fail_unless (!strcmp (GST_OBJECT_NAME (td.funnelsink11), "sink_11"));
 
@@ -235,7 +235,7 @@ GST_START_TEST (test_funnel_eos)
   gst_object_unref (td.funnelsink11);
   fail_unless (num_eos == 3);
 
-  td.funnelsink11 = gst_element_get_request_pad (td.funnel, "sink_11");
+  td.funnelsink11 = gst_element_request_pad_simple (td.funnel, "sink_11");
   fail_unless (td.funnelsink11 != NULL);
   fail_unless (!strcmp (GST_OBJECT_NAME (td.funnelsink11), "sink_11"));
 
diff --git a/tests/check/elements/leaks.c b/tests/check/elements/leaks.c
new file mode 100644 (file)
index 0000000..f1ef5dc
--- /dev/null
@@ -0,0 +1,528 @@
+/* GStreamer
+ *
+ * Unit test for leakstracer
+ *
+ * Copyright (C) <2019> Nirbheek Chauhan <nirbheek@centricular.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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/check/gstcheck.h>
+
+#define PROBE_TYPE GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BLOCK
+
+#define NUM_BUFFERS 2
+
+struct RetBufferCtx
+{
+  GstBuffer *bufs[NUM_BUFFERS];
+  guint idx;
+};
+
+static void
+ret_buffer_ctx_free (struct RetBufferCtx *ctx, gboolean free_bufs)
+{
+  guint ii;
+  if (free_bufs)
+    for (ii = 0; ii < ctx->idx; ii++)
+      gst_buffer_unref (ctx->bufs[ii]);
+  g_free (ctx);
+}
+
+static GstPadProbeReturn
+ref_buffer (GstPad * srcpad, GstPadProbeInfo * info, gpointer user_data)
+{
+  GstBuffer *buffer;
+  struct RetBufferCtx *ctx = user_data;
+
+  if (!(GST_PAD_PROBE_INFO_TYPE (info) & GST_PAD_PROBE_TYPE_BUFFER))
+    return GST_PAD_PROBE_PASS;
+
+  buffer = GST_PAD_PROBE_INFO_BUFFER (info);
+  /* ref buffer so it leaks */
+  gst_buffer_ref (buffer);
+
+  if (ctx) {
+    /* we can only store NUM_BUFFERS buffers */
+    fail_unless (ctx->idx < NUM_BUFFERS);
+    /* return the buffer so it can be freed later to avoid triggering valgrind
+     * in gst-validate */
+    ctx->bufs[ctx->idx] = buffer;
+    ctx->idx++;
+  }
+
+  return GST_PAD_PROBE_PASS;
+}
+
+static GstTracer *
+get_tracer_by_name (const gchar * name)
+{
+  GList *tracers, *l;
+  GstTracer *tracer = NULL;
+
+  tracers = gst_tracing_get_active_tracers ();
+  for (l = tracers; l; l = l->next)
+    if (g_strcmp0 (GST_OBJECT_NAME (l->data), name) == 0)
+      tracer = l->data;
+
+  g_list_free (tracers);
+  return tracer;
+}
+
+/* Test logging of live objects to debug logs */
+GST_START_TEST (test_log_live_objects)
+{
+  GstElement *pipe, *src, *sink;
+  GstPad *srcpad;
+  GstMessage *m;
+  struct RetBufferCtx *ctx = g_new0 (struct RetBufferCtx, 1);
+
+  pipe = gst_pipeline_new ("pipeline");
+  fail_unless (pipe);
+  src = gst_element_factory_make ("fakesrc", NULL);
+  fail_unless (src);
+  g_object_set (src, "num-buffers", NUM_BUFFERS, NULL);
+
+  sink = gst_element_factory_make ("fakesink", NULL);
+  fail_unless (sink);
+
+  gst_bin_add_many (GST_BIN (pipe), src, sink, NULL);
+  fail_unless (gst_element_link (src, sink));
+
+  srcpad = gst_element_get_static_pad (src, "src");
+  gst_pad_add_probe (srcpad, PROBE_TYPE, ref_buffer, ctx, NULL);
+  gst_object_unref (srcpad);
+
+  GST_DEBUG ("Setting pipeline to PLAYING");
+  fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PLAYING),
+      GST_STATE_CHANGE_ASYNC);
+
+  m = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), -1, GST_MESSAGE_EOS);
+  gst_message_unref (m);
+
+  fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_NULL),
+      GST_STATE_CHANGE_SUCCESS);
+  gst_object_unref (pipe);
+
+  /* Check the live-objects data returned by the tracer */
+  {
+    GstTracer *tracer = get_tracer_by_name ("plain");
+    fail_unless (tracer);
+    g_signal_emit_by_name (tracer, "log-live-objects");
+    gst_object_unref (tracer);
+  }
+
+  ret_buffer_ctx_free (ctx, TRUE);
+}
+
+GST_END_TEST;
+
+/* Test fetching of live objects with no detail */
+GST_START_TEST (test_get_live_objects)
+{
+  GstElement *pipe, *src, *sink;
+  GstPad *srcpad;
+  GstMessage *m;
+  struct RetBufferCtx *ctx = g_new0 (struct RetBufferCtx, 1);
+
+  pipe = gst_pipeline_new ("pipeline");
+  fail_unless (pipe);
+  src = gst_element_factory_make ("fakesrc", NULL);
+  fail_unless (src);
+  g_object_set (src, "num-buffers", NUM_BUFFERS, NULL);
+
+  sink = gst_element_factory_make ("fakesink", NULL);
+  fail_unless (sink);
+
+  gst_bin_add_many (GST_BIN (pipe), src, sink, NULL);
+  fail_unless (gst_element_link (src, sink));
+
+  srcpad = gst_element_get_static_pad (src, "src");
+  gst_pad_add_probe (srcpad, PROBE_TYPE, ref_buffer, ctx, NULL);
+  gst_object_unref (srcpad);
+
+  GST_DEBUG ("Setting pipeline to PLAYING");
+  fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PLAYING),
+      GST_STATE_CHANGE_ASYNC);
+
+  m = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), -1, GST_MESSAGE_EOS);
+  gst_message_unref (m);
+
+  fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_NULL),
+      GST_STATE_CHANGE_SUCCESS);
+  gst_object_unref (pipe);
+
+  /* Force all leftover tasks to stop */
+  gst_task_cleanup_all ();
+
+  /* Check the live-objects data returned by the tracer */
+  {
+    guint ii, size;
+    GstStructure *info;
+    const GValue *leaks;
+    GstTracer *tracer = get_tracer_by_name ("plain");
+    fail_unless (tracer);
+    g_signal_emit_by_name (tracer, "get-live-objects", &info);
+    fail_unless_equals_int (gst_structure_n_fields (info), 1);
+    leaks = gst_structure_get_value (info, "live-objects-list");
+    fail_unless (G_VALUE_HOLDS (leaks, GST_TYPE_LIST));
+    size = gst_value_list_get_size (leaks);
+    fail_unless_equals_int (size, NUM_BUFFERS);
+    for (ii = 0; ii < size; ii++) {
+      const GValue *v;
+      const GstStructure *s;
+      guint ref_count;
+
+      v = gst_value_list_get_value (leaks, ii);
+      fail_unless (G_VALUE_HOLDS (v, GST_TYPE_STRUCTURE));
+
+      s = gst_value_get_structure (v);
+      fail_unless (gst_structure_has_field_typed (s, "object",
+              GST_TYPE_BUFFER));
+
+      fail_unless (gst_structure_has_field_typed (s, "ref-count", G_TYPE_UINT));
+      fail_unless (gst_structure_get_uint (s, "ref-count", &ref_count));
+      fail_unless_equals_int (ref_count, 1);
+
+      fail_unless (gst_structure_has_field_typed (s, "trace", G_TYPE_STRING));
+      fail_unless_equals_string (gst_structure_get_string (s, "trace"), NULL);
+
+      fail_unless (!gst_structure_has_field (s, "ref-infos"));
+      fail_unless_equals_int (gst_structure_n_fields (s), 3);
+    }
+    gst_structure_free (info);
+    gst_object_unref (tracer);
+  }
+
+  /* leaked buffers were freed above with @info */
+  ret_buffer_ctx_free (ctx, FALSE);
+}
+
+GST_END_TEST;
+
+/* Test fetching of filtered live objects with full detail */
+GST_START_TEST (test_get_live_objects_filtered_detailed)
+{
+  GstElement *pipe, *src, *sink;
+  GstPad *srcpad;
+  GstMessage *m;
+  struct RetBufferCtx *ctx = g_new0 (struct RetBufferCtx, 1);
+  gboolean check_trace = FALSE;
+
+#if defined (HAVE_BACKTRACE) || defined (HAVE_UNWIND) || defined (HAVE_DBGHELP)
+  /* Otherwise, trace string (returned from gst_debug_get_stack_trace())
+   * will be null */
+  check_trace = TRUE;
+#endif
+
+  pipe = gst_pipeline_new ("pipeline");
+  fail_unless (pipe);
+  src = gst_element_factory_make ("fakesrc", NULL);
+  fail_unless (src);
+  g_object_set (src, "num-buffers", NUM_BUFFERS, NULL);
+
+  sink = gst_element_factory_make ("fakesink", NULL);
+  fail_unless (sink);
+
+  gst_bin_add_many (GST_BIN (pipe), src, sink, NULL);
+  fail_unless (gst_element_link (src, sink));
+
+  srcpad = gst_element_get_static_pad (src, "src");
+  gst_pad_add_probe (srcpad, PROBE_TYPE, ref_buffer, ctx, NULL);
+  /* leak srcpad on purpose */
+  gst_element_get_static_pad (sink, "sink");
+  /* leak sinkpad on purpose */
+
+  GST_DEBUG ("Setting pipeline to PLAYING");
+  fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PLAYING),
+      GST_STATE_CHANGE_ASYNC);
+
+  m = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), -1, GST_MESSAGE_EOS);
+  gst_message_unref (m);
+
+  fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_NULL),
+      GST_STATE_CHANGE_SUCCESS);
+  gst_object_unref (pipe);
+
+  /* Force all leftover tasks to stop */
+  gst_task_cleanup_all ();
+
+  /* Check the live-objects data returned by the tracer */
+  {
+    guint ii, jj, isize, jsize;
+    GstStructure *info;
+    const GValue *leaks;
+    GstTracer *tracer = get_tracer_by_name ("more");
+    fail_unless (tracer);
+    g_signal_emit_by_name (tracer, "get-live-objects", &info);
+    fail_unless_equals_int (gst_structure_n_fields (info), 1);
+    leaks = gst_structure_get_value (info, "live-objects-list");
+    fail_unless (G_VALUE_HOLDS (leaks, GST_TYPE_LIST));
+    isize = gst_value_list_get_size (leaks);
+    fail_unless_equals_int (isize, NUM_BUFFERS);
+    for (ii = 0; ii < isize; ii++) {
+      const GValue *v;
+      const GstStructure *s;
+      guint ref_count;
+
+      v = gst_value_list_get_value (leaks, ii);
+      fail_unless (G_VALUE_HOLDS (v, GST_TYPE_STRUCTURE));
+
+      s = gst_value_get_structure (v);
+      fail_unless (gst_structure_has_field_typed (s, "object", GST_TYPE_PAD));
+
+      fail_unless (gst_structure_has_field_typed (s, "ref-count", G_TYPE_UINT));
+      fail_unless (gst_structure_get_uint (s, "ref-count", &ref_count));
+      fail_unless_equals_int (ref_count, 1);
+
+      fail_unless (gst_structure_has_field_typed (s, "trace", G_TYPE_STRING));
+      if (check_trace)
+        fail_unless (gst_structure_get_string (s, "trace"));
+
+      fail_unless (gst_structure_has_field_typed (s, "ref-infos",
+              GST_TYPE_LIST));
+      fail_unless_equals_int (gst_structure_n_fields (s), 4);
+
+      v = gst_structure_get_value (s, "ref-infos");
+      jsize = gst_value_list_get_size (v);
+      for (jj = 0; jj < jsize; jj++) {
+        const GValue *rv;
+        const GstStructure *r;
+
+        rv = gst_value_list_get_value (v, jj);
+        fail_unless (G_VALUE_HOLDS (rv, GST_TYPE_STRUCTURE));
+
+        r = gst_value_get_structure (rv);
+        fail_unless (gst_structure_has_field_typed (r, "ts",
+                GST_TYPE_CLOCK_TIME));
+
+        fail_unless (gst_structure_has_field_typed (r, "desc", G_TYPE_STRING));
+        fail_unless (gst_structure_get_string (r, "desc"));
+
+        fail_unless (gst_structure_get_uint (r, "ref-count", &ref_count));
+        fail_unless (ref_count > 0);
+
+        fail_unless (gst_structure_has_field_typed (r, "trace", G_TYPE_STRING));
+        if (check_trace)
+          fail_unless (gst_structure_get_string (r, "trace"));
+
+        fail_unless_equals_int (gst_structure_n_fields (r), 4);
+      }
+    }
+    gst_structure_free (info);
+    gst_object_unref (tracer);
+  }
+
+  ret_buffer_ctx_free (ctx, TRUE);
+  /* leaked pads were freed above with @info */
+}
+
+GST_END_TEST;
+
+/* Just start and stop tracking without any checkpoints */
+GST_START_TEST (test_activity_start_stop)
+{
+  GstElement *pipe, *src, *sink;
+  GstMessage *m;
+  GstTracer *tracer = get_tracer_by_name ("plain");
+
+  fail_unless (tracer);
+
+  g_signal_emit_by_name (tracer, "activity-start-tracking");
+
+  pipe = gst_pipeline_new ("pipeline");
+  fail_unless (pipe);
+  src = gst_element_factory_make ("fakesrc", NULL);
+  fail_unless (src);
+  g_object_set (src, "num-buffers", NUM_BUFFERS, NULL);
+
+  sink = gst_element_factory_make ("fakesink", NULL);
+  fail_unless (sink);
+
+  gst_bin_add_many (GST_BIN (pipe), src, sink, NULL);
+  fail_unless (gst_element_link (src, sink));
+
+  GST_DEBUG ("Setting pipeline to PLAYING");
+  fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PLAYING),
+      GST_STATE_CHANGE_ASYNC);
+
+  m = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), -1, GST_MESSAGE_EOS);
+  gst_message_unref (m);
+
+  fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_NULL),
+      GST_STATE_CHANGE_SUCCESS);
+  gst_object_unref (pipe);
+
+  g_signal_emit_by_name (tracer, "activity-stop-tracking");
+  gst_object_unref (tracer);
+}
+
+GST_END_TEST;
+
+/* Track objects, and checkpoint twice */
+GST_START_TEST (test_activity_log_checkpoint)
+{
+  GstElement *pipe, *src, *sink;
+  GstMessage *m;
+  GstTracer *tracer = get_tracer_by_name ("plain");
+
+  fail_unless (tracer);
+
+  g_signal_emit_by_name (tracer, "activity-start-tracking");
+
+  pipe = gst_pipeline_new ("pipeline");
+  fail_unless (pipe);
+  src = gst_element_factory_make ("fakesrc", NULL);
+  fail_unless (src);
+  g_object_set (src, "num-buffers", NUM_BUFFERS, NULL);
+
+  sink = gst_element_factory_make ("fakesink", NULL);
+  fail_unless (sink);
+
+  gst_bin_add_many (GST_BIN (pipe), src, sink, NULL);
+  fail_unless (gst_element_link (src, sink));
+
+  g_signal_emit_by_name (tracer, "activity-log-checkpoint");
+
+  GST_DEBUG ("Setting pipeline to PLAYING");
+  fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PLAYING),
+      GST_STATE_CHANGE_ASYNC);
+
+  m = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), -1, GST_MESSAGE_EOS);
+  gst_message_unref (m);
+
+  fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_NULL),
+      GST_STATE_CHANGE_SUCCESS);
+  gst_object_unref (pipe);
+
+  g_signal_emit_by_name (tracer, "activity-log-checkpoint");
+  g_signal_emit_by_name (tracer, "activity-stop-tracking");
+  gst_object_unref (tracer);
+}
+
+GST_END_TEST;
+
+/* Track objects, checkpoint once, and assert the format of the data */
+GST_START_TEST (test_activity_get_checkpoint)
+{
+  GstElement *pipe, *src, *sink;
+  GstMessage *m;
+  GstTracer *tracer = get_tracer_by_name ("more");
+
+  fail_unless (tracer);
+
+  g_signal_emit_by_name (tracer, "activity-start-tracking");
+
+  pipe = gst_pipeline_new ("pipeline");
+  fail_unless (pipe);
+  src = gst_element_factory_make ("fakesrc", NULL);
+  fail_unless (src);
+  g_object_set (src, "num-buffers", NUM_BUFFERS, NULL);
+
+  sink = gst_element_factory_make ("fakesink", NULL);
+  fail_unless (sink);
+
+  gst_bin_add_many (GST_BIN (pipe), src, sink, NULL);
+  fail_unless (gst_element_link (src, sink));
+
+  GST_DEBUG ("Setting pipeline to PLAYING");
+  fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PLAYING),
+      GST_STATE_CHANGE_ASYNC);
+
+  m = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), -1, GST_MESSAGE_EOS);
+  gst_message_unref (m);
+
+  fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_NULL),
+      GST_STATE_CHANGE_SUCCESS);
+  gst_object_unref (pipe);
+
+  /* Force all leftover tasks to stop */
+  gst_task_cleanup_all ();
+
+  {
+    GstStructure *cpoint;
+    const GstStructure *cs, *rs;
+    const GValue *created, *removed;
+
+    g_signal_emit_by_name (tracer, "activity-get-checkpoint", &cpoint);
+    fail_unless_equals_int (gst_structure_n_fields (cpoint), 2);
+
+    created = gst_structure_get_value (cpoint, "objects-created-list");
+    fail_unless (G_VALUE_HOLDS (created, GST_TYPE_LIST));
+    created = gst_value_list_get_value (created, 0);
+    fail_unless (G_VALUE_HOLDS (created, GST_TYPE_STRUCTURE));
+    cs = gst_value_get_structure (created);
+    fail_unless (gst_structure_has_field_typed (cs, "type-name",
+            G_TYPE_STRING));
+    fail_unless (gst_structure_get_string (cs, "type-name"));
+    fail_unless (gst_structure_has_field_typed (cs, "address", G_TYPE_STRING));
+    fail_unless (gst_structure_get_string (cs, "address"));
+
+    removed = gst_structure_get_value (cpoint, "objects-removed-list");
+    fail_unless (G_VALUE_HOLDS (removed, GST_TYPE_LIST));
+    removed = gst_value_list_get_value (removed, 0);
+    fail_unless (G_VALUE_HOLDS (removed, GST_TYPE_STRUCTURE));
+    rs = gst_value_get_structure (removed);
+    fail_unless (gst_structure_has_field_typed (rs, "type-name",
+            G_TYPE_STRING));
+    fail_unless (gst_structure_get_string (rs, "type-name"));
+    fail_unless (gst_structure_has_field_typed (rs, "address", G_TYPE_STRING));
+    fail_unless (gst_structure_get_string (rs, "address"));
+    gst_structure_free (cpoint);
+  }
+  g_signal_emit_by_name (tracer, "activity-stop-tracking");
+  gst_object_unref (tracer);
+}
+
+GST_END_TEST;
+
+static Suite *
+leakstracer_suite (void)
+{
+  Suite *s = suite_create ("leakstracer");
+  TCase *tc_chain_1 = tcase_create ("live-objects");
+  TCase *tc_chain_2 = tcase_create ("activity-tracking");
+
+  suite_add_tcase (s, tc_chain_1);
+  tcase_add_test (tc_chain_1, test_log_live_objects);
+  tcase_add_test (tc_chain_1, test_get_live_objects);
+  tcase_add_test (tc_chain_1, test_get_live_objects_filtered_detailed);
+
+  suite_add_tcase (s, tc_chain_2);
+  tcase_add_test (tc_chain_2, test_activity_start_stop);
+  tcase_add_test (tc_chain_2, test_activity_log_checkpoint);
+  tcase_add_test (tc_chain_2, test_activity_get_checkpoint);
+
+  return s;
+}
+
+/* Replacement for GST_CHECK_MAIN (leakstracer); because we need to set the
+ * env before gst_init() is called */
+int
+main (int argc, char **argv)
+{
+  Suite *s;
+  g_setenv ("GST_TRACERS", "leaks(name=plain,log-leaks-on-deinit=false);"
+      "leaks(name=more,filters=GstPad,check-refs=true,stack-traces-flags=none,log-leaks-on-deinit=false);",
+      TRUE);
+  gst_check_init (&argc, &argv);
+  s = leakstracer_suite ();
+  return gst_check_run_suite (s, "leakstracer", __FILE__);
+}
index 6ec638a..817afa4 100644 (file)
@@ -42,7 +42,7 @@ setup_multiqueue (GstElement * pipe, GstElement * inputs[],
     GstPad *srcpad = NULL;
 
     /* create multiqueue sink (and source) pad */
-    sinkpad = gst_element_get_request_pad (mq, "sink_%u");
+    sinkpad = gst_element_request_pad_simple (mq, "sink_%u");
     fail_unless (sinkpad != NULL,
         "failed to create multiqueue request pad #%u", i);
 
@@ -67,7 +67,7 @@ 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_%u");
+      srcpad = gst_element_request_pad_simple (mq, "src_%u");
       fail_unless (srcpad == NULL);
 
       g_snprintf (padname, sizeof (padname), "src_%u", i);
@@ -194,21 +194,21 @@ GST_START_TEST (test_request_pads)
 
   mq = gst_element_factory_make ("multiqueue", NULL);
 
-  sink1 = gst_element_get_request_pad (mq, "foo_%u");
+  sink1 = gst_element_request_pad_simple (mq, "foo_%u");
   fail_unless (sink1 == NULL,
       "Expected NULL pad, as there is no request pad template for 'foo_%%u'");
 
-  sink1 = gst_element_get_request_pad (mq, "src_%u");
+  sink1 = gst_element_request_pad_simple (mq, "src_%u");
   fail_unless (sink1 == NULL,
       "Expected NULL pad, as there is no request pad template for 'src_%%u'");
 
-  sink1 = gst_element_get_request_pad (mq, "sink_%u");
+  sink1 = gst_element_request_pad_simple (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_%u");
+  sink2 = gst_element_request_pad_simple (mq, "sink_%u");
   fail_unless (sink2 != NULL);
   fail_unless (GST_IS_PAD (sink2));
   fail_unless (GST_PAD_IS_SINK (sink2));
@@ -251,21 +251,21 @@ GST_START_TEST (test_request_pads_named)
 
   mq = gst_element_factory_make ("multiqueue", NULL);
 
-  sink1 = gst_element_get_request_pad (mq, "sink_1");
+  sink1 = gst_element_request_pad_simple (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), "sink_1");
   GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink1));
 
-  sink3 = gst_element_get_request_pad (mq, "sink_3");
+  sink3 = gst_element_request_pad_simple (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), "sink_3");
   GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink3));
 
-  sink2 = gst_element_get_request_pad (mq, "sink_2");
+  sink2 = gst_element_request_pad_simple (mq, "sink_2");
   fail_unless (sink2 != NULL);
   fail_unless (GST_IS_PAD (sink2));
   fail_unless (GST_PAD_IS_SINK (sink2));
@@ -273,7 +273,7 @@ GST_START_TEST (test_request_pads_named)
   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_%u");
+  sink4 = gst_element_request_pad_simple (mq, "sink_%u");
   fail_unless (sink4 != NULL);
   fail_unless (GST_IS_PAD (sink4));
   fail_unless (GST_PAD_IS_SINK (sink4));
@@ -431,7 +431,7 @@ construct_n_pads (GstElement * mq, struct PadData *pad_data, gint n_pads,
     g_free (name);
     gst_pad_set_query_function (inpad, mq_dummypad_query);
 
-    mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u");
+    mq_sinkpad = gst_element_request_pad_simple (mq, "sink_%u");
     fail_unless (mq_sinkpad != NULL);
     fail_unless (gst_pad_link (inpad, mq_sinkpad) == GST_PAD_LINK_OK);
 
@@ -749,7 +749,7 @@ GST_START_TEST (test_sparse_stream)
     g_free (name);
     gst_pad_set_query_function (inputpads[i], mq_dummypad_query);
 
-    mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u");
+    mq_sinkpad = gst_element_request_pad_simple (mq, "sink_%u");
     fail_unless (mq_sinkpad != NULL);
     fail_unless (gst_pad_link (inputpads[i], mq_sinkpad) == GST_PAD_LINK_OK);
 
@@ -950,7 +950,7 @@ GST_START_TEST (test_initial_fill_above_high_threshold)
   inputpad = gst_pad_new ("dummysrc", GST_PAD_SRC);
   gst_pad_set_query_function (inputpad, mq_dummypad_query);
 
-  mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u");
+  mq_sinkpad = gst_element_request_pad_simple (mq, "sink_%u");
   fail_unless (mq_sinkpad != NULL);
   fail_unless (gst_pad_link (inputpad, mq_sinkpad) == GST_PAD_LINK_OK);
 
@@ -1038,7 +1038,7 @@ GST_START_TEST (test_watermark_and_fill_level)
   inputpad = gst_pad_new ("dummysrc", GST_PAD_SRC);
   gst_pad_set_query_function (inputpad, mq_dummypad_query);
 
-  mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u");
+  mq_sinkpad = gst_element_request_pad_simple (mq, "sink_%u");
   fail_unless (mq_sinkpad != NULL);
   fail_unless (gst_pad_link (inputpad, mq_sinkpad) == GST_PAD_LINK_OK);
 
@@ -1136,7 +1136,7 @@ GST_START_TEST (test_high_threshold_change)
   inputpad = gst_pad_new ("dummysrc", GST_PAD_SRC);
   gst_pad_set_query_function (inputpad, mq_dummypad_query);
 
-  mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u");
+  mq_sinkpad = gst_element_request_pad_simple (mq, "sink_%u");
   fail_unless (mq_sinkpad != NULL);
   fail_unless (gst_pad_link (inputpad, mq_sinkpad) == GST_PAD_LINK_OK);
 
@@ -1231,7 +1231,7 @@ GST_START_TEST (test_low_threshold_change)
   inputpad = gst_pad_new ("dummysrc", GST_PAD_SRC);
   gst_pad_set_query_function (inputpad, mq_dummypad_query);
 
-  mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u");
+  mq_sinkpad = gst_element_request_pad_simple (mq, "sink_%u");
   fail_unless (mq_sinkpad != NULL);
   fail_unless (gst_pad_link (inputpad, mq_sinkpad) == GST_PAD_LINK_OK);
 
@@ -1319,7 +1319,7 @@ GST_START_TEST (test_limit_changes)
   inputpad = gst_pad_new ("dummysrc", GST_PAD_SRC);
   gst_pad_set_query_function (inputpad, mq_dummypad_query);
 
-  mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u");
+  mq_sinkpad = gst_element_request_pad_simple (mq, "sink_%u");
   fail_unless (mq_sinkpad != NULL);
   fail_unless (gst_pad_link (inputpad, mq_sinkpad) == GST_PAD_LINK_OK);
 
@@ -1440,7 +1440,7 @@ GST_START_TEST (test_buffering_with_none_pts)
   outputpad = gst_pad_new ("dummysink", GST_PAD_SINK);
   gst_pad_set_chain_function (outputpad, pad_chain_block);
   gst_pad_set_event_function (outputpad, pad_event_always_ok);
-  mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u");
+  mq_sinkpad = gst_element_request_pad_simple (mq, "sink_%u");
   mq_srcpad = gst_element_get_static_pad (mq, "src_0");
   fail_unless (mq_sinkpad != NULL);
   fail_unless (gst_pad_link (inputpad, mq_sinkpad) == GST_PAD_LINK_OK);
@@ -1536,7 +1536,7 @@ GST_START_TEST (test_initial_events_nodelay)
 
     inputpad = gst_pad_new ("dummysrc", GST_PAD_SRC);
 
-    mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u");
+    mq_sinkpad = gst_element_request_pad_simple (mq, "sink_%u");
     fail_unless (mq_sinkpad != NULL);
     fail_unless (gst_pad_link (inputpad, mq_sinkpad) == GST_PAD_LINK_OK);
 
@@ -1641,7 +1641,7 @@ GST_START_TEST (test_stream_status_messages)
 
   gst_bin_add (GST_BIN (pipe), mq);
 
-  pad = gst_element_get_request_pad (mq, "sink_%u");
+  pad = gst_element_request_pad_simple (mq, "sink_%u");
   gst_object_unref (pad);
 
   gst_element_set_state (pipe, GST_STATE_PAUSED);
@@ -1649,7 +1649,7 @@ GST_START_TEST (test_stream_status_messages)
   check_for_stream_status_msg (pipe, mq, GST_STREAM_STATUS_TYPE_CREATE);
   check_for_stream_status_msg (pipe, mq, GST_STREAM_STATUS_TYPE_ENTER);
 
-  pad = gst_element_get_request_pad (mq, "sink_%u");
+  pad = gst_element_request_pad_simple (mq, "sink_%u");
   gst_object_unref (pad);
 
   check_for_stream_status_msg (pipe, mq, GST_STREAM_STATUS_TYPE_CREATE);
index a41ef64..9663a68 100644 (file)
@@ -183,7 +183,7 @@ setup_sink_pad (GstElement * element, GstStaticPadTemplate * tmpl)
 
 /* set queue size to 2 buffers
  * pull 1 buffer
- * check over/underuns
+ * check over/underruns
  */
 GST_START_TEST (test_non_leaky_underrun)
 {
@@ -225,9 +225,9 @@ queue_overrun_link_and_activate (GstElement * queue, gpointer user_data)
 
 /* set queue size to 2 buffers
  * push 2 buffers
- * check over/underuns
+ * check over/underruns
  * push 1 more buffer
- * check over/underuns again
+ * check over/underruns again
  */
 GST_START_TEST (test_non_leaky_overrun)
 {
@@ -320,9 +320,9 @@ GST_END_TEST;
 
 /* set queue size to 2 buffers
  * push 2 buffers
- * check over/underuns
+ * check over/underruns
  * push 1 more buffer
- * check over/underuns again
+ * check over/underruns again
  * check which buffer was leaked
  */
 GST_START_TEST (test_leaky_upstream)
@@ -409,9 +409,9 @@ GST_END_TEST;
 
 /* set queue size to 2 buffers
  * push 2 buffers
- * check over/underuns
+ * check over/underruns
  * push 1 more buffer
- * check over/underuns again
+ * check over/underruns again
  * check which buffer was leaked
  */
 GST_START_TEST (test_leaky_downstream)
index 5941c5d..c27e973 100644 (file)
@@ -661,6 +661,60 @@ GST_START_TEST (test_bitrate_query)
 
 GST_END_TEST;
 
+GST_START_TEST (test_ready_paused_buffering_message)
+{
+  /* This test verifies that a buffering message is posted during the
+   * READY->PAUSED state change. */
+
+  GstElement *pipe;
+  GstElement *fakesrc, *queue2, *fakesink;
+
+  /* Set up simple test pipeline. */
+
+  pipe = gst_pipeline_new ("pipeline");
+
+  /* Set up the fakesrc to actually produce data. */
+  fakesrc = gst_element_factory_make ("fakesrc", NULL);
+  fail_unless (fakesrc != NULL);
+  g_object_set (G_OBJECT (fakesrc), "format", (gint) 3, "filltype", (gint) 2,
+      "sizetype", (gint) 2, "sizemax", (gint) 4096, "datarate", (gint) 4096,
+      NULL);
+
+  queue2 = gst_element_factory_make ("queue2", NULL);
+  fail_unless (queue2 != NULL);
+  /* Note that use-buffering is set _before_ the queue2 got added to pipe.
+   * This is intentional. queue2's set_property function attempts to post a
+   * buffering message. This fails silently, because without having been added
+   * to a bin, queue2 won't have been assigned a bus, so it cannot post that
+   * message anywhere. In such a case, the next attempt to post a buffering
+   * message must always actually be attempted. (Normally, queue2 performs
+   * internal checks to see whether or not the buffering message would be
+   * redundant because a prior message with the same percentage was already
+   * posted. But these checked only make sense if the previous posting attempt
+   * succeeded.) */
+  g_object_set (queue2, "use-buffering", (gboolean) TRUE, NULL);
+
+  fakesink = gst_element_factory_make ("fakesink", NULL);
+  fail_unless (fakesink != NULL);
+
+  gst_bin_add_many (GST_BIN (pipe), fakesrc, queue2, fakesink, NULL);
+  gst_element_link_many (fakesrc, queue2, fakesink, NULL);
+
+  /* Set the pipeline to PAUSED. This should cause queue2 to attempt to post
+   * a buffering message during its READY->PAUSED state change. And this should
+   * succeed, since queue2 has been added to pipe by now. */
+  gst_element_set_state (pipe, GST_STATE_PAUSED);
+  gst_element_get_state (pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
+
+  /* Look for the expected 0% buffering message. */
+  CHECK_FOR_BUFFERING_MSG (pipe, 0);
+
+  gst_element_set_state (pipe, GST_STATE_NULL);
+  gst_object_unref (pipe);
+}
+
+GST_END_TEST;
+
 static Suite *
 queue2_suite (void)
 {
@@ -678,6 +732,7 @@ queue2_suite (void)
   tcase_add_test (tc_chain, test_percent_overflow);
   tcase_add_test (tc_chain, test_small_ring_buffer);
   tcase_add_test (tc_chain, test_bitrate_query);
+  tcase_add_test (tc_chain, test_ready_paused_buffering_message);
 
   return s;
 }
index 0570f13..40102be 100644 (file)
@@ -85,7 +85,7 @@ setup_output_pad (GstElement * element, GstStaticPadTemplate * tmpl)
       GINT_TO_POINTER (probe_id));
 
   /* request src pad */
-  srcpad = gst_element_get_request_pad (element, "src_%u");
+  srcpad = gst_element_request_pad_simple (element, "src_%u");
   fail_if (srcpad == NULL, "Could not get source pad from %s",
       GST_ELEMENT_NAME (element));
 
@@ -303,7 +303,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_%u");
+  sinkpad = gst_element_request_pad_simple (element, "sink_%u");
   fail_if (sinkpad == NULL, "Could not get sink pad from %s",
       GST_ELEMENT_NAME (element));
 
@@ -500,10 +500,12 @@ input_selector_push_buffer (gint stream, enum InputSelectorResult res)
   }
 }
 
+/* Consumes a ref to the passed pad */
 static gpointer
 input_selector_do_push_eos (GstPad * pad)
 {
   gst_pad_push_event (pad, gst_event_new_eos ());
+  gst_object_unref (pad);
   return NULL;
 }
 
@@ -533,7 +535,7 @@ input_selector_push_eos (gint stream, gboolean active)
      * from a separate thread. This makes this test racy, but it should only
      * cause false positives, not false negatives */
     GThread *t = g_thread_new ("selector-test-push-eos",
-        (GThreadFunc) input_selector_do_push_eos, pad);
+        (GThreadFunc) input_selector_do_push_eos, gst_object_ref (pad));
 
     /* Sleep half a second to allow the other thread to execute, this is not
      * a definitive solution but there is no way to know when the
index acee40c..a19e73e 100644 (file)
@@ -76,7 +76,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_%u");
+    req_pads[i] = gst_element_request_pad_simple (tee, "src_%u");
     fail_unless (req_pads[i] != NULL);
 
     qpad = gst_element_get_static_pad (queues[i], "sink");
@@ -142,7 +142,7 @@ GST_START_TEST (test_stress)
   for (i = 0; i < 50000; i++) {
     GstPad *pad;
 
-    pad = gst_element_get_request_pad (tee, "src_%u");
+    pad = gst_element_request_pad_simple (tee, "src_%u");
     gst_element_release_request_pad (tee, pad);
     gst_object_unref (pad);
 
@@ -201,7 +201,7 @@ buffer_alloc_harness_setup (BufferAllocHarness * h, gint countdown)
   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_%u");
+  h->tee_srcpad = gst_element_request_pad_simple (h->tee, "src_%u");
   fail_if (h->tee_srcpad == NULL);
 
   h->final_sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
@@ -265,7 +265,7 @@ final_sinkpad_bufferalloc (GstPad * pad, guint64 offset, guint size,
     GstCaps * caps, GstBuffer ** buf)
 {
   BufferAllocHarness *h;
-  GTimeVal deadline;
+  gint64 deadline;
 
   h = g_object_get_qdata (G_OBJECT (pad),
       g_quark_from_static_string ("buffer-alloc-harness"));
@@ -288,10 +288,10 @@ final_sinkpad_bufferalloc (GstPad * pad, guint64 offset, guint size,
     /* Now wait for it to do that within a second, to avoid deadlocking
      * in the event of future changes to the locking semantics. */
     g_mutex_lock (&check_mutex);
-    g_get_current_time (&deadline);
-    deadline.tv_sec += 1;
+    deadline = g_get_monotonic_time ();
+    deadline += G_USEC_PER_SEC;
     while (h->bufferalloc_blocked) {
-      if (!g_cond_timed_wait (&check_cond, &check_mutex, &deadline))
+      if (!g_cond_wait_until (&check_cond, &check_mutex, deadline))
         break;
     }
     g_mutex_unlock (&check_mutex);
@@ -353,7 +353,7 @@ GST_START_TEST (test_internal_links)
   fail_unless (res == GST_ITERATOR_DONE);
   fail_unless (g_value_get_object (&val1) == NULL);
 
-  srcpad1 = gst_element_get_request_pad (tee, "src_%u");
+  srcpad1 = gst_element_request_pad_simple (tee, "src_%u");
   fail_unless (srcpad1 != NULL);
 
   /* iterator should resync */
@@ -373,7 +373,7 @@ GST_START_TEST (test_internal_links)
   fail_unless (res == GST_ITERATOR_DONE);
   fail_unless (g_value_get_object (&val1) == NULL);
 
-  srcpad2 = gst_element_get_request_pad (tee, "src_%u");
+  srcpad2 = gst_element_request_pad_simple (tee, "src_%u");
   fail_unless (srcpad2 != NULL);
 
   /* iterator should resync */
@@ -467,9 +467,9 @@ GST_START_TEST (test_flow_aggregation)
   fail_unless (tee != NULL);
   teesink = gst_element_get_static_pad (tee, "sink");
   fail_unless (teesink != NULL);
-  teesrc1 = gst_element_get_request_pad (tee, "src_%u");
+  teesrc1 = gst_element_request_pad_simple (tee, "src_%u");
   fail_unless (teesrc1 != NULL);
-  teesrc2 = gst_element_get_request_pad (tee, "src_%u");
+  teesrc2 = gst_element_request_pad_simple (tee, "src_%u");
   fail_unless (teesrc2 != NULL);
 
   GST_DEBUG ("Creating mysink1");
@@ -602,16 +602,16 @@ GST_START_TEST (test_request_pads)
 
   tee = gst_check_setup_element ("tee");
 
-  srcpad1 = gst_element_get_request_pad (tee, "src_%u");
+  srcpad1 = gst_element_request_pad_simple (tee, "src_%u");
   fail_unless (srcpad1 != NULL);
   fail_unless_equals_string (GST_OBJECT_NAME (srcpad1), "src_0");
-  srcpad2 = gst_element_get_request_pad (tee, "src_100");
+  srcpad2 = gst_element_request_pad_simple (tee, "src_100");
   fail_unless (srcpad2 != NULL);
   fail_unless_equals_string (GST_OBJECT_NAME (srcpad2), "src_100");
-  srcpad3 = gst_element_get_request_pad (tee, "src_10");
+  srcpad3 = gst_element_request_pad_simple (tee, "src_10");
   fail_unless (srcpad3 != NULL);
   fail_unless_equals_string (GST_OBJECT_NAME (srcpad3), "src_10");
-  srcpad4 = gst_element_get_request_pad (tee, "src_%u");
+  srcpad4 = gst_element_request_pad_simple (tee, "src_%u");
   fail_unless (srcpad4 != NULL);
 
   gst_object_unref (srcpad1);
@@ -661,11 +661,11 @@ GST_START_TEST (test_allow_not_linked)
 
   fail_unless (gst_pad_push (srcpad, gst_buffer_ref (buffer)) == GST_FLOW_OK);
 
-  src1 = gst_element_get_request_pad (tee, "src_%u");
+  src1 = gst_element_request_pad_simple (tee, "src_%u");
 
   fail_unless (gst_pad_push (srcpad, gst_buffer_ref (buffer)) == GST_FLOW_OK);
 
-  src2 = gst_element_get_request_pad (tee, "src_%u");
+  src2 = gst_element_request_pad_simple (tee, "src_%u");
 
   fail_unless (gst_pad_push (srcpad, gst_buffer_ref (buffer)) == GST_FLOW_OK);
 
@@ -680,8 +680,8 @@ GST_START_TEST (test_allow_not_linked)
           gst_buffer_ref (buffer)) == GST_FLOW_NOT_LINKED);
 
   gst_element_release_request_pad (tee, src2);
-  g_object_unref (src1);
-  g_object_unref (src2);
+  gst_object_unref (src1);
+  gst_object_unref (src2);
 
   fail_unless (gst_pad_push (srcpad,
           gst_buffer_ref (buffer)) == GST_FLOW_NOT_LINKED);
@@ -850,7 +850,7 @@ GST_START_TEST (test_allocation_query_allow_not_linked)
   add_sink_pad_and_setup_query_func (tee, allocation_query3);
   /* This unlinked pad is what will make a difference between having
    * allow-not-linked set or not */
-  srcpad = gst_element_get_request_pad (tee, "src_%u");
+  srcpad = gst_element_request_pad_simple (tee, "src_%u");
   caps = gst_caps_new_empty_simple ("test/test");
 
   /* Without allow-not-linked the query should fail */
diff --git a/tests/check/generic/.gitignore b/tests/check/generic/.gitignore
deleted file mode 100644 (file)
index 8ea4b31..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-.dirstamp
-sinks
-states
-*.check.xml
diff --git a/tests/check/gst/.gitignore b/tests/check/gst/.gitignore
deleted file mode 100644 (file)
index 4c86058..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-.dirstamp
-gst
-gstabi
-gstatomicqueue
-gstbin
-gstbuffer
-gstbufferlist
-gstbufferpool
-gstbus
-gstcaps
-gstcapsfeatures
-gstchildproxy
-gstclock
-gstcontroller
-gstcontext
-gstcpp
-gstcustombufferpool
-gstdata
-gstdatetime
-gstdeinit
-gstdevice
-gstelement
-gstelementfactory
-gstevent
-gstghostpad
-gstiterator
-gstindex
-gstmessage
-gstmeta
-gstmemory
-gstminiobject
-gstobject
-gstpad
-gstparamspecs
-gstpipeline
-gstplugin
-gstpoll
-gstpreset
-gstprintf
-gstpromise
-gstprotection
-gstregistry
-gstsegment
-gststream
-gststructure
-gstsystemclock
-gsttag
-gsttagsetter
-gsttoc
-gsttocsetter
-gsttracerrecord
-gsturi
-gstutils
-gstvalue
-gstquery
-gsttask
-*.check.xml
-gstinfo
index 0991fa8..9988dbc 100644 (file)
@@ -32,6 +32,9 @@ static const gchar *caps_list[] = {
   /* Some random checks */
   "video/x-raw, format = (string) { I420, Y42B, Y444 }, framerate = (fraction) [1/MAX, MAX], width = (int) [ 1, MAX ], height = (int) [ 1, MAX ]",
 
+  /* Some nesting check */
+  "caps, nested=(GstCaps)[c1;c2;c3,deeply-nested-field=[deep-structure, test=true]]",
+
   "ANY",
   "EMPTY"
 };
index fc82763..c8208fb 100644 (file)
@@ -39,7 +39,7 @@ GST_START_TEST (test_deinit)
 {
   gst_init (NULL, NULL);
 
-  gst_deinit ();
+  /* gst_deinit will be called by test exit handler */
 }
 
 GST_END_TEST;
@@ -53,7 +53,7 @@ GST_START_TEST (test_deinit_sysclock)
   clock = gst_system_clock_obtain ();
   gst_object_unref (clock);
 
-  gst_deinit ();
+  /* gst_deinit will be called by test exit handler */
 }
 
 GST_END_TEST;
@@ -100,15 +100,19 @@ gst_suite (void)
 {
   Suite *s = suite_create ("Gst");
   TCase *tc_chain = tcase_create ("gst tests");
+  const char *ck_fork = g_getenv ("CK_FORK");
 
   suite_add_tcase (s, tc_chain);
   tcase_add_test (tc_chain, test_init);
   tcase_add_test (tc_chain, test_new_pipeline);
   tcase_add_test (tc_chain, test_new_fakesrc);
   tcase_add_test (tc_chain, test_version);
-  /* run these last so the others don't fail if CK_FORK=no is being used */
+  /* run these last so the others don't fail if CK_FORK=no is being used.
+   * only run single test for deinitialization if CK_FORK=no, so system exit
+   * will make the single deinit call */
   tcase_add_test (tc_chain, test_deinit_sysclock);
-  tcase_add_test (tc_chain, test_deinit);
+  if (!ck_fork || (strcmp (ck_fork, "no") != 0))
+    tcase_add_test (tc_chain, test_deinit);
 
   return s;
 }
index 21e6043..e366d5f 100644 (file)
@@ -42,7 +42,22 @@ pop_async_done (GstBus * bus)
 }
 
 static void
-pop_messages (GstBus * bus, int count)
+pop_latency (GstBus * bus)
+{
+  GstMessage *message;
+
+  GST_DEBUG ("popping async-done message");
+  message = gst_bus_poll (bus, GST_MESSAGE_LATENCY, -1);
+
+  fail_unless (message && GST_MESSAGE_TYPE (message)
+      == GST_MESSAGE_LATENCY, "did not get GST_MESSAGE_LATENCY");
+
+  gst_message_unref (message);
+  GST_DEBUG ("popped message");
+}
+
+static void
+pop_state_changed (GstBus * bus, int count)
 {
   GstMessage *message;
 
@@ -153,6 +168,82 @@ GST_START_TEST (test_interface)
 
 GST_END_TEST;
 
+GST_START_TEST (test_iterate_all_by_element_factory_name)
+{
+  GstBin *bin, *bin2;
+  GstElement *filesrc;
+  GstIterator *it;
+  GValue item = { 0, };
+
+  bin = GST_BIN (gst_bin_new (NULL));
+  fail_unless (bin != NULL, "Could not create bin");
+
+  filesrc = gst_element_factory_make ("filesrc", NULL);
+  fail_unless (filesrc != NULL, "Could not create filesrc");
+  gst_bin_add (bin, filesrc);
+
+  /* Test bin with single element */
+  it = gst_bin_iterate_all_by_element_factory_name (bin, "filesrc");
+  fail_unless (it != NULL);
+  fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
+  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);
+
+  /* Negative test bin with single element */
+  it = gst_bin_iterate_all_by_element_factory_name (bin, "filesink");
+  fail_unless (it != NULL);
+  fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
+  gst_iterator_free (it);
+
+  /* Test bin with multiple other elements, 1 layer */
+  gst_bin_add_many (bin,
+      gst_element_factory_make ("identity", NULL),
+      gst_element_factory_make ("identity", NULL),
+      gst_element_factory_make ("identity", NULL), NULL);
+  it = gst_bin_iterate_all_by_element_factory_name (bin, "filesrc");
+  fail_unless (it != NULL);
+  fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
+  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);
+
+  /* Test bin with multiple other elements in subbins */
+  bin2 = bin;
+  bin = GST_BIN (gst_bin_new (NULL));
+  fail_unless (bin != NULL);
+  gst_bin_add_many (bin,
+      gst_element_factory_make ("identity", NULL),
+      gst_element_factory_make ("identity", NULL),
+      GST_ELEMENT (bin2), gst_element_factory_make ("identity", NULL), NULL);
+  it = gst_bin_iterate_all_by_element_factory_name (bin, "filesrc");
+  fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
+  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);
+
+  /* Test bin with multiple other elements, multiple occurrences in subbins */
+  gst_bin_add (bin, gst_element_factory_make ("filesrc", NULL));
+  gst_bin_add (bin2, gst_element_factory_make ("filesrc", NULL));
+  it = gst_bin_iterate_all_by_element_factory_name (bin, "filesrc");
+  fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
+  g_value_reset (&item);
+  fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
+  g_value_reset (&item);
+  fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
+  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);
+}
+
+GST_END_TEST;
+
 GST_START_TEST (test_eos)
 {
   GstBus *bus;
@@ -210,6 +301,68 @@ GST_START_TEST (test_eos)
 
 GST_END_TEST;
 
+GST_START_TEST (test_eos_recheck)
+{
+  GstBus *bus;
+  GstElement *pipeline, *sink1, *sink2;
+  GstMessage *message;
+  GstPad *pad1;
+  GThread *thread1;
+
+  pipeline = gst_pipeline_new ("test_eos_recheck");
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+
+  sink1 = gst_element_factory_make ("fakesink", "sink1");
+  sink2 = gst_element_factory_make ("fakesink", "sink2");
+
+  gst_bin_add_many (GST_BIN (pipeline), sink1, sink2, NULL);
+
+  /* Set async=FALSE so we don't wait for preroll */
+  g_object_set (sink1, "async", FALSE, NULL);
+  g_object_set (sink2, "async", FALSE, NULL);
+
+  pad1 = gst_check_setup_src_pad_by_name (sink1, &srctemplate, "sink");
+
+  gst_pad_set_active (pad1, TRUE);
+
+  fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
+          GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
+  fail_unless (gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
+          GST_CLOCK_TIME_NONE) == GST_STATE_CHANGE_SUCCESS);
+
+  /* Send one EOS to sink1 */
+  thread1 = g_thread_new ("thread1", (GThreadFunc) push_one_eos, pad1);
+
+  /* Make sure the EOS message is not sent */
+  message =
+      gst_bus_poll (bus, GST_MESSAGE_ERROR | GST_MESSAGE_EOS, 2 * GST_SECOND);
+  fail_if (message != NULL);
+
+  /* Remove sink2 without it EOSing, which should trigger an EOS re-check */
+  gst_object_ref (sink2);
+  gst_bin_remove (GST_BIN (pipeline), sink2);
+  gst_element_set_state (GST_ELEMENT (sink2), GST_STATE_NULL);
+
+  /* Make sure the EOS message is sent then */
+  message =
+      gst_bus_poll (bus, GST_MESSAGE_ERROR | GST_MESSAGE_EOS, 20 * GST_SECOND);
+  fail_if (message == NULL);
+  fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_EOS);
+  gst_message_unref (message);
+
+  /* Cleanup */
+  g_thread_join (thread1);
+
+  gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
+  gst_pad_set_active (pad1, FALSE);
+  gst_check_teardown_src_pad (sink1);
+  gst_object_unref (sink2);
+  gst_object_unref (bus);
+  gst_object_unref (pipeline);
+}
+
+GST_END_TEST;
+
 GST_START_TEST (test_stream_start)
 {
   GstBus *bus;
@@ -423,7 +576,7 @@ GST_START_TEST (test_message_state_changed_children)
   ASSERT_OBJECT_REFCOUNT (sink, "sink", 2);
   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
 
-  pop_messages (bus, 3);
+  pop_state_changed (bus, 3);
   fail_if (gst_bus_have_pending (bus), "unexpected pending messages");
 
   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
@@ -461,18 +614,19 @@ GST_START_TEST (test_message_state_changed_children)
   ASSERT_OBJECT_REFCOUNT (src, "src", 4);
   /* refcount can be 4 if the bin is still processing the async_done message of
    * the sink. */
-  ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 3);
+  ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 4);
   /* 3 or 4 is valid, because the pipeline might still be posting 
    * its state_change message */
   ASSERT_OBJECT_REFCOUNT_BETWEEN (pipeline, "pipeline", 3, 4);
 
-  pop_messages (bus, 3);
+  pop_state_changed (bus, 3);
   pop_async_done (bus);
+  pop_latency (bus);
   fail_if ((gst_bus_pop (bus)) != NULL);
 
-  ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
+  ASSERT_OBJECT_REFCOUNT_BETWEEN (bus, "bus", 2, 3);
   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
-  ASSERT_OBJECT_REFCOUNT (sink, "sink", 2);
+  ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 3);
   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
 
   /* change state to PLAYING, spawning three messages */
@@ -494,7 +648,7 @@ GST_START_TEST (test_message_state_changed_children)
   ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 4);
   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
 
-  pop_messages (bus, 3);
+  pop_state_changed (bus, 3);
   fail_if ((gst_bus_pop (bus)) != NULL);
 
   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
@@ -512,10 +666,10 @@ GST_START_TEST (test_message_state_changed_children)
   /* each object is referenced by two messages, the source also has the
    * stream-status message referencing it */
   ASSERT_OBJECT_REFCOUNT (src, "src", 4);
-  ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
+  ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 3, 4);
   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
 
-  pop_messages (bus, 6);
+  pop_state_changed (bus, 6);
   fail_if ((gst_bus_pop (bus)) != NULL);
 
   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
@@ -568,8 +722,9 @@ GST_START_TEST (test_watch_for_state_change)
       GST_CLOCK_TIME_NONE);
   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
 
-  pop_messages (bus, 6);
+  pop_state_changed (bus, 6);
   pop_async_done (bus);
+  pop_latency (bus);
 
   fail_unless (gst_bus_have_pending (bus) == FALSE,
       "Unexpected messages on bus");
@@ -577,15 +732,17 @@ GST_START_TEST (test_watch_for_state_change)
   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
 
-  pop_messages (bus, 3);
+  pop_state_changed (bus, 3);
 
   /* this one might return either SUCCESS or ASYNC, likely SUCCESS */
   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
   gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, GST_CLOCK_TIME_NONE);
 
-  pop_messages (bus, 3);
-  if (ret == GST_STATE_CHANGE_ASYNC)
+  pop_state_changed (bus, 3);
+  if (ret == GST_STATE_CHANGE_ASYNC) {
     pop_async_done (bus);
+    pop_latency (bus);
+  }
 
   fail_unless (gst_bus_have_pending (bus) == FALSE,
       "Unexpected messages on bus");
@@ -794,7 +951,7 @@ GST_START_TEST (test_children_state_change_order_flagged_sink)
   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 107);
 #else
 
-  pop_messages (bus, 2);        /* pop remaining ready => paused messages off the bus */
+  pop_state_changed (bus, 2);   /* pop remaining ready => paused messages off the bus */
   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
       108);
   pop_async_done (bus);
@@ -815,8 +972,8 @@ GST_START_TEST (test_children_state_change_order_flagged_sink)
   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
 
   /* TODO: do we need to check downwards state change order as well? */
-  pop_messages (bus, 4);        /* pop playing => paused messages off the bus */
-  pop_messages (bus, 4);        /* pop paused => ready messages off the bus */
+  pop_state_changed (bus, 4);   /* pop playing => paused messages off the bus */
+  pop_state_changed (bus, 4);   /* pop paused => ready messages off the bus */
 
   while (GST_OBJECT_REFCOUNT_VALUE (pipeline) > 1)
     THREAD_SWITCH ();
@@ -899,7 +1056,7 @@ GST_START_TEST (test_children_state_change_order_semi_sink)
   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 206);
   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 207);
 #else
-  pop_messages (bus, 2);        /* pop remaining ready => paused messages off the bus */
+  pop_state_changed (bus, 2);   /* pop remaining ready => paused messages off the bus */
   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
       208);
   pop_async_done (bus);
@@ -919,8 +1076,8 @@ GST_START_TEST (test_children_state_change_order_semi_sink)
   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
 
   /* TODO: do we need to check downwards state change order as well? */
-  pop_messages (bus, 4);        /* pop playing => paused messages off the bus */
-  pop_messages (bus, 4);        /* pop paused => ready messages off the bus */
+  pop_state_changed (bus, 4);   /* pop playing => paused messages off the bus */
+  pop_state_changed (bus, 4);   /* pop paused => ready messages off the bus */
 
   GST_DEBUG ("waiting for pipeline to reach refcount 1");
   while (GST_OBJECT_REFCOUNT_VALUE (pipeline) > 1)
@@ -1704,7 +1861,7 @@ GST_END_TEST;
     expected_flags) \
 G_STMT_START { \
   GstBin *bin = GST_BIN (gst_bin_new ("test-bin")); \
-  GstElement *element = gst_element_factory_make ("identity", "test-i"); \
+  GstElement *element = gst_element_factory_make ("queue", "test-q"); \
   GstElementFlags natural_flags = GST_OBJECT_FLAGS (bin); \
   GST_OBJECT_FLAG_SET (element, element_flags); \
   gst_bin_set_suppressed_flags (bin, suppressed_flags); \
@@ -1789,7 +1946,9 @@ gst_bin_suite (void)
 
   suite_add_tcase (s, tc_chain);
   tcase_add_test (tc_chain, test_interface);
+  tcase_add_test (tc_chain, test_iterate_all_by_element_factory_name);
   tcase_add_test (tc_chain, test_eos);
+  tcase_add_test (tc_chain, test_eos_recheck);
   tcase_add_test (tc_chain, test_stream_start);
   tcase_add_test (tc_chain, test_children_state_change_order_flagged_sink);
   tcase_add_test (tc_chain, test_children_state_change_order_semi_sink);
index 99a6f9a..b9cc35f 100644 (file)
@@ -923,6 +923,27 @@ GST_START_TEST (test_wrapped_bytes)
 
 GST_END_TEST;
 
+GST_START_TEST (test_new_memdup)
+{
+  GstBuffer *buf;
+  GstMemory *mem;
+
+  buf = gst_buffer_new_memdup (ro_memory, sizeof (ro_memory));
+
+  fail_if (gst_buffer_memcmp (buf, 0, ro_memory, sizeof (ro_memory)));
+  fail_unless_equals_int (gst_buffer_get_size (buf), sizeof (ro_memory));
+
+  /* the memory should be writable */
+  mem = gst_buffer_peek_memory (buf, 0);
+  fail_unless (gst_memory_is_writable (mem));
+  fail_unless (gst_buffer_is_writable (buf));
+  gst_buffer_memset (buf, 0, 0xaa, sizeof (ro_memory));
+
+  gst_buffer_unref (buf);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_buffer_suite (void)
 {
@@ -948,6 +969,7 @@ gst_buffer_suite (void)
   tcase_add_test (tc_chain, test_parent_buffer_meta);
   tcase_add_test (tc_chain, test_writable_memory);
   tcase_add_test (tc_chain, test_wrapped_bytes);
+  tcase_add_test (tc_chain, test_new_memdup);
 
   return s;
 }
index 1a483d9..74a21d4 100644 (file)
@@ -539,6 +539,24 @@ GST_START_TEST (test_foreach_modify_non_writeable_list)
 
 GST_END_TEST;
 
+GST_START_TEST (test_foreach_modify_writeable_list)
+{
+  GstBufferList *b = gst_buffer_list_new_sized (1);
+  GstBuffer *buf;
+
+  buf = gst_buffer_new ();
+  gst_buffer_list_add (b, gst_buffer_ref (buf));
+
+  fail_unless (gst_buffer_list_is_writable (b));
+
+  gst_buffer_list_foreach (b, foreach_replace_buffer, NULL);
+
+  gst_buffer_list_unref (b);
+  gst_buffer_unref (buf);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_buffer_list_suite (void)
 {
@@ -546,6 +564,7 @@ gst_buffer_list_suite (void)
   TCase *tc_chain = tcase_create ("general");
 
   suite_add_tcase (s, tc_chain);
+
   tcase_add_checked_fixture (tc_chain, setup, cleanup);
   tcase_add_test (tc_chain, test_add_and_iterate);
   tcase_add_test (tc_chain, test_remove);
@@ -559,6 +578,7 @@ gst_buffer_list_suite (void)
   tcase_add_test (tc_chain, test_new_sized_0);
   tcase_add_test (tc_chain, test_multiple_mutable_buffer_references);
   tcase_add_test (tc_chain, test_foreach_modify_non_writeable_list);
+  tcase_add_test (tc_chain, test_foreach_modify_writeable_list);
 
   return s;
 }
index dd9b2dc..9f25c0d 100644 (file)
@@ -301,6 +301,41 @@ GST_START_TEST (test_flushing_pool_returns_flushing)
 
 GST_END_TEST;
 
+static gpointer
+unref_buf (gpointer p)
+{
+  GstBuffer *buf = (GstBuffer *) p;
+  /* remove all memory, pool should not reuse this buffer */
+  gst_buffer_remove_all_memory (buf);
+  gst_buffer_unref (buf);
+  return NULL;
+}
+
+GST_START_TEST (test_no_deadlock_for_buffer_discard)
+{
+  GstBufferPool *pool;
+  GstBuffer *buf1, *buf2;
+  GThread *thread;
+
+  pool = create_pool (1, 1, 1);
+  fail_unless (pool);
+  gst_buffer_pool_set_active (pool, TRUE);
+
+  fail_unless (gst_buffer_pool_acquire_buffer (pool, &buf1,
+          NULL) == GST_FLOW_OK);
+  thread = g_thread_new (NULL, unref_buf, buf1);
+  fail_unless (thread);
+  /* we will be blocked here until buf1 unrefed */
+  fail_unless (gst_buffer_pool_acquire_buffer (pool, &buf2,
+          NULL) == GST_FLOW_OK);
+
+  gst_buffer_unref (buf2);
+  g_thread_join (thread);
+  gst_object_unref (pool);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_buffer_pool_suite (void)
 {
@@ -319,6 +354,7 @@ gst_buffer_pool_suite (void)
   tcase_add_test (tc_chain, test_pool_activation_and_config);
   tcase_add_test (tc_chain, test_pool_config_validate);
   tcase_add_test (tc_chain, test_flushing_pool_returns_flushing);
+  tcase_add_test (tc_chain, test_no_deadlock_for_buffer_discard);
 
   return s;
 }
index f8d6cb0..578e9d9 100644 (file)
@@ -429,6 +429,94 @@ GST_START_TEST (test_watch_with_poll)
 
 GST_END_TEST;
 
+static gint check_messages_seen;
+
+static void
+send_check_messages (guint index)
+{
+  GstMessage *m;
+  GstStructure *s;
+
+  s = gst_structure_new ("test_message", "index", G_TYPE_INT, index, NULL);
+  m = gst_message_new_application (NULL, s);
+  gst_bus_post (test_bus, m);
+}
+
+static void
+message_check_func (GstBus * bus, GstMessage * message, gpointer data)
+{
+  const GstStructure *s;
+  int index;
+
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_APPLICATION);
+
+  s = gst_message_get_structure (message);
+  if (!gst_structure_get_int (s, "index", &index))
+    g_critical ("Invalid message");
+
+  check_messages_seen |= 1 << index;
+}
+
+/* test that removing and adding the signal watch again works */
+GST_START_TEST (test_watch_twice)
+{
+  GMainContext *ctx;
+  guint expect = 0;
+
+  test_bus = gst_bus_new ();
+  ctx = g_main_context_new ();
+
+  g_main_context_push_thread_default (ctx);
+
+  send_check_messages (0);
+  expect |= 1 << 0;
+
+  gst_bus_add_signal_watch (test_bus);
+
+  g_signal_connect (test_bus, "message::application",
+      (GCallback) message_check_func, NULL);
+
+  send_check_messages (1);
+  expect |= 1 << 1;
+
+  fail_unless (g_main_context_pending (ctx));
+
+  gst_bus_remove_signal_watch (test_bus);
+
+  send_check_messages (2);
+  expect |= 1 << 2;
+
+  gst_bus_add_signal_watch (test_bus);
+
+  send_check_messages (3);
+  expect |= 1 << 3;
+
+  while (g_main_context_pending (ctx))
+    g_main_context_iteration (ctx, FALSE);
+
+  /* this message will not arrive */
+  send_check_messages (4);
+  expect |= 0 << 4;
+
+  fail_unless (g_main_context_pending (ctx));
+
+  gst_bus_remove_signal_watch (test_bus);
+
+  /* this message should not arrive */
+  send_check_messages (5);
+  expect |= 0 << 5;
+
+  while (g_main_context_pending (ctx))
+    g_main_context_iteration (ctx, FALSE);
+
+  fail_unless (check_messages_seen == expect);
+
+  g_main_context_unref (ctx);
+  gst_object_unref (test_bus);
+}
+
+GST_END_TEST;
+
 /* test that you get the messages with pop. */
 GST_START_TEST (test_timed_pop)
 {
@@ -812,6 +900,32 @@ GST_START_TEST (test_async_message)
 
 GST_END_TEST;
 
+GST_START_TEST (test_single_gsource)
+{
+  GstBus *bus = gst_bus_new ();
+  GSource *source = gst_bus_create_watch (bus);
+  g_source_attach (source, NULL);
+  g_source_unref (source);
+
+  source = gst_bus_create_watch (bus);
+  fail_if (source, "Only one GSource can be added to a bus");
+
+  ASSERT_CRITICAL (gst_bus_add_signal_watch (bus));
+  ASSERT_CRITICAL (gst_bus_remove_signal_watch (bus));
+
+  fail_unless (gst_bus_remove_watch (bus), "Could not remove watch");
+  gst_bus_add_signal_watch (bus);
+
+  fail_if (gst_bus_remove_watch (bus), "Signal watch should be removed"
+      " with gst_bus_remove_signal_watch");
+
+  gst_bus_remove_signal_watch (bus);
+
+  gst_object_unref (bus);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_bus_suite (void)
 {
@@ -824,6 +938,7 @@ gst_bus_suite (void)
   tcase_add_test (tc_chain, test_hammer_bus);
   tcase_add_test (tc_chain, test_watch);
   tcase_add_test (tc_chain, test_watch_with_poll);
+  tcase_add_test (tc_chain, test_watch_twice);
   tcase_add_test (tc_chain, test_watch_with_custom_context);
   tcase_add_test (tc_chain, test_add_watch_with_custom_context);
   tcase_add_test (tc_chain, test_remove_watch);
@@ -833,6 +948,7 @@ gst_bus_suite (void)
   tcase_add_test (tc_chain, test_timed_pop_filtered_with_timeout);
   tcase_add_test (tc_chain, test_custom_main_context);
   tcase_add_test (tc_chain, test_async_message);
+  tcase_add_test (tc_chain, test_single_gsource);
   return s;
 }
 
index c80d02b..d9931d6 100644 (file)
@@ -43,9 +43,18 @@ GST_START_TEST (test_from_string)
         "Could not convert caps back to string %s\n", caps_list[i]);
     caps2 = gst_caps_from_string (to_str);
     fail_if (caps2 == NULL, "Could not create caps from string %s\n", to_str);
+    g_free (to_str);
 
     fail_unless (gst_caps_is_equal (caps, caps));
     fail_unless (gst_caps_is_equal (caps, caps2));
+    gst_caps_unref (caps2);
+
+    to_str = gst_caps_serialize (caps, GST_SERIALIZE_FLAG_NONE);
+    fail_if (to_str == NULL,
+        "Could not convert caps back to string %s\n", caps_list[i]);
+    caps2 = gst_caps_from_string (to_str);
+    fail_unless (gst_caps_is_equal (caps, caps));
+    fail_unless (gst_caps_is_equal (caps, caps2));
 
     gst_caps_unref (caps);
     gst_caps_unref (caps2);
@@ -60,7 +69,7 @@ GST_START_TEST (test_double_append)
   GstStructure *s1;
   GstCaps *c1;
 
-  c1 = gst_caps_new_any ();
+  c1 = gst_caps_new_empty ();
   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));
@@ -76,7 +85,7 @@ GST_START_TEST (test_mutability)
   GstCaps *c1;
   gint ret;
 
-  c1 = gst_caps_new_any ();
+  c1 = gst_caps_new_empty ();
   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);
@@ -270,6 +279,16 @@ GST_START_TEST (test_simplify)
   }
 
   gst_caps_unref (caps);
+
+  caps = gst_caps_new_empty ();
+  caps = gst_caps_simplify (caps);
+  fail_unless (gst_caps_is_empty (caps));
+  gst_caps_unref (caps);
+
+  caps = gst_caps_new_any ();
+  caps = gst_caps_simplify (caps);
+  fail_unless (gst_caps_is_any (caps));
+  gst_caps_unref (caps);
 }
 
 GST_END_TEST;
@@ -285,6 +304,45 @@ GST_START_TEST (test_truncate)
   caps = gst_caps_truncate (caps);
   fail_unless_equals_int (gst_caps_get_size (caps), 1);
   gst_caps_unref (caps);
+
+  caps = gst_caps_new_empty ();
+  caps = gst_caps_truncate (caps);
+  fail_if (caps == NULL);
+  fail_unless (gst_caps_is_empty (caps));
+  gst_caps_unref (caps);
+
+  caps = gst_caps_new_any ();
+  caps = gst_caps_truncate (caps);
+  fail_if (caps == NULL);
+  fail_unless (gst_caps_is_any (caps));
+  gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_fixate)
+{
+  GstCaps *caps, *expected;
+
+  caps = gst_caps_from_string (non_simple_caps_string);
+  fail_unless (caps != NULL,
+      "gst_caps_from_string (non_simple_caps_string) failed");
+  fail_unless_equals_int (gst_caps_get_size (caps), 4);
+  caps = gst_caps_fixate (caps);
+  fail_unless_equals_int (gst_caps_get_size (caps), 1);
+  expected =
+      gst_caps_from_string
+      ("video/x-raw, format=(string)I420, framerate=(fraction)1/100, "
+      "width=(int)16, height=(int)16");
+  fail_unless (gst_caps_is_equal (caps, expected));
+  gst_caps_unref (caps);
+  gst_caps_unref (expected);
+
+  caps = gst_caps_new_empty ();
+  caps = gst_caps_fixate (caps);
+  fail_if (caps == NULL);
+  fail_unless (gst_caps_is_empty (caps));
+  gst_caps_unref (caps);
 }
 
 GST_END_TEST;
@@ -333,6 +391,22 @@ GST_START_TEST (test_subset)
   fail_if (gst_caps_is_equal (c1, c2));
   gst_caps_unref (c1);
   gst_caps_unref (c2);
+
+  c1 = gst_caps_from_string ("video/x-h264, parsed=(boolean)true");
+  c2 = gst_caps_new_empty ();
+  fail_unless (gst_caps_is_subset (c2, c1));
+  fail_if (gst_caps_is_subset (c1, c2));
+  fail_if (gst_caps_is_equal (c1, c2));
+  gst_caps_unref (c1);
+  gst_caps_unref (c2);
+
+  c1 = gst_caps_from_string ("video/x-h264, parsed=(boolean)true");
+  c2 = gst_caps_new_any ();
+  fail_if (gst_caps_is_subset (c2, c1));
+  fail_unless (gst_caps_is_subset (c1, c2));
+  fail_if (gst_caps_is_equal (c1, c2));
+  gst_caps_unref (c1);
+  gst_caps_unref (c2);
 }
 
 GST_END_TEST;
@@ -729,6 +803,55 @@ GST_START_TEST (test_intersect)
 
   gst_caps_unref (c1);
   gst_caps_unref (c2);
+
+  /* ========== */
+
+  c1 = gst_caps_from_string ("video/x-raw,format=(string)I420,width=20");
+  c2 = gst_caps_new_empty ();
+
+  ci1 = gst_caps_intersect (c1, c2);
+  GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci1);
+
+  fail_unless (gst_caps_is_empty (ci1));
+  fail_unless (gst_caps_get_size (ci1) == 0);
+
+  ci2 = gst_caps_intersect (c2, c1);
+  GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci2);
+
+  fail_unless (gst_caps_is_empty (ci2));
+  fail_unless (gst_caps_get_size (ci2) == 0);
+
+  fail_unless (gst_caps_is_equal (ci1, ci2));
+
+  gst_caps_unref (ci1);
+  gst_caps_unref (ci2);
+
+  gst_caps_unref (c1);
+  gst_caps_unref (c2);
+
+
+  /* ========== */
+
+  c1 = gst_caps_from_string ("video/x-raw,format=(string)I420,width=20");
+  c2 = gst_caps_new_any ();
+
+  ci1 = gst_caps_intersect (c1, c2);
+  GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci1);
+
+  fail_unless (gst_caps_is_equal (ci1, c1));
+
+  ci2 = gst_caps_intersect (c2, c1);
+  GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci2);
+
+  fail_unless (gst_caps_is_equal (ci2, c1));
+
+  fail_unless (gst_caps_is_equal (ci1, ci2));
+
+  gst_caps_unref (ci1);
+  gst_caps_unref (ci2);
+
+  gst_caps_unref (c1);
+  gst_caps_unref (c2);
 }
 
 GST_END_TEST;
@@ -1259,6 +1382,18 @@ GST_START_TEST (test_features)
   fail_unless (gst_caps_features_is_equal (f1, f2));
 
   gst_caps_unref (c1);
+
+  c1 = gst_caps_new_any ();
+  fail_unless_equals_int (gst_caps_get_size (c1), 0);
+
+  f1 = gst_caps_features_new ("memory:EGLImage", NULL);
+  /* Nothing to set the features on, but method should still take
+   * ownership of the given features */
+  gst_caps_set_features_simple (c1, f1);
+  fail_unless_equals_int (gst_caps_get_size (c1), 0);
+  fail_unless (gst_caps_is_any (c1));
+
+  gst_caps_unref (c1);
 }
 
 GST_END_TEST;
@@ -1408,6 +1543,280 @@ GST_START_TEST (test_filter_and_map_in_place)
 
 GST_END_TEST;
 
+GST_START_TEST (test_equality)
+{
+  GstCaps *empty1, *empty2, *any1, *any2, *caps1, *caps2, *caps3, *caps4,
+      *caps5, *caps6, *caps7, *caps8, *caps9;
+  GstStructure *s;
+
+  empty1 = gst_caps_new_empty ();
+
+  empty2 = gst_caps_new_empty ();
+
+  any1 = gst_caps_new_any ();
+
+  any2 = gst_caps_new_any ();
+  s = gst_structure_new ("structure", "int", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (s);
+  gst_caps_append_structure (any2, s);
+  /* should still be ANY after append */
+
+  caps1 = gst_caps_new_simple ("structure", "int", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (caps1);
+
+  caps2 = gst_caps_new_simple ("structure", "int", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (caps2);
+  /* append an identical structure */
+  s = gst_structure_new ("structure", "int", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (s);
+  gst_caps_append_structure (caps2, s);
+
+  /* change field name */
+  caps3 = gst_caps_new_simple ("structure", "intX", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (caps3);
+
+  /* change field type */
+  caps4 = gst_caps_new_simple ("structure", "int", G_TYPE_UINT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (caps4);
+
+  /* change structure name */
+  caps5 = gst_caps_new_simple ("structureX", "int", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (caps5);
+
+  /* change field value */
+  caps6 = gst_caps_new_simple ("structure", "int", G_TYPE_INT, 3, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (caps6);
+
+  /* change caps features */
+  caps7 = gst_caps_new_simple ("structure", "int", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (caps6);
+  gst_caps_set_features (caps7, 0, gst_caps_features_new_any ());
+
+  /* add structure */
+  caps8 = gst_caps_new_simple ("structure", "int", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (caps8);
+  s = gst_structure_new ("structure2", "string", G_TYPE_STRING, "val", NULL);
+  fail_unless (s);
+  gst_caps_append_structure (caps8, s);
+
+  /* reverse the order of the structures */
+  caps9 = gst_caps_new_simple ("structure2", "string", G_TYPE_STRING, "val",
+      NULL);
+  fail_unless (caps9);
+  s = gst_structure_new ("structure", "int", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (s);
+  gst_caps_append_structure (caps9, s);
+
+  fail_unless (gst_caps_is_equal (empty1, empty2) == TRUE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, empty2) == TRUE);
+  fail_unless (gst_caps_is_equal (empty1, any1) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, any1) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, any2) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, any2) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps1) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps1) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps2) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps2) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps3) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps3) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps4) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps4) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps5) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps5) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps6) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps6) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps7) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps7) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps8) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps8) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps9) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps9) == FALSE);
+
+  fail_unless (gst_caps_is_equal (any1, any2) == TRUE);
+  fail_unless (gst_caps_is_strictly_equal (any1, any2) == TRUE);
+  fail_unless (gst_caps_is_equal (any1, caps1) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps1) == FALSE);
+  fail_unless (gst_caps_is_equal (any1, caps2) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps2) == FALSE);
+  fail_unless (gst_caps_is_equal (any1, caps3) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps3) == FALSE);
+  fail_unless (gst_caps_is_equal (any1, caps4) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps4) == FALSE);
+  fail_unless (gst_caps_is_equal (any1, caps5) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps5) == FALSE);
+  fail_unless (gst_caps_is_equal (any1, caps6) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps6) == FALSE);
+  fail_unless (gst_caps_is_equal (any1, caps7) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps7) == FALSE);
+  fail_unless (gst_caps_is_equal (any1, caps8) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps8) == FALSE);
+  fail_unless (gst_caps_is_equal (any1, caps9) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps9) == FALSE);
+
+  fail_unless (gst_caps_is_equal (any2, caps1) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps1) == FALSE);
+  fail_unless (gst_caps_is_equal (any2, caps2) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps2) == FALSE);
+  fail_unless (gst_caps_is_equal (any2, caps3) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps3) == FALSE);
+  fail_unless (gst_caps_is_equal (any2, caps4) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps4) == FALSE);
+  fail_unless (gst_caps_is_equal (any2, caps5) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps5) == FALSE);
+  fail_unless (gst_caps_is_equal (any2, caps6) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps6) == FALSE);
+  fail_unless (gst_caps_is_equal (any2, caps7) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps7) == FALSE);
+  fail_unless (gst_caps_is_equal (any2, caps8) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps8) == FALSE);
+  fail_unless (gst_caps_is_equal (any2, caps9) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps9) == FALSE);
+
+  /* caps1 and caps2 are equal, but not strictly equal because one has
+   * two copies of the same structure */
+  fail_unless (gst_caps_is_equal (caps1, caps2) == TRUE);
+  fail_unless (gst_caps_is_strictly_equal (caps1, caps2) == FALSE);
+  fail_unless (gst_caps_is_equal (caps1, caps3) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps1, caps3) == FALSE);
+  fail_unless (gst_caps_is_equal (caps1, caps4) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps1, caps4) == FALSE);
+  fail_unless (gst_caps_is_equal (caps1, caps5) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps1, caps5) == FALSE);
+  fail_unless (gst_caps_is_equal (caps1, caps6) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps1, caps6) == FALSE);
+  fail_unless (gst_caps_is_equal (caps1, caps7) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps1, caps7) == FALSE);
+  fail_unless (gst_caps_is_equal (caps1, caps8) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps1, caps8) == FALSE);
+  fail_unless (gst_caps_is_equal (caps1, caps9) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps1, caps9) == FALSE);
+
+  fail_unless (gst_caps_is_equal (caps2, caps3) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps2, caps3) == FALSE);
+  fail_unless (gst_caps_is_equal (caps2, caps4) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps2, caps4) == FALSE);
+  fail_unless (gst_caps_is_equal (caps2, caps5) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps2, caps5) == FALSE);
+  fail_unless (gst_caps_is_equal (caps2, caps6) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps2, caps6) == FALSE);
+  fail_unless (gst_caps_is_equal (caps2, caps7) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps2, caps7) == FALSE);
+  fail_unless (gst_caps_is_equal (caps2, caps8) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps2, caps8) == FALSE);
+  fail_unless (gst_caps_is_equal (caps2, caps9) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps2, caps9) == FALSE);
+
+  /* caps8 and caps9 are equal, but not strictly equal because their
+   * order of structures is different */
+  fail_unless (gst_caps_is_equal (caps8, caps9) == TRUE);
+  fail_unless (gst_caps_is_strictly_equal (caps8, caps9) == FALSE);
+
+  gst_caps_unref (empty1);
+  gst_caps_unref (empty2);
+  gst_caps_unref (any1);
+  gst_caps_unref (any2);
+  gst_caps_unref (caps1);
+  gst_caps_unref (caps2);
+  gst_caps_unref (caps3);
+  gst_caps_unref (caps4);
+  gst_caps_unref (caps5);
+  gst_caps_unref (caps6);
+  gst_caps_unref (caps7);
+  gst_caps_unref (caps8);
+  gst_caps_unref (caps9);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_remains_any)
+{
+  GstCaps *any, *caps;
+  GstStructure *s;
+
+  /* test append structure to ANY */
+  any = gst_caps_new_any ();
+  fail_unless (gst_caps_is_any (any));
+  fail_if (gst_caps_get_size (any));
+  s = gst_structure_new ("structure", "int", G_TYPE_INT, 4, NULL);
+  fail_unless (s);
+  gst_caps_append_structure (any, s);
+  fail_unless (gst_caps_is_any (any));
+  fail_if (gst_caps_get_size (any));
+  ASSERT_CRITICAL (gst_caps_get_structure (any, 0));
+
+  s = gst_structure_new ("structure", "int", G_TYPE_INT, 4, NULL);
+  fail_unless (s);
+  gst_caps_append_structure_full (any, s, gst_caps_features_new_any ());
+  fail_unless (gst_caps_is_any (any));
+  fail_if (gst_caps_get_size (any));
+  ASSERT_CRITICAL (gst_caps_get_structure (any, 0));
+
+  /* test merge structure with ANY */
+  s = gst_structure_new ("structure", "int", G_TYPE_INT, 4, NULL);
+  fail_unless (s);
+  any = gst_caps_merge_structure (any, s);
+  fail_unless (gst_caps_is_any (any));
+  fail_if (gst_caps_get_size (any));
+  ASSERT_CRITICAL (gst_caps_get_structure (any, 0));
+
+  s = gst_structure_new ("structure", "int", G_TYPE_INT, 4, NULL);
+  fail_unless (s);
+  any = gst_caps_merge_structure_full (any, s, gst_caps_features_new_any ());
+  fail_unless (gst_caps_is_any (any));
+  fail_if (gst_caps_get_size (any));
+  ASSERT_CRITICAL (gst_caps_get_structure (any, 0));
+
+  /* test appending non-ANY to ANY */
+  caps = gst_caps_new_simple ("structure", "int", G_TYPE_INT, 4, NULL);
+  fail_unless (caps);
+  gst_caps_append (any, caps);
+  fail_unless (gst_caps_is_any (any));
+  fail_if (gst_caps_get_size (any));
+  ASSERT_CRITICAL (gst_caps_get_structure (any, 0));
+
+  /* test merging non-ANY with ANY */
+  caps = gst_caps_new_simple ("structure", "int", G_TYPE_INT, 4, NULL);
+  fail_unless (caps);
+  any = gst_caps_merge (any, caps);
+  fail_unless (gst_caps_is_any (any));
+  fail_if (gst_caps_get_size (any));
+  ASSERT_CRITICAL (gst_caps_get_structure (any, 0));
+
+  caps = gst_caps_new_simple ("structure", "int", G_TYPE_INT, 4, NULL);
+  fail_unless (caps);
+  any = gst_caps_merge (caps, any);
+  fail_unless (gst_caps_is_any (any));
+  fail_if (gst_caps_get_size (any));
+  ASSERT_CRITICAL (gst_caps_get_structure (any, 0));
+
+  gst_caps_unref (any);
+
+  /* test appending ANY to non-ANY */
+  caps = gst_caps_new_simple ("structure", "int", G_TYPE_INT, 4, NULL);
+  fail_unless (caps);
+  fail_unless_equals_int (gst_caps_get_size (caps), 1);
+  fail_unless (gst_caps_get_structure (caps, 0));
+  gst_caps_append (caps, gst_caps_new_any ());
+  fail_unless (gst_caps_is_any (caps));
+  fail_if (gst_caps_get_size (caps));
+  ASSERT_CRITICAL (gst_caps_get_structure (caps, 0));
+
+  gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_caps_suite (void)
 {
@@ -1421,6 +1830,7 @@ gst_caps_suite (void)
   tcase_add_test (tc_chain, test_static_caps);
   tcase_add_test (tc_chain, test_simplify);
   tcase_add_test (tc_chain, test_truncate);
+  tcase_add_test (tc_chain, test_fixate);
   tcase_add_test (tc_chain, test_subset);
   tcase_add_test (tc_chain, test_subset_duplication);
   tcase_add_test (tc_chain, test_merge_fundamental);
@@ -1442,6 +1852,8 @@ gst_caps_suite (void)
   tcase_add_test (tc_chain, test_foreach);
   tcase_add_test (tc_chain, test_map_in_place);
   tcase_add_test (tc_chain, test_filter_and_map_in_place);
+  tcase_add_test (tc_chain, test_equality);
+  tcase_add_test (tc_chain, test_remains_any);
 
   return s;
 }
index 9d81c5d..04a11e2 100644 (file)
@@ -181,7 +181,7 @@ gst_test_obj_class_init (GstTestObjClass * klass)
 static GType
 gst_test_obj_get_type (void)
 {
-  static volatile gsize test_obj_type = 0;
+  static gsize test_obj_type = 0;
 
   if (g_once_init_enter (&test_obj_type)) {
     GType type;
@@ -276,7 +276,7 @@ gst_test_control_source_init (GstTestControlSource * self)
 static GType
 gst_test_control_source_get_type (void)
 {
-  static volatile gsize test_countrol_source_type = 0;
+  static gsize test_countrol_source_type = 0;
 
   if (g_once_init_enter (&test_countrol_source_type)) {
     GType type;
@@ -406,7 +406,7 @@ gst_test_control_binding_class_init (gpointer klass, gpointer class_data)
 static GType
 gst_test_control_binding_get_type (void)
 {
-  static volatile gsize test_countrol_binding_type = 0;
+  static gsize test_countrol_binding_type = 0;
 
   if (g_once_init_enter (&test_countrol_binding_type)) {
     GType type;
@@ -499,7 +499,7 @@ GST_START_TEST (controller_new_fail3)
   elem = gst_element_factory_make ("testobj", NULL);
   cs = gst_test_control_source_new ();
 
-  /* that property should exist and but is not controlable */
+  /* that property should exist and but is not controllable */
   cb = gst_test_control_binding_new (GST_OBJECT (elem), "static",
       GST_CONTROL_SOURCE (cs));
   fail_unless (GST_CONTROL_BINDING_PSPEC (cb) == NULL, NULL);
index 15cc977..b083431 100644 (file)
@@ -131,6 +131,53 @@ GST_START_TEST (test_GstDateTime_new_from_unix_epoch_utc)
 
 GST_END_TEST;
 
+GST_START_TEST (test_GstDateTime_new_from_unix_epoch_local_time_usecs)
+{
+  GstDateTime *dt;
+  struct tm tm;
+  /* 2007-01-01T20:00:00.500000Z */
+  gint64 time = G_GINT64_CONSTANT (1167681600500000);
+  time_t t = (time_t) (time / G_USEC_PER_SEC);
+
+#ifdef HAVE_LOCALTIME_R
+  localtime_r (&t, &tm);
+#else
+  memcpy (&tm, localtime (&t), sizeof (struct tm));
+#endif
+
+  dt = gst_date_time_new_from_unix_epoch_local_time_usecs (time);
+  assert_equals_int (gst_date_time_get_year (dt), 1900 + tm.tm_year);
+  assert_equals_int (gst_date_time_get_month (dt), 1 + tm.tm_mon);
+  assert_equals_int (gst_date_time_get_day (dt), tm.tm_mday);
+  assert_equals_int (gst_date_time_get_hour (dt), tm.tm_hour);
+  assert_equals_int (gst_date_time_get_minute (dt), tm.tm_min);
+  assert_equals_int (gst_date_time_get_second (dt), tm.tm_sec);
+  assert_equals_int (gst_date_time_get_microsecond (dt), 500000);
+  gst_date_time_unref (dt);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_GstDateTime_new_from_unix_epoch_utc_usecs)
+{
+  GstDateTime *dt;
+  /* 2007-01-01T20:00:00.500000Z */
+  gint64 time = G_GINT64_CONSTANT (1167681600500000);
+
+  dt = gst_date_time_new_from_unix_epoch_utc_usecs (time);
+  assert_equals_int (gst_date_time_get_year (dt), 2007);
+  assert_equals_int (gst_date_time_get_month (dt), 1);
+  assert_equals_int (gst_date_time_get_day (dt), 1);
+  assert_equals_int (gst_date_time_get_hour (dt), 20);
+  assert_equals_int (gst_date_time_get_minute (dt), 0);
+  assert_equals_int (gst_date_time_get_second (dt), 0);
+  assert_equals_int (gst_date_time_get_microsecond (dt), 500000);
+  assert_equals_int (gst_date_time_get_time_zone_offset (dt), 0);
+  gst_date_time_unref (dt);
+}
+
+GST_END_TEST;
+
 GST_START_TEST (test_GstDateTime_get_dmy)
 {
   GstDateTime *dt;
@@ -176,15 +223,133 @@ GST_START_TEST (test_GstDateTime_get_hour)
 
 GST_END_TEST;
 
+GST_START_TEST (test_GstDateTime_new_local_time)
+{
+  GstDateTime *dt;
+
+  /* Valid date */
+  dt = gst_date_time_new_local_time (2020, 2, 28, 12, 0, 0);
+  fail_unless (dt != NULL);
+  gst_date_time_unref (dt);
+
+  /* Date out of bounds - regression test for segfault #524 */
+  dt = gst_date_time_new_local_time (2020, 2, 31, 12, 0, 0);
+  fail_unless (dt == NULL);
+
+  // TODO more tests for correctness of the function (regarding local timezone)
+
+  /* Invalid values */
+
+  /* Year */
+  fail_if (gst_date_time_new_local_time (0, 2, 28, 12, 0, 0));  // -1 has special meaning!
+
+  fail_if (gst_date_time_new_local_time (10000, 2, 28, 12, 0, 0));
+
+  dt = gst_date_time_new_local_time (1, 2, 28, 12, 0, 0);
+  fail_unless (dt != NULL);
+  gst_date_time_unref (dt);
+
+  dt = gst_date_time_new_local_time (9999, 2, 28, 12, 0, 0);
+  fail_unless (dt != NULL);
+  gst_date_time_unref (dt);
+
+  /* Month */
+  dt = NULL;
+  fail_if (gst_date_time_new_local_time (2020, 0, 28, 12, 0, 0));
+
+  fail_if (gst_date_time_new_local_time (2020, 13, 28, 12, 0, 0));
+
+  dt = gst_date_time_new_local_time (2020, 1, 28, 12, 0, 0);
+  fail_unless (dt != NULL);
+  gst_date_time_unref (dt);
+
+  dt = gst_date_time_new_local_time (2020, 12, 28, 12, 0, 0);
+  fail_unless (dt != NULL);
+  gst_date_time_unref (dt);
+
+  dt = gst_date_time_new_local_time (2038, 6, 15, 12, 0, 0);
+  fail_unless (dt != NULL);
+  gst_date_time_unref (dt);
+
+  /* Day */
+  dt = NULL;
+  fail_if (gst_date_time_new_local_time (2020, 2, 0, 12, 0, 0));
+
+  fail_if (gst_date_time_new_local_time (2020, 2, 32, 12, 0, 0));
+  fail_unless (dt == NULL);
+
+  dt = gst_date_time_new_local_time (2020, 2, 1, 12, 0, 0);
+  fail_unless (dt != NULL);
+  gst_date_time_unref (dt);
+
+  dt = gst_date_time_new_local_time (2020, 2, 29, 12, 0, 0);    // leap year
+  fail_unless (dt != NULL);
+  gst_date_time_unref (dt);
+
+  dt = gst_date_time_new_local_time (2020, 1, 31, 12, 0, 0);
+  fail_unless (dt != NULL);
+  gst_date_time_unref (dt);
+
+  /* Hour */
+  dt = NULL;
+  fail_if (gst_date_time_new_local_time (2020, 2, 28, -10, 0, 0));      // -1 has special meaning!
+
+  fail_if (gst_date_time_new_local_time (2020, 2, 28, 24, 0, 0));
+  fail_unless (dt == NULL);
+
+  dt = gst_date_time_new_local_time (2020, 2, 28, 0, 0, 0);
+  fail_unless (dt != NULL);
+  gst_date_time_unref (dt);
+
+  dt = gst_date_time_new_local_time (2020, 2, 28, 23, 0, 0);
+  fail_unless (dt != NULL);
+  gst_date_time_unref (dt);
+
+  /* Min */
+  dt = NULL;
+  fail_if (gst_date_time_new_local_time (2020, 2, 28, 12, -10, 0));     // -1 has special meaning!
+
+  fail_if (gst_date_time_new_local_time (2020, 2, 28, 12, 60, 0));
+  fail_unless (dt == NULL);
+
+  dt = gst_date_time_new_local_time (2020, 2, 28, 12, 0, 0);
+  fail_unless (dt != NULL);
+  gst_date_time_unref (dt);
+
+  dt = gst_date_time_new_local_time (2020, 2, 28, 12, 59, 0);
+  fail_unless (dt != NULL);
+  gst_date_time_unref (dt);
+
+  /* Sec */
+  dt = NULL;
+  fail_if (gst_date_time_new_local_time (2020, 2, 28, 12, 0, -10));     // -1 has special meaning!
+
+  fail_if (gst_date_time_new_local_time (2020, 2, 28, 12, 0, 60));
+  fail_unless (dt == NULL);
+
+  dt = gst_date_time_new_local_time (2020, 2, 28, 12, 0, 0);
+  fail_unless (dt != NULL);
+  gst_date_time_unref (dt);
+
+  dt = gst_date_time_new_local_time (2020, 2, 28, 12, 0, 59);
+  fail_unless (dt != NULL);
+  gst_date_time_unref (dt);
+
+  dt = gst_date_time_new_local_time (2020, 12, 31, 23, 59, 59);
+  fail_unless (dt != NULL);
+  gst_date_time_unref (dt);
+}
+
+GST_END_TEST;
+
 GST_START_TEST (test_GstDateTime_get_microsecond)
 {
-  GTimeVal tv;
+  gint64 now_us;
   GstDateTime *dt;
 
-  g_get_current_time (&tv);
-  dt = gst_date_time_new (0, 2010, 7, 15, 11, 12,
-      13 + (tv.tv_usec / 1000000.0));
-  assert_almost_equals_int (tv.tv_usec, gst_date_time_get_microsecond (dt));
+  now_us = g_get_real_time () % GST_USECOND;
+  dt = gst_date_time_new (0, 2010, 7, 15, 11, 12, 13 + (now_us / 1000000.0));
+  assert_almost_equals_int (now_us, gst_date_time_get_microsecond (dt));
   gst_date_time_unref (dt);
 }
 
@@ -297,21 +462,21 @@ GST_START_TEST (test_GstDateTime_partial_fields)
 {
   GstDateTime *dt;
 
-  ASSERT_CRITICAL (gst_date_time_new (0.0, -1, -1, -1, -1, -1, -1));
-  ASSERT_CRITICAL (gst_date_time_new (0.0, 2012, 7, 18, 9, -1, -1));
+  fail_if (gst_date_time_new (0.0, -1, -1, -1, -1, -1, -1));
+  fail_if (gst_date_time_new (0.0, 2012, 7, 18, 9, -1, -1));
 
   dt = gst_date_time_new (0.0, 2012, -1, -1, -1, -1, -1);
   fail_unless (gst_date_time_has_year (dt));
   fail_unless_equals_int (gst_date_time_get_year (dt), 2012);
   fail_if (gst_date_time_has_month (dt));
-  ASSERT_CRITICAL (gst_date_time_get_month (dt));
+  fail_unless_equals_int (gst_date_time_get_month (dt), -1);
   fail_if (gst_date_time_has_day (dt));
-  ASSERT_CRITICAL (gst_date_time_get_day (dt));
+  fail_unless_equals_int (gst_date_time_get_day (dt), -1);
   fail_if (gst_date_time_has_time (dt));
-  ASSERT_CRITICAL (gst_date_time_get_hour (dt));
-  ASSERT_CRITICAL (gst_date_time_get_minute (dt));
+  fail_unless_equals_int (gst_date_time_get_hour (dt), -1);
+  fail_unless_equals_int (gst_date_time_get_minute (dt), -1);
   fail_if (gst_date_time_has_second (dt));
-  ASSERT_CRITICAL (gst_date_time_get_second (dt));
+  fail_unless_equals_float (gst_date_time_get_second (dt), -1.0);
   gst_date_time_unref (dt);
 
   dt = gst_date_time_new (0.0, 2012, 7, -1, -1, -1, -1);
@@ -320,12 +485,12 @@ GST_START_TEST (test_GstDateTime_partial_fields)
   fail_unless (gst_date_time_has_month (dt));
   fail_unless_equals_int (gst_date_time_get_month (dt), 7);
   fail_if (gst_date_time_has_day (dt));
-  ASSERT_CRITICAL (gst_date_time_get_day (dt));
+  fail_unless_equals_int (gst_date_time_get_day (dt), -1);
   fail_if (gst_date_time_has_time (dt));
-  ASSERT_CRITICAL (gst_date_time_get_hour (dt));
-  ASSERT_CRITICAL (gst_date_time_get_minute (dt));
+  fail_unless_equals_int (gst_date_time_get_hour (dt), -1);
+  fail_unless_equals_int (gst_date_time_get_minute (dt), -1);
   fail_if (gst_date_time_has_second (dt));
-  ASSERT_CRITICAL (gst_date_time_get_second (dt));
+  fail_unless_equals_float (gst_date_time_get_second (dt), -1.0);
   gst_date_time_unref (dt);
 
   dt = gst_date_time_new (0.0, 2012, 7, 1, -1, -1, -1);
@@ -777,6 +942,9 @@ gst_date_time_suite (void)
   tcase_add_test (tc_chain, test_GstDateTime_get_utc_offset);
   tcase_add_test (tc_chain, test_GstDateTime_new_from_unix_epoch_local_time);
   tcase_add_test (tc_chain, test_GstDateTime_new_from_unix_epoch_utc);
+  tcase_add_test (tc_chain,
+      test_GstDateTime_new_from_unix_epoch_local_time_usecs);
+  tcase_add_test (tc_chain, test_GstDateTime_new_from_unix_epoch_utc_usecs);
   tcase_add_test (tc_chain, test_GstDateTime_new_full);
   tcase_add_test (tc_chain, test_GstDateTime_now);
   tcase_add_test (tc_chain, test_GstDateTime_utc_now);
@@ -784,6 +952,7 @@ gst_date_time_suite (void)
   tcase_add_test (tc_chain, test_GstDateTime_iso8601);
   tcase_add_test (tc_chain, test_GstDateTime_to_g_date_time);
   tcase_add_test (tc_chain, test_GstDateTime_new_from_g_date_time);
+  tcase_add_test (tc_chain, test_GstDateTime_new_local_time);
 
   return s;
 }
index 2c84cbb..0c4d91f 100644 (file)
@@ -38,11 +38,10 @@ typedef struct _GstTestDeviceClass
 
 GType gst_test_device_get_type (void);
 
+G_DEFINE_TYPE (GstTestDevice, gst_test_device, GST_TYPE_DEVICE);
 
-G_DEFINE_TYPE (GstTestDevice, gst_test_device, GST_TYPE_DEVICE)
-
-     static GstElement *gst_test_device_create_element (GstDevice * device,
-    const gchar * name)
+static GstElement *
+gst_test_device_create_element (GstDevice * device, const gchar * name)
 {
   return gst_bin_new (name);
 }
@@ -140,19 +139,19 @@ typedef struct _GstTestDeviceProviderClass
 
 GType gst_test_device_provider_get_type (void);
 
-
 G_DEFINE_TYPE (GstTestDeviceProvider, gst_test_device_provider,
-    GST_TYPE_DEVICE_PROVIDER)
-
+    GST_TYPE_DEVICE_PROVIDER);
 
-     static GList *devices = NULL;
+int num_devices = 1;
 
-     static GList *gst_test_device_provider_probe (GstDeviceProvider * provider)
+static GList *
+gst_test_device_provider_probe (GstDeviceProvider * provider)
 {
-  GList *devs;
+  int i;
+  GList *devs = NULL;
 
-  devs = g_list_copy (devices);
-  g_list_foreach (devs, (GFunc) gst_object_ref, NULL);
+  for (i = 0; i < num_devices; i++)
+    devs = g_list_prepend (devs, test_device_new ());
 
   return devs;
 }
@@ -175,8 +174,12 @@ gst_test_device_provider_init (GstTestDeviceProvider * self)
 {
 }
 
-static void
-register_test_device_provider (void)
+GST_DEVICE_PROVIDER_REGISTER_DECLARE (testdeviceprovider);
+
+GST_DEVICE_PROVIDER_REGISTER_DEFINE (testdeviceprovider, "testdeviceprovider",
+    1, gst_test_device_provider_get_type ())
+
+     static void register_test_device_provider (void)
 {
   gst_device_provider_register (NULL, "testdeviceprovider", 1,
       gst_test_device_provider_get_type ());
@@ -188,7 +191,7 @@ GST_START_TEST (test_device_provider_factory)
   GList *factories;
   GstDeviceProviderFactory *f;
 
-  register_test_device_provider ();
+  GST_DEVICE_PROVIDER_REGISTER (testdeviceprovider, NULL);
 
   factories = gst_device_provider_factory_list_get_device_providers (1);
 
@@ -233,24 +236,28 @@ GST_START_TEST (test_device_provider)
   register_test_device_provider ();
 
   dp = gst_device_provider_factory_get_by_name ("testdeviceprovider");
+  num_devices = 0;
   fail_unless (dp != NULL);
   fail_unless (gst_device_provider_get_devices (dp) == NULL);
 
-  devices = g_list_append (NULL, test_device_new ());
+  num_devices = 1;
 
   devs = gst_device_provider_get_devices (dp);
   fail_unless (g_list_length (devs) == 1);
-  fail_unless_equals_pointer (devs->data, devices->data);
+  fail_unless (GST_IS_DEVICE (devs->data));
   g_list_free_full (devs, (GDestroyNotify) gst_object_unref);
 
   fail_if (gst_device_provider_can_monitor (dp));
-  fail_if (gst_device_provider_start (dp));
+  fail_if (gst_device_provider_is_started (dp));
+  fail_unless (gst_device_provider_start (dp));
 
   bus = gst_device_provider_get_bus (dp);
   fail_unless (GST_IS_BUS (bus));
   gst_object_unref (bus);
 
-  g_list_free_full (devices, (GDestroyNotify) gst_object_unref);
+  fail_unless (gst_device_provider_is_started (dp));
+  gst_device_provider_stop (dp);
+
   gst_object_unref (dp);
 }
 
@@ -269,13 +276,11 @@ typedef struct _GstTestDeviceProviderMonitorClass
 
 GType gst_test_device_provider_monitor_get_type (void);
 
-
 G_DEFINE_TYPE (GstTestDeviceProviderMonitor, gst_test_device_provider_monitor,
-    GST_TYPE_DEVICE_PROVIDER)
-
+    GST_TYPE_DEVICE_PROVIDER);
 
-     static gboolean
-         gst_test_device_provider_monitor_start (GstDeviceProvider * monitor)
+static gboolean
+gst_test_device_provider_monitor_start (GstDeviceProvider * monitor)
 {
   return TRUE;
 }
@@ -320,8 +325,6 @@ GST_START_TEST (test_device_provider_monitor)
 
   register_test_device_provider_monitor ();
 
-  devices = g_list_append (NULL, test_device_new ());
-
   dp = gst_device_provider_factory_get_by_name ("testdeviceprovidermonitor");
 
   bus = gst_device_provider_get_bus (dp);
@@ -394,8 +397,6 @@ GST_START_TEST (test_device_provider_monitor)
 
   /* Is singleton, so system keeps a ref */
   ASSERT_OBJECT_REFCOUNT (dp, "monitor", 1);
-
-  g_list_free_full (devices, (GDestroyNotify) gst_object_unref);
 }
 
 GST_END_TEST;
@@ -420,8 +421,6 @@ GST_START_TEST (test_device_monitor)
 
   mon = gst_device_monitor_new ();
 
-  devices = g_list_append (NULL, test_device_new ());
-
   devs = gst_device_monitor_get_devices (mon);
   fail_unless (devs == NULL);
 
@@ -440,23 +439,23 @@ GST_START_TEST (test_device_monitor)
   fail_unless (id > 0);
   devs = gst_device_monitor_get_devices (mon);
   fail_unless (g_list_length (devs) == 1);
-  fail_unless_equals_pointer (devs->data, devices->data);
+  fail_unless (GST_IS_DEVICE (devs->data));
   g_list_free_full (devs, (GDestroyNotify) gst_object_unref);
 
   id2 = gst_device_monitor_add_filter (mon, "Test1", NULL);
   fail_unless (id2 > 0);
   devs = gst_device_monitor_get_devices (mon);
   fail_unless (g_list_length (devs) == 2);
-  fail_unless_equals_pointer (devs->data, devices->data);
-  fail_unless_equals_pointer (devs->next->data, devices->data);
+  fail_unless (GST_IS_DEVICE (devs->data));
+  fail_unless (GST_IS_DEVICE (devs->next->data));
   g_list_free_full (devs, (GDestroyNotify) gst_object_unref);
 
   fail_unless (gst_device_monitor_remove_filter (mon, id));
 
   devs = gst_device_monitor_get_devices (mon);
   fail_unless (g_list_length (devs) == 2);
-  fail_unless_equals_pointer (devs->data, devices->data);
-  fail_unless_equals_pointer (devs->next->data, devices->data);
+  fail_unless (GST_IS_DEVICE (devs->data));
+  fail_unless (GST_IS_DEVICE (devs->next->data));
   g_list_free_full (devs, (GDestroyNotify) gst_object_unref);
 
 
@@ -464,7 +463,7 @@ GST_START_TEST (test_device_monitor)
 
   devs = gst_device_monitor_get_devices (mon);
   fail_unless (g_list_length (devs) == 1);
-  fail_unless_equals_pointer (devs->data, devices->data);
+  fail_unless (GST_IS_DEVICE (devs->data));
   g_list_free_full (devs, (GDestroyNotify) gst_object_unref);
 
   gst_device_monitor_stop (mon);
@@ -476,7 +475,7 @@ GST_START_TEST (test_device_monitor)
 
   devs = gst_device_monitor_get_devices (mon);
   fail_unless (g_list_length (devs) == 1);
-  fail_unless_equals_pointer (devs->data, devices->data);
+  fail_unless (GST_IS_DEVICE (devs->data));
   g_list_free_full (devs, (GDestroyNotify) gst_object_unref);
 
   fail_unless (gst_device_monitor_start (mon));
@@ -530,7 +529,6 @@ GST_START_TEST (test_device_monitor)
 
   gst_object_unref (dp);
   gst_object_unref (dp2);
-  g_list_free_full (devices, (GDestroyNotify) gst_object_unref);
 
   /* should work fine without any filters */
   mon = gst_device_monitor_new ();
index fa63ee6..927857b 100644 (file)
@@ -345,8 +345,8 @@ GST_START_TEST (test_pad_templates)
   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_object_unref (test);
+  gst_object_unref (test2);
 }
 
 GST_END_TEST;
@@ -729,7 +729,7 @@ GST_START_TEST (test_request_pad_templates)
     pad_name = (const gchar *) key;
     templ_name = (const gchar *) value;
 
-    pad = gst_element_get_request_pad (GST_ELEMENT (test), pad_name);
+    pad = gst_element_request_pad_simple (GST_ELEMENT (test), pad_name);
     fail_unless (pad != NULL);
     gst_element_release_request_pad (GST_ELEMENT (test), pad);
     gst_object_unref (pad);
@@ -748,7 +748,7 @@ GST_START_TEST (test_request_pad_templates)
   while (item) {
     pad_name = (const gchar *) (item->data);
     item = g_slist_next (item);
-    pad = gst_element_get_request_pad (GST_ELEMENT (test), pad_name);
+    pad = gst_element_request_pad_simple (GST_ELEMENT (test), pad_name);
     fail_unless (pad == NULL);
   }
 
@@ -763,8 +763,8 @@ GST_START_TEST (test_request_pad_templates)
           "sink"));
   gst_element_unlink (GST_ELEMENT (test), sink);
 
-  g_object_unref (test);
-  g_object_unref (sink);
+  gst_object_unref (test);
+  gst_object_unref (sink);
 
   /* gst_parse_launch */
   gst_plugin_register_static (GST_VERSION_MAJOR,
@@ -870,7 +870,7 @@ GST_START_TEST (test_foreach_pad)
   MAIN_START_THREAD_FUNCTION (0, thread_add_remove_pads, e);
   MAIN_SYNCHRONIZE ();
 
-  for (i = 0; i < 10000; ++i) {
+  for (i = 0; i < 1000; ++i) {
     gchar num[32];
 
     g_snprintf (num, 32, "foreach-test-%u", i);
index 294ebf1..7d72247 100644 (file)
@@ -72,7 +72,36 @@ GST_START_TEST (test_create)
   factory = setup_factory ();
   fail_if (factory == NULL);
 
-  g_object_unref (factory);
+  gst_object_unref (factory);
+}
+
+GST_END_TEST;
+
+/* test element creation */
+GST_START_TEST (test_element_factory)
+{
+  GstElement *e, *e_name, *e_prop;
+  const gchar name[] = "source";
+  const int nb = 10;
+  const gboolean do_ts = TRUE;
+  int num_buffers = nb;
+  gboolean do_timestamp = do_ts;
+
+  e = gst_element_factory_make ("fakesrc", NULL);
+  fail_if (e == NULL);
+
+  e_name = gst_element_factory_make ("fakesrc", name);
+  fail_if (e_name == NULL || g_strcmp0 (name, GST_OBJECT_NAME (e_name)) != 0);
+
+  e_prop = gst_element_factory_make_full ("fakesrc",
+      "num-buffers", nb, "do-timestamp", do_ts, NULL);
+  g_object_get (e_prop,
+      "num_buffers", &num_buffers, "do-timestamp", &do_timestamp, NULL);
+  fail_if (e_prop == NULL || num_buffers != nb || do_timestamp != do_ts);
+
+  gst_object_unref (e);
+  gst_object_unref (e_name);
+  gst_object_unref (e_prop);
 }
 
 GST_END_TEST;
@@ -93,7 +122,7 @@ GST_START_TEST (test_can_sink_any_caps)
   fail_if (!res);
   gst_caps_unref (caps);
 
-  g_object_unref (factory);
+  gst_object_unref (factory);
 }
 
 GST_END_TEST;
@@ -114,7 +143,7 @@ GST_START_TEST (test_can_sink_all_caps)
   fail_if (res);
   gst_caps_unref (caps);
 
-  g_object_unref (factory);
+  gst_object_unref (factory);
 }
 
 GST_END_TEST;
@@ -174,6 +203,7 @@ gst_element_factory_suite (void)
   suite_add_tcase (s, tc_chain);
   tcase_add_test (tc_chain, test_class);
   tcase_add_test (tc_chain, test_create);
+  tcase_add_test (tc_chain, test_element_factory);
   tcase_add_test (tc_chain, test_can_sink_any_caps);
   tcase_add_test (tc_chain, test_can_sink_all_caps);
 
index 39b5f30..da56cd0 100644 (file)
@@ -429,13 +429,61 @@ GST_START_TEST (create_events)
     gst_event_unref (event);
     gst_event_unref (event2);
   }
+
+  /* GST_EVENT_INSTANT_RATE_CHANGE */
+  {
+    GstSeekFlags flags = GST_SEEK_FLAG_INSTANT_RATE_CHANGE;
+    GstSegmentFlags new_flags;
+    gdouble rate_multiplier;
+
+    event = gst_event_new_instant_rate_change (1.5, (GstSegmentFlags) flags);
+    fail_if (event == NULL);
+    fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_INSTANT_RATE_CHANGE);
+    fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
+    fail_unless (GST_EVENT_IS_STICKY (event));
+
+    gst_event_parse_instant_rate_change (event, &rate_multiplier, &new_flags);
+    fail_unless (rate_multiplier == 1.5);
+    fail_unless (new_flags == (flags & GST_SEGMENT_INSTANT_FLAGS));
+
+    gst_event_unref (event);
+  }
+
+  /* GST_EVENT_INSTANT_RATE_SYNC_TIME */
+  {
+    GstClockTime running_time;
+    GstClockTime upstream_running_time;
+    gdouble rate_multiplier;
+
+    running_time = 1 * GST_SECOND;
+    upstream_running_time = 2 * GST_SECOND;
+
+    event =
+        gst_event_new_instant_rate_sync_time (1.5, running_time,
+        upstream_running_time);
+    fail_if (event == NULL);
+    fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_INSTANT_RATE_SYNC_TIME);
+    fail_unless (GST_EVENT_IS_UPSTREAM (event));
+
+    /* set some wrong values to check if the parse method overwrites them
+     * with the good values */
+    running_time = upstream_running_time = 3 * GST_SECOND;
+    gst_event_parse_instant_rate_sync_time (event, &rate_multiplier,
+        &running_time, &upstream_running_time);
+    fail_unless (rate_multiplier == 1.5);
+    fail_unless (running_time == 1 * GST_SECOND);
+    fail_unless (upstream_running_time == 2 * GST_SECOND);
+
+    gst_event_unref (event);
+  }
 }
 
 GST_END_TEST;
 
-static GTimeVal sent_event_time;
 static GstEvent *got_event_before_q, *got_event_after_q;
-static GTimeVal got_event_time;
+/* both time are in microseconds */
+static gint64 sent_event_time;
+static gint64 got_event_time;
 
 static GstPadProbeReturn
 event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
@@ -455,7 +503,7 @@ event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
         if (got_event_before_q != NULL)
           break;
         gst_event_ref ((GstEvent *) data);
-        g_get_current_time (&got_event_time);
+        got_event_time = g_get_real_time ();
         got_event_before_q = GST_EVENT (data);
         break;
       default:
@@ -470,7 +518,7 @@ event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
         if (got_event_after_q != NULL)
           break;
         gst_event_ref ((GstEvent *) data);
-        g_get_current_time (&got_event_time);
+        got_event_time = g_get_real_time ();
         got_event_after_q = GST_EVENT (data);
         break;
       default:
@@ -559,9 +607,8 @@ static void test_event
 
   event = gst_event_new_custom (type,
       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;
+  sent_event_time = g_get_real_time ();
+  got_event_time = 0;
 
   signal_data_init (&data);
 
@@ -617,13 +664,6 @@ static void test_event
   signal_data_cleanup (&data);
 }
 
-static gint64
-timediff (GTimeVal * end, GTimeVal * start)
-{
-  return (end->tv_sec - start->tv_sec) * G_USEC_PER_SEC +
-      (end->tv_usec - start->tv_usec);
-}
-
 GST_START_TEST (send_custom_events)
 {
   /* Run some tests on custom events. Checking for serialisation and whatnot.
@@ -660,49 +700,42 @@ GST_START_TEST (send_custom_events)
 
   /* Upstream events */
   test_event (pipeline, GST_EVENT_CUSTOM_UPSTREAM, sinkpad, TRUE, srcpad);
-  fail_unless (timediff (&got_event_time,
-          &sent_event_time) < G_USEC_PER_SEC / 2,
+  fail_unless ((got_event_time - sent_event_time) < G_USEC_PER_SEC / 2,
       "GST_EVENT_CUSTOM_UP took too long to reach source: %"
-      G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
+      G_GINT64_FORMAT " us", got_event_time - sent_event_time);
 
   test_event (pipeline, GST_EVENT_CUSTOM_BOTH, sinkpad, TRUE, srcpad);
-  fail_unless (timediff (&got_event_time,
-          &sent_event_time) < G_USEC_PER_SEC / 2,
+  fail_unless ((got_event_time - sent_event_time) < G_USEC_PER_SEC / 2,
       "GST_EVENT_CUSTOM_BOTH took too long to reach source: %"
-      G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
+      G_GINT64_FORMAT " us", got_event_time - sent_event_time);
 
   test_event (pipeline, GST_EVENT_CUSTOM_BOTH_OOB, sinkpad, TRUE, srcpad);
-  fail_unless (timediff (&got_event_time,
-          &sent_event_time) < G_USEC_PER_SEC / 2,
+  fail_unless ((got_event_time - sent_event_time) < G_USEC_PER_SEC / 2,
       "GST_EVENT_CUSTOM_BOTH_OOB took too long to reach source: %"
-      G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
+      G_GINT64_FORMAT " us", got_event_time - sent_event_time);
 
   /* Out of band downstream events */
   test_event (pipeline, GST_EVENT_CUSTOM_DOWNSTREAM_OOB, srcpad, FALSE, srcpad);
-  fail_unless (timediff (&got_event_time,
-          &sent_event_time) < G_USEC_PER_SEC / 2,
+  fail_unless ((got_event_time - sent_event_time) < G_USEC_PER_SEC / 2,
       "GST_EVENT_CUSTOM_DS_OOB took too long to reach source: %"
-      G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
+      G_GINT64_FORMAT " us", got_event_time - sent_event_time);
 
   test_event (pipeline, GST_EVENT_CUSTOM_BOTH_OOB, srcpad, FALSE, srcpad);
-  fail_unless (timediff (&got_event_time,
-          &sent_event_time) < G_USEC_PER_SEC / 2,
+  fail_unless ((got_event_time - sent_event_time) < G_USEC_PER_SEC / 2,
       "GST_EVENT_CUSTOM_BOTH_OOB took too long to reach source: %"
-      G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
+      G_GINT64_FORMAT " us", got_event_time - sent_event_time);
 
   /* In-band downstream events are expected to take at least 1 second
    * to traverse the queue */
   test_event (pipeline, GST_EVENT_CUSTOM_DOWNSTREAM, srcpad, FALSE, srcpad);
-  fail_unless (timediff (&got_event_time,
-          &sent_event_time) >= G_USEC_PER_SEC / 2,
+  fail_unless ((got_event_time - sent_event_time) >= G_USEC_PER_SEC / 2,
       "GST_EVENT_CUSTOM_DS arrived too quickly for an in-band event: %"
-      G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
+      G_GINT64_FORMAT " us", got_event_time - sent_event_time);
 
   test_event (pipeline, GST_EVENT_CUSTOM_BOTH, srcpad, FALSE, srcpad);
-  fail_unless (timediff (&got_event_time,
-          &sent_event_time) >= G_USEC_PER_SEC / 2,
+  fail_unless ((got_event_time - sent_event_time) >= G_USEC_PER_SEC / 2,
       "GST_EVENT_CUSTOM_BOTH arrived too quickly for an in-band event: %"
-      G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
+      G_GINT64_FORMAT " us", got_event_time - sent_event_time);
 
   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
   gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
index cefd183..04fffde 100644 (file)
@@ -192,7 +192,7 @@ GST_START_TEST (test_ghost_pads_notarget)
   fail_unless (peer == srcpad);
   gst_object_unref (peer);
 
-  /* check caps, untargetted pad should return ANY or the padtemplate caps 
+  /* check caps, untargeted pad should return ANY or the padtemplate caps 
    * when it was created from a template */
   caps = gst_pad_query_caps (srcpad, NULL);
   fail_unless (gst_caps_is_any (caps));
@@ -1393,7 +1393,7 @@ GST_START_TEST (test_deactivate_already_deactive_with_no_parent)
   fail_unless (gst_element_add_pad (bin, pad));
   fail_unless (gst_element_remove_pad (bin, pad));
 
-  /* Setting a pad that's already deactive to deactive should not fail. */
+  /* Setting a pad that's already deactivated to deactivated should not fail. */
   fail_if (gst_pad_is_active (pad));
   fail_unless (gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, FALSE));
 
index 41d5cc5..52f0c3b 100644 (file)
@@ -228,6 +228,41 @@ GST_START_TEST (info_log_handler)
 
 GST_END_TEST;
 
+static void
+compare_gst_log_func (GstDebugCategory * category, GstDebugLevel level,
+    const gchar * file, const gchar * function, gint line, GObject * object,
+    GstDebugMessage * message, gpointer user_data)
+{
+  gboolean match;
+  gchar *log_line;
+
+  fail_unless_equals_pointer (user_data, NULL);
+
+  log_line = gst_debug_log_get_line (category, level, file, function, line,
+      object, message);
+
+  match = g_pattern_match_simple ("*:*:*.*0*DEBUG*check*gstinfo.c:*"
+      ":info_log_handler_get_line: test message\n", log_line);
+  fail_unless_equals_int (match, TRUE);
+  g_free (log_line);
+}
+
+GST_START_TEST (info_log_handler_get_line)
+{
+  gst_debug_remove_log_function (gst_debug_log_default);
+  gst_debug_add_log_function (compare_gst_log_func, NULL, NULL);
+
+  gst_debug_set_default_threshold (GST_LEVEL_LOG);
+  GST_DEBUG ("test message");
+
+  /* clean up */
+  gst_debug_set_default_threshold (GST_LEVEL_NONE);
+  gst_debug_add_log_function (gst_debug_log_default, NULL, NULL);
+  gst_debug_remove_log_function (compare_gst_log_func);
+}
+
+GST_END_TEST;
+
 GST_START_TEST (info_dump_mem)
 {
   GstDebugCategory *cat = NULL;
@@ -480,9 +515,6 @@ GST_START_TEST (info_post_gst_init_category_registration)
     fail_unless_equals_int (gst_debug_category_get_threshold (cats[0xb10]),
         GST_LEVEL_LOG);
   }
-
-  for (i = 0; i < G_N_ELEMENTS (cats); ++i)
-    gst_debug_category_free (cats[i]);
 }
 
 GST_END_TEST;
@@ -501,6 +533,7 @@ gst_info_suite (void)
   tcase_add_test (tc_chain, info_segment_format_printf_extension);
   tcase_add_test (tc_chain, info_ptr_format_printf_extension);
   tcase_add_test (tc_chain, info_log_handler);
+  tcase_add_test (tc_chain, info_log_handler_get_line);
   tcase_add_test (tc_chain, info_dump_mem);
   tcase_add_test (tc_chain, info_fixme);
   tcase_add_test (tc_chain, info_old_printf_extensions);
index 223657a..88e6cf8 100644 (file)
@@ -612,6 +612,21 @@ GST_START_TEST (test_parsing)
     gst_structure_free (test_structure);
     gst_tag_list_unref (test_tag_list);
   }
+  /* GST_MESSAGE_RATE_CHANGE */
+  {
+    gdouble rate_multiplier;
+
+    message = gst_message_new_instant_rate_request (NULL, 1.5);
+    fail_if (message == NULL);
+    fail_unless (GST_MESSAGE_TYPE (message) ==
+        GST_MESSAGE_INSTANT_RATE_REQUEST);
+    fail_unless (GST_MESSAGE_SRC (message) == NULL);
+
+    gst_message_parse_instant_rate_request (message, &rate_multiplier);
+    fail_unless (rate_multiplier == 1.5);
+
+    gst_message_unref (message);
+  }
 }
 
 GST_END_TEST;
index 03af6d7..15c9de2 100644 (file)
@@ -135,7 +135,7 @@ test_transform_func (GstBuffer * transbuf, GstMeta * meta,
 static GType
 gst_meta_test_api_get_type (void)
 {
-  static volatile GType type;
+  static GType type;
   static const gchar *tags[] = { "timing", NULL };
 
   if (g_once_init_enter (&type)) {
@@ -193,7 +193,7 @@ foo_transform_func (GstBuffer * transbuf, GstMeta * meta,
 static GType
 gst_meta_foo_api_get_type (void)
 {
-  static volatile GType type;
+  static GType type;
   static const gchar *tags[] = { NULL };
 
   if (g_once_init_enter (&type)) {
@@ -688,6 +688,115 @@ GST_START_TEST (test_meta_seqnum)
 
 GST_END_TEST;
 
+GST_START_TEST (test_meta_custom)
+{
+  GstBuffer *buffer;
+  const GstMetaInfo *info;
+  GstCustomMeta *meta;
+  GstMeta *it;
+  GstStructure *s, *expected;
+  gpointer state = NULL;
+  const gchar *tags[] = { "test-tag", NULL };
+
+  info = gst_meta_register_custom ("test-custom", tags, NULL, NULL, NULL);
+
+  fail_unless (info != NULL);
+
+  buffer = gst_buffer_new_and_alloc (4);
+  fail_if (buffer == NULL);
+
+  /* add some metadata */
+  meta = gst_buffer_add_custom_meta (buffer, "test-custom");
+  fail_if (meta == NULL);
+
+  fail_unless (gst_custom_meta_has_name ((GstCustomMeta *) meta,
+          "test-custom"));
+
+  expected = gst_structure_new_empty ("test-custom");
+  s = gst_custom_meta_get_structure (meta);
+  fail_unless (gst_structure_is_equal (s, expected));
+  gst_structure_free (expected);
+
+  gst_structure_set (s, "test-field", G_TYPE_INT, 42, NULL);
+  gst_buffer_ref (buffer);
+  ASSERT_CRITICAL (gst_structure_set (s, "test-field", G_TYPE_INT, 43, NULL));
+  gst_buffer_unref (buffer);
+  expected = gst_structure_new ("test-custom",
+      "test-field", G_TYPE_INT, 42, NULL);
+  fail_unless (gst_structure_is_equal (s, expected));
+  gst_structure_free (expected);
+
+  it = gst_buffer_iterate_meta (buffer, &state);
+
+  fail_unless ((GstCustomMeta *) it == meta);
+
+  fail_unless (it->info == info);
+
+  /* clean up */
+  gst_buffer_unref (buffer);
+}
+
+GST_END_TEST;
+
+static gboolean
+transform_custom (GstBuffer * transbuf, GstMeta * meta, GstBuffer * buffer,
+    GQuark type, gpointer data, gint * user_data)
+{
+  if (GST_META_TRANSFORM_IS_COPY (type)) {
+    GstStructure *s;
+    GstCustomMeta *custom;
+
+    custom = (GstCustomMeta *) gst_buffer_add_meta (transbuf, meta->info, NULL);
+    s = gst_custom_meta_get_structure (custom);
+    gst_structure_set (s, "test-field", G_TYPE_INT, *user_data, NULL);
+  } else {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+GST_START_TEST (test_meta_custom_transform)
+{
+  GstBuffer *buffer, *buffer_copy;
+  const GstMetaInfo *info;
+  GstCustomMeta *meta;
+  GstStructure *s, *expected;
+  const gchar *tags[] = { "test-tag", NULL };
+  gint *user_data;
+
+  /* That memory should be deallocated at gst_deinit time */
+  user_data = g_malloc (sizeof (gint));
+  *user_data = 42;
+  info =
+      gst_meta_register_custom ("test-custom", tags,
+      (GstCustomMetaTransformFunction) transform_custom, user_data, g_free);
+
+  fail_unless (info != NULL);
+
+  buffer = gst_buffer_new_and_alloc (4);
+  fail_if (buffer == NULL);
+
+  /* add some metadata */
+  meta = gst_buffer_add_custom_meta (buffer, "test-custom");
+  fail_if (meta == NULL);
+
+  buffer_copy = gst_buffer_copy (buffer);
+  meta = gst_buffer_get_custom_meta (buffer_copy, "test-custom");
+  fail_unless (meta != NULL);
+  expected =
+      gst_structure_new ("test-custom", "test-field", G_TYPE_INT, 42, NULL);
+  s = gst_custom_meta_get_structure (meta);
+  fail_unless (gst_structure_is_equal (s, expected));
+  gst_structure_free (expected);
+
+  /* clean up */
+  gst_buffer_unref (buffer_copy);
+  gst_buffer_unref (buffer);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_buffermeta_suite (void)
 {
@@ -705,6 +814,8 @@ gst_buffermeta_suite (void)
   tcase_add_test (tc_chain, test_meta_foreach_remove_several);
   tcase_add_test (tc_chain, test_meta_iterate);
   tcase_add_test (tc_chain, test_meta_seqnum);
+  tcase_add_test (tc_chain, test_meta_custom);
+  tcase_add_test (tc_chain, test_meta_custom_transform);
 
   return s;
 }
index e2cc14e..93724dc 100644 (file)
@@ -220,7 +220,7 @@ struct _MyBufferPool
 {
   GSList *buffers;
 
-  volatile gboolean is_closed;
+  gboolean is_closed;
 };
 
 static void my_recycle_buffer_destroy (MyRecycleBuffer * buf);
@@ -310,7 +310,7 @@ thread_buffer_producer (MyBufferPool * pool)
     gst_buffer_unref (buf);
   }
 
-  pool->is_closed = TRUE;
+  g_atomic_int_set (&pool->is_closed, TRUE);
 }
 
 static void
@@ -327,7 +327,7 @@ thread_buffer_consumer (MyBufferPool * pool)
 
     THREAD_SWITCH ();
   }
-  while (!pool->is_closed);
+  while (!g_atomic_int_get (&pool->is_closed));
 }
 
 GST_START_TEST (test_recycle_threaded)
index 4acb0d3..3d9660a 100644 (file)
@@ -48,7 +48,7 @@ struct _GstFakeObjectClass
 static GType
 gst_fake_object_get_type (void)
 {
-  static volatile gsize fake_object_type = 0;
+  static gsize fake_object_type = 0;
 
   if (g_once_init_enter (&fake_object_type)) {
     GType type;
@@ -403,7 +403,7 @@ GST_START_TEST (test_fake_object_name_threaded_unique)
   g_free (name1);
 
   /* free stuff */
-  g_list_foreach (object_list, (GFunc) g_object_unref, NULL);
+  g_list_foreach (object_list, (GFunc) gst_object_unref, NULL);
 }
 
 GST_END_TEST;
index 004ff1e..1b1afe6 100644 (file)
@@ -169,15 +169,10 @@ GST_START_TEST (test_get_allowed_caps)
 {
   GstPad *src, *sink;
   GstCaps *caps, *gotcaps;
-  GstBuffer *buffer;
   GstPadLinkReturn plr;
 
   ASSERT_CRITICAL (gst_pad_get_allowed_caps (NULL));
 
-  buffer = gst_buffer_new ();
-  ASSERT_CRITICAL (gst_pad_get_allowed_caps ((GstPad *) buffer));
-  gst_buffer_unref (buffer);
-
   src = gst_pad_new ("src", GST_PAD_SRC);
   fail_if (src == NULL);
   caps = gst_pad_get_allowed_caps (src);
@@ -1729,9 +1724,6 @@ probe_remove_self_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
 {
   gst_pad_remove_probe (pad, info->id);
 
-  fail_unless (pad->num_probes == 0);
-  fail_unless (pad->num_blocked == 0);
-
   return GST_PAD_PROBE_REMOVE;
 }
 
@@ -1769,6 +1761,52 @@ GST_START_TEST (test_pad_probe_remove)
 
 GST_END_TEST;
 
+GST_START_TEST (test_pad_disjoint_blocks_probe_remove)
+{
+  GstPad *pad;
+
+  /* Test that installing 2 separate blocking probes - one on events
+   * and one on buffers, and then removing the blocking event probe
+   * releases the dataflow until a buffer is caught
+   *
+   * https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/658
+   */
+  pad = gst_pad_new ("src", GST_PAD_SRC);
+  fail_unless (pad != NULL);
+
+  gst_pad_set_active (pad, TRUE);
+  fail_unless (pad->num_probes == 0);
+  fail_unless (pad->num_blocked == 0);
+  gst_pad_add_probe (pad,
+      GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
+      probe_remove_self_cb, NULL, probe_remove_notify_cb);
+  fail_unless (pad->num_probes == 1);
+  fail_unless (pad->num_blocked == 1);
+
+  gst_pad_add_probe (pad,
+      GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER,
+      probe_remove_self_cb, NULL, probe_remove_notify_cb);
+  fail_unless (pad->num_probes == 2);
+  fail_unless (pad->num_blocked == 2);
+
+  pad_probe_remove_notifiy_called = FALSE;
+  gst_pad_push_event (pad, gst_event_new_stream_start ("asda"));
+
+  fail_unless (gst_pad_push_event (pad,
+          gst_event_new_segment (&dummy_segment)) == TRUE);
+
+  pad_probe_remove_notifiy_called = FALSE;
+  gst_pad_push (pad, gst_buffer_new ());
+
+  fail_unless (pad->num_probes == 0);
+  fail_unless (pad->num_blocked == 0);
+
+  gst_object_unref (pad);
+}
+
+GST_END_TEST;
+
+
 typedef struct
 {
   gulong probe_id;
@@ -2661,11 +2699,13 @@ GST_START_TEST (test_last_flow_return_push)
 
   /* initial value is flushing */
   fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_FLUSHING);
+  fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_FLUSHING);
 
   /* when active it goes to ok */
   gst_pad_set_active (srcpad, TRUE);
   fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_OK);
   gst_pad_set_active (sinkpad, TRUE);
+  fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_OK);
 
   /* startup events */
   gst_pad_push_event (srcpad, gst_event_new_stream_start ("test"));
@@ -2677,11 +2717,13 @@ GST_START_TEST (test_last_flow_return_push)
   next_return = GST_FLOW_OK;
   fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_OK);
   fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_OK);
+  fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_OK);
 
   /* push not-linked */
   next_return = GST_FLOW_NOT_LINKED;
   fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_NOT_LINKED);
   fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_NOT_LINKED);
+  fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_NOT_LINKED);
 
   /* push not-linked */
   next_return = GST_FLOW_NOT_NEGOTIATED;
@@ -2689,25 +2731,32 @@ GST_START_TEST (test_last_flow_return_push)
           gst_buffer_new ()) == GST_FLOW_NOT_NEGOTIATED);
   fail_unless (gst_pad_get_last_flow_return (srcpad) ==
       GST_FLOW_NOT_NEGOTIATED);
+  fail_unless (gst_pad_get_last_flow_return (sinkpad) ==
+      GST_FLOW_NOT_NEGOTIATED);
 
   /* push error */
   next_return = GST_FLOW_ERROR;
   fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_ERROR);
   fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_ERROR);
+  fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_ERROR);
 
   /* back to ok */
   next_return = GST_FLOW_OK;
   fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_OK);
   fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_OK);
+  fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_OK);
 
   /* unlinked push */
   gst_pad_unlink (srcpad, sinkpad);
   fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_NOT_LINKED);
   fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_NOT_LINKED);
+  /* The last flow ret from the peer pad shouldn't have changed */
+  fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_OK);
 
   gst_pad_link (srcpad, sinkpad);
   fail_unless (gst_pad_push_event (srcpad, gst_event_new_eos ()));
   fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_EOS);
+  fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_EOS);
 
   gst_object_unref (srcpad);
   gst_object_unref (sinkpad);
@@ -2746,17 +2795,20 @@ GST_START_TEST (test_last_flow_return_pull)
   gst_pad_link (srcpad, sinkpad);
 
   /* initial value is flushing */
+  fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_FLUSHING);
   fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_FLUSHING);
 
   /* when active it goes to ok */
   gst_pad_set_active (sinkpad, TRUE);
   fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_OK);
   gst_pad_set_active (srcpad, TRUE);
+  fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_OK);
 
   /* pull Ok */
   next_return = GST_FLOW_OK;
   fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_OK);
   fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_OK);
+  fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_OK);
   gst_buffer_unref (buf);
   buf = NULL;
 
@@ -2764,11 +2816,13 @@ GST_START_TEST (test_last_flow_return_pull)
   next_return = GST_FLOW_NOT_LINKED;
   fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_NOT_LINKED);
   fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_NOT_LINKED);
+  fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_NOT_LINKED);
 
   /* pull error */
   next_return = GST_FLOW_ERROR;
   fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_ERROR);
   fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_ERROR);
+  fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_ERROR);
 
   /* pull not-nego */
   next_return = GST_FLOW_NOT_NEGOTIATED;
@@ -2776,11 +2830,14 @@ GST_START_TEST (test_last_flow_return_pull)
           &buf) == GST_FLOW_NOT_NEGOTIATED);
   fail_unless (gst_pad_get_last_flow_return (sinkpad) ==
       GST_FLOW_NOT_NEGOTIATED);
+  fail_unless (gst_pad_get_last_flow_return (srcpad) ==
+      GST_FLOW_NOT_NEGOTIATED);
 
   /* pull ok again */
   next_return = GST_FLOW_OK;
   fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_OK);
   fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_OK);
+  fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_OK);
   gst_buffer_unref (buf);
   buf = NULL;
 
@@ -2788,12 +2845,15 @@ GST_START_TEST (test_last_flow_return_pull)
   gst_pad_unlink (srcpad, sinkpad);
   fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_NOT_LINKED);
   fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_NOT_LINKED);
+  /* Return value for the remote pad didn't change */
+  fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_OK);
 
   /* eos */
   gst_pad_link (srcpad, sinkpad);
   next_return = GST_FLOW_EOS;
   fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_EOS);
   fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_EOS);
+  fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_EOS);
 
   gst_object_unref (srcpad);
   gst_object_unref (sinkpad);
@@ -3352,6 +3412,7 @@ gst_pad_suite (void)
   tcase_add_test (tc_chain, test_pad_probe_pull_idle);
   tcase_add_test (tc_chain, test_pad_probe_pull_buffer);
   tcase_add_test (tc_chain, test_pad_probe_remove);
+  tcase_add_test (tc_chain, test_pad_disjoint_blocks_probe_remove);
   tcase_add_test (tc_chain, test_pad_probe_block_add_remove);
   tcase_add_test (tc_chain, test_pad_probe_block_and_drop_buffer);
   tcase_add_test (tc_chain, test_pad_probe_flush_events);
index 696c62b..fc82985 100644 (file)
@@ -114,7 +114,7 @@ GST_START_TEST (test_param_spec_fraction)
   fail_unless_equals_int (n, 15);
   fail_unless_equals_int (d, 8);
 
-  g_object_unref (obj);
+  gst_object_unref (obj);
 }
 
 GST_END_TEST static Suite *
index 808dfb1..840e886 100644 (file)
@@ -114,7 +114,7 @@ gst_preset_test_base_init (GstPresetTestClass * klass)
 static GType
 gst_preset_test_get_type (void)
 {
-  static volatile gsize preset_test_type = 0;
+  static gsize preset_test_type = 0;
 
   if (g_once_init_enter (&preset_test_type)) {
     GType type;
index 3e01df0..b973dda 100644 (file)
@@ -44,7 +44,9 @@ test_printf (const char *format, ...)
   len = __gst_vasprintf (&str, format, varargs);
   va_end (varargs);
 
-  if (len <= 0)
+  /* The length doesn't include the final `\0`, so if it's >= 0 it's allocated
+   * and non-NULL */
+  if (len < 0)
     return NULL;
 
   GST_INFO ("[%s]", str);
index 7653399..25e6f11 100644 (file)
@@ -162,12 +162,13 @@ GST_START_TEST (test_reply_data)
   r = gst_promise_new ();
 
   s = gst_structure_new ("promise", "test", G_TYPE_INT, 1, NULL);
-  gst_promise_reply (r, s);
+  gst_promise_reply (r, gst_structure_copy (s));
   fail_unless (gst_promise_wait (r) == GST_PROMISE_RESULT_REPLIED);
   ret = gst_promise_get_reply (r);
   fail_unless (gst_structure_is_equal (ret, s));
 
   gst_promise_unref (r);
+  gst_structure_free (s);
 }
 
 GST_END_TEST;
index 1669c81..51908e9 100644 (file)
@@ -96,7 +96,7 @@ gst_protection_test_base_init (GstProtectionTestClass * klass)
 static GType
 gst_protection_test_get_type (void)
 {
-  static volatile gsize protection_test_type = 0;
+  static gsize protection_test_type = 0;
 
   if (g_once_init_enter (&protection_test_type)) {
     GType type;
index ac46b7d..229b270 100644 (file)
@@ -675,6 +675,19 @@ GST_START_TEST (segment_seek_noupdate)
   fail_unless_equals_uint64 (segment.position, 50);
   fail_unless_equals_uint64 (segment.base, 0);
   fail_unless_equals_uint64 (segment.offset, 50);
+
+  /* FALSE should be returned when GST_SEEK_FLAG_INSTANT_RATE_CHANGE */
+  fail_unless (gst_segment_do_seek (&segment, 1.5,
+          GST_FORMAT_TIME,
+          GST_SEEK_FLAG_INSTANT_RATE_CHANGE,
+          GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0, NULL) == FALSE);
+  fail_unless (segment.format == GST_FORMAT_TIME);
+  fail_unless_equals_uint64 (segment.start, 0);
+  fail_unless_equals_uint64 (segment.stop, 200);
+  fail_unless_equals_uint64 (segment.time, 0);
+  fail_unless_equals_uint64 (segment.position, 50);
+  fail_unless_equals_uint64 (segment.base, 0);
+  fail_unless_equals_uint64 (segment.offset, 50);
 }
 
 GST_END_TEST;
index b871636..d9531ec 100644 (file)
@@ -161,6 +161,37 @@ GST_START_TEST (test_from_string)
   fail_unless_equals_int (g_value_get_boolean (val), TRUE);
   gst_structure_free (structure);
 
+  /* Test trailing comas */
+  s = "test-string,";
+  structure = gst_structure_from_string (s, NULL);
+  fail_if (structure == NULL, "Could not get structure from string %s", s);
+  gst_structure_free (structure);
+
+  s = "test-string,;";
+  structure = gst_structure_from_string (s, NULL);
+  fail_if (structure == NULL, "Could not get structure from string %s", s);
+  gst_structure_free (structure);
+
+  s = "test-string,value=true,";
+  structure = gst_structure_from_string (s, NULL);
+  fail_if (structure == NULL, "Could not get structure from string %s", s);
+  fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL);
+  fail_unless (G_VALUE_HOLDS_BOOLEAN (val));
+  fail_unless_equals_int (g_value_get_boolean (val), TRUE);
+  gst_structure_free (structure);
+
+  s = "test-string,value=true,;";
+  structure = gst_structure_from_string (s, NULL);
+  fail_if (structure == NULL, "Could not get structure from string %s", s);
+  fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL);
+  fail_unless (G_VALUE_HOLDS_BOOLEAN (val));
+  fail_unless_equals_int (g_value_get_boolean (val), TRUE);
+  gst_structure_free (structure);
+
+  s = "test-string,value=true,,";
+  structure = gst_structure_from_string (s, NULL);
+  fail_unless (structure == NULL, "Created structure from string %s", s);
+
   /* Tests for flagset deserialisation */
   s = "foobar,value=0010:ffff";
   structure = gst_structure_from_string (s, NULL);
@@ -192,6 +223,21 @@ GST_START_TEST (test_from_string)
   ASSERT_CRITICAL (structure = gst_structure_from_string (s, NULL));
   fail_unless (structure == NULL, "Could not get structure from string %s", s);
 
+  /* Test that escaping works both with and without a type */
+  s = "foo/bar, value=\"raven \\\"nevermore\\\"\"";
+  structure = gst_structure_from_string (s, NULL);
+  fail_if (structure == NULL, "Could not get structure from string %s", s);
+  fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL);
+  fail_unless (G_VALUE_HOLDS_STRING (val));
+  gst_structure_free (structure);
+
+  s = "foo/bar, value=(string)\"raven \\\"nevermore\\\"\"";
+  structure = gst_structure_from_string (s, NULL);
+  fail_if (structure == NULL, "Could not get structure from string %s", s);
+  fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL);
+  fail_unless (G_VALUE_HOLDS_STRING (val));
+  gst_structure_free (structure);
+
   /* make sure we bail out correctly in case of an error or if parsing fails */
   s = "***foo***, abc=(boolean)false";
   structure = gst_structure_from_string (s, NULL);
@@ -723,6 +769,41 @@ GST_START_TEST (test_structure_nested_from_and_to_string)
 
 GST_END_TEST;
 
+GST_START_TEST (test_serialize_nested_structures)
+{
+  GstStructure *s;
+  const gchar *str1;
+  gchar *str2, *end = NULL;
+
+  str1 = "main"
+      ", main-sub1=(structure)[type-b, machine-type=(int)0;]"
+      ", main-sub2=(structure)[type-a, plugin-filename=(string)\"/home/user/lib/lib\\ with\\ spaces.dll\", machine-type=(int)1;]"
+      ", main-sub3=(structure)[type-b, plugin-filename=(string)/home/user/lib/lib_no_spaces.so, machine-type=(int)1;]"
+      ";";
+
+  s = gst_structure_from_string (str1, &end);
+  fail_unless (s != NULL);
+
+  GST_DEBUG ("not parsed part : %s", end);
+  fail_unless (*end == '\0');
+
+  fail_unless (gst_structure_n_fields (s) == 3);
+
+  fail_unless (gst_structure_has_field_typed (s, "main-sub1",
+          GST_TYPE_STRUCTURE));
+
+  str2 = gst_structure_serialize (s, GST_SERIALIZE_FLAG_NONE);
+  fail_unless (str2 != NULL);
+
+  fail_unless (g_str_equal (str1, str2));
+
+  g_free (str2);
+
+  gst_structure_free (s);
+}
+
+GST_END_TEST;
+
 GST_START_TEST (test_vararg_getters)
 {
   GstStructure *s;
@@ -963,6 +1044,7 @@ gst_structure_suite (void)
   tcase_add_test (tc_chain, test_is_subset_superset_extra_values);
   tcase_add_test (tc_chain, test_structure_nested);
   tcase_add_test (tc_chain, test_structure_nested_from_and_to_string);
+  tcase_add_test (tc_chain, test_serialize_nested_structures);
   tcase_add_test (tc_chain, test_vararg_getters);
   tcase_add_test (tc_chain, test_foreach);
   tcase_add_test (tc_chain, test_map_in_place);
index 59b3af1..2307a63 100644 (file)
@@ -65,61 +65,6 @@ GST_START_TEST (test_signedness)
 
 GST_END_TEST;
 
-#define TIME_UNIT (GST_SECOND / 5)
-static void
-gst_clock_debug (GstClock * clock)
-{
-  GstClockTime time;
-
-  time = gst_clock_get_time (clock);
-  GST_DEBUG ("Clock info: time %" GST_TIME_FORMAT, GST_TIME_ARGS (time));
-}
-
-static gboolean
-ok_callback (GstClock * clock, GstClockTime time,
-    GstClockID id, gpointer user_data)
-{
-  GST_LOG ("unlocked async id %p", id);
-  return FALSE;
-}
-
-static gboolean
-error_callback (GstClock * clock, GstClockTime time,
-    GstClockID id, gpointer user_data)
-{
-  GST_WARNING ("unlocked unscheduled async id %p, this is wrong", id);
-  fail_if (TRUE);
-
-  return FALSE;
-}
-
-GMutex store_lock;
-
-static gboolean
-store_callback (GstClock * clock, GstClockTime time,
-    GstClockID id, gpointer user_data)
-{
-  GList **list = user_data;
-
-  GST_DEBUG ("unlocked async id %p", id);
-  g_mutex_lock (&store_lock);
-  *list = g_list_append (*list, id);
-  g_mutex_unlock (&store_lock);
-  return FALSE;
-}
-
-static gboolean
-notify_callback (GstClock * clock, GstClockTime time,
-    GstClockID id, gpointer user_data)
-{
-  gboolean *ret = (gboolean *) user_data;
-
-  if (ret != NULL)
-    *ret = TRUE;
-
-  return FALSE;
-}
-
 GST_START_TEST (test_set_default)
 {
   GstClock *clock, *static_clock;
@@ -136,11 +81,11 @@ GST_START_TEST (test_set_default)
   gst_object_ref_sink (clock);
   gst_system_clock_set_default (clock);
   g_assert_cmpint (GST_OBJECT_REFCOUNT (static_clock), ==, 1);
-  g_object_unref (static_clock);
+  gst_object_unref (static_clock);
   static_clock = gst_system_clock_obtain ();
   fail_unless (static_clock == clock);
   g_assert_cmpint (GST_OBJECT_REFCOUNT (clock), ==, 3);
-  g_object_unref (static_clock);
+  gst_object_unref (static_clock);
 
   /* Reset the default clock to the static one */
   gst_system_clock_set_default (NULL);
@@ -148,415 +93,8 @@ GST_START_TEST (test_set_default)
   fail_unless (static_clock != clock);
   g_assert_cmpint (GST_OBJECT_REFCOUNT (clock), ==, 1);
   g_assert_cmpint (GST_OBJECT_REFCOUNT (static_clock), ==, 2);
-  g_object_unref (clock);
-  g_object_unref (static_clock);
-}
-
-GST_END_TEST;
-
-GST_START_TEST (test_single_shot)
-{
-  GstClock *clock;
-  GstClockID id, id2;
-  GstClockTime base;
-  GstClockReturn result;
-
-  clock = gst_system_clock_obtain ();
-  fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
-
-  gst_clock_debug (clock);
-  base = gst_clock_get_time (clock);
-
-  id = gst_clock_new_single_shot_id (clock, base + TIME_UNIT);
-  fail_unless (id != NULL, "Could not create single shot id");
-
-  GST_DEBUG ("waiting one time unit");
-  result = gst_clock_id_wait (id, NULL);
-  gst_clock_debug (clock);
-  fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK (result=%d)",
-      result);
-  fail_unless (gst_clock_get_time (clock) > (base + TIME_UNIT),
-      "target time has not been reached");
-
-  GST_DEBUG ("waiting in the past");
-  result = gst_clock_id_wait (id, NULL);
-  gst_clock_debug (clock);
-  fail_unless (result == GST_CLOCK_EARLY,
-      "Waiting did not return EARLY(result=%d)", result);
-  gst_clock_id_unref (id);
-
-  id = gst_clock_new_single_shot_id (clock, base + 2 * TIME_UNIT);
-  GST_DEBUG ("waiting one second async id %p", id);
-  result = gst_clock_id_wait_async (id, ok_callback, NULL, NULL);
-  fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-  g_usleep (TIME_UNIT / (2 * 1000));
-  gst_clock_id_unschedule (id);
-  gst_clock_id_unref (id);
-
-  id = gst_clock_new_single_shot_id (clock, base + 5 * TIME_UNIT);
-  GST_DEBUG ("waiting one second async, with cancel on id %p", id);
-  result = gst_clock_id_wait_async (id, error_callback, NULL, NULL);
-  fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-  g_usleep (TIME_UNIT / (2 * 1000));
-  GST_DEBUG ("cancel id %p after half a time unit", id);
-  gst_clock_id_unschedule (id);
-  gst_clock_id_unref (id);
-  GST_DEBUG ("canceled id %p", id);
-
-  GST_DEBUG ("waiting multiple one second async, with cancel");
-  id = gst_clock_new_single_shot_id (clock, base + 5 * TIME_UNIT);
-  id2 = gst_clock_new_single_shot_id (clock, base + 6 * TIME_UNIT);
-  GST_DEBUG ("waiting id %p", id);
-  result = gst_clock_id_wait_async (id, ok_callback, NULL, NULL);
-  fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-
-  GST_DEBUG ("waiting id %p", id2);
-  result = gst_clock_id_wait_async (id2, error_callback, NULL, NULL);
-  fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-  g_usleep (TIME_UNIT / (2 * 1000));
-  GST_DEBUG ("cancel id %p after half a time unit", id2);
-  gst_clock_id_unschedule (id2);
-  GST_DEBUG ("canceled id %p", id2);
-  gst_clock_id_unref (id2);
-
-  /* wait for the entry to time out */
-  g_usleep (TIME_UNIT / 1000 * 5);
-  fail_unless (((GstClockEntry *) id)->status == GST_CLOCK_OK,
-      "Waiting did not finish");
-  gst_clock_id_unref (id);
-
-  gst_object_unref (clock);
-}
-
-GST_END_TEST;
-
-GST_START_TEST (test_periodic_shot)
-{
-  GstClock *clock;
-  GstClockID id, id2;
-  GstClockTime base;
-  GstClockReturn result;
-
-  clock = gst_system_clock_obtain ();
-  fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
-
-  gst_clock_debug (clock);
-  base = gst_clock_get_time (clock);
-
-  /* signal every half a time unit */
-  id = gst_clock_new_periodic_id (clock, base + TIME_UNIT, TIME_UNIT / 2);
-  fail_unless (id != NULL, "Could not create periodic id");
-
-  GST_DEBUG ("waiting one time unit");
-  result = gst_clock_id_wait (id, NULL);
-  gst_clock_debug (clock);
-  fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-
-  GST_DEBUG ("waiting for the next");
-  result = gst_clock_id_wait (id, NULL);
-  gst_clock_debug (clock);
-  fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-
-  GST_DEBUG ("waiting for the next async %p", id);
-  result = gst_clock_id_wait_async (id, ok_callback, NULL, NULL);
-  fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-  g_usleep (TIME_UNIT / (2 * 1000));
-
-  GST_DEBUG ("waiting some more for the next async %p", id);
-  result = gst_clock_id_wait_async (id, ok_callback, NULL, NULL);
-  fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-  g_usleep (TIME_UNIT / (2 * 1000));
-
-  id2 = gst_clock_new_periodic_id (clock, base + TIME_UNIT, TIME_UNIT / 2);
-  fail_unless (id2 != NULL, "Could not create second periodic id");
-
-  GST_DEBUG ("waiting some more for another async %p", id2);
-  result = gst_clock_id_wait_async (id2, ok_callback, NULL, NULL);
-  fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-  g_usleep (TIME_UNIT / (2 * 1000));
-
-  GST_DEBUG ("unschedule %p", id);
-  gst_clock_id_unschedule (id);
-
-  /* entry cannot be used again */
-  result = gst_clock_id_wait_async (id, error_callback, NULL, NULL);
-  fail_unless (result == GST_CLOCK_UNSCHEDULED,
-      "Waiting did not return UNSCHEDULED");
-  result = gst_clock_id_wait (id, NULL);
-  fail_unless (result == GST_CLOCK_UNSCHEDULED,
-      "Waiting did not return UNSCHEDULED");
-  g_usleep (TIME_UNIT / (2 * 1000));
-
-  /* clean up */
-  gst_clock_id_unref (id);
-  gst_clock_id_unschedule (id2);
-  gst_clock_id_unref (id2);
-
-  gst_object_unref (clock);
-}
-
-GST_END_TEST;
-
-GST_START_TEST (test_async_order)
-{
-  GstClock *clock;
-  GstClockID id1, id2;
-  GList *cb_list = NULL, *next;
-  GstClockTime base;
-  GstClockReturn result;
-
-  clock = gst_system_clock_obtain ();
-  fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
-
-  gst_clock_debug (clock);
-  base = gst_clock_get_time (clock);
-
-  id1 = gst_clock_new_single_shot_id (clock, base + 2 * TIME_UNIT);
-  id2 = gst_clock_new_single_shot_id (clock, base + 1 * TIME_UNIT);
-  result = gst_clock_id_wait_async (id1, store_callback, &cb_list, NULL);
-  fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-  g_usleep (TIME_UNIT / (2 * 1000));
-  result = gst_clock_id_wait_async (id2, store_callback, &cb_list, NULL);
-  fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-  g_usleep (TIME_UNIT / 1000);
-  /* at this point at least one of the timers should have timed out */
-  g_mutex_lock (&store_lock);
-  fail_unless (cb_list != NULL, "expected notification");
-  fail_unless (cb_list->data == id2,
-      "Expected notification for id2 to come first");
-  g_mutex_unlock (&store_lock);
-  g_usleep (TIME_UNIT / 1000);
-  g_mutex_lock (&store_lock);
-  /* now both should have timed out */
-  next = g_list_next (cb_list);
-  fail_unless (next != NULL, "expected second notification");
-  fail_unless (next->data == id1, "Missing notification for id1");
-  g_mutex_unlock (&store_lock);
-
-  gst_clock_id_unref (id1);
-  gst_clock_id_unref (id2);
-  g_list_free (cb_list);
-
-  gst_object_unref (clock);
-}
-
-GST_END_TEST;
-
-GST_START_TEST (test_async_order_stress_test)
-{
-#define ALARM_COUNT 20
-  GstClock *clock;
-  GstClockID id[ALARM_COUNT];
-  GList *cb_list = NULL, *cb_list_it;
-  GstClockTime base;
-  GstClockReturn result;
-  unsigned int i;
-
-  clock = gst_system_clock_obtain ();
-  fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
-
-  gst_clock_debug (clock);
-  base = gst_clock_get_time (clock);
-
-  /* keep inserting at the beginning of the list.
-   * We expect the alarm thread to keep detecting the new entries and to
-   * switch to wait on the first entry on the list
-   */
-  for (i = ALARM_COUNT; i > 0; --i) {
-    id[i - 1] = gst_clock_new_single_shot_id (clock, base + i * TIME_UNIT);
-    result =
-        gst_clock_id_wait_async (id[i - 1], store_callback, &cb_list, NULL);
-    fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-  }
-
-  g_usleep (TIME_UNIT * (ALARM_COUNT + 1) / 1000);
-  /* at this point all the timers should have timed out */
-  g_mutex_lock (&store_lock);
-  fail_unless (cb_list != NULL, "expected notification");
-  cb_list_it = cb_list;
-  /* alarms must trigger in order.
-   * Will fail if alarm thread did not properly switch to wait on first entry
-   * from the list
-   */
-  for (i = 0; i < ALARM_COUNT; ++i) {
-    fail_unless (cb_list_it != NULL, "No notification received for id[%d]", i);
-    fail_unless (cb_list_it->data == id[i],
-        "Expected notification for id[%d]", i);
-    cb_list_it = g_list_next (cb_list_it);
-  }
-  g_mutex_unlock (&store_lock);
-
-  for (i = 0; i < ALARM_COUNT; ++i)
-    gst_clock_id_unref (id[i]);
-  g_list_free (cb_list);
-
-  gst_object_unref (clock);
-}
-
-GST_END_TEST;
-
-struct test_async_sync_interaction_data
-{
-  GMutex lock;
-
-  GstClockID sync_id;
-  GstClockID sync_id2;
-
-  GstClockID async_id;
-  GstClockID async_id2;
-  GstClockID async_id3;
-};
-
-static gboolean
-test_async_sync_interaction_cb (GstClock * clock, GstClockTime time,
-    GstClockID id, gpointer user_data)
-{
-  struct test_async_sync_interaction_data *td =
-      (struct test_async_sync_interaction_data *) (user_data);
-
-  g_mutex_lock (&td->lock);
-  /* The first async callback is ignored */
-  if (id == td->async_id)
-    goto out;
-
-  if (id != td->async_id2 && id != td->async_id3)
-    goto out;
-
-  /* Unschedule the sync callback */
-  if (id == td->async_id3) {
-    gst_clock_id_unschedule (td->sync_id);
-    gst_clock_id_unschedule (td->async_id2);
-  }
-out:
-  g_mutex_unlock (&td->lock);
-  return FALSE;
-}
-
-GST_START_TEST (test_async_sync_interaction)
-{
-  /* This test schedules an async callback, then before it completes, schedules
-   * an earlier async callback, and quickly unschedules the first, and inserts
-   * a THIRD even earlier async callback. It then attempts to wait on a
-   * sync clock ID. While that's sleeping, the 3rd async callback should fire
-   * and unschedule it. This tests for problems with unscheduling async and
-   * sync callbacks on the system clock. */
-  GstClock *clock;
-  GstClockReturn result;
-  GstClockTime base;
-  GstClockTimeDiff jitter;
-  struct test_async_sync_interaction_data td;
-  int i;
-
-  clock = gst_system_clock_obtain ();
-  fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
-
-  g_mutex_init (&td.lock);
-
-  for (i = 0; i < 50; i++) {
-    gst_clock_debug (clock);
-    base = gst_clock_get_time (clock);
-    g_mutex_lock (&td.lock);
-    td.async_id = gst_clock_new_single_shot_id (clock, base + 40 * GST_MSECOND);
-    td.async_id2 =
-        gst_clock_new_single_shot_id (clock, base + 30 * GST_MSECOND);
-    td.async_id3 =
-        gst_clock_new_single_shot_id (clock, base + 20 * GST_MSECOND);
-    td.sync_id2 = gst_clock_new_single_shot_id (clock, base + 10 * GST_MSECOND);
-    td.sync_id = gst_clock_new_single_shot_id (clock, base + 50 * GST_MSECOND);
-    g_mutex_unlock (&td.lock);
-
-    result = gst_clock_id_wait_async (td.async_id,
-        test_async_sync_interaction_cb, &td, NULL);
-    fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-
-    /* Wait 10ms, then unschedule async_id and schedule async_id2 */
-    result = gst_clock_id_wait (td.sync_id2, &jitter);
-    fail_unless (result == GST_CLOCK_OK || result == GST_CLOCK_EARLY,
-        "Waiting did not return OK or EARLY");
-    /* async_id2 is earlier than async_id - should become head of the queue */
-    result = gst_clock_id_wait_async (td.async_id2,
-        test_async_sync_interaction_cb, &td, NULL);
-    fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-    gst_clock_id_unschedule (td.async_id);
-
-    /* async_id3 is earlier than async_id2 - should become head of the queue */
-    result = gst_clock_id_wait_async (td.async_id3,
-        test_async_sync_interaction_cb, &td, NULL);
-    fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-
-    /* While this is sleeping, the async3 id should fire and unschedule it */
-    result = gst_clock_id_wait (td.sync_id, &jitter);
-    fail_unless (result == GST_CLOCK_UNSCHEDULED || result == GST_CLOCK_EARLY,
-        "Waiting did not return UNSCHEDULED (was %d)", result);
-
-    gst_clock_id_unschedule (td.async_id3);
-    g_mutex_lock (&td.lock);
-
-    gst_clock_id_unref (td.sync_id);
-    gst_clock_id_unref (td.sync_id2);
-    gst_clock_id_unref (td.async_id);
-    gst_clock_id_unref (td.async_id2);
-    gst_clock_id_unref (td.async_id3);
-    g_mutex_unlock (&td.lock);
-  }
-
-  g_mutex_clear (&td.lock);
-  gst_object_unref (clock);
-}
-
-GST_END_TEST;
-
-GST_START_TEST (test_periodic_multi)
-{
-  GstClock *clock;
-  GstClockID clock_id;
-  GstClockID clock_id_async;
-  GstClockTime base;
-  GstClockReturn result;
-  gboolean got_callback = FALSE;
-
-  clock = gst_system_clock_obtain ();
-  fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
-
-  gst_clock_debug (clock);
-  base = gst_clock_get_time (clock);
-
-  clock_id = gst_clock_new_periodic_id (clock, base + TIME_UNIT, TIME_UNIT);
-  gst_clock_id_wait (clock_id, NULL);
-  fail_unless (gst_clock_get_time (clock) >= base + TIME_UNIT);
-  fail_unless (gst_clock_get_time (clock) < base + 2 * TIME_UNIT);
-
-  /* now perform a concurrent wait and wait_async */
-
-  clock_id_async =
-      gst_clock_new_periodic_id (clock, base + TIME_UNIT, TIME_UNIT);
-  result =
-      gst_clock_id_wait_async (clock_id_async, notify_callback, &got_callback,
-      NULL);
-  fail_unless (result == GST_CLOCK_OK, "Async waiting did not return OK");
-
-  result = gst_clock_id_wait (clock_id, NULL);
-  fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-  fail_unless (gst_clock_get_time (clock) >= base + 2 * TIME_UNIT);
-  /* give the async thread some time to call our callback: */
-  g_usleep (TIME_UNIT / (10 * 1000));
-  fail_unless (got_callback == TRUE, "got no async callback (1)");
-  fail_unless (gst_clock_get_time (clock) < base + 3 * TIME_UNIT);
-  got_callback = FALSE;
-
-  result = gst_clock_id_wait (clock_id, NULL);
-  fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
-  fail_unless (gst_clock_get_time (clock) >= base + 3 * TIME_UNIT);
-  /* give the async thread some time to call our callback: */
-  g_usleep (TIME_UNIT / (10 * 1000));
-  fail_unless (got_callback == TRUE, "got no async callback (2)");
-  fail_unless (gst_clock_get_time (clock) < base + 4 * TIME_UNIT);
-
-  /* clean up */
-  gst_clock_id_unref (clock_id);
-  gst_clock_id_unschedule (clock_id_async);
-  gst_clock_id_unref (clock_id_async);
   gst_object_unref (clock);
+  gst_object_unref (static_clock);
 }
 
 GST_END_TEST;
@@ -578,76 +116,6 @@ GST_START_TEST (test_diff)
 
 GST_END_TEST;
 
-/* test if a blocking wait, unblocked by an async entry continues to be
- * scheduled */
-typedef struct
-{
-  GstClock *clock;
-  GstClockID id;
-  GstClockTimeDiff jitter;
-  GstClockReturn ret;
-} MixedInfo;
-
-static gpointer
-mixed_thread (MixedInfo * info)
-{
-  info->ret = gst_clock_id_wait (info->id, &info->jitter);
-  return NULL;
-}
-
-static gboolean
-mixed_async_cb (GstClock * clock, GstClockTime time,
-    GstClockID id, gpointer user_data)
-{
-  return TRUE;
-}
-
-GST_START_TEST (test_mixed)
-{
-  GThread *thread;
-  GError *error = NULL;
-  MixedInfo info;
-  GstClockTime base;
-  GstClockID id;
-
-  info.clock = gst_system_clock_obtain ();
-  fail_unless (info.clock != NULL,
-      "Could not create instance of GstSystemClock");
-
-  /* get current time of the clock as base time */
-  base = gst_clock_get_time (info.clock);
-
-  /* create entry to wait for 1 second */
-  info.id = gst_clock_new_single_shot_id (info.clock, base + GST_SECOND);
-
-  /* make and start an entry that is scheduled every 10ms */
-  id = gst_clock_new_periodic_id (info.clock, base, 10 * GST_MSECOND);
-
-  /* start waiting for the entry */
-  thread =
-      g_thread_try_new ("gst-check", (GThreadFunc) mixed_thread, &info, &error);
-  fail_unless (error == NULL, "error creating thread");
-  fail_unless (thread != NULL, "Could not create thread");
-
-  /* wait half a second so we are sure to be in the thread */
-  g_usleep (G_USEC_PER_SEC / 2);
-
-  /* start scheduling the entry */
-  gst_clock_id_wait_async (id, mixed_async_cb, NULL, NULL);
-
-  /* wait for thread to finish */
-  g_thread_join (thread);
-  /* entry must have timed out correctly */
-  fail_unless (info.ret == GST_CLOCK_OK, "clock return was %d", info.ret);
-
-  gst_clock_id_unschedule (id);
-  gst_clock_id_unref (id);
-  gst_clock_id_unref (info.id);
-  gst_object_unref (info.clock);
-}
-
-GST_END_TEST;
-
 static gboolean
 test_async_full_slave_callback (GstClock * master, GstClockTime time,
     GstClockID id, GstClock * clock)
@@ -753,7 +221,7 @@ GST_START_TEST (test_resolution)
     prev_t = now_t;
     g_thread_yield ();
   }
-  g_object_unref (clock);
+  gst_object_unref (clock);
   clock = NULL;
 }
 
@@ -802,7 +270,7 @@ single_shot_wait_thread_func (gpointer data)
     g_mutex_unlock (&d->lock);
   }
 
-  g_object_unref (clock);
+  gst_object_unref (clock);
 
   return NULL;
 }
@@ -860,6 +328,9 @@ GST_START_TEST (test_stress_cleanup_unschedule)
   for (i = 0; i < num; i++) {
     WaitUnscheduleData *d = &data[i];
     d->running = FALSE;
+  }
+  for (i = 0; i < num; i++) {
+    WaitUnscheduleData *d = &data[i];
     g_thread_join (d->thread_wait);
     g_thread_join (d->thread_unschedule);
     g_mutex_clear (&d->lock);
@@ -902,6 +373,9 @@ GST_START_TEST (test_stress_reschedule)
   for (i = 0; i < num; i++) {
     WaitUnscheduleData *d = &data[i];
     d->running = FALSE;
+  }
+  for (i = 0; i < num; i++) {
+    WaitUnscheduleData *d = &data[i];
     g_thread_join (d->thread_wait);
     g_thread_join (d->thread_unschedule);
     g_mutex_clear (&d->lock);
@@ -920,14 +394,7 @@ gst_systemclock_suite (void)
   suite_add_tcase (s, tc_chain);
   tcase_add_test (tc_chain, test_range);
   tcase_add_test (tc_chain, test_signedness);
-  tcase_add_test (tc_chain, test_single_shot);
-  tcase_add_test (tc_chain, test_periodic_shot);
-  tcase_add_test (tc_chain, test_periodic_multi);
-  tcase_add_test (tc_chain, test_async_order);
-  tcase_add_test (tc_chain, test_async_order_stress_test);
-  tcase_add_test (tc_chain, test_async_sync_interaction);
   tcase_add_test (tc_chain, test_diff);
-  tcase_add_test (tc_chain, test_mixed);
   tcase_add_test (tc_chain, test_async_full);
   tcase_add_test (tc_chain, test_set_default);
   tcase_add_test (tc_chain, test_resolution);
index d330cb3..99a87cd 100644 (file)
@@ -500,6 +500,21 @@ GST_START_TEST (test_equal)
   gst_tag_list_unref (tags);
   gst_tag_list_unref (tags2);
 
+  /* test comparing lists with equal length but different items */
+
+  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);
+
+  tags2 = gst_tag_list_new_empty ();
+  gst_tag_list_add (tags2, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, "Foo", NULL);
+  gst_tag_list_add (tags2, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, "Bar", NULL);
+
+  fail_unless (!gst_tag_list_is_equal (tags2, tags));
+
+  gst_tag_list_unref (tags);
+  gst_tag_list_unref (tags2);
+
   /* samples */
   buf = gst_buffer_new_wrapped (g_strdup ("test 1-2-3"), 10);
   sample1 = gst_sample_new (buf, NULL, NULL, NULL);
index 10f68fe..8413d4a 100644 (file)
@@ -118,7 +118,7 @@ GST_START_TEST (test_merge)
   gst_tag_list_unref (list2);
   gst_tag_list_unref (list1);
 
-  g_object_unref (enc);
+  gst_object_unref (enc);
 }
 
 GST_END_TEST
@@ -319,7 +319,7 @@ GST_START_TEST (test_threads)
   g_thread_join (threads[1]);
   g_thread_join (threads[2]);
 
-  g_object_unref (G_OBJECT (setter));
+  gst_object_unref (G_OBJECT (setter));
 }
 
 GST_END_TEST static Suite *
index e18a508..dcf7038 100644 (file)
@@ -32,6 +32,48 @@ static GRecMutex task_mutex;
 #define TEST_RACE_ITERATIONS 1000
 
 static void
+task_resume_func (void *data)
+{
+  g_mutex_lock (&task_lock);
+  g_cond_signal (&task_cond);
+  g_mutex_unlock (&task_lock);
+}
+
+GST_START_TEST (test_resume)
+{
+  GstTask *t;
+
+  t = gst_task_new (task_resume_func, &t, NULL);
+  fail_if (t == NULL);
+
+  g_rec_mutex_init (&task_mutex);
+  gst_task_set_lock (t, &task_mutex);
+
+  g_cond_init (&task_cond);
+  g_mutex_init (&task_lock);
+
+  g_mutex_lock (&task_lock);
+
+  /* Pause the task, and resume it. */
+  fail_unless (gst_task_pause (t));
+  fail_unless (gst_task_resume (t));
+
+  while (GST_TASK_STATE (t) != GST_TASK_STARTED)
+    g_cond_wait (&task_cond, &task_lock);
+
+  fail_unless (gst_task_stop (t));
+  g_mutex_unlock (&task_lock);
+  fail_unless (gst_task_join (t));
+
+  /* Make sure we cannot resume from stopped. */
+  fail_if (gst_task_resume (t));
+
+  gst_object_unref (t);
+}
+
+GST_END_TEST;
+
+static void
 task_signal_pause_func (void *data)
 {
   GstTask **t = data;
@@ -251,6 +293,176 @@ GST_START_TEST (test_create)
 
 GST_END_TEST;
 
+typedef struct
+{
+  gboolean called;
+  gpointer caller_thread;
+
+  GCond blocked_cond;
+  GMutex blocked_lock;
+  gboolean blocked;
+
+  GCond unblock_cond;
+  GMutex unblock_lock;
+  gboolean unblock;
+} TaskData;
+
+static void
+task_cb (TaskData * tdata)
+{
+  tdata->called = TRUE;
+  tdata->caller_thread = g_thread_self ();
+
+  g_mutex_lock (&tdata->blocked_lock);
+  tdata->blocked = TRUE;
+  g_cond_signal (&tdata->blocked_cond);
+  g_mutex_unlock (&tdata->blocked_lock);
+
+  g_mutex_lock (&tdata->unblock_lock);
+  while (!tdata->unblock)
+    g_cond_wait (&tdata->unblock_cond, &tdata->unblock_lock);
+
+  g_mutex_unlock (&tdata->unblock_lock);
+}
+
+static void
+init_task_data (TaskData * tdata)
+{
+  tdata->called = FALSE;
+  tdata->caller_thread = NULL;
+  tdata->unblock = FALSE;
+  g_cond_init (&tdata->unblock_cond);
+  g_mutex_init (&tdata->unblock_lock);
+
+  tdata->blocked = FALSE;
+  g_cond_init (&tdata->blocked_cond);
+  g_mutex_init (&tdata->blocked_lock);
+}
+
+static void
+cleanup_task_data (TaskData * tdata)
+{
+  g_mutex_clear (&tdata->unblock_lock);
+  g_cond_clear (&tdata->unblock_cond);
+  g_mutex_clear (&tdata->blocked_lock);
+  g_cond_clear (&tdata->blocked_cond);
+}
+
+/* In this test, we use a shared task pool with max-threads=1 and verify
+ * that the caller thread for two tasks is the same */
+GST_START_TEST (test_shared_task_pool_shared_thread)
+{
+  GstTaskPool *pool;
+  gpointer handle, handle2;
+  GError *err = NULL;
+  TaskData tdata, tdata2;
+
+  init_task_data (&tdata);
+  init_task_data (&tdata2);
+
+  pool = gst_shared_task_pool_new ();
+  gst_task_pool_prepare (pool, &err);
+
+  fail_unless (err == NULL);
+
+  /* We request that two tasks be executed, and our task function is blocking.
+   * This means no new thread is available to spawn, and the second task should
+   * be queued up on the first thread */
+  handle =
+      gst_task_pool_push (pool, (GstTaskPoolFunction) task_cb, &tdata, &err);
+  fail_unless (err == NULL);
+  handle2 =
+      gst_task_pool_push (pool, (GstTaskPoolFunction) task_cb, &tdata2, &err);
+  fail_unless (err == NULL);
+
+  g_mutex_lock (&tdata.unblock_lock);
+  tdata.unblock = TRUE;
+  g_cond_signal (&tdata.unblock_cond);
+  g_mutex_unlock (&tdata.unblock_lock);
+
+  g_mutex_lock (&tdata2.unblock_lock);
+  tdata2.unblock = TRUE;
+  g_cond_signal (&tdata2.unblock_cond);
+  g_mutex_unlock (&tdata2.unblock_lock);
+
+  gst_task_pool_join (pool, handle);
+  gst_task_pool_join (pool, handle2);
+
+  fail_unless (tdata.called == TRUE);
+  fail_unless (tdata2.called == TRUE);
+  fail_unless (tdata.caller_thread == tdata2.caller_thread);
+
+  cleanup_task_data (&tdata);
+  cleanup_task_data (&tdata2);
+
+  gst_task_pool_cleanup (pool);
+
+  g_object_unref (pool);
+}
+
+GST_END_TEST;
+
+/* In this test, we use a shared task pool with max-threads=2 and verify
+ * that the caller thread for two tasks is different */
+GST_START_TEST (test_shared_task_pool_two_threads)
+{
+  GstTaskPool *pool;
+  gpointer handle, handle2;
+  GError *err = NULL;
+  TaskData tdata, tdata2;
+
+  init_task_data (&tdata);
+  init_task_data (&tdata2);
+
+  pool = gst_shared_task_pool_new ();
+  gst_shared_task_pool_set_max_threads (GST_SHARED_TASK_POOL (pool), 2);
+  gst_task_pool_prepare (pool, &err);
+
+  fail_unless (err == NULL);
+
+  /* We request that two tasks be executed, and our task function is blocking.
+   * This means the pool will have to spawn a new thread to handle the task */
+  handle =
+      gst_task_pool_push (pool, (GstTaskPoolFunction) task_cb, &tdata, &err);
+  fail_unless (err == NULL);
+  handle2 =
+      gst_task_pool_push (pool, (GstTaskPoolFunction) task_cb, &tdata2, &err);
+  fail_unless (err == NULL);
+
+  /* Make sure that the second task has started executing before unblocking */
+  g_mutex_lock (&tdata2.blocked_lock);
+  while (!tdata2.blocked) {
+    g_cond_wait (&tdata2.blocked_cond, &tdata2.blocked_lock);
+  }
+  g_mutex_unlock (&tdata2.blocked_lock);
+
+  g_mutex_lock (&tdata.unblock_lock);
+  tdata.unblock = TRUE;
+  g_cond_signal (&tdata.unblock_cond);
+  g_mutex_unlock (&tdata.unblock_lock);
+
+  g_mutex_lock (&tdata2.unblock_lock);
+  tdata2.unblock = TRUE;
+  g_cond_signal (&tdata2.unblock_cond);
+  g_mutex_unlock (&tdata2.unblock_lock);
+
+  gst_task_pool_join (pool, handle);
+  gst_task_pool_join (pool, handle2);
+
+  fail_unless (tdata.called == TRUE);
+  fail_unless (tdata2.called == TRUE);
+
+  fail_unless (tdata.caller_thread != tdata2.caller_thread);
+
+  cleanup_task_data (&tdata);
+  cleanup_task_data (&tdata2);
+
+  gst_task_pool_cleanup (pool);
+
+  g_object_unref (pool);
+}
+
+GST_END_TEST;
 
 static Suite *
 gst_task_suite (void)
@@ -265,6 +477,9 @@ gst_task_suite (void)
   tcase_add_test (tc_chain, test_lock_start);
   tcase_add_test (tc_chain, test_join);
   tcase_add_test (tc_chain, test_pause_stop_race);
+  tcase_add_test (tc_chain, test_resume);
+  tcase_add_test (tc_chain, test_shared_task_pool_shared_thread);
+  tcase_add_test (tc_chain, test_shared_task_pool_two_threads);
 
   return s;
 }
index f15e198..877dfbd 100644 (file)
@@ -258,7 +258,7 @@ GST_START_TEST (test_set)
 
   fail_unless (toc == NULL);
 
-  g_object_unref (enc);
+  gst_object_unref (enc);
 }
 
 GST_END_TEST static int spin_and_wait = 1;
@@ -369,7 +369,7 @@ GST_START_TEST (test_threads)
   g_thread_join (threads[1]);
   g_thread_join (threads[2]);
 
-  g_object_unref (G_OBJECT (setter));
+  gst_object_unref (setter);
 }
 
 GST_END_TEST static Suite *
index 6dd629a..5627152 100644 (file)
@@ -90,7 +90,7 @@ GST_START_TEST (serialize_message_logging)
   str = (gchar *) messages->data;
   fail_unless (str != NULL);
 
-  g_object_unref (tr);
+  gst_object_unref (tr);
 }
 
 GST_END_TEST;
@@ -147,7 +147,7 @@ GST_START_TEST (serialize_static_record)
   g_free (str_val);
 
   gst_structure_free (s);
-  g_object_unref (tr);
+  gst_object_unref (tr);
 }
 
 GST_END_TEST;
index c8f1a1d..3364ee7 100644 (file)
@@ -923,7 +923,7 @@ GST_START_TEST (test_url_constructors)
 
   url2 = gst_uri_copy (url1);
   fail_unless (gst_uri_equal (url1, url2));
-  gst_uri_set_query_value (url2, "key", "value");
+  fail_unless (gst_uri_set_query_value (url2, "key", "value"));
   fail_unless (!gst_uri_equal (url1, url2));
   gst_uri_unref (url2);
 
@@ -1171,6 +1171,28 @@ GST_START_TEST (test_url_get_media_fragment_table)
 
 GST_END_TEST;
 
+GST_START_TEST (test_url_unescape_equals_in_http_query)
+{
+  GstUri *url;
+  gchar *query_string;
+
+  url =
+      gst_uri_from_string
+      ("http://abc.manifest?token=exp=123~acl=/QualityLevels(*~hmac=0cb");
+
+  fail_unless_equals_string (gst_uri_get_scheme (url), "http");
+  query_string = gst_uri_get_query_string (url);
+  fail_unless_equals_string (query_string,
+      "token=exp=123~acl=/QualityLevels(*~hmac=0cb");
+  g_free (query_string);
+  fail_unless (gst_uri_query_has_key (url, "token"));
+  fail_unless_equals_string (gst_uri_get_query_value (url, "token"),
+      "exp=123~acl=/QualityLevels(*~hmac=0cb");
+  gst_uri_unref (url);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_uri_suite (void)
 {
@@ -1199,6 +1221,7 @@ gst_uri_suite (void)
   tcase_add_test (tc_chain, test_url_constructors);
   tcase_add_test (tc_chain, test_url_get_set);
   tcase_add_test (tc_chain, test_url_get_media_fragment_table);
+  tcase_add_test (tc_chain, test_url_unescape_equals_in_http_query);
 
   return s;
 }
index 18ba199..4ac2b67 100644 (file)
@@ -984,12 +984,12 @@ GST_START_TEST (test_pad_proxy_query_caps_aggregation)
   tee = gst_element_factory_make ("tee", "tee");
 
   sink1 = gst_element_factory_make ("fakesink", "sink1");
-  tee_src1 = gst_element_get_request_pad (tee, "src_%u");
+  tee_src1 = gst_element_request_pad_simple (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_%u");
+  tee_src2 = gst_element_request_pad_simple (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);
 
@@ -1953,6 +1953,26 @@ GST_START_TEST (test_regression)
 
 GST_END_TEST;
 
+GST_START_TEST (test_mark_as_plugin_api)
+{
+  GstPluginAPIFlags api_flags;
+
+  fail_unless (!gst_type_is_plugin_api (GST_TYPE_ELEMENT, NULL));
+
+  gst_type_mark_as_plugin_api (GST_TYPE_ELEMENT, 0);
+
+  fail_unless (gst_type_is_plugin_api (GST_TYPE_ELEMENT, &api_flags));
+  fail_unless_equals_int (api_flags, 0);
+
+  gst_type_mark_as_plugin_api (GST_TYPE_ELEMENT,
+      GST_PLUGIN_API_FLAG_IGNORE_ENUM_MEMBERS);
+
+  fail_unless (gst_type_is_plugin_api (GST_TYPE_ELEMENT, &api_flags));
+  fail_unless_equals_int (api_flags, GST_PLUGIN_API_FLAG_IGNORE_ENUM_MEMBERS);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_utils_suite (void)
 {
@@ -1994,6 +2014,8 @@ gst_utils_suite (void)
   tcase_add_test (tc_chain, test_write_macros);
   tcase_add_test (tc_chain, test_regression);
 
+  tcase_add_test (tc_chain, test_mark_as_plugin_api);
+
   return s;
 }
 
index 841a4c8..b86eef4 100644 (file)
@@ -801,21 +801,21 @@ GST_START_TEST (test_deserialize_string)
     "\"Hello\\ World", "\"Hello\\ World"}, {
     "\"\\", "\"\\"}, {
     "\"\\0", "\"\\0"}, {
+    "\"t\\303\\274t\"", "tüt"}, {
+      /* utf8 octal sequence */
     "", ""},                    /* empty strings */
     {
-    "\"\"", ""},                /* quoted empty string -> empty string */
+    "\"\"", ""}, {              /* quoted empty string -> empty string */
+    "\" \"", " "}, {            /* allow spaces to be not escaped */
+    "tüüt", "tüüt"},        /* allow special chars to be not escaped */
         /* Expected FAILURES: */
     {
-    "\"\\0\"", NULL},           /* unfinished escaped character */
-    {
-    "\"", NULL},                /* solitary quote */
-    {
-    "\" \"", NULL},             /* spaces must be escaped */
-#if 0
-        /* FIXME 0.9: this test should fail, but it doesn't */
-    {
-    "tüüt", NULL}             /* string with special chars must be escaped */
-#endif
+    "\"\\0\"", NULL}, {         /* unfinished escaped character */
+    "\"", NULL}, {              /* solitary quote */
+    "\"\\380\"", NULL}, {       /* invalid octal sequence */
+    "\"\\344\\204\\062\"", NULL}, {
+      /* invalid utf8: wrong end byte */
+    "\"\\344\\204\"", NULL}     /* invalid utf8: wrong number of bytes */
   };
   guint i;
   GValue v = { 0, };
@@ -1020,6 +1020,15 @@ GST_START_TEST (test_value_compare)
   g_value_unset (&value2);
   g_value_unset (&tmp);
 
+  g_value_init (&value1, G_TYPE_VALUE_ARRAY);
+  g_value_init (&value2, G_TYPE_VALUE_ARRAY);
+
+  fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL,
+      "Empty Value arrays aren't equals when they should");
+
+  g_value_unset (&value1);
+  g_value_unset (&value2);
+
   g_value_init (&value1, GST_TYPE_BITMASK);
   gst_value_set_bitmask (&value1, 0x123);
   g_value_init (&value2, GST_TYPE_BITMASK);
@@ -2668,9 +2677,9 @@ GST_START_TEST (test_serialize_deserialize_format_enum)
   str = gst_structure_to_string (s);
   GST_LOG ("Got structure string '%s'", GST_STR_NULL (str));
   fail_unless (str != NULL);
-  fail_unless (strstr (str, "TIME") != NULL);
-  fail_unless (strstr (str, "BYTE") != NULL);
-  fail_unless (strstr (str, "DEFAULT") != NULL);
+  fail_unless (strstr (str, "time") != NULL);
+  fail_unless (strstr (str, "byte") != NULL);
+  fail_unless (strstr (str, "default") != NULL);
   fail_unless (strstr (str, "FOOBAR") != NULL);
 
   s2 = gst_structure_from_string (str, &end);
@@ -2720,51 +2729,143 @@ GST_START_TEST (test_serialize_deserialize_value_array)
 
 GST_END_TEST;
 
-GST_START_TEST (test_serialize_deserialize_caps)
+GST_START_TEST (test_compare_caps)
 {
   GValue value = { 0 }
   , value2 = {
   0};
-  GstCaps *caps, *caps2;
-  GstCaps *incaps;
-  gchar *serialized;
 
-  incaps = gst_caps_new_simple ("caps/internal",
+  g_value_init (&value, GST_TYPE_CAPS);
+  g_value_init (&value2, GST_TYPE_CAPS);
+  g_value_take_boxed (&value, NULL);
+  g_value_take_boxed (&value2, NULL);
+
+  fail_unless_equals_int (gst_value_compare (&value, &value2), GST_VALUE_EQUAL);
+
+  g_value_take_boxed (&value, gst_caps_new_empty_simple ("something"));
+
+  fail_unless_equals_int (gst_value_compare (&value, &value2),
+      GST_VALUE_UNORDERED);
+
+  g_value_unset (&value);
+  g_value_unset (&value2);
+
+}
+
+GST_END_TEST;
+
+static void
+_test_serialize_deserialize_boxed_in_structure (const gpointer boxed_value,
+    GType type)
+{
+  GValue value = G_VALUE_INIT, str_val = G_VALUE_INIT;
+  const GValue *value_after;
+  GstStructure *s, *s2;
+  const gchar *first_str_val = "first \" string", *second_str_val =
+      "second \" string";
+  gchar *str, *str2, *end;
+
+  g_value_init (&value, type);
+  g_value_init (&str_val, G_TYPE_STRING);
+  g_value_set_boxed (&value, boxed_value);
+
+  s = gst_structure_new_empty ("test-struct");
+  g_value_set_string (&str_val, first_str_val);
+  gst_structure_set_value (s, "first", &str_val);
+  gst_structure_set_value (s, "test-value", &value);
+  g_value_set_string (&str_val, second_str_val);
+  gst_structure_set_value (s, "second", &str_val);
+
+  /* serialize the values in the structure */
+  str = gst_structure_to_string (s);
+  fail_unless (str != NULL);
+  GST_DEBUG ("Got structure string '%s'", str);
+
+  /* recreate the structure */
+  s2 = gst_structure_from_string (str, &end);
+  fail_unless (s2 != NULL);
+  fail_unless (end[0] == '\0');
+
+  /* make sure the new structure serializes to the same string */
+  str2 = gst_structure_to_string (s2);
+  fail_unless_equals_string (str, str2);
+
+  /* test for equality if values can be compared */
+  value_after = gst_structure_get_value (s2, "test-value");
+  fail_unless (value_after != NULL);
+  fail_unless (G_VALUE_TYPE (value_after) == G_VALUE_TYPE (&value));
+  if (gst_value_can_compare (&value, value_after))
+    fail_unless (gst_value_compare (&value, value_after) == GST_VALUE_EQUAL);
+
+  /* test to make sure that the string values are still present, and
+   * haven't been gobbled by the value serialization */
+  fail_unless_equals_string (gst_structure_get_string (s2, "first"),
+      first_str_val);
+  fail_unless_equals_string (gst_structure_get_string (s2, "second"),
+      second_str_val);
+
+  /* cleanup */
+  gst_structure_free (s);
+  gst_structure_free (s2);
+  g_free (str);
+  g_free (str2);
+  g_value_unset (&value);
+  g_value_unset (&str_val);
+}
+
+GST_START_TEST (test_serialize_deserialize_caps)
+{
+  GValue value = G_VALUE_INIT, value2 = G_VALUE_INIT;
+  GstCaps *incaps = gst_caps_new_simple ("caps/internal",
       "in-field", G_TYPE_INT, 20, "in-field2",
       G_TYPE_STRING, "some in ternal field", NULL);
-  caps = gst_caps_new_simple ("test/caps",
-      "foo", G_TYPE_INT, 10, "bar", G_TYPE_STRING, "test",
-      "int-caps", GST_TYPE_CAPS, incaps, NULL);
-  fail_if (GST_CAPS_REFCOUNT_VALUE (caps) != 1);
-  gst_caps_unref (incaps);
+  GstCaps *test_caps[] = {
+    gst_caps_new_simple ("test/caps",
+        "foo", G_TYPE_INT, 10, "bar", G_TYPE_STRING, "test",
+        "int-caps", GST_TYPE_CAPS, incaps, NULL),
+    gst_caps_new_any (),
+    gst_caps_new_empty ()
+  };
+  GstCaps *caps, *caps2;
+  gchar *serialized;
+  gint i;
 
-  /* and assign caps to gvalue */
+  gst_caps_unref (incaps);
   g_value_init (&value, GST_TYPE_CAPS);
-  g_value_take_boxed (&value, caps);
-  fail_if (GST_CAPS_REFCOUNT_VALUE (caps) != 1);
+  g_value_init (&value2, GST_TYPE_CAPS);
 
-  /* now serialize it */
-  serialized = gst_value_serialize (&value);
-  GST_DEBUG ("serialized caps to %s", serialized);
-  fail_unless (serialized != NULL);
+  for (i = 0; i < G_N_ELEMENTS (test_caps); i++) {
+    caps = test_caps[i];
+    fail_if (GST_CAPS_REFCOUNT_VALUE (caps) != 1);
 
-  /* refcount should not change */
-  fail_if (GST_CAPS_REFCOUNT_VALUE (caps) != 1);
+    /* and assign caps to gvalue */
+    g_value_take_boxed (&value, caps);
+    fail_if (GST_CAPS_REFCOUNT_VALUE (caps) != 1);
 
-  /* now deserialize again */
-  g_value_init (&value2, GST_TYPE_CAPS);
-  gst_value_deserialize (&value2, serialized);
+    /* now serialize it */
+    serialized = gst_value_serialize (&value);
+    GST_DEBUG ("serialized caps to %s", serialized);
+    fail_unless (serialized != NULL);
 
-  caps2 = g_value_get_boxed (&value2);
-  fail_if (GST_CAPS_REFCOUNT_VALUE (caps2) != 1);
+    /* refcount should not change */
+    fail_if (GST_CAPS_REFCOUNT_VALUE (caps) != 1);
 
-  /* they should be equal */
-  fail_unless (gst_caps_is_equal (caps, caps2));
+    /* now deserialize again */
+    fail_unless (gst_value_deserialize (&value2, serialized));
 
-  /* cleanup */
+    caps2 = g_value_get_boxed (&value2);
+    fail_if (GST_CAPS_REFCOUNT_VALUE (caps2) != 1);
+
+    /* they should be equal */
+    fail_unless (gst_caps_is_equal (caps, caps2));
+    fail_unless (gst_caps_is_any (caps) == gst_caps_is_any (caps2));
+
+    _test_serialize_deserialize_boxed_in_structure (caps, GST_TYPE_CAPS);
+    /* cleanup */
+    g_free (serialized);
+  }
   g_value_unset (&value);
   g_value_unset (&value2);
-  g_free (serialized);
 }
 
 GST_END_TEST;
@@ -3063,6 +3164,9 @@ GST_START_TEST (test_stepped_int_range_parsing)
     "[1, 2, 2]",
     "[2, 3, 2]",
     "[0, 0, 0]",
+    "[0, 0, 1]",
+    "[1, 2, 0]",
+    "[1, 1, 1]",
   };
 
   /* check we can parse good ranges */
@@ -3257,31 +3361,30 @@ GST_START_TEST (test_structure_ops)
     const gchar *op;
     gint ret;
     GType str_type;
-    const gchar *str_result;
   } comparisons[] = {
     /* *INDENT-OFF* */
-    {"foo,bar=(int)1", "foo,bar=(int)1", "compare", GST_VALUE_EQUAL, 0, NULL},
-    {"foo,bar=(int)1", "foo,bar=(int)1", "is_subset", TRUE, 0, NULL},
-    {"foo,bar=(int)1", "foo,bar=(int)1", "intersect", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)1"},
-    {"foo,bar=(int)1", "foo,bar=(int)1", "union", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)1"},
-    {"foo,bar=(int)[1,2]", "foo,bar=(int)1", "compare", GST_VALUE_UNORDERED, 0, NULL},
-    {"foo,bar=(int)[1,2]", "foo,bar=(int)1", "is_subset", FALSE, 0, NULL},
-    {"foo,bar=(int)[1,2]", "foo,bar=(int)1", "intersect", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)1"},
-    {"foo,bar=(int)[1,2]", "foo,bar=(int)1", "union", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)[1,2]"},
-    {"foo,bar=(int)1", "foo,bar=(int)[1,2]", "compare", GST_VALUE_UNORDERED, 0, NULL},
-    {"foo,bar=(int)1", "foo,bar=(int)[1,2]", "is_subset", TRUE, 0, NULL},
-    {"foo,bar=(int)1", "foo,bar=(int)[1,2]", "intersect", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)1"},
-    {"foo,bar=(int)1", "foo,bar=(int)[1,2]", "union", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)[1,2]"},
-    {"foo,bar=(int)1", "foo,bar=(int)2", "compare", GST_VALUE_UNORDERED, 0, NULL},
-    {"foo,bar=(int)1", "foo,bar=(int)2", "is_subset", FALSE, 0, NULL},
-    {"foo,bar=(int)1", "foo,bar=(int)2", "intersect", FALSE, 0, NULL},
-    {"foo,bar=(int)1", "foo,bar=(int)2", "union", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)[1,2]"},
-    {"foo,bar=(int)1", "baz,bar=(int)1", "compare", GST_VALUE_UNORDERED, 0, NULL},
-    {"foo,bar=(int)1", "baz,bar=(int)1", "is_subset", FALSE, 0, NULL},
-    {"foo,bar=(int)1", "baz,bar=(int)1", "intersect", FALSE, 0, NULL},
+    {"foo,bar=(int)1", "foo,bar=(int)1", "compare", GST_VALUE_EQUAL, 0},
+    {"foo,bar=(int)1", "foo,bar=(int)1", "is_subset", TRUE, 0},
+    {"foo,bar=(int)1", "foo,bar=(int)1", "intersect", TRUE, GST_TYPE_STRUCTURE},
+    {"foo,bar=(int)1", "foo,bar=(int)1", "union", TRUE, GST_TYPE_STRUCTURE},
+    {"foo,bar=(int)[1,2]", "foo,bar=(int)1", "compare", GST_VALUE_UNORDERED, 0},
+    {"foo,bar=(int)[1,2]", "foo,bar=(int)1", "is_subset", FALSE, 0},
+    {"foo,bar=(int)[1,2]", "foo,bar=(int)1", "intersect", TRUE, GST_TYPE_STRUCTURE},
+    {"foo,bar=(int)[1,2]", "foo,bar=(int)1", "union", TRUE, GST_TYPE_STRUCTURE},
+    {"foo,bar=(int)1", "foo,bar=(int)[1,2]", "compare", GST_VALUE_UNORDERED, 0},
+    {"foo,bar=(int)1", "foo,bar=(int)[1,2]", "is_subset", TRUE, 0},
+    {"foo,bar=(int)1", "foo,bar=(int)[1,2]", "intersect", TRUE, GST_TYPE_STRUCTURE},
+    {"foo,bar=(int)1", "foo,bar=(int)[1,2]", "union", TRUE, GST_TYPE_STRUCTURE},
+    {"foo,bar=(int)1", "foo,bar=(int)2", "compare", GST_VALUE_UNORDERED, 0},
+    {"foo,bar=(int)1", "foo,bar=(int)2", "is_subset", FALSE, 0},
+    {"foo,bar=(int)1", "foo,bar=(int)2", "intersect", FALSE, 0},
+    {"foo,bar=(int)1", "foo,bar=(int)2", "union", TRUE, GST_TYPE_STRUCTURE},
+    {"foo,bar=(int)1", "baz,bar=(int)1", "compare", GST_VALUE_UNORDERED, 0},
+    {"foo,bar=(int)1", "baz,bar=(int)1", "is_subset", FALSE, 0},
+    {"foo,bar=(int)1", "baz,bar=(int)1", "intersect", FALSE, 0},
 #if 0
     /* deserializing lists is not implemented (but this should still work!) */
-    {"foo,bar=(int)1", "baz,bar=(int)1", "union", TRUE, G_TYPE_LIST, "{foo,bar=(int)1;, baz,bar=(int)1;}"},
+    {"foo,bar=(int)1", "baz,bar=(int)1", "union", TRUE, G_TYPE_LIST},
 #endif
     /* *INDENT-ON* */
   };
@@ -3296,8 +3399,7 @@ GST_START_TEST (test_structure_ops)
     fail_unless (s2 != NULL);
 
     GST_DEBUG ("checking %s with structure1 %" GST_PTR_FORMAT " structure2 %"
-        GST_PTR_FORMAT " is %d, %s", comparisons[i].op, s1, s2,
-        comparisons[i].ret, comparisons[i].str_result);
+        GST_PTR_FORMAT " is %d", comparisons[i].op, s1, s2, comparisons[i].ret);
 
     g_value_init (&v1, GST_TYPE_STRUCTURE);
     gst_value_set_structure (&v1, s1);
@@ -3320,11 +3422,10 @@ GST_START_TEST (test_structure_ops)
 
         str = gst_value_serialize (&v3);
         GST_LOG ("result %s", str);
-        g_free (str);
 
         g_value_init (&result, comparisons[i].str_type);
-        fail_unless (gst_value_deserialize (&result,
-                comparisons[i].str_result));
+        fail_unless (gst_value_deserialize (&result, str));
+        g_free (str);
         fail_unless (gst_value_compare (&result, &v3) == GST_VALUE_EQUAL);
         g_value_unset (&v3);
         g_value_unset (&result);
@@ -3340,6 +3441,62 @@ GST_START_TEST (test_structure_ops)
 
 GST_END_TEST;
 
+static gpointer
+get_serialize_deserialize_boxed (const gpointer boxed, GType type)
+{
+  gchar *serialized, *cmp;
+  GValue value = G_VALUE_INIT, value2 = G_VALUE_INIT;
+  gpointer ret;
+
+  g_value_init (&value, type);
+  g_value_init (&value2, type);
+
+  g_value_set_boxed (&value, boxed);
+  serialized = gst_value_serialize (&value);
+  fail_unless (serialized != NULL);
+  GST_DEBUG ("serialized to %s", serialized);
+  fail_unless (gst_value_deserialize (&value2, serialized));
+  cmp = gst_value_serialize (&value2);
+  fail_unless_equals_string (cmp, serialized);
+
+  ret = g_value_dup_boxed (&value2);
+
+  g_free (serialized);
+  g_free (cmp);
+  g_value_unset (&value);
+  g_value_unset (&value2);
+  return ret;
+}
+
+GST_START_TEST (test_serialize_deserialize_structure)
+{
+  GstStructure *instr = gst_structure_new ("structure/internal",
+      "in-field", G_TYPE_INT, 20, "in-field2",
+      G_TYPE_STRING, "some in ternal field", NULL);
+  GstStructure *test_str[] = {
+    gst_structure_new ("test/structure",
+        "foo", G_TYPE_INT, 10, "bar", G_TYPE_STRING, "test",
+        "int-str", GST_TYPE_STRUCTURE, instr, NULL),
+    gst_structure_new_empty ("empty")
+  };
+  gint i;
+  GstStructure *str, *str2;
+
+  gst_structure_free (instr);
+  for (i = 0; i < G_N_ELEMENTS (test_str); i++) {
+    str = test_str[i];
+    str2 = get_serialize_deserialize_boxed (str, GST_TYPE_STRUCTURE);
+    fail_unless (gst_structure_is_equal (str, str2));
+
+    _test_serialize_deserialize_boxed_in_structure (str, GST_TYPE_STRUCTURE);
+
+    gst_structure_free (str);
+    gst_structure_free (str2);
+  }
+}
+
+GST_END_TEST;
+
 static void
 setup_test_value_array (GValue * value)
 {
@@ -3435,6 +3592,329 @@ GST_START_TEST (test_serialize_null_aray)
 
 GST_END_TEST;
 
+GST_START_TEST (test_deserialize_array)
+{
+  GValue value = { 0 };
+  const gchar *strings[] = {
+    "{ test, }",
+    "{ , }",
+    "{ test,, }",
+    "{ , , }",
+  };
+  gint results_size[] = { 1, 0, -1, -1 };       /* -1 means deserialization should fail */
+  int i;
+
+  for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
+    /* Workaround a bug in our parser that would lead to segfaults
+     * when deserializing container types using static strings */
+    gchar *str = g_strdup (strings[i]);
+    g_value_init (&value, GST_TYPE_LIST);
+
+    if (results_size[i] == -1) {
+      fail_if (gst_value_deserialize (&value, str),
+          "Should not be able to deserialize %s (%d) as list", str, i);
+    } else {
+      fail_unless (gst_value_deserialize (&value, str),
+          "could not deserialize %s (%d)", str, i);
+      fail_unless (gst_value_list_get_size (&value) == results_size[i],
+          "Wrong array size: %d. expected %d",
+          gst_value_array_get_size (&value), results_size[i]);
+    }
+
+    g_value_unset (&value);
+    g_free (str);
+  }
+}
+
+GST_END_TEST;
+
+#define TEST_FLAGS_TYPE (test_flags_get_type())
+static GType
+test_flags_get_type (void)
+{
+  static const GFlagsValue values[] = {
+    {1, "One", "one"},
+    {1 << 1, "Two", "two"},
+    {1 << 3, "Eight", "eight"},
+    {0, NULL, NULL}
+  };
+  static GType id = 0;
+
+  if (g_once_init_enter ((gsize *) & id)) {
+    GType _id;
+
+    _id = g_flags_register_static ("TestFlags", values);
+
+    g_once_init_leave ((gsize *) & id, _id);
+  }
+
+  return id;
+}
+
+#define _RESULT(i) result_##i
+#define RESULT(i) _RESULT(i)
+
+GST_START_TEST (test_deserialize_with_pspec)
+{
+  GValue value = { 0 };
+  GParamSpec *pspec;
+  const gchar *strings[] = {
+    "< one, 0>",
+    "< one+eight, two >",
+    "< 9, 0>",
+  };
+  int i;
+
+  gint results[3][2] = {
+    {1, 0},
+    {9, 2},
+    {9, 0}
+  };
+
+  pspec = gst_param_spec_array ("flags-array",
+      "Flags Array", "An array of flags",
+      g_param_spec_flags ("flags", "Flags", "Flags", TEST_FLAGS_TYPE, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
+    int j;
+    gchar *str = g_strdup (strings[i]);
+    g_value_init (&value, GST_TYPE_ARRAY);
+
+    fail_unless (gst_value_deserialize_with_pspec (&value, str, pspec),
+        "could not deserialize %s (%d)", str, i);
+
+    fail_unless (gst_value_array_get_size (&value) ==
+        G_N_ELEMENTS (results[i]));
+
+    for (j = 0; j < G_N_ELEMENTS (results[i]); j++) {
+      const GValue *elem_value = gst_value_array_get_value (&value, j);
+      fail_unless (G_VALUE_TYPE (elem_value) == TEST_FLAGS_TYPE);
+      fail_unless_equals_int (g_value_get_flags (elem_value), results[i][j]);
+    }
+
+    g_value_unset (&value);
+    g_free (str);
+  }
+
+  g_param_spec_unref (pspec);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_serialize_deserialize_segment)
+{
+  GstSegment *seg, *seg2;
+
+  seg = gst_segment_new ();
+  gst_segment_init (seg, GST_FORMAT_DEFAULT);
+  fail_unless (gst_segment_do_seek (seg, 1.2, GST_FORMAT_DEFAULT,
+          GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 20, GST_SEEK_TYPE_SET, 30,
+          NULL));
+  seg2 = get_serialize_deserialize_boxed (seg, GST_TYPE_SEGMENT);
+  fail_unless (gst_segment_is_equal (seg, seg2));
+
+  _test_serialize_deserialize_boxed_in_structure (seg, GST_TYPE_SEGMENT);
+
+  gst_segment_free (seg);
+  gst_segment_free (seg2);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_serialize_deserialize_caps_features)
+{
+  GstCapsFeatures *test_feats[] = {
+    gst_caps_features_new ("abc:val1", "xyz:val2", NULL),
+    gst_caps_features_new ("feat:val", NULL),
+    gst_caps_features_new_any (),
+    gst_caps_features_new_empty ()
+  };
+  gint i;
+  GstCapsFeatures *feats, *feats2;
+
+  for (i = 0; i < G_N_ELEMENTS (test_feats); i++) {
+    feats = test_feats[i];
+    fail_unless (feats != NULL);
+    feats2 = get_serialize_deserialize_boxed (feats, GST_TYPE_CAPS_FEATURES);
+    fail_unless (gst_caps_features_is_equal (feats, feats2));
+    fail_unless (gst_caps_features_is_any (feats) ==
+        gst_caps_features_is_any (feats2));
+
+    _test_serialize_deserialize_boxed_in_structure (feats,
+        GST_TYPE_CAPS_FEATURES);
+
+    gst_caps_features_free (feats);
+    gst_caps_features_free (feats2);
+  }
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_serialize_deserialize_tag_list)
+{
+  GstTagList *test_tags[] = {
+    gst_tag_list_new (GST_TAG_TITLE, "A Title", GST_TAG_ARTIST, "Art櫱",
+        GST_TAG_TRACK_NUMBER, 1, NULL),
+    gst_tag_list_new_empty ()
+  };
+  gint i;
+  GstTagList *tags, *tags2;
+
+  for (i = 0; i < G_N_ELEMENTS (test_tags); i++) {
+    tags = test_tags[i];
+    fail_unless (tags != NULL);
+    tags2 = get_serialize_deserialize_boxed (tags, GST_TYPE_TAG_LIST);
+    fail_unless (gst_tag_list_is_equal (tags, tags2));
+
+    _test_serialize_deserialize_boxed_in_structure (tags, GST_TYPE_TAG_LIST);
+
+    gst_tag_list_unref (tags);
+    gst_tag_list_unref (tags2);
+  }
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_deserialize_serialize_nested_structures)
+{
+  gint i;
+  gchar *structure_str;
+  GstStructure *structure, *structure2;
+
+  /* *INDENT-OFF* */
+  struct
+  {
+    const gchar *serialized_struct;
+    gboolean should_fail;
+    const gchar *path_to_bool;
+    const gchar *subcaps_str;
+  } tests_data[] = {
+      {"s, substruct=[sub, is-deepest=true]", FALSE, "substruct"},
+      {"s, substruct=(structure) [sub, is-deepest=true]", FALSE, "substruct"},
+      {"s, substruct=[sub, is-substruct=true, subsubstruct=[subsub, is-deepest=true]]", FALSE, "substruct/subsubstruct"},
+      {"s, substruct=[sub, is-substruct=true, subsubstruct=[subsub, subsubsubstruct=[subsubsub, is-deepest=true]]]", FALSE, "substruct/subsubstruct/subsubsubstruct"},
+      {"s, substruct=[sub, an-array={a, b}, subsubstruct=[subsub, a-range=[1,2], a-string=\"this is a \\\"string\\\"\"]]", FALSE, NULL},
+      {"s, sub-caps=[nested-caps(some:Feature), is-caps=true; second, caps-structure=true]", FALSE, NULL, "nested-caps(some:Feature), is-caps=true; second, caps-structure=true"},
+      {"s, sub-caps=[nested-caps(some:Feature)]", FALSE, NULL, "nested-caps(some:Feature)"},
+      {"s, array=(structure){[struct, n=1], [struct, n=2]}"},
+      /* Broken structure with substructures */
+      {"s, substruct=[sub, is-substruct=true", TRUE},
+      {"s, substruct=[sub, is-substruct=true, sub=\"yes]", TRUE},
+      {"s, substruct=[sub, a-broken-string=$broken]", TRUE},
+      {"s, sub-caps=(int)[nested-caps(some:Feature)]", TRUE},
+  };
+  /* *INDENT-ON* */
+
+  for (i = 0; i < G_N_ELEMENTS (tests_data); i++) {
+    structure = gst_structure_new_from_string (tests_data[i].serialized_struct);
+    if (tests_data[i].should_fail) {
+      fail_if (structure, "%s not be deserialized",
+          tests_data[i].serialized_struct);
+      continue;
+    }
+    fail_unless (structure, "%s could not be deserialized",
+        tests_data[i].serialized_struct);
+    structure_str = gst_structure_to_string (structure);
+    structure2 = gst_structure_new_from_string (structure_str);
+    fail_unless (gst_structure_is_equal (structure, structure2));
+    g_free (structure_str);
+
+    if (tests_data[i].path_to_bool) {
+      const GstStructure *tmpstruct = structure;
+      gchar **tmpstrv = g_strsplit (tests_data[i].path_to_bool, "/", -1);
+      gint j;
+
+      for (j = 0; tmpstrv[j]; j++) {
+        const GValue *v = gst_structure_get_value (tmpstruct, tmpstrv[j]);
+
+        fail_unless (v, "Could not find '%s' in %s", tmpstrv[j],
+            gst_structure_to_string (tmpstruct));
+        tmpstruct = gst_value_get_structure (v);
+
+        fail_unless (GST_IS_STRUCTURE (tmpstruct));
+        if (!tmpstrv[j + 1]) {
+          gboolean tmp;
+
+          fail_unless (gst_structure_get_boolean (tmpstruct, "is-deepest", &tmp)
+              && tmp);
+        }
+      }
+      g_strfreev (tmpstrv);
+    }
+    if (tests_data[i].subcaps_str) {
+      const GValue *v = gst_structure_get_value (structure, "sub-caps");
+      const GstCaps *caps = gst_value_get_caps (v);
+      GstCaps *caps2 = gst_caps_from_string (tests_data[i].subcaps_str);
+
+      fail_unless (gst_caps_is_equal (caps, caps2));
+      gst_caps_unref (caps2);
+    }
+
+    /* Ensure that doing a round trip works as expected */
+    structure_str = gst_structure_to_string (structure2);
+    gst_structure_free (structure2);
+    structure2 = gst_structure_new_from_string (structure_str);
+    fail_unless (gst_structure_is_equal (structure, structure2));
+    gst_structure_free (structure);
+    gst_structure_free (structure2);
+    g_free (structure_str);
+  }
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_serialize_deserialize_sample)
+{
+  GstSample *samp, *samp2;
+  gsize buff_len = 8;
+  const gchar buff_str[8] = "buf\ndat";
+  gchar *buff_val;
+  GstBuffer *buff = gst_buffer_new_wrapped (g_strdup (buff_str), buff_len);
+  GstCaps *caps = gst_caps_new_simple ("caps", "Int", G_TYPE_INT, 20,
+      "String", G_TYPE_STRING, "a string", NULL);
+  GstSegment *seg = gst_segment_new ();
+
+  gst_segment_init (seg, GST_FORMAT_DEFAULT);
+  fail_unless (gst_segment_do_seek (seg, 1.2, GST_FORMAT_DEFAULT,
+          GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 20, GST_SEEK_TYPE_SET, 30,
+          NULL));
+  fail_unless (buff != NULL);
+  fail_unless (caps != NULL);
+  samp = gst_sample_new (buff, caps, seg,
+      gst_structure_new ("structure", "Float", G_TYPE_FLOAT, -2.5, NULL));
+  gst_buffer_unref (buff);
+  gst_caps_unref (caps);
+
+  samp2 = get_serialize_deserialize_boxed (samp, GST_TYPE_SAMPLE);
+  fail_unless (gst_caps_is_equal (gst_sample_get_caps (samp),
+          gst_sample_get_caps (samp2)));
+  fail_unless (gst_structure_is_equal (gst_sample_get_info (samp),
+          gst_sample_get_info (samp2)));
+  fail_unless (gst_segment_is_equal (gst_sample_get_segment (samp),
+          gst_sample_get_segment (samp2)));
+
+  buff = gst_sample_get_buffer (samp);
+  gst_buffer_extract_dup (buff, 0, -1, (gpointer *) & buff_val, &buff_len);
+  fail_unless_equals_int (buff_len, 8);
+  fail_unless_equals_string (buff_val, buff_str);
+  g_free (buff_val);
+  buff = gst_sample_get_buffer (samp2);
+  gst_buffer_extract_dup (buff, 0, -1, (gpointer *) & buff_val, &buff_len);
+  fail_unless_equals_int (buff_len, 8);
+  fail_unless_equals_string (buff_val, buff_str);
+  g_free (buff_val);
+
+  _test_serialize_deserialize_boxed_in_structure (samp, GST_TYPE_SAMPLE);
+
+  gst_sample_unref (samp);
+  gst_sample_unref (samp2);
+  gst_segment_free (seg);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_value_suite (void)
 {
@@ -3455,6 +3935,7 @@ gst_value_suite (void)
   tcase_add_test (tc_chain, test_deserialize_gtype);
   tcase_add_test (tc_chain, test_deserialize_gtype_failures);
   tcase_add_test (tc_chain, test_deserialize_bitmask);
+  tcase_add_test (tc_chain, test_deserialize_array);
   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);
@@ -3473,6 +3954,7 @@ gst_value_suite (void)
   tcase_add_test (tc_chain, test_date_time);
   tcase_add_test (tc_chain, test_fraction_range);
   tcase_add_test (tc_chain, test_serialize_deserialize_caps);
+  tcase_add_test (tc_chain, test_compare_caps);
   tcase_add_test (tc_chain, test_int_range);
   tcase_add_test (tc_chain, test_int64_range);
   tcase_add_test (tc_chain, test_serialize_int64_range);
@@ -3484,9 +3966,16 @@ gst_value_suite (void)
   tcase_add_test (tc_chain, test_structure_basic);
   tcase_add_test (tc_chain, test_structure_single_ops);
   tcase_add_test (tc_chain, test_structure_ops);
+  tcase_add_test (tc_chain, test_serialize_deserialize_structure);
   tcase_add_test (tc_chain, test_transform_array);
   tcase_add_test (tc_chain, test_transform_list);
   tcase_add_test (tc_chain, test_serialize_null_aray);
+  tcase_add_test (tc_chain, test_deserialize_with_pspec);
+  tcase_add_test (tc_chain, test_deserialize_serialize_nested_structures);
+  tcase_add_test (tc_chain, test_serialize_deserialize_segment);
+  tcase_add_test (tc_chain, test_serialize_deserialize_caps_features);
+  tcase_add_test (tc_chain, test_serialize_deserialize_tag_list);
+  tcase_add_test (tc_chain, test_serialize_deserialize_sample);
 
   return s;
 }
index 18dd246..61a653f 100644 (file)
    fun:clone
 }
 
+### glibc suppressions
+
+{
+   <conditional jump on wim's debian 2/2/06>
+   Memcheck:Cond
+   obj:/lib/ld-2.*.so
+   fun:dl_open_worker
+   obj:/lib/ld-2.*.so
+   fun:_dl_open
+   fun:dlopen_doit
+   obj:/lib/ld-2.*.so
+   fun:_dlerror_run
+   fun:dlopen
+   fun:g_module_open
+   fun:gst_plugin_load_file
+}
+
+{
+   <Conditional jump>
+   Memcheck:Cond
+   fun:strlen
+   fun:fillin_rpath
+   fun:_dl_init_paths
+   fun:dl_main
+   fun:_dl_sysdep_start
+   fun:_dl_start
+   obj:/lib64/ld-2.*.so
+   obj:*
+   obj:*
+}
+
+{
+   <Conditional jump>
+   Memcheck:Cond
+   fun:_dl_relocate_object
+   fun:dl_main
+   fun:_dl_sysdep_start
+   fun:_dl_start
+}
+
+{
+   <insert a suppression name here>
+   Memcheck:Cond
+   fun:*
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.2.5
+}
+
+# glibc does not deallocate thread-local storage
+
+{
+   <tls>
+   Memcheck:Leak
+   fun:calloc
+   fun:_dl_allocate_tls
+   fun:pthread_create@@*
+}
+
+{
+   <tls>
+   Memcheck:Leak
+   fun:calloc
+   fun:allocate_dtv
+   fun:_dl_allocate_tls
+}
+
+# I get an extra stack entry on x86/dapper
+{
+   <tls>
+   Memcheck:Leak
+   fun:calloc
+   obj:/lib/ld-2.3.*.so
+   fun:_dl_allocate_tls
+   fun:pthread_create@@*
+}
+
+
+{
+   <pthread strstr>
+   Memcheck:Cond
+   fun:strstr
+   fun:__pthread_initialize_minimal
+   obj:/lib/libpthread-*.so
+   obj:/lib/libpthread-*.so
+   fun:call_init
+   fun:_dl_init
+   obj:/lib/ld-*.so
+}
+
 # a thread-related free problem in glibc from Edgard
 {
    __libc_freeres_rw_acess
 }
 
 {
+   <a conditional jump on wim's debian>
+   Memcheck:Cond
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+}
+
+# g_module_open-related problems
+{
+   <started showing up on fc4-quick>
+   Memcheck:Addr2
+   fun:memcpy
+   fun:_dl_map_object_deps
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.1
+   fun:g_module_open
+   fun:gst_plugin_load_file
+   fun:gst_registry_scan_path_level
+   fun:gst_registry_scan_path_level
+   fun:gst_registry_scan_path_level
+   fun:init_post
+   fun:g_option_context_parse
+   fun:gst_init_check
+   fun:gst_init
+   fun:gst_check_init
+   fun:main
+}
+
+{
+   <started showing up on fc4-quick>
+   Memcheck:Addr4
+   fun:memcpy
+   fun:_dl_map_object_deps
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.1
+   fun:g_module_open
+   fun:gst_plugin_load_file
+   fun:gst_registry_scan_path_level
+   fun:gst_registry_scan_path_level
+   fun:gst_registry_scan_path_level
+   fun:init_post
+   fun:g_option_context_parse
+   fun:gst_init_check
+   fun:gst_init
+   fun:gst_check_init
+   fun:main
+}
+
+{
+   <g_module_open on wim's debian>
+   Memcheck:Cond
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   fun:do_sym
+   fun:_dl_sym
+   fun:dlsym_doit
+   obj:/lib/ld-2.3.*.so
+   fun:_dlerror_run
+   fun:dlsym
+   fun:g_module_symbol
+   fun:g_module_open
+   fun:gst_plugin_load_file
+}
+
+{
+   <g_module_open on wim's debian>
+   Memcheck:Cond
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   fun:dl_open_worker
+   obj:/lib/ld-2.3.*.so
+   fun:_dl_open
+   fun:dlopen_doit
+   obj:/lib/ld-2.3.*.so
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.1
+   fun:g_module_open
+   fun:gst_plugin_load_file
+}
+{
+   <g_module_open on wim's debian>
+   Memcheck:Cond
+   obj:/lib/ld-2.3.*.so
+   fun:dl_open_worker
+   obj:/lib/ld-2.3.*.so
+   fun:_dl_open
+   fun:dlopen_doit
+   obj:/lib/ld-2.3.*.so
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.1
+   fun:g_module_open
+   fun:gst_plugin_load_file
+   fun:gst_plugin_load_by_name
+   fun:gst_plugin_feature_load
+}
+
+{
+   <leak on wim's debian in g_module_open>
+   Memcheck:Leak
+   fun:malloc
+   obj:/lib/ld-2.3.*.so
+   fun:dl_open_worker
+   obj:/lib/ld-2.3.*.so
+   fun:_dl_open
+   fun:dlopen_doit
+   obj:/lib/ld-2.3.*.so
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.1
+   fun:g_module_open
+   fun:gst_plugin_load_file
+   fun:gst_plugin_load_by_name
+}
+
+{
+   <invalid read on wim's debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   fun:dl_open_worker
+   obj:/lib/ld-2.3.*.so
+   fun:_dl_open
+   fun:dlopen_doit
+   obj:/lib/ld-2.3.*.so
+}
+
+{
+   <invalid read on wim's debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   fun:dl_open_worker
+   obj:/lib/ld-2.3.*.so
+   fun:_dl_open
+   fun:dlopen_doit
+   obj:/lib/ld-2.3.*.so
+   fun:_dlerror_run
+}
+
+{
+   <invalid read on wim's debian - 2006-02-02>
+   Memcheck:Addr4
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   fun:dl_open_worker
+   obj:/lib/ld-2.3.*.so
+   fun:_dl_open
+   fun:dlopen_doit
+   obj:/lib/ld-2.3.*.so
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.1
+   fun:g_module_open
+}
+
+{
+   <invalid read on wim's debian - 2006-02-02>
+   Memcheck:Addr4
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   fun:dl_open_worker
+   obj:/lib/ld-2.3.*.so
+   fun:_dl_open
+   fun:dlopen_doit
+   obj:/lib/ld-2.3.*.so
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.1
+   fun:g_module_open
+}
+
+{
+   <invalid read on wim's debian - 2006-02-02>
+   Memcheck:Addr4
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   fun:do_sym
+   fun:_dl_sym
+   fun:dlsym_doit
+   obj:/lib/ld-2.3.*.so
+   fun:_dlerror_run
+   fun:dlsym
+   fun:g_module_symbol
+   fun:g_module_open
+}
+
+{
    <futex on Andy's 64-bit ubuntu>
    Memcheck:Param
    futex(uaddr2)
    fun:setup_messaging
 }
 
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+   fun:g_module_open
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libc-2.7.so
+   fun:_dl_sym
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlsym
+   fun:g_module_symbol
+   fun:g_module_open
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+   fun:g_module_open
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+   fun:g_module_open
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+   fun:g_module_open
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libc-2.7.so
+   obj:/lib/ld-2.7.so
+   fun:__libc_dlopen_mode
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libc-2.7.so
+   obj:/lib/ld-2.7.so
+   fun:__libc_dlopen_mode
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libc-2.7.so
+   obj:/lib/ld-2.7.so
+   fun:__libc_dlopen_mode
+   obj:/lib/i686/cmov/libc-2.7.so
+   obj:/lib/i686/cmov/libc-2.7.so
+   obj:/lib/i686/cmov/libc-2.7.so
+   obj:/lib/i686/cmov/libc-2.7.so
+   obj:/lib/i686/cmov/libc-2.7.so
+   fun:iconv_open
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libc-2.7.so
+   obj:/lib/ld-2.7.so
+   fun:__libc_dlopen_mode
+   obj:/lib/i686/cmov/libc-2.7.so
+   obj:/lib/i686/cmov/libc-2.7.so
+   obj:/lib/i686/cmov/libc-2.7.so
+   obj:/lib/i686/cmov/libc-2.7.so
+   obj:/lib/i686/cmov/libc-2.7.so
+   fun:iconv_open
+}
+
+{
+   <suppression for glibc 2.7 on Ubunty Hardy 64-bit>
+   Memcheck:Addr8
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libc-2.7.so
+   obj:/lib/ld-2.7.so
+   fun:__libc_dlopen_mode
+   obj:/lib/libc-2.7.so
+   obj:/lib/libc-2.7.so
+   obj:/lib/libc-2.7.so
+   obj:/lib/libc-2.7.so
+   obj:/lib/libc-2.7.so
+   fun:iconv_open
+}
+
+{
+   <suppression for glibc 2.7 on Ubunty Hardy 64-bit>
+   Memcheck:Addr8
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libc-2.7.so
+   obj:/lib/ld-2.7.so
+   fun:__libc_dlopen_mode
+   obj:/lib/libc-2.7.so
+   obj:/lib/libc-2.7.so
+   obj:/lib/libc-2.7.so
+   obj:/lib/libc-2.7.so
+   obj:/lib/libc-2.7.so
+   fun:iconv_open
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+}
+
+{
+   <suppression for glibc 2.7 on Ubunty Hardy 64-bit>
+   Memcheck:Addr8
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libc-2.7.so
+   obj:/lib/ld-2.7.so
+   fun:__libc_dlopen_mode
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Cond
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Cond
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Cond
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Cond
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Cond
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Cond
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+}
+
+{
+   <suppression for glibc 2.7 on debian>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/i686/cmov/libdl-2.7.so
+   fun:dlopen
+}
+
 # suppression for a glibc bug:
 # http://valgrind.org/docs/manual/faq.html#faq.exit_errors>
 {
    fun:__libc_freeres
 }
 
+# valgrind doesn't allow me to specify a suppression for Addr1, Addr2, Addr4
+# as Addr*, so 3 copies for that; and then 2 of each for that pesky memcpy
+{
+   <Invalid read of size 1, 2, 4 on thomas's FC4>
+   Memcheck:Addr1
+   fun:_dl_signal_error
+   fun:_dl_map_object_deps
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.1
+   fun:g_module_open
+}
+
+{
+   <Invalid read of size 1, 2, 4 on thomas's FC4>
+   Memcheck:Addr2
+   fun:_dl_signal_error
+   fun:_dl_map_object_deps
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.1
+   fun:g_module_open
+}
+{
+   <Invalid read of size 1, 2, 4 on thomas's FC4>
+   Memcheck:Addr4
+   fun:_dl_signal_error
+   fun:_dl_map_object_deps
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.1
+   fun:g_module_open
+}
+
+{
+   <Invalid read of size 1, 2, 4 on thomas's FC4>
+   Memcheck:Addr1
+   fun:memcpy
+   fun:_dl_signal_error
+   fun:_dl_map_object_deps
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.1
+   fun:g_module_open
+}
+
+{
+   <Invalid read of size 1, 2, 4 on thomas's FC4>
+   Memcheck:Addr2
+   fun:memcpy
+   fun:_dl_signal_error
+   fun:_dl_map_object_deps
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.1
+   fun:g_module_open
+}
+{
+   <Invalid read of size 1, 2, 4 on thomas's FC4>
+   Memcheck:Addr4
+   fun:memcpy
+   fun:_dl_signal_error
+   fun:_dl_map_object_deps
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.1
+   fun:g_module_open
+}
+
+{
+   <Addr8 on Andy's AMD64 ubuntu in dl_open>
+   Memcheck:Addr8
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/libc-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   fun:_dl_open
+   obj:/lib/libdl-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+}
+
+{
+   <Conditional jump on Andy's AMD64 ubuntu>
+   Memcheck:Cond
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/libc-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   fun:_dl_open
+   obj:/lib/libdl-2.3.*.so
+   obj:/lib/ld-2.3.*.so
+   obj:/lib/libdl-2.3.*.so
+   fun:dlopen
+   fun:g_module_open
+   fun:gst_plugin_load_file
+   fun:gst_plugin_load_by_name
+   fun:gst_plugin_feature_load
+}
+
+{
+   <Mike's x86 dapper>
+   Memcheck:Addr4
+   obj:/lib/ld-2.3.6.so
+   obj:/lib/ld-2.3.6.so
+   obj:/lib/tls/i686/cmov/libc-2.3.6.so
+   obj:/lib/ld-2.3.6.so
+   fun:_dl_open
+   obj:/lib/tls/i686/cmov/libdl-2.3.6.so
+   obj:/lib/ld-2.3.6.so
+   obj:/lib/tls/i686/cmov/libdl-2.3.6.so
+   fun:dlopen
+}
+
+{
+   <Mike's x86 dapper>
+   Memcheck:Cond
+   obj:/lib/ld-2.3.6.so
+   obj:/lib/tls/i686/cmov/libc-2.3.6.so
+   obj:/lib/ld-2.3.6.so
+   fun:_dl_open
+   obj:/lib/tls/i686/cmov/libdl-2.3.6.so
+   obj:/lib/ld-2.3.6.so
+   obj:/lib/tls/i686/cmov/libdl-2.3.6.so
+   fun:dlopen
+}
+
+{
+   <Another dapper one>
+   Memcheck:Cond
+   obj:/lib/ld-2.3.6.so
+   obj:/lib/ld-2.3.6.so
+   obj:/lib/ld-2.3.6.so
+   obj:/lib/tls/i686/cmov/libc-2.3.6.so
+   obj:/lib/ld-2.3.6.so
+   fun:_dl_open
+   obj:/lib/tls/i686/cmov/libdl-2.3.6.so
+   obj:/lib/ld-2.3.6.so
+   obj:/lib/tls/i686/cmov/libdl-2.3.6.so
+   fun:dlopen
+}
+
 ### glib suppressions
 {
    <g_parse_debug_string>
 #pthread memleaks
 
 {
+   Thread creation leak
+   Memcheck:Leak
+   fun:calloc
+   fun:allocate_dtv
+   fun:_dl_allocate*
+   fun:_dl_allocate*
+   fun:__pthread_initialize_minimal
+}
+
+{
+   Thread management leak
+   Memcheck:Leak
+   fun:calloc
+   fun:allocate_dtv
+   fun:_dl_allocate*
+   fun:_dl_allocate*
+   fun:__pthread_*
+}
+
+{
+   Thread management leak 2
+   Memcheck:Leak
+   fun:memalign
+   fun:_dl_allocate*
+   fun:_dl_allocate*
+   fun:__pthread_*
+}
+
+{
    pthread_create Syscall param write(buf) points to uninitialised byte(s)
    Memcheck:Param
    write(buf)
 }
 
 {
+   <annoying read error inside dlopen stuff on Ubuntu Dapper x86_64>
+   Memcheck:Addr8
+   obj:/lib/ld-2.3.6.so
+}
+
+{
    <Ubuntu Dapper x86_64>
    Memcheck:Param
    futex(uaddr2)
 }
 
 {
-   <libcdio 0.76 leak>
-   Memcheck:Leak
-   fun:calloc
-   obj:/usr/lib/libcdio.so.6.0.1
-   fun:cdio_open_am_linux
-   obj:/usr/lib/libcdio.so.6.0.1
-   fun:cdio_open_am
+   <Ubuntu Dapper x86_64 dlopen stuff again>
+   Memcheck:Cond
+   obj:/lib/ld-2.3.6.so
+   obj:/lib/ld-2.3.6.so
+   fun:_dl_open
+   obj:/lib/libdl-2.3.6.so
+   obj:/lib/ld-2.3.6.so
+   obj:/lib/libdl-2.3.6.so
+   fun:dlopen
+   fun:g_module_open
+   fun:gst_plugin_load_file
+}
+# this exists in a bunch of different variations, hence the short tail/trace
+{
+   <dlopen invalid read of size 4 suppression on tpm's Ubuntu edgy/x86>
+   Memcheck:Addr4
+   obj:/lib/ld-2.4.so
+   obj:/lib/ld-2.4.so
+}
+{
+   <and the same for 64bit systems>
+   Memcheck:Addr8
+   obj:/lib/ld-2.4.so
+   obj:/lib/ld-2.4.so
 }
 
+# More edgy suppressions (Mike)
 {
-   <First of many Alsa errors>
+   <dlopen Condition jump suppressions for Ubuntu Edgy/x86>
    Memcheck:Cond
-   fun:snd_pcm_direct_shm_create_or_connect
-   fun:snd_pcm_dsnoop_open
-   fun:_snd_pcm_dsnoop_open
-   obj:/*lib/libasound.so.2.0.0
-   obj:/*lib/libasound.so.2.0.0
-   fun:snd_pcm_open_slave
-   fun:_snd_pcm_plug_open
-   obj:/*lib/libasound.so.2.0.0
-   fun:snd_pcm_open_slave
-   fun:_snd_pcm_asym_open
+   obj:/lib/ld-2.4.so
+   obj:/lib/ld-2.4.so
+   obj:/lib/ld-2.4.so
+   obj:/lib/ld-2.4.so
+   fun:dlopen_doit
+   obj:/lib/ld-2.4.so
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.1
+}
+
+{
+   <dlopen Condition jump suppressions for Ubuntu Edgy/x86>
+   Memcheck:Cond
+   obj:/lib/ld-2.4.so
+   obj:/lib/ld-2.4.so
+   obj:/lib/ld-2.4.so
+   obj:/lib/ld-2.4.so
+   obj:/lib/ld-2.4.so
+   obj:/lib/ld-2.4.so
+   fun:dlopen_doit
+   obj:/lib/ld-2.4.so
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.1
+}
+
+{
+   <dlopen Condition jump suppressions for Ubuntu Edgy/x86>
+   Memcheck:Cond
+   obj:/lib/ld-2.4.so
+   obj:/lib/ld-2.4.so
+   obj:/lib/ld-2.4.so
+   fun:do_sym
+   fun:_dl_sym
+}
+
+# This one's overly general, but there's zero other information in the stack
+# trace - just these five lines!
+{
+   <dlopen Condition jump suppressions for Ubuntu Edgy/x86>
+   Memcheck:Cond
+   obj:/lib/ld-2.4.so
+   obj:/lib/ld-2.4.so
+   obj:/lib/ld-2.4.so
+   obj:/lib/ld-2.4.so
+   obj:/lib/ld-2.4.so
+}
+
+{
+   <tls leaks on Edgy/x86>
+   Memcheck:Leak
+   fun:calloc
+   obj:/lib/ld-2.4.so
+   fun:_dl_allocate_tls
+   fun:pthread_create@@GLIBC_2.1
+}
+
+# TLS leaks for feisty/x86
+{
+   <tls leaks on Feisty/x86>
+   Memcheck:Leak
+   fun:calloc
+   fun:allocate_dtv
+   fun:_dl_allocate_tls
+   fun:pthread_create@@GLIBC_2.1
+}
+
+{
+   <libcdio 0.76 leak>
+   Memcheck:Leak
+   fun:calloc
+   obj:/usr/lib/libcdio.so.6.0.1
+   fun:cdio_open_am_linux
+   obj:/usr/lib/libcdio.so.6.0.1
+   fun:cdio_open_am
+}
+
+{
+   <Addr8 on Jan's AMD64 ubuntu Feisty in dl_open>
+   Memcheck:Addr8
+   obj:/lib/ld-2.5.so
+}
+
+{
+   <First of many Alsa errors>
+   Memcheck:Cond
+   fun:snd_pcm_direct_shm_create_or_connect
+   fun:snd_pcm_dsnoop_open
+   fun:_snd_pcm_dsnoop_open
+   obj:/*lib/libasound.so.2.0.0
+   obj:/*lib/libasound.so.2.0.0
+   fun:snd_pcm_open_slave
+   fun:_snd_pcm_plug_open
+   obj:/*lib/libasound.so.2.0.0
+   fun:snd_pcm_open_slave
+   fun:_snd_pcm_asym_open
    obj:/*lib/libasound.so.2.0.0
    obj:/*lib/libasound.so.2.0.0
 }
    fun:snd_config_update_r
    fun:snd_config_update
 }
+{
+   <alsa leak snd_config_searcha_hooks>
+   Memcheck:Leak
+   fun:*alloc
+   fun:_dl_close_worker
+   ...
+   fun:snd_config_searcha_hooks
+}
 
 {
    <nss lookup within ALSA>
    fun:FcInitLoadConfig
 }
 
+# Issues with ubuntu Hardy, same crack as for previous ubuntus
+{
+   <tls leak generic ubuntu hardy x86>
+   Memcheck:Leak
+   fun:calloc
+   obj:*
+   fun:_dl_allocate_tls
+   fun:pthread_create@@*
+   obj:/usr/lib/libgthread*
+   fun:g_thread_*
+}
+
+# I've made this version generic, so that it covers future modifications
+# of library names
+{
+   <tls leak generic>
+   Memcheck:Leak
+   fun:calloc
+   obj:*
+   fun:_dl_allocate_tls
+   fun:pthread_create@@*
+   fun:g_thread_*
+}
+
+# series of invalid read of size 4 in g_module_open for ubuntu
+# hardy x86/32bit
+{
+   <invalid read of size 4 within <g_module_open>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/tls/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/tls/i686/cmov/libdl-2.7.so
+   fun:dlopen
+   fun:g_module_open
+   fun:gst_plugin_load_*
+}
+
+{
+   <invalid read of size 4 within <g_module_open>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/tls/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/tls/i686/cmov/libdl-2.7.so
+   fun:dlopen
+   fun:g_module_open
+   fun:gst_plugin_load_*
+}
+
+{
+   <invalid read of size 4 within <g_module_open>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/tls/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/tls/i686/cmov/libdl-2.7.so
+   fun:dlopen
+   fun:g_module_open
+   fun:gst_plugin_load_*
+}
+
+{
+   <invalid read of size 4 within <g_module_open>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/tls/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/tls/i686/cmov/libdl-2.7.so
+   fun:dlopen
+   fun:g_module_open
+   fun:gst_plugin_load_*
+}
+
+{
+   <invalid read of size 4 within <g_module_open>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/tls/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/tls/i686/cmov/libdl-2.7.so
+   fun:dlopen
+   fun:g_module_open
+   fun:gst_plugin_load*
+}
+
+{
+   <invalid read of size 4 within <g_module_open>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/tls/i686/cmov/libc-2.7.so
+   fun:_dl_sym
+   obj:/lib/tls/i686/cmov/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/tls/i686/cmov/libdl-2.7.so
+   fun:dlsym
+   fun:g_module_symbol
+   fun:g_module_open
+   fun:gst_plugin_load_*
+}
+
+# series of invalid read of size 8 in g_module_open for ubuntu
+# hardy x86/64bit
+{
+   <invalid read of size 8 within <g_module_open>
+   Memcheck:Addr8
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libdl-2.7.so
+   fun:dlopen
+   fun:g_module_open
+}
+
+{
+   <invalid read of size 8 within <g_module_open>
+   Memcheck:Addr8
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libdl-2.7.so
+   fun:dlopen
+   fun:g_module_open
+}
+
+{
+   <invalid read of size 8 within <g_module_open>
+   Memcheck:Addr8
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libdl-2.7.so
+   fun:dlopen
+   fun:g_module_open
+}
+
+{
+   <invalid read of size 8 within <g_module_open>
+   Memcheck:Addr8
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libdl-2.7.so
+   fun:dlopen
+   fun:g_module_open
+}
+
+{
+   <invalid read of size 8 within <g_module_open>
+   Memcheck:Addr8
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libdl-2.7.so
+   fun:dlopen
+   fun:g_module_open
+}
+
+{
+   <invalid read of size 8 within <g_module_open>
+   Memcheck:Addr8
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libdl-2.7.so
+   fun:dlopen
+   fun:g_module_open
+}
+
+{
+   <invalid read of size 8 within <g_module_open>
+   Memcheck:Addr8
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libc-2.7.so
+   obj:/lib/libdl-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libdl-2.7.so
+   fun:dlsym
+   fun:g_module_symbol
+   fun:g_module_open
+}
+
+{
+   <GLib caching>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/tls/i686/cmov/libc-2.7.so
+   obj:/lib/ld-2.7.so
+   fun:__libc_dlopen_mode
+   fun:__nss_lookup_function
+   obj:/lib/tls/i686/cmov/libc-2.7.so
+   fun:__nss_passwd_lookup
+   fun:getpwnam_r
+}
+
+{
+   <GLib caching>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/tls/i686/cmov/libc-2.7.so
+   obj:/lib/ld-2.7.so
+   fun:__libc_dlopen_mode
+   fun:__nss_lookup_function
+   obj:/lib/tls/i686/cmov/libc-2.7.so
+   fun:__nss_passwd_lookup
+   fun:getpwnam_r
+}
+
+{
+   <GLib caching>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/tls/i686/cmov/libc-2.7.so
+   obj:/lib/ld-2.7.so
+   fun:__libc_dlopen_mode
+   fun:__nss_lookup_function
+   obj:/lib/tls/i686/cmov/libnss_compat-2.7.so
+   fun:_nss_compat_getpwnam_r
+   fun:getpwnam_r
+}
+
+{
+   <GLib caching>
+   Memcheck:Addr4
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/tls/i686/cmov/libc-2.7.so
+   obj:/lib/ld-2.7.so
+   fun:__libc_dlopen_mode
+   fun:__nss_lookup_function
+   obj:/lib/tls/i686/cmov/libnss_compat-2.7.so
+   fun:_nss_compat_getpwnam_r
+   fun:getpwnam_r
+}
+
+{
+   <GLib caching>
+   Memcheck:Addr8
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/ld-2.7.so
+   obj:/lib/libc-2.7.so
+   obj:/lib/ld-2.7.so
+   fun:__libc_dlopen_mode
+   fun:__nss_lookup_function
+   obj:/lib/libc-2.7.so
+   fun:getpwnam_r
+}
+
 ## Leaks in ALSA (variations of leak from snd_config_load1)
 
 {
 ## Leak of GIO module through gnomevfs
 
 {
-   <gio leak>
-   Memcheck:Leak
-   fun:malloc
-   fun:g_malloc
-   fun:*
+   <gio leak>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:*
+   fun:*
+   fun:g_type_create_instance
+   fun:*
+   fun:*
+   fun:*
+   fun:*
+   fun:g_io_module_new
+   fun:g_io_modules_load_all_in_directory
+   fun:*
+   fun:get_default_vfs
+}
+
+## Conditional jump in getaddrinfo (bilboed, gentoo ~amd64, Dec 13 2008)
+{
+   <Leak of addrinfo in esd>
+   Memcheck:Cond
+   fun:gaih_inet
+   fun:getaddrinfo
+}
+
+## Dynamic pad templates in mxfmux
+{
+   <Dynamic pad templates in mxfmux>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   fun:gst_caps_new_empty
+   fun:gst_caps_from_string
+   fun:mxf_*_init
+   fun:plugin_init
+}
+
+## We don't know if ffmpeg frees this or not and better pass a copy for safety
+{
+   <insert a suppression name here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_strdup
+   fun:gst_ffmpeg_cfg_fill_context
+   fun:gst_ffmpegenc_setcaps
+   fun:gst_pad_set_caps
+}
+
+## Leak/overreads with glibc-2.10
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:do_sym
+   fun:dlsym_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlsym
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:do_sym
+   fun:dlsym_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlsym
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen*
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_relocate_object
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen*
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_check_map_versions
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen*
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen*
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_relocate_object
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen*
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_check_map_versions
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen*
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_map_object*
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen*
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_map_object*
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen*
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_check_caller
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen*
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_check_caller
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen*
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   obj:/lib*/libc-2.10.*.so
+   obj:/lib*/libc-2.10.*.so
+   fun:_vgnU_freeres
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   obj:/lib*/libc-2.10.*.so
+   obj:/lib*/libc-2.10.*.so
+   fun:_vgnU_freeres
+}
+{
+   <glibc-2.10 mysterious invalid free on exit>
+   Memcheck:Free
+   fun:free
+   obj:/lib*/libc-2.10.*.so
+   obj:/lib*/libc-2.10.*.so
+   fun:_vgnU_freeres
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_fini
+   fun:__run_exit_handlers
+   fun:exit
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_fini
+   fun:__run_exit_handlers
+   fun:exit
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_sort_fini
+   fun:_dl_fini
+   fun:__run_exit_handlers
+   fun:exit
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_sort_fini
+   fun:_dl_fini
+   fun:__run_exit_handlers
+   fun:exit
+}
+
+# glibc-2.10 dl overreads
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_fixup
+   fun:_dl_runtime_resolve
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_fixup
+   fun:_dl_runtime_resolve
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_lookup_symbol_x
+   fun:_dl_fixup
+   fun:_dl_runtime_resolve
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_lookup_symbol_x
+   fun:_dl_fixup
+   fun:_dl_runtime_resolve
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:call_init
+   fun:_dl_init
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_init
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:do_lookup_x
+   fun:_dl_lookup_symbol_x
+   fun:_dl_relocate_object
+   fun:dl_main
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:do_lookup_x
+   fun:_dl_lookup_symbol_x
+   fun:_dl_relocate_object
+   fun:dl_main
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_lookup_symbol_x
+   fun:_dl_relocate_object
+   fun:dl_main
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_relocate_object
+   fun:dl_main
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:dl_main
+   fun:_dl_sysdep_start
+   fun:_dl_start
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:dl_main
+   fun:_dl_sysdep_start
+   fun:_dl_start
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:*
+   fun:do_lookup_x
+   fun:_dl_lookup_symbol_x
+   fun:_dl_relocate_object
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:do_lookup_x
+   fun:_dl_lookup_symbol_x
+   fun:_dl_relocate_object
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_check_map_versions
+   fun:_dl_check_all_versions
+   fun:version_check_doit
+   fun:_dl_receive_error
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_check_map_versions
+   fun:_dl_check_all_versions
+   fun:version_check_doit
+   fun:_dl_receive_error
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_check_all_versions
+   fun:version_check_doit
+   fun:_dl_receive_error
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_check_all_versions
+   fun:version_check_doit
+   fun:_dl_receive_error
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:_dl_check_map_versions
+   fun:_dl_check_all_versions
+   fun:version_check_doit
+   fun:_dl_receive_error
+   fun:dl_main
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:*
+   fun:_dl_check_map_versions
+   fun:_dl_check_all_versions
+   fun:version_check_doit
+   fun:_dl_receive_error
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:init_tls
+   fun:dl_main
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:init_tls
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_map_object_deps
+   fun:dl_main
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_map_object_deps
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_protect_relro
+   fun:_dl_relocate_object
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:do_lookup_x
+   fun:_dl_lookup_symbol_x
+   fun:_dl_relocate_object
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_setup_hash
+   fun:_dl_map_object_from_fd
+   fun:_dl_map_object
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:_dl_new_object
+   fun:_dl_map_object_from_fd
+   fun:_dl_map_object
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:*
+   fun:_dl_new_object
+   fun:_dl_map_object_from_fd
+   fun:_dl_map_object
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:openaux
+   fun:_dl_catch_error
+   fun:_dl_map_object_deps
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:_dl_map_object
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:*
+   fun:_dl_map_object
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_map_object
+   fun:openaux
+   fun:_dl_catch_error
+   fun:_dl_map_object_deps
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_map_object
+   fun:openaux
+   fun:_dl_catch_error
+   fun:_dl_map_object_deps
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:*
+   fun:_dl_map_object
+   fun:openaux
+   fun:_dl_catch_error
+   fun:_dl_map_object_deps
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:open_path
+   fun:_dl_map_object
+   fun:openaux
+   fun:_dl_catch_error
+   fun:_dl_map_object_deps
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:*
+   fun:open_path
+   fun:_dl_map_object
+   fun:openaux
+   fun:_dl_catch_error
+   fun:_dl_map_object_deps
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_map_object_from_fd
+   fun:_dl_map_object
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_map_object_from_fd
+   fun:_dl_map_object
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:_dl_new_object
+   fun:_dl_map_object_from_fd
+   fun:_dl_map_object
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_new_object
+   fun:_dl_map_object_from_fd
+   fun:_dl_map_object
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_new_object
+   fun:_dl_map_object_from_fd
+   fun:_dl_map_object
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:_dl_name_match_p
+   fun:_dl_map_object
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:*
+   fun:*
+   fun:_dl_map_object
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:_dl_name_match_p
+   fun:_dl_check_map_versions
+   fun:_dl_check_all_versions
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:*
+   fun:do_lookup_x
+   fun:_dl_lookup_symbol_x
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:do_lookup_x
+   fun:_dl_lookup_symbol_x
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:do_lookup_x
+   fun:_dl_lookup_symbol_x
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:do_lookup_x
+   fun:_dl_lookup_symbol_x
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:*
+   fun:do_lookup_x
+   fun:_dl_lookup_symbol_x
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_name_match_p
+   fun:_dl_map_object
+   fun:dl_open_worker
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_name_match_p
+   fun:_dl_map_object
+   fun:dl_open_worker
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:_dl_name_match_p
+   fun:_dl_map_object
+   fun:dl_open_worker
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:*
+   fun:_dl_name_match_p
+   fun:_dl_map_object
+   fun:dl_open_worker
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_lookup_symbol_x
+   fun:_dl_relocate_object
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_lookup_symbol_x
+   fun:_dl_relocate_object
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:*
+   fun:_dl_check_map_versions
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:_dl_check_map_versions
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:*
+   fun:*
+   fun:_dl_check_map_versions
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:*
+   fun:_dl_check_map_versions
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:openaux
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_name_match_p
+   fun:_dl_map_object
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_close_worker
+   fun:_dl_close
+   fun:_dl_catch_error
+   fun:dlerror_run
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_close_worker
+   fun:_dl_close
+   fun:_dl_catch_error
+   fun:dlerror_run
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:*
+   fun:_dl_close_worker
+   fun:_dl_close
+   fun:_dl_catch_error
+   fun:dlerror_run
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:_dl_close_worker
+   fun:_dl_close
+   fun:_dl_catch_error
+   fun:dlerror_run
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:fillin_rpath
+   fun:_dl_init_paths
+   fun:dl_main
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:fillin_rpath
+   fun:_dl_init_paths
+   fun:dl_main
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:*
+   fun:fillin_rpath
+   fun:_dl_init_paths
+   fun:dl_main
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:fillin_rpath
+   fun:_dl_init_paths
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_map_object
+   fun:map_doit
+   fun:_dl_catch_error
+   fun:do_preload
+   fun:dl_main
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_map_object
+   fun:map_doit
+   fun:_dl_catch_error
+   fun:do_preload
+   fun:dl_main
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Param
+   open(filename)
+   fun:open
+   fun:open_verify
+   fun:_dl_map_object
+   fun:map_doit
+   fun:_dl_catch_error
+   fun:do_preload
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Param
+   stat(file_name)
+   fun:_xstat
+   fun:open_path
+   fun:_dl_map_object
+   fun:openaux
+   fun:_dl_catch_error
+   fun:_dl_map_object_deps
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:_dl_catch_error
+   fun:_dl_map_object_deps
+   fun:dl_open_worker
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
    fun:*
-   fun:g_type_create_instance
+   fun:_dl_map_object_deps
+   fun:dl_main
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
    fun:*
+   fun:_dl_map_object_deps
+   fun:dl_main
+}
+
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
    fun:*
    fun:*
+   fun:_dl_map_object_deps
+   fun:dl_main
+}
+
+# glibc-2.10 tls issues
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
    fun:*
-   fun:g_io_module_new
-   fun:g_io_modules_load_all_in_directory
+   fun:init_tls
+   fun:dl_main
+}
+{
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
    fun:*
-   fun:get_default_vfs
+   fun:init_tls
+   fun:dl_main
 }
-
-## Conditional jump in getaddrinfo (bilboed, gentoo ~amd64, Dec 13 2008)
 {
-   <Leak of addrinfo in esd>
+   <glibc-2.10 overreads/conditionals>
    Memcheck:Cond
-   fun:gaih_inet
-   fun:getaddrinfo
+   fun:*
+   fun:*
+   fun:init_tls
+   fun:dl_main
 }
-
-## Dynamic pad templates in mxfmux
 {
-   <Dynamic pad templates in mxfmux>
-   Memcheck:Leak
-   fun:malloc
-   fun:g_malloc
-   fun:g_slice_alloc
-   fun:gst_caps_new_empty
-   fun:gst_caps_from_string
-   fun:mxf_*_init
-   fun:plugin_init
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:*
+   fun:init_tls
+   fun:dl_main
 }
 
-## We don't know if ffmpeg frees this or not and better pass a copy for safety
 {
-   <insert a suppression name here>
-   Memcheck:Leak
-   fun:malloc
-   fun:g_malloc
-   fun:g_strdup
-   fun:gst_ffmpeg_cfg_fill_context
-   fun:gst_ffmpegenc_setcaps
-   fun:gst_pad_set_caps
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Cond
+   fun:_dl_allocate_tls_init
+   fun:dl_main
 }
-
 {
    <glibc-2.10 overreads/conditionals>
    Memcheck:Value8
-   obj:/lib*/libc-2.10.*.so
-   obj:/lib*/libc-2.10.*.so
-   fun:_vgnU_freeres
+   fun:_dl_allocate_tls_init
+   fun:dl_main
 }
 {
    <glibc-2.10 overreads/conditionals>
    Memcheck:Cond
-   obj:/lib*/libc-2.10.*.so
-   obj:/lib*/libc-2.10.*.so
-   fun:_vgnU_freeres
+   fun:*
+   fun:_dl_allocate_tls_init
+   fun:dl_main
 }
 {
-   <glibc-2.10 mysterious invalid free on exit>
-   Memcheck:Free
-   fun:free
-   obj:/lib*/libc-2.10.*.so
-   obj:/lib*/libc-2.10.*.so
-   fun:_vgnU_freeres
+   <glibc-2.10 overreads/conditionals>
+   Memcheck:Value8
+   fun:*
+   fun:_dl_allocate_tls_init
+   fun:dl_main
 }
 
-# glibc-2.10 dl overreads
-
 {
    <glibc-2.10 overreads/conditionals>
    Memcheck:Cond
    arch_prctl(arg2)
    fun:init_tls
 }
+# GLib caching tmp/home directories (glibc-2.10 variants)
+{
+   <glibc-2.10 GLIB leaks>
+   Memcheck:Cond
+   fun:*
+   fun:dl_open_worker
+   fun:*
+   fun:*
+   fun:*
+   fun:_dl_catch_error
+   fun:dlerror_run
+   fun:*
+   fun:__nss_lookup_function
+   fun:__nss_lookup
+   fun:getpwnam*
+}
+{
+   <glibc-2.10 GLIB leaks>
+   Memcheck:Value8
+   fun:*
+   fun:dl_open_worker
+   fun:*
+   fun:*
+   fun:*
+   fun:_dl_catch_error
+   fun:dlerror_run
+   fun:*
+   fun:__nss_lookup_function
+   fun:__nss_lookup
+   fun:getpwnam*
+}
+{
+   <glibc-2.10 GLIB leaks>
+   Memcheck:Cond
+   fun:dl_open_worker
+   fun:*
+   fun:*
+   fun:do_dlopen
+   fun:*
+   fun:dlerror_run
+   fun:*
+   fun:__nss_lookup_function
+   fun:__nss_lookup
+   fun:getpwnam*
+}
+{
+   <glibc-2.10 GLIB leaks>
+   Memcheck:Value8
+   fun:dl_open_worker
+   fun:*
+   fun:*
+   fun:do_dlopen
+   fun:*
+   fun:dlerror_run
+   fun:*
+   fun:__nss_lookup_function
+   fun:__nss_lookup
+   fun:getpwnam*
+}
+
+{
+   <glibc-2.10 GLIB leaks>
+   Memcheck:Value8
+   fun:_dl_add_to_slotinfo
+   fun:dl_main
+}
+{
+   <glibc-2.10 GLIB leaks>
+   Memcheck:Param
+   open(filename)
+   fun:open
+   fun:open_verify
+   fun:open_path
+   fun:_dl_map_object
+}
+
+
 
 # GModule issues with glibc-2.10
 {
    <glibc-2.10 GLIB leaks>
    Memcheck:Value8
+   fun:*
+   fun:*
+   fun:dlsym
+   fun:g_module_symbol
+}
+{
+   <glibc-2.10 GLIB leaks>
+   Memcheck:Value8
    fun:g_module_*
    fun:gst_plugin*
 }
    fun:gst_plugin*
 }
 
+{
+   <glibc-2.10 GLIB leaks>
+   Memcheck:Value8
+   fun:*
+   fun:*
+   fun:dlopen*
+   fun:g_module_open
+}
+{
+   <glibc-2.10 GLIB leaks>
+   Memcheck:Value8
+   fun:*
+   fun:*
+   fun:*
+   fun:*
+   fun:*
+   fun:*
+   fun:*
+   fun:dlsym
+   fun:g_module_symbol
+}
+
+{
+   <glibc-2.10 GLIB leaks>
+   Memcheck:Value8
+   fun:*
+   fun:*
+   fun:*
+   fun:*
+   fun:*
+   fun:dlopen*
+   fun:g_module_open
+}
+
 # Leak in GSlice
 {
    <insert a suppression name here>
    fun:__pthread_initialize_minimal
 }
 
+# glibc 2.11 conditional
+{
+   <glibc-2.11 conditional>
+   Memcheck:Cond
+   fun:_dl_relocate_object
+   fun:dl_main
+   fun:_dl_sysdep_start
+   fun:_dl_start
+   obj:/lib64/ld-2.11.so
+}
+
+# glibc 2.11 Leak
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:*alloc
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.2.5
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:*alloc
+   fun:_dl_*
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.2.5
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:*alloc
+   fun:_dl_*
+   fun:_dl_*
+   fun:_dl_*
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.2.5
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:*alloc
+   fun:*
+   fun:_dl_*
+   fun:openaux
+   fun:_dl_catch_error
+   fun:_dl_map_object_deps
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.2.5
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:*alloc
+   fun:*
+   fun:_dl_map_object
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.2.5
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:*alloc
+   fun:_dl_new_object
+   fun:_dl_map_object_from_fd
+   fun:_dl_map_object
+   fun:openaux
+   fun:_dl_catch_error
+   fun:_dl_map_object_deps
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.2.5
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:*alloc
+   fun:*
+   fun:_dl_*
+   fun:_dl_*
+   fun:_dl_*
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.2.5
+}
+
 # glib type leaks
 {
    <insert_a_suppression_name_here>
    fun:_gst_tag_initialize
 }
 
-# system-wide tags
-# these tags are registered once
-
-{
-   <insert_a_suppression_name_here>
-   Memcheck:Leak
-   fun:*alloc
-   ...
-   fun:gst_tag_register_static
-}
-
 # system-wide type classes that we keep referenced
 
 {
    fun:g_slist_prepend
    fun:gst_debug_add_log_function
 }
+
 {
-   <We do not care about anything ld related, and don't use library constructors>
-   Memcheck:Addr1
-   ...
-   obj:*/ld-*.so
-   ...
-}
-{
-   <We do not care about anything ld related, and don't use library constructors>
-   Memcheck:Addr2
-   ...
-   obj:*/ld-*.so
-   ...
-}
-{
-   <We do not care about anything ld related, and don't use library constructors>
-   Memcheck:Addr4
-   ...
-   obj:*/ld-*.so
+   Leak of debug function list item
+   Memcheck:Leak
+   fun:*alloc
    ...
+   fun:g_slist_copy_deep
+   fun:gst_debug_add_log_function
 }
+
 {
-   <We do not care about anything ld related, and don't use library constructors>
-   Memcheck:Addr8
-   ...
-   obj:*/ld-*.so
-   ...
+  <Ignore dlopen errors when parsing launch lines>
+  Memcheck:Leak
+  fun:malloc
+  ...
+  fun:g_module_open
+  fun:_priv_gst_plugin_load_file_for_registry
 }
+
+# fixed in https://github.com/libunwind/libunwind/commit/b256722d49a63719c69c0416eba9163a4d069584
 {
-   <We do not care about anything ld related, and don't use library constructors>
-   Memcheck:Leak
-   ...
-   obj:*/ld-*.so
-   ...
+  debian libunwind invalid file descriptor -1 in syscall close()
+  Memcheck:Param
+  msync(start)
+  ...
+  fun:_ULx86_64_step
+  fun:generate_unwind_trace
+  fun:gst_debug_get_stack_trace
 }
+
+# fixed in https://github.com/libunwind/libunwind/commit/b256722d49a63719c69c0416eba9163a4d069584
 {
-   <We do not care about anything ld related, and don't use library constructors>
-   Memcheck:Cond
-   ...
-   obj:*/ld-*.so
-   ...
+  fedora libunwind invalid file descriptor -1 in syscall close()
+  Memcheck:Param
+  write(buf)
+  ...
+  fun:_ULx86_64_step
+  fun:generate_unwind_trace
+  fun:gst_debug_get_stack_trace
 }
diff --git a/tests/check/libs/.gitignore b/tests/check/libs/.gitignore
deleted file mode 100644 (file)
index cdf0c9d..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-.dirstamp
-adapter
-aggregator
-baseparse
-basesink
-basesrc
-bitreader
-bitreader-noinline
-bitwriter
-bytereader
-bytereader-noinline
-bytewriter
-bytewriter-noinline
-gdp
-collectpads
-controller
-flowcombiner
-gstharness
-gstlibscpp
-gstnetclientclock
-gstnettimeprovider
-gsttestclock
-libsabi
-sparsefile
-transform1
-transform2
-typefindhelper
-queuearray
-*.check.xml
index 631f982..e51ffcb 100644 (file)
@@ -58,6 +58,8 @@ struct _GstTestAggregator
 
   guint64 timestamp;
   gboolean gap_expected;
+  gboolean do_flush_on_aggregate;
+  gboolean do_remove_pad_on_aggregate;
 };
 
 struct _GstTestAggregatorClass
@@ -100,7 +102,29 @@ gst_test_aggregator_aggregate (GstAggregator * aggregator, gboolean timeout)
           testagg->gap_expected = FALSE;
         }
 
-        gst_aggregator_pad_drop_buffer (pad);
+        if (testagg->do_flush_on_aggregate) {
+          GstBuffer *popped_buf;
+          buf = gst_aggregator_pad_peek_buffer (pad);
+
+          GST_DEBUG_OBJECT (pad, "Flushing on aggregate");
+
+          gst_pad_send_event (GST_PAD (pad), gst_event_new_flush_start ());
+          popped_buf = gst_aggregator_pad_pop_buffer (pad);
+
+          fail_unless (buf == popped_buf);
+          gst_buffer_unref (buf);
+          gst_buffer_unref (popped_buf);
+        } else if (testagg->do_remove_pad_on_aggregate) {
+          buf = gst_aggregator_pad_peek_buffer (pad);
+
+          GST_DEBUG_OBJECT (pad, "Removing pad on aggregate");
+
+          gst_buffer_unref (buf);
+          gst_element_release_request_pad (GST_ELEMENT (aggregator),
+              GST_PAD (pad));
+        } else {
+          gst_aggregator_pad_drop_buffer (pad);
+        }
 
         g_value_reset (&value);
         break;
@@ -364,7 +388,7 @@ _chain_data_init (ChainData * data, GstElement * agg, ...)
   g_free (pad_name);
   gst_pad_set_active (data->srcpad, TRUE);
   data->aggregator = agg;
-  data->sinkpad = gst_element_get_request_pad (agg, "sink_%u");
+  data->sinkpad = gst_element_request_pad_simple (agg, "sink_%u");
   fail_unless (GST_IS_PAD (data->sinkpad));
   fail_unless (gst_pad_link (data->srcpad, data->sinkpad) == GST_PAD_LINK_OK);
 
@@ -797,6 +821,7 @@ GST_START_TEST (test_flushing_seek)
   ChainData data2 = { 0, };
   TestData test = { 0, };
   GstBuffer *buf;
+  guint32 seqnum;
 
   _test_data_init (&test, TRUE);
 
@@ -817,16 +842,20 @@ GST_START_TEST (test_flushing_seek)
   /* now do a successful flushing seek */
   event = gst_event_new_seek (1, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
       GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 10 * GST_SECOND);
+  seqnum = gst_event_get_seqnum (event);
   fail_unless (gst_pad_send_event (test.srcpad, event));
 
-  /* flushing starts once one of the upstream elements sends the first
-   * FLUSH_START */
-  fail_unless_equals_int (test.flush_start_events, 0);
+  /* flushing starts when a flushing seek is received, and stops
+   * when all sink pads have received FLUSH_STOP */
+  fail_unless_equals_int (test.flush_start_events, 1);
   fail_unless_equals_int (test.flush_stop_events, 0);
 
-  /* send a first FLUSH_START on agg:sink_0, will be sent downstream */
+  /* send a first FLUSH_START on agg:sink_0, nothing will be sent
+   * downstream */
   GST_DEBUG_OBJECT (data2.sinkpad, "send flush_start");
-  fail_unless (gst_pad_push_event (data2.srcpad, gst_event_new_flush_start ()));
+  event = gst_event_new_flush_start ();
+  gst_event_set_seqnum (event, seqnum);
+  fail_unless (gst_pad_push_event (data2.srcpad, event));
   fail_unless_equals_int (test.flush_start_events, 1);
   fail_unless_equals_int (test.flush_stop_events, 0);
 
@@ -834,16 +863,19 @@ GST_START_TEST (test_flushing_seek)
   data2.expected_result = GST_FLOW_FLUSHING;
   thread2 = g_thread_try_new ("gst-check", push_data, &data2, NULL);
 
-  /* this should send not additional flush_start */
+  /* this should send no additional flush_start */
   GST_DEBUG_OBJECT (data1.sinkpad, "send flush_start");
-  fail_unless (gst_pad_push_event (data1.srcpad, gst_event_new_flush_start ()));
+  event = gst_event_new_flush_start ();
+  gst_event_set_seqnum (event, seqnum);
+  fail_unless (gst_pad_push_event (data1.srcpad, event));
   fail_unless_equals_int (test.flush_start_events, 1);
   fail_unless_equals_int (test.flush_stop_events, 0);
 
   /* the first FLUSH_STOP is not forwarded downstream */
   GST_DEBUG_OBJECT (data1.srcpad, "send flush_stop");
-  fail_unless (gst_pad_push_event (data1.srcpad,
-          gst_event_new_flush_stop (TRUE)));
+  event = gst_event_new_flush_stop (TRUE);
+  gst_event_set_seqnum (event, seqnum);
+  fail_unless (gst_pad_push_event (data1.srcpad, event));
   fail_unless_equals_int (test.flush_start_events, 1);
   fail_unless_equals_int (test.flush_stop_events, 0);
 
@@ -858,7 +890,9 @@ GST_START_TEST (test_flushing_seek)
   /* flush agg:sink_1 as well. This completes the flushing seek so a FLUSH_STOP is
    * sent downstream */
   GST_DEBUG_OBJECT (data2.srcpad, "send flush_stop");
-  gst_pad_push_event (data2.srcpad, gst_event_new_flush_stop (TRUE));
+  event = gst_event_new_flush_stop (TRUE);
+  gst_event_set_seqnum (event, seqnum);
+  gst_pad_push_event (data2.srcpad, event);
 
   /* and the last FLUSH_STOP is forwarded downstream */
   fail_unless_equals_int (test.flush_stop_events, 1);
@@ -1249,6 +1283,66 @@ GST_START_TEST (test_change_state_intensive)
 
 GST_END_TEST;
 
+GST_START_TEST (test_flush_on_aggregate)
+{
+  GThread *thread1, *thread2;
+  ChainData data1 = { 0, };
+  ChainData data2 = { 0, };
+  TestData test = { 0, };
+
+  _test_data_init (&test, FALSE);
+  ((GstTestAggregator *) test.aggregator)->do_flush_on_aggregate = TRUE;
+  _chain_data_init (&data1, test.aggregator, gst_buffer_new (), NULL);
+  _chain_data_init (&data2, test.aggregator, gst_buffer_new (), NULL);
+
+  thread1 = g_thread_try_new ("gst-check", push_data, &data1, NULL);
+  thread2 = g_thread_try_new ("gst-check", push_data, &data2, NULL);
+
+  g_main_loop_run (test.ml);
+  g_source_remove (test.timeout_id);
+
+  /* these will return immediately as when the data is popped the threads are
+   * unlocked and will terminate */
+  g_thread_join (thread1);
+  g_thread_join (thread2);
+
+  _chain_data_clear (&data1);
+  _chain_data_clear (&data2);
+  _test_data_clear (&test);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_remove_pad_on_aggregate)
+{
+  GThread *thread1, *thread2;
+  ChainData data1 = { 0, };
+  ChainData data2 = { 0, };
+  TestData test = { 0, };
+
+  _test_data_init (&test, FALSE);
+  ((GstTestAggregator *) test.aggregator)->do_remove_pad_on_aggregate = TRUE;
+  _chain_data_init (&data1, test.aggregator, gst_buffer_new (), NULL);
+  _chain_data_init (&data2, test.aggregator, gst_buffer_new (), NULL);
+
+  thread1 = g_thread_try_new ("gst-check", push_data, &data1, NULL);
+  thread2 = g_thread_try_new ("gst-check", push_data, &data2, NULL);
+
+  g_main_loop_run (test.ml);
+  g_source_remove (test.timeout_id);
+
+  /* these will return immediately as when the data is popped the threads are
+   * unlocked and will terminate */
+  g_thread_join (thread1);
+  g_thread_join (thread2);
+
+  _chain_data_clear (&data1);
+  _chain_data_clear (&data2);
+  _test_data_clear (&test);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_aggregator_suite (void)
 {
@@ -1276,6 +1370,8 @@ gst_aggregator_suite (void)
   tcase_add_test (general, test_timeout_pipeline_with_wait);
   tcase_add_test (general, test_add_remove);
   tcase_add_test (general, test_change_state_intensive);
+  tcase_add_test (general, test_flush_on_aggregate);
+  tcase_add_test (general, test_remove_pad_on_aggregate);
 
   return suite;
 }
index e03fc2a..a53fdfe 100644 (file)
@@ -24,6 +24,7 @@
 #endif
 #include <gst/gst.h>
 #include <gst/check/gstcheck.h>
+#include <gst/check/gstharness.h>
 #include <gst/base/gstbaseparse.h>
 
 static GstPad *mysrcpad, *mysinkpad;
@@ -56,6 +57,9 @@ struct _GstParserTester
 
   guint min_frame_size;
   guint last_frame_size;
+
+  /* don't immediately set the src caps when receiving sink caps */
+  gboolean delay_srccaps;
 };
 
 struct _GstParserTesterClass
@@ -80,7 +84,11 @@ gst_parser_tester_stop (GstBaseParse * parse)
 static gboolean
 gst_parser_tester_set_sink_caps (GstBaseParse * parse, GstCaps * caps)
 {
-  gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
+  GstParserTester *test = (GstParserTester *) parse;
+
+  if (!test->delay_srccaps)
+    gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
+
   return TRUE;
 }
 
@@ -672,6 +680,48 @@ GST_START_TEST (parser_pull_frame_growth)
 
 GST_END_TEST;
 
+GST_START_TEST (parser_initial_gap_prefer_upstream_caps)
+{
+  GstHarness *h;
+  GstCaps *upstream_caps, *downstream_caps, *caps;
+  GstEvent *e;
+
+  parsetest = g_object_new (GST_PARSER_TESTER_TYPE, NULL);
+  /* we need this so that baseparse tries to negotiate default caps */
+  ((GstParserTester *) parsetest)->delay_srccaps = TRUE;
+
+  h = gst_harness_new_with_element (parsetest, "sink", "src");
+  downstream_caps =
+      gst_caps_new_simple ("video/x-test-custom", "width", GST_TYPE_INT_RANGE,
+      TEST_VIDEO_WIDTH - 2, TEST_VIDEO_WIDTH + 2, "height", G_TYPE_INT,
+      TEST_VIDEO_HEIGHT, "framerate", GST_TYPE_FRACTION, TEST_VIDEO_FPS_N,
+      TEST_VIDEO_FPS_D, NULL);
+  upstream_caps =
+      gst_caps_new_simple ("video/x-test-custom", "width", G_TYPE_INT,
+      TEST_VIDEO_WIDTH * 2, "height", G_TYPE_INT, TEST_VIDEO_HEIGHT * 2,
+      "framerate", GST_TYPE_FRACTION, TEST_VIDEO_FPS_N, TEST_VIDEO_FPS_D, NULL);
+  gst_harness_set_caps (h, upstream_caps, downstream_caps);
+
+  fail_unless (gst_harness_push_event (h, gst_event_new_gap (0,
+              GST_CLOCK_TIME_NONE)));
+
+  fail_unless (e = gst_harness_pull_event (h));
+  fail_unless_equals_int (GST_EVENT_STREAM_START, GST_EVENT_TYPE (e));
+  gst_event_unref (e);
+
+  fail_unless (e = gst_harness_pull_event (h));
+  fail_unless_equals_int (GST_EVENT_CAPS, GST_EVENT_TYPE (e));
+  gst_event_parse_caps (e, &caps);
+  gst_event_unref (e);
+
+  fail_unless (gst_caps_can_intersect (caps, downstream_caps));
+
+  gst_harness_teardown (h);
+  gst_object_unref (parsetest);
+}
+
+GST_END_TEST;
+
 
 static void
 baseparse_setup (void)
@@ -704,6 +754,7 @@ gst_baseparse_suite (void)
   tcase_add_test (tc, parser_reverse_playback);
   tcase_add_test (tc, parser_pull_short_read);
   tcase_add_test (tc, parser_pull_frame_growth);
+  tcase_add_test (tc, parser_initial_gap_prefer_upstream_caps);
 
   return s;
 }
index f964cba..253d69a 100644 (file)
@@ -909,6 +909,8 @@ typedef struct
   GstBaseSrc parent;
   GstSegment *segment;
   gboolean n_output_buffers;
+  gsize num_times_negotiate_called;
+  gboolean do_renegotiate;
 } TimeSrc;
 
 typedef GstBaseSrcClass TimeSrcClass;
@@ -923,6 +925,8 @@ time_src_init (TimeSrc * src)
   gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
   gst_base_src_set_automatic_eos (GST_BASE_SRC (src), FALSE);
   src->n_output_buffers = 0;
+  src->num_times_negotiate_called = 0;
+  src->do_renegotiate = FALSE;
 }
 
 /* This test src outputs a compressed format, with a single GOP
@@ -941,6 +945,11 @@ time_src_create (GstBaseSrc * bsrc, guint64 offset, guint size,
   if (src->segment->position >= src->segment->stop)
     return GST_FLOW_EOS;
 
+  if (src->do_renegotiate) {
+    gst_base_src_negotiate (bsrc);
+    src->do_renegotiate = FALSE;
+  }
+
   *p_buf = gst_buffer_new ();
   GST_BUFFER_PTS (*p_buf) = src->segment->position;
   GST_BUFFER_DURATION (*p_buf) = GST_SECOND;
@@ -973,6 +982,14 @@ time_src_is_seekable (GstBaseSrc * bsrc)
   return TRUE;
 }
 
+static gboolean
+time_src_negotiate (GstBaseSrc * bsrc)
+{
+  TimeSrc *src = (TimeSrc *) bsrc;
+  src->num_times_negotiate_called++;
+  return GST_BASE_SRC_CLASS (time_src_parent_class)->negotiate (bsrc);
+}
+
 static void
 time_src_class_init (TimeSrcClass * klass)
 {
@@ -984,6 +1001,7 @@ time_src_class_init (TimeSrcClass * klass)
   gstbasesrc_class->create = time_src_create;
   gstbasesrc_class->do_seek = time_src_do_seek;
   gstbasesrc_class->is_seekable = time_src_is_seekable;
+  gstbasesrc_class->negotiate = time_src_negotiate;
 }
 
 GST_START_TEST (basesrc_time_automatic_eos)
@@ -1033,6 +1051,63 @@ GST_START_TEST (basesrc_time_automatic_eos)
 
 GST_END_TEST;
 
+GST_START_TEST (basesrc_negotiate)
+{
+  GstElement *src, *sink;
+  GstElement *pipe;
+  GstSegment seg;
+
+  src = g_object_new (time_src_get_type (), NULL);
+  sink = gst_element_factory_make ("fakesink", NULL);
+
+  pipe = gst_pipeline_new (NULL);
+
+  gst_bin_add (GST_BIN (pipe), src);
+  gst_bin_add (GST_BIN (pipe), sink);
+
+  gst_element_link (src, sink);
+
+  /* Use some default segment to get the stream going. */
+  gst_segment_init (&seg, GST_FORMAT_TIME);
+  ((TimeSrc *) src)->segment = gst_segment_copy (&seg);
+
+  /* Check that gst_base_src_negotiate () actually ends up calling
+   * the negotiate () vmethod by first running the test pipeline
+   * normally, and then running it with a gst_base_src_negotiate ()
+   * call, and checking how many times negotiate () was called in
+   * both cases. */
+
+  /* Run pipeline, keep do_renegotiate at FALSE, so
+   * gst_base_src_negotiate () won't be called. negotiate () still
+   * will be called once, as part of the regular caps negotiation
+   * sequence. */
+  fail_unless (((TimeSrc *) src)->num_times_negotiate_called == 0);
+  gst_element_set_state (pipe, GST_STATE_PLAYING);
+  gst_element_get_state (pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
+  fail_unless (((TimeSrc *) src)->num_times_negotiate_called == 1);
+  gst_element_set_state (pipe, GST_STATE_NULL);
+
+  ((TimeSrc *) src)->num_times_negotiate_called = 0;
+
+  /* Run pipeline, set do_renegotiate to TRUE. This will cause
+   * negotiate () to be called twice: Once during caps negotiation,
+   * and once by the gst_base_src_negotiate () call in the
+   * time_src_create () function. */
+  ((TimeSrc *) src)->do_renegotiate = TRUE;
+  fail_unless (((TimeSrc *) src)->num_times_negotiate_called == 0);
+  gst_element_set_state (pipe, GST_STATE_PLAYING);
+  gst_element_get_state (pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
+  fail_unless (((TimeSrc *) src)->num_times_negotiate_called == 2);
+  gst_element_set_state (pipe, GST_STATE_NULL);
+
+  if (((TimeSrc *) src)->segment)
+    gst_segment_free (((TimeSrc *) src)->segment);
+
+  gst_object_unref (pipe);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_basesrc_suite (void)
 {
@@ -1050,6 +1125,7 @@ gst_basesrc_suite (void)
   tcase_add_test (tc, basesrc_seek_on_last_buffer);
   tcase_add_test (tc, basesrc_create_bufferlist);
   tcase_add_test (tc, basesrc_time_automatic_eos);
+  tcase_add_test (tc, basesrc_negotiate);
 
   return s;
 }
index f3fc373..19fb2d7 100644 (file)
@@ -29,9 +29,7 @@
 #include <gst/check/gstcheck.h>
 #include <gst/base/gstbitwriter.h>
 #include <gst/base/gstbitreader.h>
-#ifdef TIZEN_FEATURE_UPSTREAM
 #include "gst/glib-compat-private.h"
-#endif /* TIZEN_FEATURE_UPSTREAM */
 
 GST_START_TEST (test_initialization)
 {
@@ -79,11 +77,7 @@ GST_START_TEST (test_data)
   fail_unless (gst_bit_writer_put_bits_uint64 (&writer, 0x45, 48));
   fail_unless_equals_int (gst_bit_writer_get_remaining (&writer), 2048 - 71);
   fail_unless (gst_bit_writer_align_bytes (&writer, 0));
-#ifdef TIZEN_FEATURE_UPSTREAM
   data = g_memdup2 (sdata, sizeof (sdata));
-#else /* TIZEN_FEATURE_UPSTREAM */
-  data = g_memdup (sdata, sizeof (sdata));
-#endif /* TIZEN_FEATURE_UPSTREAM */
   fail_unless (gst_bit_writer_put_bytes (&writer, data, sizeof (sdata)));
 
   gst_bit_reader_init (&reader, gst_bit_writer_get_data (&writer), 256);
@@ -155,6 +149,66 @@ GST_START_TEST (test_reset)
 
 GST_END_TEST;
 
+GST_START_TEST (test_reset_data_unaligned)
+{
+  GstBitWriter writer;
+  static guint8 sdata[] = { 0xff, 0xf1, 0xf2, 0x80 };
+  guint8 *data, i;
+  GstBuffer *buf;
+  GstMapInfo info;
+
+  gst_bit_writer_init_with_size (&writer, 32, TRUE);
+  fail_unless_equals_int (gst_bit_writer_get_remaining (&writer), 2048);
+
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0xf, 4));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0x7, 3));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0x3, 2));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0x3, 2));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0x8, 4));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0x1, 1));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0xf2, 8));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0x2, 2));
+
+  fail_unless_equals_int (gst_bit_writer_get_remaining (&writer), 2048 - 26);
+
+  data = gst_bit_writer_reset_and_get_data (&writer);
+  fail_unless (data != NULL);
+
+  for (i = 0; i < 4; i++)
+    fail_unless (memcmp (&sdata[i], &data[i], 1) == 0);
+
+  gst_bit_writer_init (&writer);
+
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0x7, 3));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0xf, 4));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0x1, 1));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0x1, 1));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0x3, 2));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0x8, 4));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0x1, 1));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0xf2, 8));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0x1, 1));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0x0, 1));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0x0, 1));
+  fail_unless (gst_bit_writer_put_bits_uint8 (&writer, 0x0, 3));
+
+  fail_unless_equals_int (gst_bit_writer_get_size (&writer), 30);
+
+  buf = gst_bit_writer_reset_and_get_buffer (&writer);
+  fail_unless (buf != NULL);
+  fail_unless (gst_buffer_map (buf, &info, GST_MAP_READWRITE));
+  fail_unless (info.data);
+  fail_unless_equals_int (info.size, 4);
+
+  for (i = 0; i < 4; i++)
+    fail_unless (memcmp (&sdata[i], &info.data[i], 1) == 0);
+
+  g_free (data);
+  gst_buffer_unmap (buf, &info);
+  gst_buffer_unref (buf);
+}
+
+GST_END_TEST;
 
 static Suite *
 gst_bit_writer_suite (void)
@@ -167,6 +221,7 @@ gst_bit_writer_suite (void)
   tcase_add_test (tc_chain, test_initialization);
   tcase_add_test (tc_chain, test_data);
   tcase_add_test (tc_chain, test_reset);
+  tcase_add_test (tc_chain, test_reset_data_unaligned);
 
   return s;
 }
index e021bf5..bc4c406 100644 (file)
@@ -27,9 +27,7 @@
 #include <gst/gst.h>
 #include <gst/check/gstcheck.h>
 #include <gst/base/gstbytereader.h>
-#ifdef TIZEN_FEATURE_UPSTREAM
 #include "gst/glib-compat-private.h"
-#endif /* TIZEN_FEATURE_UPSTREAM */
 
 #ifndef fail_unless_equals_int64
 #define fail_unless_equals_int64(a, b)                                 \
@@ -577,11 +575,7 @@ GST_START_TEST (test_scan)
     gint found;
 
     /* dup so valgrind can detect out of bounds access more easily */
-#ifdef TIZEN_FEATURE_UPSTREAM
     m = g_memdup2 (sync_data, sizeof (sync_data));
-#else /* TIZEN_FEATURE_UPSTREAM */
-    m = g_memdup (sync_data, sizeof (sync_data));
-#endif /* TIZEN_FEATURE_UPSTREAM */
     gst_byte_reader_init (&reader, m, sizeof (sync_data));
 
     found = gst_byte_reader_masked_scan_uint32_peek (&reader, 0xffffff00,
index c746159..c8017b8 100644 (file)
@@ -27,9 +27,7 @@
 #include <gst/gst.h>
 #include <gst/check/gstcheck.h>
 #include <gst/base/gstbytewriter.h>
-#ifdef TIZEN_FEATURE_UPSTREAM
 #include "gst/glib-compat-private.h"
-#endif /* TIZEN_FEATURE_UPSTREAM */
 
 GST_START_TEST (test_initialization)
 {
@@ -45,11 +43,7 @@ GST_START_TEST (test_initialization)
           (&writer)), 0);
   gst_byte_writer_reset (&writer);
 
-#ifdef TIZEN_FEATURE_UPSTREAM
   data = g_memdup2 (sdata, sizeof (sdata));
-#else /* TIZEN_FEATURE_UPSTREAM */
-  data = g_memdup (sdata, sizeof (sdata));
-#endif /* TIZEN_FEATURE_UPSTREAM */
   gst_byte_writer_init_with_data (&writer, data, sizeof (sdata), FALSE);
   fail_unless_equals_int (gst_byte_writer_get_pos (&writer), 0);
   fail_unless_equals_int (gst_byte_writer_get_size (&writer), 0);
@@ -63,11 +57,7 @@ GST_START_TEST (test_initialization)
   g_free (data);
   data = tmp = NULL;
 
-#ifdef TIZEN_FEATURE_UPSTREAM
   data = g_memdup2 (sdata, sizeof (sdata));
-#else /* TIZEN_FEATURE_UPSTREAM */
-  data = g_memdup (sdata, sizeof (sdata));
-#endif /* TIZEN_FEATURE_UPSTREAM */
   gst_byte_writer_init_with_data (&writer, data, sizeof (sdata), TRUE);
   fail_unless_equals_int (gst_byte_writer_get_pos (&writer), 0);
   fail_unless_equals_int (gst_byte_writer_get_size (&writer), sizeof (sdata));
index 53a9d4c..083c7f4 100644 (file)
@@ -836,7 +836,7 @@ setup_src_pad (GstElement * element,
   GstPad *srcpad, *sinkpad;
 
   srcpad = gst_pad_new_from_static_template (tmpl, "src");
-  sinkpad = gst_element_get_request_pad (element, name);
+  sinkpad = gst_element_request_pad_simple (element, name);
   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK,
       "Could not link source and %s sink pads", GST_ELEMENT_NAME (element));
   gst_pad_set_event_function (srcpad, src_event);
@@ -973,7 +973,7 @@ GST_START_TEST (test_flushing_seek)
   fail_unless_equals_int (flush_start_events, 0);
   fail_unless_equals_int (flush_stop_events, 0);
 
-  /* flush ogg:sink_0. This flushs collectpads, calls ::flush() and sends
+  /* flush ogg:sink_0. This flushes collectpads, calls ::flush() and sends
    * FLUSH_START downstream */
   fail_unless (gst_pad_push_event (srcpad1, gst_event_new_flush_start ()));
   fail_unless_equals_int (flush_start_events, 1);
index 9fdb760..4ada88e 100644 (file)
@@ -240,7 +240,7 @@ gst_test_obj_base_init (GstTestObjClass * klass)
 static GType
 gst_test_obj_get_type (void)
 {
-  static volatile gsize test_obj_type = 0;
+  static gsize test_obj_type = 0;
 
   if (g_once_init_enter (&test_obj_type)) {
     GType type;
@@ -1527,6 +1527,39 @@ GST_START_TEST (controller_trigger_tolerance)
 
 GST_END_TEST;
 
+GST_START_TEST (controller_first_value_in_range)
+{
+  GstControlSource *cs;
+  GstTimedValueControlSource *tvcs;
+  GstElement *elem;
+
+  elem = gst_element_factory_make ("testobj", NULL);
+
+  /* set object values */
+  GST_TEST_OBJ (elem)->val_int = 32;
+
+  cs = gst_interpolation_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) cs;
+  g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_direct_control_binding_new_absolute (GST_OBJECT (elem), "int",
+              cs)));
+
+  /* Add 1 value of 0 (which is the default) */
+  fail_unless (gst_timed_value_control_source_set (tvcs, GST_SECOND, 0));
+  /* First sync outside interpolation range */
+  gst_object_sync_values (GST_OBJECT (elem), 0);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 32);
+
+  gst_object_sync_values (GST_OBJECT (elem), GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+
+  gst_object_unref (cs);
+  gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
 GST_START_TEST (controller_proxy)
 {
   GstControlBinding *cb, *cb2;
@@ -1665,6 +1698,7 @@ gst_controller_suite (void)
   tcase_add_test (tc, controller_lfo_rsaw);
   tcase_add_test (tc, controller_lfo_triangle);
   tcase_add_test (tc, controller_trigger_exact);
+  tcase_add_test (tc, controller_first_value_in_range);
   tcase_add_test (tc, controller_trigger_tolerance);
   tcase_add_test (tc, controller_proxy);
 
index 6c634c1..dee5efe 100644 (file)
@@ -232,6 +232,20 @@ GST_START_TEST (test_clear)
 
 GST_END_TEST;
 
+GST_START_TEST (test_no_pads_passthrough)
+{
+  GstFlowCombiner *combiner = gst_flow_combiner_new ();
+
+  fail_unless_equals_int (GST_FLOW_FLUSHING,
+      gst_flow_combiner_update_flow (combiner, GST_FLOW_FLUSHING));
+  fail_unless_equals_int (GST_FLOW_OK,
+      gst_flow_combiner_update_flow (combiner, GST_FLOW_OK));
+
+  gst_flow_combiner_free (combiner);
+}
+
+GST_END_TEST;
+
 static Suite *
 flow_combiner_suite (void)
 {
@@ -241,6 +255,7 @@ flow_combiner_suite (void)
   suite_add_tcase (s, tc_chain);
   tcase_add_test (tc_chain, test_combined_flows);
   tcase_add_test (tc_chain, test_clear);
+  tcase_add_test (tc_chain, test_no_pads_passthrough);
 
   return s;
 }
index 633d538..7999b4b 100644 (file)
 #include <gst/check/gstcheck.h>
 #include <gst/check/gstharness.h>
 
+GST_START_TEST (test_harness_empty)
+{
+  GstHarness *h = gst_harness_new_empty ();
+  gst_harness_teardown (h);
+}
+
+GST_END_TEST;
+
 static void
 create_destroy_element_harness (gpointer data, gpointer user_data)
 {
@@ -170,6 +178,45 @@ GST_START_TEST (test_forward_event_and_query_to_sink_harness_while_teardown)
 
 GST_END_TEST;
 
+static void
+push_sticky_events (gpointer data, G_GNUC_UNUSED gpointer user_data)
+{
+  GstHarness *h;
+  GstCaps *caps;
+  GstSegment segment;
+
+  h = (GstHarness *) user_data;
+
+  gst_harness_push_event (h, gst_event_new_stream_start ("999"));
+
+  caps = gst_caps_new_empty_simple ("mycaps");
+  gst_harness_push_event (h, gst_event_new_caps (caps));
+  gst_caps_unref (caps);
+
+  gst_segment_init (&segment, GST_FORMAT_TIME);
+  gst_harness_push_event (h, gst_event_new_segment (&segment));
+}
+
+GST_START_TEST (test_forward_sticky_events_to_sink_harness_while_teardown)
+{
+  GstHarness *h = gst_harness_new ("identity");
+  GstHarnessThread *e_thread = gst_harness_stress_custom_start (h, NULL,
+      push_sticky_events, h, 0);
+  gdouble duration = 1.0;
+  GTimer *timer = g_timer_new ();
+
+  while (g_timer_elapsed (timer, NULL) < duration) {
+    gst_harness_add_sink (h, "fakesink");
+    g_thread_yield ();
+  }
+
+  g_timer_destroy (timer);
+  gst_harness_stress_thread_stop (e_thread);
+  gst_harness_teardown (h);
+}
+
+GST_END_TEST;
+
 static GstHarness *
 harness_new_and_fill_with_data (void)
 {
@@ -254,6 +301,7 @@ gst_harness_suite (void)
 
   suite_add_tcase (s, tc_chain);
 
+  tcase_add_test (tc_chain, test_harness_empty);
   tcase_add_test (tc_chain, test_harness_element_ref);
   tcase_add_test (tc_chain, test_src_harness);
   tcase_add_test (tc_chain, test_src_harness_no_forwarding);
@@ -261,6 +309,9 @@ gst_harness_suite (void)
 
   tcase_add_test (tc_chain,
       test_forward_event_and_query_to_sink_harness_while_teardown);
+  tcase_add_test (tc_chain,
+      test_forward_sticky_events_to_sink_harness_while_teardown);
+
   tcase_add_test (tc_chain, test_get_all_data);
 
   return s;
index e3b86fd..386a191 100644 (file)
@@ -454,7 +454,8 @@ GST_START_TEST (test_single_shot_sync_past)
   clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND - 1);
   wait_ctx =
       gst_test_util_wait_for_clock_id_begin (test_clock, clock_id, &jitter);
-  g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx) == GST_CLOCK_EARLY);
+  fail_unless_equals_int (gst_test_util_wait_for_clock_id_end (wait_ctx),
+      GST_CLOCK_EARLY);
   g_assert_cmpint (jitter, ==, 1);
   gst_clock_id_unref (clock_id);
 
@@ -477,7 +478,8 @@ GST_START_TEST (test_single_shot_sync_present)
   clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND);
   wait_ctx =
       gst_test_util_wait_for_clock_id_begin (test_clock, clock_id, &jitter);
-  g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx) == GST_CLOCK_OK);
+  fail_unless_equals_int (gst_test_util_wait_for_clock_id_end (wait_ctx),
+      GST_CLOCK_OK);
   g_assert_cmpint (jitter, ==, 0);
   gst_clock_id_unref (clock_id);
 
@@ -501,7 +503,8 @@ GST_START_TEST (test_single_shot_sync_future)
   wait_ctx =
       gst_test_util_wait_for_clock_id_begin (test_clock, clock_id, &jitter);
   gst_test_clock_advance_time (test_clock, GST_SECOND);
-  g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx) == GST_CLOCK_OK);
+  fail_unless_equals_int (gst_test_util_wait_for_clock_id_end (wait_ctx),
+      GST_CLOCK_OK);
   g_assert_cmpint (jitter, ==, -GST_SECOND);
   gst_clock_id_unref (clock_id);
 
@@ -532,8 +535,8 @@ GST_START_TEST (test_single_shot_sync_unschedule)
   clock_id = gst_clock_new_single_shot_id (clock, 2 * GST_SECOND);
   wait_ctx = gst_test_util_wait_for_clock_id_begin (test_clock, clock_id, NULL);
   gst_clock_id_unschedule (clock_id);
-  g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx)
-      == GST_CLOCK_UNSCHEDULED);
+  fail_unless_equals_int (gst_test_util_wait_for_clock_id_end (wait_ctx),
+      GST_CLOCK_UNSCHEDULED);
   gst_clock_id_unref (clock_id);
 
   gst_object_unref (clock);
@@ -563,8 +566,10 @@ GST_START_TEST (test_single_shot_sync_ordering)
 
   gst_test_clock_advance_time (test_clock, GST_SECOND);
 
-  g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx_b) == GST_CLOCK_OK);
-  g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx_a) == GST_CLOCK_OK);
+  fail_unless_equals_int (gst_test_util_wait_for_clock_id_end (wait_ctx_b),
+      GST_CLOCK_OK);
+  fail_unless_equals_int (gst_test_util_wait_for_clock_id_end (wait_ctx_a),
+      GST_CLOCK_OK);
 
   gst_clock_id_unref (clock_id_b);
   gst_clock_id_unref (clock_id_a);
@@ -594,12 +599,14 @@ GST_START_TEST (test_single_shot_sync_ordering_parallel)
   g_assert_cmpuint (gst_test_clock_get_next_entry_time (test_clock), ==,
       2 * GST_SECOND);
   gst_test_clock_advance_time (test_clock, GST_SECOND);
-  g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx_b) == GST_CLOCK_OK);
+  fail_unless_equals_int (gst_test_util_wait_for_clock_id_end (wait_ctx_b),
+      GST_CLOCK_OK);
 
   g_assert_cmpuint (gst_test_clock_get_next_entry_time (test_clock), ==,
       3 * GST_SECOND);
   gst_test_clock_advance_time (test_clock, GST_SECOND);
-  g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx_a) == GST_CLOCK_OK);
+  fail_unless_equals_int (gst_test_util_wait_for_clock_id_end (wait_ctx_a),
+      GST_CLOCK_OK);
 
   gst_clock_id_unref (clock_id_b);
   gst_clock_id_unref (clock_id_a);
@@ -907,7 +914,8 @@ GST_START_TEST (test_periodic_sync)
     else
       gst_test_clock_advance_time (test_clock, interval);
 
-    gst_test_util_wait_for_clock_id_end (wait_ctx);
+    fail_unless_equals_int (gst_test_util_wait_for_clock_id_end (wait_ctx),
+        GST_CLOCK_OK);
   }
 
   gst_clock_id_unref (clock_id);
@@ -996,7 +1004,8 @@ GST_START_TEST (test_periodic_uniqueness)
     }
 
     gst_test_clock_advance_time (test_clock, interval);
-    gst_test_util_wait_for_clock_id_end (wait_ctx);
+    fail_unless_equals_int (gst_test_util_wait_for_clock_id_end (wait_ctx),
+        GST_CLOCK_OK);
   }
 
   gst_clock_id_unref (clock_id);
@@ -1043,6 +1052,45 @@ GST_START_TEST (test_crank)
 
 GST_END_TEST;
 
+GST_START_TEST (test_late_crank)
+{
+  GstClock *clock;
+  GstTestClock *test_clock;
+  GstClockID clock_id;
+  SyncClockWaitContext context;
+  GThread *worker_thread;
+
+  clock = gst_test_clock_new_with_start_time (GST_SECOND);
+  test_clock = GST_TEST_CLOCK (clock);
+
+  /* register a wait for 5 seconds */
+  clock_id = gst_clock_new_single_shot_id (clock, 5 * GST_SECOND);
+  context.clock_id = gst_clock_id_ref (clock_id);
+  context.jitter = 0;
+
+  /* crank the clock while the pending clock id is in the past */
+  gst_test_clock_set_time (test_clock, 6 * GST_SECOND);
+  worker_thread =
+      g_thread_new ("worker_thread_a",
+      test_wait_pending_single_shot_id_sync_worker, &context);
+  gst_test_clock_crank (test_clock);
+
+  /* the clock should have advanced and the wait released */
+  g_thread_join (worker_thread);
+
+  /* the pending entry was schedule 1 second before waiting */
+  fail_unless_equals_int64 (1 * GST_SECOND, context.jitter);
+
+  /* and the clock is still 5 seconds as configured */
+  fail_unless_equals_int64 (6 * GST_SECOND, gst_clock_get_time (clock));
+
+  gst_clock_id_unref (context.clock_id);
+  gst_clock_id_unref (clock_id);
+  gst_object_unref (clock);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_test_clock_suite (void)
 {
@@ -1075,6 +1123,7 @@ gst_test_clock_suite (void)
   tcase_add_test (tc_chain, test_periodic_async);
   tcase_add_test (tc_chain, test_periodic_uniqueness);
   tcase_add_test (tc_chain, test_crank);
+  tcase_add_test (tc_chain, test_late_crank);
 
   return s;
 }
index 273104d..534599b 100644 (file)
@@ -72,6 +72,8 @@ static GstFlowReturn (*klass_transform_ip) (GstBaseTransform * trans,
     GstBuffer * buf) = NULL;
 static gboolean (*klass_set_caps) (GstBaseTransform * trans, GstCaps * incaps,
     GstCaps * outcaps) = NULL;
+static GstCaps *(*klass_fixate_caps) (GstBaseTransform * trans,
+    GstPadDirection direction, GstCaps * caps, GstCaps * othercaps) = NULL;
 static GstCaps *(*klass_transform_caps) (GstBaseTransform * trans,
     GstPadDirection direction, GstCaps * caps, GstCaps * filter) = NULL;
 static gboolean (*klass_transform_size) (GstBaseTransform * trans,
@@ -114,6 +116,8 @@ gst_test_trans_class_init (GstTestTransClass * klass)
     trans_class->transform_size = klass_transform_size;
   if (klass_set_caps != NULL)
     trans_class->set_caps = klass_set_caps;
+  if (klass_fixate_caps != NULL)
+    trans_class->fixate_caps = klass_fixate_caps;
   if (klass_submit_input_buffer != NULL)
     trans_class->submit_input_buffer = klass_submit_input_buffer;
   if (klass_generate_output)
index 45e6477..2b9cb1e 100644 (file)
@@ -887,6 +887,60 @@ GST_START_TEST (basetransform_chain_ct3)
 
 GST_END_TEST;
 
+static gboolean transform_fixate_caps_invalid_called = FALSE;
+
+static GstCaps *
+transform_fixate_caps_invalid (G_GNUC_UNUSED GstBaseTransform * trans,
+    G_GNUC_UNUSED GstPadDirection direction, G_GNUC_UNUSED GstCaps * caps,
+    GstCaps * othercaps)
+{
+  transform_fixate_caps_invalid_called = TRUE;
+  gst_caps_unref (othercaps);
+  return NULL;
+}
+
+GST_START_TEST (basetransform_invalid_fixatecaps_impl)
+{
+  TestTransData *trans;
+  GstBuffer *buffer;
+  GstFlowReturn res;
+  GstCaps *caps;
+
+  klass_fixate_caps = transform_fixate_caps_invalid;
+
+  trans = gst_test_trans_new ();
+
+  gst_test_trans_push_segment (trans);
+
+  /* passthrough without caps */
+  buffer = gst_buffer_new_and_alloc (20);
+  res = gst_test_trans_push (trans, buffer);
+  fail_unless (res == GST_FLOW_OK);
+
+  buffer = gst_test_trans_pop (trans);
+  fail_unless (buffer != NULL);
+  fail_unless (gst_buffer_get_size (buffer) == 20);
+
+  /* try to set caps prior to push data
+   * all following attempts to fixate_caps would fail producing a g_critical */
+  gst_pad_push_event (trans->srcpad, gst_event_new_flush_start ());
+  gst_pad_push_event (trans->srcpad, gst_event_new_flush_stop (TRUE));
+
+  caps = gst_caps_from_string ("foo/x-bar");
+  ASSERT_CRITICAL (gst_test_trans_setcaps (trans, caps));
+  gst_caps_unref (caps);
+
+  ASSERT_CRITICAL (gst_test_trans_push_segment (trans));
+
+  ASSERT_CRITICAL (res = gst_test_trans_push (trans, buffer));
+  fail_unless (transform_fixate_caps_invalid_called == TRUE);
+  fail_unless (res == GST_FLOW_NOT_NEGOTIATED);
+
+  gst_test_trans_free (trans);
+}
+
+GST_END_TEST;
+
 static void
 transform1_setup (void)
 {
@@ -903,6 +957,7 @@ transform1_teardown (void)
   klass_transform_caps = NULL;
   klass_transform_size = NULL;
   klass_set_caps = NULL;
+  klass_fixate_caps = NULL;
   klass_submit_input_buffer = NULL;
   klass_generate_output = NULL;
 }
@@ -927,6 +982,8 @@ gst_basetransform_suite (void)
   tcase_add_test (tc, basetransform_chain_ct2);
   tcase_add_test (tc, basetransform_chain_ct3);
 
+  tcase_add_test (tc, basetransform_invalid_fixatecaps_impl);
+
   return s;
 }
 
index 94a56c5..a617cf1 100644 (file)
@@ -88,6 +88,7 @@ core_tests = [
   [ 'elements/filesrc.c', not gst_registry ],
   [ 'elements/funnel.c', not gst_registry ],
   [ 'elements/identity.c', not gst_registry or not gst_parse ],
+  [ 'elements/leaks.c', not tracer_hooks or not gst_debug ],
   [ 'elements/multiqueue.c', not gst_registry ],
   [ 'elements/selector.c', not gst_registry ],
   [ 'elements/streamiddemux.c', not gst_registry ],
@@ -112,7 +113,7 @@ core_tests = [
 ]
 
 # Make sure our headers are C++ clean
-if add_languages('cpp', required : false)
+if add_languages('cpp', native: false, required: false)
   core_tests += [
     [ 'gst/gstcpp.cc', not gst_registry ],
     [ 'libs/gstlibscpp.cc', false ],
@@ -124,7 +125,6 @@ test_defines = [
   '-UG_DISABLE_CAST_CHECKS',
   '-DGST_CHECK_TEST_ENVIRONMENT_BEACON="GST_STATE_IGNORE_ELEMENTS"',
   '-DTESTFILE="' + meson.current_source_dir() + '/meson.build"',
-  '-DGST_USE_UNSTABLE_API',
   '-DGST_DISABLE_DEPRECATED',
 ]
 
diff --git a/tests/check/pipelines/.gitignore b/tests/check/pipelines/.gitignore
deleted file mode 100644 (file)
index 6ce366e..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-.dirstamp
-cleanup
-seek
-simple-launch-lines
-stress
-parse-launch
-*.check.xml
-parse-disabled
-queue-error
index 5ccb50b..4bb5e43 100644 (file)
@@ -92,7 +92,7 @@ GST_START_TEST (test_pipeline_unref)
   run_pipeline (pipeline, s,
       GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
       GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE |
-      GST_MESSAGE_STREAM_START, GST_MESSAGE_EOS);
+      GST_MESSAGE_STREAM_START | GST_MESSAGE_LATENCY, GST_MESSAGE_EOS);
   while (GST_OBJECT_REFCOUNT_VALUE (src) > 1)
     THREAD_SWITCH ();
   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
index 6e91165..58c2e53 100644 (file)
@@ -129,8 +129,8 @@ GST_START_TEST (test_launch_lines)
   fail_unless (efac != NULL);
   type = gst_element_factory_get_element_type (efac);
   fail_unless (type != 0);
-  g_object_unref (efac);
-  g_object_unref (efac);
+  gst_object_unref (efac);
+  gst_object_unref (efac);
   fail_unless (gst_element_register (NULL, "1__dentity", GST_RANK_NONE, type));
 
   for (s = test_lines; *s != NULL; s++) {
@@ -321,9 +321,9 @@ static const gchar *expected_failures[] = {
   "fakesrc ! video/raw,format=(antwerp)monkeys ! fakesink silent=true",
   /* checks: Empty pipeline is invalid */
   "",
-  /* checks: Link without sink element failes */
+  /* checks: Link without sink element fails */
   "fakesrc ! ",
-  /* checks: Link without src element failes */
+  /* checks: Link without src element fails */
   " ! fakesink silent=true",
   /* checks: Source URI for which no element exists is a failure */
   "borky://fdaffd ! fakesink silent=true",
@@ -419,6 +419,7 @@ run_delayed_test (const gchar * pipe_str, const gchar * peer,
 {
   GstElement *pipe, *src, *sink;
   GstPad *srcpad, *sinkpad, *peerpad = NULL;
+  GstStateChangeReturn ret;
 
   pipe = setup_pipeline (pipe_str);
 
@@ -434,11 +435,22 @@ run_delayed_test (const gchar * pipe_str, const gchar * peer,
 
   /* Set the state to PAUSED and wait until the src at least reaches that
    * state */
-  fail_if (gst_element_set_state (pipe, GST_STATE_PAUSED) ==
-      GST_STATE_CHANGE_FAILURE);
+  ret = gst_element_set_state (pipe, GST_STATE_PAUSED);
+
+  if (expect_link) {
+    fail_if (ret == GST_STATE_CHANGE_FAILURE);
+  } else {
+    fail_unless (ret == GST_STATE_CHANGE_FAILURE
+        || ret == GST_STATE_CHANGE_ASYNC);
+  }
 
-  fail_if (gst_element_get_state (src, NULL, NULL, GST_CLOCK_TIME_NONE) ==
-      GST_STATE_CHANGE_FAILURE);
+  ret = gst_element_get_state (pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
+
+  if (expect_link) {
+    fail_if (ret == GST_STATE_CHANGE_FAILURE);
+  } else {
+    fail_unless (ret == GST_STATE_CHANGE_FAILURE);
+  }
 
   /* Now, the source element should have a src pad, and if "peer" was passed, 
    * then the src pad should have gotten linked to the 'sink' pad of that 
@@ -658,6 +670,24 @@ GST_START_TEST (test_missing_elements)
 
 GST_END_TEST;
 
+GST_START_TEST (test_preset)
+{
+  GstElement *element;
+  GError *err = NULL;
+
+  /* missing preset */
+  element =
+      gst_parse_launch
+      ("fakesrc ! identity @preset=\"Wrong preset\" ! fakesink", &err);
+  fail_unless (err != NULL, "expected error");
+  fail_unless_equals_int (err->code, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY);
+  fail_unless (element != NULL, "Doesn't NULL return without FATAL_ERRORS");
+  gst_clear_object (&element);
+  g_clear_error (&err);
+}
+
+GST_END_TEST;
+
 GST_START_TEST (test_flags)
 {
   GstElement *element;
@@ -722,6 +752,7 @@ parse_suite (void)
   tcase_add_test (tc_chain, test_flags);
   tcase_add_test (tc_chain, test_missing_elements);
   tcase_add_test (tc_chain, test_parsing);
+  tcase_add_test (tc_chain, test_preset);
   return s;
 }
 
index 28bb884..5f7447b 100644 (file)
@@ -521,7 +521,7 @@ GST_START_TEST (test_loopback_2)
 
   GST_INFO ("wait for segment done message");
 
-  msg = gst_bus_timed_pop_filtered (bus, (GstClockTime) 2 * GST_SECOND,
+  msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
       GST_MESSAGE_SEGMENT_DONE | GST_MESSAGE_ERROR);
   fail_unless (msg, "no message within the timed window");
   fail_unless_equals_string (GST_MESSAGE_TYPE_NAME (msg), "segment-done");
index 62385b2..cf03db3 100644 (file)
@@ -103,31 +103,31 @@ GST_START_TEST (test_2_elements)
   run_pipeline (setup_pipeline (s), s,
       GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
       GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE |
-      GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN);
+      GST_MESSAGE_STREAM_START | GST_MESSAGE_LATENCY, GST_MESSAGE_UNKNOWN);
 
   s = "fakesrc can-activate-push=true ! fakesink can-activate-pull=false";
   run_pipeline (setup_pipeline (s), s,
       GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
       GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE |
-      GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN);
+      GST_MESSAGE_STREAM_START | GST_MESSAGE_LATENCY, GST_MESSAGE_UNKNOWN);
 
   s = "fakesrc can-activate-push=false num-buffers=10 ! fakesink can-activate-pull=true";
   run_pipeline (setup_pipeline (s), s,
       GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
       GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE |
-      GST_MESSAGE_STREAM_START, GST_MESSAGE_EOS);
+      GST_MESSAGE_STREAM_START | GST_MESSAGE_LATENCY, GST_MESSAGE_EOS);
 
   s = "fakesrc can-activate-push=true num-buffers=10 ! fakesink can-activate-pull=false";
   run_pipeline (setup_pipeline (s), s,
       GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
       GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE |
-      GST_MESSAGE_STREAM_START, GST_MESSAGE_EOS);
+      GST_MESSAGE_STREAM_START | GST_MESSAGE_LATENCY, GST_MESSAGE_EOS);
 
   s = "fakesrc can-activate-push=false ! fakesink can-activate-pull=false";
   ASSERT_CRITICAL (run_pipeline (setup_pipeline (s), s,
           GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED |
           GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE |
-          GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN));
+          GST_MESSAGE_STREAM_START | GST_MESSAGE_LATENCY, GST_MESSAGE_UNKNOWN));
 }
 
 GST_END_TEST;
diff --git a/tests/examples/Makefile.am b/tests/examples/Makefile.am
deleted file mode 100644 (file)
index ea563c8..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-# adapter test needs sys/times.h and unistd.h
-if HAVE_SYS_TIMES_H_AND_UNISTD_H
-  ADAPTER_TEST_DIR = adapter
-else
-  ADAPTER_TEST_DIR =
-endif
-
-always_dirs = \
-       controller \
-       helloworld \
-       memory   \
-       netclock \
-       ptp \
-       stepping \
-       streamiddemux \
-       streams
-
-SUBDIRS =                              \
-       $(always_dirs)                  \
-       $(ADAPTER_TEST_DIR)
-
-DIST_SUBDIRS = $(always_dirs) adapter
-
-include $(top_srcdir)/common/parallel-subdirs.mak
diff --git a/tests/examples/adapter/.gitignore b/tests/examples/adapter/.gitignore
deleted file mode 100644 (file)
index 1119593..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-adapter_test
-*.gcno
diff --git a/tests/examples/adapter/Makefile.am b/tests/examples/adapter/Makefile.am
deleted file mode 100644 (file)
index cbd2987..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-noinst_PROGRAMS = adapter_test
-
-adapter_test_LDADD = $(GST_OBJ_LIBS) $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la
-adapter_test_CFLAGS = $(GST_OBJ_CFLAGS)
diff --git a/tests/examples/controller/.gitignore b/tests/examples/controller/.gitignore
deleted file mode 100644 (file)
index 2d3d919..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-audio-example
-control-sources
-controller-graph
-text-color-example
-absolute-example
-*.bb
-*.bbg
-*.da
-*.gcno
diff --git a/tests/examples/controller/Makefile.am b/tests/examples/controller/Makefile.am
deleted file mode 100644 (file)
index 146416c..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-noinst_PROGRAMS = audio-example control-sources text-color-example absolute-example
-
-AM_CFLAGS  = $(GST_OBJ_CFLAGS) -I$(top_builddir)/libs
-
-LDADD = \
-       $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \
-       $(GST_OBJ_LIBS)
-
-if HAVE_GTK
-noinst_PROGRAMS += controller-graph
-
-controller_graph_CFLAGS = $(GST_OBJ_CFLAGS) $(GTK_CFLAGS)
-controller_graph_LDADD = \
-       $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \
-       $(GST_OBJ_LIBS) $(GTK_LIBS)
-
-endif
\ No newline at end of file
index 5322933..6c190ff 100644 (file)
@@ -153,7 +153,7 @@ gst_test_obj_base_init (GstTestObjClass * klass)
 static GType
 gst_test_obj_get_type (void)
 {
-  static volatile gsize TEST_OBJ_type = 0;
+  static gsize TEST_OBJ_type = 0;
 
   if (g_once_init_enter (&TEST_OBJ_type)) {
     GType type;
index ef90a27..ea87bef 100644 (file)
@@ -88,7 +88,7 @@ on_graph_draw (GtkWidget * widget, cairo_t * cr, gpointer user_data)
   ts = G_GUINT64_CONSTANT (0);
   for (i = 0; i < G_N_ELEMENTS (yval); i++) {
     cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
-    cairo_arc (cr, x + ts, y + yval[i] * h, 3.0, 0.0, 2 * M_PI);
+    cairo_arc (cr, x + ts, y + yval[i] * h, 3.0, 0.0, 2 * G_PI);
     cairo_stroke_preserve (cr);
     cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
     cairo_fill (cr);
diff --git a/tests/examples/helloworld/.gitignore b/tests/examples/helloworld/.gitignore
deleted file mode 100644 (file)
index 2d86467..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-helloworld
-*.bb
-*.bbg
-*.da
-helloworld-helloworld.gcno
diff --git a/tests/examples/helloworld/Makefile.am b/tests/examples/helloworld/Makefile.am
deleted file mode 100644 (file)
index a7d1bd9..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-noinst_PROGRAMS = helloworld
-
-helloworld_LDADD = $(GST_OBJ_LIBS)
-helloworld_CFLAGS = $(GST_OBJ_CFLAGS)
index ca6e07c..a95d785 100644 (file)
@@ -67,7 +67,7 @@ main (gint argc, gchar * argv[])
 
   bus = gst_element_get_bus (playbin);
   bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
-  g_object_unref (bus);
+  gst_object_unref (bus);
 
   /* start play back and listed to events */
   gst_element_set_state (playbin, GST_STATE_PLAYING);
@@ -75,7 +75,7 @@ main (gint argc, gchar * argv[])
 
   /* cleanup */
   gst_element_set_state (playbin, GST_STATE_NULL);
-  g_object_unref (playbin);
+  gst_object_unref (playbin);
   g_source_remove (bus_watch_id);
   g_main_loop_unref (loop);
 
diff --git a/tests/examples/memory/.gitignore b/tests/examples/memory/.gitignore
deleted file mode 100644 (file)
index 39e6071..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-memory_test
-*.gcno
diff --git a/tests/examples/memory/Makefile.am b/tests/examples/memory/Makefile.am
deleted file mode 100644 (file)
index b0399c0..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-noinst_PROGRAMS = memory_test
-
-memory_test_SOURCES = memory_test.c my-memory.c my-memory.h my-vidmem.c my-vidmem.h
-memory_test_LDADD = $(GST_OBJ_LIBS)
-memory_test_CFLAGS = $(GST_OBJ_CFLAGS)
diff --git a/tests/examples/netclock/.gitignore b/tests/examples/netclock/.gitignore
deleted file mode 100644 (file)
index bf0b328..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-netclock-server
-netclock-client
diff --git a/tests/examples/netclock/Makefile.am b/tests/examples/netclock/Makefile.am
deleted file mode 100644 (file)
index 9506997..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-noinst_PROGRAMS = netclock-server netclock-client
-
-netclock_server_LDADD = \
-       $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \
-       $(GST_OBJ_LIBS)
-netclock_server_CFLAGS = $(GST_OBJ_CFLAGS)
-
-netclock_client_LDADD = \
-       $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \
-       $(GST_OBJ_LIBS)
-netclock_client_CFLAGS = $(GST_OBJ_CFLAGS)
index 2082297..cd43d89 100644 (file)
@@ -53,7 +53,7 @@ main (gint argc, gchar * argv[])
 
   /* cleanup */
   g_main_loop_unref (loop);
-  g_object_unref (client_clock);
+  gst_object_unref (client_clock);
 
   return 0;
 }
diff --git a/tests/examples/ptp/.gitignore b/tests/examples/ptp/.gitignore
deleted file mode 100644 (file)
index b5b83be..0000000
+++ /dev/null
@@ -1 +0,0 @@
-ptp-print-times
diff --git a/tests/examples/ptp/Makefile.am b/tests/examples/ptp/Makefile.am
deleted file mode 100644 (file)
index d76b4ad..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-noinst_PROGRAMS = ptp-print-times
-
-ptp_print_times_LDADD = \
-       $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \
-       $(GST_OBJ_LIBS)
-ptp_print_times_CFLAGS = $(GST_OBJ_CFLAGS)
-
diff --git a/tests/examples/stepping/.gitignore b/tests/examples/stepping/.gitignore
deleted file mode 100644 (file)
index 0b661c7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-framestep1
-*.bb
-*.bbg
-*.da
-framestep1-framestep1.gcno
diff --git a/tests/examples/stepping/Makefile.am b/tests/examples/stepping/Makefile.am
deleted file mode 100644 (file)
index 2a6fbc1..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-noinst_PROGRAMS = framestep1
-
-framestep1_LDADD = $(GST_OBJ_LIBS)
-framestep1_CFLAGS = $(GST_OBJ_CFLAGS)
diff --git a/tests/examples/streamiddemux/Makefile.am b/tests/examples/streamiddemux/Makefile.am
deleted file mode 100644 (file)
index e182d29..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-noinst_PROGRAMS = streamiddemux-stream
-
-streamiddemux_stream_SOURCES = streamiddemux-stream.c
-streamiddemux_stream_LDADD = $(GST_OBJ_LIBS)
-streamiddemux_stream_CFLAGS = $(GST_OBJ_CFLAGS)
-
index 8180221..d3ab9b2 100644 (file)
@@ -69,7 +69,7 @@ sink_do_reconfigure (App * app)
 
   for (i = 0; i < NUM_STREAM; i++) {
     sync_sinkpad[i] =
-        gst_element_get_request_pad (app->stream_synchronizer, "sink_%u");
+        gst_element_request_pad_simple (app->stream_synchronizer, "sink_%u");
     it = gst_pad_iterate_internal_links (sync_sinkpad[i]);
     g_assert (it);
     gst_iterator_next (it, &item);
@@ -189,7 +189,7 @@ main (gint argc, gchar * argv[])
 
   bus = gst_element_get_bus (app->pipeline);
   bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
-  g_object_unref (bus);
+  gst_object_unref (bus);
 
   for (stream_cnt = 0; stream_cnt < NUM_STREAM; stream_cnt++) {
     gst_bin_add_many (GST_BIN (app->pipeline), app->audiotestsrc[stream_cnt],
@@ -210,7 +210,7 @@ main (gint argc, gchar * argv[])
 
   for (stream_cnt = 0; stream_cnt < NUM_STREAM; stream_cnt++) {
     funnel_sinkpad[stream_cnt] =
-        gst_element_get_request_pad (app->funnel, "sink_%u");
+        gst_element_request_pad_simple (app->funnel, "sink_%u");
     oggmux_srcpad[stream_cnt] =
         gst_element_get_static_pad (app->oggmux[stream_cnt], "src");
     gst_pad_link (oggmux_srcpad[stream_cnt], funnel_sinkpad[stream_cnt]);
@@ -225,7 +225,7 @@ main (gint argc, gchar * argv[])
   g_main_loop_run (loop);
 
   gst_element_set_state (app->pipeline, GST_STATE_NULL);
-  g_object_unref (app->pipeline);
+  gst_object_unref (app->pipeline);
   g_source_remove (bus_watch_id);
   g_main_loop_unref (loop);
 
diff --git a/tests/examples/streams/.gitignore b/tests/examples/streams/.gitignore
deleted file mode 100644 (file)
index d8cfe30..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-stream-status
-rtpool-test
-*.bb
-*.bbg
-*.da
-stream-status-stream-status.gcno
diff --git a/tests/examples/streams/Makefile.am b/tests/examples/streams/Makefile.am
deleted file mode 100644 (file)
index e1f87ac..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-noinst_PROGRAMS = stream-status
-if HAVE_PTHREAD
-noinst_PROGRAMS += rtpool-test
-endif
-
-stream_status_SOURCES = stream-status.c
-stream_status_LDADD = $(GST_OBJ_LIBS)
-stream_status_CFLAGS = $(GST_OBJ_CFLAGS)
-
-rtpool_test_SOURCES = rtpool-test.c testrtpool.h testrtpool.c
-rtpool_test_LDADD = $(GST_OBJ_LIBS) $(PTHREAD_LIBS)
-rtpool_test_CFLAGS = $(GST_OBJ_CFLAGS) $(PTHREAD_CFLAGS)
-
-EXTRA_DIST = rtpool-test.c testrtpool.h testrtpool.c
index 324355c..f3589a5 100644 (file)
@@ -2,6 +2,7 @@ if not get_option('benchmarks').disabled()
   subdir('benchmarks')
 endif
 if not get_option('tests').disabled() and gst_check_dep.found()
+  subdir('validate')
   subdir('check')
 endif
 if not get_option('examples').disabled()
diff --git a/tests/misc/Makefile.am b/tests/misc/Makefile.am
deleted file mode 100644 (file)
index bccbffd..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-EXTRA_DIST = \
-       network-clock.scm \
-       network-clock-utils.scm \
-       plot-data
-
-noinst_PROGRAMS = netclock-replay
-
-netclock_replay_LDADD = $(GST_OBJ_LIBS) $(GIO_LIBS)
-netclock_replay_CFLAGS = $(GST_OBJ_CFLAGS) $(GIO_CFLAGS)
index b7b741b..e405902 100644 (file)
@@ -48,6 +48,41 @@ static GOptionEntry entries[] = {
   {NULL,}
 };
 
+static gboolean
+parse_time_values (const gchar * line, GstClockTime * local_1,
+    GstClockTime * remote_1, GstClockTime * remote_2, GstClockTime * local_2)
+{
+  gchar **split;
+  gboolean ret = FALSE;
+
+  if (!line)
+    return FALSE;
+
+  split = g_strsplit (line, " ", -1);
+
+  if (g_strv_length (split) != 4)
+    goto out;
+
+  if (!g_ascii_string_to_unsigned (split[0], 10, 0, G_MAXUINT64, local_1, NULL))
+    goto out;
+
+  if (!g_ascii_string_to_unsigned (split[1], 10, 0, G_MAXUINT64, remote_1,
+          NULL))
+    goto out;
+
+  if (!g_ascii_string_to_unsigned (split[2], 10, 0, G_MAXUINT64, remote_2,
+          NULL))
+    goto out;
+
+  if (!g_ascii_string_to_unsigned (split[3], 10, 0, G_MAXUINT64, local_2, NULL))
+    goto out;
+
+  ret = TRUE;
+out:
+  g_strfreev (split);
+  return ret;
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -92,12 +127,10 @@ main (int argc, char *argv[])
 
   while ((status = g_io_channel_read_line (channel, &line, NULL, NULL,
               &error)) == G_IO_STATUS_NORMAL) {
-    GstClockTime local_1, local_2, remote_1, remote_2;
+    GstClockTime local_1, remote_1, remote_2, local_2;
     GstMessage *message;
 
-    if (sscanf (line, "%" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " %"
-            G_GUINT64_FORMAT " %" G_GUINT64_FORMAT, &local_1, &remote_1,
-            &remote_2, &local_2) != 4) {
+    if (!parse_time_values (line, &local_1, &remote_1, &remote_2, &local_2)) {
       g_print ("Failed to get local/remote time values from: %s\n", line);
       goto done;
     }
diff --git a/tests/validate/gst-tester.c b/tests/validate/gst-tester.c
new file mode 100644 (file)
index 0000000..2ab4865
--- /dev/null
@@ -0,0 +1,219 @@
+/* GStreamer
+ * Copyright (C) 2020 Igalia, S.L.
+ *   Author: Thibault Saunier <tsaunier@igalia.com>
+
+ * gst-tester.c: tool to launch `.validatetest` files with
+ * TAP compatible output and supporting missing `gst-validate`
+ * application.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <gio/gio.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef G_OS_UNIX
+#include <glib-unix.h>
+#include <sys/wait.h>
+#elif defined (G_OS_WIN32)
+#include <windows.h>
+#include <io.h>
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+#define isatty _isatty
+#endif
+
+#if defined (G_OS_WIN32)
+#define VALIDATE_NAME "gst-validate-" GST_API_VERSION ".exe"
+#else
+#define VALIDATE_NAME "gst-validate-" GST_API_VERSION
+#endif
+
+
+typedef struct
+{
+  const gchar *testname;
+
+  GSubprocess *subproc;
+  GMainLoop *ml;
+#if defined(G_OS_UNIX)
+  guint signal_watch_intr_id;
+#endif
+  gint exitcode;
+} Application;
+
+#if defined(G_OS_UNIX)
+/* As the interrupt handler is dispatched from GMainContext as a GSourceFunc
+ * handler, we can react to this by posting a message. */
+static gboolean
+intr_handler (gpointer user_data)
+{
+  Application *app = user_data;
+
+  g_print ("Bail out! Got interupted.\n");
+
+  g_subprocess_force_exit (app->subproc);
+
+  /* remove signal handler */
+  app->signal_watch_intr_id = 0;
+  return G_SOURCE_REMOVE;
+}
+#endif
+
+static void
+_run_app (Application * app)
+{
+  GError *err = NULL;
+  gboolean bailed_out = FALSE, skipped = FALSE;
+  gchar *_stdout = NULL;
+  gboolean is_tty = isatty (STDOUT_FILENO);
+
+  g_print ("1..1\n");
+  g_subprocess_communicate_utf8 (app->subproc, NULL, NULL,
+      is_tty ? NULL : &_stdout, NULL, &err);
+  if (_stdout) {
+    gchar *c;
+    GString *output = g_string_new (NULL);
+
+    for (c = _stdout; *c != '\0'; c++) {
+      g_string_append_c (output, *c);
+      if (!bailed_out && !skipped && *c == '\n' && *(c + 1) != '\0') {
+        if (strstr ((c + 1), "Bail out!") == c + 1) {
+          bailed_out = TRUE;
+          continue;
+        }
+
+        if (strstr ((c + 1), "ok") == c + 1 && strstr ((c + 1), "# SKIP")) {
+          skipped = TRUE;
+          app->exitcode = 0;
+          continue;
+        }
+
+        g_string_append (output, "# ");
+      }
+    }
+    g_print ("# %s\n", output->str);
+    g_string_free (output, TRUE);
+    g_free (_stdout);
+  }
+#ifdef G_OS_UNIX
+  if (app->signal_watch_intr_id > 0)
+    g_source_remove (app->signal_watch_intr_id);
+#endif
+
+  if (skipped || bailed_out)
+    goto done;
+
+  if (g_subprocess_get_if_signaled (app->subproc))
+    app->exitcode = g_subprocess_get_term_sig (app->subproc);
+  else
+    app->exitcode = g_subprocess_get_exit_status (app->subproc);
+
+  if (app->exitcode == 0) {
+    g_print ("ok 1 %s\n", app->testname);
+  } else if (app->exitcode == 18) {
+    g_print ("not ok 1 %s # Got a critical report\n", app->testname);
+  } else {
+    g_print ("not ok 1 %s # Unknown reason\n", app->testname);
+  }
+
+done:
+  g_clear_object (&app->subproc);
+  g_main_loop_quit (app->ml);
+}
+
+int
+main (int argc, gchar ** argv)
+{
+  Application app = { 0, };
+  gchar *dirname;
+  GFile *f;
+  gchar **args = g_new0 (gchar *, argc + 2);
+  gint i;
+  GError *err = NULL;
+  gchar *filename;
+  gboolean is_tty = isatty (STDOUT_FILENO);
+
+  if (argc < 2) {
+    g_print ("1..0\nnot ok # Missing <testfile> argument\n");
+    return 1;
+  }
+
+  app.testname = argv[1];
+
+  dirname = g_path_get_dirname (argv[0]);
+  filename = g_build_filename ("subprojects", "gst-devtools",
+      "validate", "tools", VALIDATE_NAME, NULL);
+  f = g_file_new_for_path (filename);
+  g_free (filename);
+
+  if (g_file_query_exists (f, NULL)) {
+    /* Try to find `gst-validate` as a meson subproject */
+    g_free (args[0]);
+    g_clear_error (&err);
+    args[0] = g_file_get_path (f);
+    g_print ("# Running from meson subproject %s\n", args[0]);
+  }
+  g_free (dirname);
+  g_object_unref (f);
+
+  if (!args[0])
+    args[0] = g_strdup (VALIDATE_NAME);
+  args[1] = g_strdup ("--set-test-file");
+  for (i = 1; i < argc; i++)
+    args[i + 1] = g_strdup (argv[i]);
+
+  app.subproc = g_subprocess_newv ((const char *const *) args,
+      is_tty ? G_SUBPROCESS_FLAGS_STDIN_INHERIT :
+      G_SUBPROCESS_FLAGS_STDOUT_PIPE, &err);
+
+  if (!app.subproc) {
+    g_printerr ("%s %s\n", args[0], err->message);
+    if (g_error_matches (err, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT)) {
+      g_print ("1..0 # Skipped: `" VALIDATE_NAME "` not available\n");
+      return 0;
+    }
+
+    g_print ("1..0\nnot ok # %s\n", err->message);
+    return -1;
+  }
+
+  app.ml = g_main_loop_new (NULL, TRUE);
+
+#ifdef G_OS_UNIX
+  app.signal_watch_intr_id =
+      g_unix_signal_add (SIGINT, (GSourceFunc) intr_handler, &app);
+#endif
+
+/* Running the subprocess in it own thread so that we can properly catch
+ * interuptions in the main thread main loop */
+  g_thread_new ("gst-tester-thread", (GThreadFunc) _run_app, &app);
+  g_main_loop_run (app.ml);
+  g_main_loop_unref (app.ml);
+  g_strfreev (args);
+
+  return app.exitcode;
+}
diff --git a/tests/validate/meson.build b/tests/validate/meson.build
new file mode 100644 (file)
index 0000000..4f1ab1e
--- /dev/null
@@ -0,0 +1,33 @@
+gst_tester = executable('gst-tester-' + apiversion,
+    'gst-tester.c',
+    c_args : gst_c_args + ['-DBUILDDIR=' + meson.build_root()],
+    include_directories : [configinc],
+    install: true,
+    dependencies : [gio_dep],
+)
+
+meson.override_find_program('gst-tester-' + apiversion, gst_tester)
+
+tests = [
+    'simplest',
+]
+
+env = environment()
+env.set('GST_PLUGIN_PATH_1_0', meson.build_root())
+env.set('GST_PLUGIN_SYSTEM_PATH_1_0', '')
+env.set('GST_REGISTRY', '@0@/@1@.registry'.format(meson.current_build_dir(), 'validate'))
+env.set('GST_PLUGIN_SCANNER_1_0', gst_scanner_dir + '/gst-plugin-scanner')
+env.set('GST_PLUGIN_LOADING_WHITELIST', 'gstreamer', 'gst-validate')
+
+foreach t: tests
+    test_dir_name = t.split('/')
+    test_name = 'validate'
+    foreach c: test_dir_name
+        test_name += '.' + c
+    endforeach
+    test_env = env
+    test_env.set('GST_VALIDATE_LOGSDIR', join_paths(meson.current_build_dir(), test_name))
+    test_file = join_paths(meson.current_source_dir(), t + '.validatetest')
+    test(test_name, gst_tester, args: [test_file, '--use-fakesinks'],
+        env: test_env, timeout : 3 * 60, protocol: 'tap')
+endforeach
\ No newline at end of file
diff --git a/tests/validate/simplest.validatetest b/tests/validate/simplest.validatetest
new file mode 100644 (file)
index 0000000..ca1f8d6
--- /dev/null
@@ -0,0 +1,17 @@
+meta,
+    handles-states=true,
+    ignore-eos=true,
+    args = {
+        "fakesrc num-buffers=5 ! fakesink sync=true name=sink",
+    },
+    configs = {
+        "core, fail-on-missing-plugin=true",
+        "$(validateflow), pad=sink:sink, buffers-checksum=true",
+    }
+
+play
+crank-clock, expected-elapsed-time=0.0
+crank-clock, repeat=5, expected-elapsed-time=0.0
+
+stop, on-message=eos
+
diff --git a/tests/validate/simplest/flow-expectations/log-sink-sink-expected b/tests/validate/simplest/flow-expectations/log-sink-sink-expected
new file mode 100644 (file)
index 0000000..dfdfbd4
--- /dev/null
@@ -0,0 +1,8 @@
+event stream-start: GstEventStreamStart, flags=(GstStreamFlags)GST_STREAM_FLAG_NONE, group-id=(uint)1;
+event segment: format=BYTES, start=0, offset=0, stop=18446744073709551615, time=0, base=0, position=0
+buffer: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709, dts=0:00:00.000000000, pts=0:00:00.000000000, flags=discont
+buffer: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709, dts=0:00:00.000000000, pts=0:00:00.000000000
+buffer: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709, dts=0:00:00.000000000, pts=0:00:00.000000000
+buffer: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709, dts=0:00:00.000000000, pts=0:00:00.000000000
+buffer: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709, dts=0:00:00.000000000, pts=0:00:00.000000000
+event eos: (no structure)
diff --git a/tools/.gitignore b/tools/.gitignore
deleted file mode 100644 (file)
index e4ea6b8..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-Makefile
-Makefile.in
-.dirstamp
-*.o
-*.lo
-*.la
-.deps
-.libs
-*.bb
-*.bbg
-*.da
-*.gcno
-
-gst-inspect-?.0
-gst-launch-?.0
-gst-typefind-?.0
-gst-stats-?.0
diff --git a/tools/Makefile.am b/tools/Makefile.am
deleted file mode 100644 (file)
index 7fc3da1..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-
-bin_PROGRAMS = \
-       gst-inspect-@GST_API_VERSION@ \
-       gst-stats-@GST_API_VERSION@ \
-       gst-typefind-@GST_API_VERSION@
-
-gst_inspect_@GST_API_VERSION@_SOURCES = gst-inspect.c tools.h
-gst_inspect_@GST_API_VERSION@_CFLAGS = $(GST_OBJ_CFLAGS) -fPIE
-gst_inspect_@GST_API_VERSION@_LDADD = $(GST_OBJ_LIBS)
-gst_inspect_@GST_API_VERSION@_LDFLAGS = -pie
-
-gst_stats_@GST_API_VERSION@_SOURCES = gst-stats.c tools.h
-gst_stats_@GST_API_VERSION@_CFLAGS = $(GST_OBJ_CFLAGS) -fPIE
-gst_stats_@GST_API_VERSION@_LDADD = $(GST_OBJ_LIBS)
-gst_stats_@GST_API_VERSION@_LDFLAGS = -pie
-
-gst_typefind_@GST_API_VERSION@_SOURCES = gst-typefind.c tools.h
-gst_typefind_@GST_API_VERSION@_CFLAGS = $(GST_OBJ_CFLAGS) -fPIE
-gst_typefind_@GST_API_VERSION@_LDADD = $(GST_OBJ_LIBS)
-gst_typefind_@GST_API_VERSION@_LDFLAGS = -pie
-
-if !GST_DISABLE_PARSE
-bin_PROGRAMS += gst-launch-@GST_API_VERSION@
-
-gst_launch_@GST_API_VERSION@_SOURCES = gst-launch.c tools.h
-gst_launch_@GST_API_VERSION@_CFLAGS = $(GST_OBJ_CFLAGS) -fPIE
-gst_launch_@GST_API_VERSION@_LDADD = $(GST_OBJ_LIBS)
-gst_launch_@GST_API_VERSION@_LDFLAGS = -pie
-endif
-
-manpages = \
-       gst-inspect-@GST_API_VERSION@.1 \
-       gst-stats-@GST_API_VERSION@.1 \
-       gst-typefind-@GST_API_VERSION@.1
-
-if !GST_DISABLE_PARSE
-manpages += gst-launch-@GST_API_VERSION@.1
-endif
-
-man_MANS = $(manpages)
-
-# developer helper tools, not meant for installation
-noinst_SCRIPTS = gst-indent
-
-noinst_HEADERS = tools.h
-
-EXTRA_DIST = \
-       gst-inspect-@GST_API_VERSION@.1 \
-       gst-typefind-@GST_API_VERSION@.1 \
-       gst-launch-@GST_API_VERSION@.1 \
-       gst-stats-@GST_API_VERSION@.1 \
-       $(noinst_SCRIPTS)
index 14e6387..6299f4c 100644 (file)
@@ -57,10 +57,13 @@ is at least the version specified
 .B  \-u, \-\-uri\-handlers
 Print supported URI schemes, with the elements that implement them
 .TP 8
-.B  \-u, \-\-no\-colors
+.B  \-\-no\-colors
 Disable colors in output. You can also achieve the same by setting
 \'GST_INSPECT_NO_COLORS\' environment variable to any value.
 .TP 8
+.B  \-C, \-\-color
+Color output, even when not connected to a tty.
+.TP 8
 .B  \-\-print\-plugin\-auto\-install\-info
 Print a machine-parsable list of features the specified plugin provides.
 Useful in connection with external automatic plugin installation mechanisms.
@@ -78,6 +81,17 @@ Enable printout of errors while loading \fIGStreamer\fP plugins
 .B  \-\-gst\-plugin\-path=PATH
 Add directories separated with ':' to the plugin search path
 .
+.SH "ENVIRONMENT VARIABLES"
+.l
+\fIgst\-inspect\-1.0\fP reads the following environment variables, in addition
+to the generic \fIGStreamer\fP environment variables also described in
+.BR gst\-launch\-1.0 (1):
+.TP 8
+.B GST_LESS
+Override the options passed to \fIless\fR (by default "RXF").
+.br
+See \fBless\fR(1) for more information.
+.
 .SH "SEE ALSO"
 .BR gst\-launch\-1.0 (1),
 .BR gst\-typefind\-1.0 (1)
index 1b5ed83..b7bf806 100644 (file)
 /* "R" : support color
  * "X" : do not clear the screen when leaving the pager
  * "F" : skip the pager if content fit into the screen
+ *
+ * Don't forget to update the manpage gst-inspect-1.0.1
+ * after changing this default.
  */
 #define DEFAULT_LESS_OPTS "RXF"
 
 gboolean colored_output = TRUE;
 
+typedef enum
+{
+  SORT_TYPE_NONE = 0,
+  SORT_TYPE_NAME,               /* default */
+} SortType;
+
+SortType sort_output = SORT_TYPE_NAME;
+
 #ifdef G_OS_UNIX
 static const gchar DEFAULT_PAGER[] = "less";
 GPid child_pid = -1;
@@ -132,6 +143,7 @@ n_print (const char *format, ...)
 {
   va_list args;
   int i;
+  gchar *str;
 
   if (_name)
     g_print ("%s", _name);
@@ -140,8 +152,14 @@ n_print (const char *format, ...)
     g_print ("  ");
 
   va_start (args, format);
-  g_vprintf (format, args);
+  str = gst_info_strdup_vprintf (format, args);
   va_end (args);
+
+  if (!str)
+    return;
+
+  g_print ("%s", str);
+  g_free (str);
 }
 
 static gboolean
@@ -225,7 +243,7 @@ print_factory_details_info (GstElementFactory * factory)
 {
   gchar **keys, **k;
   GstRank rank;
-  char s[20];
+  char s[40];
 
   rank = gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory));
   n_print ("%sFactory Details:%s\n", HEADING_COLOR, RESET_COLOR);
@@ -340,7 +358,8 @@ flags_to_string (GFlagsValue * vals, guint flags)
   G_PARAM_LAX_VALIDATION |  G_PARAM_STATIC_STRINGS | \
   G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_DEPRECATED | \
   GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | \
-  GST_PARAM_MUTABLE_PAUSED | GST_PARAM_MUTABLE_READY)
+  GST_PARAM_MUTABLE_PAUSED | GST_PARAM_MUTABLE_READY | \
+  GST_PARAM_CONDITIONALLY_AVAILABLE)
 
 static int
 sort_gparamspecs (GParamSpec ** a, GParamSpec ** b)
@@ -415,6 +434,11 @@ print_object_properties_info (GObject * obj, GObjectClass * obj_class,
           RESET_COLOR);
       first_flag = FALSE;
     }
+    if (param->flags & GST_PARAM_CONDITIONALLY_AVAILABLE) {
+      g_print (", %s%s%s", PROP_ATTR_VALUE_COLOR, _("conditionally available"),
+          RESET_COLOR);
+      first_flag = FALSE;
+    }
     if (param->flags & GST_PARAM_MUTABLE_PLAYING) {
       g_print (", %s%s%s", PROP_ATTR_VALUE_COLOR,
           _("changeable in NULL, READY, PAUSED or PLAYING state"), RESET_COLOR);
@@ -714,10 +738,22 @@ print_element_properties_info (GstElement * element)
       G_OBJECT_GET_CLASS (element), "Element Properties");
 }
 
+static gint
+gst_static_pad_compare_func (gconstpointer p1, gconstpointer p2)
+{
+  GstStaticPadTemplate *pt1, *pt2;
+
+  pt1 = (GstStaticPadTemplate *) p1;
+  pt2 = (GstStaticPadTemplate *) p2;
+
+  return strcmp (pt1->name_template, pt2->name_template);
+}
+
+
 static void
 print_pad_templates_info (GstElement * element, GstElementFactory * factory)
 {
-  const GList *pads;
+  GList *pads;
   GstStaticPadTemplate *padtemplate;
   GstPadTemplate *tmpl;
 
@@ -730,7 +766,9 @@ print_pad_templates_info (GstElement * element, GstElementFactory * factory)
     goto done;
   }
 
-  pads = gst_element_factory_get_static_pad_templates (factory);
+  pads = g_list_copy ((GList *)
+      gst_element_factory_get_static_pad_templates (factory));
+  pads = g_list_sort (pads, gst_static_pad_compare_func);
   while (pads) {
     padtemplate = (GstStaticPadTemplate *) (pads->data);
     pads = g_list_next (pads);
@@ -793,7 +831,7 @@ print_pad_templates_info (GstElement * element, GstElementFactory * factory)
     if (pads != NULL)
       n_print ("\n");
   }
-
+  g_list_free (pads);
 done:
   pop_indent ();
 }
@@ -1116,12 +1154,32 @@ print_preset_list (GstElement * element)
     n_print ("\n");
     n_print ("%sPresets%s:\n", HEADING_COLOR, RESET_COLOR);
     for (preset = presets; *preset; preset++) {
-      n_print ("  \"%s\"\n", *preset);
+      gchar *comment = NULL;
+      n_print ("  \"%s\"", *preset);
+
+      if (gst_preset_get_meta (GST_PRESET (element), *preset, "comment",
+              &comment) && comment)
+        g_print (": %s", comment);
+      g_free (comment);
+      g_print ("\n");
     }
     g_strfreev (presets);
   }
 }
 
+static gint
+gst_plugin_name_compare_func (gconstpointer p1, gconstpointer p2)
+{
+  return strcmp (gst_plugin_get_name ((GstPlugin *) p1),
+      gst_plugin_get_name ((GstPlugin *) p2));
+}
+
+static gint
+gst_plugin_feature_name_compare_func (gconstpointer p1, gconstpointer p2)
+{
+  return strcmp (GST_OBJECT_NAME (p1), GST_OBJECT_NAME (p2));
+}
+
 static void
 print_blacklist (void)
 {
@@ -1131,6 +1189,9 @@ print_blacklist (void)
   g_print ("%s%s%s\n", HEADING_COLOR, _("Blacklisted files:"), RESET_COLOR);
 
   plugins = gst_registry_get_plugin_list (gst_registry_get ());
+  if (sort_output == SORT_TYPE_NAME)
+    plugins = g_list_sort (plugins, gst_plugin_name_compare_func);
+
   for (cur = plugins; cur != NULL; cur = g_list_next (cur)) {
     GstPlugin *plugin = (GstPlugin *) (cur->data);
     if (GST_OBJECT_FLAG_IS_SET (plugin, GST_PLUGIN_FLAG_BLACKLISTED)) {
@@ -1176,6 +1237,8 @@ print_element_list (gboolean print_all, gchar * ftypes)
   }
 
   orig_plugins = plugins = gst_registry_get_plugin_list (gst_registry_get ());
+  if (sort_output == SORT_TYPE_NAME)
+    plugins = g_list_sort (plugins, gst_plugin_name_compare_func);
   while (plugins) {
     GList *features, *orig_features;
     GstPlugin *plugin;
@@ -1192,6 +1255,8 @@ print_element_list (gboolean print_all, gchar * ftypes)
     orig_features = features =
         gst_registry_get_feature_list_by_plugin (gst_registry_get (),
         gst_plugin_get_name (plugin));
+    if (sort_output == SORT_TYPE_NAME)
+      features = g_list_sort (features, gst_plugin_feature_name_compare_func);
     while (features) {
       GstPluginFeature *feature;
 
@@ -1293,14 +1358,16 @@ print_all_uri_handlers (void)
   GList *plugins, *p, *features, *f;
 
   plugins = gst_registry_get_plugin_list (gst_registry_get ());
-
+  if (sort_output == SORT_TYPE_NAME)
+    plugins = g_list_sort (plugins, gst_plugin_name_compare_func);
   for (p = plugins; p; p = p->next) {
     GstPlugin *plugin = (GstPlugin *) (p->data);
 
     features =
         gst_registry_get_feature_list_by_plugin (gst_registry_get (),
         gst_plugin_get_name (plugin));
-
+    if (sort_output == SORT_TYPE_NAME)
+      features = g_list_sort (features, gst_plugin_feature_name_compare_func);
     for (f = features; f; f = f->next) {
       GstPluginFeature *feature = GST_PLUGIN_FEATURE (f->data);
 
@@ -1436,7 +1503,8 @@ print_plugin_features (GstPlugin * plugin)
   origlist = features =
       gst_registry_get_feature_list_by_plugin (gst_registry_get (),
       gst_plugin_get_name (plugin));
-
+  if (sort_output == SORT_TYPE_NAME)
+    features = g_list_sort (features, gst_plugin_feature_name_compare_func);
   while (features) {
     GstPluginFeature *feature;
 
@@ -1610,7 +1678,7 @@ print_typefind_info (GstPluginFeature * feature, gboolean print_names)
   GstPlugin *plugin;
   GstCaps *caps;
   GstRank rank;
-  char s[20];
+  char s[40];
   const gchar *const *extensions;
 
   factory = GST_TYPE_FIND_FACTORY (gst_plugin_feature_load (feature));
@@ -1865,6 +1933,8 @@ print_all_plugin_automatic_install_info (void)
   GList *plugins, *orig_plugins;
 
   orig_plugins = plugins = gst_registry_get_plugin_list (gst_registry_get ());
+  if (sort_output == SORT_TYPE_NAME)
+    plugins = g_list_sort (plugins, gst_plugin_name_compare_func);
   while (plugins) {
     GstPlugin *plugin;
 
@@ -1882,7 +1952,7 @@ redirect_stdout (void)
 {
   GError *error = NULL;
   gchar **argv;
-  const gchar *pager;
+  const gchar *pager, *less;
   gint stdin_fd;
   gchar **envp;
 
@@ -1892,8 +1962,12 @@ redirect_stdout (void)
 
   argv = g_strsplit (pager, " ", 0);
 
+  less = g_getenv ("GST_LESS");
+  if (less == NULL)
+    less = DEFAULT_LESS_OPTS;
+
   envp = g_get_environ ();
-  envp = g_environ_setenv (envp, "LESS", DEFAULT_LESS_OPTS, TRUE);
+  envp = g_environ_setenv (envp, "LESS", less, TRUE);
 
   if (!g_spawn_async_with_pipes (NULL, argv, envp,
           G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
@@ -1931,6 +2005,21 @@ child_exit_cb (GPid child_pid, gint status, gpointer user_data)
 }
 #endif
 
+static gboolean
+_parse_sort_type (const gchar * option_name, const gchar * optarg,
+    gpointer data, GError ** error)
+{
+  if (!g_strcmp0 (optarg, "name")) {
+    sort_output = SORT_TYPE_NAME;
+    return TRUE;
+  } else if (!g_strcmp0 (optarg, "none")) {
+    sort_output = SORT_TYPE_NONE;
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -1940,6 +2029,7 @@ main (int argc, char *argv[])
   gboolean print_aii = FALSE;
   gboolean uri_handlers = FALSE;
   gboolean check_exists = FALSE;
+  gboolean color_always = FALSE;
   gchar *min_version = NULL;
   guint minver_maj = GST_VERSION_MAJOR;
   guint minver_min = GST_VERSION_MINOR;
@@ -1976,9 +2066,16 @@ main (int argc, char *argv[])
     {"no-colors", '\0', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE,
           &colored_output,
           N_
-          ("Disable colors in output. You can also achieve the same by setting"
+          ("Disable colors in output. You can also achieve the same by setting "
               "'GST_INSPECT_NO_COLORS' environment variable to any value."),
         NULL},
+    {"sort", '\0', G_OPTION_ARG_NONE, G_OPTION_ARG_CALLBACK, &_parse_sort_type,
+          "Sort plugins and features. Sorting keys: name (default), none.",
+        "<sort-key>"}
+    ,
+    {"color", 'C', 0, G_OPTION_ARG_NONE, &color_always,
+          N_("Color output, even when not sending to a tty."),
+        NULL},
     GST_TOOLS_GOPTION_VERSION,
     {NULL}
   };
@@ -2032,8 +2129,10 @@ main (int argc, char *argv[])
             &minver_micro) < 2) {
       g_printerr ("Can't parse version '%s' passed to --atleast-version\n",
           min_version);
+      g_free (min_version);
       return -1;
     }
+    g_free (min_version);
     check_exists = TRUE;
   }
 
@@ -2073,10 +2172,11 @@ main (int argc, char *argv[])
     if (redirect_stdout ())
       loop = g_main_loop_new (NULL, FALSE);
   } else {
-    colored_output = FALSE;
+    colored_output = (color_always) ? TRUE : FALSE;
   }
 #elif defined(G_OS_WIN32)
   {
+    /* g_log_writer_supports_color is available since 2.50.0 */
     gint fd = _fileno (stdout);
     /* On Windows 10, g_log_writer_supports_color will also setup the console
      * so that it correctly interprets ANSI VT sequences if it's supported */
index 33a7d14..8195768 100644 (file)
@@ -10,7 +10,8 @@ gst\-launch\-1.0 \- build and run a GStreamer pipeline
 
 In simple form, a PIPELINE\-DESCRIPTION is a list of
 elements separated by exclamation marks (!). Properties may be appended to
-elements, in the form \fIproperty=value\fR.
+elements, in the form \fIproperty=value\fR. A "preset" can also be set using
+the \fI@preset=<preset name>\fR syntax.
 
 For a complete description of possible PIPELINE-DESCRIPTIONS see the section
 \fIpipeline description\fR below or consult the GStreamer documentation.
@@ -55,6 +56,16 @@ Do not install a fault handler
 Print memory allocation traces. The feature must be enabled at compile time to
 work.
 .TP 8
+.B  \-\-no\-position
+Do not print current position of pipeline.
+If this option is unspecified, the position will be printed when stdout is a TTY.
+To enable printing position when stdout is not a TTY,
+use "force-position" option.
+.TP 8
+.B  \-\-force\-position
+Allow printing current position of pipeline even if stdout is not a TTY.
+This option has no effect if the "no-position" option is specified.
+.TP 8
 
 .
 .SH "GSTREAMER OPTIONS"
@@ -149,6 +160,13 @@ find out about properties and allowed values of different elements.
 .br
 Enumeration properties can be set by name, nick or value.
 
+.B Presets
+
+@preset=<preset name> ...
+
+Sets the preset on the element. you can use \fbgst\-inspect\-1.0\fr(1) to
+find out what presets are available for a specific element.
+
 .B Bins
 
 \fI[BINTYPE.]\fR ( \fI[PROPERTY1 ...]\fR PIPELINE-DESCRIPTION )
index ad64cd3..d38ea9f 100644 (file)
 #elif defined (G_OS_WIN32)
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
+#include <io.h>
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+#define isatty _isatty
 #endif
 #include <locale.h>             /* for LC_ALL */
 #include "tools.h"
+#ifdef HAVE_WINMM
+#include <timeapi.h>
+#endif
 
 extern volatile gboolean glib_on_error_halt;
 
@@ -49,23 +57,36 @@ static void fault_restore (void);
 static void fault_spin (void);
 #endif
 
-/* event_loop return codes */
-typedef enum _EventLoopResult
+/* exit codes */
+typedef enum _LaunchExitCode
 {
-  ELR_NO_ERROR = 0,
-  ELR_ERROR,
-  ELR_INTERRUPT
-} EventLoopResult;
+  LEC_STATE_CHANGE_FAILURE = -1,
+  LEC_NO_ERROR = 0,
+  LEC_ERROR,
+  LEC_INTERRUPT
+} LaunchExitCode;
+
+static GMainLoop *loop = NULL;
+static GstElement *pipeline = NULL;
 
-static GstElement *pipeline;
-static EventLoopResult caught_error = ELR_NO_ERROR;
+/* options */
 static gboolean quiet = FALSE;
 static gboolean tags = FALSE;
 static gboolean toc = FALSE;
 static gboolean messages = FALSE;
+static gboolean eos_on_shutdown = FALSE;
+static gchar **exclude_args = NULL;
+
+/* pipeline status */
 static gboolean is_live = FALSE;
+static gboolean buffering = FALSE;
+static LaunchExitCode last_launch_code = LEC_NO_ERROR;
+static GstState target_state = GST_STATE_PAUSED;
+static gboolean prerolled = FALSE;
+static gboolean in_progress = FALSE;
+static GstClockTime tfthen = GST_CLOCK_TIME_NONE;
+static gboolean interrupting = FALSE;
 static gboolean waiting_eos = FALSE;
-static gchar **exclude_args = NULL;
 
 /* convenience macro so we don't have to litter the code with if(!quiet) */
 #define PRINT if(!quiet)gst_print
@@ -76,7 +97,7 @@ fault_handler_sighandler (int signum)
 {
   fault_restore ();
 
-  /* printf is used instead of g_print(), since it's less likely to
+  /* printf is used instead of gst_print(), since it's less likely to
    * deadlock */
   switch (signum) {
     case SIGSEGV:
@@ -249,13 +270,13 @@ print_index_stats (GPtrArray * index_stats)
   gint i;
 
   if (index_stats->len) {
-    g_print ("%s:\n", _("Index statistics"));
+    gst_print ("%s:\n", _("Index statistics"));
   }
 
   for (i = 0; i < index_stats->len; i++) {
     GstIndexStats *s = g_ptr_array_index (index_stats, i);
     if (s) {
-      g_print ("id %d, %s\n", s->id, s->desc);
+      gst_print ("id %d, %s\n", s->id, s->desc);
       if (s->num_frames) {
         GstClockTime last_frame = s->last_keyframe;
 
@@ -266,24 +287,24 @@ print_index_stats (GPtrArray * index_stats)
         }
 
         if (GST_CLOCK_TIME_IS_VALID (last_frame)) {
-          g_print ("  total time               = %" GST_TIME_FORMAT "\n",
+          gst_print ("  total time               = %" GST_TIME_FORMAT "\n",
               GST_TIME_ARGS (last_frame));
         }
-        g_print ("  frame/keyframe rate      = %u / %u = ", s->num_frames,
+        gst_print ("  frame/keyframe rate      = %u / %u = ", s->num_frames,
             s->num_keyframes);
         if (s->num_keyframes)
-          g_print ("%lf\n", s->num_frames / (gdouble) s->num_keyframes);
+          gst_print ("%lf\n", s->num_frames / (gdouble) s->num_keyframes);
         else
-          g_print ("-\n");
+          gst_print ("-\n");
         if (s->num_keyframes) {
-          g_print ("  min/avg/max keyframe gap = %" GST_TIME_FORMAT ", %"
+          gst_print ("  min/avg/max keyframe gap = %" GST_TIME_FORMAT ", %"
               GST_TIME_FORMAT ", %" GST_TIME_FORMAT "\n",
               GST_TIME_ARGS (s->min_keyframe_gap),
               GST_TIME_ARGS (s->avg_keyframe_gap),
               GST_TIME_ARGS (s->max_keyframe_gap));
         }
       } else {
-        g_print ("  no stats\n");
+        gst_print ("  no stats\n");
       }
 
       g_free (s->desc);
@@ -425,7 +446,7 @@ print_tag_foreach (const GstTagList * tags, const gchar * tag,
   else
     str = gst_value_serialize (&val);
 
-  g_print ("%*s%s: %s\n", 2 * depth, " ", gst_tag_get_nick (tag), str);
+  gst_print ("%*s%s: %s\n", 2 * depth, " ", gst_tag_get_nick (tag), str);
   g_free (str);
 
   g_value_unset (&val);
@@ -471,9 +492,6 @@ static guint signal_watch_hup_id;
 #endif
 #if defined(G_OS_UNIX) || defined(G_OS_WIN32)
 static guint signal_watch_intr_id;
-#if defined(G_OS_WIN32)
-static GstElement *intr_pipeline;
-#endif
 #endif
 
 #if defined(G_OS_UNIX) || defined(G_OS_WIN32)
@@ -522,47 +540,39 @@ hup_handler (gpointer user_data)
 static BOOL WINAPI
 w32_intr_handler (DWORD dwCtrlType)
 {
-  intr_handler ((gpointer) intr_pipeline);
-  intr_pipeline = NULL;
+  if (pipeline)
+    intr_handler ((gpointer) pipeline);
+
+  SetConsoleCtrlHandler (w32_intr_handler, FALSE);
+
   return TRUE;
 }
 #endif /* G_OS_WIN32 */
 #endif /* G_OS_UNIX */
 
-/* returns ELR_ERROR if there was an error
- * or ELR_INTERRUPT if we caught a keyboard interrupt
- * or ELR_NO_ERROR otherwise. */
-static EventLoopResult
-event_loop (GstElement * pipeline, gboolean blocking, gboolean do_progress,
-    GstState target_state)
+static void
+do_initial_play (GstElement * pipeline)
 {
-  GstBus *bus;
-  GstMessage *message = NULL;
-  EventLoopResult res = ELR_NO_ERROR;
-  gboolean buffering = FALSE, in_progress = FALSE;
-  gboolean prerolled = target_state != GST_STATE_PAUSED;
+  PRINT (_("Setting pipeline to PLAYING ...\n"));
 
-  bus = gst_element_get_bus (GST_ELEMENT (pipeline));
+  tfthen = gst_util_get_timestamp ();
 
-#ifdef G_OS_UNIX
-  signal_watch_intr_id =
-      g_unix_signal_add (SIGINT, (GSourceFunc) intr_handler, pipeline);
-  signal_watch_hup_id =
-      g_unix_signal_add (SIGHUP, (GSourceFunc) hup_handler, pipeline);
-#elif defined(G_OS_WIN32)
-  intr_pipeline = NULL;
-  if (SetConsoleCtrlHandler (w32_intr_handler, TRUE))
-    intr_pipeline = pipeline;
-#endif
+  if (gst_element_set_state (pipeline,
+          GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
+    gst_printerr (_("ERROR: pipeline doesn't want to play.\n"));
+    last_launch_code = LEC_STATE_CHANGE_FAILURE;
 
-  while (TRUE) {
-    message = gst_bus_poll (bus, GST_MESSAGE_ANY, blocking ? -1 : 0);
+    /* error message will be posted later */
+    return;
+  }
 
-    /* if the poll timed out, only when !blocking */
-    if (message == NULL)
-      goto exit;
+  target_state = GST_STATE_PLAYING;
+}
 
-    /* check if we need to dump messages to the console */
+static gboolean
+bus_handler (GstBus * bus, GstMessage * message, gpointer data)
+{
+  {
     if (messages) {
       GstObject *src_obj;
       const GstStructure *s;
@@ -618,10 +628,13 @@ event_loop (GstElement * pipeline, gboolean blocking, gboolean do_progress,
         gst_element_set_state (pipeline, GST_STATE_PLAYING);
         break;
       case GST_MESSAGE_EOS:{
-        waiting_eos = FALSE;
         PRINT (_("Got EOS from element \"%s\".\n"),
             GST_MESSAGE_SRC_NAME (message));
-        goto exit;
+
+        if (eos_on_shutdown)
+          PRINT (_("EOS received - stopping pipeline...\n"));
+        g_main_loop_quit (loop);
+        break;
       }
       case GST_MESSAGE_TAG:
         if (tags) {
@@ -701,17 +714,6 @@ event_loop (GstElement * pipeline, gboolean blocking, gboolean do_progress,
         g_free (name);
         break;
       }
-      case GST_MESSAGE_ERROR:{
-        /* dump graph on error */
-        GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
-            GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.error");
-
-        print_error_message (message);
-
-        /* we have an error */
-        res = ELR_ERROR;
-        goto exit;
-      }
       case GST_MESSAGE_STATE_CHANGED:{
         GstState old, new, pending;
 
@@ -721,9 +723,10 @@ event_loop (GstElement * pipeline, gboolean blocking, gboolean do_progress,
 
         gst_message_parse_state_changed (message, &old, &new, &pending);
 
-        /* if we reached the final target state, exit */
         if (target_state == GST_STATE_PAUSED && new == target_state) {
           prerolled = TRUE;
+
+          PRINT (_("Pipeline is PREROLLED ...\n"));
           /* ignore when we are buffering since then we mess with the states
            * ourselves. */
           if (buffering) {
@@ -734,7 +737,8 @@ event_loop (GstElement * pipeline, gboolean blocking, gboolean do_progress,
             PRINT (_("Prerolled, waiting for progress to finish...\n"));
             break;
           }
-          goto exit;
+
+          do_initial_play (pipeline);
         }
         /* else not an interesting message */
         break;
@@ -752,12 +756,17 @@ event_loop (GstElement * pipeline, gboolean blocking, gboolean do_progress,
         if (percent == 100) {
           /* a 100% message means buffering is done */
           buffering = FALSE;
+
+          if (target_state == GST_STATE_PAUSED) {
+            do_initial_play (pipeline);
+            break;
+          }
+
           /* if the desired state is playing, go back */
           if (target_state == GST_STATE_PLAYING) {
             PRINT (_("Done buffering, setting pipeline to PLAYING ...\n"));
             gst_element_set_state (pipeline, GST_STATE_PLAYING);
-          } else if (prerolled && !in_progress)
-            goto exit;
+          }
         } else {
           /* buffering busy */
           if (!buffering && target_state == GST_STATE_PLAYING) {
@@ -799,8 +808,26 @@ event_loop (GstElement * pipeline, gboolean blocking, gboolean do_progress,
           /* this application message is posted when we caught an interrupt and
            * we need to stop the pipeline. */
           PRINT (_("Interrupt: Stopping pipeline ...\n"));
-          res = ELR_INTERRUPT;
-          goto exit;
+          interrupting = TRUE;
+
+          if (eos_on_shutdown) {
+            if (waiting_eos) {
+              PRINT (_
+                  ("Interrupt while waiting for EOS - stopping pipeline...\n"));
+
+              g_main_loop_quit (loop);
+            } else {
+              PRINT (_
+                  ("EOS on shutdown enabled -- Forcing EOS on the pipeline\n"));
+              gst_element_send_event (pipeline, gst_event_new_eos ());
+
+              PRINT (_("Waiting for EOS...\n"));
+
+              waiting_eos = TRUE;
+            }
+          } else {
+            g_main_loop_quit (loop);
+          }
         }
         break;
       }
@@ -814,10 +841,7 @@ event_loop (GstElement * pipeline, gboolean blocking, gboolean do_progress,
         switch (type) {
           case GST_PROGRESS_TYPE_START:
           case GST_PROGRESS_TYPE_CONTINUE:
-            if (do_progress) {
-              in_progress = TRUE;
-              blocking = TRUE;
-            }
+            in_progress = TRUE;
             break;
           case GST_PROGRESS_TYPE_COMPLETE:
           case GST_PROGRESS_TYPE_CANCELED:
@@ -831,8 +855,9 @@ event_loop (GstElement * pipeline, gboolean blocking, gboolean do_progress,
         g_free (code);
         g_free (text);
 
-        if (do_progress && !in_progress && !buffering && prerolled)
-          goto exit;
+        if (!in_progress && prerolled && target_state == GST_STATE_PAUSED) {
+          do_initial_play (pipeline);
+        }
         break;
       }
       case GST_MESSAGE_ELEMENT:{
@@ -899,7 +924,7 @@ event_loop (GstElement * pipeline, gboolean blocking, gboolean do_progress,
           val_str = g_strdup ("(no value)");
         }
 
-        g_print ("%s: %s = %s\n", obj_name, name, val_str);
+        gst_print ("%s: %s = %s\n", obj_name, name, val_str);
         g_free (obj_name);
         g_free (val_str);
         break;
@@ -908,27 +933,9 @@ event_loop (GstElement * pipeline, gboolean blocking, gboolean do_progress,
         /* just be quiet by default */
         break;
     }
-    if (message)
-      gst_message_unref (message);
   }
-  g_assert_not_reached ();
 
-exit:
-  {
-    if (message)
-      gst_message_unref (message);
-    gst_object_unref (bus);
-#ifdef G_OS_UNIX
-    if (signal_watch_intr_id > 0)
-      g_source_remove (signal_watch_intr_id);
-    if (signal_watch_hup_id > 0)
-      g_source_remove (signal_watch_hup_id);
-#elif defined(G_OS_WIN32)
-    intr_pipeline = NULL;
-    SetConsoleCtrlHandler (w32_intr_handler, FALSE);
-#endif
-    return res;
-  }
+  return TRUE;
 }
 
 static GstBusSyncReply
@@ -968,23 +975,113 @@ bus_sync_handler (GstBus * bus, GstMessage * message, gpointer data)
         g_free (state_transition_name);
       }
       break;
+    case GST_MESSAGE_ERROR:{
+      /* dump graph on error */
+      GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
+          GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.error");
+
+      print_error_message (message);
+
+      if (target_state == GST_STATE_PAUSED) {
+        gst_printerr (_("ERROR: pipeline doesn't want to preroll.\n"));
+      } else if (interrupting) {
+        PRINT (_("An error happened while waiting for EOS\n"));
+      }
+
+      /* we have an error */
+      last_launch_code = LEC_ERROR;
+      g_main_loop_quit (loop);
+      break;
+    }
     default:
       break;
   }
   return GST_BUS_PASS;
 }
 
+static gboolean
+query_pipeline_position (gpointer user_data)
+{
+  gint64 pos = -1, dur = -1;
+  gboolean output_is_tty = GPOINTER_TO_INT (user_data);
+
+  if (buffering)
+    return G_SOURCE_CONTINUE;
+
+  gst_element_query_position (pipeline, GST_FORMAT_TIME, &pos);
+  gst_element_query_duration (pipeline, GST_FORMAT_TIME, &dur);
+
+  if (pos >= 0) {
+    gchar dstr[32], pstr[32];
+
+    /* FIXME: pretty print in nicer format */
+    g_snprintf (pstr, 32, "%" GST_TIME_FORMAT, GST_TIME_ARGS (pos));
+    pstr[9] = '\0';
+    g_snprintf (dstr, 32, "%" GST_TIME_FORMAT, GST_TIME_ARGS (dur));
+    dstr[9] = '\0';
+
+    if (dur > 0 && dur >= pos) {
+      gdouble percent;
+      percent = 100 * (gdouble) (pos) / dur;
+
+      gst_print ("%s / %s (%.1f %%)%c", pstr, dstr, percent,
+          output_is_tty ? '\r' : '\n');
+    } else
+      gst_print ("%s / %s%c", pstr, dstr, output_is_tty ? '\r' : '\n');
+  }
+
+  return G_SOURCE_CONTINUE;
+}
+
+#ifdef HAVE_WINMM
+static guint
+enable_winmm_timer_resolution (void)
+{
+  TIMECAPS time_caps;
+  guint resolution = 0;
+  MMRESULT res;
+
+  res = timeGetDevCaps (&time_caps, sizeof (TIMECAPS));
+  if (res != TIMERR_NOERROR) {
+    g_warning ("timeGetDevCaps() returned non-zero code %d", res);
+    return 0;
+  }
+
+  resolution = MIN (MAX (time_caps.wPeriodMin, 1), time_caps.wPeriodMax);
+  res = timeBeginPeriod (resolution);
+  if (res != TIMERR_NOERROR) {
+    g_warning ("timeBeginPeriod() returned non-zero code %d", res);
+    return 0;
+  }
+
+  PRINT (_("Use Windows high-resolution clock, precision: %u ms\n"),
+      resolution);
+
+  return resolution;
+}
+
+static void
+clear_winmm_timer_resolution (guint resolution)
+{
+  if (resolution == 0)
+    return;
+
+  timeEndPeriod (resolution);
+}
+#endif
+
 int
 main (int argc, char *argv[])
 {
   /* options */
   gboolean verbose = FALSE;
   gboolean no_fault = FALSE;
-  gboolean eos_on_shutdown = FALSE;
 #if 0
   gboolean check_index = FALSE;
 #endif
   gchar *savefile = NULL;
+  gboolean no_position = FALSE;
+  gboolean force_position = FALSE;
 #ifndef GST_DISABLE_OPTION_PARSING
   GOptionEntry options[] = {
     {"tags", 't', 0, G_OPTION_ARG_NONE, &tags,
@@ -1010,6 +1107,17 @@ main (int argc, char *argv[])
         N_("Gather and print index statistics"), NULL},
 #endif
     GST_TOOLS_GOPTION_VERSION,
+    {"no-position", '\0', 0, G_OPTION_ARG_NONE, &no_position,
+        N_("Do not print current position of pipeline. "
+              "If this option is unspecified, the position will be printed "
+              "when stdout is a TTY. "
+              "To enable printing position when stdout is not a TTY, "
+              "use \"force-position\" option"), NULL},
+    {"force-position", '\0', 0, G_OPTION_ARG_NONE, &force_position,
+          N_("Allow printing current position of pipeline even if "
+              "stdout is not a TTY. This option has no effect if "
+              "the \"no-position\" option is specified"),
+        NULL},
     {NULL}
   };
   GOptionContext *ctx;
@@ -1022,7 +1130,11 @@ main (int argc, char *argv[])
   gchar **argvn;
   GError *error = NULL;
   gulong deep_notify_id = 0;
-  gint res = 0;
+  guint bus_watch_id = 0;
+  GSource *position_source = NULL;
+#ifdef HAVE_WINMM
+  guint winmm_timer_resolution = 0;
+#endif
 
   free (malloc (8));            /* -lefence */
 
@@ -1088,8 +1200,9 @@ main (int argc, char *argv[])
     return 1;
   }
 
+  loop = g_main_loop_new (NULL, FALSE);
+
   if (!savefile) {
-    GstState state, pending;
     GstStateChangeReturn ret;
     GstBus *bus;
 
@@ -1104,6 +1217,23 @@ main (int argc, char *argv[])
       gst_bin_add (GST_BIN (real_pipeline), pipeline);
       pipeline = real_pipeline;
     }
+#ifdef HAVE_WINMM
+    /* Enable high-precision clock which will improve accuracy of various
+     * Windows timer APIs (e.g., Sleep()), and it will increase the precision
+     * of GstSystemClock as well
+     */
+
+    /* NOTE: Once timer resolution is updated via timeBeginPeriod(),
+     * application should undo it by calling timeEndPeriod()
+     *
+     * Prior to Windows 10, version 2004, timeBeginPeriod() affects global
+     * Windows setting (meaning that it will affect other processes),
+     * but starting with Windows 10, version 2004, this function no longer
+     * affects global timer resolution
+     */
+    winmm_timer_resolution = enable_winmm_timer_resolution ();
+#endif
+
     if (verbose) {
       deep_notify_id =
           gst_element_add_property_deep_notify_watch (pipeline, NULL, TRUE);
@@ -1127,6 +1257,7 @@ main (int argc, char *argv[])
 
     bus = gst_element_get_bus (pipeline);
     gst_bus_set_sync_handler (bus, bus_sync_handler, (gpointer) pipeline, NULL);
+    bus_watch_id = gst_bus_add_watch (bus, bus_handler, NULL);
     gst_object_unref (bus);
 
     PRINT (_("Setting pipeline to PAUSED ...\n"));
@@ -1134,9 +1265,8 @@ main (int argc, char *argv[])
 
     switch (ret) {
       case GST_STATE_CHANGE_FAILURE:
-        gst_printerr (_("ERROR: Pipeline doesn't want to pause.\n"));
-        res = -1;
-        event_loop (pipeline, FALSE, FALSE, GST_STATE_VOID_PENDING);
+        gst_printerr (_("Failed to set pipeline to PAUSED.\n"));
+        last_launch_code = LEC_STATE_CHANGE_FAILURE;
         goto end;
       case GST_STATE_CHANGE_NO_PREROLL:
         PRINT (_("Pipeline is live and does not need PREROLL ...\n"));
@@ -1144,108 +1274,58 @@ main (int argc, char *argv[])
         break;
       case GST_STATE_CHANGE_ASYNC:
         PRINT (_("Pipeline is PREROLLING ...\n"));
-        caught_error = event_loop (pipeline, TRUE, TRUE, GST_STATE_PAUSED);
-        if (caught_error) {
-          gst_printerr (_("ERROR: pipeline doesn't want to preroll.\n"));
-          res = caught_error;
-          goto end;
-        }
-        state = GST_STATE_PAUSED;
-        /* fallthrough */
-      case GST_STATE_CHANGE_SUCCESS:
-        PRINT (_("Pipeline is PREROLLED ...\n"));
+        break;
+      default:
         break;
     }
 
-    caught_error = event_loop (pipeline, FALSE, TRUE, GST_STATE_PLAYING);
-
-    if (caught_error) {
-      gst_printerr (_("ERROR: pipeline doesn't want to preroll.\n"));
-      res = caught_error;
-    } else {
-      GstClockTime tfthen, tfnow;
-      GstClockTimeDiff diff;
-
-      PRINT (_("Setting pipeline to PLAYING ...\n"));
+#ifdef G_OS_UNIX
+    signal_watch_intr_id =
+        g_unix_signal_add (SIGINT, (GSourceFunc) intr_handler, pipeline);
+    signal_watch_hup_id =
+        g_unix_signal_add (SIGHUP, (GSourceFunc) hup_handler, pipeline);
+#elif defined(G_OS_WIN32)
+    SetConsoleCtrlHandler (w32_intr_handler, TRUE);
+#endif
+    if (!no_position) {
+      gboolean output_is_tty = TRUE;
 
-      if (gst_element_set_state (pipeline,
-              GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
-        GstMessage *err_msg;
-        GstBus *bus;
+      if (!isatty (STDOUT_FILENO))
+        output_is_tty = FALSE;
 
-        gst_printerr (_("ERROR: pipeline doesn't want to play.\n"));
-        bus = gst_element_get_bus (pipeline);
-        if ((err_msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0))) {
-          print_error_message (err_msg);
-          gst_message_unref (err_msg);
-        }
-        gst_object_unref (bus);
-        res = -1;
-        goto end;
+      if (output_is_tty || (!output_is_tty && force_position)) {
+        position_source = g_timeout_source_new (100);
+        g_source_set_callback (position_source, query_pipeline_position,
+            GINT_TO_POINTER (output_is_tty), NULL);
+        g_source_attach (position_source, NULL);
       }
+    }
 
-      tfthen = gst_util_get_timestamp ();
-      caught_error = event_loop (pipeline, TRUE, FALSE, GST_STATE_PLAYING);
-      res = caught_error;
-      if (eos_on_shutdown && caught_error != ELR_NO_ERROR) {
-        gboolean ignore_errors;
-
-        waiting_eos = TRUE;
-        if (caught_error == ELR_INTERRUPT) {
-          PRINT (_("EOS on shutdown enabled -- Forcing EOS on the pipeline\n"));
-          gst_element_send_event (pipeline, gst_event_new_eos ());
-          ignore_errors = FALSE;
-        } else {
-          PRINT (_("EOS on shutdown enabled -- waiting for EOS after Error\n"));
-          ignore_errors = TRUE;
-        }
-        PRINT (_("Waiting for EOS...\n"));
+    /* playing state will be set on state-changed message handler */
+    g_main_loop_run (loop);
 
-        while (TRUE) {
-          caught_error = event_loop (pipeline, TRUE, FALSE, GST_STATE_PLAYING);
+    if (position_source) {
+      g_source_destroy (position_source);
+      g_source_unref (position_source);
+    }
 
-          if (caught_error == ELR_NO_ERROR) {
-            /* we got EOS */
-            PRINT (_("EOS received - stopping pipeline...\n"));
-            break;
-          } else if (caught_error == ELR_INTERRUPT) {
-            PRINT (_
-                ("Interrupt while waiting for EOS - stopping pipeline...\n"));
-            res = caught_error;
-            break;
-          } else if (caught_error == ELR_ERROR) {
-            if (!ignore_errors) {
-              PRINT (_("An error happened while waiting for EOS\n"));
-              res = caught_error;
-              break;
-            }
-          }
-        }
-      }
-      tfnow = gst_util_get_timestamp ();
+    {
+      GstClockTime tfnow;
+      GstClockTimeDiff diff;
 
-      diff = GST_CLOCK_DIFF (tfthen, tfnow);
+      if (GST_CLOCK_TIME_IS_VALID (tfthen)) {
+        tfnow = gst_util_get_timestamp ();
+        diff = GST_CLOCK_DIFF (tfthen, tfnow);
 
-      PRINT (_("Execution ended after %" GST_TIME_FORMAT "\n"),
-          GST_TIME_ARGS (diff));
+        PRINT (_("Execution ended after %" GST_TIME_FORMAT "\n"),
+            GST_TIME_ARGS (diff));
+      }
     }
 
-    PRINT (_("Setting pipeline to PAUSED ...\n"));
-    gst_element_set_state (pipeline, GST_STATE_PAUSED);
-    if (caught_error == ELR_NO_ERROR)
-      gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
-
-    /* iterate mainloop to process pending stuff */
-    while (g_main_context_iteration (NULL, FALSE));
-
     /* No need to see all those pad caps going to NULL etc., it's just noise */
     if (deep_notify_id != 0)
       g_signal_handler_disconnect (pipeline, deep_notify_id);
 
-    PRINT (_("Setting pipeline to READY ...\n"));
-    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);
@@ -1256,6 +1336,20 @@ main (int argc, char *argv[])
   end:
     PRINT (_("Setting pipeline to NULL ...\n"));
     gst_element_set_state (pipeline, GST_STATE_NULL);
+
+#ifdef G_OS_UNIX
+    if (signal_watch_intr_id > 0)
+      g_source_remove (signal_watch_intr_id);
+    if (signal_watch_hup_id > 0)
+      g_source_remove (signal_watch_hup_id);
+#endif
+    g_source_remove (bus_watch_id);
+    g_main_loop_unref (loop);
+
+#ifdef HAVE_WINMM
+    /* Undo timeBeginPeriod() if required */
+    clear_winmm_timer_resolution (winmm_timer_resolution);
+#endif
   }
 
   PRINT (_("Freeing pipeline ...\n"));
@@ -1263,5 +1357,5 @@ main (int argc, char *argv[])
 
   gst_deinit ();
 
-  return res;
+  return last_launch_code;
 }
index 5c57f85..597c1ba 100644 (file)
@@ -47,12 +47,16 @@ static GstClockTime last_ts = G_GUINT64_CONSTANT (0);
 static guint total_cpuload = 0;
 static gboolean have_cpuload = FALSE;
 
+static GPtrArray *plugin_stats = NULL;
+
 static gboolean have_latency = FALSE;
 static gboolean have_element_latency = FALSE;
 static gboolean have_element_reported_latency = FALSE;
 
 typedef struct
 {
+  /* display name of the element */
+  gchar *name;
   /* the number of latencies counted  */
   guint64 count;
   /* the total of all latencies */
@@ -61,6 +65,7 @@ typedef struct
   guint64 min;
   /* the max of all latencies */
   guint64 max;
+  GstClockTime first_latency_ts;
 } GstLatencyStats;
 
 typedef struct
@@ -119,26 +124,56 @@ typedef struct
   guint cpuload;
 } GstThreadStats;
 
+static const gchar *FACTORY_TYPES[] = {
+  "element",
+  "device-provider",
+  "typefind",
+  "dynamic-type",
+};
+
+#define N_FACTORY_TYPES G_N_ELEMENTS(FACTORY_TYPES)
+
+typedef struct
+{
+  gchar *name;
+
+  GPtrArray *factories[N_FACTORY_TYPES];
+} GstPluginStats;
+
 /* stats helper */
 
+static gint
+sort_latency_stats_by_first_ts (gconstpointer a, gconstpointer b)
+{
+  const GstLatencyStats *ls1 = a, *ls2 = b;
+
+  return (GST_CLOCK_DIFF (ls2->first_latency_ts, ls1->first_latency_ts));
+}
+
 static void
-latencies_foreach_print_stats (gchar * key, GstLatencyStats * ls, gpointer data)
+print_latency_stats (gpointer value, gpointer user_data)
 {
-  printf ("\t%s: mean=%" G_GUINT64_FORMAT " min=%" G_GUINT64_FORMAT " max=%"
-      G_GUINT64_FORMAT "\n", key, ls->total / ls->count, ls->min, ls->max);
+  GstLatencyStats *ls = value;
+
+  printf ("\t%s: mean=%" GST_TIME_FORMAT " min=%" GST_TIME_FORMAT " max=%"
+      GST_TIME_FORMAT "\n", ls->name, GST_TIME_ARGS (ls->total / ls->count),
+      GST_TIME_ARGS (ls->min), GST_TIME_ARGS (ls->max));
 }
 
 static void
 reported_latencies_foreach_print_stats (GstReportedLatency * rl, gpointer data)
 {
-  printf ("\t%s: min=%" G_GUINT64_FORMAT " max=%" G_GUINT64_FORMAT " ts=%"
-      GST_TIME_FORMAT "\n", rl->element, rl->min,
-      rl->max, GST_TIME_ARGS (rl->ts));
+  printf ("\t%s: min=%" GST_TIME_FORMAT " max=%" GST_TIME_FORMAT " ts=%"
+      GST_TIME_FORMAT "\n", rl->element, GST_TIME_ARGS (rl->min),
+      GST_TIME_ARGS (rl->max), GST_TIME_ARGS (rl->ts));
 }
 
 static void
 free_latency_stats (gpointer data)
 {
+  GstLatencyStats *ls = data;
+
+  g_free (ls->name);
   g_slice_free (GstLatencyStats, data);
 }
 
@@ -266,6 +301,36 @@ free_thread_stats (gpointer data)
   g_slice_free (GstThreadStats, data);
 }
 
+static GstPluginStats *
+new_plugin_stats (const gchar * plugin_name)
+{
+  GstPluginStats *plugin = g_slice_new (GstPluginStats);
+  guint i;
+
+  plugin->name = g_strdup (plugin_name);
+
+  for (i = 0; i < N_FACTORY_TYPES; i++)
+    plugin->factories[i] = g_ptr_array_new_with_free_func (g_free);
+
+  g_ptr_array_add (plugin_stats, plugin);
+
+  return plugin;
+}
+
+static void
+free_plugin_stats (gpointer data)
+{
+  GstPluginStats *plugin = data;
+  guint i;
+
+  g_free (plugin->name);
+
+  for (i = 0; i < N_FACTORY_TYPES; i++)
+    g_ptr_array_unref (plugin->factories[i]);
+
+  g_slice_free (GstPluginStats, data);
+}
+
 static void
 do_pad_stats (GstPadStats * stats, guint elem_ix, guint size, guint64 ts,
     guint64 buffer_ts, guint64 buffer_dur, GstBufferFlags buffer_flags)
@@ -474,17 +539,20 @@ do_proc_rusage_stats (GstStructure * s)
 }
 
 static void
-update_latency_table (GHashTable * table, const gchar * key, guint64 time)
+update_latency_table (GHashTable * table, const gchar * key, guint64 time,
+    GstClockTime ts)
 {
   /* Find the values in the hash table */
   GstLatencyStats *ls = g_hash_table_lookup (table, key);
   if (!ls) {
     /* Insert the new key if the value does not exist */
     ls = g_new0 (GstLatencyStats, 1);
+    ls->name = g_strdup (key);
     ls->count = 1;
     ls->total = time;
     ls->min = time;
     ls->max = time;
+    ls->first_latency_ts = ts;
     g_hash_table_insert (table, g_strdup (key), ls);
   } else {
     /* Otherwise update the existing value */
@@ -523,7 +591,7 @@ do_latency_stats (GstStructure * s)
       src, sink_element_id, sink_element, sink);
 
   /* Update the latency in the table */
-  update_latency_table (latencies, key, time);
+  update_latency_table (latencies, key, time, ts);
 
   /* Clean up */
   g_free (key);
@@ -552,7 +620,7 @@ do_element_latency_stats (GstStructure * s)
   key = g_strdup_printf ("%s.%s.%s", element_id, element, src);
 
   /* Update the latency in the table */
-  update_latency_table (element_latencies, key, time);
+  update_latency_table (element_latencies, key, time, ts);
 
   /* Clean up */
   g_free (key);
@@ -588,6 +656,48 @@ do_element_reported_latency (GstStructure * s)
   have_element_reported_latency = TRUE;
 }
 
+static void
+do_factory_used (GstStructure * s)
+{
+  const gchar *factory = NULL;
+  const gchar *factory_type = NULL;
+  const gchar *plugin_name = NULL;
+  GstPluginStats *plugin = NULL;
+  guint i, f;
+
+  factory = gst_structure_get_string (s, "factory");
+  factory_type = gst_structure_get_string (s, "factory-type");
+  plugin_name = gst_structure_get_string (s, "plugin");
+
+  if (!g_strcmp0 (plugin_name, "staticelements"))
+    return;
+
+  if (plugin_name == NULL || plugin_name[0] == 0)
+    plugin_name = "built-in";
+
+  for (f = 0; f < N_FACTORY_TYPES; f++)
+    if (!g_strcmp0 (factory_type, FACTORY_TYPES[f]))
+      break;
+  if (f == N_FACTORY_TYPES)
+    return;
+
+  for (i = 0; i < plugin_stats->len; i++) {
+    GstPluginStats *tmp_plugin = g_ptr_array_index (plugin_stats, i);
+    if (!strcmp (tmp_plugin->name, plugin_name)) {
+      plugin = tmp_plugin;
+      break;
+    }
+  }
+
+  if (plugin == NULL)
+    plugin = new_plugin_stats (plugin_name);
+
+  if (factory && factory[0] &&
+      !g_ptr_array_find_with_equal_func (plugin->factories[f], factory,
+          g_str_equal, NULL))
+    g_ptr_array_add (plugin->factories[f], g_strdup (factory));
+}
+
 /* reporting */
 
 static gint
@@ -673,22 +783,22 @@ print_element_stats (gpointer value, gpointer user_data)
 
     printf ("  %-45s:", fullname);
     if (stats->recv_buffers)
-      printf (" buffers in/out %7u", stats->recv_buffers);
+      g_print (" buffers in/out %7u", stats->recv_buffers);
     else
-      printf (" buffers in/out %7s", "-");
+      g_print (" buffers in/out %7s", "-");
     if (stats->sent_buffers)
-      printf ("/%7u", stats->sent_buffers);
+      g_print ("/%7u", stats->sent_buffers);
     else
-      printf ("/%7s", "-");
+      g_print ("/%7s", "-");
     if (stats->recv_bytes)
-      printf (" bytes in/out %12" G_GUINT64_FORMAT, stats->recv_bytes);
+      g_print (" bytes in/out %12" G_GUINT64_FORMAT, stats->recv_bytes);
     else
-      printf (" bytes in/out %12s", "-");
+      g_print (" bytes in/out %12s", "-");
     if (stats->sent_bytes)
-      printf ("/%12" G_GUINT64_FORMAT, stats->sent_bytes);
+      g_print ("/%12" G_GUINT64_FORMAT, stats->sent_bytes);
     else
       printf ("/%12s", "-");
-    printf (" first activity %" GST_TIME_FORMAT ", "
+    g_print (" first activity %" GST_TIME_FORMAT ", "
         " ev/msg/qry sent %5u/%5u/%5u\n", GST_TIME_ARGS (stats->first_ts),
         stats->num_events, stats->num_messages, stats->num_queries);
   }
@@ -753,7 +863,7 @@ sort_element_stats_by_first_activity (gconstpointer es1, gconstpointer es2)
 static void
 sort_bin_stats (gpointer value, gpointer user_data)
 {
-  if (((GstElementStats *) value)->is_bin) {
+  if (value != NULL && ((GstElementStats *) value)->is_bin) {
     GSList **list = user_data;
 
     *list =
@@ -765,7 +875,7 @@ sort_bin_stats (gpointer value, gpointer user_data)
 static void
 sort_element_stats (gpointer value, gpointer user_data)
 {
-  if (!(((GstElementStats *) value)->is_bin)) {
+  if (value != NULL && !(((GstElementStats *) value)->is_bin)) {
     GSList **list = user_data;
 
     *list =
@@ -802,14 +912,16 @@ static gboolean
 init (void)
 {
   /* compile the parser regexps */
-  /* 0:00:00.004925027 31586      0x1c5c600 DEBUG           GST_REGISTRY gstregistry.c:463:gst_registry_add_plugin:<registry0> adding plugin 0x1c79160 for filename "/usr/lib/gstreamer-1.0/libgstxxx.so" */
+  /* 0:00:00.004925027 31586      0x1c5c600 DEBUG           GST_REGISTRY gstregistry.c:463:gst_registry_add_plugin:<registry0> adding plugin 0x1c79160 for filename "/usr/lib/gstreamer-1.0/libgstxxx.so"
+   * 0:00:02.719599000 35292 000001C031A49C60 DEBUG             GST_TRACER gsttracer.c:162:gst_tracer_register:<registry0> update existing feature 000001C02F9843C0 (latency)
+   */
   raw_log = g_regex_new (
       /* 1: ts */
       "^([0-9:.]+) +"
       /* 2: pid */
       "([0-9]+) +"
       /* 3: thread */
-      "(0x[0-9a-fA-F]+) +"
+      "(0?x?[0-9a-fA-F]+) +"
       /* 4: level */
       "([A-Z]+) +"
       /* 5: category */
@@ -852,6 +964,8 @@ init (void)
       free_latency_stats);
   element_reported_latencies = g_queue_new ();
 
+  plugin_stats = g_ptr_array_new_with_free_func (free_plugin_stats);
+
   return TRUE;
 }
 
@@ -880,33 +994,53 @@ done (void)
     element_reported_latencies = NULL;
   }
 
+  g_clear_pointer (&plugin_stats, g_ptr_array_unref);
+
   if (raw_log)
     g_regex_unref (raw_log);
   if (ansi_log)
     g_regex_unref (ansi_log);
 }
 
+static gint
+compare_plugin_stats (gconstpointer a, gconstpointer b)
+{
+  const GstPluginStats *plugin_a = *(GstPluginStats **) a;
+  const GstPluginStats *plugin_b = *(GstPluginStats **) b;
+
+  return strcmp (plugin_a->name, plugin_b->name);
+}
+
+static gint
+compare_string (gconstpointer a, gconstpointer b)
+{
+  const char *str_a = *(const char **) a;
+  const char *str_b = *(const char **) b;
+
+  return strcmp (str_a, str_b);
+}
+
 static void
 print_stats (void)
 {
   guint num_threads = g_hash_table_size (threads);
 
   /* print overall stats */
-  puts ("\nOverall Statistics:");
-  printf ("Number of Threads: %u\n", num_threads);
-  printf ("Number of Elements: %u\n", num_elements - num_bins);
-  printf ("Number of Bins: %u\n", num_bins);
-  printf ("Number of Pads: %u\n", num_pads - num_ghostpads);
-  printf ("Number of GhostPads: %u\n", num_ghostpads);
-  printf ("Number of Buffers passed: %" G_GUINT64_FORMAT "\n", num_buffers);
-  printf ("Number of Events sent: %" G_GUINT64_FORMAT "\n", num_events);
-  printf ("Number of Message sent: %" G_GUINT64_FORMAT "\n", num_messages);
-  printf ("Number of Queries sent: %" G_GUINT64_FORMAT "\n", num_queries);
-  printf ("Time: %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (last_ts));
+  g_print ("\nOverall Statistics:\n");
+  g_print ("Number of Threads: %u\n", num_threads);
+  g_print ("Number of Elements: %u\n", num_elements - num_bins);
+  g_print ("Number of Bins: %u\n", num_bins);
+  g_print ("Number of Pads: %u\n", num_pads - num_ghostpads);
+  g_print ("Number of GhostPads: %u\n", num_ghostpads);
+  g_print ("Number of Buffers passed: %" G_GUINT64_FORMAT "\n", num_buffers);
+  g_print ("Number of Events sent: %" G_GUINT64_FORMAT "\n", num_events);
+  g_print ("Number of Message sent: %" G_GUINT64_FORMAT "\n", num_messages);
+  g_print ("Number of Queries sent: %" G_GUINT64_FORMAT "\n", num_queries);
+  g_print ("Time: %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (last_ts));
   if (have_cpuload) {
-    printf ("Avg CPU load: %4.1f %%\n", (gfloat) total_cpuload / 10.0);
+    g_print ("Avg CPU load: %4.1f %%\n", (gfloat) total_cpuload / 10.0);
   }
-  puts ("");
+  g_print ("\n");
 
   /* thread stats */
   if (num_threads) {
@@ -942,7 +1076,7 @@ print_stats (void)
     /* attribute bin stats to parent-bins */
     for (i = 0; i < num_elements; i++) {
       GstElementStats *stats = g_ptr_array_index (elements, i);
-      if (stats->is_bin) {
+      if (stats != NULL && stats->is_bin) {
         g_hash_table_insert (accum_bins, GUINT_TO_POINTER (i), stats);
       }
     }
@@ -959,18 +1093,28 @@ print_stats (void)
 
   /* latency stats */
   if (have_latency) {
+    GList *list = NULL;
+
     puts ("Latency Statistics:");
-    g_hash_table_foreach (latencies, (GHFunc) latencies_foreach_print_stats,
-        NULL);
+    list = g_hash_table_get_values (latencies);
+    /* Sort by first activity */
+    list = g_list_sort (list, sort_latency_stats_by_first_ts);
+    g_list_foreach (list, print_latency_stats, NULL);
     puts ("");
+    g_list_free (list);
   }
 
   /* element latency stats */
   if (have_element_latency) {
+    GList *list = NULL;
+
     puts ("Element Latency Statistics:");
-    g_hash_table_foreach (element_latencies,
-        (GHFunc) latencies_foreach_print_stats, NULL);
+    list = g_hash_table_get_values (element_latencies);
+    /* Sort by first activity */
+    list = g_list_sort (list, sort_latency_stats_by_first_ts);
+    g_list_foreach (list, print_latency_stats, NULL);
     puts ("");
+    g_list_free (list);
   }
 
   /* element reported latency stats */
@@ -980,6 +1124,43 @@ print_stats (void)
         (GFunc) reported_latencies_foreach_print_stats, NULL);
     puts ("");
   }
+
+  if (plugin_stats->len > 0) {
+    guint i, j, f;
+
+    g_ptr_array_sort (plugin_stats, compare_plugin_stats);
+
+    printf ("Plugins used: ");
+    for (i = 0; i < plugin_stats->len; i++) {
+      GstPluginStats *ps = g_ptr_array_index (plugin_stats, i);
+      printf ("%s%s", i == 0 ? "" : ";", ps->name);
+    }
+    printf ("\n");
+
+    for (f = 0; f < N_FACTORY_TYPES; f++) {
+      gboolean first = TRUE;
+
+      printf ("%c%ss: ", g_ascii_toupper (FACTORY_TYPES[f][0]),
+          FACTORY_TYPES[f] + 1);
+      for (i = 0; i < plugin_stats->len; i++) {
+        GstPluginStats *ps = g_ptr_array_index (plugin_stats, i);
+
+        if (ps->factories[f]->len > 0) {
+          printf ("%s%s:", first ? "" : ";", ps->name);
+          first = FALSE;
+
+          g_ptr_array_sort (ps->factories[f], compare_string);
+
+          for (j = 0; j < ps->factories[f]->len; j++) {
+            const gchar *factory = g_ptr_array_index (ps->factories[f], j);
+
+            printf ("%s%s", j == 0 ? "" : ",", factory);
+          }
+        }
+      }
+      printf ("\n");
+    }
+  }
 }
 
 static void
@@ -1040,6 +1221,8 @@ collect_stats (const gchar * filename)
                   do_element_latency_stats (s);
                 } else if (!strcmp (name, "element-reported-latency")) {
                   do_element_reported_latency (s);
+                } else if (!strcmp (name, "factory-used")) {
+                  do_factory_used (s);
                 } else {
                   // TODO(ensonic): parse the xxx.class log lines
                   if (!g_str_has_suffix (data, ".class")) {
@@ -1050,7 +1233,9 @@ collect_stats (const gchar * filename)
               } else {
                 GST_WARNING ("unknown log entry: '%s'", data);
               }
+              g_free (data);
             }
+            g_free (level);
           } else {
             if (*line) {
               GST_WARNING ("foreign log entry: %s:%d:'%s'", filename, lnr,
index 1e33811..e22721d 100644 (file)
@@ -1,19 +1,37 @@
 tools = ['gst-inspect', 'gst-stats', 'gst-typefind']
 
+extra_launch_dep = []
+extra_launch_arg = []
+
 if gst_parse
+  if host_system == 'windows'
+    winmm_lib = cc.find_library('winmm', required: false)
+    if winmm_lib.found() and cc.has_header('timeapi.h')
+      extra_launch_dep += [winmm_lib]
+      extra_launch_arg += ['-DHAVE_WINMM']
+    endif
+  endif
+
   tools += ['gst-launch']
 endif
 
 foreach tool : tools
   exe_name = '@0@-@1@'.format(tool, apiversion)
   src_file = '@0@.c'.format(tool)
+  extra_deps = []
+  extra_c_args = []
+
+  if tool == 'gst-launch'
+    extra_deps += extra_launch_dep
+    extra_c_args += extra_launch_arg
+  endif
 
   executable(exe_name,
     src_file,
     install: true,
     include_directories : [configinc],
-    dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep],
-    c_args: gst_c_args,
+    dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep] + extra_deps,
+    c_args: gst_c_args + extra_c_args,
   )
 
   man_page = '@0@-1.0.1'.format(tool)
index 6bed5ac..fb24718 100644 (file)
@@ -31,7 +31,7 @@
 /*
  * This is a kind of hacky way to make all the tools use the same version code.
  * If anyone knows a less hacky way to get this done, feel free to implement it.
- * 
+ *
  * It also includes all the files that all the tools require.
  */