Merge remote-tracking branch 'origin/master' into 0.11
authorTim-Philipp Müller <tim.muller@collabora.co.uk>
Thu, 8 Dec 2011 01:19:03 +0000 (01:19 +0000)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Thu, 8 Dec 2011 01:19:03 +0000 (01:19 +0000)
Conflicts:
ext/alsa/gstalsadeviceprobe.c
ext/alsa/gstalsamixer.c
ext/pango/gsttextoverlay.c
ext/pango/gsttextoverlay.h
gst-libs/gst/audio/gstaudiobasesink.c
gst-libs/gst/audio/gstaudioringbuffer.c
gst-libs/gst/audio/gstaudiosrc.c
gst-libs/gst/video/Makefile.am
gst-libs/gst/video/video.c
gst/encoding/gststreamcombiner.c
gst/encoding/gststreamsplitter.c
gst/playback/gstplaybasebin.c
gst/playback/gststreamsynchronizer.c
gst/playback/gstsubtitleoverlay.c
gst/playback/gsturidecodebin.c
sys/xvimage/xvimagesink.c
tests/examples/Makefile.am
win32/common/libgstvideo.def

Video overlay composition disabled for now, needs
porting to buffer meta.

44 files changed:
1  2 
configure.ac
docs/libs/gst-plugins-base-libs-docs.sgml
docs/libs/gst-plugins-base-libs-sections.txt
ext/alsa/gstalsamixer.c
ext/alsa/gstalsamixer.h
ext/alsa/gstalsasink.c
ext/alsa/gstalsasrc.c
ext/ogg/gstoggdemux.c
gst-libs/gst/Makefile.am
gst-libs/gst/app/gstappsink.c
gst-libs/gst/app/gstappsrc.c
gst-libs/gst/audio/gstaudiobasesink.c
gst-libs/gst/audio/gstaudiodecoder.c
gst-libs/gst/audio/gstaudioencoder.c
gst-libs/gst/audio/gstaudioringbuffer.c
gst-libs/gst/audio/gstaudiosink.c
gst-libs/gst/audio/gstaudiosrc.c
gst-libs/gst/pbutils/gstdiscoverer.c
gst-libs/gst/rtsp/gstrtspconnection.c
gst-libs/gst/video/convertframe.c
gst-libs/gst/video/videooverlay.c
gst/playback/gstdecodebin.c
gst/playback/gstdecodebin2.c
gst/playback/gstplaybin2.c
gst/playback/gstplaysink.c
gst/playback/gstplaysinkconvertbin.c
gst/playback/gststreamsynchronizer.c
gst/playback/gstsubtitleoverlay.c
gst/playback/gsturidecodebin.c
gst/tcp/gstmultifdsink.c
gst/videorate/gstvideorate.c
sys/ximage/ximagesink.c
sys/xvimage/xvimagesink.c
tests/check/libs/video.c
tests/examples/Makefile.am
tests/examples/encoding/encoding.c
tests/examples/overlay/gtk-videooverlay.c
tests/examples/overlay/qt-videooverlay.cpp
tests/examples/seek/jsseek.c
tests/examples/seek/scrubby.c
tests/examples/seek/seek.c
tests/icles/test-colorkey.c
tests/icles/test-videooverlay.c
tools/gst-discoverer.c

diff --combined configure.ac
@@@ -5,7 -5,7 +5,7 @@@ dnl please read gstreamer/docs/random/a
  dnl initialize autoconf
  dnl releases only do -Wall, git and prerelease does -Werror too
  dnl use a three digit version number for releases, and four for git/prerelease
 -AC_INIT(GStreamer Base Plug-ins, 0.10.35.1,
 +AC_INIT(GStreamer Base Plug-ins, 0.11.1.1,
      http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer,
      gst-plugins-base)
  
@@@ -40,7 -40,7 +40,7 @@@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_R
  dnl our libraries and install dirs use major.minor as a version
  GST_MAJORMINOR=$PACKAGE_VERSION_MAJOR.$PACKAGE_VERSION_MINOR
  dnl we override it here if we need to for the release candidate of new series
 -GST_MAJORMINOR=0.10
 +GST_MAJORMINOR=0.11
  AC_SUBST(GST_MAJORMINOR)
  
  dnl CURRENT, REVISION, AGE
@@@ -49,7 -49,7 +49,7 @@@ dnl - interfaces added/removed/changed 
  dnl - interfaces added -> increment AGE
  dnl - interfaces removed -> AGE = 0
  dnl sets GST_LT_LDFLAGS
 -AS_LIBTOOL(GST, 24, 0, 24)
 +AS_LIBTOOL(GST, 26, 0, 0)
  
  dnl FIXME: this macro doesn't actually work;
  dnl the generated libtool script has no support for the listed tags.
@@@ -60,7 -60,7 +60,7 @@@ AC_LIBTOOL_WIN32_DL
  AM_PROG_LIBTOOL
  
  dnl *** required versions of GStreamer stuff ***
 -GST_REQ=0.10.35.1
 +GST_REQ=0.11.1
  
  dnl *** autotools stuff ****
  
@@@ -171,6 -171,10 +171,6 @@@ dnl *** checks for header files **
  dnl check if we have ANSI C header files
  AC_HEADER_STDC
  
 -dnl used in gst/ffmpegcolorspace/mem.c
 -dnl FIXME: could be fixed by redefining av_malloc and av_free to GLib's
 -AC_CHECK_HEADERS([malloc.h])
 -
  ac_cppflags_save="$CPPFLAGS"
  CPPFLAGS="`$PKG_CONFIG --cflags libxml-2.0`"
  AC_COMPILE_IFELSE(
@@@ -185,7 -189,7 +185,7 @@@ CPPFLAGS="$ac_cppflags_save
  AM_CONDITIONAL(HAVE_LIBXML_HTML, test "x$HAVE_LIBXML_HTML" = "xyes")
  
  dnl used in gst/tcp
- AC_CHECK_HEADERS([sys/socket.h], 
+ AC_CHECK_HEADERS([sys/socket.h],
    HAVE_SYS_SOCKET_H="yes", HAVE_SYS_SOCKET_H="no")
  AM_CONDITIONAL(HAVE_SYS_SOCKET_H, test "x$HAVE_SYS_SOCKET_H" = "xyes")
  
@@@ -209,6 -213,9 +209,6 @@@ LIBS="$save_libs
  dnl used in gst-libs/gst/pbutils and associated unit test
  AC_CHECK_HEADERS([process.h sys/types.h sys/wait.h sys/stat.h])
  
 -AC_CHECK_HEADERS([xmmintrin.h emmintrin.h])
 -
 -dnl ffmpegcolorspace includes _stdint.h
  dnl also, Windows does not have long long
  AX_CREATE_STDINT_H
  
@@@ -237,7 -244,7 +237,7 @@@ dnl check for fseeko(
  AC_FUNC_FSEEKO
  
  dnl Check for fast float to int casting as defined in C99
 -dnl used in gst-libs/gst/floatcast/floatcast.h
 +dnl used to be used in gst-libs/gst/floatcast/floatcast.h (FIXME: still needed?)
  save_libs=$LIBS
  LIBS="$LIBS $LIBM"
  AC_C99_FUNC_LRINT
@@@ -254,7 -261,7 +254,7 @@@ AC_CHECK_FUNC(gethostbyname,,[AC_CHECK_
  dnl *** checks for dependency libraries ***
  
  dnl GLib is required
 -AG_GST_GLIB_CHECK([2.24])
 +AG_GST_GLIB_CHECK([2.26])
  
  ORC_CHECK([0.4.11])
  
@@@ -412,7 -419,7 +412,7 @@@ AG_GST_CHECK_PLUGIN(audioconvert
  AG_GST_CHECK_PLUGIN(audiorate)
  AG_GST_CHECK_PLUGIN(audiotestsrc)
  AG_GST_CHECK_PLUGIN(encoding)
 -AG_GST_CHECK_PLUGIN(ffmpegcolorspace)
 +AG_GST_CHECK_PLUGIN(videoconvert)
  AG_GST_CHECK_PLUGIN(gdp)
  AG_GST_CHECK_PLUGIN(playback)
  AG_GST_CHECK_PLUGIN(audioresample)
@@@ -424,9 -431,11 +424,9 @@@ AG_GST_CHECK_PLUGIN(videorate
  AG_GST_CHECK_PLUGIN(videoscale)
  AG_GST_CHECK_PLUGIN(volume)
  
 -dnl check for gstreamer core features (subsystems)
 -dnl FIXME: this assumes srcdir == builddir for uninstalled setups
 -GST_CONFIGPATH=`$PKG_CONFIG --variable=includedir gstreamer-0.10`"/gst/gstconfig.h"
 -AG_GST_PARSE_SUBSYSTEM_DISABLES($GST_CONFIGPATH)
 -AM_CONDITIONAL(USE_XML, test $GST_DISABLE_XML != "1")
 +dnl FIXME 0.11: check for libxml, split subparse and move libxml parts to ext/
 +AM_CONDITIONAL(USE_XML, false)
 +AC_DEFINE([GST_DISABLE_XML], [1], [set to disable libxml2-dependent code in subparse])
  
  dnl disable plug-ins that require libxml2's HTML support if it is not available
  if test "x$HAVE_LIBXML_HTML" != "xyes"; then
@@@ -537,7 -546,7 +537,7 @@@ AG_GST_CHECK_FEATURE(X, [X libraries an
    CFLAGS="$ac_cflags_save"
    CPPFLAGS="$ac_cppflags_save"
  ])
-   
  dnl Check for Xv extension
  translit(dnm, m, l) AM_CONDITIONAL(USE_XVIDEO, true)
  AG_GST_CHECK_FEATURE(XVIDEO, [X11 XVideo extensions],
@@@ -549,26 -558,71 +549,26 @@@ dnl check for X Sh
  translit(dnm, m, l) AM_CONDITIONAL(USE_XSHM, true)
  AG_GST_CHECK_FEATURE(XSHM, [X Shared Memory extension], , [
    if test x$HAVE_X = xyes; then
-     AC_CHECK_LIB(Xext, XShmAttach, 
+     AC_CHECK_LIB(Xext, XShmAttach,
                 HAVE_XSHM="yes", HAVE_XSHM="no",
-                $X_LIBS) 
+                $X_LIBS)
      if test "x$HAVE_XSHM" = "xyes"; then
        XSHM_LIBS="-lXext"
      else
        dnl On AIX, it is in XextSam instead, but we still need -lXext
-       AC_CHECK_LIB(XextSam, XShmAttach, 
+       AC_CHECK_LIB(XextSam, XShmAttach,
                   HAVE_XSHM="yes", HAVE_XSHM="no",
-                  $X_LIBS) 
+                  $X_LIBS)
        if test "x$HAVE_XSHM" = "xyes"; then
        XSHM_LIBS="-lXext -lXextSam"
        fi
      fi
    fi
- ], , [ 
-   AC_SUBST(HAVE_XSHM) 
-   AC_SUBST(XSHM_LIBS) 
+ ], , [
+   AC_SUBST(HAVE_XSHM)
+   AC_SUBST(XSHM_LIBS)
  ])
  
 -dnl v4l/v4l2 checks have been moved down because they require X
 -
 -dnl *** Video 4 Linux ***
 -dnl for information about the header/define, see sys/v4l/gstv4lelement.h
 -dnl renamed to GST_V4L in accordance with V4L2 below
 -translit(dnm, m, l) AM_CONDITIONAL(USE_GST_V4L, true)
 -AG_GST_CHECK_FEATURE(GST_V4L, [Video 4 Linux], video4linux, [
 -  AC_CHECK_DECL(VID_TYPE_MPEG_ENCODER, HAVE_GST_V4L="yes", HAVE_GST_V4L="no", [
 -#include <sys/types.h>
 -#define _LINUX_TIME_H
 -#define __user
 -#include <linux/videodev.h>
 -  ])
 -
 -  dnl we can build v4l without Xv, but then we won't have XOverlay support
 -  if test "x$HAVE_GST_V4L" = "xyes" -a "x$HAVE_XVIDEO" != "xyes"
 -  then
 -    AC_MSG_NOTICE([NO XVIDEO FOUND, VIDEO4LINUX WILL BE BUILT])
 -    AC_MSG_NOTICE([WITHOUT XOVERLAY SUPPORT])
 -  fi
 -])
 -
 -# Optional gudev for device probing
 -AC_ARG_WITH([gudev],
 -  AC_HELP_STRING([--with-gudev],
 -    [device detection with gudev]),
 -  [],
 -  [with_gudev=check])
 -if test x$HAVE_GST_V4L = xyes; then
 -  if test x$with_gudev != xno; then
 -      PKG_CHECK_MODULES(GUDEV, [ gudev-1.0 >= 143 ],
 -          [ have_gudev=yes
 -            AC_DEFINE(HAVE_GUDEV, 1,
 -               [Whether gudev is available for device detection])
 -            AC_DEFINE([G_UDEV_API_IS_SUBJECT_TO_CHANGE], 1, [I know the API is subject to change.])
 -          ], [
 -          have_gudev=no
 -          ])
 -  else
 -    have_gudev=no
 -  fi
 -fi
 -AC_SUBST(GUDEV_CFLAGS)
 -AC_SUBST(GUDEV_LIBS)
 -
  dnl *** ext plug-ins ***
  dnl keep this list sorted alphabetically !
  
@@@ -597,17 -651,17 +597,17 @@@ AG_GST_CHECK_FEATURE(CDPARANOIA, [CDPar
    PKG_CHECK_MODULES(CDPARANOIA, cdparanoia-3 >= 10.2, [
      HAVE_CDPARANOIA="yes"
    ], [
-     AG_GST_CHECK_LIBHEADER(CDPARANOIA, cdda_interface, 
-                         cdda_open, -lm, 
-                         cdda_interface.h, 
+     AG_GST_CHECK_LIBHEADER(CDPARANOIA, cdda_interface,
+                         cdda_open, -lm,
+                         cdda_interface.h,
                          CDPARANOIA_LIBS="-lcdda_interface -lcdda_paranoia"
                          HEADER_DIR="no"
                          FOUND_CDPARANOIA="yes")
      if test "x$FOUND_CDPARANOIA" != "xyes";
      then
-       AG_GST_CHECK_LIBHEADER(CDPARANOIA, cdda_interface, 
-                           cdda_open, -lm, 
-                           cdda/cdda_interface.h, 
+       AG_GST_CHECK_LIBHEADER(CDPARANOIA, cdda_interface,
+                           cdda_open, -lm,
+                           cdda/cdda_interface.h,
                            CDPARANOIA_LIBS="-lcdda_interface -lcdda_paranoia"
                            HEADER_DIR="yes"
                            FOUND_CDPARANOIA="yes")
@@@ -633,6 -687,22 +633,6 @@@ dnl FIXME : add second check somehow i
  dnl AC_CHECK_LIB(cdda_paranoia, paranoia_init, : , HAVE_CDPARANOIA=no, -lcdda_interface )
  dnl AC_CHECK_HEADER(cdda_paranoia.h, :, HAVE_CDPARANOIA=no)
  
 -dnl *** GNOME VFS ***
 -translit(dnm, m, l) AM_CONDITIONAL(USE_GNOME_VFS, true)
 -AG_GST_CHECK_FEATURE(GNOME_VFS, [GNOME VFS], gnomevfs, [
 -  PKG_CHECK_MODULES(GNOME_VFS, gnome-vfs-2.0, [
 -      HAVE_GNOME_VFS="yes"
 -      AC_SUBST(GNOME_VFS_CFLAGS)
 -      AC_SUBST(GNOME_VFS_LIBS)
 -      GNOME_VFS_MODULES_DIR="`$PKG_CONFIG --variable=modulesdir gnome-vfs-2.0`"
 -      AC_DEFINE_UNQUOTED(GNOME_VFS_MODULES_DIR, "$GNOME_VFS_MODULES_DIR",
 -             [The GnomeVFS modules directory.])
 -    ],[
 -      HAVE_GNOME_VFS="no"
 -    ]
 -    )
 -])
 -
  dnl *** ivorbis ***
  dnl AM_PATH_IVORBIS only takes two options
  translit(dnm, m, l) AM_CONDITIONAL(USE_IVORBIS, true)
@@@ -761,6 -831,7 +761,6 @@@ dnl but we still need to set the condit
  AM_CONDITIONAL(USE_ALSA, false)
  AM_CONDITIONAL(USE_CDPARANOIA, false)
  AM_CONDITIONAL(USE_GIO, false)
 -AM_CONDITIONAL(USE_GNOME_VFS, false)
  AM_CONDITIONAL(USE_IVORBIS, false)
  AM_CONDITIONAL(USE_LIBVISUAL, false)
  AM_CONDITIONAL(USE_OGG, false)
@@@ -823,7 -894,6 +823,7 @@@ AC_SUBST(GST_PLUGINS_BASE_CFLAGS
  
  dnl FIXME: do we want to rename to GST_ALL_* ?
  dnl add GST_OPTION_CFLAGS, but overridable
 +GST_CFLAGS="$GST_CFLAGS -DGST_USE_UNSTABLE_API"
  GST_CXXFLAGS="$GLIB_CFLAGS $GST_CFLAGS \$(GLIB_EXTRA_CFLAGS) \$(GST_OPTION_CXXFLAGS)"
  GST_CFLAGS="$GLIB_CFLAGS $GST_CFLAGS \$(GLIB_EXTRA_CFLAGS) \$(GST_OPTION_CFLAGS)"
  AC_SUBST(GST_CFLAGS)
@@@ -864,7 -934,7 +864,7 @@@ gst/audioconvert/Makefil
  gst/audiorate/Makefile
  gst/audiotestsrc/Makefile
  gst/encoding/Makefile
 -gst/ffmpegcolorspace/Makefile
 +gst/videoconvert/Makefile
  gst/gdp/Makefile
  gst/playback/Makefile
  gst/audioresample/Makefile
@@@ -878,9 -948,11 +878,9 @@@ gst/volume/Makefil
  sys/Makefile
  sys/ximage/Makefile
  sys/xvimage/Makefile
 -sys/v4l/Makefile
  ext/Makefile
  ext/alsa/Makefile
  ext/cdparanoia/Makefile
 -ext/gnomevfs/Makefile
  ext/gio/Makefile
  ext/libvisual/Makefile
  ext/ogg/Makefile
@@@ -891,8 -963,11 +891,8 @@@ gst-libs/Makefil
  gst-libs/gst/Makefile
  gst-libs/gst/audio/Makefile
  gst-libs/gst/app/Makefile
 -gst-libs/gst/cdda/Makefile
  gst-libs/gst/fft/Makefile
 -gst-libs/gst/floatcast/Makefile
  gst-libs/gst/interfaces/Makefile
 -gst-libs/gst/netbuffer/Makefile
  gst-libs/gst/riff/Makefile
  gst-libs/gst/rtp/Makefile
  gst-libs/gst/rtsp/Makefile
@@@ -907,10 -982,16 +907,10 @@@ pkgconfig/gstreamer-audio.p
  pkgconfig/gstreamer-audio-uninstalled.pc
  pkgconfig/gstreamer-app.pc
  pkgconfig/gstreamer-app-uninstalled.pc
 -pkgconfig/gstreamer-cdda.pc
 -pkgconfig/gstreamer-cdda-uninstalled.pc
  pkgconfig/gstreamer-fft.pc
  pkgconfig/gstreamer-fft-uninstalled.pc
 -pkgconfig/gstreamer-floatcast.pc
 -pkgconfig/gstreamer-floatcast-uninstalled.pc
  pkgconfig/gstreamer-interfaces.pc
  pkgconfig/gstreamer-interfaces-uninstalled.pc
 -pkgconfig/gstreamer-netbuffer.pc
 -pkgconfig/gstreamer-netbuffer-uninstalled.pc
  pkgconfig/gstreamer-pbutils.pc
  pkgconfig/gstreamer-pbutils-uninstalled.pc
  pkgconfig/gstreamer-riff.pc
@@@ -934,11 -1015,13 +934,12 @@@ tests/examples/app/Makefil
  tests/examples/audio/Makefile
  tests/examples/dynamic/Makefile
  tests/examples/encoding/Makefile
+ tests/examples/fft/Makefile
  tests/examples/gio/Makefile
  tests/examples/overlay/Makefile
  tests/examples/seek/Makefile
  tests/examples/snapshot/Makefile
  tests/examples/playrec/Makefile
 -tests/examples/v4l/Makefile
  tests/files/Makefile
  tests/icles/Makefile
  tests/icles/playback/Makefile
@@@ -989,7 -1072,7 +990,7 @@@ sed 
      -e "s/.* PACKAGE_STRING$/#define PACKAGE_STRING \"$PACKAGE_STRING\"/" \
      -e 's/.* PACKAGE_TARNAME$/#define PACKAGE_TARNAME "'$PACKAGE_TARNAME'"/' \
      -e 's/.* PACKAGE_VERSION$/#define PACKAGE_VERSION "'$PACKAGE_VERSION'"/' \
 -    -e 's/.* PLUGINDIR$/#ifdef _DEBUG\n#  define PLUGINDIR PREFIX "\\\\debug\\\\lib\\\\gstreamer-0.10"\n#else\n#  define PLUGINDIR PREFIX "\\\\lib\\\\gstreamer-0.10"\n#endif/' \
 +    -e 's/.* PLUGINDIR$/#ifdef _DEBUG\n#  define PLUGINDIR PREFIX "\\\\debug\\\\lib\\\\gstreamer-0.11"\n#else\n#  define PLUGINDIR PREFIX "\\\\lib\\\\gstreamer-0.11"\n#endif/' \
      -e 's/.* USE_BINARY_REGISTRY$/#define USE_BINARY_REGISTRY/' \
      -e 's/.* VERSION$/#define VERSION "'$VERSION'"/' \
      -e "s/.* DEFAULT_AUDIOSINK$/#define DEFAULT_AUDIOSINK \"directsoundsink\"/" \
@@@ -43,7 -43,6 +43,7 @@@
          <filename>-lgstaudio-&GST_MAJORMINOR;</filename> to the library flags.
        </para>
        <xi:include href="xml/gstaudio.xml" />
 +      <xi:include href="xml/gstaudiocdsrc.xml" />
        <xi:include href="xml/gstaudioclock.xml" />
        <xi:include href="xml/gstaudiodecoder.xml" />
        <xi:include href="xml/gstaudioencoder.xml" />
        <xi:include href="xml/gstaudiomixerutils.xml" />
        <xi:include href="xml/gstaudiosink.xml" />
        <xi:include href="xml/gstaudiosrc.xml" />
 -      <xi:include href="xml/gstbaseaudiosink.xml" />
 -      <xi:include href="xml/gstbaseaudiosrc.xml" />
 +      <xi:include href="xml/gstaudiobasesink.xml" />
 +      <xi:include href="xml/gstaudiobasesrc.xml" />
        <xi:include href="xml/gstmultichannel.xml" />
 -      <xi:include href="xml/gstringbuffer.xml" />
 +      <xi:include href="xml/gstaudioringbuffer.xml" />
        <xi:include href="xml/gstaudioiec61937.xml" />
      </chapter>
  
 -    <chapter id="gstreamer-cdda">
 -      <title>CDDA Library</title>
 -      <para>
 -        This library should be linked to by getting cflags and libs from
 -        <filename>gstreamer-plugins-base-&GST_MAJORMINOR;.pc</filename> and adding
 -        <filename>-lgstcdda-&GST_MAJORMINOR;</filename> to the library flags.
 -      </para>
 -      <xi:include href="xml/gstcddabasesrc.xml" />
 -    </chapter>
 -
      <chapter id="gstreamer-ffft">
        <title>FFT Library</title>
        <para>
        <xi:include href="xml/gstfftf64.xml" />
      </chapter>
  
 -    <chapter id="gstreamer-floatcast">
 -      <title>FloatCast Library</title>
 -      <para>
 -        This library should be linked to by getting cflags and libs from
 -        <filename>gstreamer-plugins-base-&GST_MAJORMINOR;.pc</filename> and adding
 -        <filename>-lgstfloatcase-&GST_MAJORMINOR;</filename> to the library flags.
 -      </para>
 -      <xi:include href="xml/gstfloatcast.xml" />
 -    </chapter>
 -
      <chapter id="gstreamer-interfaces">
        <title>Interfaces Library</title>
        <para>
        <xi:include href="xml/gsttunerchannel.xml" />
        <xi:include href="xml/gsttunernorm.xml" />
        <xi:include href="xml/gstvideoorientation.xml" />
 -      <xi:include href="xml/gstxoverlay.xml" />
 -    </chapter>
 -
 -    <chapter id="gstreamer-netbuffer">
 -      <title>Network Buffer Library</title>
 -      <para>
 -        This library should be linked to by getting cflags and libs from
 -        <filename>gstreamer-plugins-base-&GST_MAJORMINOR;.pc</filename> and adding
 -        <filename>-lgstnetbuffer-&GST_MAJORMINOR;</filename> to the library flags.
 -      </para>
 -      <xi:include href="xml/gstnetbuffer.xml" />
 +      <xi:include href="xml/gstvideooverlay.xml" />
      </chapter>
  
      <chapter id="gstreamer-riff">
          <filename>gstreamer-plugins-base-&GST_MAJORMINOR;.pc</filename> and adding
          <filename>-lgstrtp-&GST_MAJORMINOR;</filename> to the library flags.
        </para>
 -      <xi:include href="xml/gstbasertpaudiopayload.xml" />
 -      <xi:include href="xml/gstbasertpdepayload.xml" />
 -      <xi:include href="xml/gstbasertppayload.xml" />
 +      <xi:include href="xml/gstrtpbaseaudiopayload.xml" />
 +      <xi:include href="xml/gstrtpbasedepayload.xml" />
 +      <xi:include href="xml/gstrtpbasepayload.xml" />
        <xi:include href="xml/gstrtpbuffer.xml" />
        <xi:include href="xml/gstrtcpbuffer.xml" />
        <xi:include href="xml/gstrtppayloads.xml" />
          <filename>gstreamer-plugins-base-&GST_MAJORMINOR;.pc</filename> and adding
          <filename>-lgstrtsp-&GST_MAJORMINOR;</filename> to the library flags.
        </para>
 -      <xi:include href="xml/gstrtspbase64.xml" />
        <xi:include href="xml/gstrtspconnection.xml" />
        <xi:include href="xml/gstrtspdefs.xml" />
        <xi:include href="xml/gstrtspextension.xml" />
          <filename>-lgstvideo-&GST_MAJORMINOR;</filename> to the library flags.
        </para>
        <xi:include href="xml/gstvideo.xml" />
+       <xi:include href="xml/gstvideooverlaycomposition.xml" />
        <xi:include href="xml/gstvideofilter.xml" />
        <xi:include href="xml/gstvideosink.xml" />
      </chapter>
@@@ -60,7 -60,8 +60,7 @@@ gst_app_sink_get_max_buffer
  gst_app_sink_set_drop
  gst_app_sink_get_drop
  gst_app_sink_pull_preroll
 -gst_app_sink_pull_buffer
 -gst_app_sink_pull_buffer_list
 +gst_app_sink_pull_sample
  GstAppSinkCallbacks
  gst_app_sink_set_callbacks
  <SUBSECTION Standard>
@@@ -87,6 -88,9 +87,6 @@@ GstAudioFormatFlag
  GstAudioFormatInfo
  GstAudioInfo
  gst_audio_info_init
 -gst_audio_info_clear
 -gst_audio_info_copy
 -gst_audio_info_free
  gst_audio_info_from_caps
  gst_audio_info_to_caps
  gst_audio_info_convert
@@@ -114,9 -118,19 +114,9 @@@ GST_AUDIO_INFO_POSITIO
  GST_AUDIO_INFO_RATE
  GST_AUDIO_INFO_WIDTH
  
 -GstAudioFieldFlag
  GST_FRAMES_TO_CLOCK_TIME
  GST_CLOCK_TIME_TO_FRAMES
  GST_AUDIO_DEF_RATE
 -GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS
 -GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS
 -GST_AUDIO_INT_PAD_TEMPLATE_CAPS
 -GST_AUDIO_INT_STANDARD_PAD_TEMPLATE_CAPS
 -gst_audio_frame_byte_size
 -gst_audio_frame_length
 -gst_audio_duration_from_pad_buffer
 -gst_audio_is_buffer_framed
 -gst_audio_structure_set_int
  gst_audio_buffer_clip
  <SUBSECTION Standard>
  GST_TYPE_BUFFER_FORMAT
@@@ -133,6 -147,7 +133,6 @@@ _GST_AUDIO_FORMAT_N
  GstAudioClock
  GstAudioClockGetTimeFunc
  gst_audio_clock_new
 -gst_audio_clock_new_full
  gst_audio_clock_adjust
  gst_audio_clock_get_time
  gst_audio_clock_reset
@@@ -149,26 -164,6 +149,26 @@@ GST_AUDIO_CLOCK_CAS
  </SECTION>
  
  <SECTION>
 +<FILE>gstaudiocdsrc</FILE>
 +<INCLUDE>gst/audio/gstaudiocdsrc.h</INCLUDE>
 +GstAudioCdSrc
 +GstAudioCdSrcClass
 +GstAudioCdSrcTrack
 +GstAudioCdSrcMode
 +gst_audio_cd_src_add_track
 +<SUBSECTION Standard>
 +GST_TYPE_AUDIO_CD_SRC_MODE
 +gst_audio_cd_src_mode_get_type
 +GST_AUDIO_CD_SRC
 +GST_AUDIO_CD_SRC_CLASS
 +GST_AUDIO_CD_SRC_GET_CLASS
 +GST_IS_AUDIO_CD_SRC
 +GST_IS_AUDIO_CD_SRC_CLASS
 +GST_TYPE_AUDIO_CD_SRC
 +gst_audio_cd_src_get_type
 +</SECTION>
 +
 +<SECTION>
  <FILE>gstaudiodecoder</FILE>
  <INCLUDE>gst/audio/gstaudiodecoder.h</INCLUDE>
  GstAudioDecoder
@@@ -305,59 -300,59 +305,59 @@@ GST_AUDIO_SRC_GET_CLAS
  </SECTION>
  
  <SECTION>
 -<FILE>gstbaseaudiosink</FILE>
 -<INCLUDE>gst/audio/gstbaseaudiosink.h</INCLUDE>
 -GstBaseAudioSink
 -GstBaseAudioSinkClass
 -GstBaseAudioSinkSlaveMethod
 +<FILE>gstaudiobasesink</FILE>
 +<INCLUDE>gst/audio/gstaudiobasesink.h</INCLUDE>
 +GstAudioBaseSink
 +GstAudioBaseSinkClass
 +GstAudioBaseSinkSlaveMethod
  
 -GST_BASE_AUDIO_SINK_CLOCK
 -GST_BASE_AUDIO_SINK_PAD
 -gst_base_audio_sink_create_ringbuffer
 -gst_base_audio_sink_set_provide_clock
 -gst_base_audio_sink_get_provide_clock
 -gst_base_audio_sink_set_slave_method
 -gst_base_audio_sink_get_slave_method
 -gst_base_audio_sink_get_drift_tolerance
 -gst_base_audio_sink_set_drift_tolerance
 +GST_AUDIO_BASE_SINK_CLOCK
 +GST_AUDIO_BASE_SINK_PAD
 +gst_audio_base_sink_create_ringbuffer
 +gst_audio_base_sink_set_provide_clock
 +gst_audio_base_sink_get_provide_clock
 +gst_audio_base_sink_set_slave_method
 +gst_audio_base_sink_get_slave_method
 +gst_audio_base_sink_get_drift_tolerance
 +gst_audio_base_sink_set_drift_tolerance
  <SUBSECTION Standard>
 -GST_BASE_AUDIO_SINK
 -GST_IS_BASE_AUDIO_SINK
 -GST_TYPE_BASE_AUDIO_SINK
 -gst_base_audio_sink_get_type
 -GST_BASE_AUDIO_SINK_CLASS
 -GST_IS_BASE_AUDIO_SINK_CLASS
 -GST_BASE_AUDIO_SINK_GET_CLASS
 -GstBaseAudioSinkPrivate
 -gst_base_audio_sink_slave_method_get_type
 -GST_TYPE_BASE_AUDIO_SINK_SLAVE_METHOD
 -</SECTION>
 -
 -<SECTION>
 -<FILE>gstbaseaudiosrc</FILE>
 -<INCLUDE>gst/audio/gstbaseaudiosrc.h</INCLUDE>
 -GstBaseAudioSrc
 -GstBaseAudioSrcClass
 -GstBaseAudioSrcSlaveMethod
 -
 -GST_BASE_AUDIO_SRC_CLOCK
 -GST_BASE_AUDIO_SRC_PAD
 -gst_base_audio_src_create_ringbuffer
 -gst_base_audio_src_set_provide_clock
 -gst_base_audio_src_get_provide_clock
 -gst_base_audio_src_get_slave_method
 -gst_base_audio_src_set_slave_method
 +GST_AUDIO_BASE_SINK
 +GST_IS_AUDIO_BASE_SINK
 +GST_TYPE_AUDIO_BASE_SINK
 +gst_audio_base_sink_get_type
 +GST_AUDIO_BASE_SINK_CLASS
 +GST_IS_AUDIO_BASE_SINK_CLASS
 +GST_AUDIO_BASE_SINK_GET_CLASS
 +GstAudioBaseSinkPrivate
 +gst_audio_base_sink_slave_method_get_type
 +GST_TYPE_AUDIO_BASE_SINK_SLAVE_METHOD
 +</SECTION>
 +
 +<SECTION>
 +<FILE>gstaudiobasesrc</FILE>
 +<INCLUDE>gst/audio/gstaudiobasesrc.h</INCLUDE>
 +GstAudioBaseSrc
 +GstAudioBaseSrcClass
 +GstAudioBaseSrcSlaveMethod
 +
 +GST_AUDIO_BASE_SRC_CLOCK
 +GST_AUDIO_BASE_SRC_PAD
 +gst_audio_base_src_create_ringbuffer
 +gst_audio_base_src_set_provide_clock
 +gst_audio_base_src_get_provide_clock
 +gst_audio_base_src_get_slave_method
 +gst_audio_base_src_set_slave_method
  <SUBSECTION Standard>
 -GstBaseAudioSrcPrivate
 -GST_BASE_AUDIO_SRC
 -GST_IS_BASE_AUDIO_SRC
 -GST_TYPE_BASE_AUDIO_SRC
 -gst_base_audio_src_get_type
 -GST_BASE_AUDIO_SRC_CLASS
 -GST_IS_BASE_AUDIO_SRC_CLASS
 -GST_BASE_AUDIO_SRC_GET_CLASS
 -gst_base_audio_src_slave_method_get_type
 -GST_TYPE_BASE_AUDIO_SRC_SLAVE_METHOD
 +GstAudioBaseSrcPrivate
 +GST_AUDIO_BASE_SRC
 +GST_IS_AUDIO_BASE_SRC
 +GST_TYPE_AUDIO_BASE_SRC
 +gst_audio_base_src_get_type
 +GST_AUDIO_BASE_SRC_CLASS
 +GST_IS_AUDIO_BASE_SRC_CLASS
 +GST_AUDIO_BASE_SRC_GET_CLASS
 +gst_audio_base_src_slave_method_get_type
 +GST_TYPE_AUDIO_BASE_SRC_SLAVE_METHOD
  </SECTION>
  
  <SECTION>
@@@ -376,71 -371,72 +376,71 @@@ gst_audio_channel_position_get_typ
  </SECTION>
  
  <SECTION>
 -<FILE>gstringbuffer</FILE>
 -<INCLUDE>gst/audio/gstringbuffer.h</INCLUDE>
 -GstRingBuffer
 -GstRingBufferClass
 -GstRingBufferSpec
 -GstRingBufferCallback
 -GstRingBufferSegState
 -GstRingBufferState
 -GstBufferFormat
 +<FILE>gstaudioringbuffer</FILE>
 +<INCLUDE>gst/audio/gstaudioringbuffer.h</INCLUDE>
 +GstAudioRingBuffer
 +GstAudioRingBufferClass
 +GstAudioRingBufferSpec
 +GstAudioRingBufferCallback
 +GstAudioRingBufferSegState
 +GstAudioRingBufferState
  GstBufferFormatType
  
 -GST_RING_BUFFER_BROADCAST
 -GST_RING_BUFFER_GET_COND
 -GST_RING_BUFFER_SIGNAL
 -GST_RING_BUFFER_WAIT
 +GST_AUDIO_RING_BUFFER_BROADCAST
 +GST_AUDIO_RING_BUFFER_GET_COND
 +GST_AUDIO_RING_BUFFER_SIGNAL
 +GST_AUDIO_RING_BUFFER_WAIT
  
 -gst_ring_buffer_set_callback
 +gst_audio_ring_buffer_set_callback
  
 -gst_ring_buffer_acquire
 -gst_ring_buffer_release
 -gst_ring_buffer_is_acquired
 +gst_audio_ring_buffer_acquire
 +gst_audio_ring_buffer_release
 +gst_audio_ring_buffer_is_acquired
  
 -gst_ring_buffer_activate
 -gst_ring_buffer_is_active
 +gst_audio_ring_buffer_activate
 +gst_audio_ring_buffer_is_active
  
 -gst_ring_buffer_start
 -gst_ring_buffer_pause
 -gst_ring_buffer_stop
 +gst_audio_ring_buffer_start
 +gst_audio_ring_buffer_pause
 +gst_audio_ring_buffer_stop
  
 -gst_ring_buffer_delay
 -gst_ring_buffer_samples_done
 -gst_ring_buffer_set_sample
 -gst_ring_buffer_commit
 -gst_ring_buffer_commit_full
 -gst_ring_buffer_convert
 +gst_audio_ring_buffer_delay
 +gst_audio_ring_buffer_samples_done
 +gst_audio_ring_buffer_set_sample
 +gst_audio_ring_buffer_commit
 +gst_audio_ring_buffer_commit_full
 +gst_audio_ring_buffer_convert
  
 -gst_ring_buffer_prepare_read
 -gst_ring_buffer_read
 -gst_ring_buffer_clear
 -gst_ring_buffer_clear_all
 -gst_ring_buffer_advance
 +gst_audio_ring_buffer_prepare_read
 +gst_audio_ring_buffer_read
 +gst_audio_ring_buffer_clear
 +gst_audio_ring_buffer_clear_all
 +gst_audio_ring_buffer_advance
  
 -gst_ring_buffer_close_device
 -gst_ring_buffer_open_device
 -gst_ring_buffer_device_is_open
 +gst_audio_ring_buffer_close_device
 +gst_audio_ring_buffer_open_device
 +gst_audio_ring_buffer_device_is_open
  
 -gst_ring_buffer_may_start
 -gst_ring_buffer_parse_caps
 -gst_ring_buffer_set_flushing
 +gst_audio_ring_buffer_may_start
 +gst_audio_ring_buffer_parse_caps
 +gst_audio_ring_buffer_set_flushing
  
  <SUBSECTION Standard>
 -GST_TYPE_RING_BUFFER
 -GST_RING_BUFFER
 -GST_RING_BUFFER_CLASS
 -GST_RING_BUFFER_GET_CLASS
 -GST_IS_RING_BUFFER
 -GST_IS_RING_BUFFER_CLASS
 -GST_RING_BUFFER_CAST
 -gst_ring_buffer_get_type
 -GST_TYPE_RING_BUFFER_SEG_STATE
 -gst_ring_buffer_seg_state_get_type
 -GST_TYPE_RING_BUFFER_STATE
 -gst_ring_buffer_state_get_type
 +GST_TYPE_AUDIO_RING_BUFFER
 +GST_AUDIO_RING_BUFFER
 +GST_AUDIO_RING_BUFFER_CLASS
 +GST_AUDIO_RING_BUFFER_GET_CLASS
 +GST_IS_AUDIO_RING_BUFFER
 +GST_IS_AUDIO_RING_BUFFER_CLASS
 +GST_AUDIO_RING_BUFFER_CAST
 +gst_audio_ring_buffer_get_type
 +GST_TYPE_AUDIO_RING_BUFFER_SEG_STATE
 +gst_audio_ring_buffer_seg_state_get_type
 +GST_TYPE_AUDIO_RING_BUFFER_STATE
 +gst_audio_ring_buffer_state_get_type
  <SUBSECTION Private>
 -gst_ring_buffer_debug_spec_buff
 -gst_ring_buffer_debug_spec_caps
 +gst_audio_ring_buffer_debug_spec_buff
 +gst_audio_ring_buffer_debug_spec_caps
  </SECTION>
  
  <SECTION>
@@@ -450,6 -446,29 +450,6 @@@ gst_audio_iec61937_frame_siz
  gst_audio_iec61937_payload
  </SECTION>
  
 -
 -# cdda
 -
 -<SECTION>
 -<FILE>gstcddabasesrc</FILE>
 -<INCLUDE>gst/cdda/gstcddabasesrc.h</INCLUDE>
 -GstCddaBaseSrc
 -GstCddaBaseSrcClass
 -GstCddaBaseSrcTrack
 -GstCddaBaseSrcMode
 -gst_cdda_base_src_add_track
 -<SUBSECTION Standard>
 -GST_TYPE_CDDA_BASE_SRC_MODE
 -gst_cdda_base_src_mode_get_type
 -GST_CDDA_BASE_SRC
 -GST_CDDA_BASE_SRC_CLASS
 -GST_CDDA_BASE_SRC_GET_CLASS
 -GST_IS_CDDA_BASE_SRC
 -GST_IS_CDDA_BASE_SRC_CLASS
 -GST_TYPE_CDDA_BASE_SRC
 -gst_cdda_base_src_get_type
 -</SECTION>
 -
  # fft
  
  <SECTION>
@@@ -560,13 -579,25 +560,13 @@@ KISS_FFT_F64_MALLO
  KISS_FFT_F64_SIN
  </SECTION>
  
 -# floatcast
 -
 -<SECTION>
 -<FILE>gstfloatcast</FILE>
 -<INCLUDE>gst/floatcast/floatcast.h</INCLUDE>
 -gst_cast_double
 -gst_cast_float
 -<SUBSECTION Standard>
 -inline
 -</SECTION>
 -
 -
  # interfaces
  
  <SECTION>
  <FILE>gstcolorbalance</FILE>
 -<INCLUDE>gst/interfaces/color.h</INCLUDE>
 +<INCLUDE>gst/video/colorbalance.h</INCLUDE>
  GstColorBalance
 -GstColorBalanceClass
 +GstColorBalanceInterface
  GstColorBalanceType
  gst_color_balance_list_channels
  gst_color_balance_get_value
@@@ -575,9 -606,11 +575,9 @@@ gst_color_balance_value_change
  gst_color_balance_get_balance_type
  <SUBSECTION Standard>
  GST_COLOR_BALANCE
 -GST_COLOR_BALANCE_CLASS
 -GST_COLOR_BALANCE_GET_CLASS
 +GST_COLOR_BALANCE_GET_INTERACE
  GST_COLOR_BALANCE_TYPE
  GST_IS_COLOR_BALANCE
 -GST_IS_COLOR_BALANCE_CLASS
  GST_TYPE_COLOR_BALANCE
  GST_TYPE_COLOR_BALANCE_TYPE
  gst_color_balance_get_type
@@@ -586,7 -619,7 +586,7 @@@ gst_color_balance_type_get_typ
  
  <SECTION>
  <FILE>gstcolorbalancechannel</FILE>
 -<INCLUDE>gst/interfaces/colorbalancechannel.h</INCLUDE>
 +<INCLUDE>gst/video/colorbalancechannel.h</INCLUDE>
  GstColorBalanceChannel
  GstColorBalanceChannelClass
  <SUBSECTION Standard>
@@@ -600,7 -633,7 +600,7 @@@ gst_color_balance_channel_get_typ
  
  <SECTION>
  <FILE>gstmixer</FILE>
 -<INCLUDE>gst/interfaces/mixer.h</INCLUDE>
 +<INCLUDE>gst/audio/mixer.h</INCLUDE>
  GstMixer
  GstMixerType
  GstMixerFlags
@@@ -640,9 -673,11 +640,9 @@@ GST_TYPE_MIXER_TYP
  GST_TYPE_MIXER_FLAGS
  GST_TYPE_MIXER_MESSAGE_TYPE
  GST_MIXER
 -GST_MIXER_CLASS
 -GST_MIXER_GET_CLASS
 +GST_MIXER_GET_INTERFACE
  GST_MIXER_TYPE
  GST_IS_MIXER
 -GST_IS_MIXER_CLASS
  GST_TYPE_STREAM_VOLUME_FORMAT
  gst_mixer_get_type
  gst_mixer_type_get_type
@@@ -653,7 -688,7 +653,7 @@@ gst_stream_volume_format_get_typ
  
  <SECTION>
  <FILE>gstmixeroptions</FILE>
 -<INCLUDE>gst/interfaces/mixer.h</INCLUDE>
 +<INCLUDE>gst/audio/mixer.h</INCLUDE>
  GstMixerOptions
  gst_mixer_options_get_values
  <SUBSECTION Standard>
@@@ -669,7 -704,7 +669,7 @@@ gst_mixer_options_get_typ
  
  <SECTION>
  <FILE>gstmixertrack</FILE>
 -<INCLUDE>gst/interfaces/mixer.h</INCLUDE>
 +<INCLUDE>gst/audio/mixer.h</INCLUDE>
  GstMixerTrack
  GstMixerTrackFlags
  GST_MIXER_TRACK_HAS_FLAG
@@@ -731,7 -766,7 +731,7 @@@ GST_NAVIGATION_COMMAND_DVD_TITLE_MEN
  <SUBSECTION Standard>
  GST_TYPE_NAVIGATION
  GST_NAVIGATION
 -GST_NAVIGATION_GET_IFACE
 +GST_NAVIGATION_GET_INTERFACE
  GST_TYPE_NAVIGATION_COMMAND
  GST_TYPE_NAVIGATION_EVENT_TYPE
  GST_TYPE_NAVIGATION_MESSAGE_TYPE
@@@ -764,14 -799,14 +764,14 @@@ gst_property_probe_probe_property_nam
  <SUBSECTION Standard>
  GST_TYPE_PROPERTY_PROBE
  GST_PROPERTY_PROBE
 -GST_PROPERTY_PROBE_GET_IFACE
 +GST_PROPERTY_PROBE_GET_INTEFACE
  GST_IS_PROPERTY_PROBE
  gst_property_probe_get_type
  </SECTION>
  
  <SECTION>
  <FILE>gststreamvolume</FILE>
 -<INCLUDE>gst/interfaces/streamvolume.h</INCLUDE>
 +<INCLUDE>gst/audio/streamvolume.h</INCLUDE>
  GstStreamVolume
  GstStreamVolumeFormat
  
@@@ -798,7 -833,7 +798,7 @@@ gst_stream_volume_get_typ
  <FILE>gsttuner</FILE>
  <INCLUDE>gst/interfaces/tuner.h</INCLUDE>
  GstTuner
 -GstTunerClass
 +GstTunerInterface
  
  gst_tuner_list_channels
  gst_tuner_get_channel
@@@ -822,8 -857,10 +822,8 @@@ gst_tuner_signal_change
  <SUBSECTION Standard>
  GST_TYPE_TUNER
  GST_TUNER
 -GST_TUNER_CLASS
 -GST_TUNER_GET_CLASS
 +GST_TUNER_GET_INTERFACE
  GST_IS_TUNER
 -GST_IS_TUNER_CLASS
  gst_tuner_get_type
  </SECTION>
  
@@@ -861,7 -898,7 +861,7 @@@ gst_tuner_norm_get_typ
  
  <SECTION>
  <FILE>gstvideoorientation</FILE>
 -<INCLUDE>gst/interfaces/videoorientation.h</INCLUDE>
 +<INCLUDE>gst/video/videoorientation.h</INCLUDE>
  GstVideoOrientation
  GstVideoOrientationInterface
  gst_video_orientation_get_hcenter
@@@ -876,30 -913,69 +876,30 @@@ gst_video_orientation_set_vfli
  GST_TYPE_VIDEO_ORIENTATION
  GST_VIDEO_ORIENTATION
  GST_IS_VIDEO_ORIENTATION
 -GST_VIDEO_ORIENTATION_GET_IFACE
 +GST_VIDEO_ORIENTATION_GET_INTERFACE
  gst_video_orientation_get_type
  </SECTION>
  
  <SECTION>
 -<FILE>gstxoverlay</FILE>
 -<INCLUDE>gst/interfaces/xoverlay.h</INCLUDE>
 +<FILE>gstvideooverlay</FILE>
 +<INCLUDE>gst/video/videooverlay.h</INCLUDE>
  GstXOverlay
 -GstXOverlayClass
 -gst_x_overlay_set_xwindow_id
 -gst_x_overlay_got_xwindow_id
 -gst_x_overlay_got_window_handle
 -gst_x_overlay_set_window_handle
 -gst_x_overlay_prepare_xwindow_id
 -gst_x_overlay_expose
 -gst_x_overlay_handle_events
 -gst_x_overlay_set_render_rectangle
 +GstXOverlayIface
 +gst_video_overlay_got_window_handle
 +gst_video_overlay_set_window_handle
 +gst_video_overlay_prepare_window_handle
 +gst_video_overlay_expose
 +gst_video_overlay_handle_events
 +gst_video_overlay_set_render_rectangle
  <SUBSECTION Standard>
 -GST_TYPE_X_OVERLAY
 -GST_X_OVERLAY
 -GST_X_OVERLAY_CLASS
 -GST_X_OVERLAY_GET_CLASS
 -GST_IS_X_OVERLAY
 -GST_IS_X_OVERLAY_CLASS
 -gst_x_overlay_get_type
 +GST_TYPE_VIDEO_OVERLAY
 +GST_VIDEO_OVERLAY
 +GST_IS_VIDEO_OVERLAY
 +GST_VIDEO_OVERLAY_GET_INTERFACE
 +gst_video_overlay_get_type
  </SECTION>
  
  
 -# netbuffer
 -
 -<SECTION>
 -<FILE>gstnetbuffer</FILE>
 -<INCLUDE>gst/netbuffer/gstnetbuffer.h</INCLUDE>
 -GstNetBuffer
 -GstNetType
 -GST_NETADDRESS_MAX_LEN
 -GstNetAddress
 -
 -gst_netbuffer_new
 -gst_netaddress_get_net_type
 -
 -gst_netaddress_set_ip4_address
 -gst_netaddress_get_ip4_address
 -
 -gst_netaddress_set_ip6_address
 -gst_netaddress_get_ip6_address
 -
 -gst_netaddress_get_address_bytes
 -gst_netaddress_set_address_bytes
 -
 -gst_netaddress_equal
 -
 -gst_netaddress_to_string
 -<SUBSECTION Standard>
 -GstNetBufferClass
 -GST_TYPE_NETBUFFER
 -GST_NETBUFFER
 -GST_NETBUFFER_CLASS
 -GST_NETBUFFER_GET_CLASS
 -GST_IS_NETBUFFER
 -GST_IS_NETBUFFER_CLASS
 -gst_netbuffer_get_type
 -</SECTION>
  
  
  # riff
@@@ -1119,53 -1195,54 +1119,53 @@@ gst_riff_str
  # rtp
  
  <SECTION>
 -<FILE>gstbasertpaudiopayload</FILE>
 -<INCLUDE>gst/rtp/gstbasertpaudiopayload.h</INCLUDE>
 -GstBaseRTPAudioPayload
 -GstBaseRTPAudioPayloadClass
 +<FILE>gstrtpbaseaudiopayload</FILE>
 +<INCLUDE>gst/rtp/gstrtpbaseaudiopayload.h</INCLUDE>
 +GstRTPBaseAudioPayload
 +GstRTPBaseAudioPayloadClass
  
 -gst_base_rtp_audio_payload_set_frame_based
 -gst_base_rtp_audio_payload_set_frame_options
 -gst_base_rtp_audio_payload_set_sample_based
 -gst_base_rtp_audio_payload_set_sample_options
 -gst_base_rtp_audio_payload_get_adapter
 -gst_base_rtp_audio_payload_push
 -gst_base_rtp_audio_payload_flush
 -gst_base_rtp_audio_payload_set_samplebits_options
 +gst_rtp_base_audio_payload_set_frame_based
 +gst_rtp_base_audio_payload_set_frame_options
 +gst_rtp_base_audio_payload_set_sample_based
 +gst_rtp_base_audio_payload_set_sample_options
 +gst_rtp_base_audio_payload_get_adapter
 +gst_rtp_base_audio_payload_push
 +gst_rtp_base_audio_payload_flush
 +gst_rtp_base_audio_payload_set_samplebits_options
  <SUBSECTION Standard>
 -GST_TYPE_BASE_RTP_AUDIO_PAYLOAD
 -GST_BASE_RTP_AUDIO_PAYLOAD
 -GST_BASE_RTP_AUDIO_PAYLOAD_CLASS
 -GST_IS_BASE_RTP_AUDIO_PAYLOAD
 -GST_IS_BASE_RTP_AUDIO_PAYLOAD_CLASS
 -GST_BASE_RTP_AUDIO_PAYLOAD_CAST
 -gst_base_rtp_audio_payload_get_type
 -GstBaseRTPAudioPayloadPrivate
 +GST_TYPE_RTP_BASE_AUDIO_PAYLOAD
 +GST_RTP_BASE_AUDIO_PAYLOAD
 +GST_RTP_BASE_AUDIO_PAYLOAD_CLASS
 +GST_IS_RTP_BASE_AUDIO_PAYLOAD
 +GST_IS_RTP_BASE_AUDIO_PAYLOAD_CLASS
 +GST_RTP_BASE_AUDIO_PAYLOAD_CAST
 +gst_rtp_base_audio_payload_get_type
 +GstRTPBaseAudioPayloadPrivate
  </SECTION>
  
  <SECTION>
 -<FILE>gstbasertpdepayload</FILE>
 -<INCLUDE>gst/rtp/gstbasertpdepayload.h</INCLUDE>
 -GstBaseRTPDepayload
 -GstBaseRTPDepayloadClass
 +<FILE>gstrtpbasedepayload</FILE>
 +<INCLUDE>gst/rtp/gstrtpbasedepayload.h</INCLUDE>
 +GstRTPBaseDepayload
 +GstRTPBaseDepayloadClass
  
 -GST_BASE_RTP_DEPAYLOAD_SINKPAD
 -GST_BASE_RTP_DEPAYLOAD_SRCPAD
 +GST_RTP_BASE_DEPAYLOAD_SINKPAD
 +GST_RTP_BASE_DEPAYLOAD_SRCPAD
  
 -gst_base_rtp_depayload_push
 -gst_base_rtp_depayload_push_ts
 -gst_base_rtp_depayload_push_list
 +gst_rtp_base_depayload_push
 +gst_rtp_base_depayload_push_list
  
  <SUBSECTION Standard>
 -GstBaseRTPDepayloadPrivate
 -GST_TYPE_BASE_RTP_DEPAYLOAD
 -GST_BASE_RTP_DEPAYLOAD
 -GST_BASE_RTP_DEPAYLOAD_CLASS
 -GST_BASE_RTP_DEPAYLOAD_GET_CLASS
 -GST_IS_BASE_RTP_DEPAYLOAD
 -GST_IS_BASE_RTP_DEPAYLOAD_CLASS
 -GST_BASE_RTP_PAYLOAD_CAST
 -gst_base_rtp_depayload_get_type
 -GstBaseRTPPayloadPrivate
 +GstRTPBaseDepayloadPrivate
 +GST_TYPE_RTP_BASE_DEPAYLOAD
 +GST_RTP_BASE_DEPAYLOAD
 +GST_RTP_BASE_DEPAYLOAD_CLASS
 +GST_RTP_BASE_DEPAYLOAD_GET_CLASS
 +GST_IS_RTP_BASE_DEPAYLOAD
 +GST_IS_RTP_BASE_DEPAYLOAD_CLASS
 +GST_RTP_BASE_PAYLOAD_CAST
 +gst_rtp_base_depayload_get_type
 +GstRTPBasePayloadPrivate
  
  <SUBSECTION Private>
  QUEUE_LOCK_INIT
@@@ -1175,29 -1252,29 +1175,29 @@@ QUEUE_UNLOC
  </SECTION>
  
  <SECTION>
 -<FILE>gstbasertppayload</FILE>
 -<INCLUDE>gst/rtp/gstbasertppayload.h</INCLUDE>
 -GstBaseRTPPayload
 -GstBaseRTPPayloadClass
 +<FILE>gstrtpbasepayload</FILE>
 +<INCLUDE>gst/rtp/gstrtpbasepayload.h</INCLUDE>
 +GstRTPBasePayload
 +GstRTPBasePayloadClass
  
 -GST_BASE_RTP_PAYLOAD_MTU
 -GST_BASE_RTP_PAYLOAD_PT
 -GST_BASE_RTP_PAYLOAD_SINKPAD
 -GST_BASE_RTP_PAYLOAD_SRCPAD
 +GST_RTP_BASE_PAYLOAD_MTU
 +GST_RTP_BASE_PAYLOAD_PT
 +GST_RTP_BASE_PAYLOAD_SINKPAD
 +GST_RTP_BASE_PAYLOAD_SRCPAD
  
 -gst_basertppayload_is_filled
 -gst_basertppayload_push
 -gst_basertppayload_push_list
 -gst_basertppayload_set_options
 -gst_basertppayload_set_outcaps
 +gst_rtp_base_payload_is_filled
 +gst_rtp_base_payload_push
 +gst_rtp_base_payload_push_list
 +gst_rtp_base_payload_set_options
 +gst_rtp_base_payload_set_outcaps
  <SUBSECTION Standard>
 -GST_TYPE_BASE_RTP_PAYLOAD
 -GST_BASE_RTP_PAYLOAD
 -GST_BASE_RTP_PAYLOAD_CLASS
 -GST_BASE_RTP_PAYLOAD_GET_CLASS
 -GST_IS_BASE_RTP_PAYLOAD
 -GST_IS_BASE_RTP_PAYLOAD_CLASS
 -gst_basertppayload_get_type
 +GST_TYPE_RTP_BASE_PAYLOAD
 +GST_RTP_BASE_PAYLOAD
 +GST_RTP_BASE_PAYLOAD_CLASS
 +GST_RTP_BASE_PAYLOAD_GET_CLASS
 +GST_IS_RTP_BASE_PAYLOAD
 +GST_IS_RTP_BASE_PAYLOAD_CLASS
 +gst_rtp_base_payload_get_type
  </SECTION>
  
  <SECTION>
@@@ -1225,8 -1302,7 +1225,8 @@@ gst_rtcp_buffer_validate_dat
  gst_rtcp_buffer_validate
  
  gst_rtcp_buffer_new
 -gst_rtcp_buffer_end
 +gst_rtcp_buffer_map
 +gst_rtcp_buffer_unmap
  
  gst_rtcp_buffer_get_packet_count
  gst_rtcp_buffer_get_first_packet
@@@ -1354,6 -1430,7 +1354,6 @@@ gst_rtp_buffer_new_take_dat
  gst_rtp_buffer_new_copy_data
  gst_rtp_buffer_new_allocate
  gst_rtp_buffer_new_allocate_len
 -gst_rtp_buffer_list_from_buffer
  
  gst_rtp_buffer_calc_header_len
  gst_rtp_buffer_calc_packet_len
@@@ -1407,10 -1484,31 +1407,10 @@@ gst_rtp_buffer_compare_seqnu
  gst_rtp_buffer_ext_timestamp
  gst_rtp_buffer_set_extension_data
  
 -gst_rtp_buffer_list_validate
 -
 -gst_rtp_buffer_list_get_payload_len
 -
 -gst_rtp_buffer_list_get_payload_type
 -gst_rtp_buffer_list_set_payload_type
 -
 -gst_rtp_buffer_list_get_seq
 -gst_rtp_buffer_list_set_seq
 -
 -gst_rtp_buffer_list_get_ssrc
 -gst_rtp_buffer_list_set_ssrc
 -
 -gst_rtp_buffer_list_get_timestamp
 -gst_rtp_buffer_list_set_timestamp
 -
  gst_rtp_buffer_get_extension_onebyte_header
  gst_rtp_buffer_get_extension_twobytes_header
  gst_rtp_buffer_add_extension_onebyte_header
  gst_rtp_buffer_add_extension_twobytes_header
 -
 -gst_rtp_buffer_list_get_extension_onebyte_header
 -gst_rtp_buffer_list_get_extension_twobytes_header
 -gst_rtp_buffer_list_add_extension_onebyte_header
 -gst_rtp_buffer_list_add_extension_twobytes_header
  </SECTION>
  
  # rtsp
@@@ -1480,6 -1578,13 +1480,6 @@@ gst_rtsp_lower_trans_get_typ
  </SECTION>
  
  <SECTION>
 -<FILE>gstrtspbase64</FILE>
 -<INCLUDE>gst/rtsp/gstrtspbase64.h</INCLUDE>
 -gst_rtsp_base64_encode
 -gst_rtsp_base64_decode_ip
 -</SECTION>
 -
 -<SECTION>
  <FILE>gstrtspconnection</FILE>
  <INCLUDE>gst/rtsp/gstrtspconnection.h</INCLUDE>
  GstRTSPConnection
@@@ -1530,6 -1635,8 +1530,6 @@@ gst_rtsp_watch_ne
  gst_rtsp_watch_unref
  gst_rtsp_watch_attach
  gst_rtsp_watch_reset
 -gst_rtsp_watch_queue_message
 -gst_rtsp_watch_queue_data
  gst_rtsp_watch_send_message
  gst_rtsp_watch_write_data
  </SECTION>
@@@ -1542,7 -1649,7 +1542,7 @@@ GstRTSPExtensionInterfac
  <SUBSECTION Standard>
  GST_IS_RTSP_EXTENSION
  GST_RTSP_EXTENSION
 -GST_RTSP_EXTENSION_GET_IFACE
 +GST_RTSP_EXTENSION_GET_INTERFACE
  GST_TYPE_RTSP_EXTENSION
  gst_rtsp_extension_after_send
  gst_rtsp_extension_before_send
@@@ -2095,16 -2202,104 +2095,16 @@@ GstEncodingTargetClas
  <SECTION>
  <FILE>gstvideo</FILE>
  <INCLUDE>gst/video/video.h</INCLUDE>
 -GST_VIDEO_BLUE_MASK_15
 -GST_VIDEO_BLUE_MASK_15_INT
 -GST_VIDEO_BLUE_MASK_16
 -GST_VIDEO_BLUE_MASK_16_INT
 -GST_VIDEO_BYTE1_MASK_24
 -GST_VIDEO_BYTE1_MASK_24_INT
 -GST_VIDEO_BYTE1_MASK_32
 -GST_VIDEO_BYTE1_MASK_32_INT
 -GST_VIDEO_BYTE2_MASK_24
 -GST_VIDEO_BYTE2_MASK_24_INT
 -GST_VIDEO_BYTE2_MASK_32
 -GST_VIDEO_BYTE2_MASK_32_INT
 -GST_VIDEO_BYTE3_MASK_24
 -GST_VIDEO_BYTE3_MASK_24_INT
 -GST_VIDEO_BYTE3_MASK_32
 -GST_VIDEO_BYTE3_MASK_32_INT
 -GST_VIDEO_BYTE4_MASK_32
 -GST_VIDEO_BYTE4_MASK_32_INT
 -GST_VIDEO_CAPS_ABGR
 -GST_VIDEO_CAPS_ARGB
 -GST_VIDEO_CAPS_BGR
 -GST_VIDEO_CAPS_BGRA
 -GST_VIDEO_CAPS_BGRx
 -GST_VIDEO_CAPS_BGRx_HOST_ENDIAN
 -GST_VIDEO_CAPS_RGB
 -GST_VIDEO_CAPS_RGBA
 -GST_VIDEO_CAPS_RGB_15
 -GST_VIDEO_CAPS_RGB_16
 -GST_VIDEO_CAPS_RGBx
 -GST_VIDEO_CAPS_YUV
 -GST_VIDEO_CAPS_xBGR
 -GST_VIDEO_CAPS_xRGB
 -GST_VIDEO_CAPS_xRGB_HOST_ENDIAN
 -GST_VIDEO_CAPS_BGR_15
 -GST_VIDEO_CAPS_BGR_16
 -GST_VIDEO_CAPS_RGB8_PALETTED
 -GST_VIDEO_CAPS_GRAY8
 -GST_VIDEO_CAPS_GRAY16
 -GST_VIDEO_CAPS_ARGB_64
 -GST_VIDEO_CAPS_r210
 -GST_VIDEO_COMP1_MASK_15
 -GST_VIDEO_COMP1_MASK_15_INT
 -GST_VIDEO_COMP1_MASK_16
 -GST_VIDEO_COMP1_MASK_16_INT
 -GST_VIDEO_COMP2_MASK_15
 -GST_VIDEO_COMP2_MASK_15_INT
 -GST_VIDEO_COMP2_MASK_16
 -GST_VIDEO_COMP2_MASK_16_INT
 -GST_VIDEO_COMP3_MASK_15
 -GST_VIDEO_COMP3_MASK_15_INT
 -GST_VIDEO_COMP3_MASK_16
 -GST_VIDEO_COMP3_MASK_16_INT
  GST_VIDEO_FPS_RANGE
 -GST_VIDEO_GREEN_MASK_15
 -GST_VIDEO_GREEN_MASK_15_INT
 -GST_VIDEO_GREEN_MASK_16
 -GST_VIDEO_GREEN_MASK_16_INT
 -GST_VIDEO_RED_MASK_15
 -GST_VIDEO_RED_MASK_15_INT
 -GST_VIDEO_RED_MASK_16
 -GST_VIDEO_RED_MASK_16_INT
  GST_VIDEO_SIZE_RANGE
 -GST_VIDEO_BUFFER_TFF
 -GST_VIDEO_BUFFER_RFF
 -GST_VIDEO_BUFFER_ONEFIELD
 -GST_VIDEO_BUFFER_PROGRESSIVE
  GstVideoFormat
  gst_video_calculate_display_ratio
 -gst_video_frame_rate
 -gst_video_get_size
 -gst_video_get_size_from_caps
 -gst_video_format_convert
 -gst_video_format_new_caps
 -gst_video_format_new_caps_interlaced
 -gst_video_format_new_template_caps
 -gst_video_format_get_component_height
 -gst_video_format_get_component_offset
 -gst_video_format_get_component_width
 -gst_video_format_get_component_depth
 -gst_video_format_get_pixel_stride
 -gst_video_format_get_row_stride
 -gst_video_format_get_size
 -gst_video_format_has_alpha
 -gst_video_format_is_rgb
 -gst_video_format_is_gray
 -gst_video_format_is_yuv
  gst_video_format_to_fourcc
  gst_video_format_from_fourcc
 -gst_video_format_parse_caps
 -gst_video_format_parse_caps_interlaced
 -gst_video_parse_caps_framerate
 -gst_video_parse_caps_pixel_aspect_ratio
 -gst_video_parse_caps_color_matrix
 -gst_video_parse_caps_chroma_site
  gst_video_parse_caps_palette
 -GstVideoConvertFrameCallback
 -gst_video_convert_frame
 -gst_video_convert_frame_async
 +GstVideoConvertSampleCallback
 +gst_video_convert_sample
 +gst_video_convert_sample_async
  gst_video_event_new_still_frame
  gst_video_event_parse_still_frame
  gst_video_event_new_upstream_force_key_unit
@@@ -2118,6 -2313,56 +2118,56 @@@ GST_TYPE_VIDEO_FORMA
  </SECTION>
  
  <SECTION>
+ <FILE>gstvideooverlaycomposition</FILE>
+ <INCLUDE>gst/video/video-overlay-composition.h</INCLUDE>
+ <SUBSECTION composition>
+ GstVideoOverlayComposition
+ GstVideoOverlayCompositionClass
+ gst_video_overlay_composition_new
+ gst_video_overlay_composition_ref
+ gst_video_overlay_composition_unref
+ gst_video_overlay_composition_add_rectangle
+ gst_video_overlay_composition_n_rectangles
+ gst_video_overlay_composition_get_rectangle
+ gst_video_overlay_composition_get_seqnum
+ gst_video_overlay_composition_copy
+ gst_video_overlay_composition_make_writable
+ gst_video_overlay_composition_blend
+ <SUBSECTION composition-set-get>
+ gst_video_buffer_get_overlay_composition
+ gst_video_buffer_set_overlay_composition
+ <SUBSECTION rectangle>
+ GstVideoOverlayFormatFlags
+ GstVideoOverlayRectangle
+ GstVideoOverlayRectangleClass
+ gst_video_overlay_rectangle_new_argb
+ gst_video_overlay_rectangle_ref
+ gst_video_overlay_rectangle_unref
+ gst_video_overlay_rectangle_get_pixels_argb
+ gst_video_overlay_rectangle_get_pixels_unscaled_argb
+ gst_video_overlay_rectangle_get_render_rectangle
+ gst_video_overlay_rectangle_get_seqnum
+ gst_video_overlay_rectangle_set_render_rectangle
+ gst_video_overlay_rectangle_copy
+ <SUBSECTION Standard>
+ GST_TYPE_VIDEO_OVERLAY_COMPOSITION
+ GST_VIDEO_OVERLAY_COMPOSITION
+ GST_VIDEO_OVERLAY_COMPOSITION_CLASS
+ GST_VIDEO_OVERLAY_COMPOSITION_GET_CLASS
+ GST_IS_VIDEO_OVERLAY_COMPOSITION
+ GST_IS_VIDEO_VIDEO_OVERLAY_COMPOSITION_CLASS
+ gst_video_overlay_composition_get_type
+ GST_TYPE_VIDEO_OVERLAY_RECTANGLE
+ GST_VIDEO_OVERLAY_RECTANGLE
+ GST_VIDEO_OVERLAY_RECTANGLE_CLASS
+ GST_VIDEO_OVERLAY_RECTANGLE_GET_CLASS
+ GST_IS_VIDEO_OVERLAY_RECTANGLE
+ GST_IS_VIDEO_VIDEO_OVERLAY_RECTANGLE_CLASS
+ gst_video_overlay_rectangle_get_type
+ </SECTION>
+ <SECTION>
  <FILE>gstvideofilter</FILE>
  <INCLUDE>gst/video/gstvideofilter.h</INCLUDE>
  GstVideoFilter
diff --combined ext/alsa/gstalsamixer.c
  #include "config.h"
  #endif
  
+ /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+  * with newer GLib versions (>= 2.31.0) */
+ #define GLIB_DISABLE_DEPRECATION_WARNINGS
  #include "gstalsamixer.h"
+ #include "gst/glib-compat-private.h"
  #include <errno.h>
  
  static void gst_alsa_mixer_update_option (GstAlsaMixer * mixer,
@@@ -130,14 -135,14 +135,14 @@@ gst_alsa_mixer_find_master_mixer (GstAl
  
    count = snd_mixer_get_count (handle);
  
-   g_static_rec_mutex_lock (mixer->rec_mutex);
+   GST_ALSA_MIXER_LOCK (mixer);
  
    /* Check if we have a playback mixer labelled as 'Master' */
    element = snd_mixer_first_elem (handle);
    for (i = 0; i < count; i++) {
      if (snd_mixer_selem_has_playback_volume (element) &&
          strcmp (snd_mixer_selem_get_name (element), "Master") == 0) {
-       g_static_rec_mutex_unlock (mixer->rec_mutex);
+       GST_ALSA_MIXER_UNLOCK (mixer);
        return element;
      }
      element = snd_mixer_elem_next (element);
    for (i = 0; i < count; i++) {
      if (snd_mixer_selem_has_playback_volume (element) &&
          strcmp (snd_mixer_selem_get_name (element), "Front") == 0) {
-       g_static_rec_mutex_unlock (mixer->rec_mutex);
+       GST_ALSA_MIXER_UNLOCK (mixer);
        return element;
      }
      element = snd_mixer_elem_next (element);
    for (i = 0; i < count; i++) {
      if (snd_mixer_selem_has_playback_volume (element) &&
          strcmp (snd_mixer_selem_get_name (element), "PCM") == 0) {
-       g_static_rec_mutex_unlock (mixer->rec_mutex);
+       GST_ALSA_MIXER_UNLOCK (mixer);
        return element;
      }
      element = snd_mixer_elem_next (element);
    for (i = 0; i < count; i++) {
      if (snd_mixer_selem_has_playback_volume (element) &&
          strcmp (snd_mixer_selem_get_name (element), "Speaker") == 0) {
-       g_static_rec_mutex_unlock (mixer->rec_mutex);
+       GST_ALSA_MIXER_UNLOCK (mixer);
        return element;
      }
      element = snd_mixer_elem_next (element);
      if (snd_mixer_selem_has_playback_volume (element) &&
          snd_mixer_selem_has_playback_switch (element) &&
          !snd_mixer_selem_is_playback_mono (element)) {
-       g_static_rec_mutex_unlock (mixer->rec_mutex);
+       GST_ALSA_MIXER_UNLOCK (mixer);
        return element;
      }
      element = snd_mixer_elem_next (element);
    for (i = 0; i < count; i++) {
      if (snd_mixer_selem_has_playback_volume (element) &&
          snd_mixer_selem_has_playback_switch (element)) {
-       g_static_rec_mutex_unlock (mixer->rec_mutex);
+       GST_ALSA_MIXER_UNLOCK (mixer);
        return element;
      }
      element = snd_mixer_elem_next (element);
    element = snd_mixer_first_elem (handle);
    for (i = 0; i < count; i++) {
      if (snd_mixer_selem_has_playback_volume (element)) {
-       g_static_rec_mutex_unlock (mixer->rec_mutex);
+       GST_ALSA_MIXER_UNLOCK (mixer);
        return element;
      }
      element = snd_mixer_elem_next (element);
    }
  
-   g_static_rec_mutex_unlock (mixer->rec_mutex);
+   GST_ALSA_MIXER_UNLOCK (mixer);
    /* Looks like we're out of luck ... */
    return NULL;
  }
@@@ -222,7 -227,7 +227,7 @@@ gst_alsa_mixer_update (GstAlsaMixer * m
  
    g_return_if_fail (mixer != NULL);
  
-   g_static_rec_mutex_lock (mixer->rec_mutex);
+   GST_ALSA_MIXER_LOCK (mixer);
  
    for (item = mixer->tracklist; item != NULL; item = item->next) {
      if (GST_IS_ALSA_MIXER_TRACK (item->data)) {
      }
    }
  
-   g_static_rec_mutex_unlock (mixer->rec_mutex);
+   GST_ALSA_MIXER_UNLOCK (mixer);
  }
  
  static int
@@@ -287,7 -292,7 +292,7 @@@ gst_alsa_mixer_ensure_track_list (GstAl
    if (mixer->tracklist)
      return;
  
-   g_static_rec_mutex_lock (mixer->rec_mutex);
+   GST_ALSA_MIXER_LOCK (mixer);
  
    master = gst_alsa_mixer_find_master_mixer (mixer, mixer->handle);
  
      snd_mixer_elem_set_callback_private (temp, mixer);
    }
  
-   g_static_rec_mutex_unlock (mixer->rec_mutex);
+   GST_ALSA_MIXER_UNLOCK (mixer);
  }
  
  static void
@@@ -421,13 -426,13 +426,13 @@@ task_monitor_alsa (gpointer data
    GstAlsaMixer *mixer = (GstAlsaMixer *) data;
    gint ret;
  
-   g_static_rec_mutex_lock (mixer->rec_mutex);
+   GST_ALSA_MIXER_LOCK (mixer);
  
    nfds = snd_mixer_poll_descriptors_count (mixer->handle);
    if (nfds <= 0) {
      GST_ERROR ("snd_mixer_poll_descriptors_count <= 0: %d", nfds);
      /* FIXME: sleep ? stop monitoring ? */
-     g_static_rec_mutex_unlock (mixer->rec_mutex);
+     GST_ALSA_MIXER_UNLOCK (mixer);
      return;
    }
  
      GST_ELEMENT_ERROR (mixer, RESOURCE, READ, (NULL), ("alsa error: %s",
              snd_strerror (rnfds)));
      gst_task_pause (mixer->task);
-     g_static_rec_mutex_unlock (mixer->rec_mutex);
+     GST_ALSA_MIXER_UNLOCK (mixer);
      return;
    }
  
    pfds[rnfds].events = POLLIN | POLLPRI | POLLHUP | POLLERR;
    pfds[rnfds].revents = 0;
  
-   g_static_rec_mutex_unlock (mixer->rec_mutex);
+   GST_ALSA_MIXER_UNLOCK (mixer);
  
    GST_LOG ("task loop");
    ret = poll (pfds, rnfds + 1, -1);
      return;
    }
  
-   g_static_rec_mutex_lock (mixer->rec_mutex);
+   GST_ALSA_MIXER_LOCK (mixer);
  
    ret =
        snd_mixer_poll_descriptors_revents (mixer->handle, pfds, nfds, &revents);
      gst_task_pause (mixer->task);
    }
  
-   g_static_rec_mutex_unlock (mixer->rec_mutex);
+   GST_ALSA_MIXER_UNLOCK (mixer);
  }
  
  /* API */
@@@ -491,14 -496,15 +496,15 @@@ gst_alsa_mixer_new (const char *device
    if (pipe (ret->pfd) == -1)
      goto error;
  
-   ret->rec_mutex = g_new (GStaticRecMutex, 1);
-   g_static_rec_mutex_init (ret->rec_mutex);
-   ret->task_mutex = g_new (GStaticRecMutex, 1);
-   g_static_rec_mutex_init (ret->task_mutex);
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
+   g_static_rec_mutex_init (&ret->rec_mutex);
+ #else
+   g_rec_mutex_init (&ret->rec_mutex);
+ #endif
+   g_static_rec_mutex_init (&ret->task_mutex);
  
 -  ret->task = gst_task_create (task_monitor_alsa, ret);
 +  ret->task = gst_task_new (task_monitor_alsa, ret);
-   gst_task_set_lock (ret->task, ret->task_mutex);
+   gst_task_set_lock (ret->task, &ret->task_mutex);
  
    ret->device = g_strdup (device);
    ret->dir = dir;
@@@ -540,9 -546,7 +546,7 @@@ gst_alsa_mixer_free (GstAlsaMixer * mix
      mixer->task = NULL;
    }
  
-   g_static_rec_mutex_free (mixer->task_mutex);
-   g_free (mixer->task_mutex);
-   mixer->task_mutex = NULL;
+   g_static_rec_mutex_free (&mixer->task_mutex);
  
    if (mixer->pfd[0] > 0) {
      close (mixer->pfd[0]);
      snd_mixer_close (mixer->handle);
      mixer->handle = NULL;
    }
-   g_static_rec_mutex_free (mixer->rec_mutex);
-   g_free (mixer->rec_mutex);
-   mixer->rec_mutex = NULL;
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
+   g_static_rec_mutex_free (&mixer->rec_mutex);
+ #else
+   g_rec_mutex_clear (&mixer->rec_mutex);
+ #endif
  
    g_free (mixer);
  }
@@@ -606,7 -611,7 +611,7 @@@ gst_alsa_mixer_get_volume (GstAlsaMixe
  
    g_return_if_fail (mixer->handle != NULL);
  
-   g_static_rec_mutex_lock (mixer->rec_mutex);
+   GST_ALSA_MIXER_LOCK (mixer);
  
    gst_alsa_mixer_track_update (alsa_track);
  
          volumes[i] = alsa_track->volumes[i];
      }
    }
-   g_static_rec_mutex_unlock (mixer->rec_mutex);
+   GST_ALSA_MIXER_UNLOCK (mixer);
  }
  
  static gboolean
@@@ -670,7 -675,7 +675,7 @@@ gst_alsa_mixer_set_volume (GstAlsaMixe
  
    g_return_if_fail (mixer->handle != NULL);
  
-   g_static_rec_mutex_lock (mixer->rec_mutex);
+   GST_ALSA_MIXER_LOCK (mixer);
  
    gst_alsa_mixer_track_update (alsa_track);
  
          alsa_track->volumes[i] = volumes[i];
      }
    }
-   g_static_rec_mutex_unlock (mixer->rec_mutex);
+   GST_ALSA_MIXER_UNLOCK (mixer);
  }
  
  void
@@@ -729,12 -734,12 +734,12 @@@ gst_alsa_mixer_set_mute (GstAlsaMixer 
  
    g_return_if_fail (mixer->handle != NULL);
  
-   g_static_rec_mutex_lock (mixer->rec_mutex);
+   GST_ALSA_MIXER_LOCK (mixer);
  
    gst_alsa_mixer_track_update (alsa_track);
  
    if (! !(mute) == ! !(track->flags & GST_MIXER_TRACK_MUTE)) {
-     g_static_rec_mutex_unlock (mixer->rec_mutex);
+     GST_ALSA_MIXER_UNLOCK (mixer);
      return;
    }
    if (mute) {
  
      for (i = 0; i < ((GstMixerTrack *) ctrl_track)->num_channels; i++) {
        long vol =
-           mute ? ((GstMixerTrack *) ctrl_track)->
-           min_volume : ctrl_track->volumes[i];
+           mute ? ((GstMixerTrack *) ctrl_track)->min_volume : ctrl_track->
+           volumes[i];
        snd_mixer_selem_set_playback_volume (ctrl_track->element, i, vol);
      }
    }
-   g_static_rec_mutex_unlock (mixer->rec_mutex);
+   GST_ALSA_MIXER_UNLOCK (mixer);
  }
  
  void
@@@ -781,12 -786,12 +786,12 @@@ gst_alsa_mixer_set_record (GstAlsaMixe
  
    g_return_if_fail (mixer->handle != NULL);
  
-   g_static_rec_mutex_lock (mixer->rec_mutex);
+   GST_ALSA_MIXER_LOCK (mixer);
  
    gst_alsa_mixer_track_update (alsa_track);
  
    if (! !(record) == ! !(track->flags & GST_MIXER_TRACK_RECORD)) {
-     g_static_rec_mutex_unlock (mixer->rec_mutex);
+     GST_ALSA_MIXER_UNLOCK (mixer);
      return;
    }
  
        snd_mixer_selem_set_capture_volume (alsa_track->element, i, vol);
      }
    }
-   g_static_rec_mutex_unlock (mixer->rec_mutex);
+   GST_ALSA_MIXER_UNLOCK (mixer);
  }
  
  void
@@@ -848,9 -853,9 +853,9 @@@ gst_alsa_mixer_set_option (GstAlsaMixe
    if (idx == -1)
      return;
  
-   g_static_rec_mutex_lock (mixer->rec_mutex);
+   GST_ALSA_MIXER_LOCK (mixer);
    snd_mixer_selem_set_enum_item (alsa_opts->element, 0, idx);
-   g_static_rec_mutex_unlock (mixer->rec_mutex);
+   GST_ALSA_MIXER_UNLOCK (mixer);
  }
  
  const gchar *
@@@ -861,9 -866,9 +866,9 @@@ gst_alsa_mixer_get_option (GstAlsaMixe
    GstAlsaMixerOptions *alsa_opts = GST_ALSA_MIXER_OPTIONS (opts);
  
    g_return_val_if_fail (mixer->handle != NULL, NULL);
-   g_static_rec_mutex_lock (mixer->rec_mutex);
+   GST_ALSA_MIXER_LOCK (mixer);
    ret = snd_mixer_selem_get_enum_item (alsa_opts->element, 0, &idx);
-   g_static_rec_mutex_unlock (mixer->rec_mutex);
+   GST_ALSA_MIXER_UNLOCK (mixer);
    if (ret == 0)
      return g_list_nth_data (opts->values, idx);
    else
@@@ -890,9 -895,9 +895,9 @@@ gst_alsa_mixer_update_option (GstAlsaMi
      GST_WARNING ("Cannot send update notifications, no GstMixer * given");
      return;
    }
-   g_static_rec_mutex_lock (mixer->rec_mutex);
+   GST_ALSA_MIXER_LOCK (mixer);
    ret = snd_mixer_selem_get_enum_item (alsa_opts->element, 0, &idx);
-   g_static_rec_mutex_unlock (mixer->rec_mutex);
+   GST_ALSA_MIXER_UNLOCK (mixer);
    if (ret == 0) {
      option = g_list_nth_data (GST_MIXER_OPTIONS (alsa_opts)->values, idx);
      gst_mixer_option_changed (mixer->interface, GST_MIXER_OPTIONS (alsa_opts),
diff --combined ext/alsa/gstalsamixer.h
@@@ -23,7 -23,7 +23,7 @@@
  
  #include "gstalsa.h"
  
 -#include <gst/interfaces/mixer.h>
 +#include <gst/audio/mixer.h>
  #include "gstalsamixeroptions.h"
  #include "gstalsamixertrack.h"
  
@@@ -53,8 -53,13 +53,13 @@@ struct _GstAlsaMixe
    snd_mixer_t *         handle;
  
    GstTask *           task;
-   GStaticRecMutex *   task_mutex;
-   GStaticRecMutex *   rec_mutex;
+   GStaticRecMutex     task_mutex;
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
+   GStaticRecMutex     rec_mutex;
+ #else
+   GRecMutex           rec_mutex;
+ #endif
  
    int                 pfd[2];
  
    GstAlsaMixerDirection dir;
  };
  
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
+ #define GST_ALSA_MIXER_LOCK(mixer)   g_static_rec_mutex_lock (&mixer->rec_mutex)
+ #define GST_ALSA_MIXER_UNLOCK(mixer) g_static_rec_mutex_unlock (&mixer->rec_mutex)
+ #else
+ #define GST_ALSA_MIXER_LOCK(mixer)   g_rec_mutex_lock (&mixer->rec_mutex)
+ #define GST_ALSA_MIXER_UNLOCK(mixer) g_rec_mutex_unlock (&mixer->rec_mutex)
+ #endif
  
  GstAlsaMixer*   gst_alsa_mixer_new              (const gchar *device,
                                                   GstAlsaMixerDirection dir);
@@@ -93,6 -105,14 +105,6 @@@ void               _gst_alsa_mixer_set_interface   (
  GstMixerFlags   gst_alsa_mixer_get_mixer_flags  (GstAlsaMixer *mixer);
  
  #define GST_IMPLEMENT_ALSA_MIXER_METHODS(Type, interface_as_function)           \
 -static gboolean                                                                 \
 -interface_as_function ## _supported (Type *this, GType iface_type)              \
 -{                                                                               \
 -  g_assert (iface_type == GST_TYPE_MIXER);                                      \
 -                                                                                \
 -  return (this->mixer != NULL);                                                 \
 -}                                                                               \
 -                                                                                \
  static const GList*                                                             \
  interface_as_function ## _list_tracks (GstMixer * mixer)                        \
  {                                                                               \
@@@ -187,19 -207,19 +199,19 @@@ interface_as_function ## _get_mixer_fla
  }                                                                               \
                                                                                  \
  static void                                                                     \
 -interface_as_function ## _interface_init (GstMixerClass * klass)                \
 +interface_as_function ## _interface_init (GstMixerInterface * iface)            \
  {                                                                               \
 -  GST_MIXER_TYPE (klass) = GST_MIXER_HARDWARE;                                  \
 +  GST_MIXER_TYPE (iface) = GST_MIXER_HARDWARE;                                  \
                                                                                  \
    /* set up the interface hooks */                                              \
 -  klass->list_tracks = interface_as_function ## _list_tracks;                   \
 -  klass->set_volume = interface_as_function ## _set_volume;                     \
 -  klass->get_volume = interface_as_function ## _get_volume;                     \
 -  klass->set_mute = interface_as_function ## _set_mute;                         \
 -  klass->set_record = interface_as_function ## _set_record;                     \
 -  klass->set_option = interface_as_function ## _set_option;                     \
 -  klass->get_option = interface_as_function ## _get_option;                     \
 -  klass->get_mixer_flags = interface_as_function ## _get_mixer_flags;           \
 +  iface->list_tracks = interface_as_function ## _list_tracks;                   \
 +  iface->set_volume = interface_as_function ## _set_volume;                     \
 +  iface->get_volume = interface_as_function ## _get_volume;                     \
 +  iface->set_mute = interface_as_function ## _set_mute;                         \
 +  iface->set_record = interface_as_function ## _set_record;                     \
 +  iface->set_option = interface_as_function ## _set_option;                     \
 +  iface->get_option = interface_as_function ## _get_option;                     \
 +  iface->get_mixer_flags = interface_as_function ## _get_mixer_flags;           \
  }
  
  
diff --combined ext/alsa/gstalsasink.c
@@@ -52,6 -52,7 +52,7 @@@
  #include "gstalsadeviceprobe.h"
  
  #include <gst/gst-i18n-plugin.h>
+ #include "gst/glib-compat-private.h"
  
  #define DEFAULT_DEVICE                "default"
  #define DEFAULT_DEVICE_NAME   ""
@@@ -69,9 -70,9 +70,9 @@@ enu
  };
  
  static void gst_alsasink_init_interfaces (GType type);
 -
 -GST_BOILERPLATE_FULL (GstAlsaSink, gst_alsasink, GstAudioSink,
 -    GST_TYPE_AUDIO_SINK, gst_alsasink_init_interfaces);
 +#define gst_alsasink_parent_class parent_class
 +G_DEFINE_TYPE_WITH_CODE (GstAlsaSink, gst_alsasink,
 +    GST_TYPE_AUDIO_SINK, gst_alsasink_init_interfaces (g_define_type_id));
  
  static void gst_alsasink_finalise (GObject * object);
  static void gst_alsasink_set_property (GObject * object,
  static void gst_alsasink_get_property (GObject * object,
      guint prop_id, GValue * value, GParamSpec * pspec);
  
 -static GstCaps *gst_alsasink_getcaps (GstBaseSink * bsink);
 +static GstCaps *gst_alsasink_getcaps (GstBaseSink * bsink, GstCaps * filter);
  
  static gboolean gst_alsasink_open (GstAudioSink * asink);
  static gboolean gst_alsasink_prepare (GstAudioSink * asink,
 -    GstRingBufferSpec * spec);
 +    GstAudioRingBufferSpec * spec);
  static gboolean gst_alsasink_unprepare (GstAudioSink * asink);
  static gboolean gst_alsasink_close (GstAudioSink * asink);
 -static guint gst_alsasink_write (GstAudioSink * asink, gpointer data,
 +static gint gst_alsasink_write (GstAudioSink * asink, gpointer data,
      guint length);
  static guint gst_alsasink_delay (GstAudioSink * asink);
  static void gst_alsasink_reset (GstAudioSink * asink);
@@@ -95,13 -96,46 +96,13 @@@ static gint output_ref;         /* 
  static snd_output_t *output;    /* NULL */
  static GStaticMutex output_mutex = G_STATIC_MUTEX_INIT;
  
 -
 -#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
 -# define ALSA_SINK_FACTORY_ENDIANNESS "LITTLE_ENDIAN, BIG_ENDIAN"
 -#else
 -# define ALSA_SINK_FACTORY_ENDIANNESS "BIG_ENDIAN, LITTLE_ENDIAN"
 -#endif
 -
  static GstStaticPadTemplate alsasink_sink_factory =
      GST_STATIC_PAD_TEMPLATE ("sink",
      GST_PAD_SINK,
      GST_PAD_ALWAYS,
 -    GST_STATIC_CAPS ("audio/x-raw-int, "
 -        "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
 -        "signed = (boolean) { TRUE, FALSE }, "
 -        "width = (int) 32, "
 -        "depth = (int) 32, "
 -        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
 -        "audio/x-raw-int, "
 -        "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
 -        "signed = (boolean) { TRUE, FALSE }, "
 -        "width = (int) 24, "
 -        "depth = (int) 24, "
 -        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
 -        "audio/x-raw-int, "
 -        "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
 -        "signed = (boolean) { TRUE, FALSE }, "
 -        "width = (int) 32, "
 -        "depth = (int) 24, "
 +    GST_STATIC_CAPS ("audio/x-raw, "
 +        "formats = (string) " GST_AUDIO_FORMATS_ALL ", "
          "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
 -        "audio/x-raw-int, "
 -        "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
 -        "signed = (boolean) { TRUE, FALSE }, "
 -        "width = (int) 16, "
 -        "depth = (int) 16, "
 -        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
 -        "audio/x-raw-int, "
 -        "signed = (boolean) { TRUE, FALSE }, "
 -        "width = (int) 8, "
 -        "depth = (int) 8, "
 -        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ];"
          "audio/x-iec958")
      );
  
@@@ -131,15 -165,26 +132,15 @@@ gst_alsasink_init_interfaces (GType typ
  }
  
  static void
 -gst_alsasink_base_init (gpointer g_class)
 -{
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 -
 -  gst_element_class_set_details_simple (element_class,
 -      "Audio sink (ALSA)", "Sink/Audio",
 -      "Output to a sound card via ALSA", "Wim Taymans <wim@fluendo.com>");
 -
 -  gst_element_class_add_static_pad_template (element_class,
 -      &alsasink_sink_factory);
 -}
 -
 -static void
  gst_alsasink_class_init (GstAlsaSinkClass * klass)
  {
    GObjectClass *gobject_class;
 +  GstElementClass *gstelement_class;
    GstBaseSinkClass *gstbasesink_class;
    GstAudioSinkClass *gstaudiosink_class;
  
    gobject_class = (GObjectClass *) klass;
 +  gstelement_class = (GstElementClass *) klass;
    gstbasesink_class = (GstBaseSinkClass *) klass;
    gstaudiosink_class = (GstAudioSinkClass *) klass;
  
    gobject_class->get_property = gst_alsasink_get_property;
    gobject_class->set_property = gst_alsasink_set_property;
  
 +  gst_element_class_set_details_simple (gstelement_class,
 +      "Audio sink (ALSA)", "Sink/Audio",
 +      "Output to a sound card via ALSA", "Wim Taymans <wim@fluendo.com>");
 +
 +  gst_element_class_add_pad_template (gstelement_class,
 +      gst_static_pad_template_get (&alsasink_sink_factory));
 +
    gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasink_getcaps);
  
    gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_alsasink_open);
@@@ -234,7 -272,7 +235,7 @@@ gst_alsasink_get_property (GObject * ob
  }
  
  static void
 -gst_alsasink_init (GstAlsaSink * alsasink, GstAlsaSinkClass * g_class)
 +gst_alsasink_init (GstAlsaSink * alsasink)
  {
    GST_DEBUG_OBJECT (alsasink, "initializing alsasink");
  
@@@ -258,12 -296,12 +259,12 @@@ if ((err = call) < 0)           
  } G_STMT_END;
  
  static GstCaps *
 -gst_alsasink_getcaps (GstBaseSink * bsink)
 +gst_alsasink_getcaps (GstBaseSink * bsink, GstCaps * filter)
  {
    GstElementClass *element_class;
    GstPadTemplate *pad_template;
    GstAlsaSink *sink = GST_ALSA_SINK (bsink);
 -  GstCaps *caps;
 +  GstCaps *caps, *templ_caps;
  
    if (sink->handle == NULL) {
      GST_DEBUG_OBJECT (sink, "device not open, using template caps");
  
    if (sink->cached_caps) {
      GST_LOG_OBJECT (sink, "Returning cached caps");
 -    return gst_caps_ref (sink->cached_caps);
 +    if (filter)
 +      return gst_caps_intersect_full (filter, sink->cached_caps,
 +          GST_CAPS_INTERSECT_FIRST);
 +    else
 +      return gst_caps_ref (sink->cached_caps);
    }
  
    element_class = GST_ELEMENT_GET_CLASS (sink);
    pad_template = gst_element_class_get_pad_template (element_class, "sink");
    g_return_val_if_fail (pad_template != NULL, NULL);
  
 +  templ_caps = gst_pad_template_get_caps (pad_template);
    caps = gst_alsa_probe_supported_formats (GST_OBJECT (sink), sink->handle,
 -      gst_pad_template_get_caps (pad_template));
 +      templ_caps);
 +  gst_caps_unref (templ_caps);
  
    if (caps) {
      sink->cached_caps = gst_caps_ref (caps);
  
    GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, caps);
  
 -  return caps;
 +  if (filter) {
 +    GstCaps *intersection;
 +
 +    intersection =
 +        gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
 +    gst_caps_unref (caps);
 +    return intersection;
 +  } else {
 +    return caps;
 +  }
  }
  
  static int
@@@ -588,102 -611,32 +589,102 @@@ set_sw_params
  }
  
  static gboolean
 -alsasink_parse_spec (GstAlsaSink * alsa, GstRingBufferSpec * spec)
 +alsasink_parse_spec (GstAlsaSink * alsa, GstAudioRingBufferSpec * spec)
  {
    /* Initialize our boolean */
    alsa->iec958 = FALSE;
  
    switch (spec->type) {
 -    case GST_BUFTYPE_LINEAR:
 -      GST_DEBUG_OBJECT (alsa,
 -          "Linear format : depth=%d, width=%d, sign=%d, bigend=%d", spec->depth,
 -          spec->width, spec->sign, spec->bigend);
 -
 -      alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width,
 -          spec->sign ? 0 : 1, spec->bigend ? 1 : 0);
 -      break;
 -    case GST_BUFTYPE_FLOAT:
 -      switch (spec->format) {
 -        case GST_FLOAT32_LE:
 +    case GST_BUFTYPE_RAW:
 +      switch (GST_AUDIO_INFO_FORMAT (&spec->info)) {
 +        case GST_AUDIO_FORMAT_U8:
 +          alsa->format = SND_PCM_FORMAT_U8;
 +          break;
 +        case GST_AUDIO_FORMAT_S8:
 +          alsa->format = SND_PCM_FORMAT_S8;
 +          break;
 +        case GST_AUDIO_FORMAT_S16LE:
 +          alsa->format = SND_PCM_FORMAT_S16_LE;
 +          break;
 +        case GST_AUDIO_FORMAT_S16BE:
 +          alsa->format = SND_PCM_FORMAT_S16_BE;
 +          break;
 +        case GST_AUDIO_FORMAT_U16LE:
 +          alsa->format = SND_PCM_FORMAT_U16_LE;
 +          break;
 +        case GST_AUDIO_FORMAT_U16BE:
 +          alsa->format = SND_PCM_FORMAT_U16_BE;
 +          break;
 +        case GST_AUDIO_FORMAT_S24_32LE:
 +          alsa->format = SND_PCM_FORMAT_S24_LE;
 +          break;
 +        case GST_AUDIO_FORMAT_S24_32BE:
 +          alsa->format = SND_PCM_FORMAT_S24_BE;
 +          break;
 +        case GST_AUDIO_FORMAT_U24_32LE:
 +          alsa->format = SND_PCM_FORMAT_U24_LE;
 +          break;
 +        case GST_AUDIO_FORMAT_U24_32BE:
 +          alsa->format = SND_PCM_FORMAT_U24_BE;
 +          break;
 +        case GST_AUDIO_FORMAT_S32LE:
 +          alsa->format = SND_PCM_FORMAT_S32_LE;
 +          break;
 +        case GST_AUDIO_FORMAT_S32BE:
 +          alsa->format = SND_PCM_FORMAT_S32_BE;
 +          break;
 +        case GST_AUDIO_FORMAT_U32LE:
 +          alsa->format = SND_PCM_FORMAT_U32_LE;
 +          break;
 +        case GST_AUDIO_FORMAT_U32BE:
 +          alsa->format = SND_PCM_FORMAT_U32_BE;
 +          break;
 +        case GST_AUDIO_FORMAT_S24LE:
 +          alsa->format = SND_PCM_FORMAT_S24_3LE;
 +          break;
 +        case GST_AUDIO_FORMAT_S24BE:
 +          alsa->format = SND_PCM_FORMAT_S24_3BE;
 +          break;
 +        case GST_AUDIO_FORMAT_U24LE:
 +          alsa->format = SND_PCM_FORMAT_U24_3LE;
 +          break;
 +        case GST_AUDIO_FORMAT_U24BE:
 +          alsa->format = SND_PCM_FORMAT_U24_3BE;
 +          break;
 +        case GST_AUDIO_FORMAT_S20LE:
 +          alsa->format = SND_PCM_FORMAT_S20_3LE;
 +          break;
 +        case GST_AUDIO_FORMAT_S20BE:
 +          alsa->format = SND_PCM_FORMAT_S20_3BE;
 +          break;
 +        case GST_AUDIO_FORMAT_U20LE:
 +          alsa->format = SND_PCM_FORMAT_U20_3LE;
 +          break;
 +        case GST_AUDIO_FORMAT_U20BE:
 +          alsa->format = SND_PCM_FORMAT_U20_3BE;
 +          break;
 +        case GST_AUDIO_FORMAT_S18LE:
 +          alsa->format = SND_PCM_FORMAT_S18_3LE;
 +          break;
 +        case GST_AUDIO_FORMAT_S18BE:
 +          alsa->format = SND_PCM_FORMAT_S18_3BE;
 +          break;
 +        case GST_AUDIO_FORMAT_U18LE:
 +          alsa->format = SND_PCM_FORMAT_U18_3LE;
 +          break;
 +        case GST_AUDIO_FORMAT_U18BE:
 +          alsa->format = SND_PCM_FORMAT_U18_3BE;
 +          break;
 +        case GST_AUDIO_FORMAT_F32LE:
            alsa->format = SND_PCM_FORMAT_FLOAT_LE;
            break;
 -        case GST_FLOAT32_BE:
 +        case GST_AUDIO_FORMAT_F32BE:
            alsa->format = SND_PCM_FORMAT_FLOAT_BE;
            break;
 -        case GST_FLOAT64_LE:
 +        case GST_AUDIO_FORMAT_F64LE:
            alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
            break;
 -        case GST_FLOAT64_BE:
 +        case GST_AUDIO_FORMAT_F64BE:
            alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
            break;
          default:
        goto error;
  
    }
 -  alsa->rate = spec->rate;
 -  alsa->channels = spec->channels;
 +  alsa->rate = GST_AUDIO_INFO_RATE (&spec->info);
 +  alsa->channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
    alsa->buffer_time = spec->buffer_time;
    alsa->period_time = spec->latency_time;
    alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
@@@ -754,14 -707,14 +755,14 @@@ open_error
  }
  
  static gboolean
 -gst_alsasink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
 +gst_alsasink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec)
  {
    GstAlsaSink *alsa;
    gint err;
  
    alsa = GST_ALSA_SINK (asink);
  
 -  if (spec->format == GST_IEC958) {
 +  if (spec->type == GST_BUFTYPE_IEC958) {
      snd_pcm_close (alsa->handle);
      alsa->handle = gst_alsa_open_iec958_pcm (GST_OBJECT (alsa));
      if (G_UNLIKELY (!alsa->handle)) {
    CHECK (set_hwparams (alsa), hw_params_failed);
    CHECK (set_swparams (alsa), sw_params_failed);
  
 -  alsa->bytes_per_sample = spec->bytes_per_sample;
 -  spec->segsize = alsa->period_size * spec->bytes_per_sample;
 +  alsa->bpf = GST_AUDIO_INFO_BPF (&spec->info);
 +  spec->segsize = alsa->period_size * alsa->bpf;
    spec->segtotal = alsa->buffer_size / alsa->period_size;
  
    {
@@@ -883,7 -836,7 +884,7 @@@ xrun_recovery (GstAlsaSink * alsa, snd_
    return err;
  }
  
 -static guint
 +static gint
  gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
  {
    GstAlsaSink *alsa;
  
    GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length);
  
 -  cptr = length / alsa->bytes_per_sample;
 +  cptr = length / alsa->bpf;
  
    GST_ALSA_SINK_LOCK (asink);
    while (cptr > 0) {
    }
    GST_ALSA_SINK_UNLOCK (asink);
  
 -  return length - (cptr * alsa->bytes_per_sample);
 +  return length - (cptr * alsa->bpf);
  
  write_error:
    {
diff --combined ext/alsa/gstalsasrc.c
@@@ -48,6 -48,7 +48,7 @@@
  
  #include "gstalsasrc.h"
  #include "gstalsadeviceprobe.h"
+ #include "gst/glib-compat-private.h"
  
  #include <gst/gst-i18n-plugin.h>
  
@@@ -65,9 -66,9 +66,9 @@@ enu
  };
  
  static void gst_alsasrc_init_interfaces (GType type);
 -
 -GST_BOILERPLATE_FULL (GstAlsaSrc, gst_alsasrc, GstAudioSrc,
 -    GST_TYPE_AUDIO_SRC, gst_alsasrc_init_interfaces);
 +#define gst_alsasrc_parent_class parent_class
 +G_DEFINE_TYPE_WITH_CODE (GstAlsaSrc, gst_alsasrc,
 +    GST_TYPE_AUDIO_SRC, gst_alsasrc_init_interfaces (g_define_type_id));
  
  GST_IMPLEMENT_ALSA_MIXER_METHODS (GstAlsaSrc, gst_alsasrc_mixer);
  
@@@ -77,11 -78,11 +78,11 @@@ static void gst_alsasrc_set_property (G
  static void gst_alsasrc_get_property (GObject * object,
      guint prop_id, GValue * value, GParamSpec * pspec);
  
 -static GstCaps *gst_alsasrc_getcaps (GstBaseSrc * bsrc);
 +static GstCaps *gst_alsasrc_getcaps (GstBaseSrc * bsrc, GstCaps * filter);
  
  static gboolean gst_alsasrc_open (GstAudioSrc * asrc);
  static gboolean gst_alsasrc_prepare (GstAudioSrc * asrc,
 -    GstRingBufferSpec * spec);
 +    GstAudioRingBufferSpec * spec);
  static gboolean gst_alsasrc_unprepare (GstAudioSrc * asrc);
  static gboolean gst_alsasrc_close (GstAudioSrc * asrc);
  static guint gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length);
@@@ -101,11 -102,37 +102,11 @@@ enu
  #endif
  
  static GstStaticPadTemplate alsasrc_src_factory =
 -    GST_STATIC_PAD_TEMPLATE ("src",
 +GST_STATIC_PAD_TEMPLATE ("src",
      GST_PAD_SRC,
      GST_PAD_ALWAYS,
 -    GST_STATIC_CAPS ("audio/x-raw-int, "
 -        "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
 -        "signed = (boolean) { TRUE, FALSE }, "
 -        "width = (int) 32, "
 -        "depth = (int) 32, "
 -        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
 -        "audio/x-raw-int, "
 -        "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
 -        "signed = (boolean) { TRUE, FALSE }, "
 -        "width = (int) 32, "
 -        "depth = (int) 24, "
 -        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
 -        "audio/x-raw-int, "
 -        "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
 -        "signed = (boolean) { TRUE, FALSE }, "
 -        "width = (int) 24, "
 -        "depth = (int) 24, "
 -        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
 -        "audio/x-raw-int, "
 -        "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
 -        "signed = (boolean) { TRUE, FALSE }, "
 -        "width = (int) 16, "
 -        "depth = (int) 16, "
 -        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
 -        "audio/x-raw-int, "
 -        "signed = (boolean) { TRUE, FALSE }, "
 -        "width = (int) 8, "
 -        "depth = (int) 8, "
 +    GST_STATIC_CAPS ("audio/x-raw, "
 +        "format = (string) " GST_AUDIO_FORMATS_ALL ", "
          "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]")
      );
  
@@@ -120,30 -147,63 +121,30 @@@ gst_alsasrc_finalize (GObject * object
    G_OBJECT_CLASS (parent_class)->finalize (object);
  }
  
 -static gboolean
 -gst_alsasrc_interface_supported (GstAlsaSrc * this, GType interface_type)
 -{
 -  /* only support this one interface (wrapped by GstImplementsInterface) */
 -  g_assert (interface_type == GST_TYPE_MIXER);
 -
 -  return gst_alsasrc_mixer_supported (this, interface_type);
 -}
 -
 -static void
 -gst_implements_interface_init (GstImplementsInterfaceClass * klass)
 -{
 -  klass->supported = (gpointer) gst_alsasrc_interface_supported;
 -}
 -
  static void
  gst_alsasrc_init_interfaces (GType type)
  {
 -  static const GInterfaceInfo implements_iface_info = {
 -    (GInterfaceInitFunc) gst_implements_interface_init,
 -    NULL,
 -    NULL,
 -  };
    static const GInterfaceInfo mixer_iface_info = {
      (GInterfaceInitFunc) gst_alsasrc_mixer_interface_init,
      NULL,
      NULL,
    };
  
 -  g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
 -      &implements_iface_info);
    g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info);
  
    gst_alsa_type_add_device_property_probe_interface (type);
  }
  
  static void
 -gst_alsasrc_base_init (gpointer g_class)
 -{
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 -
 -  gst_element_class_set_details_simple (element_class,
 -      "Audio source (ALSA)", "Source/Audio",
 -      "Read from a sound card via ALSA", "Wim Taymans <wim@fluendo.com>");
 -
 -  gst_element_class_add_static_pad_template (element_class,
 -      &alsasrc_src_factory);
 -}
 -
 -static void
  gst_alsasrc_class_init (GstAlsaSrcClass * klass)
  {
    GObjectClass *gobject_class;
 +  GstElementClass *gstelement_class;
    GstBaseSrcClass *gstbasesrc_class;
    GstAudioSrcClass *gstaudiosrc_class;
  
    gobject_class = (GObjectClass *) klass;
 +  gstelement_class = (GstElementClass *) klass;
    gstbasesrc_class = (GstBaseSrcClass *) klass;
    gstaudiosrc_class = (GstAudioSrcClass *) klass;
  
    gobject_class->get_property = gst_alsasrc_get_property;
    gobject_class->set_property = gst_alsasrc_set_property;
  
 +  gst_element_class_set_details_simple (gstelement_class,
 +      "Audio source (ALSA)", "Source/Audio",
 +      "Read from a sound card via ALSA", "Wim Taymans <wim@fluendo.com>");
 +
 +  gst_element_class_add_pad_template (gstelement_class,
 +      gst_static_pad_template_get (&alsasrc_src_factory));
 +
    gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasrc_getcaps);
  
    gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_alsasrc_open);
@@@ -235,7 -288,7 +236,7 @@@ gst_alsasrc_get_property (GObject * obj
  }
  
  static void
 -gst_alsasrc_init (GstAlsaSrc * alsasrc, GstAlsaSrcClass * g_class)
 +gst_alsasrc_init (GstAlsaSrc * alsasrc)
  {
    GST_DEBUG_OBJECT (alsasrc, "initializing");
  
@@@ -253,39 -306,31 +254,39 @@@ if ((err = call) < 0)           
  
  
  static GstCaps *
 -gst_alsasrc_getcaps (GstBaseSrc * bsrc)
 +gst_alsasrc_getcaps (GstBaseSrc * bsrc, GstCaps * filter)
  {
    GstElementClass *element_class;
    GstPadTemplate *pad_template;
    GstAlsaSrc *src;
 -  GstCaps *caps;
 +  GstCaps *caps, *templ_caps;
  
    src = GST_ALSA_SRC (bsrc);
  
    if (src->handle == NULL) {
      GST_DEBUG_OBJECT (src, "device not open, using template caps");
 -    return NULL;                /* base class will get template caps for us */
 +    return GST_BASE_SRC_CLASS (parent_class)->get_caps (bsrc, filter);
    }
  
    if (src->cached_caps) {
      GST_LOG_OBJECT (src, "Returning cached caps");
 -    return gst_caps_ref (src->cached_caps);
 +    if (filter)
 +      return gst_caps_intersect_full (filter, src->cached_caps,
 +          GST_CAPS_INTERSECT_FIRST);
 +    else
 +      return gst_caps_ref (src->cached_caps);
    }
  
    element_class = GST_ELEMENT_GET_CLASS (src);
    pad_template = gst_element_class_get_pad_template (element_class, "src");
    g_return_val_if_fail (pad_template != NULL, NULL);
  
 +  templ_caps = gst_pad_template_get_caps (pad_template);
 +  GST_INFO_OBJECT (src, "template caps %" GST_PTR_FORMAT, templ_caps);
 +
    caps = gst_alsa_probe_supported_formats (GST_OBJECT (src), src->handle,
 -      gst_pad_template_get_caps (pad_template));
 +      templ_caps);
 +  gst_caps_unref (templ_caps);
  
    if (caps) {
      src->cached_caps = gst_caps_ref (caps);
  
    GST_INFO_OBJECT (src, "returning caps %" GST_PTR_FORMAT, caps);
  
 -  return caps;
 +  if (filter) {
 +    GstCaps *intersection;
 +
 +    intersection =
 +        gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
 +    gst_caps_unref (caps);
 +    return intersection;
 +  } else {
 +    return caps;
 +  }
  }
  
  static int
@@@ -524,99 -560,25 +525,99 @@@ set_sw_params
  }
  
  static gboolean
 -alsasrc_parse_spec (GstAlsaSrc * alsa, GstRingBufferSpec * spec)
 +alsasrc_parse_spec (GstAlsaSrc * alsa, GstAudioRingBufferSpec * spec)
  {
    switch (spec->type) {
 -    case GST_BUFTYPE_LINEAR:
 -      alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width,
 -          spec->sign ? 0 : 1, spec->bigend ? 1 : 0);
 -      break;
 -    case GST_BUFTYPE_FLOAT:
 -      switch (spec->format) {
 -        case GST_FLOAT32_LE:
 +    case GST_BUFTYPE_RAW:
 +      switch (GST_AUDIO_INFO_FORMAT (&spec->info)) {
 +        case GST_AUDIO_FORMAT_U8:
 +          alsa->format = SND_PCM_FORMAT_U8;
 +          break;
 +        case GST_AUDIO_FORMAT_S8:
 +          alsa->format = SND_PCM_FORMAT_S8;
 +          break;
 +        case GST_AUDIO_FORMAT_S16LE:
 +          alsa->format = SND_PCM_FORMAT_S16_LE;
 +          break;
 +        case GST_AUDIO_FORMAT_S16BE:
 +          alsa->format = SND_PCM_FORMAT_S16_BE;
 +          break;
 +        case GST_AUDIO_FORMAT_U16LE:
 +          alsa->format = SND_PCM_FORMAT_U16_LE;
 +          break;
 +        case GST_AUDIO_FORMAT_U16BE:
 +          alsa->format = SND_PCM_FORMAT_U16_BE;
 +          break;
 +        case GST_AUDIO_FORMAT_S24_32LE:
 +          alsa->format = SND_PCM_FORMAT_S24_LE;
 +          break;
 +        case GST_AUDIO_FORMAT_S24_32BE:
 +          alsa->format = SND_PCM_FORMAT_S24_BE;
 +          break;
 +        case GST_AUDIO_FORMAT_U24_32LE:
 +          alsa->format = SND_PCM_FORMAT_U24_LE;
 +          break;
 +        case GST_AUDIO_FORMAT_U24_32BE:
 +          alsa->format = SND_PCM_FORMAT_U24_BE;
 +          break;
 +        case GST_AUDIO_FORMAT_S32LE:
 +          alsa->format = SND_PCM_FORMAT_S32_LE;
 +          break;
 +        case GST_AUDIO_FORMAT_S32BE:
 +          alsa->format = SND_PCM_FORMAT_S32_BE;
 +          break;
 +        case GST_AUDIO_FORMAT_U32LE:
 +          alsa->format = SND_PCM_FORMAT_U32_LE;
 +          break;
 +        case GST_AUDIO_FORMAT_U32BE:
 +          alsa->format = SND_PCM_FORMAT_U32_BE;
 +          break;
 +        case GST_AUDIO_FORMAT_S24LE:
 +          alsa->format = SND_PCM_FORMAT_S24_3LE;
 +          break;
 +        case GST_AUDIO_FORMAT_S24BE:
 +          alsa->format = SND_PCM_FORMAT_S24_3BE;
 +          break;
 +        case GST_AUDIO_FORMAT_U24LE:
 +          alsa->format = SND_PCM_FORMAT_U24_3LE;
 +          break;
 +        case GST_AUDIO_FORMAT_U24BE:
 +          alsa->format = SND_PCM_FORMAT_U24_3BE;
 +          break;
 +        case GST_AUDIO_FORMAT_S20LE:
 +          alsa->format = SND_PCM_FORMAT_S20_3LE;
 +          break;
 +        case GST_AUDIO_FORMAT_S20BE:
 +          alsa->format = SND_PCM_FORMAT_S20_3BE;
 +          break;
 +        case GST_AUDIO_FORMAT_U20LE:
 +          alsa->format = SND_PCM_FORMAT_U20_3LE;
 +          break;
 +        case GST_AUDIO_FORMAT_U20BE:
 +          alsa->format = SND_PCM_FORMAT_U20_3BE;
 +          break;
 +        case GST_AUDIO_FORMAT_S18LE:
 +          alsa->format = SND_PCM_FORMAT_S18_3LE;
 +          break;
 +        case GST_AUDIO_FORMAT_S18BE:
 +          alsa->format = SND_PCM_FORMAT_S18_3BE;
 +          break;
 +        case GST_AUDIO_FORMAT_U18LE:
 +          alsa->format = SND_PCM_FORMAT_U18_3LE;
 +          break;
 +        case GST_AUDIO_FORMAT_U18BE:
 +          alsa->format = SND_PCM_FORMAT_U18_3BE;
 +          break;
 +        case GST_AUDIO_FORMAT_F32LE:
            alsa->format = SND_PCM_FORMAT_FLOAT_LE;
            break;
 -        case GST_FLOAT32_BE:
 +        case GST_AUDIO_FORMAT_F32BE:
            alsa->format = SND_PCM_FORMAT_FLOAT_BE;
            break;
 -        case GST_FLOAT64_LE:
 +        case GST_AUDIO_FORMAT_F64LE:
            alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
            break;
 -        case GST_FLOAT64_BE:
 +        case GST_AUDIO_FORMAT_F64BE:
            alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
            break;
          default:
        goto error;
  
    }
 -  alsa->rate = spec->rate;
 -  alsa->channels = spec->channels;
 +  alsa->rate = GST_AUDIO_INFO_RATE (&spec->info);
 +  alsa->channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
    alsa->buffer_time = spec->buffer_time;
    alsa->period_time = spec->latency_time;
    alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
@@@ -683,7 -645,7 +684,7 @@@ open_error
  }
  
  static gboolean
 -gst_alsasrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
 +gst_alsasrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
  {
    GstAlsaSrc *alsa;
    gint err;
    CHECK (set_swparams (alsa), sw_params_failed);
    CHECK (snd_pcm_prepare (alsa->handle), prepare_failed);
  
 -  alsa->bytes_per_sample = spec->bytes_per_sample;
 -  spec->segsize = alsa->period_size * spec->bytes_per_sample;
 +  alsa->bpf = GST_AUDIO_INFO_BPF (&spec->info);
 +  spec->segsize = alsa->period_size * alsa->bpf;
    spec->segtotal = alsa->buffer_size / alsa->period_size;
 -  spec->silence_sample[0] = 0;
 -  spec->silence_sample[1] = 0;
 -  spec->silence_sample[2] = 0;
 -  spec->silence_sample[3] = 0;
  
    return TRUE;
  
@@@ -811,7 -777,7 +812,7 @@@ gst_alsasrc_read (GstAudioSrc * asrc, g
  
    alsa = GST_ALSA_SRC (asrc);
  
 -  cptr = length / alsa->bytes_per_sample;
 +  cptr = length / alsa->bpf;
    ptr = data;
  
    GST_ALSA_SRC_LOCK (asrc);
    }
    GST_ALSA_SRC_UNLOCK (asrc);
  
 -  return length - (cptr * alsa->bytes_per_sample);
 +  return length - (cptr * alsa->bpf);
  
  read_error:
    {
diff --combined ext/ogg/gstoggdemux.c
  #ifdef HAVE_CONFIG_H
  #include "config.h"
  #endif
+ /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+  * with newer GLib versions (>= 2.31.0) */
+ #define GLIB_DISABLE_DEPRECATION_WARNINGS
  #include <string.h>
  #include <gst/gst-i18n-plugin.h>
  #include <gst/tag/tag.h>
  
  #include "gstoggdemux.h"
  
+ #include "gst/glib-compat-private.h"
  #define CHUNKSIZE (8500)        /* this is out of vorbisfile */
  
  /* we hope we get a granpos within this many bytes off the end */
@@@ -131,10 -138,10 +138,10 @@@ static gboolean gst_ogg_demux_receive_e
  static void gst_ogg_pad_dispose (GObject * object);
  static void gst_ogg_pad_finalize (GObject * object);
  
 -static const GstQueryType *gst_ogg_pad_query_types (GstPad * pad);
 -static gboolean gst_ogg_pad_src_query (GstPad * pad, GstQuery * query);
 -static gboolean gst_ogg_pad_event (GstPad * pad, GstEvent * event);
 -static GstCaps *gst_ogg_pad_getcaps (GstPad * pad);
 +static gboolean gst_ogg_pad_src_query (GstPad * pad, GstObject * parent,
 +    GstQuery * query);
 +static gboolean gst_ogg_pad_event (GstPad * pad, GstObject * parent,
 +    GstEvent * event);
  static GstOggPad *gst_ogg_chain_get_stream (GstOggChain * chain,
      guint32 serialno);
  
@@@ -169,9 -176,12 +176,9 @@@ gst_ogg_pad_init (GstOggPad * pad
  {
    gst_pad_set_event_function (GST_PAD (pad),
        GST_DEBUG_FUNCPTR (gst_ogg_pad_event));
 -  gst_pad_set_getcaps_function (GST_PAD (pad),
 -      GST_DEBUG_FUNCPTR (gst_ogg_pad_getcaps));
 -  gst_pad_set_query_type_function (GST_PAD (pad),
 -      GST_DEBUG_FUNCPTR (gst_ogg_pad_query_types));
    gst_pad_set_query_function (GST_PAD (pad),
        GST_DEBUG_FUNCPTR (gst_ogg_pad_src_query));
 +  gst_pad_use_fixed_caps (GST_PAD (pad));
  
    pad->mode = GST_OGG_PAD_MODE_INIT;
  
  
    pad->start_time = GST_CLOCK_TIME_NONE;
  
 -  pad->last_stop = GST_CLOCK_TIME_NONE;
 +  pad->position = GST_CLOCK_TIME_NONE;
  
    pad->have_type = FALSE;
    pad->continued = NULL;
@@@ -240,13 -250,31 +247,13 @@@ gst_ogg_pad_finalize (GObject * object
    G_OBJECT_CLASS (gst_ogg_pad_parent_class)->finalize (object);
  }
  
 -static const GstQueryType *
 -gst_ogg_pad_query_types (GstPad * pad)
 -{
 -  static const GstQueryType query_types[] = {
 -    GST_QUERY_DURATION,
 -    GST_QUERY_SEEKING,
 -    0
 -  };
 -
 -  return query_types;
 -}
 -
 -static GstCaps *
 -gst_ogg_pad_getcaps (GstPad * pad)
 -{
 -  return gst_caps_ref (GST_PAD_CAPS (pad));
 -}
 -
  static gboolean
 -gst_ogg_pad_src_query (GstPad * pad, GstQuery * query)
 +gst_ogg_pad_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
  {
    gboolean res = TRUE;
    GstOggDemux *ogg;
  
 -  ogg = GST_OGG_DEMUX (gst_pad_get_parent (pad));
 +  ogg = GST_OGG_DEMUX (parent);
  
    switch (GST_QUERY_TYPE (query)) {
      case GST_QUERY_DURATION:
      }
  
      default:
 -      res = gst_pad_query_default (pad, query);
 +      res = gst_pad_query_default (pad, parent, query);
        break;
    }
  done:
 -  gst_object_unref (ogg);
  
    return res;
  
@@@ -385,12 -414,12 +392,12 @@@ error
  }
  
  static gboolean
 -gst_ogg_pad_event (GstPad * pad, GstEvent * event)
 +gst_ogg_pad_event (GstPad * pad, GstObject * parent, GstEvent * event)
  {
    gboolean res;
    GstOggDemux *ogg;
  
 -  ogg = GST_OGG_DEMUX (gst_pad_get_parent (pad));
 +  ogg = GST_OGG_DEMUX (parent);
  
    switch (GST_EVENT_TYPE (event)) {
      case GST_EVENT_SEEK:
        gst_event_unref (event);
        break;
      default:
 -      res = gst_pad_event_default (pad, event);
 +      res = gst_pad_event_default (pad, parent, event);
        break;
    }
 -  gst_object_unref (ogg);
  
    return res;
  }
@@@ -419,7 -449,7 +426,7 @@@ gst_ogg_pad_reset (GstOggPad * pad
    pad->continued = NULL;
  
    pad->last_ret = GST_FLOW_OK;
 -  pad->last_stop = GST_CLOCK_TIME_NONE;
 +  pad->position = GST_CLOCK_TIME_NONE;
    pad->current_granule = -1;
    pad->keyframe_granule = -1;
    pad->is_eos = FALSE;
@@@ -605,14 -635,14 +612,14 @@@ gst_ogg_demux_chain_peer (GstOggPad * p
      goto not_added;
  
    buf = gst_buffer_new_and_alloc (packet->bytes - offset - trim);
 -  gst_buffer_set_caps (buf, GST_PAD_CAPS (pad));
  
    /* set delta flag for OGM content */
    if (delta_unit)
      GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
  
    /* copy packet in buffer */
 -  memcpy (buf->data, packet->packet + offset, packet->bytes - offset - trim);
 +  gst_buffer_fill (buf, 0, packet->packet + offset,
 +      packet->bytes - offset - trim);
  
    GST_BUFFER_TIMESTAMP (buf) = out_timestamp;
    GST_BUFFER_DURATION (buf) = out_duration;
      pad->discont = FALSE;
    }
  
 -  pad->last_stop = ogg->segment.last_stop;
 +  pad->position = ogg->segment.position;
  
    /* don't push the header packets when we are asked to skip them */
    if (!packet->b_o_s || push_headers) {
  
    /* check if valid granulepos, then we can calculate the current
     * position. We know the granule for each packet but we only want to update
 -   * the last_stop when we have a valid granulepos on the packet because else
 +   * the position when we have a valid granulepos on the packet because else
     * our time jumps around for the different streams. */
    if (packet->granulepos < 0)
      goto done;
    }
  
    /* and store as the current position */
 -  gst_segment_set_last_stop (&ogg->segment, GST_FORMAT_TIME, current_time);
 +  ogg->segment.position = current_time;
  
    GST_DEBUG_OBJECT (ogg, "ogg current time %" GST_TIME_FORMAT,
        GST_TIME_ARGS (current_time));
@@@ -777,7 -807,7 +784,7 @@@ gst_ogg_pad_submit_packet (GstOggPad * 
    if (!pad->have_type) {
      pad->have_type = gst_ogg_stream_setup_map (&pad->map, packet);
      if (!pad->have_type) {
 -      pad->map.caps = gst_caps_new_simple ("application/x-unknown", NULL);
 +      pad->map.caps = gst_caps_new_empty_simple ("application/x-unknown");
      }
      if (pad->map.is_skeleton) {
        GST_DEBUG_OBJECT (ogg, "we have a fishead");
  
          if (start_time != G_MAXUINT64) {
            gint64 segment_time;
 +          GstSegment segment;
  
            GST_DEBUG_OBJECT (ogg, "start_time:  %" GST_TIME_FORMAT,
                GST_TIME_ARGS (start_time));
              segment_time = chain->begin_time;
  
            /* create the newsegment event we are going to send out */
 +          gst_segment_init (&segment, GST_FORMAT_TIME);
 +
            GST_PUSH_LOCK (ogg);
            if (!ogg->pullmode && ogg->push_state == PUSH_LINEAR2) {
              /* if we are fast forwarding to the actual seek target,
                  ", start_time %" GST_TIME_FORMAT,
                  GST_TIME_ARGS (ogg->push_seek_time_original_target),
                  GST_TIME_ARGS (start_time));
 -            event =
 -                gst_event_new_new_segment (FALSE, ogg->push_seek_rate,
 -                GST_FORMAT_TIME, ogg->push_seek_time_original_target, -1,
 -                ogg->push_seek_time_original_target);
 +            segment.rate = ogg->push_seek_rate;
 +            segment.start = ogg->push_seek_time_original_target;
 +            segment.stop = -1;
 +            segment.time = ogg->push_seek_time_original_target;
 +            event = gst_event_new_segment (&segment);
              ogg->push_state = PUSH_PLAYING;
            } else {
 -            event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
 -                GST_FORMAT_TIME, start_time, chain->segment_stop, segment_time);
 +            segment.rate = ogg->segment.rate;
 +            segment.applied_rate = ogg->segment.applied_rate;
 +            segment.start = start_time;
 +            segment.stop = chain->segment_stop;
 +            segment.time = segment_time;
 +            event = gst_event_new_segment (&segment);
            }
            GST_PUSH_UNLOCK (ogg);
  
          /* see if we have enough info to activate the chain, we have enough info
           * when all streams have a valid start time. */
          if (gst_ogg_demux_collect_chain_info (ogg, chain)) {
 +          GstSegment segment;
  
            GST_DEBUG_OBJECT (ogg, "segment_start: %" GST_TIME_FORMAT,
                GST_TIME_ARGS (chain->segment_start));
                GST_TIME_ARGS (chain->begin_time));
  
            /* create the newsegment event we are going to send out */
 -          event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
 -              GST_FORMAT_TIME, chain->segment_start, chain->segment_stop,
 -              chain->begin_time);
 +          gst_segment_init (&segment, GST_FORMAT_TIME);
 +          segment.rate = ogg->segment.rate;
 +          segment.applied_rate = ogg->segment.applied_rate;
 +          segment.start = chain->segment_start;
 +          segment.stop = chain->segment_stop;
 +          segment.time = chain->begin_time;
 +          event = gst_event_new_segment (&segment);
          }
        }
  
@@@ -1066,7 -1083,7 +1073,7 @@@ gst_ogg_pad_stream_out (GstOggPad * pad
           * collecting headers and that we don't have exposed the pads yet */
          if (result == GST_FLOW_NOT_LINKED)
            break;
 -        else if (result <= GST_FLOW_UNEXPECTED)
 +        else if (result <= GST_FLOW_EOS)
            goto could_not_submit;
          break;
        default:
@@@ -1824,11 -1841,12 +1831,11 @@@ gst_ogg_chain_new_stream (GstOggChain 
    GST_DEBUG_OBJECT (chain->ogg,
        "creating new stream %08x in chain %p", serialno, chain);
  
 -  name = g_strdup_printf ("serial_%08x", serialno);
 +  name = g_strdup_printf ("src_%08x", serialno);
    ret = g_object_new (GST_TYPE_OGG_PAD, "name", name, NULL);
    g_free (name);
    /* we own this one */
 -  gst_object_ref (ret);
 -  gst_object_sink (ret);
 +  gst_object_ref_sink (ret);
  
    GST_PAD_DIRECTION (ret) = GST_PAD_SRC;
    gst_ogg_pad_mark_discont (ret);
      goto init_failed;
  
    /* FIXME: either do something with it or remove it */
 -  list = gst_tag_list_new ();
 +  list = gst_tag_list_new_empty ();
    gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_SERIAL, serialno,
        NULL);
    gst_tag_list_free (list);
        "created new ogg src %p for stream with serial %08x", ret, serialno);
  
    g_array_append_val (chain->streams, ret);
 +  gst_pad_set_active (GST_PAD_CAST (ret), TRUE);
  
    return ret;
  
@@@ -1898,7 -1915,7 +1905,7 @@@ enu
  };
  
  static GstStaticPadTemplate ogg_demux_src_template_factory =
 -GST_STATIC_PAD_TEMPLATE ("src_%d",
 +GST_STATIC_PAD_TEMPLATE ("src_%08x",
      GST_PAD_SRC,
      GST_PAD_SOMETIMES,
      GST_STATIC_CAPS_ANY);
@@@ -1917,38 -1934,42 +1924,38 @@@ static GstFlowReturn gst_ogg_demux_read
  static GstFlowReturn gst_ogg_demux_read_end_chain (GstOggDemux * ogg,
      GstOggChain * chain);
  
 -static gboolean gst_ogg_demux_sink_event (GstPad * pad, GstEvent * event);
 +static gboolean gst_ogg_demux_sink_event (GstPad * pad, GstObject * parent,
 +    GstEvent * event);
  static void gst_ogg_demux_loop (GstOggPad * pad);
 -static GstFlowReturn gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer);
 -static gboolean gst_ogg_demux_sink_activate (GstPad * sinkpad);
 -static gboolean gst_ogg_demux_sink_activate_pull (GstPad * sinkpad,
 -    gboolean active);
 -static gboolean gst_ogg_demux_sink_activate_push (GstPad * sinkpad,
 -    gboolean active);
 +static GstFlowReturn gst_ogg_demux_chain (GstPad * pad, GstObject * parent,
 +    GstBuffer * buffer);
 +static gboolean gst_ogg_demux_sink_activate (GstPad * sinkpad,
 +    GstObject * parent);
 +static gboolean gst_ogg_demux_sink_activate_mode (GstPad * sinkpad,
 +    GstObject * parent, GstPadMode mode, gboolean active);
  static GstStateChangeReturn gst_ogg_demux_change_state (GstElement * element,
      GstStateChange transition);
  
  static void gst_ogg_print (GstOggDemux * demux);
  
 -GST_BOILERPLATE (GstOggDemux, gst_ogg_demux, GstElement, GST_TYPE_ELEMENT);
 +#define gst_ogg_demux_parent_class parent_class
 +G_DEFINE_TYPE (GstOggDemux, gst_ogg_demux, GST_TYPE_ELEMENT);
  
  static void
 -gst_ogg_demux_base_init (gpointer g_class)
 +gst_ogg_demux_class_init (GstOggDemuxClass * klass)
  {
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 +  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
 +  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  
 -  gst_element_class_set_details_simple (element_class,
 +  gst_element_class_set_details_simple (gstelement_class,
        "Ogg demuxer", "Codec/Demuxer",
        "demux ogg streams (info about ogg: http://xiph.org)",
        "Wim Taymans <wim@fluendo.com>");
  
 -  gst_element_class_add_static_pad_template (element_class,
 -      &ogg_demux_sink_template_factory);
 -  gst_element_class_add_static_pad_template (element_class,
 -      &ogg_demux_src_template_factory);
 -}
 -
 -static void
 -gst_ogg_demux_class_init (GstOggDemuxClass * klass)
 -{
 -  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
 -  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 +  gst_element_class_add_pad_template (gstelement_class,
 +      gst_static_pad_template_get (&ogg_demux_sink_template_factory));
 +  gst_element_class_add_pad_template (gstelement_class,
 +      gst_static_pad_template_get (&ogg_demux_src_template_factory));
  
    gstelement_class->change_state = gst_ogg_demux_change_state;
    gstelement_class->send_event = gst_ogg_demux_receive_event;
  }
  
  static void
 -gst_ogg_demux_init (GstOggDemux * ogg, GstOggDemuxClass * g_class)
 +gst_ogg_demux_init (GstOggDemux * ogg)
  {
    /* create the sink pad */
    ogg->sinkpad =
    gst_pad_set_event_function (ogg->sinkpad, gst_ogg_demux_sink_event);
    gst_pad_set_chain_function (ogg->sinkpad, gst_ogg_demux_chain);
    gst_pad_set_activate_function (ogg->sinkpad, gst_ogg_demux_sink_activate);
 -  gst_pad_set_activatepull_function (ogg->sinkpad,
 -      gst_ogg_demux_sink_activate_pull);
 -  gst_pad_set_activatepush_function (ogg->sinkpad,
 -      gst_ogg_demux_sink_activate_push);
 +  gst_pad_set_activatemode_function (ogg->sinkpad,
 +      gst_ogg_demux_sink_activate_mode);
    gst_element_add_pad (GST_ELEMENT (ogg), ogg->sinkpad);
  
    ogg->chain_lock = g_mutex_new ();
@@@ -2025,12 -2048,12 +2032,12 @@@ gst_ogg_demux_reset_streams (GstOggDemu
  }
  
  static gboolean
 -gst_ogg_demux_sink_event (GstPad * pad, GstEvent * event)
 +gst_ogg_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
  {
    gboolean res;
    GstOggDemux *ogg;
  
 -  ogg = GST_OGG_DEMUX (gst_pad_get_parent (pad));
 +  ogg = GST_OGG_DEMUX (parent);
  
    switch (GST_EVENT_TYPE (event)) {
      case GST_EVENT_FLUSH_START:
          gst_ogg_demux_reset_streams (ogg);
        }
        break;
 -    case GST_EVENT_NEWSEGMENT:
 +    case GST_EVENT_SEGMENT:
        GST_DEBUG_OBJECT (ogg, "got a new segment event");
        {
 -        gboolean update;
 -        GstFormat format;
 -        gdouble rate, arate;
 -        gint64 start, stop, time;
 -
 -        gst_event_parse_new_segment_full (event, &update, &rate, &arate,
 -            &format, &start, &stop, &time);
 -        if (format == GST_FORMAT_BYTES) {
 +        GstSegment segment;
 +
 +        gst_event_copy_segment (event, &segment);
 +
 +        if (segment.format == GST_FORMAT_BYTES) {
            GST_PUSH_LOCK (ogg);
 -          ogg->push_byte_offset = start;
 -          ogg->push_last_seek_offset = start;
 +          ogg->push_byte_offset = segment.start;
 +          ogg->push_last_seek_offset = segment.start;
            GST_PUSH_UNLOCK (ogg);
          } else {
            GST_WARNING_OBJECT (ogg, "unexpected segment format: %s",
 -              gst_format_get_name (format));
 +              gst_format_get_name (segment.format));
          }
        }
        gst_event_unref (event);
        res = gst_ogg_demux_send_event (ogg, event);
        break;
    }
 -  gst_object_unref (ogg);
  
    return res;
  }
  static GstFlowReturn
  gst_ogg_demux_submit_buffer (GstOggDemux * ogg, GstBuffer * buffer)
  {
 -  gint size;
 -  guint8 *data;
 +  gsize size;
    gchar *oggbuffer;
    GstFlowReturn ret = GST_FLOW_OK;
  
 -  size = GST_BUFFER_SIZE (buffer);
 -  data = GST_BUFFER_DATA (buffer);
 -
 -  GST_DEBUG_OBJECT (ogg, "submitting %u bytes", size);
 +  size = gst_buffer_get_size (buffer);
 +  GST_DEBUG_OBJECT (ogg, "submitting %" G_GSIZE_FORMAT " bytes", size);
    if (G_UNLIKELY (size == 0))
      goto done;
  
    if (G_UNLIKELY (oggbuffer == NULL))
      goto no_buffer;
  
 -  memcpy (oggbuffer, data, size);
 +  gst_buffer_extract (buffer, 0, oggbuffer, size);
 +
    if (G_UNLIKELY (ogg_sync_wrote (&ogg->sync, size) < 0))
      goto write_failed;
  
@@@ -2147,8 -2176,8 +2154,8 @@@ no_buffer
    }
  write_failed:
    {
 -    GST_ELEMENT_ERROR (ogg, STREAM, DECODE,
 -        (NULL), ("failed to write %d bytes to the sync buffer", size));
 +    GST_ELEMENT_ERROR (ogg, STREAM, DECODE, (NULL),
 +        ("failed to write %" G_GSIZE_FORMAT " bytes to the sync buffer", size));
      ret = GST_FLOW_ERROR;
      goto done;
    }
@@@ -2191,7 -2220,7 +2198,7 @@@ gst_ogg_demux_get_data (GstOggDemux * o
    if (ret != GST_FLOW_OK)
      goto error;
  
 -  ogg->read_offset += GST_BUFFER_SIZE (buffer);
 +  ogg->read_offset += gst_buffer_get_size (buffer);
  
    ret = gst_ogg_demux_submit_buffer (ogg, buffer);
  
@@@ -2206,7 -2235,7 +2213,7 @@@ boundary_reached
  eos:
    {
      GST_LOG_OBJECT (ogg, "reached EOS");
 -    return GST_FLOW_UNEXPECTED;
 +    return GST_FLOW_EOS;
    }
  error:
    {
   * @offset will contain the offset the next page starts at when this function
   * returns GST_FLOW_OK.
   *
 - * GST_FLOW_UNEXPECTED is returned on EOS.
 + * GST_FLOW_EOS is returned on EOS.
   *
   * GST_FLOW_LIMIT is returned when we did not find a page before the
   * boundary. If @boundary is -1, this is never returned.
@@@ -2337,7 -2366,7 +2344,7 @@@ gst_ogg_demux_get_prev_page (GstOggDemu
          break;
        }
        /* something went wrong */
 -      if (ret == GST_FLOW_UNEXPECTED) {
 +      if (ret == GST_FLOW_EOS) {
          new_offset = 0;
          GST_LOG_OBJECT (ogg, "got unexpected");
        } else if (ret != GST_FLOW_OK) {
@@@ -2435,8 -2464,7 +2442,8 @@@ gst_ogg_demux_set_header_on_caps (GstOg
      ogg_packet *op = headers->data;
      g_assert (op);
      buffer = gst_buffer_new_and_alloc (op->bytes);
 -    memcpy (GST_BUFFER_DATA (buffer), op->packet, op->bytes);
 +    if (op->bytes)
 +      gst_buffer_fill (buffer, 0, op->packet, op->bytes);
      GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS);
      g_value_init (&value, GST_TYPE_BUFFER);
      gst_value_take_buffer (&value, buffer);
@@@ -2509,8 -2537,7 +2516,8 @@@ gst_ogg_demux_activate_chain (GstOggDem
      gst_ogg_pad_mark_discont (pad);
      pad->last_ret = GST_FLOW_OK;
  
 -    if (pad->map.is_skeleton || pad->added || GST_PAD_CAPS (pad) == NULL)
 +    if (pad->map.is_skeleton || pad->added
 +        || !gst_pad_has_current_caps (GST_PAD_CAST (pad)))
        continue;
  
      GST_DEBUG_OBJECT (ogg, "adding pad %" GST_PTR_FORMAT, pad);
  
    /* FIXME, must be sent from the streaming thread */
    if (event) {
 +    GstTagList *tags;
 +
      gst_ogg_demux_send_event (ogg, event);
  
 -    gst_element_found_tags (GST_ELEMENT_CAST (ogg),
 -        gst_tag_list_new_full (GST_TAG_CONTAINER_FORMAT, "Ogg", NULL));
 +    tags = gst_tag_list_new (GST_TAG_CONTAINER_FORMAT, "Ogg", NULL);
 +    gst_ogg_demux_send_event (ogg, gst_event_new_tag (tags));
    }
  
    GST_DEBUG_OBJECT (ogg, "starting chain");
      /* FIXME also streaming thread */
      if (pad->map.taglist) {
        GST_DEBUG_OBJECT (ogg, "pushing tags");
 -      gst_element_found_tags_for_pad (GST_ELEMENT_CAST (ogg),
 -          GST_PAD_CAST (pad), pad->map.taglist);
 +      gst_pad_push_event (GST_PAD_CAST (pad),
 +          gst_event_new_tag (pad->map.taglist));
        pad->map.taglist = NULL;
      }
  
@@@ -2776,7 -2801,7 +2783,7 @@@ gst_ogg_demux_do_seek (GstOggDemux * og
    gint i, pending, len;
    gboolean first_parsed_page = TRUE;
  
 -  position = segment->last_stop;
 +  position = segment->position;
  
    /* first find the chain to search in */
    total = ogg->total_time;
@@@ -2931,7 -2956,7 +2938,7 @@@ done
    if (keyframe) {
      if (segment->rate > 0.0)
        segment->time = keytarget;
 -    segment->last_stop = keytarget - begintime;
 +    segment->position = keytarget - begintime;
    }
  
    *rchain = chain;
@@@ -3029,8 -3054,28 +3036,8 @@@ gst_ogg_demux_perform_seek_pull (GstOgg
     * forever. */
    GST_PAD_STREAM_LOCK (ogg->sinkpad);
  
 -  if (ogg->segment_running && !flush) {
 -    /* create the segment event to close the current segment */
 -    if ((chain = ogg->current_chain)) {
 -      GstEvent *newseg;
 -      gint64 chain_start = 0;
 -
 -      if (chain->segment_start != GST_CLOCK_TIME_NONE)
 -        chain_start = chain->segment_start;
 -
 -      newseg = gst_event_new_new_segment (TRUE, ogg->segment.rate,
 -          GST_FORMAT_TIME, ogg->segment.start + chain_start,
 -          ogg->segment.last_stop + chain_start, ogg->segment.time);
 -      /* set the seqnum of the running segment */
 -      gst_event_set_seqnum (newseg, ogg->seqnum);
 -
 -      /* send segment on old chain, FIXME, must be sent from streaming thread. */
 -      gst_ogg_demux_send_event (ogg, newseg);
 -    }
 -  }
 -
    if (event) {
 -    gst_segment_set_seek (&ogg->segment, rate, format, flags,
 +    gst_segment_do_seek (&ogg->segment, rate, format, flags,
          cur_type, cur, stop_type, stop, &update);
    }
  
    /* we need to stop flushing on the srcpad as we're going to use it
     * next. We can do this as we have the STREAM lock now. */
    if (flush) {
 -    tevent = gst_event_new_flush_stop ();
 +    tevent = gst_event_new_flush_stop (TRUE);
      gst_event_set_seqnum (tevent, seqnum);
      gst_pad_push_event (ogg->sinkpad, tevent);
    }
      GstEvent *event;
      gint64 stop;
      gint64 start;
 -    gint64 last_stop, begin_time;
 +    gint64 position, begin_time;
 +    GstSegment segment;
  
      /* we have to send the flush to the old chain, not the new one */
      if (flush) {
 -      tevent = gst_event_new_flush_stop ();
 +      tevent = gst_event_new_flush_stop (TRUE);
        gst_event_set_seqnum (tevent, seqnum);
        gst_ogg_demux_send_event (ogg, tevent);
      }
        stop = MIN (stop, chain->segment_stop);
      }
  
 -    last_stop = ogg->segment.last_stop;
 +    position = ogg->segment.position;
      if (chain->segment_start != GST_CLOCK_TIME_NONE)
 -      last_stop += chain->segment_start;
 +      position += chain->segment_start;
  
 -    /* create the segment event we are going to send out */
 -    if (ogg->segment.rate >= 0.0)
 -      event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
 -          ogg->segment.format, last_stop, stop, ogg->segment.time);
 -    else
 -      event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
 -          ogg->segment.format, start, last_stop, ogg->segment.time);
 +    gst_segment_copy_into (&ogg->segment, &segment);
  
 +    /* create the segment event we are going to send out */
 +    if (ogg->segment.rate >= 0.0) {
 +      segment.start = position;
 +      segment.stop = stop;
 +    } else {
 +      segment.start = start;
 +      segment.stop = position;
 +    }
 +    event = gst_event_new_segment (&segment);
      gst_event_set_seqnum (event, seqnum);
  
      if (chain != ogg->current_chain) {
        GstMessage *message;
  
        message = gst_message_new_segment_start (GST_OBJECT (ogg),
 -          GST_FORMAT_TIME, ogg->segment.last_stop);
 +          GST_FORMAT_TIME, ogg->segment.position);
        gst_message_set_seqnum (message, seqnum);
  
        gst_element_post_message (GST_ELEMENT (ogg), message);
      }
  
 -    ogg->segment_running = TRUE;
      ogg->seqnum = seqnum;
      /* restart our task since it might have been stopped when we did the 
       * flush. */
@@@ -3223,16 -3265,18 +3230,16 @@@ gst_ogg_demux_check_duration_push (GstO
  
      GST_DEBUG_OBJECT (ogg, "Trying to find byte/time length");
      if ((peer = gst_pad_get_peer (ogg->sinkpad)) != NULL) {
 -      GstFormat format = GST_FORMAT_BYTES;
        gint64 length;
        int res;
  
 -      res = gst_pad_query_duration (peer, &format, &length);
 +      res = gst_pad_query_duration (peer, GST_FORMAT_BYTES, &length);
        if (res && length > 0) {
          ogg->push_byte_length = length;
          GST_DEBUG_OBJECT (ogg,
              "File byte length %" G_GINT64_FORMAT, ogg->push_byte_length);
        }
 -      format = GST_FORMAT_TIME;
 -      res = gst_pad_query_duration (peer, &format, &length);
 +      res = gst_pad_query_duration (peer, GST_FORMAT_TIME, &length);
        gst_object_unref (peer);
        if (res && length >= 0) {
          ogg->push_time_length = length;
@@@ -3472,7 -3516,7 +3479,7 @@@ gst_ogg_demux_bisect_forward_serialno (
      gst_ogg_demux_seek (ogg, bisect);
      ret = gst_ogg_demux_get_next_page (ogg, &og, -1, &offset);
  
 -    if (ret == GST_FLOW_UNEXPECTED) {
 +    if (ret == GST_FLOW_EOS) {
        endsearched = bisect;
      } else if (ret == GST_FLOW_OK) {
        guint32 serial = ogg_page_serialno (&og);
  
    gst_ogg_demux_seek (ogg, next);
    ret = gst_ogg_demux_read_chain (ogg, &nextchain);
 -  if (ret == GST_FLOW_UNEXPECTED) {
 +  if (ret == GST_FLOW_EOS) {
      nextchain = NULL;
      ret = GST_FLOW_OK;
      GST_LOG_OBJECT (ogg, "no next chain");
@@@ -3548,7 -3592,7 +3555,7 @@@ gst_ogg_demux_read_chain (GstOggDemux 
  
      ret = gst_ogg_demux_get_next_page (ogg, &og, -1, NULL);
      if (ret != GST_FLOW_OK) {
 -      if (ret == GST_FLOW_UNEXPECTED) {
 +      if (ret == GST_FLOW_EOS) {
          GST_DEBUG_OBJECT (ogg, "Reached EOS, done reading end chain");
        } else {
          GST_WARNING_OBJECT (ogg, "problem reading BOS page: ret=%d", ret);
         * ignore it */
        if (!chain) {
          GST_WARNING_OBJECT (ogg, "No chain found, no Ogg data in stream ?");
 -        ret = GST_FLOW_UNEXPECTED;
 +        ret = GST_FLOW_EOS;
        }
        break;
      }
      if (ret == GST_FLOW_OK) {
        GST_WARNING_OBJECT (ogg, "no chain was found");
        ret = GST_FLOW_ERROR;
 -    } else if (ret != GST_FLOW_UNEXPECTED) {
 +    } else if (ret != GST_FLOW_EOS) {
        GST_WARNING_OBJECT (ogg, "failed to read chain");
      } else {
        GST_DEBUG_OBJECT (ogg, "done reading chains");
@@@ -3839,7 -3883,7 +3846,7 @@@ gst_ogg_demux_collect_info (GstOggDemu
  
      ogg->total_time += chain->total_time;
    }
 -  gst_segment_set_duration (&ogg->segment, GST_FORMAT_TIME, ogg->total_time);
 +  ogg->segment.duration = ogg->total_time;
  }
  
  /* find all the chains in the ogg file, this reads the first and
@@@ -3851,6 -3895,7 +3858,6 @@@ gst_ogg_demux_find_chains (GstOggDemux 
  {
    ogg_page og;
    GstPad *peer;
 -  GstFormat format;
    gboolean res;
    guint32 serialno;
    GstOggChain *chain;
      goto no_peer;
  
    /* find length to read last page, we store this for later use. */
 -  format = GST_FORMAT_BYTES;
 -  res = gst_pad_query_duration (peer, &format, &ogg->length);
 +  res = gst_pad_query_duration (peer, GST_FORMAT_BYTES, &ogg->length);
    gst_object_unref (peer);
    if (!res || ogg->length <= 0)
      goto no_length;
@@@ -3960,17 -4006,13 +3967,17 @@@ gst_ogg_demux_handle_page (GstOggDemux 
      if (chain) {
        GstEvent *event;
        gint64 start = 0;
 +      GstSegment segment;
  
        if (chain->segment_start != GST_CLOCK_TIME_NONE)
          start = chain->segment_start;
  
        /* create the newsegment event we are going to send out */
 -      event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
 -          GST_FORMAT_TIME, start, chain->segment_stop, chain->begin_time);
 +      gst_segment_copy_into (&ogg->segment, &segment);
 +      segment.start = start;
 +      segment.stop = chain->segment_stop;
 +      segment.time = chain->begin_time;
 +      event = gst_event_new_segment (&segment);
        gst_event_set_seqnum (event, ogg->seqnum);
  
        GST_DEBUG_OBJECT (ogg,
        if (ogg->pullmode)
          goto unknown_chain;
  
 -      current_time = ogg->segment.last_stop;
 +      current_time = ogg->segment.position;
  
        /* time of new chain is current time */
        chain_time = current_time;
@@@ -4058,13 -4100,13 +4065,13 @@@ unknown_chain
   * the serialno, submit pages and packets to the oggpads
   */
  static GstFlowReturn
 -gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
 +gst_ogg_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
  {
    GstOggDemux *ogg;
    gint ret = 0;
    GstFlowReturn result = GST_FLOW_OK;
  
 -  ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (pad));
 +  ogg = GST_OGG_DEMUX (parent);
  
    GST_DEBUG_OBJECT (ogg, "enter");
    result = gst_ogg_demux_submit_buffer (ogg, buffer);
@@@ -4190,7 -4232,7 +4197,7 @@@ gst_ogg_demux_loop_forward (GstOggDemu
    if (ogg->offset == ogg->length) {
      GST_LOG_OBJECT (ogg, "no more data to pull %" G_GINT64_FORMAT
          " == %" G_GINT64_FORMAT, ogg->offset, ogg->length);
 -    ret = GST_FLOW_UNEXPECTED;
 +    ret = GST_FLOW_EOS;
      goto done;
    }
  
      goto done;
    }
  
 -  ogg->offset += GST_BUFFER_SIZE (buffer);
 +  ogg->offset += gst_buffer_get_size (buffer);
  
    if (G_UNLIKELY (ogg->newsegment)) {
      gst_ogg_demux_send_event (ogg, ogg->newsegment);
      ogg->newsegment = NULL;
    }
  
 -  ret = gst_ogg_demux_chain (ogg->sinkpad, buffer);
 +  ret = gst_ogg_demux_chain (ogg->sinkpad, GST_OBJECT_CAST (ogg), buffer);
    if (ret != GST_FLOW_OK) {
      GST_LOG_OBJECT (ogg, "Failed demux_chain");
      goto done;
    /* check for the end of the segment */
    if (gst_ogg_demux_check_eos (ogg)) {
      GST_LOG_OBJECT (ogg, "got EOS");
 -    ret = GST_FLOW_UNEXPECTED;
 +    ret = GST_FLOW_EOS;
      goto done;
    }
  done:
@@@ -4242,7 -4284,7 +4249,7 @@@ gst_ogg_demux_loop_reverse (GstOggDemu
    if (ogg->offset == 0) {
      GST_LOG_OBJECT (ogg, "no more data to pull %" G_GINT64_FORMAT
          " == 0", ogg->offset);
 -    ret = GST_FLOW_UNEXPECTED;
 +    ret = GST_FLOW_EOS;
      goto done;
    }
  
    /* check for the end of the segment */
    if (gst_ogg_demux_check_eos (ogg)) {
      GST_LOG_OBJECT (ogg, "got EOS");
 -    ret = GST_FLOW_UNEXPECTED;
 +    ret = GST_FLOW_EOS;
      goto done;
    }
  done:
@@@ -4280,7 -4322,7 +4287,7 @@@ gst_ogg_demux_sync_streams (GstOggDemu
    guint i;
  
    chain = ogg->current_chain;
 -  cur = ogg->segment.last_stop;
 +  cur = ogg->segment.position;
    if (chain == NULL || cur == -1)
      return;
  
      /* Theoretically, we should be doing this for all streams, but we're only
       * doing it for known-to-be-sparse streams at the moment in order not to
       * break things for wrongly-muxed streams (like we used to produce once) */
 -    if (stream->map.is_sparse && stream->last_stop != GST_CLOCK_TIME_NONE) {
 +    if (stream->map.is_sparse && stream->position != GST_CLOCK_TIME_NONE) {
  
        /* Does this stream lag? Random threshold of 2 seconds */
 -      if (GST_CLOCK_DIFF (stream->last_stop, cur) > (2 * GST_SECOND)) {
 +      if (GST_CLOCK_DIFF (stream->position, cur) > (2 * GST_SECOND)) {
          GST_DEBUG_OBJECT (stream, "synchronizing stream with others by "
              "advancing time from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
 -            GST_TIME_ARGS (stream->last_stop), GST_TIME_ARGS (cur));
 -        stream->last_stop = cur;
 +            GST_TIME_ARGS (stream->position), GST_TIME_ARGS (cur));
 +
 +        stream->position = cur;
 +
 +#if 0
 +        ogg->segment.base += cur - stream->position;
          /* advance stream time (FIXME: is this right, esp. time_pos?) */
          gst_pad_push_event (GST_PAD_CAST (stream),
              gst_event_new_new_segment (TRUE, ogg->segment.rate,
 -                GST_FORMAT_TIME, stream->last_stop, -1, stream->last_stop));
 +                ogg->segment.applied_rate,
 +                GST_FORMAT_TIME, stream->position, -1, stream->position));
 +#endif
        }
      }
    }
@@@ -4385,9 -4421,10 +4392,9 @@@ pause
      GstEvent *event = NULL;
  
      GST_LOG_OBJECT (ogg, "pausing task, reason %s", reason);
 -    ogg->segment_running = FALSE;
      gst_pad_pause_task (ogg->sinkpad);
  
 -    if (ret == GST_FLOW_UNEXPECTED) {
 +    if (ret == GST_FLOW_EOS) {
        /* perform EOS logic */
        if (ogg->segment.flags & GST_SEEK_FLAG_SEGMENT) {
          gint64 stop;
          GST_LOG_OBJECT (ogg, "Sending EOS, at end of stream");
          event = gst_event_new_eos ();
        }
 -    } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) {
 +    } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
        GST_ELEMENT_ERROR (ogg, STREAM, FAILED,
            (_("Internal data stream error.")),
            ("stream stopped, reason %s", reason));
@@@ -4454,65 -4491,51 +4461,65 @@@ gst_ogg_demux_clear_chains (GstOggDemu
   * pull based.
   */
  static gboolean
 -gst_ogg_demux_sink_activate (GstPad * sinkpad)
 +gst_ogg_demux_sink_activate (GstPad * sinkpad, GstObject * parent)
  {
 -  if (gst_pad_check_pull_range (sinkpad)) {
 -    GST_DEBUG_OBJECT (sinkpad, "activating pull");
 -    return gst_pad_activate_pull (sinkpad, TRUE);
 -  } else {
 -    GST_DEBUG_OBJECT (sinkpad, "activating push");
 -    return gst_pad_activate_push (sinkpad, TRUE);
 +  GstQuery *query;
 +  gboolean pull_mode;
 +
 +  query = gst_query_new_scheduling ();
 +
 +  if (!gst_pad_peer_query (sinkpad, query)) {
 +    gst_query_unref (query);
 +    goto activate_push;
    }
 -}
  
 -/* this function gets called when we activate ourselves in push mode.
 - * We cannot seek (ourselves) in the stream */
 -static gboolean
 -gst_ogg_demux_sink_activate_push (GstPad * sinkpad, gboolean active)
 -{
 -  GstOggDemux *ogg;
 +  pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL);
 +  gst_query_unref (query);
  
 -  ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (sinkpad));
 +  if (!pull_mode)
 +    goto activate_push;
  
 -  ogg->pullmode = FALSE;
 -  ogg->resync = FALSE;
 +  GST_DEBUG_OBJECT (sinkpad, "activating pull");
 +  return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
  
 -  return TRUE;
 +activate_push:
 +  {
 +    GST_DEBUG_OBJECT (sinkpad, "activating push");
 +    return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
 +  }
  }
  
 -/* this function gets called when we activate ourselves in pull mode.
 - * We can perform  random access to the resource and we start a task
 - * to start reading */
  static gboolean
 -gst_ogg_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
 +gst_ogg_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
 +    GstPadMode mode, gboolean active)
  {
 +  gboolean res;
    GstOggDemux *ogg;
  
 -  ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (sinkpad));
 +  ogg = GST_OGG_DEMUX (parent);
  
 -  if (active) {
 -    ogg->need_chains = TRUE;
 -    ogg->pullmode = TRUE;
 +  switch (mode) {
 +    case GST_PAD_MODE_PUSH:
 +      ogg->pullmode = FALSE;
 +      ogg->resync = FALSE;
 +      res = TRUE;
 +      break;
 +    case GST_PAD_MODE_PULL:
 +      if (active) {
 +        ogg->need_chains = TRUE;
 +        ogg->pullmode = TRUE;
  
 -    return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_ogg_demux_loop,
 -        sinkpad);
 -  } else {
 -    return gst_pad_stop_task (sinkpad);
 +        res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_ogg_demux_loop,
 +            sinkpad);
 +      } else {
 +        res = gst_pad_stop_task (sinkpad);
 +      }
 +      break;
 +    default:
 +      res = FALSE;
 +      break;
    }
 +  return res;
  }
  
  static GstStateChangeReturn
@@@ -4532,6 -4555,7 +4539,6 @@@ gst_ogg_demux_change_state (GstElement 
        ogg_sync_reset (&ogg->sync);
        ogg->running = FALSE;
        ogg->bitrate = 0;
 -      ogg->segment_running = FALSE;
        ogg->total_time = -1;
        GST_PUSH_LOCK (ogg);
        ogg->push_byte_offset = 0;
        break;
    }
  
 -  result = parent_class->change_state (element, transition);
 +  result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
  
    switch (transition) {
      case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
        gst_ogg_demux_clear_chains (ogg);
        GST_OBJECT_LOCK (ogg);
        ogg->running = FALSE;
 -      ogg->segment_running = FALSE;
        GST_OBJECT_UNLOCK (ogg);
        break;
      case GST_STATE_CHANGE_READY_TO_NULL:
diff --combined gst-libs/gst/Makefile.am
@@@ -1,32 -1,36 +1,32 @@@
  # The interfaces directory has to be built before the others,
  # otherwise some generated header files will be missing for the
  # plugins in the other directories.
 -# Also, the tag directory has to be built before the cdda directory.
  SUBDIRS = \
        interfaces \
        tag \
 -      cdda \
        fft \
 -      floatcast \
 -      netbuffer \
        rtp \
        sdp \
        rtsp \
        video \
 -      pbutils \
        audio \
 +      pbutils \
        riff \
        app
  
- noinst_HEADERS = gettext.h gst-i18n-plugin.h
+ noinst_HEADERS = gettext.h gst-i18n-plugin.h glib-compat-private.h
  
  # dependencies:
 -audio: interfaces pbutils
 -
 -cdda: tag
 +audio: interfaces tag
  
  riff: tag audio
  
  rtsp: sdp
  
 +pbutils: video audio
 +
  INDEPENDENT_SUBDIRS = \
 -      interfaces tag fft floatcast netbuffer pbutils rtp sdp video app
 +      interfaces tag audio fft rtp sdp video app
  
  .PHONY: independent-subdirs $(INDEPENDENT_SUBDIRS)
  
@@@ -19,9 -19,9 +19,9 @@@
   */
  /**
   * SECTION:gstappsink
 - * @short_description: Easy way for applications to extract buffers from a
 + * @short_description: Easy way for applications to extract samples from a
   *     pipeline
 - * @see_also: #GstBaseSink, appsrc
 + * @see_also: #GstSample, #GstBaseSink, appsrc
   *
   * Appsink is a sink plugin that supports many different methods for making
   * the application get a handle on the GStreamer data in a pipeline. Unlike
   * appsink can be used by linking to the gstappsink.h header file to access the
   * methods or by using the appsink action signals and properties.
   *
 - * The normal way of retrieving buffers from appsink is by using the
 - * gst_app_sink_pull_buffer() and gst_app_sink_pull_preroll() methods.
 - * These methods block until a buffer becomes available in the sink or when the
 + * The normal way of retrieving samples from appsink is by using the
 + * gst_app_sink_pull_sample() and gst_app_sink_pull_preroll() methods.
 + * These methods block until a sample becomes available in the sink or when the
   * sink is shut down or reaches EOS.
   *
   * Appsink will internally use a queue to collect buffers from the streaming
 - * thread. If the application is not pulling buffers fast enough, this queue
 + * thread. If the application is not pulling samples fast enough, this queue
   * will consume a lot of memory over time. The "max-buffers" property can be
   * used to limit the queue size. The "drop" property controls whether the
   * streaming thread blocks or if older buffers are dropped when the maximum
   * affect real-time performance and should be avoided.
   *
   * If a blocking behaviour is not desirable, setting the "emit-signals" property
 - * to %TRUE will make appsink emit the "new-buffer" and "new-preroll" signals
 - * when a buffer can be pulled without blocking.
 + * to %TRUE will make appsink emit the "new-sample" and "new-preroll" signals
 + * when a sample can be pulled without blocking.
   *
   * The "caps" property on appsink can be used to control the formats that
   * appsink can receive. This property can contain non-fixed caps, the format of
 - * the pulled buffers can be obtained by getting the buffer caps.
 + * the pulled samples can be obtained by getting the sample caps.
   *
 - * If one of the pull-preroll or pull-buffer methods return %NULL, the appsink
 + * If one of the pull-preroll or pull-sample methods return %NULL, the appsink
   * is stopped or in the EOS state. You can check for the EOS state with the
   * "eos" property or with the gst_app_sink_is_eos() method.
   *
  #include <gst/gst.h>
  #include <gst/base/gstbasesink.h>
  #include <gst/gstbuffer.h>
 -#include <gst/gstbufferlist.h>
  
  #include <string.h>
  
 +#include "gstapp-marshal.h"
  #include "gstappsink.h"
  
+ #include "gst/glib-compat-private.h"
  struct _GstAppSinkPrivate
  {
    GstCaps *caps;
    gboolean emit_signals;
 +  guint num_buffers;
    guint max_buffers;
    gboolean drop;
  
@@@ -88,9 -89,6 +90,9 @@@
    GMutex *mutex;
    GQueue *queue;
    GstBuffer *preroll;
 +  GstCaps *preroll_caps;
 +  GstCaps *last_caps;
 +  GstSegment last_segment;
    gboolean flushing;
    gboolean unlock;
    gboolean started;
    GstAppSinkCallbacks callbacks;
    gpointer user_data;
    GDestroyNotify notify;
 -
 -  gboolean buffer_lists_supported;
  };
  
  GST_DEBUG_CATEGORY_STATIC (app_sink_debug);
@@@ -109,11 -109,13 +111,11 @@@ enu
    /* signals */
    SIGNAL_EOS,
    SIGNAL_NEW_PREROLL,
 -  SIGNAL_NEW_BUFFER,
 -  SIGNAL_NEW_BUFFER_LIST,
 +  SIGNAL_NEW_SAMPLE,
  
    /* actions */
    SIGNAL_PULL_PREROLL,
 -  SIGNAL_PULL_BUFFER,
 -  SIGNAL_PULL_BUFFER_LIST,
 +  SIGNAL_PULL_SAMPLE,
  
    LAST_SIGNAL
  };
@@@ -158,27 -160,87 +160,27 @@@ static gboolean gst_app_sink_stop (GstB
  static gboolean gst_app_sink_event (GstBaseSink * sink, GstEvent * event);
  static GstFlowReturn gst_app_sink_preroll (GstBaseSink * psink,
      GstBuffer * buffer);
 -static GstFlowReturn gst_app_sink_render_common (GstBaseSink * psink,
 -    GstMiniObject * data, gboolean is_list);
  static GstFlowReturn gst_app_sink_render (GstBaseSink * psink,
      GstBuffer * buffer);
 -static GstFlowReturn gst_app_sink_render_list (GstBaseSink * psink,
 -    GstBufferList * list);
 -static GstCaps *gst_app_sink_getcaps (GstBaseSink * psink);
 -static GstMiniObject *gst_app_sink_pull_object (GstAppSink * appsink);
 +static gboolean gst_app_sink_setcaps (GstBaseSink * sink, GstCaps * caps);
 +static GstCaps *gst_app_sink_getcaps (GstBaseSink * psink, GstCaps * filter);
  
  static guint gst_app_sink_signals[LAST_SIGNAL] = { 0 };
  
 -static void
 -_do_init (GType filesrc_type)
 -{
 -  static const GInterfaceInfo urihandler_info = {
 -    gst_app_sink_uri_handler_init,
 -    NULL,
 -    NULL
 -  };
 -  g_type_add_interface_static (filesrc_type, GST_TYPE_URI_HANDLER,
 -      &urihandler_info);
 -}
 -
 -GST_BOILERPLATE_FULL (GstAppSink, gst_app_sink, GstBaseSink, GST_TYPE_BASE_SINK,
 -    _do_init);
 -
 -/* Can't use glib-genmarshal for this, as it doesn't know how to handle
 - * GstMiniObject-based types, which are a new fundamental type */
 -static void
 -gst_app_marshal_BUFFER__VOID (GClosure * closure,
 -    GValue * return_value,
 -    guint n_param_values,
 -    const GValue * param_values,
 -    gpointer invocation_hint, gpointer marshal_data)
 -{
 -  typedef GstBuffer *(*GMarshalFunc_BUFFER__VOID) (gpointer data1,
 -      gpointer data2);
 -  register GMarshalFunc_BUFFER__VOID callback;
 -  register GCClosure *cc = (GCClosure *) closure;
 -  register gpointer data1, data2;
 -  GstBuffer *v_return;
 -
 -  g_return_if_fail (return_value != NULL);
 -  g_return_if_fail (n_param_values == 1);
 -
 -  if (G_CCLOSURE_SWAP_DATA (closure)) {
 -    data1 = closure->data;
 -    data2 = g_value_peek_pointer (param_values + 0);
 -  } else {
 -    data1 = g_value_peek_pointer (param_values + 0);
 -    data2 = closure->data;
 -  }
 -  callback =
 -      (GMarshalFunc_BUFFER__VOID) (marshal_data ? marshal_data : cc->callback);
 -
 -  v_return = callback (data1, data2);
 -
 -  gst_value_take_buffer (return_value, v_return);
 -}
 -
 -static void
 -gst_app_sink_base_init (gpointer g_class)
 -{
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 -
 -  GST_DEBUG_CATEGORY_INIT (app_sink_debug, "appsink", 0, "appsink element");
 -
 -  gst_element_class_set_details_simple (element_class, "AppSink",
 -      "Generic/Sink", "Allow the application to get access to raw buffer",
 -      "David Schleef <ds@schleef.org>, Wim Taymans <wim.taymans@gmail.com>");
 -
 -  gst_element_class_add_static_pad_template (element_class,
 -      &gst_app_sink_template);
 -}
 +#define gst_app_sink_parent_class parent_class
 +G_DEFINE_TYPE_WITH_CODE (GstAppSink, gst_app_sink, GST_TYPE_BASE_SINK,
 +    G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER,
 +        gst_app_sink_uri_handler_init));
  
  static void
  gst_app_sink_class_init (GstAppSinkClass * klass)
  {
    GObjectClass *gobject_class = (GObjectClass *) klass;
 +  GstElementClass *element_class = (GstElementClass *) klass;
    GstBaseSinkClass *basesink_class = (GstBaseSinkClass *) klass;
  
 +  GST_DEBUG_CATEGORY_INIT (app_sink_debug, "appsink", 0, "appsink element");
 +
    gobject_class->dispose = gst_app_sink_dispose;
    gobject_class->finalize = gst_app_sink_finalize;
  
     * GstAppSink::new-preroll:
     * @appsink: the appsink element that emitted the signal
     *
 -   * Signal that a new preroll buffer is available.
 +   * Signal that a new preroll sample is available.
     *
     * This signal is emitted from the steaming thread and only when the
     * "emit-signals" property is %TRUE.
     *
 -   * The new preroll buffer can be retrieved with the "pull-preroll" action
 +   * The new preroll sample can be retrieved with the "pull-preroll" action
     * signal or gst_app_sink_pull_preroll() either from this signal callback
     * or from any other thread.
     *
        G_STRUCT_OFFSET (GstAppSinkClass, new_preroll),
        NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
    /**
 -   * GstAppSink::new-buffer:
 -   * @appsink: the appsink element that emitted the signal
 +   * GstAppSink::new-sample:
 +   * @appsink: the appsink element that emited the signal
     *
 -   * Signal that a new buffer is available.
 +   * Signal that a new sample is available.
     *
     * This signal is emitted from the steaming thread and only when the
     * "emit-signals" property is %TRUE.
     *
 -   * The new buffer can be retrieved with the "pull-buffer" action
 -   * signal or gst_app_sink_pull_buffer() either from this signal callback
 +   * The new sample can be retrieved with the "pull-sample" action
 +   * signal or gst_app_sink_pull_sample() either from this signal callback
     * or from any other thread.
     *
     * Note that this signal is only emitted when the "emit-signals" property is
     * set to %TRUE, which it is not by default for performance reasons.
     */
 -  gst_app_sink_signals[SIGNAL_NEW_BUFFER] =
 -      g_signal_new ("new-buffer", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
 -      G_STRUCT_OFFSET (GstAppSinkClass, new_buffer),
 -      NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
 -  /**
 -   * GstAppSink::new-buffer-list:
 -   * @appsink: the appsink element that emitted the signal
 -   *
 -   * Signal that a new bufferlist is available.
 -   *
 -   * This signal is emitted from the steaming thread and only when the
 -   * "emit-signals" property is %TRUE.
 -   *
 -   * The new buffer can be retrieved with the "pull-buffer-list" action
 -   * signal or gst_app_sink_pull_buffer_list() either from this signal callback
 -   * or from any other thread.
 -   *
 -   * Note that this signal is only emitted when the "emit-signals" property is
 -   * set to %TRUE, which it is not by default for performance reasons.
 -   */
 -  gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST] =
 -      g_signal_new ("new-buffer-list", G_TYPE_FROM_CLASS (klass),
 -      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstAppSinkClass, new_buffer_list),
 +  gst_app_sink_signals[SIGNAL_NEW_SAMPLE] =
 +      g_signal_new ("new-sample", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
 +      G_STRUCT_OFFSET (GstAppSinkClass, new_sample),
        NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
  
    /**
     * GstAppSink::pull-preroll:
     * @appsink: the appsink element to emit this signal on
     *
 -   * Get the last preroll buffer in @appsink. This was the buffer that caused the
 -   * appsink to preroll in the PAUSED state. This buffer can be pulled many times
 +   * Get the last preroll sample in @appsink. This was the sample that caused the
 +   * appsink to preroll in the PAUSED state. This sample can be pulled many times
     * and remains available to the application even after EOS.
     *
     * This function is typically used when dealing with a pipeline in the PAUSED
 -   * state. Calling this function after doing a seek will give the buffer right
 +   * state. Calling this function after doing a seek will give the sample right
     * after the seek position.
     *
 -   * Note that the preroll buffer will also be returned as the first buffer
 -   * when calling gst_app_sink_pull_buffer() or the "pull-buffer" action signal.
 +   * Note that the preroll sample will also be returned as the first sample
 +   * when calling gst_app_sink_pull_sample() or the "pull-sample" action signal.
     *
     * If an EOS event was received before any buffers, this function returns
     * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
     *
 -   * This function blocks until a preroll buffer or EOS is received or the appsink
 +   * This function blocks until a preroll sample or EOS is received or the appsink
     * element is set to the READY/NULL state.
     *
 -   * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
 +   * Returns: a #GstSample or NULL when the appsink is stopped or EOS.
     */
    gst_app_sink_signals[SIGNAL_PULL_PREROLL] =
        g_signal_new ("pull-preroll", G_TYPE_FROM_CLASS (klass),
        G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
 -          pull_preroll), NULL, NULL, gst_app_marshal_BUFFER__VOID,
 -      GST_TYPE_BUFFER, 0, G_TYPE_NONE);
 +          pull_preroll), NULL, NULL, __gst_app_marshal_BOXED__VOID,
 +      GST_TYPE_SAMPLE, 0, G_TYPE_NONE);
    /**
 -   * GstAppSink::pull-buffer:
 +   * GstAppSink::pull-sample:
     * @appsink: the appsink element to emit this signal on
     *
 -   * This function blocks until a buffer or EOS becomes available or the appsink
 +   * This function blocks until a sample or EOS becomes available or the appsink
     * element is set to the READY/NULL state.
     *
 -   * This function will only return buffers when the appsink is in the PLAYING
 -   * state. All rendered buffers will be put in a queue so that the application
 -   * can pull buffers at its own rate.
 +   * This function will only return samples when the appsink is in the PLAYING
 +   * state. All rendered samples will be put in a queue so that the application
 +   * can pull samples at its own rate.
     *
 -   * Note that when the application does not pull buffers fast enough, the
 -   * queued buffers could consume a lot of memory, especially when dealing with
 +   * Note that when the application does not pull samples fast enough, the
 +   * queued samples could consume a lot of memory, especially when dealing with
     * raw video frames. It's possible to control the behaviour of the queue with
     * the "drop" and "max-buffers" properties.
     *
     * If an EOS event was received before any buffers, this function returns
     * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
     *
 -   * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
 +   * Returns: a #GstSample or NULL when the appsink is stopped or EOS.
     */
 -  gst_app_sink_signals[SIGNAL_PULL_BUFFER] =
 -      g_signal_new ("pull-buffer", G_TYPE_FROM_CLASS (klass),
 +  gst_app_sink_signals[SIGNAL_PULL_SAMPLE] =
 +      g_signal_new ("pull-sample", G_TYPE_FROM_CLASS (klass),
        G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
 -          pull_buffer), NULL, NULL, gst_app_marshal_BUFFER__VOID,
 -      GST_TYPE_BUFFER, 0, G_TYPE_NONE);
 -  /**
 -   * GstAppSink::pull-buffer-list:
 -   * @appsink: the appsink element to emit this signal on
 -   *
 -   * This function blocks until a buffer list or EOS becomes available or the appsink
 -   * element is set to the READY/NULL state.
 -   *
 -   * This function will only return bufferlists when the appsink is in the PLAYING
 -   * state. All rendered bufferlists will be put in a queue so that the application
 -   * can pull bufferlists at its own rate.
 -   *
 -   * Note that when the application does not pull bufferlists fast enough, the
 -   * queued bufferlists could consume a lot of memory, especially when dealing with
 -   * raw video frames. It's possible to control the behaviour of the queue with
 -   * the "drop" and "max-buffers" properties.
 -   *
 -   * If an EOS event was received before any buffers, this function returns
 -   * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
 -   *
 -   * Returns: a #GstBufferList or NULL when the appsink is stopped or EOS.
 -   */
 -  gst_app_sink_signals[SIGNAL_PULL_BUFFER_LIST] =
 -      g_signal_new ("pull-buffer-list", G_TYPE_FROM_CLASS (klass),
 -      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
 -          pull_buffer_list), NULL, NULL, gst_app_marshal_BUFFER__VOID,
 -      GST_TYPE_BUFFER_LIST, 0, G_TYPE_NONE);
 +          pull_sample), NULL, NULL, __gst_app_marshal_BOXED__VOID,
 +      GST_TYPE_SAMPLE, 0, G_TYPE_NONE);
 +
 +  gst_element_class_set_details_simple (element_class, "AppSink",
 +      "Generic/Sink", "Allow the application to get access to raw buffer",
 +      "David Schleef <ds@schleef.org>, Wim Taymans <wim.taymans@gmail.com>");
 +
 +  gst_element_class_add_pad_template (element_class,
 +      gst_static_pad_template_get (&gst_app_sink_template));
  
    basesink_class->unlock = gst_app_sink_unlock_start;
    basesink_class->unlock_stop = gst_app_sink_unlock_stop;
    basesink_class->event = gst_app_sink_event;
    basesink_class->preroll = gst_app_sink_preroll;
    basesink_class->render = gst_app_sink_render;
 -  basesink_class->render_list = gst_app_sink_render_list;
    basesink_class->get_caps = gst_app_sink_getcaps;
 +  basesink_class->set_caps = gst_app_sink_setcaps;
  
    klass->pull_preroll = gst_app_sink_pull_preroll;
 -  klass->pull_buffer = gst_app_sink_pull_buffer;
 -  klass->pull_buffer_list = gst_app_sink_pull_buffer_list;
 +  klass->pull_sample = gst_app_sink_pull_sample;
  
    g_type_class_add_private (klass, sizeof (GstAppSinkPrivate));
  }
  
  static void
 -gst_app_sink_init (GstAppSink * appsink, GstAppSinkClass * klass)
 +gst_app_sink_init (GstAppSink * appsink)
  {
    GstAppSinkPrivate *priv;
  
@@@ -381,11 -483,12 +383,11 @@@ gst_app_sink_dispose (GObject * obj
    GST_OBJECT_UNLOCK (appsink);
  
    g_mutex_lock (priv->mutex);
 -  if (priv->preroll) {
 -    gst_buffer_unref (priv->preroll);
 -    priv->preroll = NULL;
 -  }
    while ((queue_obj = g_queue_pop_head (priv->queue)))
      gst_mini_object_unref (queue_obj);
 +  gst_buffer_replace (&priv->preroll, NULL);
 +  gst_caps_replace (&priv->preroll_caps, NULL);
 +  gst_caps_replace (&priv->last_caps, NULL);
    g_mutex_unlock (priv->mutex);
  
    G_OBJECT_CLASS (parent_class)->dispose (obj);
@@@ -505,10 -608,24 +507,10 @@@ gst_app_sink_flush_unlocked (GstAppSin
    gst_buffer_replace (&priv->preroll, NULL);
    while ((obj = g_queue_pop_head (priv->queue)))
      gst_mini_object_unref (obj);
 +  priv->num_buffers = 0;
    g_cond_signal (priv->cond);
  }
  
 -#define NEW_BUFFER_LIST_SIGID \
 -    gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST]
 -
 -static gboolean
 -gst_app_sink_check_buffer_lists_support (GstAppSink * appsink)
 -{
 -  gboolean ret;
 -
 -  ret = (appsink->priv->callbacks.new_buffer_list != NULL) ||
 -      g_signal_has_handler_pending (appsink, NEW_BUFFER_LIST_SIGID, 0, FALSE);
 -
 -  GST_INFO_OBJECT (appsink, "application supports buffer lists: %d", ret);
 -  return ret;
 -}
 -
  static gboolean
  gst_app_sink_start (GstBaseSink * psink)
  {
    GST_DEBUG_OBJECT (appsink, "starting");
    priv->flushing = FALSE;
    priv->started = TRUE;
 -  priv->buffer_lists_supported =
 -      gst_app_sink_check_buffer_lists_support (appsink);
 +  gst_segment_init (&priv->last_segment, GST_FORMAT_TIME);
    g_mutex_unlock (priv->mutex);
  
    return TRUE;
@@@ -536,23 -654,6 +538,23 @@@ gst_app_sink_stop (GstBaseSink * psink
    priv->flushing = TRUE;
    priv->started = FALSE;
    gst_app_sink_flush_unlocked (appsink);
 +  gst_caps_replace (&priv->preroll_caps, NULL);
 +  gst_caps_replace (&priv->last_caps, NULL);
 +  g_mutex_unlock (priv->mutex);
 +
 +  return TRUE;
 +}
 +
 +static gboolean
 +gst_app_sink_setcaps (GstBaseSink * sink, GstCaps * caps)
 +{
 +  GstAppSink *appsink = GST_APP_SINK_CAST (sink);
 +  GstAppSinkPrivate *priv = appsink->priv;
 +
 +  g_mutex_lock (priv->mutex);
 +  GST_DEBUG_OBJECT (appsink, "receiving CAPS");
 +  g_queue_push_tail (priv->queue, gst_event_new_caps (caps));
 +  gst_caps_replace (&priv->preroll_caps, caps);
    g_mutex_unlock (priv->mutex);
  
    return TRUE;
@@@ -565,13 -666,8 +567,13 @@@ gst_app_sink_event (GstBaseSink * sink
    GstAppSinkPrivate *priv = appsink->priv;
  
    switch (event->type) {
 +    case GST_EVENT_SEGMENT:
 +      g_mutex_lock (priv->mutex);
 +      GST_DEBUG_OBJECT (appsink, "receiving SEGMENT");
 +      g_queue_push_tail (priv->queue, gst_event_ref (event));
 +      g_mutex_unlock (priv->mutex);
 +      break;
      case GST_EVENT_EOS:
 -
        g_mutex_lock (priv->mutex);
        GST_DEBUG_OBJECT (appsink, "receiving EOS");
        priv->is_eos = TRUE;
      default:
        break;
    }
 -  return TRUE;
 +  return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
  }
  
  static GstFlowReturn
@@@ -636,52 -732,9 +638,52 @@@ flushing
    }
  }
  
 +static GstBuffer *
 +dequeue_buffer (GstAppSink * appsink)
 +{
 +  GstAppSinkPrivate *priv = appsink->priv;
 +  GstBuffer *buffer;
 +
 +  do {
 +    GstMiniObject *obj;
 +
 +    obj = g_queue_pop_head (priv->queue);
 +
 +    if (GST_IS_BUFFER (obj)) {
 +      buffer = GST_BUFFER_CAST (obj);
 +      GST_DEBUG_OBJECT (appsink, "dequeued buffer %p", buffer);
 +      priv->num_buffers--;
 +      break;
 +    } else if (GST_IS_EVENT (obj)) {
 +      GstEvent *event = GST_EVENT_CAST (obj);
 +
 +      switch (GST_EVENT_TYPE (obj)) {
 +        case GST_EVENT_CAPS:
 +        {
 +          GstCaps *caps;
 +
 +          gst_event_parse_caps (event, &caps);
 +          GST_DEBUG_OBJECT (appsink, "activating caps %" GST_PTR_FORMAT, caps);
 +          gst_caps_replace (&priv->last_caps, caps);
 +          break;
 +        }
 +        case GST_EVENT_SEGMENT:
 +          gst_event_copy_segment (event, &priv->last_segment);
 +          GST_DEBUG_OBJECT (appsink, "activated segment %" GST_SEGMENT_FORMAT,
 +              &priv->last_segment);
 +          break;
 +        default:
 +          break;
 +      }
 +      gst_mini_object_unref (obj);
 +    }
 +  } while (TRUE);
 +
 +  return buffer;
 +}
 +
  static GstFlowReturn
 -gst_app_sink_render_common (GstBaseSink * psink, GstMiniObject * data,
 -    gboolean is_list)
 +gst_app_sink_render (GstBaseSink * psink, GstBuffer * buffer)
  {
    GstFlowReturn ret;
    GstAppSink *appsink = GST_APP_SINK_CAST (psink);
@@@ -693,21 -746,20 +695,21 @@@ restart
    if (priv->flushing)
      goto flushing;
  
 -  GST_DEBUG_OBJECT (appsink, "pushing render buffer%s %p on queue (%d)",
 -      is_list ? " list" : "", data, priv->queue->length);
 +  GST_DEBUG_OBJECT (appsink, "pushing render buffer %p on queue (%d)",
 +      buffer, priv->num_buffers);
  
 -  while (priv->max_buffers > 0 && priv->queue->length >= priv->max_buffers) {
 +  while (priv->max_buffers > 0 && priv->num_buffers >= priv->max_buffers) {
      if (priv->drop) {
 -      GstMiniObject *obj;
 +      GstBuffer *old;
  
 -      /* we need to drop the oldest buffer/list and try again */
 -      obj = g_queue_pop_head (priv->queue);
 -      GST_DEBUG_OBJECT (appsink, "dropping old buffer/list %p", obj);
 -      gst_mini_object_unref (obj);
 +      /* we need to drop the oldest buffer and try again */
 +      if ((old = dequeue_buffer (appsink))) {
 +        GST_DEBUG_OBJECT (appsink, "dropping old buffer %p", old);
 +        gst_buffer_unref (old);
 +      }
      } else {
        GST_DEBUG_OBJECT (appsink, "waiting for free space, length %d >= %d",
 -          priv->queue->length, priv->max_buffers);
 +          priv->num_buffers, priv->max_buffers);
  
        if (priv->unlock) {
          /* we are asked to unlock, call the wait_preroll method */
      }
    }
    /* we need to ref the buffer when pushing it in the queue */
 -  g_queue_push_tail (priv->queue, gst_mini_object_ref (data));
 +  g_queue_push_tail (priv->queue, gst_buffer_ref (buffer));
 +  priv->num_buffers++;
    g_cond_signal (priv->cond);
    emit = priv->emit_signals;
    g_mutex_unlock (priv->mutex);
  
 -  if (is_list) {
 -    if (priv->callbacks.new_buffer_list)
 -      priv->callbacks.new_buffer_list (appsink, priv->user_data);
 -    else if (emit)
 -      g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST], 0);
 -  } else {
 -    if (priv->callbacks.new_buffer)
 -      priv->callbacks.new_buffer (appsink, priv->user_data);
 -    else if (emit)
 -      g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_BUFFER], 0);
 -  }
 +  if (priv->callbacks.new_sample)
 +    priv->callbacks.new_sample (appsink, priv->user_data);
 +  else if (emit)
 +    g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_SAMPLE], 0);
 +
    return GST_FLOW_OK;
  
  flushing:
@@@ -752,26 -809,121 +754,26 @@@ stopping
    }
  }
  
 -static GstFlowReturn
 -gst_app_sink_render (GstBaseSink * psink, GstBuffer * buffer)
 -{
 -  return gst_app_sink_render_common (psink, GST_MINI_OBJECT_CAST (buffer),
 -      FALSE);
 -}
 -
 -static GstFlowReturn
 -gst_app_sink_render_list (GstBaseSink * sink, GstBufferList * list)
 -{
 -  GstBufferListIterator *it;
 -  GstFlowReturn flow;
 -  GstAppSink *appsink;
 -  GstBuffer *group;
 -
 -  appsink = GST_APP_SINK_CAST (sink);
 -
 -  if (appsink->priv->buffer_lists_supported)
 -    return gst_app_sink_render_common (sink, GST_MINI_OBJECT_CAST (list), TRUE);
 -
 -  /* The application doesn't support buffer lists, extract individual buffers
 -   * then and push them one-by-one */
 -  GST_INFO_OBJECT (sink, "chaining each group in list as a merged buffer");
 -
 -  it = gst_buffer_list_iterate (list);
 -
 -  if (gst_buffer_list_iterator_next_group (it)) {
 -    do {
 -      group = gst_buffer_list_iterator_merge_group (it);
 -      if (group == NULL) {
 -        group = gst_buffer_new ();
 -        GST_DEBUG_OBJECT (sink, "chaining empty group");
 -      } else {
 -        GST_DEBUG_OBJECT (sink, "chaining group");
 -      }
 -      flow = gst_app_sink_render (sink, group);
 -      gst_buffer_unref (group);
 -    } while (flow == GST_FLOW_OK && gst_buffer_list_iterator_next_group (it));
 -  } else {
 -    GST_DEBUG_OBJECT (sink, "chaining empty group");
 -    group = gst_buffer_new ();
 -    flow = gst_app_sink_render (sink, group);
 -    gst_buffer_unref (group);
 -  }
 -
 -  gst_buffer_list_iterator_free (it);
 -
 -  return flow;
 -}
 -
  static GstCaps *
 -gst_app_sink_getcaps (GstBaseSink * psink)
 +gst_app_sink_getcaps (GstBaseSink * psink, GstCaps * filter)
  {
    GstCaps *caps;
    GstAppSink *appsink = GST_APP_SINK_CAST (psink);
    GstAppSinkPrivate *priv = appsink->priv;
  
    GST_OBJECT_LOCK (appsink);
 -  if ((caps = priv->caps))
 -    gst_caps_ref (caps);
 +  if ((caps = priv->caps)) {
 +    if (filter)
 +      caps = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
 +    else
 +      gst_caps_ref (caps);
 +  }
    GST_DEBUG_OBJECT (appsink, "got caps %" GST_PTR_FORMAT, caps);
    GST_OBJECT_UNLOCK (appsink);
  
    return caps;
  }
  
 -static GstMiniObject *
 -gst_app_sink_pull_object (GstAppSink * appsink)
 -{
 -  GstMiniObject *obj = NULL;
 -  GstAppSinkPrivate *priv;
 -
 -  g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
 -
 -  priv = appsink->priv;
 -
 -  g_mutex_lock (priv->mutex);
 -
 -  while (TRUE) {
 -    GST_DEBUG_OBJECT (appsink, "trying to grab a buffer/list");
 -    if (!priv->started)
 -      goto not_started;
 -
 -    if (!g_queue_is_empty (priv->queue))
 -      break;
 -
 -    if (priv->is_eos)
 -      goto eos;
 -
 -    /* nothing to return, wait */
 -    GST_DEBUG_OBJECT (appsink, "waiting for a buffer/list");
 -    g_cond_wait (priv->cond, priv->mutex);
 -  }
 -  obj = g_queue_pop_head (priv->queue);
 -  GST_DEBUG_OBJECT (appsink, "we have a buffer/list %p", obj);
 -  g_cond_signal (priv->cond);
 -  g_mutex_unlock (priv->mutex);
 -
 -  return obj;
 -
 -  /* special conditions */
 -eos:
 -  {
 -    GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL");
 -    g_mutex_unlock (priv->mutex);
 -    return NULL;
 -  }
 -not_started:
 -  {
 -    GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL");
 -    g_mutex_unlock (priv->mutex);
 -    return NULL;
 -  }
 -}
 -
  /* external API */
  
  /**
@@@ -842,13 -994,13 +844,13 @@@ gst_app_sink_get_caps (GstAppSink * app
   * gst_app_sink_is_eos:
   * @appsink: a #GstAppSink
   *
 - * Check if @appsink is EOS, which is when no more buffers can be pulled because
 + * Check if @appsink is EOS, which is when no more samples can be pulled because
   * an EOS event was received.
   *
   * This function also returns %TRUE when the appsink is not in the PAUSED or
   * PLAYING state.
   *
 - * Returns: %TRUE if no more buffers can be pulled and the appsink is EOS.
 + * Returns: %TRUE if no more samples can be pulled and the appsink is EOS.
   *
   * Since: 0.10.22
   */
@@@ -866,7 -1018,7 +868,7 @@@ gst_app_sink_is_eos (GstAppSink * appsi
    if (!priv->started)
      goto not_started;
  
 -  if (priv->is_eos && g_queue_is_empty (priv->queue)) {
 +  if (priv->is_eos && priv->num_buffers == 0) {
      GST_DEBUG_OBJECT (appsink, "we are EOS and the queue is empty");
      ret = TRUE;
    } else {
@@@ -890,7 -1042,7 +892,7 @@@ not_started
   * @appsink: a #GstAppSink
   * @emit: the new state
   *
 - * Make appsink emit the "new-preroll" and "new-buffer" signals. This option is
 + * Make appsink emit the "new-preroll" and "new-sample" signals. This option is
   * by default disabled because signal emission is expensive and unneeded when
   * the application prefers to operate in pull mode.
   *
@@@ -914,9 -1066,9 +916,9 @@@ gst_app_sink_set_emit_signals (GstAppSi
   * gst_app_sink_get_emit_signals:
   * @appsink: a #GstAppSink
   *
 - * Check if appsink will emit the "new-preroll" and "new-buffer" signals.
 + * Check if appsink will emit the "new-preroll" and "new-sample" signals.
   *
 - * Returns: %TRUE if @appsink is emitting the "new-preroll" and "new-buffer"
 + * Returns: %TRUE if @appsink is emiting the "new-preroll" and "new-sample"
   * signals.
   *
   * Since: 0.10.22
@@@ -945,7 -1097,7 +947,7 @@@ gst_app_sink_get_emit_signals (GstAppSi
   *
   * Set the maximum amount of buffers that can be queued in @appsink. After this
   * amount of buffers are queued in appsink, any more buffers will block upstream
 - * elements until a buffer is pulled from @appsink.
 + * elements until a sample is pulled from @appsink.
   *
   * Since: 0.10.22
   */
@@@ -1055,31 -1207,31 +1057,31 @@@ gst_app_sink_get_drop (GstAppSink * app
   * gst_app_sink_pull_preroll:
   * @appsink: a #GstAppSink
   *
 - * Get the last preroll buffer in @appsink. This was the buffer that caused the
 - * appsink to preroll in the PAUSED state. This buffer can be pulled many times
 + * Get the last preroll sample in @appsink. This was the sample that caused the
 + * appsink to preroll in the PAUSED state. This sample can be pulled many times
   * and remains available to the application even after EOS.
   *
   * This function is typically used when dealing with a pipeline in the PAUSED
 - * state. Calling this function after doing a seek will give the buffer right
 + * state. Calling this function after doing a seek will give the sample right
   * after the seek position.
   *
 - * Note that the preroll buffer will also be returned as the first buffer
 - * when calling gst_app_sink_pull_buffer().
 + * Note that the preroll sample will also be returned as the first sample
 + * when calling gst_app_sink_pull_sample().
   *
   * If an EOS event was received before any buffers, this function returns
   * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
   *
 - * This function blocks until a preroll buffer or EOS is received or the appsink
 + * This function blocks until a preroll sample or EOS is received or the appsink
   * element is set to the READY/NULL state.
   *
   * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
   *
   * Since: 0.10.22
   */
 -GstBuffer *
 +GstSample *
  gst_app_sink_pull_preroll (GstAppSink * appsink)
  {
 -  GstBuffer *buf = NULL;
 +  GstSample *sample = NULL;
    GstAppSinkPrivate *priv;
  
    g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
      GST_DEBUG_OBJECT (appsink, "waiting for the preroll buffer");
      g_cond_wait (priv->cond, priv->mutex);
    }
 -  buf = gst_buffer_ref (priv->preroll);
 -  GST_DEBUG_OBJECT (appsink, "we have the preroll buffer %p", buf);
 +  sample =
 +      gst_sample_new (priv->preroll, priv->preroll_caps, &priv->last_segment,
 +      NULL);
 +  GST_DEBUG_OBJECT (appsink, "we have the preroll sample %p", sample);
    g_mutex_unlock (priv->mutex);
  
 -  return buf;
 +  return sample;
  
    /* special conditions */
  eos:
@@@ -1127,16 -1277,16 +1129,16 @@@ not_started
  }
  
  /**
 - * gst_app_sink_pull_buffer:
 + * gst_app_sink_pull_sample:
   * @appsink: a #GstAppSink
   *
 - * This function blocks until a buffer or EOS becomes available or the appsink
 + * This function blocks until a sample or EOS becomes available or the appsink
   * element is set to the READY/NULL state.
   *
 - * This function will only return buffers when the appsink is in the PLAYING
 + * This function will only return samples when the appsink is in the PLAYING
   * state. All rendered buffers will be put in a queue so that the application
 - * can pull buffers at its own rate. Note that when the application does not
 - * pull buffers fast enough, the queued buffers could consume a lot of memory,
 + * can pull samples at its own rate. Note that when the application does not
 + * pull samples fast enough, the queued buffers could consume a lot of memory,
   * especially when dealing with raw video frames.
   *
   * If an EOS event was received before any buffers, this function returns
   * Since: 0.10.22
   */
  
 -GstBuffer *
 -gst_app_sink_pull_buffer (GstAppSink * appsink)
 +GstSample *
 +gst_app_sink_pull_sample (GstAppSink * appsink)
  {
 -  GST_DEBUG_OBJECT (appsink, "pull a buffer");
 -  return GST_BUFFER_CAST (gst_app_sink_pull_object (appsink));
 -}
 +  GstSample *sample = NULL;
 +  GstBuffer *buffer;
 +  GstAppSinkPrivate *priv;
  
 -/**
 - * gst_app_sink_pull_buffer_list:
 - * @appsink: a #GstAppSink
 - *
 - * This function blocks until a buffer list or EOS becomes available or the
 - * appsink element is set to the READY/NULL state.
 - *
 - * This function will only return buffer lists when the appsink is in the
 - * PLAYING state. All rendered buffer lists will be put in a queue so that
 - * the application can pull buffer lists at its own rate. Note that when
 - * the application does not pull buffer lists fast enough, the queued buffer
 - * lists could consume a lot of memory, especially when dealing with raw
 - * video frames.
 - *
 - * If an EOS event was received before any buffer lists, this function returns
 - * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
 - *
 - * Returns: a #GstBufferList or NULL when the appsink is stopped or EOS.
 - */
 -GstBufferList *
 -gst_app_sink_pull_buffer_list (GstAppSink * appsink)
 -{
 -  GST_DEBUG_OBJECT (appsink, "pull a buffer list");
 -  return GST_BUFFER_LIST_CAST (gst_app_sink_pull_object (appsink));
 +  g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
 +
 +  priv = appsink->priv;
 +
 +  g_mutex_lock (priv->mutex);
 +
 +  while (TRUE) {
 +    GST_DEBUG_OBJECT (appsink, "trying to grab a buffer");
 +    if (!priv->started)
 +      goto not_started;
 +
 +    if (priv->num_buffers > 0)
 +      break;
 +
 +    if (priv->is_eos)
 +      goto eos;
 +
 +    /* nothing to return, wait */
 +    GST_DEBUG_OBJECT (appsink, "waiting for a buffer");
 +    g_cond_wait (priv->cond, priv->mutex);
 +  }
 +  buffer = dequeue_buffer (appsink);
 +  GST_DEBUG_OBJECT (appsink, "we have a buffer %p", buffer);
 +  sample = gst_sample_new (buffer, priv->last_caps, &priv->last_segment, NULL);
 +  gst_buffer_unref (buffer);
 +
 +  g_cond_signal (priv->cond);
 +  g_mutex_unlock (priv->mutex);
 +
 +  return sample;
 +
 +  /* special conditions */
 +eos:
 +  {
 +    GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL");
 +    g_mutex_unlock (priv->mutex);
 +    return NULL;
 +  }
 +not_started:
 +  {
 +    GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL");
 +    g_mutex_unlock (priv->mutex);
 +    return NULL;
 +  }
  }
  
  /**
   * @user_data: a user_data argument for the callbacks
   * @notify: a destroy notify function
   *
 - * Set callbacks which will be executed for each new preroll, new buffer and eos.
 + * Set callbacks which will be executed for each new preroll, new sample and eos.
   * This is an alternative to using the signals, it has lower overhead and is thus
   * less expensive, but also less flexible.
   *
@@@ -1247,37 -1377,44 +1249,37 @@@ gst_app_sink_set_callbacks (GstAppSink 
    priv->callbacks = *callbacks;
    priv->user_data = user_data;
    priv->notify = notify;
 -  priv->buffer_lists_supported =
 -      gst_app_sink_check_buffer_lists_support (appsink);
    GST_OBJECT_UNLOCK (appsink);
  }
  
  /*** GSTURIHANDLER INTERFACE *************************************************/
  
  static GstURIType
 -gst_app_sink_uri_get_type (void)
 +gst_app_sink_uri_get_type (GType type)
  {
    return GST_URI_SINK;
  }
  
 -static gchar **
 -gst_app_sink_uri_get_protocols (void)
 +static const gchar *const *
 +gst_app_sink_uri_get_protocols (GType type)
  {
 -  static gchar *protocols[] = { (char *) "appsink", NULL };
 +  static const gchar *protocols[] = { "appsink", NULL };
  
    return protocols;
  }
  
 -static const gchar *
 +static gchar *
  gst_app_sink_uri_get_uri (GstURIHandler * handler)
  {
 -  return "appsink";
 +  return g_strdup ("appsink");
  }
  
  static gboolean
 -gst_app_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri)
 +gst_app_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri,
 +    GError ** error)
  {
 -  gchar *protocol;
 -  gboolean ret;
 -
 -  protocol = gst_uri_get_protocol (uri);
 -  ret = !strcmp (protocol, "appsink");
 -  g_free (protocol);
 -
 -  return ret;
 +  /* GstURIHandler checks the protocol for us */
 +  return TRUE;
  }
  
  static void
@@@ -1289,5 -1426,4 +1291,5 @@@ gst_app_sink_uri_handler_init (gpointe
    iface->get_protocols = gst_app_sink_uri_get_protocols;
    iface->get_uri = gst_app_sink_uri_get_uri;
    iface->set_uri = gst_app_sink_uri_set_uri;
 +
  }
  #include "gstapp-marshal.h"
  #include "gstappsrc.h"
  
+ #include "gst/glib-compat-private.h"
  struct _GstAppSrcPrivate
  {
    GCond *cond;
@@@ -217,7 -219,6 +219,7 @@@ static void gst_app_src_get_property (G
  static void gst_app_src_set_latencies (GstAppSrc * appsrc,
      gboolean do_min, guint64 min, gboolean do_max, guint64 max);
  
 +static gboolean gst_app_src_negotiate (GstBaseSrc * basesrc);
  static GstFlowReturn gst_app_src_create (GstBaseSrc * bsrc,
      guint64 offset, guint size, GstBuffer ** buf);
  static gboolean gst_app_src_start (GstBaseSrc * bsrc);
@@@ -226,6 -227,7 +228,6 @@@ static gboolean gst_app_src_unlock (Gst
  static gboolean gst_app_src_unlock_stop (GstBaseSrc * bsrc);
  static gboolean gst_app_src_do_seek (GstBaseSrc * src, GstSegment * segment);
  static gboolean gst_app_src_is_seekable (GstBaseSrc * src);
 -static gboolean gst_app_src_check_get_range (GstBaseSrc * src);
  static gboolean gst_app_src_do_get_size (GstBaseSrc * src, guint64 * size);
  static gboolean gst_app_src_query (GstBaseSrc * src, GstQuery * query);
  
@@@ -234,19 -236,42 +236,19 @@@ static GstFlowReturn gst_app_src_push_b
  
  static guint gst_app_src_signals[LAST_SIGNAL] = { 0 };
  
 -static void
 -_do_init (GType filesrc_type)
 -{
 -  static const GInterfaceInfo urihandler_info = {
 -    gst_app_src_uri_handler_init,
 -    NULL,
 -    NULL
 -  };
 -  g_type_add_interface_static (filesrc_type, GST_TYPE_URI_HANDLER,
 -      &urihandler_info);
 -}
 -
 -GST_BOILERPLATE_FULL (GstAppSrc, gst_app_src, GstBaseSrc, GST_TYPE_BASE_SRC,
 -    _do_init);
 -
 -static void
 -gst_app_src_base_init (gpointer g_class)
 -{
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 -
 -  GST_DEBUG_CATEGORY_INIT (app_src_debug, "appsrc", 0, "appsrc element");
 -
 -  gst_element_class_set_details_simple (element_class, "AppSrc",
 -      "Generic/Source", "Allow the application to feed buffers to a pipeline",
 -      "David Schleef <ds@schleef.org>, Wim Taymans <wim.taymans@gmail.com>");
 -
 -  gst_element_class_add_static_pad_template (element_class,
 -      &gst_app_src_template);
 -}
 +#define gst_app_src_parent_class parent_class
 +G_DEFINE_TYPE_WITH_CODE (GstAppSrc, gst_app_src, GST_TYPE_BASE_SRC,
 +    G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gst_app_src_uri_handler_init));
  
  static void
  gst_app_src_class_init (GstAppSrcClass * klass)
  {
    GObjectClass *gobject_class = (GObjectClass *) klass;
 +  GstElementClass *element_class = (GstElementClass *) klass;
    GstBaseSrcClass *basesrc_class = (GstBaseSrcClass *) klass;
  
 +  GST_DEBUG_CATEGORY_INIT (app_src_debug, "appsrc", 0, "appsrc element");
 +
    gobject_class->dispose = gst_app_src_dispose;
    gobject_class->finalize = gst_app_src_finalize;
  
    gst_app_src_signals[SIGNAL_PUSH_BUFFER] =
        g_signal_new ("push-buffer", G_TYPE_FROM_CLASS (klass),
        G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSrcClass,
 -          push_buffer), NULL, NULL, __gst_app_marshal_ENUM__OBJECT,
 +          push_buffer), NULL, NULL, __gst_app_marshal_ENUM__BOXED,
        GST_TYPE_FLOW_RETURN, 1, GST_TYPE_BUFFER);
  
     /**
            end_of_stream), NULL, NULL, __gst_app_marshal_ENUM__VOID,
        GST_TYPE_FLOW_RETURN, 0, G_TYPE_NONE);
  
 +  gst_element_class_set_details_simple (element_class, "AppSrc",
 +      "Generic/Source", "Allow the application to feed buffers to a pipeline",
 +      "David Schleef <ds@schleef.org>, Wim Taymans <wim.taymans@gmail.com>");
 +
 +  gst_element_class_add_pad_template (element_class,
 +      gst_static_pad_template_get (&gst_app_src_template));
 +
 +  basesrc_class->negotiate = gst_app_src_negotiate;
    basesrc_class->create = gst_app_src_create;
    basesrc_class->start = gst_app_src_start;
    basesrc_class->stop = gst_app_src_stop;
    basesrc_class->unlock_stop = gst_app_src_unlock_stop;
    basesrc_class->do_seek = gst_app_src_do_seek;
    basesrc_class->is_seekable = gst_app_src_is_seekable;
 -  basesrc_class->check_get_range = gst_app_src_check_get_range;
    basesrc_class->get_size = gst_app_src_do_get_size;
    basesrc_class->get_size = gst_app_src_do_get_size;
    basesrc_class->query = gst_app_src_query;
  }
  
  static void
 -gst_app_src_init (GstAppSrc * appsrc, GstAppSrcClass * klass)
 +gst_app_src_init (GstAppSrc * appsrc)
  {
    GstAppSrcPrivate *priv;
  
@@@ -750,6 -768,24 +752,6 @@@ gst_app_src_is_seekable (GstBaseSrc * s
  }
  
  static gboolean
 -gst_app_src_check_get_range (GstBaseSrc * src)
 -{
 -  GstAppSrc *appsrc = GST_APP_SRC_CAST (src);
 -  GstAppSrcPrivate *priv = appsrc->priv;
 -  gboolean res = FALSE;
 -
 -  switch (priv->stream_type) {
 -    case GST_APP_STREAM_TYPE_STREAM:
 -    case GST_APP_STREAM_TYPE_SEEKABLE:
 -      break;
 -    case GST_APP_STREAM_TYPE_RANDOM_ACCESS:
 -      res = TRUE;
 -      break;
 -  }
 -  return res;
 -}
 -
 -static gboolean
  gst_app_src_do_get_size (GstBaseSrc * src, guint64 * size)
  {
    GstAppSrc *appsrc = GST_APP_SRC_CAST (src);
@@@ -786,22 -822,6 +788,22 @@@ gst_app_src_query (GstBaseSrc * src, Gs
        gst_query_set_latency (query, live, min, max);
        break;
      }
 +    case GST_QUERY_SCHEDULING:
 +    {
 +      gst_query_set_scheduling (query, GST_SCHEDULING_FLAG_SEEKABLE, 1, -1, 0);
 +      gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH);
 +
 +      switch (priv->stream_type) {
 +        case GST_APP_STREAM_TYPE_STREAM:
 +        case GST_APP_STREAM_TYPE_SEEKABLE:
 +          break;
 +        case GST_APP_STREAM_TYPE_RANDOM_ACCESS:
 +          gst_query_add_scheduling_mode (query, GST_PAD_MODE_PULL);
 +          break;
 +      }
 +      res = TRUE;
 +      break;
 +    }
      default:
        res = GST_BASE_SRC_CLASS (parent_class)->query (src, query);
        break;
@@@ -819,7 -839,7 +821,7 @@@ gst_app_src_do_seek (GstBaseSrc * src, 
    gint64 desired_position;
    gboolean res = FALSE;
  
 -  desired_position = segment->last_stop;
 +  desired_position = segment->position;
  
    GST_DEBUG_OBJECT (appsrc, "seeking to %" G_GINT64_FORMAT ", format %s",
        desired_position, gst_format_get_name (segment->format));
@@@ -901,28 -921,6 +903,28 @@@ gst_app_src_emit_need_data (GstAppSrc 
    /* we can be flushing now because we released the lock */
  }
  
 +static gboolean
 +gst_app_src_negotiate (GstBaseSrc * basesrc)
 +{
 +  GstAppSrc *appsrc = GST_APP_SRC_CAST (basesrc);
 +  GstAppSrcPrivate *priv = appsrc->priv;
 +  GstCaps *caps;
 +  gboolean result;
 +
 +  GST_OBJECT_LOCK (appsrc);
 +  if ((caps = priv->caps))
 +    gst_caps_ref (caps);
 +  GST_OBJECT_UNLOCK (appsrc);
 +
 +  if (caps) {
 +    result = gst_base_src_set_caps (basesrc, caps);
 +    gst_caps_unref (caps);
 +  } else {
 +    result = GST_BASE_SRC_CLASS (parent_class)->negotiate (basesrc);
 +  }
 +  return result;
 +}
 +
  static GstFlowReturn
  gst_app_src_create (GstBaseSrc * bsrc, guint64 offset, guint size,
      GstBuffer ** buf)
    GstAppSrc *appsrc = GST_APP_SRC_CAST (bsrc);
    GstAppSrcPrivate *priv = appsrc->priv;
    GstFlowReturn ret;
 -  GstCaps *caps;
  
    GST_OBJECT_LOCK (appsrc);
 -  caps = priv->caps ? gst_caps_ref (priv->caps) : NULL;
    if (G_UNLIKELY (priv->size != bsrc->segment.duration &&
            bsrc->segment.format == GST_FORMAT_BYTES)) {
      GST_DEBUG_OBJECT (appsrc,
          "Size changed from %" G_GINT64_FORMAT " to %" G_GINT64_FORMAT,
          bsrc->segment.duration, priv->size);
 -    gst_segment_set_duration (&bsrc->segment, GST_FORMAT_BYTES, priv->size);
 +    bsrc->segment.duration = priv->size;
      GST_OBJECT_UNLOCK (appsrc);
  
      gst_element_post_message (GST_ELEMENT (appsrc),
        guint buf_size;
  
        *buf = g_queue_pop_head (priv->queue);
 -      buf_size = GST_BUFFER_SIZE (*buf);
 +      buf_size = gst_buffer_get_size (*buf);
  
        GST_DEBUG_OBJECT (appsrc, "we have buffer %p of size %u", *buf, buf_size);
  
        /* only update the offset when in random_access mode */
        if (priv->stream_type == GST_APP_STREAM_TYPE_RANDOM_ACCESS)
          priv->offset += buf_size;
 -      if (caps) {
 -        *buf = gst_buffer_make_metadata_writable (*buf);
 -        gst_buffer_set_caps (*buf, caps);
 -      }
  
        /* signal that we removed an item */
        g_cond_broadcast (priv->cond);
      g_cond_wait (priv->cond, priv->mutex);
    }
    g_mutex_unlock (priv->mutex);
 -  if (caps)
 -    gst_caps_unref (caps);
    return ret;
  
    /* ERRORS */
@@@ -1030,17 -1036,23 +1032,17 @@@ flushing
    {
      GST_DEBUG_OBJECT (appsrc, "we are flushing");
      g_mutex_unlock (priv->mutex);
 -    if (caps)
 -      gst_caps_unref (caps);
      return GST_FLOW_WRONG_STATE;
    }
  eos:
    {
      GST_DEBUG_OBJECT (appsrc, "we are EOS");
      g_mutex_unlock (priv->mutex);
 -    if (caps)
 -      gst_caps_unref (caps);
 -    return GST_FLOW_UNEXPECTED;
 +    return GST_FLOW_EOS;
    }
  seek_error:
    {
      g_mutex_unlock (priv->mutex);
 -    if (caps)
 -      gst_caps_unref (caps);
      GST_ELEMENT_ERROR (appsrc, RESOURCE, READ, ("failed to seek"),
          GST_ERROR_SYSTEM);
      return GST_FLOW_ERROR;
@@@ -1467,7 -1479,7 +1469,7 @@@ gst_app_src_push_buffer_full (GstAppSr
    if (!steal_ref)
      gst_buffer_ref (buffer);
    g_queue_push_tail (priv->queue, buffer);
 -  priv->queued_bytes += GST_BUFFER_SIZE (buffer);
 +  priv->queued_bytes += gst_buffer_get_size (buffer);
    g_cond_broadcast (priv->cond);
    g_mutex_unlock (priv->mutex);
  
@@@ -1488,7 -1500,7 +1490,7 @@@ eos
      if (steal_ref)
        gst_buffer_unref (buffer);
      g_mutex_unlock (priv->mutex);
 -    return GST_FLOW_UNEXPECTED;
 +    return GST_FLOW_EOS;
    }
  }
  
   *
   * Returns: #GST_FLOW_OK when the buffer was successfuly queued.
   * #GST_FLOW_WRONG_STATE when @appsrc is not PAUSED or PLAYING.
 - * #GST_FLOW_UNEXPECTED when EOS occured.
 + * #GST_FLOW_EOS when EOS occured.
   *
   * Since: 0.10.22
   */
@@@ -1620,31 -1632,36 +1622,31 @@@ gst_app_src_set_callbacks (GstAppSrc * 
  /*** GSTURIHANDLER INTERFACE *************************************************/
  
  static GstURIType
 -gst_app_src_uri_get_type (void)
 +gst_app_src_uri_get_type (GType type)
  {
    return GST_URI_SRC;
  }
  
 -static gchar **
 -gst_app_src_uri_get_protocols (void)
 +static const gchar *const *
 +gst_app_src_uri_get_protocols (GType type)
  {
 -  static gchar *protocols[] = { (char *) "appsrc", NULL };
 +  static const gchar *protocols[] = { "appsrc", NULL };
  
    return protocols;
  }
  
 -static const gchar *
 +static gchar *
  gst_app_src_uri_get_uri (GstURIHandler * handler)
  {
 -  return "appsrc";
 +  return g_strdup ("appsrc");
  }
  
  static gboolean
 -gst_app_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
 +gst_app_src_uri_set_uri (GstURIHandler * handler, const gchar * uri,
 +    GError ** error)
  {
 -  gchar *protocol;
 -  gboolean ret;
 -
 -  protocol = gst_uri_get_protocol (uri);
 -  ret = !strcmp (protocol, "appsrc");
 -  g_free (protocol);
 -
 -  return ret;
 +  /* GstURIHandler checks the protocol for us */
 +  return TRUE;
  }
  
  static void
@@@ -2,7 -2,7 +2,7 @@@
   * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
   *                    2005 Wim Taymans <wim@fluendo.com>
   *
 - * gstbaseaudiosink.c:
 + * gstaudiobasesink.c:
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Library General Public
@@@ -21,9 -21,9 +21,9 @@@
   */
  
  /**
 - * SECTION:gstbaseaudiosink
 + * SECTION:gstaudiobasesink
   * @short_description: Base class for audio sinks
 - * @see_also: #GstAudioSink, #GstRingBuffer.
 + * @see_also: #GstAudioSink, #GstAudioRingBuffer.
   *
   * This is the base class for audio sinks. Subclasses need to implement the
   * ::create_ringbuffer vmethod. This base class will then take care of
  
  #include <string.h>
  
+ /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+  * with newer GLib versions (>= 2.31.0) */
+ #define GLIB_DISABLE_DEPRECATION_WARNINGS
 +#include "gstaudiobasesink.h"
  
 -#include "gstbaseaudiosink.h"
 +GST_DEBUG_CATEGORY_STATIC (gst_audio_base_sink_debug);
 +#define GST_CAT_DEFAULT gst_audio_base_sink_debug
  
 -GST_DEBUG_CATEGORY_STATIC (gst_base_audio_sink_debug);
 -#define GST_CAT_DEFAULT gst_base_audio_sink_debug
 +#define GST_AUDIO_BASE_SINK_GET_PRIVATE(obj)  \
 +   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_AUDIO_BASE_SINK, GstAudioBaseSinkPrivate))
  
 -#define GST_BASE_AUDIO_SINK_GET_PRIVATE(obj)  \
 -   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_AUDIO_SINK, GstBaseAudioSinkPrivate))
 -
 -struct _GstBaseAudioSinkPrivate
 +struct _GstAudioBaseSinkPrivate
  {
    /* upstream latency */
    GstClockTime us_latency;
    /* the clock slaving algorithm in use */
 -  GstBaseAudioSinkSlaveMethod slave_method;
 +  GstAudioBaseSinkSlaveMethod slave_method;
    /* running average of clock skew */
    GstClockTimeDiff avg_skew;
    /* the number of samples we aligned last time */
@@@ -57,6 -61,7 +60,6 @@@
  
    GstClockTime eos_time;
  
 -  gboolean do_time_offset;
    /* number of microseconds we allow clock slaving to drift
     * before resyncing */
    guint64 drift_tolerance;
@@@ -83,7 -88,7 +86,7 @@@ enu
  #define DEFAULT_BUFFER_TIME     ((200 * GST_MSECOND) / GST_USECOND)
  #define DEFAULT_LATENCY_TIME    ((10 * GST_MSECOND) / GST_USECOND)
  #define DEFAULT_PROVIDE_CLOCK   TRUE
 -#define DEFAULT_SLAVE_METHOD    GST_BASE_AUDIO_SINK_SLAVE_SKEW
 +#define DEFAULT_SLAVE_METHOD    GST_AUDIO_BASE_SINK_SLAVE_SKEW
  
  /* FIXME, enable pull mode when clock slaving and trick modes are figured out */
  #define DEFAULT_CAN_ACTIVATE_PULL FALSE
@@@ -117,20 -122,20 +120,20 @@@ enu
  };
  
  GType
 -gst_base_audio_sink_slave_method_get_type (void)
 +gst_audio_base_sink_slave_method_get_type (void)
  {
    static volatile gsize slave_method_type = 0;
    static const GEnumValue slave_method[] = {
 -    {GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE, "GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE",
 +    {GST_AUDIO_BASE_SINK_SLAVE_RESAMPLE, "GST_AUDIO_BASE_SINK_SLAVE_RESAMPLE",
          "resample"},
 -    {GST_BASE_AUDIO_SINK_SLAVE_SKEW, "GST_BASE_AUDIO_SINK_SLAVE_SKEW", "skew"},
 -    {GST_BASE_AUDIO_SINK_SLAVE_NONE, "GST_BASE_AUDIO_SINK_SLAVE_NONE", "none"},
 +    {GST_AUDIO_BASE_SINK_SLAVE_SKEW, "GST_AUDIO_BASE_SINK_SLAVE_SKEW", "skew"},
 +    {GST_AUDIO_BASE_SINK_SLAVE_NONE, "GST_AUDIO_BASE_SINK_SLAVE_NONE", "none"},
      {0, NULL, NULL},
    };
  
    if (g_once_init_enter (&slave_method_type)) {
      GType tmp =
 -        g_enum_register_static ("GstBaseAudioSinkSlaveMethod", slave_method);
 +        g_enum_register_static ("GstAudioBaseSinkSlaveMethod", slave_method);
      g_once_init_leave (&slave_method_type, tmp);
    }
  
  }
  
  
 -#define _do_init(bla) \
 -    GST_DEBUG_CATEGORY_INIT (gst_base_audio_sink_debug, "baseaudiosink", 0, "baseaudiosink element");
 -
 -GST_BOILERPLATE_FULL (GstBaseAudioSink, gst_base_audio_sink, GstBaseSink,
 +#define _do_init \
 +    GST_DEBUG_CATEGORY_INIT (gst_audio_base_sink_debug, "audiobasesink", 0, "audiobasesink element");
 +#define gst_audio_base_sink_parent_class parent_class
 +G_DEFINE_TYPE_WITH_CODE (GstAudioBaseSink, gst_audio_base_sink,
      GST_TYPE_BASE_SINK, _do_init);
  
 -static void gst_base_audio_sink_dispose (GObject * object);
 +static void gst_audio_base_sink_dispose (GObject * object);
  
 -static void gst_base_audio_sink_set_property (GObject * object, guint prop_id,
 +static void gst_audio_base_sink_set_property (GObject * object, guint prop_id,
      const GValue * value, GParamSpec * pspec);
 -static void gst_base_audio_sink_get_property (GObject * object, guint prop_id,
 +static void gst_audio_base_sink_get_property (GObject * object, guint prop_id,
      GValue * value, GParamSpec * pspec);
  
 -static GstStateChangeReturn gst_base_audio_sink_async_play (GstBaseSink *
 +#if 0
 +static GstStateChangeReturn gst_audio_base_sink_async_play (GstBaseSink *
      basesink);
 -static GstStateChangeReturn gst_base_audio_sink_change_state (GstElement *
 +#endif
 +static GstStateChangeReturn gst_audio_base_sink_change_state (GstElement *
      element, GstStateChange transition);
 -static gboolean gst_base_audio_sink_activate_pull (GstBaseSink * basesink,
 +static gboolean gst_audio_base_sink_activate_pull (GstBaseSink * basesink,
      gboolean active);
 -static gboolean gst_base_audio_sink_query (GstElement * element, GstQuery *
 +static gboolean gst_audio_base_sink_query (GstElement * element, GstQuery *
      query);
  
 -static GstClock *gst_base_audio_sink_provide_clock (GstElement * elem);
 -static GstClockTime gst_base_audio_sink_get_time (GstClock * clock,
 -    GstBaseAudioSink * sink);
 -static void gst_base_audio_sink_callback (GstRingBuffer * rbuf, guint8 * data,
 -    guint len, gpointer user_data);
 +static GstClock *gst_audio_base_sink_provide_clock (GstElement * elem);
 +static GstClockTime gst_audio_base_sink_get_time (GstClock * clock,
 +    GstAudioBaseSink * sink);
 +static void gst_audio_base_sink_callback (GstAudioRingBuffer * rbuf,
 +    guint8 * data, guint len, gpointer user_data);
  
 -static GstFlowReturn gst_base_audio_sink_preroll (GstBaseSink * bsink,
 +static GstFlowReturn gst_audio_base_sink_preroll (GstBaseSink * bsink,
      GstBuffer * buffer);
 -static GstFlowReturn gst_base_audio_sink_render (GstBaseSink * bsink,
 +static GstFlowReturn gst_audio_base_sink_render (GstBaseSink * bsink,
      GstBuffer * buffer);
 -static gboolean gst_base_audio_sink_event (GstBaseSink * bsink,
 +static gboolean gst_audio_base_sink_event (GstBaseSink * bsink,
      GstEvent * event);
 -static void gst_base_audio_sink_get_times (GstBaseSink * bsink,
 +static GstFlowReturn gst_audio_base_sink_wait_eos (GstBaseSink * bsink,
 +    GstEvent * event);
 +static void gst_audio_base_sink_get_times (GstBaseSink * bsink,
      GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
 -static gboolean gst_base_audio_sink_setcaps (GstBaseSink * bsink,
 +static gboolean gst_audio_base_sink_setcaps (GstBaseSink * bsink,
      GstCaps * caps);
 -static void gst_base_audio_sink_fixate (GstBaseSink * bsink, GstCaps * caps);
 +static void gst_audio_base_sink_fixate (GstBaseSink * bsink, GstCaps * caps);
  
 -static gboolean gst_base_audio_sink_query_pad (GstPad * pad, GstQuery * query);
 +static gboolean gst_audio_base_sink_query_pad (GstBaseSink * bsink,
 +    GstQuery * query);
  
  
 -/* static guint gst_base_audio_sink_signals[LAST_SIGNAL] = { 0 }; */
 +/* static guint gst_audio_base_sink_signals[LAST_SIGNAL] = { 0 }; */
  
  static void
 -gst_base_audio_sink_base_init (gpointer g_class)
 -{
 -}
 -
 -static void
 -gst_base_audio_sink_class_init (GstBaseAudioSinkClass * klass)
 +gst_audio_base_sink_class_init (GstAudioBaseSinkClass * klass)
  {
    GObjectClass *gobject_class;
    GstElementClass *gstelement_class;
    gstelement_class = (GstElementClass *) klass;
    gstbasesink_class = (GstBaseSinkClass *) klass;
  
 -  g_type_class_add_private (klass, sizeof (GstBaseAudioSinkPrivate));
 +  g_type_class_add_private (klass, sizeof (GstAudioBaseSinkPrivate));
  
 -  gobject_class->set_property = gst_base_audio_sink_set_property;
 -  gobject_class->get_property = gst_base_audio_sink_get_property;
 -  gobject_class->dispose = gst_base_audio_sink_dispose;
 +  gobject_class->set_property = gst_audio_base_sink_set_property;
 +  gobject_class->get_property = gst_audio_base_sink_get_property;
 +  gobject_class->dispose = gst_audio_base_sink_dispose;
  
    g_object_class_install_property (gobject_class, PROP_BUFFER_TIME,
        g_param_spec_int64 ("buffer-time", "Buffer Time",
    g_object_class_install_property (gobject_class, PROP_SLAVE_METHOD,
        g_param_spec_enum ("slave-method", "Slave Method",
            "Algorithm to use to match the rate of the masterclock",
 -          GST_TYPE_BASE_AUDIO_SINK_SLAVE_METHOD, DEFAULT_SLAVE_METHOD,
 +          GST_TYPE_AUDIO_BASE_SINK_SLAVE_METHOD, DEFAULT_SLAVE_METHOD,
            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
    g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL,
            "Allow pull-based scheduling", DEFAULT_CAN_ACTIVATE_PULL,
            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
    /**
 -   * GstBaseAudioSink:drift-tolerance
 +   * GstAudioBaseSink:drift-tolerance
     *
     * Controls the amount of time in microseconds that clocks are allowed
     * to drift before resynchronisation happens.
            G_MAXINT64, DEFAULT_DRIFT_TOLERANCE,
            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
    /**
 -   * GstBaseAudioSink:alignment_threshold
 +   * GstAudioBaseSink:alignment_threshold
     *
     * Controls the amount of time in nanoseconds that timestamps are allowed
     * to drift from their ideal time before choosing not to align them.
            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
    /**
 -   * GstBaseAudioSink:discont-wait
 +   * GstAudioBaseSink:discont-wait
     *
     * A window of time in nanoseconds to wait before creating a discontinuity as
     * a result of breaching the drift-tolerance.
            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
    gstelement_class->change_state =
 -      GST_DEBUG_FUNCPTR (gst_base_audio_sink_change_state);
 +      GST_DEBUG_FUNCPTR (gst_audio_base_sink_change_state);
    gstelement_class->provide_clock =
 -      GST_DEBUG_FUNCPTR (gst_base_audio_sink_provide_clock);
 -  gstelement_class->query = GST_DEBUG_FUNCPTR (gst_base_audio_sink_query);
 -
 -  gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_base_audio_sink_event);
 -  gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_base_audio_sink_preroll);
 -  gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_base_audio_sink_render);
 +      GST_DEBUG_FUNCPTR (gst_audio_base_sink_provide_clock);
 +  gstelement_class->query = GST_DEBUG_FUNCPTR (gst_audio_base_sink_query);
 +
 +  gstbasesink_class->fixate = GST_DEBUG_FUNCPTR (gst_audio_base_sink_fixate);
 +  gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_audio_base_sink_setcaps);
 +  gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_audio_base_sink_event);
 +  gstbasesink_class->wait_eos =
 +      GST_DEBUG_FUNCPTR (gst_audio_base_sink_wait_eos);
    gstbasesink_class->get_times =
 -      GST_DEBUG_FUNCPTR (gst_base_audio_sink_get_times);
 -  gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_base_audio_sink_setcaps);
 -  gstbasesink_class->fixate = GST_DEBUG_FUNCPTR (gst_base_audio_sink_fixate);
 -  gstbasesink_class->async_play =
 -      GST_DEBUG_FUNCPTR (gst_base_audio_sink_async_play);
 +      GST_DEBUG_FUNCPTR (gst_audio_base_sink_get_times);
 +  gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_audio_base_sink_preroll);
 +  gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_audio_base_sink_render);
 +  gstbasesink_class->query = GST_DEBUG_FUNCPTR (gst_audio_base_sink_query_pad);
    gstbasesink_class->activate_pull =
 -      GST_DEBUG_FUNCPTR (gst_base_audio_sink_activate_pull);
 +      GST_DEBUG_FUNCPTR (gst_audio_base_sink_activate_pull);
  
    /* ref class from a thread-safe context to work around missing bit of
     * thread-safety in GObject */
    g_type_class_ref (GST_TYPE_AUDIO_CLOCK);
 -  g_type_class_ref (GST_TYPE_RING_BUFFER);
 +  g_type_class_ref (GST_TYPE_AUDIO_RING_BUFFER);
  
  }
  
  static void
 -gst_base_audio_sink_init (GstBaseAudioSink * baseaudiosink,
 -    GstBaseAudioSinkClass * g_class)
 +gst_audio_base_sink_init (GstAudioBaseSink * audiobasesink)
  {
 -  GstPluginFeature *feature;
    GstBaseSink *basesink;
  
 -  baseaudiosink->priv = GST_BASE_AUDIO_SINK_GET_PRIVATE (baseaudiosink);
 +  audiobasesink->priv = GST_AUDIO_BASE_SINK_GET_PRIVATE (audiobasesink);
  
 -  baseaudiosink->buffer_time = DEFAULT_BUFFER_TIME;
 -  baseaudiosink->latency_time = DEFAULT_LATENCY_TIME;
 -  baseaudiosink->provide_clock = DEFAULT_PROVIDE_CLOCK;
 -  baseaudiosink->priv->slave_method = DEFAULT_SLAVE_METHOD;
 -  baseaudiosink->priv->drift_tolerance = DEFAULT_DRIFT_TOLERANCE;
 -  baseaudiosink->priv->alignment_threshold = DEFAULT_ALIGNMENT_THRESHOLD;
 -  baseaudiosink->priv->discont_wait = DEFAULT_DISCONT_WAIT;
 +  audiobasesink->buffer_time = DEFAULT_BUFFER_TIME;
 +  audiobasesink->latency_time = DEFAULT_LATENCY_TIME;
 +  audiobasesink->priv->slave_method = DEFAULT_SLAVE_METHOD;
 +  audiobasesink->priv->drift_tolerance = DEFAULT_DRIFT_TOLERANCE;
 +  audiobasesink->priv->alignment_threshold = DEFAULT_ALIGNMENT_THRESHOLD;
 +  audiobasesink->priv->discont_wait = DEFAULT_DISCONT_WAIT;
  
 -  baseaudiosink->provided_clock = gst_audio_clock_new ("GstAudioSinkClock",
 -      (GstAudioClockGetTimeFunc) gst_base_audio_sink_get_time, baseaudiosink);
 +  audiobasesink->provided_clock = gst_audio_clock_new ("GstAudioSinkClock",
 +      (GstAudioClockGetTimeFunc) gst_audio_base_sink_get_time, audiobasesink,
 +      NULL);
  
 -  basesink = GST_BASE_SINK_CAST (baseaudiosink);
 +  basesink = GST_BASE_SINK_CAST (audiobasesink);
    basesink->can_activate_push = TRUE;
    basesink->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
  
 -  gst_base_sink_set_last_buffer_enabled (basesink, FALSE);
 -
 -  /* install some custom pad_query functions */
 -  gst_pad_set_query_function (GST_BASE_SINK_PAD (baseaudiosink),
 -      GST_DEBUG_FUNCPTR (gst_base_audio_sink_query_pad));
 -
 -  baseaudiosink->priv->do_time_offset = TRUE;
 -
 -  /* check the factory, pulsesink < 0.10.17 does the timestamp offset itself so
 -   * we should not do ourselves */
 -  feature =
 -      GST_PLUGIN_FEATURE_CAST (GST_ELEMENT_CLASS (g_class)->elementfactory);
 -  GST_DEBUG ("created from factory %p", feature);
 -
 -  /* HACK for old pulsesink that did the time_offset themselves */
 -  if (feature) {
 -    if (strcmp (gst_plugin_feature_get_name (feature), "pulsesink") == 0) {
 -      if (!gst_plugin_feature_check_version (feature, 0, 10, 17)) {
 -        /* we're dealing with an old pulsesink, we need to disable time correction */
 -        GST_DEBUG ("disable time offset");
 -        baseaudiosink->priv->do_time_offset = FALSE;
 -      }
 -    }
 -  }
 +  gst_base_sink_set_last_sample_enabled (basesink, FALSE);
 +  if (DEFAULT_PROVIDE_CLOCK)
 +    GST_OBJECT_FLAG_SET (basesink, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
 +  else
 +    GST_OBJECT_FLAG_UNSET (basesink, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
  }
  
  static void
 -gst_base_audio_sink_dispose (GObject * object)
 +gst_audio_base_sink_dispose (GObject * object)
  {
 -  GstBaseAudioSink *sink;
 +  GstAudioBaseSink *sink;
  
 -  sink = GST_BASE_AUDIO_SINK (object);
 +  sink = GST_AUDIO_BASE_SINK (object);
  
    if (sink->provided_clock) {
      gst_audio_clock_invalidate (sink->provided_clock);
  
  
  static GstClock *
 -gst_base_audio_sink_provide_clock (GstElement * elem)
 +gst_audio_base_sink_provide_clock (GstElement * elem)
  {
 -  GstBaseAudioSink *sink;
 +  GstAudioBaseSink *sink;
    GstClock *clock;
  
 -  sink = GST_BASE_AUDIO_SINK (elem);
 +  sink = GST_AUDIO_BASE_SINK (elem);
  
    /* we have no ringbuffer (must be NULL state) */
    if (sink->ringbuffer == NULL)
      goto wrong_state;
  
 -  if (!gst_ring_buffer_is_acquired (sink->ringbuffer))
 +  if (!gst_audio_ring_buffer_is_acquired (sink->ringbuffer))
      goto wrong_state;
  
    GST_OBJECT_LOCK (sink);
 -  if (!sink->provide_clock)
 +  if (!GST_OBJECT_FLAG_IS_SET (sink, GST_ELEMENT_FLAG_PROVIDE_CLOCK))
      goto clock_disabled;
  
    clock = GST_CLOCK_CAST (gst_object_ref (sink->provided_clock));
@@@ -390,12 -415,12 +393,12 @@@ clock_disabled
  }
  
  static gboolean
 -gst_base_audio_sink_query_pad (GstPad * pad, GstQuery * query)
 +gst_audio_base_sink_query_pad (GstBaseSink * bsink, GstQuery * query)
  {
    gboolean res = FALSE;
 -  GstBaseAudioSink *basesink;
 +  GstAudioBaseSink *basesink;
  
 -  basesink = GST_BASE_AUDIO_SINK (gst_pad_get_parent (pad));
 +  basesink = GST_AUDIO_BASE_SINK (bsink);
  
    switch (GST_QUERY_TYPE (query)) {
      case GST_QUERY_CONVERT:
        GstFormat src_fmt, dest_fmt;
        gint64 src_val, dest_val;
  
 -      GST_LOG_OBJECT (pad, "query convert");
 +      GST_LOG_OBJECT (basesink, "query convert");
  
        if (basesink->ringbuffer) {
          gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, NULL);
 -        res = gst_ring_buffer_convert (basesink->ringbuffer, src_fmt, src_val,
 -            dest_fmt, &dest_val);
 +        res =
 +            gst_audio_ring_buffer_convert (basesink->ringbuffer, src_fmt,
 +            src_val, dest_fmt, &dest_val);
          if (res) {
            gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
          }
        break;
      }
      default:
 +      res = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query);
        break;
    }
 -
 -  gst_object_unref (basesink);
 -
    return res;
  }
  
  static gboolean
 -gst_base_audio_sink_query (GstElement * element, GstQuery * query)
 +gst_audio_base_sink_query (GstElement * element, GstQuery * query)
  {
    gboolean res = FALSE;
 -  GstBaseAudioSink *basesink;
 +  GstAudioBaseSink *basesink;
  
 -  basesink = GST_BASE_AUDIO_SINK (element);
 +  basesink = GST_AUDIO_BASE_SINK (element);
  
    switch (GST_QUERY_TYPE (query)) {
      case GST_QUERY_LATENCY:
  
          /* we and upstream are both live, adjust the min_latency */
          if (live && us_live) {
 -          GstRingBufferSpec *spec;
 +          GstAudioRingBufferSpec *spec;
  
            GST_OBJECT_LOCK (basesink);
 -          if (!basesink->ringbuffer || !basesink->ringbuffer->spec.rate) {
 +          if (!basesink->ringbuffer || !basesink->ringbuffer->spec.info.rate) {
              GST_OBJECT_UNLOCK (basesink);
  
              GST_DEBUG_OBJECT (basesink,
  
            base_latency =
                gst_util_uint64_scale_int (spec->seglatency * spec->segsize,
 -              GST_SECOND, spec->rate * spec->bytes_per_sample);
 +              GST_SECOND, spec->info.rate * spec->info.bpf);
            GST_OBJECT_UNLOCK (basesink);
  
            /* we cannot go lower than the buffer size and the min peer latency */
  
        if (basesink->ringbuffer) {
          gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, NULL);
 -        res = gst_ring_buffer_convert (basesink->ringbuffer, src_fmt, src_val,
 -            dest_fmt, &dest_val);
 +        res =
 +            gst_audio_ring_buffer_convert (basesink->ringbuffer, src_fmt,
 +            src_val, dest_fmt, &dest_val);
          if (res) {
            gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
          }
@@@ -520,21 -545,21 +523,21 @@@ done
  
  
  static GstClockTime
 -gst_base_audio_sink_get_time (GstClock * clock, GstBaseAudioSink * sink)
 +gst_audio_base_sink_get_time (GstClock * clock, GstAudioBaseSink * sink)
  {
    guint64 raw, samples;
    guint delay;
    GstClockTime result;
  
 -  if (sink->ringbuffer == NULL || sink->ringbuffer->spec.rate == 0)
 +  if (sink->ringbuffer == NULL || sink->ringbuffer->spec.info.rate == 0)
      return GST_CLOCK_TIME_NONE;
  
    /* our processed samples are always increasing */
 -  raw = samples = gst_ring_buffer_samples_done (sink->ringbuffer);
 +  raw = samples = gst_audio_ring_buffer_samples_done (sink->ringbuffer);
  
    /* the number of samples not yet processed, this is still queued in the
     * device (not played for playback). */
 -  delay = gst_ring_buffer_delay (sink->ringbuffer);
 +  delay = gst_audio_ring_buffer_delay (sink->ringbuffer);
  
    if (G_LIKELY (samples >= delay))
      samples -= delay;
      samples = 0;
  
    result = gst_util_uint64_scale_int (samples, GST_SECOND,
 -      sink->ringbuffer->spec.rate);
 +      sink->ringbuffer->spec.info.rate);
  
    GST_DEBUG_OBJECT (sink,
        "processed samples: raw %" G_GUINT64_FORMAT ", delay %u, real %"
  }
  
  /**
 - * gst_base_audio_sink_set_provide_clock:
 - * @sink: a #GstBaseAudioSink
 + * gst_audio_base_sink_set_provide_clock:
 + * @sink: a #GstAudioBaseSink
   * @provide: new state
   *
   * Controls whether @sink will provide a clock or not. If @provide is %TRUE,
   * Since: 0.10.16
   */
  void
 -gst_base_audio_sink_set_provide_clock (GstBaseAudioSink * sink,
 +gst_audio_base_sink_set_provide_clock (GstAudioBaseSink * sink,
      gboolean provide)
  {
 -  g_return_if_fail (GST_IS_BASE_AUDIO_SINK (sink));
 +  g_return_if_fail (GST_IS_AUDIO_BASE_SINK (sink));
  
    GST_OBJECT_LOCK (sink);
 -  sink->provide_clock = provide;
 +  if (provide)
 +    GST_OBJECT_FLAG_SET (sink, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
 +  else
 +    GST_OBJECT_FLAG_UNSET (sink, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
    GST_OBJECT_UNLOCK (sink);
  }
  
  /**
 - * gst_base_audio_sink_get_provide_clock:
 - * @sink: a #GstBaseAudioSink
 + * gst_audio_base_sink_get_provide_clock:
 + * @sink: a #GstAudioBaseSink
   *
   * Queries whether @sink will provide a clock or not. See also
 - * gst_base_audio_sink_set_provide_clock.
 + * gst_audio_base_sink_set_provide_clock.
   *
   * Returns: %TRUE if @sink will provide a clock.
   *
   * Since: 0.10.16
   */
  gboolean
 -gst_base_audio_sink_get_provide_clock (GstBaseAudioSink * sink)
 +gst_audio_base_sink_get_provide_clock (GstAudioBaseSink * sink)
  {
    gboolean result;
  
 -  g_return_val_if_fail (GST_IS_BASE_AUDIO_SINK (sink), FALSE);
 +  g_return_val_if_fail (GST_IS_AUDIO_BASE_SINK (sink), FALSE);
  
    GST_OBJECT_LOCK (sink);
 -  result = sink->provide_clock;
 +  result = GST_OBJECT_FLAG_IS_SET (sink, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
    GST_OBJECT_UNLOCK (sink);
  
    return result;
  }
  
  /**
 - * gst_base_audio_sink_set_slave_method:
 - * @sink: a #GstBaseAudioSink
 + * gst_audio_base_sink_set_slave_method:
 + * @sink: a #GstAudioBaseSink
   * @method: the new slave method
   *
   * Controls how clock slaving will be performed in @sink.
   * Since: 0.10.16
   */
  void
 -gst_base_audio_sink_set_slave_method (GstBaseAudioSink * sink,
 -    GstBaseAudioSinkSlaveMethod method)
 +gst_audio_base_sink_set_slave_method (GstAudioBaseSink * sink,
 +    GstAudioBaseSinkSlaveMethod method)
  {
 -  g_return_if_fail (GST_IS_BASE_AUDIO_SINK (sink));
 +  g_return_if_fail (GST_IS_AUDIO_BASE_SINK (sink));
  
    GST_OBJECT_LOCK (sink);
    sink->priv->slave_method = method;
  }
  
  /**
 - * gst_base_audio_sink_get_slave_method:
 - * @sink: a #GstBaseAudioSink
 + * gst_audio_base_sink_get_slave_method:
 + * @sink: a #GstAudioBaseSink
   *
   * Get the current slave method used by @sink.
   *
   *
   * Since: 0.10.16
   */
 -GstBaseAudioSinkSlaveMethod
 -gst_base_audio_sink_get_slave_method (GstBaseAudioSink * sink)
 +GstAudioBaseSinkSlaveMethod
 +gst_audio_base_sink_get_slave_method (GstAudioBaseSink * sink)
  {
 -  GstBaseAudioSinkSlaveMethod result;
 +  GstAudioBaseSinkSlaveMethod result;
  
 -  g_return_val_if_fail (GST_IS_BASE_AUDIO_SINK (sink), -1);
 +  g_return_val_if_fail (GST_IS_AUDIO_BASE_SINK (sink), -1);
  
    GST_OBJECT_LOCK (sink);
    result = sink->priv->slave_method;
  
  
  /**
 - * gst_base_audio_sink_set_drift_tolerance:
 - * @sink: a #GstBaseAudioSink
 + * gst_audio_base_sink_set_drift_tolerance:
 + * @sink: a #GstAudioBaseSink
   * @drift_tolerance: the new drift tolerance in microseconds
   *
   * Controls the sink's drift tolerance.
   * Since: 0.10.31
   */
  void
 -gst_base_audio_sink_set_drift_tolerance (GstBaseAudioSink * sink,
 +gst_audio_base_sink_set_drift_tolerance (GstAudioBaseSink * sink,
      gint64 drift_tolerance)
  {
 -  g_return_if_fail (GST_IS_BASE_AUDIO_SINK (sink));
 +  g_return_if_fail (GST_IS_AUDIO_BASE_SINK (sink));
  
    GST_OBJECT_LOCK (sink);
    sink->priv->drift_tolerance = drift_tolerance;
  }
  
  /**
 - * gst_base_audio_sink_get_drift_tolerance
 - * @sink: a #GstBaseAudioSink
 + * gst_audio_base_sink_get_drift_tolerance
 + * @sink: a #GstAudioBaseSink
   *
   * Get the current drift tolerance, in microseconds, used by @sink.
   *
   * Since: 0.10.31
   */
  gint64
 -gst_base_audio_sink_get_drift_tolerance (GstBaseAudioSink * sink)
 +gst_audio_base_sink_get_drift_tolerance (GstAudioBaseSink * sink)
  {
    gint64 result;
  
 -  g_return_val_if_fail (GST_IS_BASE_AUDIO_SINK (sink), -1);
 +  g_return_val_if_fail (GST_IS_AUDIO_BASE_SINK (sink), -1);
  
    GST_OBJECT_LOCK (sink);
    result = sink->priv->drift_tolerance;
  }
  
  /**
 - * gst_base_audio_sink_set_alignment_threshold:
 - * @sink: a #GstBaseAudioSink
 + * gst_audio_base_sink_set_alignment_threshold:
 + * @sink: a #GstAudioBaseSink
   * @alignment_threshold: the new alignment threshold in nanoseconds
   *
   * Controls the sink's alignment threshold.
   * Since: 0.10.36
   */
  void
 -gst_base_audio_sink_set_alignment_threshold (GstBaseAudioSink * sink,
 +gst_audio_base_sink_set_alignment_threshold (GstAudioBaseSink * sink,
      GstClockTime alignment_threshold)
  {
 -  g_return_if_fail (GST_IS_BASE_AUDIO_SINK (sink));
 +  g_return_if_fail (GST_IS_AUDIO_BASE_SINK (sink));
  
    GST_OBJECT_LOCK (sink);
    sink->priv->alignment_threshold = alignment_threshold;
  }
  
  /**
 - * gst_base_audio_sink_get_alignment_threshold
 - * @sink: a #GstBaseAudioSink
 + * gst_audio_base_sink_get_alignment_threshold
 + * @sink: a #GstAudioBaseSink
   *
   * Get the current alignment threshold, in nanoseconds, used by @sink.
   *
   * Since: 0.10.36
   */
  GstClockTime
 -gst_base_audio_sink_get_alignment_threshold (GstBaseAudioSink * sink)
 +gst_audio_base_sink_get_alignment_threshold (GstAudioBaseSink * sink)
  {
    gint64 result;
  
 -  g_return_val_if_fail (GST_IS_BASE_AUDIO_SINK (sink), -1);
 +  g_return_val_if_fail (GST_IS_AUDIO_BASE_SINK (sink), -1);
  
    GST_OBJECT_LOCK (sink);
    result = sink->priv->alignment_threshold;
  }
  
  /**
 - * gst_base_audio_sink_set_discont_wait:
 - * @sink: a #GstBaseAudioSink
 + * gst_audio_base_sink_set_discont_wait:
 + * @sink: a #GstAudioBaseSink
   * @discont_wait: the new discont wait in nanoseconds
   *
   * Controls how long the sink will wait before creating a discontinuity.
   * Since: 0.10.36
   */
  void
 -gst_base_audio_sink_set_discont_wait (GstBaseAudioSink * sink,
 +gst_audio_base_sink_set_discont_wait (GstAudioBaseSink * sink,
      GstClockTime discont_wait)
  {
 -  g_return_if_fail (GST_IS_BASE_AUDIO_SINK (sink));
 +  g_return_if_fail (GST_IS_AUDIO_BASE_SINK (sink));
  
    GST_OBJECT_LOCK (sink);
    sink->priv->discont_wait = discont_wait;
  }
  
  /**
 - * gst_base_audio_sink_get_discont_wait
 - * @sink: a #GstBaseAudioSink
 + * gst_audio_base_sink_get_discont_wait
 + * @sink: a #GstAudioBaseSink
   *
   * Get the current discont wait, in nanoseconds, used by @sink.
   *
   * Since: 0.10.36
   */
  GstClockTime
 -gst_base_audio_sink_get_discont_wait (GstBaseAudioSink * sink)
 +gst_audio_base_sink_get_discont_wait (GstAudioBaseSink * sink)
  {
    GstClockTime result;
  
 -  g_return_val_if_fail (GST_IS_BASE_AUDIO_SINK (sink), -1);
 +  g_return_val_if_fail (GST_IS_AUDIO_BASE_SINK (sink), -1);
  
    GST_OBJECT_LOCK (sink);
    result = sink->priv->discont_wait;
  }
  
  static void
 -gst_base_audio_sink_set_property (GObject * object, guint prop_id,
 +gst_audio_base_sink_set_property (GObject * object, guint prop_id,
      const GValue * value, GParamSpec * pspec)
  {
 -  GstBaseAudioSink *sink;
 +  GstAudioBaseSink *sink;
  
 -  sink = GST_BASE_AUDIO_SINK (object);
 +  sink = GST_AUDIO_BASE_SINK (object);
  
    switch (prop_id) {
      case PROP_BUFFER_TIME:
        sink->latency_time = g_value_get_int64 (value);
        break;
      case PROP_PROVIDE_CLOCK:
 -      gst_base_audio_sink_set_provide_clock (sink, g_value_get_boolean (value));
 +      gst_audio_base_sink_set_provide_clock (sink, g_value_get_boolean (value));
        break;
      case PROP_SLAVE_METHOD:
 -      gst_base_audio_sink_set_slave_method (sink, g_value_get_enum (value));
 +      gst_audio_base_sink_set_slave_method (sink, g_value_get_enum (value));
        break;
      case PROP_CAN_ACTIVATE_PULL:
        GST_BASE_SINK (sink)->can_activate_pull = g_value_get_boolean (value);
        break;
      case PROP_DRIFT_TOLERANCE:
 -      gst_base_audio_sink_set_drift_tolerance (sink, g_value_get_int64 (value));
 +      gst_audio_base_sink_set_drift_tolerance (sink, g_value_get_int64 (value));
        break;
      case PROP_ALIGNMENT_THRESHOLD:
 -      gst_base_audio_sink_set_alignment_threshold (sink,
 +      gst_audio_base_sink_set_alignment_threshold (sink,
            g_value_get_uint64 (value));
        break;
      case PROP_DISCONT_WAIT:
 -      gst_base_audio_sink_set_discont_wait (sink, g_value_get_uint64 (value));
 +      gst_audio_base_sink_set_discont_wait (sink, g_value_get_uint64 (value));
        break;
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  }
  
  static void
 -gst_base_audio_sink_get_property (GObject * object, guint prop_id,
 +gst_audio_base_sink_get_property (GObject * object, guint prop_id,
      GValue * value, GParamSpec * pspec)
  {
 -  GstBaseAudioSink *sink;
 +  GstAudioBaseSink *sink;
  
 -  sink = GST_BASE_AUDIO_SINK (object);
 +  sink = GST_AUDIO_BASE_SINK (object);
  
    switch (prop_id) {
      case PROP_BUFFER_TIME:
        g_value_set_int64 (value, sink->latency_time);
        break;
      case PROP_PROVIDE_CLOCK:
 -      g_value_set_boolean (value, gst_base_audio_sink_get_provide_clock (sink));
 +      g_value_set_boolean (value, gst_audio_base_sink_get_provide_clock (sink));
        break;
      case PROP_SLAVE_METHOD:
 -      g_value_set_enum (value, gst_base_audio_sink_get_slave_method (sink));
 +      g_value_set_enum (value, gst_audio_base_sink_get_slave_method (sink));
        break;
      case PROP_CAN_ACTIVATE_PULL:
        g_value_set_boolean (value, GST_BASE_SINK (sink)->can_activate_pull);
        break;
      case PROP_DRIFT_TOLERANCE:
 -      g_value_set_int64 (value, gst_base_audio_sink_get_drift_tolerance (sink));
 +      g_value_set_int64 (value, gst_audio_base_sink_get_drift_tolerance (sink));
        break;
      case PROP_ALIGNMENT_THRESHOLD:
        g_value_set_uint64 (value,
 -          gst_base_audio_sink_get_alignment_threshold (sink));
 +          gst_audio_base_sink_get_alignment_threshold (sink));
        break;
      case PROP_DISCONT_WAIT:
 -      g_value_set_uint64 (value, gst_base_audio_sink_get_discont_wait (sink));
 +      g_value_set_uint64 (value, gst_audio_base_sink_get_discont_wait (sink));
        break;
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  }
  
  static gboolean
 -gst_base_audio_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
 +gst_audio_base_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
  {
 -  GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (bsink);
 -  GstRingBufferSpec *spec;
 +  GstAudioBaseSink *sink = GST_AUDIO_BASE_SINK (bsink);
 +  GstAudioRingBufferSpec *spec;
    GstClockTime now;
    GstClockTime crate_num, crate_denom;
  
  
    GST_DEBUG_OBJECT (sink, "release old ringbuffer");
  
 -  /* get current time, updates the last_time */
 +  /* get current time, updates the last_time. When the subclass has a clock that
 +   * restarts from 0 when a new format is negotiated, it will call
 +   * gst_audio_clock_reset() which will use this last_time to create an offset
 +   * so that time from the clock keeps on increasing monotonically. */
    now = gst_clock_get_time (sink->provided_clock);
  
    GST_DEBUG_OBJECT (sink, "time was %" GST_TIME_FORMAT, GST_TIME_ARGS (now));
  
    /* release old ringbuffer */
 -  gst_ring_buffer_pause (sink->ringbuffer);
 -  gst_ring_buffer_activate (sink->ringbuffer, FALSE);
 -  gst_ring_buffer_release (sink->ringbuffer);
 +  gst_audio_ring_buffer_pause (sink->ringbuffer);
 +  gst_audio_ring_buffer_activate (sink->ringbuffer, FALSE);
 +  gst_audio_ring_buffer_release (sink->ringbuffer);
  
    GST_DEBUG_OBJECT (sink, "parse caps");
  
    spec->latency_time = sink->latency_time;
  
    /* parse new caps */
 -  if (!gst_ring_buffer_parse_caps (spec, caps))
 +  if (!gst_audio_ring_buffer_parse_caps (spec, caps))
      goto parse_error;
  
 -  gst_ring_buffer_debug_spec_buff (spec);
 +  gst_audio_ring_buffer_debug_spec_buff (spec);
  
    GST_DEBUG_OBJECT (sink, "acquire ringbuffer");
 -  if (!gst_ring_buffer_acquire (sink->ringbuffer, spec))
 +  if (!gst_audio_ring_buffer_acquire (sink->ringbuffer, spec))
      goto acquire_error;
  
 -  if (bsink->pad_mode == GST_ACTIVATE_PUSH) {
 +  if (bsink->pad_mode == GST_PAD_MODE_PUSH) {
      GST_DEBUG_OBJECT (sink, "activate ringbuffer");
 -    gst_ring_buffer_activate (sink->ringbuffer, TRUE);
 +    gst_audio_ring_buffer_activate (sink->ringbuffer, TRUE);
    }
  
    /* due to possible changes in the spec file we should recalibrate the clock */
    /* calculate actual latency and buffer times.
     * FIXME: In 0.11, store the latency_time internally in ns */
    spec->latency_time = gst_util_uint64_scale (spec->segsize,
 -      (GST_SECOND / GST_USECOND), spec->rate * spec->bytes_per_sample);
 +      (GST_SECOND / GST_USECOND), spec->info.rate * spec->info.bpf);
  
    spec->buffer_time = spec->segtotal * spec->latency_time;
  
 -  gst_ring_buffer_debug_spec_buff (spec);
 +  gst_audio_ring_buffer_debug_spec_buff (spec);
  
    return TRUE;
  
@@@ -941,7 -960,7 +944,7 @@@ acquire_error
  }
  
  static void
 -gst_base_audio_sink_fixate (GstBaseSink * bsink, GstCaps * caps)
 +gst_audio_base_sink_fixate (GstBaseSink * bsink, GstCaps * caps)
  {
    GstStructure *s;
    gint width, depth;
      gst_structure_fixate_field_boolean (s, "signed", TRUE);
    if (gst_structure_has_field (s, "endianness"))
      gst_structure_fixate_field_nearest_int (s, "endianness", G_BYTE_ORDER);
 +
 +  GST_BASE_SINK_CLASS (parent_class)->fixate (bsink, caps);
  }
  
  static void
 -gst_base_audio_sink_get_times (GstBaseSink * bsink, GstBuffer * buffer,
 +gst_audio_base_sink_get_times (GstBaseSink * bsink, GstBuffer * buffer,
      GstClockTime * start, GstClockTime * end)
  {
    /* our clock sync is a bit too much for the base class to handle so
  
  /* This waits for the drain to happen and can be canceled */
  static gboolean
 -gst_base_audio_sink_drain (GstBaseAudioSink * sink)
 +gst_audio_base_sink_drain (GstAudioBaseSink * sink)
  {
    if (!sink->ringbuffer)
      return TRUE;
 -  if (!sink->ringbuffer->spec.rate)
 +  if (!sink->ringbuffer->spec.info.rate)
      return TRUE;
  
    /* if PLAYING is interrupted,
     * arrange to have clock running when going to PLAYING again */
 -  g_atomic_int_set (&sink->abidata.ABI.eos_rendering, 1);
 +  g_atomic_int_set (&sink->eos_rendering, 1);
  
    /* need to start playback before we can drain, but only when
     * we have successfully negotiated a format and thus acquired the
     * ringbuffer. */
 -  if (gst_ring_buffer_is_acquired (sink->ringbuffer))
 -    gst_ring_buffer_start (sink->ringbuffer);
 +  if (gst_audio_ring_buffer_is_acquired (sink->ringbuffer))
 +    gst_audio_ring_buffer_start (sink->ringbuffer);
  
    if (sink->priv->eos_time != -1) {
      GST_DEBUG_OBJECT (sink,
  
      GST_DEBUG_OBJECT (sink, "drained audio");
    }
 -  g_atomic_int_set (&sink->abidata.ABI.eos_rendering, 0);
 +  g_atomic_int_set (&sink->eos_rendering, 0);
    return TRUE;
  }
  
 +static GstFlowReturn
 +gst_audio_base_sink_wait_eos (GstBaseSink * bsink, GstEvent * event)
 +{
 +  GstAudioBaseSink *sink = GST_AUDIO_BASE_SINK (bsink);
 +  GstFlowReturn ret;
 +
 +  ret = GST_BASE_SINK_CLASS (parent_class)->event (bsink, event);
 +  if (ret != GST_FLOW_OK)
 +    return ret;
 +
 +  /* now wait till we played everything */
 +  gst_audio_base_sink_drain (sink);
 +
 +  return ret;
 +}
 +
  static gboolean
 -gst_base_audio_sink_event (GstBaseSink * bsink, GstEvent * event)
 +gst_audio_base_sink_event (GstBaseSink * bsink, GstEvent * event)
  {
 -  GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (bsink);
 +  GstAudioBaseSink *sink = GST_AUDIO_BASE_SINK (bsink);
  
    switch (GST_EVENT_TYPE (event)) {
      case GST_EVENT_FLUSH_START:
        if (sink->ringbuffer)
 -        gst_ring_buffer_set_flushing (sink->ringbuffer, TRUE);
 +        gst_audio_ring_buffer_set_flushing (sink->ringbuffer, TRUE);
        break;
      case GST_EVENT_FLUSH_STOP:
        /* always resync on sample after a flush */
        sink->priv->eos_time = -1;
        sink->priv->discont_time = -1;
        if (sink->ringbuffer)
 -        gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE);
 +        gst_audio_ring_buffer_set_flushing (sink->ringbuffer, FALSE);
        break;
 -    case GST_EVENT_EOS:
 -      /* now wait till we played everything */
 -      gst_base_audio_sink_drain (sink);
 -      break;
 -    case GST_EVENT_NEWSEGMENT:
 -    {
 -      gdouble rate;
 -
 -      /* we only need the rate */
 -      gst_event_parse_new_segment_full (event, NULL, &rate, NULL, NULL,
 -          NULL, NULL, NULL);
 -
 -      GST_DEBUG_OBJECT (sink, "new segment rate of %f", rate);
 -      break;
 -    }
      default:
        break;
    }
 -  return TRUE;
 +  return GST_BASE_SINK_CLASS (parent_class)->event (bsink, event);
  }
  
  static GstFlowReturn
 -gst_base_audio_sink_preroll (GstBaseSink * bsink, GstBuffer * buffer)
 +gst_audio_base_sink_preroll (GstBaseSink * bsink, GstBuffer * buffer)
  {
 -  GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (bsink);
 +  GstAudioBaseSink *sink = GST_AUDIO_BASE_SINK (bsink);
  
 -  if (!gst_ring_buffer_is_acquired (sink->ringbuffer))
 +  if (!gst_audio_ring_buffer_is_acquired (sink->ringbuffer))
      goto wrong_state;
  
    /* we don't really do anything when prerolling. We could make a
@@@ -1075,7 -1091,7 +1078,7 @@@ wrong_state
  }
  
  static guint64
 -gst_base_audio_sink_get_offset (GstBaseAudioSink * sink)
 +gst_audio_base_sink_get_offset (GstAudioBaseSink * sink)
  {
    guint64 sample;
    gint writeseg, segdone, sps;
@@@ -1130,7 -1146,7 +1133,7 @@@ clock_convert_external (GstClockTime ex
  /* algorithm to calculate sample positions that will result in resampling to
   * match the clock rate of the master */
  static void
 -gst_base_audio_sink_resample_slaving (GstBaseAudioSink * sink,
 +gst_audio_base_sink_resample_slaving (GstAudioBaseSink * sink,
      GstClockTime render_start, GstClockTime render_stop,
      GstClockTime * srender_start, GstClockTime * srender_stop)
  {
  /* algorithm to calculate sample positions that will result in changing the
   * playout pointer to match the clock rate of the master */
  static void
 -gst_base_audio_sink_skew_slaving (GstBaseAudioSink * sink,
 +gst_audio_base_sink_skew_slaving (GstAudioBaseSink * sink,
      GstClockTime render_start, GstClockTime render_stop,
      GstClockTime * srender_start, GstClockTime * srender_stop)
  {
      cexternal = cexternal > mdrift ? cexternal - mdrift : 0;
      sink->priv->avg_skew -= mdrift;
  
 -    driftsamples = (sink->ringbuffer->spec.rate * mdrift) / GST_SECOND;
 +    driftsamples = (sink->ringbuffer->spec.info.rate * mdrift) / GST_SECOND;
      last_align = sink->priv->last_align;
  
      /* if we were aligning in the wrong direction or we aligned more than what we
      cexternal += mdrift;
      sink->priv->avg_skew += mdrift;
  
 -    driftsamples = (sink->ringbuffer->spec.rate * mdrift) / GST_SECOND;
 +    driftsamples = (sink->ringbuffer->spec.info.rate * mdrift) / GST_SECOND;
      last_align = sink->priv->last_align;
  
      /* if we were aligning in the wrong direction or we aligned more than what we
  
  /* apply the clock offset but do no slaving otherwise */
  static void
 -gst_base_audio_sink_none_slaving (GstBaseAudioSink * sink,
 +gst_audio_base_sink_none_slaving (GstAudioBaseSink * sink,
      GstClockTime render_start, GstClockTime render_stop,
      GstClockTime * srender_start, GstClockTime * srender_stop)
  {
  
  /* converts render_start and render_stop to their slaved values */
  static void
 -gst_base_audio_sink_handle_slaving (GstBaseAudioSink * sink,
 +gst_audio_base_sink_handle_slaving (GstAudioBaseSink * sink,
      GstClockTime render_start, GstClockTime render_stop,
      GstClockTime * srender_start, GstClockTime * srender_stop)
  {
    switch (sink->priv->slave_method) {
 -    case GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE:
 -      gst_base_audio_sink_resample_slaving (sink, render_start, render_stop,
 +    case GST_AUDIO_BASE_SINK_SLAVE_RESAMPLE:
 +      gst_audio_base_sink_resample_slaving (sink, render_start, render_stop,
            srender_start, srender_stop);
        break;
 -    case GST_BASE_AUDIO_SINK_SLAVE_SKEW:
 -      gst_base_audio_sink_skew_slaving (sink, render_start, render_stop,
 +    case GST_AUDIO_BASE_SINK_SLAVE_SKEW:
 +      gst_audio_base_sink_skew_slaving (sink, render_start, render_stop,
            srender_start, srender_stop);
        break;
 -    case GST_BASE_AUDIO_SINK_SLAVE_NONE:
 -      gst_base_audio_sink_none_slaving (sink, render_start, render_stop,
 +    case GST_AUDIO_BASE_SINK_SLAVE_NONE:
 +      gst_audio_base_sink_none_slaving (sink, render_start, render_stop,
            srender_start, srender_stop);
        break;
      default:
  
  /* must be called with LOCK */
  static GstFlowReturn
 -gst_base_audio_sink_sync_latency (GstBaseSink * bsink, GstMiniObject * obj)
 +gst_audio_base_sink_sync_latency (GstBaseSink * bsink, GstMiniObject * obj)
  {
    GstClock *clock;
    GstClockReturn status;
    GstClockTime time, render_delay;
    GstFlowReturn ret;
 -  GstBaseAudioSink *sink;
 +  GstAudioBaseSink *sink;
    GstClockTime itime, etime;
    GstClockTime rate_num, rate_denom;
    GstClockTimeDiff jitter;
  
 -  sink = GST_BASE_AUDIO_SINK (bsink);
 +  sink = GST_AUDIO_BASE_SINK (bsink);
  
    clock = GST_ELEMENT_CLOCK (sink);
    if (G_UNLIKELY (clock == NULL))
    }
  
    /* start ringbuffer so we can start slaving right away when we need to */
 -  gst_ring_buffer_start (sink->ringbuffer);
 +  gst_audio_ring_buffer_start (sink->ringbuffer);
  
    GST_DEBUG_OBJECT (sink,
        "internal time: %" GST_TIME_FORMAT " external time: %" GST_TIME_FORMAT,
        rate_num, rate_denom);
  
    switch (sink->priv->slave_method) {
 -    case GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE:
 +    case GST_AUDIO_BASE_SINK_SLAVE_RESAMPLE:
        /* only set as master when we are resampling */
        GST_DEBUG_OBJECT (sink, "Setting clock as master");
        gst_clock_set_master (sink->provided_clock, clock);
        break;
 -    case GST_BASE_AUDIO_SINK_SLAVE_SKEW:
 -    case GST_BASE_AUDIO_SINK_SLAVE_NONE:
 +    case GST_AUDIO_BASE_SINK_SLAVE_SKEW:
 +    case GST_AUDIO_BASE_SINK_SLAVE_NONE:
      default:
        break;
    }
@@@ -1474,10 -1490,10 +1477,10 @@@ flushing
  }
  
  static gint64
 -gst_base_audio_sink_get_alignment (GstBaseAudioSink * sink,
 +gst_audio_base_sink_get_alignment (GstAudioBaseSink * sink,
      GstClockTime sample_offset)
  {
 -  GstRingBuffer *ringbuf = sink->ringbuffer;
 +  GstAudioRingBuffer *ringbuf = sink->ringbuffer;
    gint64 align;
    gint64 sample_diff;
    gint64 max_sample_diff;
    gint64 headroom = sample_offset - samples_done;
    gboolean allow_align = TRUE;
    gboolean discont = FALSE;
 +  gint rate;
  
    /* now try to align the sample to the previous one, first see how big the
     * difference is. */
    else
      sample_diff = sink->next_sample - sample_offset;
  
 +  rate = GST_AUDIO_INFO_RATE (&ringbuf->spec.info);
 +
    /* calculate the max allowed drift in units of samples. */
    max_sample_diff = gst_util_uint64_scale_int (sink->priv->alignment_threshold,
 -      ringbuf->spec.rate, GST_SECOND);
 +      rate, GST_SECOND);
  
    /* calc align with previous sample */
    align = sink->next_sample - sample_offset;
      /* wait before deciding to make a discontinuity */
      if (sink->priv->discont_wait > 0) {
        GstClockTime time = gst_util_uint64_scale_int (sample_offset,
 -          GST_SECOND, ringbuf->spec.rate);
 +          GST_SECOND, rate);
        if (sink->priv->discont_time == -1) {
          /* discont candidate */
          sink->priv->discont_time = time;
      gint64 diff_s G_GNUC_UNUSED;
  
      /* calculate sample diff in seconds for error message */
 -    diff_s =
 -        gst_util_uint64_scale_int (sample_diff, GST_SECOND, ringbuf->spec.rate);
 +    diff_s = gst_util_uint64_scale_int (sample_diff, GST_SECOND, rate);
  
      /* timestamps drifted apart from previous samples too much, we need to
       * resync. We log this as an element warning. */
  }
  
  static GstFlowReturn
 -gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
 +gst_audio_base_sink_render (GstBaseSink * bsink, GstBuffer * buf)
  {
    guint64 in_offset;
    GstClockTime time, stop, render_start, render_stop, sample_offset;
    GstClockTimeDiff sync_offset, ts_offset;
 -  GstBaseAudioSinkClass *bclass;
 -  GstBaseAudioSink *sink;
 -  GstRingBuffer *ringbuf;
 -  gint64 diff, align, ctime, cstop;
 +  GstAudioBaseSinkClass *bclass;
 +  GstAudioBaseSink *sink;
 +  GstAudioRingBuffer *ringbuf;
 +  gint64 diff, align;
 +  guint64 ctime, cstop;
 +  gsize offset;
    guint8 *data;
 -  guint size;
 +  gsize size;
    guint samples, written;
 -  gint bps;
 +  gint bpf, rate;
    gint accum;
    gint out_samples;
    GstClockTime base_time, render_delay, latency;
    gint64 time_offset;
    GstBuffer *out = NULL;
  
 -  sink = GST_BASE_AUDIO_SINK (bsink);
 -  bclass = GST_BASE_AUDIO_SINK_GET_CLASS (sink);
 +  sink = GST_AUDIO_BASE_SINK (bsink);
 +  bclass = GST_AUDIO_BASE_SINK_GET_CLASS (sink);
  
    ringbuf = sink->ringbuffer;
  
    /* can't do anything when we don't have the device */
 -  if (G_UNLIKELY (!gst_ring_buffer_is_acquired (ringbuf)))
 +  if (G_UNLIKELY (!gst_audio_ring_buffer_is_acquired (ringbuf)))
      goto wrong_state;
  
    /* Wait for upstream latency before starting the ringbuffer, we do this so
    GST_OBJECT_LOCK (sink);
    base_time = GST_ELEMENT_CAST (sink)->base_time;
    if (G_UNLIKELY (sink->priv->sync_latency)) {
 -    ret = gst_base_audio_sink_sync_latency (bsink, GST_MINI_OBJECT_CAST (buf));
 +    ret = gst_audio_base_sink_sync_latency (bsink, GST_MINI_OBJECT_CAST (buf));
      GST_OBJECT_UNLOCK (sink);
      if (G_UNLIKELY (ret != GST_FLOW_OK))
        goto sync_latency_failed;
      buf = out;
    }
  
 -  bps = ringbuf->spec.bytes_per_sample;
 +  bpf = GST_AUDIO_INFO_BPF (&ringbuf->spec.info);
 +  rate = GST_AUDIO_INFO_RATE (&ringbuf->spec.info);
  
 -  size = GST_BUFFER_SIZE (buf);
 -  if (G_UNLIKELY (size % bps) != 0)
 +  size = gst_buffer_get_size (buf);
 +  if (G_UNLIKELY (size % bpf) != 0)
      goto wrong_size;
  
 -  samples = size / bps;
 +  samples = size / bpf;
    out_samples = samples;
  
    in_offset = GST_BUFFER_OFFSET (buf);
        GST_TIME_FORMAT ", samples %u", GST_TIME_ARGS (time), in_offset,
        GST_TIME_ARGS (bsink->segment.start), samples);
  
 -  data = GST_BUFFER_DATA (buf);
 +  offset = 0;
  
    /* if not valid timestamp or we can't clip or sync, try to play
     * sample ASAP */
    if (!GST_CLOCK_TIME_IS_VALID (time)) {
 -    render_start = gst_base_audio_sink_get_offset (sink);
 +    render_start = gst_audio_base_sink_get_offset (sink);
      render_stop = render_start + samples;
 -    GST_DEBUG_OBJECT (sink,
 -        "Buffer of size %u has no time. Using render_start=%" G_GUINT64_FORMAT,
 -        GST_BUFFER_SIZE (buf), render_start);
 +    GST_DEBUG_OBJECT (sink, "Buffer of size %" G_GSIZE_FORMAT " has no time."
 +        " Using render_start=%" G_GUINT64_FORMAT, size, render_start);
      /* we don't have a start so we don't know stop either */
      stop = -1;
      goto no_sync;
  
    /* let's calc stop based on the number of samples in the buffer instead
     * of trusting the DURATION */
 -  stop = time + gst_util_uint64_scale_int (samples, GST_SECOND,
 -      ringbuf->spec.rate);
 +  stop = time + gst_util_uint64_scale_int (samples, GST_SECOND, rate);
  
    /* prepare the clipping segment. Since we will be subtracting ts-offset and
     * device-delay later we scale the start and stop with those values so that we
    diff = ctime - time;
    if (diff > 0) {
      /* bring clipped time to samples */
 -    diff = gst_util_uint64_scale_int (diff, ringbuf->spec.rate, GST_SECOND);
 +    diff = gst_util_uint64_scale_int (diff, rate, GST_SECOND);
      GST_DEBUG_OBJECT (sink, "clipping start to %" GST_TIME_FORMAT " %"
          G_GUINT64_FORMAT " samples", GST_TIME_ARGS (ctime), diff);
      samples -= diff;
 -    data += diff * bps;
 +    offset += diff * bpf;
      time = ctime;
    }
    diff = stop - cstop;
    if (diff > 0) {
      /* bring clipped time to samples */
 -    diff = gst_util_uint64_scale_int (diff, ringbuf->spec.rate, GST_SECOND);
 +    diff = gst_util_uint64_scale_int (diff, rate, GST_SECOND);
      GST_DEBUG_OBJECT (sink, "clipping stop to %" GST_TIME_FORMAT " %"
          G_GUINT64_FORMAT " samples", GST_TIME_ARGS (cstop), diff);
      samples -= diff;
  
    if (!sync) {
      /* no sync needed, play sample ASAP */
 -    render_start = gst_base_audio_sink_get_offset (sink);
 +    render_start = gst_audio_base_sink_get_offset (sink);
      render_stop = render_start + samples;
      GST_DEBUG_OBJECT (sink,
          "no sync needed. Using render_start=%" G_GUINT64_FORMAT, render_start);
  
    if ((slaved = clock != sink->provided_clock)) {
      /* handle clock slaving */
 -    gst_base_audio_sink_handle_slaving (sink, render_start, render_stop,
 +    gst_audio_base_sink_handle_slaving (sink, render_start, render_stop,
          &render_start, &render_stop);
    } else {
      /* no slaving needed but we need to adapt to the clock calibration
       * parameters */
 -    gst_base_audio_sink_none_slaving (sink, render_start, render_stop,
 +    gst_audio_base_sink_none_slaving (sink, render_start, render_stop,
          &render_start, &render_stop);
    }
  
        GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop));
  
    /* bring to position in the ringbuffer */
 -  if (sink->priv->do_time_offset) {
 -    time_offset =
 -        GST_AUDIO_CLOCK_CAST (sink->provided_clock)->abidata.ABI.time_offset;
 -    GST_DEBUG_OBJECT (sink,
 -        "time offset %" GST_TIME_FORMAT, GST_TIME_ARGS (time_offset));
 -    if (render_start > time_offset)
 -      render_start -= time_offset;
 -    else
 -      render_start = 0;
 -    if (render_stop > time_offset)
 -      render_stop -= time_offset;
 -    else
 -      render_stop = 0;
 -  }
 +  time_offset = GST_AUDIO_CLOCK_CAST (sink->provided_clock)->time_offset;
 +  GST_DEBUG_OBJECT (sink,
 +      "time offset %" GST_TIME_FORMAT, GST_TIME_ARGS (time_offset));
 +  if (render_start > time_offset)
 +    render_start -= time_offset;
 +  else
 +    render_start = 0;
 +  if (render_stop > time_offset)
 +    render_stop -= time_offset;
 +  else
 +    render_stop = 0;
  
    /* in some clock slaving cases, all late samples end up at 0 first,
     * and subsequent ones align with that until threshold exceeded,
      goto too_late;
  
    /* and bring the time to the rate corrected offset in the buffer */
 -  render_start = gst_util_uint64_scale_int (render_start,
 -      ringbuf->spec.rate, GST_SECOND);
 -  render_stop = gst_util_uint64_scale_int (render_stop,
 -      ringbuf->spec.rate, GST_SECOND);
 +  render_start = gst_util_uint64_scale_int (render_start, rate, GST_SECOND);
 +  render_stop = gst_util_uint64_scale_int (render_stop, rate, GST_SECOND);
  
    /* positive playback rate, first sample is render_start, negative rate, first
     * sample is render_stop. When no rate conversion is active, render exactly
      goto no_align;
    }
  
 -  align = gst_base_audio_sink_get_alignment (sink, sample_offset);
 +  align = gst_audio_base_sink_get_alignment (sink, sample_offset);
    sink->priv->last_align = align;
  
    /* apply alignment */
    render_start += align;
  
    /* only align stop if we are not slaved to resample */
 -  if (slaved && sink->priv->slave_method == GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE) {
 +  if (slaved && sink->priv->slave_method == GST_AUDIO_BASE_SINK_SLAVE_RESAMPLE) {
      GST_DEBUG_OBJECT (sink, "no stop time align needed: we are slaved");
      goto no_align;
    }
@@@ -1851,11 -1869,10 +1854,11 @@@ no_sync
    /* we need to accumulate over different runs for when we get interrupted */
    accum = 0;
    align_next = TRUE;
 +  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
    do {
      written =
 -        gst_ring_buffer_commit_full (ringbuf, &sample_offset, data, samples,
 -        out_samples, &accum);
 +        gst_audio_ring_buffer_commit (ringbuf, &sample_offset,
 +        data + offset, samples, out_samples, &accum);
  
      GST_DEBUG_OBJECT (sink, "wrote %u of %u", written, samples);
      /* if we wrote all, we're done */
        break;
  
      samples -= written;
 -    data += written * bps;
 +    offset += written * bpf;
    } while (TRUE);
 +  gst_buffer_unmap (buf, data, size);
  
    if (align_next)
      sink->next_sample = sample_offset;
    if (GST_CLOCK_TIME_IS_VALID (stop) && stop >= bsink->segment.stop) {
      GST_DEBUG_OBJECT (sink,
          "start playback because we are at the end of segment");
 -    gst_ring_buffer_start (ringbuf);
 +    gst_audio_ring_buffer_start (ringbuf);
    }
  
    ret = GST_FLOW_OK;
@@@ -1946,7 -1962,6 +1949,7 @@@ stopping
    {
      GST_DEBUG_OBJECT (sink, "preroll got interrupted: %d (%s)", ret,
          gst_flow_get_name (ret));
 +    gst_buffer_unmap (buf, data, size);
      goto done;
    }
  sync_latency_failed:
  }
  
  /**
 - * gst_base_audio_sink_create_ringbuffer:
 - * @sink: a #GstBaseAudioSink.
 + * gst_audio_base_sink_create_ringbuffer:
 + * @sink: a #GstAudioBaseSink.
   *
 - * Create and return the #GstRingBuffer for @sink. This function will call the
 + * Create and return the #GstAudioRingBuffer for @sink. This function will call the
   * ::create_ringbuffer vmethod and will set @sink as the parent of the returned
   * buffer (see gst_object_set_parent()).
   *
   * Returns: The new ringbuffer of @sink.
   */
 -GstRingBuffer *
 -gst_base_audio_sink_create_ringbuffer (GstBaseAudioSink * sink)
 +GstAudioRingBuffer *
 +gst_audio_base_sink_create_ringbuffer (GstAudioBaseSink * sink)
  {
 -  GstBaseAudioSinkClass *bclass;
 -  GstRingBuffer *buffer = NULL;
 +  GstAudioBaseSinkClass *bclass;
 +  GstAudioRingBuffer *buffer = NULL;
  
 -  bclass = GST_BASE_AUDIO_SINK_GET_CLASS (sink);
 +  bclass = GST_AUDIO_BASE_SINK_GET_CLASS (sink);
    if (bclass->create_ringbuffer)
      buffer = bclass->create_ringbuffer (sink);
  
  }
  
  static void
 -gst_base_audio_sink_callback (GstRingBuffer * rbuf, guint8 * data, guint len,
 -    gpointer user_data)
 +gst_audio_base_sink_callback (GstAudioRingBuffer * rbuf, guint8 * data,
 +    guint len, gpointer user_data)
  {
    GstBaseSink *basesink;
 -  GstBaseAudioSink *sink;
 +  GstAudioBaseSink *sink;
    GstBuffer *buf;
    GstFlowReturn ret;
 +  gsize size;
  
    basesink = GST_BASE_SINK (user_data);
 -  sink = GST_BASE_AUDIO_SINK (user_data);
 +  sink = GST_AUDIO_BASE_SINK (user_data);
  
    GST_PAD_STREAM_LOCK (basesink->sinkpad);
  
    /* would be nice to arrange for pad_alloc_buffer to return data -- as it is we
       will copy twice, once into data, once into DMA */
 -  GST_LOG_OBJECT (basesink, "pulling %d bytes offset %" G_GUINT64_FORMAT
 +  GST_LOG_OBJECT (basesink, "pulling %u bytes offset %" G_GUINT64_FORMAT
        " to fill audio buffer", len, basesink->offset);
    ret =
 -      gst_pad_pull_range (basesink->sinkpad, basesink->segment.last_stop, len,
 +      gst_pad_pull_range (basesink->sinkpad, basesink->segment.position, len,
        &buf);
  
    if (ret != GST_FLOW_OK) {
 -    if (ret == GST_FLOW_UNEXPECTED)
 +    if (ret == GST_FLOW_EOS)
        goto eos;
      else
        goto error;
    }
  
 -  GST_PAD_PREROLL_LOCK (basesink->sinkpad);
 +  GST_BASE_SINK_PREROLL_LOCK (basesink);
    if (basesink->flushing)
      goto flushing;
  
    if (ret != GST_FLOW_OK)
      goto preroll_error;
  
 -  if (len != GST_BUFFER_SIZE (buf)) {
 +  size = gst_buffer_get_size (buf);
 +
 +  if (len != size) {
      GST_INFO_OBJECT (basesink,
 -        "got different size than requested from sink pad: %u != %u", len,
 -        GST_BUFFER_SIZE (buf));
 -    len = MIN (GST_BUFFER_SIZE (buf), len);
 +        "got different size than requested from sink pad: %u"
 +        " != %" G_GSIZE_FORMAT, len, size);
 +    len = MIN (size, len);
    }
  
 -  basesink->segment.last_stop += len;
 +  basesink->segment.position += len;
  
 -  memcpy (data, GST_BUFFER_DATA (buf), len);
 -  GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
 +  gst_buffer_extract (buf, 0, data, len);
 +  GST_BASE_SINK_PREROLL_UNLOCK (basesink);
  
    GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
  
@@@ -2043,7 -2055,7 +2046,7 @@@ error
    {
      GST_WARNING_OBJECT (basesink, "Got flow '%s' but can't return it: %d",
          gst_flow_get_name (ret), ret);
 -    gst_ring_buffer_pause (rbuf);
 +    gst_audio_ring_buffer_pause (rbuf);
      GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
      return;
    }
@@@ -2053,8 -2065,8 +2056,8 @@@ eos
       * the sink gets shut down; maybe we should set a flag somewhere, or
       * set segment.stop and segment.duration to the last sample or so */
      GST_DEBUG_OBJECT (sink, "EOS");
 -    gst_base_audio_sink_drain (sink);
 -    gst_ring_buffer_pause (rbuf);
 +    gst_audio_base_sink_drain (sink);
 +    gst_audio_ring_buffer_pause (rbuf);
      gst_element_post_message (GST_ELEMENT_CAST (sink),
          gst_message_new_eos (GST_OBJECT_CAST (sink)));
      GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
  flushing:
    {
      GST_DEBUG_OBJECT (sink, "we are flushing");
 -    gst_ring_buffer_pause (rbuf);
 -    GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
 +    gst_audio_ring_buffer_pause (rbuf);
 +    GST_BASE_SINK_PREROLL_UNLOCK (basesink);
      GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
      return;
    }
  preroll_error:
    {
      GST_DEBUG_OBJECT (sink, "error %s", gst_flow_get_name (ret));
 -    gst_ring_buffer_pause (rbuf);
 -    GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
 +    gst_audio_ring_buffer_pause (rbuf);
 +    GST_BASE_SINK_PREROLL_UNLOCK (basesink);
      GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
      return;
    }
  }
  
  static gboolean
 -gst_base_audio_sink_activate_pull (GstBaseSink * basesink, gboolean active)
 +gst_audio_base_sink_activate_pull (GstBaseSink * basesink, gboolean active)
  {
    gboolean ret;
 -  GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (basesink);
 +  GstAudioBaseSink *sink = GST_AUDIO_BASE_SINK (basesink);
  
    if (active) {
      GST_DEBUG_OBJECT (basesink, "activating pull");
  
 -    gst_ring_buffer_set_callback (sink->ringbuffer,
 -        gst_base_audio_sink_callback, sink);
 +    gst_audio_ring_buffer_set_callback (sink->ringbuffer,
 +        gst_audio_base_sink_callback, sink);
  
 -    ret = gst_ring_buffer_activate (sink->ringbuffer, TRUE);
 +    ret = gst_audio_ring_buffer_activate (sink->ringbuffer, TRUE);
    } else {
      GST_DEBUG_OBJECT (basesink, "deactivating pull");
 -    gst_ring_buffer_set_callback (sink->ringbuffer, NULL, NULL);
 -    ret = gst_ring_buffer_activate (sink->ringbuffer, FALSE);
 +    gst_audio_ring_buffer_set_callback (sink->ringbuffer, NULL, NULL);
 +    ret = gst_audio_ring_buffer_activate (sink->ringbuffer, FALSE);
    }
  
    return ret;
  }
  
 +#if 0
  /* should be called with the LOCK */
  static GstStateChangeReturn
 -gst_base_audio_sink_async_play (GstBaseSink * basesink)
 +gst_audio_base_sink_async_play (GstBaseSink * basesink)
  {
 -  GstBaseAudioSink *sink;
 +  GstAudioBaseSink *sink;
  
 -  sink = GST_BASE_AUDIO_SINK (basesink);
 +  sink = GST_AUDIO_BASE_SINK (basesink);
  
    GST_DEBUG_OBJECT (sink, "ringbuffer may start now");
    sink->priv->sync_latency = TRUE;
 -  gst_ring_buffer_may_start (sink->ringbuffer, TRUE);
 -  if (basesink->pad_mode == GST_ACTIVATE_PULL) {
 -    /* we always start the ringbuffer in pull mode immediately */
 -    gst_ring_buffer_start (sink->ringbuffer);
 +  gst_audio_ring_buffer_may_start (sink->ringbuffer, TRUE);
 +  if (basesink->pad_mode == GST_PAD_MODE_PULL) {
 +    /* we always start the ringbuffer in pull mode immediatly */
 +    gst_audio_ring_buffer_start (sink->ringbuffer);
    }
  
    return GST_STATE_CHANGE_SUCCESS;
  }
 +#endif
  
  static GstStateChangeReturn
 -gst_base_audio_sink_change_state (GstElement * element,
 +gst_audio_base_sink_change_state (GstElement * element,
      GstStateChange transition)
  {
    GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
 -  GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (element);
 +  GstAudioBaseSink *sink = GST_AUDIO_BASE_SINK (element);
  
    switch (transition) {
      case GST_STATE_CHANGE_NULL_TO_READY:
        if (sink->ringbuffer == NULL) {
          gst_audio_clock_reset (GST_AUDIO_CLOCK (sink->provided_clock), 0);
 -        sink->ringbuffer = gst_base_audio_sink_create_ringbuffer (sink);
 +        sink->ringbuffer = gst_audio_base_sink_create_ringbuffer (sink);
        }
 -      if (!gst_ring_buffer_open_device (sink->ringbuffer))
 +      if (!gst_audio_ring_buffer_open_device (sink->ringbuffer))
          goto open_failed;
        break;
      case GST_STATE_CHANGE_READY_TO_PAUSED:
        sink->priv->last_align = -1;
        sink->priv->eos_time = -1;
        sink->priv->discont_time = -1;
 -      gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE);
 -      gst_ring_buffer_may_start (sink->ringbuffer, FALSE);
 +      gst_audio_ring_buffer_set_flushing (sink->ringbuffer, FALSE);
 +      gst_audio_ring_buffer_may_start (sink->ringbuffer, FALSE);
  
        /* Only post clock-provide messages if this is the clock that
         * we've created. If the subclass has overriden it the subclass
         * should post this messages whenever necessary */
        if (sink->provided_clock && GST_IS_AUDIO_CLOCK (sink->provided_clock) &&
            GST_AUDIO_CLOCK_CAST (sink->provided_clock)->func ==
 -          (GstAudioClockGetTimeFunc) gst_base_audio_sink_get_time)
 +          (GstAudioClockGetTimeFunc) gst_audio_base_sink_get_time)
          gst_element_post_message (element,
              gst_message_new_clock_provide (GST_OBJECT_CAST (element),
                  sink->provided_clock, TRUE));
        eos = GST_BASE_SINK (sink)->eos;
        GST_OBJECT_UNLOCK (sink);
  
 -      gst_ring_buffer_may_start (sink->ringbuffer, TRUE);
 -      if (GST_BASE_SINK_CAST (sink)->pad_mode == GST_ACTIVATE_PULL ||
 -          g_atomic_int_get (&sink->abidata.ABI.eos_rendering) || eos) {
 -        /* we always start the ringbuffer in pull mode immediately */
 +      gst_audio_ring_buffer_may_start (sink->ringbuffer, TRUE);
 +      if (GST_BASE_SINK_CAST (sink)->pad_mode == GST_PAD_MODE_PULL ||
 +          g_atomic_int_get (&sink->eos_rendering) || eos) {
 +        /* we always start the ringbuffer in pull mode immediatly */
          /* sync rendering on eos needs running clock,
           * and others need running clock when finished rendering eos */
 -        gst_ring_buffer_start (sink->ringbuffer);
 +        gst_audio_ring_buffer_start (sink->ringbuffer);
        }
        break;
      }
      case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
        /* ringbuffer cannot start anymore */
 -      gst_ring_buffer_may_start (sink->ringbuffer, FALSE);
 -      gst_ring_buffer_pause (sink->ringbuffer);
 +      gst_audio_ring_buffer_may_start (sink->ringbuffer, FALSE);
 +      gst_audio_ring_buffer_pause (sink->ringbuffer);
  
        GST_OBJECT_LOCK (sink);
        sink->priv->sync_latency = FALSE;
         * should post this messages whenever necessary */
        if (sink->provided_clock && GST_IS_AUDIO_CLOCK (sink->provided_clock) &&
            GST_AUDIO_CLOCK_CAST (sink->provided_clock)->func ==
 -          (GstAudioClockGetTimeFunc) gst_base_audio_sink_get_time)
 +          (GstAudioClockGetTimeFunc) gst_audio_base_sink_get_time)
          gst_element_post_message (element,
              gst_message_new_clock_lost (GST_OBJECT_CAST (element),
                  sink->provided_clock));
  
        /* make sure we unblock before calling the parent state change
         * so it can grab the STREAM_LOCK */
 -      gst_ring_buffer_set_flushing (sink->ringbuffer, TRUE);
 +      gst_audio_ring_buffer_set_flushing (sink->ringbuffer, TRUE);
        break;
      default:
        break;
        gst_clock_set_master (sink->provided_clock, NULL);
        break;
      case GST_STATE_CHANGE_PAUSED_TO_READY:
 -      gst_ring_buffer_activate (sink->ringbuffer, FALSE);
 -      gst_ring_buffer_release (sink->ringbuffer);
 +      gst_audio_ring_buffer_activate (sink->ringbuffer, FALSE);
 +      gst_audio_ring_buffer_release (sink->ringbuffer);
        break;
      case GST_STATE_CHANGE_READY_TO_NULL:
        /* we release again here because the aqcuire happens when setting the
         * caps, which happens before we commit the state to PAUSED and thus the
         * PAUSED->READY state change (see above, where we release the ringbuffer)
         * might not be called when we get here. */
 -      gst_ring_buffer_activate (sink->ringbuffer, FALSE);
 -      gst_ring_buffer_release (sink->ringbuffer);
 -      gst_ring_buffer_close_device (sink->ringbuffer);
 +      gst_audio_ring_buffer_activate (sink->ringbuffer, FALSE);
 +      gst_audio_ring_buffer_release (sink->ringbuffer);
 +      gst_audio_ring_buffer_close_device (sink->ringbuffer);
        GST_OBJECT_LOCK (sink);
        gst_object_unparent (GST_OBJECT_CAST (sink->ringbuffer));
        sink->ringbuffer = NULL;
  #include "config.h"
  #endif
  
+ /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+  * with newer GLib versions (>= 2.31.0) */
+ #define GLIB_DISABLE_DEPRECATION_WARNINGS
  #include "gstaudiodecoder.h"
  #include <gst/pbutils/descriptions.h>
  
@@@ -276,54 -280,25 +280,54 @@@ static GstFlowReturn gst_audio_decoder_
  
  static GstStateChangeReturn gst_audio_decoder_change_state (GstElement *
      element, GstStateChange transition);
 -static gboolean gst_audio_decoder_sink_event (GstPad * pad, GstEvent * event);
 -static gboolean gst_audio_decoder_src_event (GstPad * pad, GstEvent * event);
 -static gboolean gst_audio_decoder_sink_setcaps (GstPad * pad, GstCaps * caps);
 -static gboolean gst_audio_decoder_src_setcaps (GstPad * pad, GstCaps * caps);
 -static GstFlowReturn gst_audio_decoder_chain (GstPad * pad, GstBuffer * buf);
 -static gboolean gst_audio_decoder_src_query (GstPad * pad, GstQuery * query);
 -static gboolean gst_audio_decoder_sink_query (GstPad * pad, GstQuery * query);
 -static const GstQueryType *gst_audio_decoder_get_query_types (GstPad * pad);
 +static gboolean gst_audio_decoder_sink_event (GstPad * pad, GstObject * parent,
 +    GstEvent * event);
 +static gboolean gst_audio_decoder_src_event (GstPad * pad, GstObject * parent,
 +    GstEvent * event);
 +static gboolean gst_audio_decoder_sink_setcaps (GstAudioDecoder * dec,
 +    GstCaps * caps);
 +gboolean gst_audio_decoder_src_setcaps (GstAudioDecoder * dec, GstCaps * caps);
 +static GstFlowReturn gst_audio_decoder_chain (GstPad * pad, GstObject * parent,
 +    GstBuffer * buf);
 +static gboolean gst_audio_decoder_src_query (GstPad * pad, GstObject * parent,
 +    GstQuery * query);
 +static gboolean gst_audio_decoder_sink_query (GstPad * pad, GstObject * parent,
 +    GstQuery * query);
  static void gst_audio_decoder_reset (GstAudioDecoder * dec, gboolean full);
  
 +static GstElementClass *parent_class = NULL;
  
 -GST_BOILERPLATE (GstAudioDecoder, gst_audio_decoder, GstElement,
 -    GST_TYPE_ELEMENT);
 +static void gst_audio_decoder_class_init (GstAudioDecoderClass * klass);
 +static void gst_audio_decoder_init (GstAudioDecoder * dec,
 +    GstAudioDecoderClass * klass);
  
 -static void
 -gst_audio_decoder_base_init (gpointer g_class)
 +GType
 +gst_audio_decoder_get_type (void)
  {
 +  static volatile gsize audio_decoder_type = 0;
 +
 +  if (g_once_init_enter (&audio_decoder_type)) {
 +    GType _type;
 +    static const GTypeInfo audio_decoder_info = {
 +      sizeof (GstAudioDecoderClass),
 +      NULL,
 +      NULL,
 +      (GClassInitFunc) gst_audio_decoder_class_init,
 +      NULL,
 +      NULL,
 +      sizeof (GstAudioDecoder),
 +      0,
 +      (GInstanceInitFunc) gst_audio_decoder_init,
 +    };
 +
 +    _type = g_type_register_static (GST_TYPE_ELEMENT,
 +        "GstAudioDecoder", &audio_decoder_info, G_TYPE_FLAG_ABSTRACT);
 +    g_once_init_leave (&audio_decoder_type, _type);
 +  }
 +  return audio_decoder_type;
  }
  
 +
  static void
  gst_audio_decoder_class_init (GstAudioDecoderClass * klass)
  {
@@@ -382,6 -357,8 +386,6 @@@ gst_audio_decoder_init (GstAudioDecode
    dec->sinkpad = gst_pad_new_from_template (pad_template, "sink");
    gst_pad_set_event_function (dec->sinkpad,
        GST_DEBUG_FUNCPTR (gst_audio_decoder_sink_event));
 -  gst_pad_set_setcaps_function (dec->sinkpad,
 -      GST_DEBUG_FUNCPTR (gst_audio_decoder_sink_setcaps));
    gst_pad_set_chain_function (dec->sinkpad,
        GST_DEBUG_FUNCPTR (gst_audio_decoder_chain));
    gst_pad_set_query_function (dec->sinkpad,
    g_return_if_fail (pad_template != NULL);
  
    dec->srcpad = gst_pad_new_from_template (pad_template, "src");
 -  gst_pad_set_setcaps_function (dec->srcpad,
 -      GST_DEBUG_FUNCPTR (gst_audio_decoder_src_setcaps));
    gst_pad_set_event_function (dec->srcpad,
        GST_DEBUG_FUNCPTR (gst_audio_decoder_src_event));
    gst_pad_set_query_function (dec->srcpad,
        GST_DEBUG_FUNCPTR (gst_audio_decoder_src_query));
 -  gst_pad_set_query_type_function (dec->srcpad,
 -      GST_DEBUG_FUNCPTR (gst_audio_decoder_get_query_types));
    gst_pad_use_fixed_caps (dec->srcpad);
    gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
    GST_DEBUG_OBJECT (dec, "srcpad created");
@@@ -434,7 -415,7 +438,7 @@@ gst_audio_decoder_reset (GstAudioDecode
      dec->priv->error_count = 0;
      gst_audio_decoder_clear_queues (dec);
  
 -    gst_audio_info_clear (&dec->priv->ctx.info);
 +    gst_audio_info_init (&dec->priv->ctx.info);
      memset (&dec->priv->ctx, 0, sizeof (dec->priv->ctx));
  
      if (dec->priv->taglist) {
@@@ -485,22 -466,17 +489,22 @@@ gst_audio_decoder_finalize (GObject * o
    G_OBJECT_CLASS (parent_class)->finalize (object);
  }
  
 -/* automagically perform sanity checking of src caps;
 - * also extracts output data format */
 -static gboolean
 -gst_audio_decoder_src_setcaps (GstPad * pad, GstCaps * caps)
 +/**
 + * gst_audio_decoder_set_outcaps:
 + * @dec: a #GstAudioDecoder
 + * @caps: #GstCaps
 + *
 + * Configure output @caps on the srcpad of @dec. Also perform
 + * sanity checking of @caps and extracts output data format
 + *
 + * Returns: %TRUE on success.
 + * */
 +gboolean
 +gst_audio_decoder_set_outcaps (GstAudioDecoder * dec, GstCaps * caps)
  {
 -  GstAudioDecoder *dec;
    gboolean res = TRUE;
    guint old_rate;
  
 -  dec = GST_AUDIO_DECODER (gst_pad_get_parent (pad));
 -
    GST_DEBUG_OBJECT (dec, "setting src caps %" GST_PTR_FORMAT, caps);
  
    GST_AUDIO_DECODER_STREAM_LOCK (dec);
  done:
    GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
  
 -  gst_object_unref (dec);
 +  res = gst_pad_set_caps (dec->srcpad, caps);
 +
    return res;
  
    /* ERRORS */
@@@ -538,11 -513,13 +542,11 @@@ refuse_caps
  }
  
  static gboolean
 -gst_audio_decoder_sink_setcaps (GstPad * pad, GstCaps * caps)
 +gst_audio_decoder_sink_setcaps (GstAudioDecoder * dec, GstCaps * caps)
  {
 -  GstAudioDecoder *dec;
    GstAudioDecoderClass *klass;
    gboolean res = TRUE;
  
 -  dec = GST_AUDIO_DECODER (gst_pad_get_parent (pad));
    klass = GST_AUDIO_DECODER_GET_CLASS (dec);
  
    GST_DEBUG_OBJECT (dec, "caps: %" GST_PTR_FORMAT, caps);
    GST_AUDIO_DECODER_STREAM_LOCK (dec);
    /* NOTE pbutils only needed here */
    /* TODO maybe (only) upstream demuxer/parser etc should handle this ? */
 +#if 0
    if (dec->priv->taglist)
      gst_tag_list_free (dec->priv->taglist);
    dec->priv->taglist = gst_tag_list_new ();
    gst_pb_utils_add_codec_description_to_tag_list (dec->priv->taglist,
        GST_TAG_AUDIO_CODEC, caps);
 +#endif
  
    if (klass->set_format)
      res = klass->set_format (dec, caps);
  
    GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
  
 -  g_object_unref (dec);
    return res;
  }
  
@@@ -604,9 -580,8 +608,9 @@@ gst_audio_decoder_push_forward (GstAudi
      return GST_FLOW_OK;
    }
  
 -  GST_LOG_OBJECT (dec, "clipping buffer of size %d with ts %" GST_TIME_FORMAT
 -      ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buf),
 +  GST_LOG_OBJECT (dec,
 +      "clipping buffer of size %" G_GSIZE_FORMAT " with ts %" GST_TIME_FORMAT
 +      ", duration %" GST_TIME_FORMAT, gst_buffer_get_size (buf),
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
        GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
  
    }
  
    /* decorate */
 -  gst_buffer_set_caps (buf, GST_PAD_CAPS (dec->srcpad));
 -
    if (G_UNLIKELY (priv->discont)) {
      GST_LOG_OBJECT (dec, "marking discont");
      GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
    if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) {
      /* duration should always be valid for raw audio */
      g_assert (GST_BUFFER_DURATION_IS_VALID (buf));
 -    dec->segment.last_stop =
 +    dec->segment.position =
          GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);
    }
  
      }
    }
  
 -  GST_LOG_OBJECT (dec, "pushing buffer of size %d with ts %" GST_TIME_FORMAT
 -      ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buf),
 +  GST_LOG_OBJECT (dec,
 +      "pushing buffer of size %" G_GSIZE_FORMAT " with ts %" GST_TIME_FORMAT
 +      ", duration %" GST_TIME_FORMAT, gst_buffer_get_size (buf),
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
        GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
  
@@@ -672,9 -648,8 +676,9 @@@ gst_audio_decoder_output (GstAudioDecod
      gst_audio_decoder_setup (dec);
  
    if (G_LIKELY (buf)) {
 -    GST_LOG_OBJECT (dec, "output buffer of size %d with ts %" GST_TIME_FORMAT
 -        ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buf),
 +    GST_LOG_OBJECT (dec,
 +        "output buffer of size %" G_GSIZE_FORMAT " with ts %" GST_TIME_FORMAT
 +        ", duration %" GST_TIME_FORMAT, gst_buffer_get_size (buf),
          GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
          GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
    }
@@@ -709,7 -684,7 +713,7 @@@ again
        }
        gst_adapter_push (priv->adapter_out, buf);
        priv->out_dur += GST_BUFFER_DURATION (buf);
 -      av += GST_BUFFER_SIZE (buf);
 +      av += gst_buffer_get_size (buf);
        buf = NULL;
      }
      if (priv->out_dur > dec->priv->latency)
@@@ -773,30 -748,27 +777,30 @@@ gst_audio_decoder_finish_frame (GstAudi
    GstAudioDecoderContext *ctx;
    gint samples = 0;
    GstClockTime ts, next_ts;
 +  gsize size;
    GstFlowReturn ret = GST_FLOW_OK;
  
    /* subclass should know what it is producing by now */
 -  g_return_val_if_fail (buf == NULL || GST_PAD_CAPS (dec->srcpad) != NULL,
 +  g_return_val_if_fail (buf == NULL || gst_pad_has_current_caps (dec->srcpad),
        GST_FLOW_ERROR);
    /* subclass should not hand us no data */
 -  g_return_val_if_fail (buf == NULL || GST_BUFFER_SIZE (buf) > 0,
 +  g_return_val_if_fail (buf == NULL || gst_buffer_get_size (buf) > 0,
        GST_FLOW_ERROR);
    /* no dummy calls please */
    g_return_val_if_fail (frames != 0, GST_FLOW_ERROR);
  
    priv = dec->priv;
    ctx = &dec->priv->ctx;
 +  size = buf ? gst_buffer_get_size (buf) : 0;
  
    /* must know the output format by now */
    g_return_val_if_fail (buf == NULL || GST_AUDIO_INFO_IS_VALID (&ctx->info),
        GST_FLOW_ERROR);
  
 -  GST_LOG_OBJECT (dec, "accepting %d bytes == %d samples for %d frames",
 -      buf ? GST_BUFFER_SIZE (buf) : -1,
 -      buf ? GST_BUFFER_SIZE (buf) / ctx->info.bpf : -1, frames);
 +  GST_LOG_OBJECT (dec,
 +      "accepting %" G_GSIZE_FORMAT " bytes == %" G_GSIZE_FORMAT
 +      " samples for %d frames", buf ? size : -1,
 +      buf ? size / ctx->info.bpf : -1, frames);
  
    GST_AUDIO_DECODER_STREAM_LOCK (dec);
  
  
    /* output shoud be whole number of sample frames */
    if (G_LIKELY (buf && ctx->info.bpf)) {
 -    if (GST_BUFFER_SIZE (buf) % ctx->info.bpf)
 +    if (size % ctx->info.bpf)
        goto wrong_buffer;
      /* per channel least */
 -    samples = GST_BUFFER_SIZE (buf) / ctx->info.bpf;
 +    samples = size / ctx->info.bpf;
    }
  
    /* frame and ts book-keeping */
      if (gst_tag_list_is_empty (priv->taglist)) {
        gst_tag_list_free (priv->taglist);
      } else {
 -      gst_element_found_tags (GST_ELEMENT (dec), priv->taglist);
 +      gst_pad_push_event (dec->srcpad, gst_event_new_tag (priv->taglist));
      }
      priv->taglist = NULL;
    }
  
 -  buf = gst_buffer_make_metadata_writable (buf);
 +  buf = gst_buffer_make_writable (buf);
    if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (priv->base_ts))) {
      GST_BUFFER_TIMESTAMP (buf) =
          priv->base_ts +
@@@ -929,7 -901,7 +933,7 @@@ exit
  wrong_buffer:
    {
      GST_ELEMENT_ERROR (dec, STREAM, ENCODE, (NULL),
 -        ("buffer size %d not a multiple of %d", GST_BUFFER_SIZE (buf),
 +        ("buffer size %" G_GSIZE_FORMAT " not a multiple of %d", size,
              ctx->info.bpf));
      gst_buffer_unref (buf);
      ret = GST_FLOW_ERROR;
@@@ -952,14 -924,13 +956,14 @@@ gst_audio_decoder_handle_frame (GstAudi
      GstAudioDecoderClass * klass, GstBuffer * buffer)
  {
    if (G_LIKELY (buffer)) {
 +    gsize size = gst_buffer_get_size (buffer);
      /* keep around for admin */
 -    GST_LOG_OBJECT (dec, "tracking frame size %d, ts %" GST_TIME_FORMAT,
 -        GST_BUFFER_SIZE (buffer),
 +    GST_LOG_OBJECT (dec,
 +        "tracking frame size %" G_GSIZE_FORMAT ", ts %" GST_TIME_FORMAT, size,
          GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
      g_queue_push_tail (&dec->priv->frames, buffer);
      dec->priv->ctx.delay = dec->priv->frames.length;
 -    dec->priv->bytes_in += GST_BUFFER_SIZE (buffer);
 +    dec->priv->bytes_in += size;
    } else {
      GST_LOG_OBJECT (dec, "providing subclass with NULL frame");
    }
@@@ -1021,7 -992,7 +1025,7 @@@ gst_audio_decoder_push_buffers (GstAudi
              goto parse_failed;
          }
  
 -        if (ret == GST_FLOW_UNEXPECTED) {
 +        if (ret == GST_FLOW_EOS) {
            GST_LOG_OBJECT (dec, "no frame yet");
            ret = GST_FLOW_OK;
            break;
          priv->prev_ts = ts;
        }
        buffer = gst_adapter_take_buffer (priv->adapter, len);
 -      buffer = gst_buffer_make_metadata_writable (buffer);
 +      buffer = gst_buffer_make_writable (buffer);
        GST_BUFFER_TIMESTAMP (buffer) = ts;
        flush += len;
      } else {
@@@ -1142,7 -1113,7 +1146,7 @@@ gst_audio_decoder_chain_forward (GstAud
    GstFlowReturn ret = GST_FLOW_OK;
  
    /* discard silly case, though maybe ts may be of value ?? */
 -  if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) == 0)) {
 +  if (G_UNLIKELY (gst_buffer_get_size (buffer) == 0)) {
      GST_DEBUG_OBJECT (dec, "discarding empty buffer");
      gst_buffer_unref (buffer);
      goto exit;
@@@ -1307,12 -1278,12 +1311,12 @@@ gst_audio_decoder_flush_decode (GstAudi
      }
  
      if (G_LIKELY (res == GST_FLOW_OK)) {
 -      GST_DEBUG_OBJECT (dec, "pushing buffer %p of size %u, "
 +      GST_DEBUG_OBJECT (dec, "pushing buffer %p of size %" G_GSIZE_FORMAT ", "
            "time %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT, buf,
 -          GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
 +          gst_buffer_get_size (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
            GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
        /* should be already, but let's be sure */
 -      buf = gst_buffer_make_metadata_writable (buf);
 +      buf = gst_buffer_make_writable (buf);
        /* avoid stray DISCONT from forward processing,
         * which have no meaning in reverse pushing */
        GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
@@@ -1350,9 -1321,9 +1354,9 @@@ gst_audio_decoder_chain_reverse (GstAud
    }
  
    if (G_LIKELY (buf)) {
 -    GST_DEBUG_OBJECT (dec, "gathering buffer %p of size %u, "
 +    GST_DEBUG_OBJECT (dec, "gathering buffer %p of size %" G_GSIZE_FORMAT ", "
          "time %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT, buf,
 -        GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
 +        gst_buffer_get_size (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
          GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
  
      /* add buffer to gather queue */
  }
  
  static GstFlowReturn
 -gst_audio_decoder_chain (GstPad * pad, GstBuffer * buffer)
 +gst_audio_decoder_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
  {
    GstAudioDecoder *dec;
    GstFlowReturn ret;
  
 -  dec = GST_AUDIO_DECODER (GST_PAD_PARENT (pad));
 +  dec = GST_AUDIO_DECODER (parent);
  
    GST_LOG_OBJECT (dec,
 -      "received buffer of size %d with ts %" GST_TIME_FORMAT
 -      ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer),
 +      "received buffer of size %" G_GSIZE_FORMAT " with ts %" GST_TIME_FORMAT
 +      ", duration %" GST_TIME_FORMAT, gst_buffer_get_size (buffer),
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
        GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
  
@@@ -1424,37 -1395,47 +1428,37 @@@ gst_audio_decoder_sink_eventfunc (GstAu
    gboolean handled = FALSE;
  
    switch (GST_EVENT_TYPE (event)) {
 -    case GST_EVENT_NEWSEGMENT:
 +    case GST_EVENT_SEGMENT:
      {
 -      GstFormat format;
 -      gdouble rate, arate;
 -      gint64 start, stop, time;
 -      gboolean update;
 +      GstSegment seg;
  
        GST_AUDIO_DECODER_STREAM_LOCK (dec);
 -      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
 -          &start, &stop, &time);
 +      gst_event_copy_segment (event, &seg);
  
 -      if (format == GST_FORMAT_TIME) {
 -        GST_DEBUG_OBJECT (dec, "received TIME NEW_SEGMENT %" GST_TIME_FORMAT
 -            " -- %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT
 -            ", rate %g, applied_rate %g",
 -            GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time),
 -            rate, arate);
 +      if (seg.format == GST_FORMAT_TIME) {
 +        GST_DEBUG_OBJECT (dec, "received TIME SEGMENT %" GST_SEGMENT_FORMAT,
 +            &seg);
        } else {
 -        GstFormat dformat = GST_FORMAT_TIME;
 -
 -        GST_DEBUG_OBJECT (dec, "received NEW_SEGMENT %" G_GINT64_FORMAT
 -            " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT
 -            ", rate %g, applied_rate %g", start, stop, time, rate, arate);
 +        gint64 nstart;
 +        GST_DEBUG_OBJECT (dec, "received SEGMENT %" GST_SEGMENT_FORMAT, &seg);
          /* handle newsegment resulting from legacy simple seeking */
          /* note that we need to convert this whether or not enough data
           * to handle initial newsegment */
          if (dec->priv->ctx.do_byte_time &&
 -            gst_pad_query_convert (dec->sinkpad, GST_FORMAT_BYTES, start,
 -                &dformat, &start)) {
 +            gst_pad_query_convert (dec->sinkpad, GST_FORMAT_BYTES, seg.start,
 +                GST_FORMAT_TIME, &nstart)) {
            /* best attempt convert */
            /* as these are only estimates, stop is kept open-ended to avoid
             * premature cutting */
            GST_DEBUG_OBJECT (dec, "converted to TIME start %" GST_TIME_FORMAT,
 -              GST_TIME_ARGS (start));
 -          format = GST_FORMAT_TIME;
 -          time = start;
 -          stop = GST_CLOCK_TIME_NONE;
 +              GST_TIME_ARGS (nstart));
 +          seg.format = GST_FORMAT_TIME;
 +          seg.start = nstart;
 +          seg.time = nstart;
 +          seg.stop = GST_CLOCK_TIME_NONE;
            /* replace event */
            gst_event_unref (event);
 -          event = gst_event_new_new_segment_full (update, rate, arate,
 -              GST_FORMAT_TIME, start, stop, time);
 +          event = gst_event_new_segment (&seg);
          } else {
            GST_DEBUG_OBJECT (dec, "unsupported format; ignoring");
            GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
        /* finish current segment */
        gst_audio_decoder_drain (dec);
  
 +#if 0
        if (update) {
          /* time progressed without data, see if we can fill the gap with
           * some concealment data */
          GST_DEBUG_OBJECT (dec,
 -            "segment update: plc %d, do_plc %d, last_stop %" GST_TIME_FORMAT,
 +            "segment update: plc %d, do_plc %d, position %" GST_TIME_FORMAT,
              dec->priv->plc, dec->priv->ctx.do_plc,
 -            GST_TIME_ARGS (dec->segment.last_stop));
 +            GST_TIME_ARGS (dec->segment.position));
          if (dec->priv->plc && dec->priv->ctx.do_plc &&
 -            dec->segment.rate > 0.0 && dec->segment.last_stop < start) {
 +            dec->segment.rate > 0.0 && dec->segment.position < start) {
            GstAudioDecoderClass *klass;
            GstBuffer *buf;
  
            klass = GST_AUDIO_DECODER_GET_CLASS (dec);
            /* hand subclass empty frame with duration that needs covering */
            buf = gst_buffer_new ();
 -          GST_BUFFER_DURATION (buf) = start - dec->segment.last_stop;
 +          GST_BUFFER_DURATION (buf) = start - dec->segment.position;
            /* best effort, not much error handling */
            gst_audio_decoder_handle_frame (dec, klass, buf);
          }
 -      } else {
 +      } else
 +#endif
 +      {
          /* prepare for next one */
          gst_audio_decoder_flush (dec, FALSE);
          /* and that's where we time from,
           * in case upstream does not come up with anything better
           * (e.g. upstream BYTE) */
 -        if (format != GST_FORMAT_TIME) {
 -          dec->priv->base_ts = start;
 +        if (seg.format != GST_FORMAT_TIME) {
 +          dec->priv->base_ts = seg.start;
            dec->priv->samples = 0;
          }
        }
  
        /* and follow along with segment */
 -      gst_segment_set_newsegment_full (&dec->segment, update, rate, arate,
 -          format, start, stop, time);
 -
 +      dec->segment = seg;
        dec->priv->pending_events =
            g_list_append (dec->priv->pending_events, event);
        handled = TRUE;
        GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
        break;
  
 +    case GST_EVENT_CAPS:
 +    {
 +      GstCaps *caps;
 +
 +      gst_event_parse_caps (event, &caps);
 +      gst_audio_decoder_sink_setcaps (dec, caps);
 +      gst_event_unref (event);
 +      handled = TRUE;
 +      break;
 +    }
      default:
        break;
    }
  }
  
  static gboolean
 -gst_audio_decoder_sink_event (GstPad * pad, GstEvent * event)
 +gst_audio_decoder_sink_event (GstPad * pad, GstObject * parent,
 +    GstEvent * event)
  {
    GstAudioDecoder *dec;
    GstAudioDecoderClass *klass;
    gboolean handled = FALSE;
    gboolean ret = TRUE;
  
 -  dec = GST_AUDIO_DECODER (gst_pad_get_parent (pad));
 +  dec = GST_AUDIO_DECODER (parent);
    klass = GST_AUDIO_DECODER_GET_CLASS (dec);
  
    GST_DEBUG_OBJECT (dec, "received event %d, %s", GST_EVENT_TYPE (event),
      if (!GST_EVENT_IS_SERIALIZED (event)
          || GST_EVENT_TYPE (event) == GST_EVENT_EOS
          || GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
 -      ret = gst_pad_event_default (pad, event);
 +      ret = gst_pad_event_default (pad, parent, event);
      } else {
        GST_AUDIO_DECODER_STREAM_LOCK (dec);
        dec->priv->pending_events =
  
    GST_DEBUG_OBJECT (dec, "event handled");
  
 -  gst_object_unref (dec);
    return ret;
  }
  
@@@ -1630,12 -1600,13 +1634,12 @@@ gst_audio_decoder_do_seek (GstAudioDeco
    }
  
    memcpy (&seek_segment, &dec->segment, sizeof (seek_segment));
 -  gst_segment_set_seek (&seek_segment, rate, format, flags, start_type,
 +  gst_segment_do_seek (&seek_segment, rate, format, flags, start_type,
        start_time, end_type, end_time, NULL);
 -  start_time = seek_segment.last_stop;
 +  start_time = seek_segment.position;
  
 -  format = GST_FORMAT_BYTES;
    if (!gst_pad_query_convert (dec->sinkpad, GST_FORMAT_TIME, start_time,
 -          &format, &start)) {
 +          GST_FORMAT_BYTES, &start)) {
      GST_DEBUG_OBJECT (dec, "conversion failed");
      return FALSE;
    }
  }
  
  static gboolean
 -gst_audio_decoder_src_event (GstPad * pad, GstEvent * event)
 +gst_audio_decoder_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
  {
    GstAudioDecoder *dec;
    gboolean res = FALSE;
  
 -  dec = GST_AUDIO_DECODER (gst_pad_get_parent (pad));
 -  if (G_UNLIKELY (dec == NULL)) {
 -    gst_event_unref (event);
 -    return FALSE;
 -  }
 +  dec = GST_AUDIO_DECODER (parent);
  
    GST_DEBUG_OBJECT (dec, "received event %d, %s", GST_EVENT_TYPE (event),
        GST_EVENT_TYPE_NAME (event));
    switch (GST_EVENT_TYPE (event)) {
      case GST_EVENT_SEEK:
      {
 -      GstFormat format, tformat;
 +      GstFormat format;
        gdouble rate;
        GstSeekFlags flags;
        GstSeekType cur_type, stop_type;
  
        /* ... though a non-time seek can be aided as well */
        /* First bring the requested format to time */
 -      tformat = GST_FORMAT_TIME;
 -      if (!(res = gst_pad_query_convert (pad, format, cur, &tformat, &tcur)))
 +      if (!(res =
 +              gst_pad_query_convert (pad, format, cur, GST_FORMAT_TIME, &tcur)))
          goto convert_error;
 -      if (!(res = gst_pad_query_convert (pad, format, stop, &tformat, &tstop)))
 +      if (!(res =
 +              gst_pad_query_convert (pad, format, stop, GST_FORMAT_TIME,
 +                  &tstop)))
          goto convert_error;
  
        /* then seek with time on the peer */
        break;
    }
  done:
 -  gst_object_unref (dec);
 -
    return res;
  
    /* ERRORS */
@@@ -1793,13 -1768,12 +1797,13 @@@ exit
  }
  
  static gboolean
 -gst_audio_decoder_sink_query (GstPad * pad, GstQuery * query)
 +gst_audio_decoder_sink_query (GstPad * pad, GstObject * parent,
 +    GstQuery * query)
  {
 -  gboolean res = TRUE;
 +  gboolean res = FALSE;
    GstAudioDecoder *dec;
  
 -  dec = GST_AUDIO_DECODER (gst_pad_get_parent (pad));
 +  dec = GST_AUDIO_DECODER (parent);
  
    switch (GST_QUERY_TYPE (query)) {
      case GST_QUERY_FORMATS:
        break;
      }
      default:
 -      res = gst_pad_query_default (pad, query);
 +      res = gst_pad_query_default (pad, parent, query);
        break;
    }
  
  error:
 -  gst_object_unref (dec);
    return res;
  }
  
 -static const GstQueryType *
 -gst_audio_decoder_get_query_types (GstPad * pad)
 -{
 -  static const GstQueryType gst_audio_decoder_src_query_types[] = {
 -    GST_QUERY_POSITION,
 -    GST_QUERY_DURATION,
 -    GST_QUERY_CONVERT,
 -    GST_QUERY_LATENCY,
 -    0
 -  };
 -
 -  return gst_audio_decoder_src_query_types;
 -}
 -
  /* FIXME ? are any of these queries (other than latency) a decoder's business ??
   * also, the conversion stuff might seem to make sense, but seems to not mind
   * segment stuff etc at all
   * Supposedly that's backward compatibility ... */
  static gboolean
 -gst_audio_decoder_src_query (GstPad * pad, GstQuery * query)
 +gst_audio_decoder_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
  {
    GstAudioDecoder *dec;
 -  GstPad *peerpad;
    gboolean res = FALSE;
  
 -  dec = GST_AUDIO_DECODER (GST_PAD_PARENT (pad));
 -  if (G_UNLIKELY (dec == NULL))
 -    return FALSE;
 -
 -  peerpad = gst_pad_get_peer (GST_PAD (dec->sinkpad));
 +  dec = GST_AUDIO_DECODER (parent);
  
    GST_LOG_OBJECT (dec, "handling query: %" GST_PTR_FORMAT, query);
  
        GstFormat format;
  
        /* upstream in any case */
 -      if ((res = gst_pad_query_default (pad, query)))
 +      if ((res = gst_pad_query_default (pad, parent, query)))
          break;
  
        gst_query_parse_duration (query, &format, NULL);
        if (format == GST_FORMAT_TIME && gst_audio_decoder_do_byte (dec)) {
          gint64 value;
  
 -        format = GST_FORMAT_BYTES;
 -        if (gst_pad_query_peer_duration (dec->sinkpad, &format, &value)) {
 +        if (gst_pad_peer_query_duration (dec->sinkpad, GST_FORMAT_BYTES,
 +                &value)) {
            GST_LOG_OBJECT (dec, "upstream size %" G_GINT64_FORMAT, value);
 -          format = GST_FORMAT_TIME;
            if (gst_pad_query_convert (dec->sinkpad, GST_FORMAT_BYTES, value,
 -                  &format, &value)) {
 +                  GST_FORMAT_TIME, &value)) {
              gst_query_set_duration (query, GST_FORMAT_TIME, value);
              res = TRUE;
            }
        }
  
        /* we start from the last seen time */
 -      time = dec->segment.last_stop;
 +      time = dec->segment.position;
        /* correct for the segment values */
        time = gst_segment_to_stream_time (&dec->segment, GST_FORMAT_TIME, time);
  
        /* and convert to the final format */
        gst_query_parse_position (query, &format, NULL);
        if (!(res = gst_pad_query_convert (pad, GST_FORMAT_TIME, time,
 -                  &format, &value)))
 +                  format, &value)))
          break;
  
        gst_query_set_position (query, format, value);
        break;
      }
      default:
 -      res = gst_pad_query_default (pad, query);
 +      res = gst_pad_query_default (pad, parent, query);
        break;
    }
  
 -  gst_object_unref (peerpad);
    return res;
  }
  
@@@ -2067,7 -2063,7 +2071,7 @@@ gst_audio_decoder_change_state (GstElem
        break;
    }
  
 -  ret = parent_class->change_state (element, transition);
 +  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
  
    switch (transition) {
      case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
  #  include "config.h"
  #endif
  
+ /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+  * with newer GLib versions (>= 2.31.0) */
+ #define GLIB_DISABLE_DEPRECATION_WARNINGS
  #include "gstaudioencoder.h"
  #include <gst/base/gstadapter.h>
  #include <gst/audio/audio.h>
@@@ -293,22 -297,17 +297,22 @@@ static void gst_audio_encoder_set_prope
  static void gst_audio_encoder_get_property (GObject * object,
      guint prop_id, GValue * value, GParamSpec * pspec);
  
 -static gboolean gst_audio_encoder_sink_activate_push (GstPad * pad,
 -    gboolean active);
 -
 -static gboolean gst_audio_encoder_sink_event (GstPad * pad, GstEvent * event);
 -static gboolean gst_audio_encoder_sink_setcaps (GstPad * pad, GstCaps * caps);
 -static GstFlowReturn gst_audio_encoder_chain (GstPad * pad, GstBuffer * buffer);
 -static gboolean gst_audio_encoder_src_query (GstPad * pad, GstQuery * query);
 -static gboolean gst_audio_encoder_sink_query (GstPad * pad, GstQuery * query);
 -static const GstQueryType *gst_audio_encoder_get_query_types (GstPad * pad);
 -static GstCaps *gst_audio_encoder_sink_getcaps (GstPad * pad);
 -
 +static gboolean gst_audio_encoder_sink_activate_mode (GstPad * pad,
 +    GstObject * parent, GstPadMode mode, gboolean active);
 +
 +static GstCaps *gst_audio_encoder_getcaps_default (GstAudioEncoder * enc,
 +    GstCaps * filter);
 +
 +static gboolean gst_audio_encoder_sink_event (GstPad * pad, GstObject * parent,
 +    GstEvent * event);
 +static gboolean gst_audio_encoder_sink_setcaps (GstAudioEncoder * enc,
 +    GstCaps * caps);
 +static GstFlowReturn gst_audio_encoder_chain (GstPad * pad, GstObject * parent,
 +    GstBuffer * buffer);
 +static gboolean gst_audio_encoder_src_query (GstPad * pad, GstObject * parent,
 +    GstQuery * query);
 +static gboolean gst_audio_encoder_sink_query (GstPad * pad, GstObject * parent,
 +    GstQuery * query);
  
  static void
  gst_audio_encoder_class_init (GstAudioEncoderClass * klass)
            "Consider discontinuity if timestamp jitter/imperfection exceeds tolerance (ns)",
            0, G_MAXINT64, DEFAULT_TOLERANCE,
            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 +
 +  klass->getcaps = gst_audio_encoder_getcaps_default;
  }
  
  static void
@@@ -366,12 -363,16 +370,12 @@@ gst_audio_encoder_init (GstAudioEncode
    enc->sinkpad = gst_pad_new_from_template (pad_template, "sink");
    gst_pad_set_event_function (enc->sinkpad,
        GST_DEBUG_FUNCPTR (gst_audio_encoder_sink_event));
 -  gst_pad_set_setcaps_function (enc->sinkpad,
 -      GST_DEBUG_FUNCPTR (gst_audio_encoder_sink_setcaps));
 -  gst_pad_set_getcaps_function (enc->sinkpad,
 -      GST_DEBUG_FUNCPTR (gst_audio_encoder_sink_getcaps));
    gst_pad_set_query_function (enc->sinkpad,
        GST_DEBUG_FUNCPTR (gst_audio_encoder_sink_query));
    gst_pad_set_chain_function (enc->sinkpad,
        GST_DEBUG_FUNCPTR (gst_audio_encoder_chain));
 -  gst_pad_set_activatepush_function (enc->sinkpad,
 -      GST_DEBUG_FUNCPTR (gst_audio_encoder_sink_activate_push));
 +  gst_pad_set_activatemode_function (enc->sinkpad,
 +      GST_DEBUG_FUNCPTR (gst_audio_encoder_sink_activate_mode));
    gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
  
    GST_DEBUG_OBJECT (enc, "sinkpad created");
    enc->srcpad = gst_pad_new_from_template (pad_template, "src");
    gst_pad_set_query_function (enc->srcpad,
        GST_DEBUG_FUNCPTR (gst_audio_encoder_src_query));
 -  gst_pad_set_query_type_function (enc->srcpad,
 -      GST_DEBUG_FUNCPTR (gst_audio_encoder_get_query_types));
    gst_pad_use_fixed_caps (enc->srcpad);
    gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
    GST_DEBUG_OBJECT (enc, "src created");
@@@ -413,7 -416,7 +417,7 @@@ gst_audio_encoder_reset (GstAudioEncode
      enc->priv->active = FALSE;
      enc->priv->samples_in = 0;
      enc->priv->bytes_out = 0;
 -    gst_audio_info_clear (&enc->priv->ctx.info);
 +    gst_audio_info_init (&enc->priv->ctx.info);
      memset (&enc->priv->ctx, 0, sizeof (enc->priv->ctx));
  
      if (enc->priv->tags)
@@@ -486,16 -489,15 +490,16 @@@ gst_audio_encoder_finish_frame (GstAudi
    ctx = &enc->priv->ctx;
  
    /* subclass should know what it is producing by now */
 -  g_return_val_if_fail (GST_PAD_CAPS (enc->srcpad) != NULL, GST_FLOW_ERROR);
 +  g_return_val_if_fail (gst_pad_has_current_caps (enc->srcpad), GST_FLOW_ERROR);
    /* subclass should not hand us no data */
 -  g_return_val_if_fail (buf == NULL || GST_BUFFER_SIZE (buf) > 0,
 +  g_return_val_if_fail (buf == NULL || gst_buffer_get_size (buf) > 0,
        GST_FLOW_ERROR);
  
    GST_AUDIO_ENCODER_STREAM_LOCK (enc);
  
 -  GST_LOG_OBJECT (enc, "accepting %d bytes encoded data as %d samples",
 -      buf ? GST_BUFFER_SIZE (buf) : -1, samples);
 +  GST_LOG_OBJECT (enc,
 +      "accepting %" G_GSIZE_FORMAT " bytes encoded data as %d samples",
 +      buf ? gst_buffer_get_size (buf) : -1, samples);
  
    /* mark subclass still alive and providing */
    if (G_LIKELY (buf))
    /* send after pending events, which likely includes newsegment event */
    if (G_UNLIKELY (enc->priv->tags)) {
      GstTagList *tags;
 +#if 0
 +    GstCaps *caps;
 +#endif
  
      /* add codec info to pending tags */
      tags = enc->priv->tags;
      /* no more pending */
      enc->priv->tags = NULL;
 -    gst_pb_utils_add_codec_description_to_tag_list (tags, GST_TAG_CODEC,
 -        GST_PAD_CAPS (enc->srcpad));
 +#if 0
 +    caps = gst_pad_get_current_caps (enc->srcpad);
 +    gst_pb_utils_add_codec_description_to_tag_list (tags, GST_TAG_CODEC, caps);
      gst_pb_utils_add_codec_description_to_tag_list (tags, GST_TAG_AUDIO_CODEC,
 -        GST_PAD_CAPS (enc->srcpad));
 +        caps);
 +#endif
      GST_DEBUG_OBJECT (enc, "sending tags %" GST_PTR_FORMAT, tags);
 -    gst_element_found_tags_for_pad (GST_ELEMENT (enc), enc->srcpad, tags);
 +    gst_pad_push_event (enc->srcpad, gst_event_new_tag (tags));
    }
  
    /* remove corresponding samples from input */
  
    /* collect output */
    if (G_LIKELY (buf)) {
 -    GST_LOG_OBJECT (enc, "taking %d bytes for output", GST_BUFFER_SIZE (buf));
 -    buf = gst_buffer_make_metadata_writable (buf);
 +    gsize size;
 +
 +    size = gst_buffer_get_size (buf);
 +
 +    GST_LOG_OBJECT (enc, "taking %" G_GSIZE_FORMAT " bytes for output", size);
 +    buf = gst_buffer_make_writable (buf);
  
      /* decorate */
 -    gst_buffer_set_caps (buf, GST_PAD_CAPS (enc->srcpad));
      if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (priv->base_ts))) {
        /* FIXME ? lookahead could lead to weird ts and duration ?
         * (particularly if not in perfect mode) */
              ctx->info.rate);
        } else {
          GST_BUFFER_OFFSET (buf) = priv->bytes_out;
 -        GST_BUFFER_OFFSET_END (buf) = priv->bytes_out + GST_BUFFER_SIZE (buf);
 +        GST_BUFFER_OFFSET_END (buf) = priv->bytes_out + size;
        }
      }
  
 -    priv->bytes_out += GST_BUFFER_SIZE (buf);
 +    priv->bytes_out += size;
  
      if (G_UNLIKELY (priv->discont)) {
        GST_LOG_OBJECT (enc, "marking discont");
        }
      }
  
 -    GST_LOG_OBJECT (enc, "pushing buffer of size %d with ts %" GST_TIME_FORMAT
 -        ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buf),
 +    GST_LOG_OBJECT (enc,
 +        "pushing buffer of size %" G_GSIZE_FORMAT " with ts %" GST_TIME_FORMAT
 +        ", duration %" GST_TIME_FORMAT, size,
          GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
          GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
  
@@@ -763,12 -756,10 +767,12 @@@ gst_audio_encoder_push_buffers (GstAudi
      }
  
      if (need) {
 -      buf = gst_buffer_new ();
 -      GST_BUFFER_DATA (buf) = (guint8 *)
 -          gst_adapter_peek (priv->adapter, priv->offset + need) + priv->offset;
 -      GST_BUFFER_SIZE (buf) = need;
 +      const guint8 *data;
 +
 +      data = gst_adapter_map (priv->adapter, priv->offset + need);
 +      buf =
 +          gst_buffer_new_wrapped_full ((gpointer) data, NULL, priv->offset,
 +          need);
      }
  
      GST_LOG_OBJECT (enc, "providing subclass with %d bytes at offset %d",
      priv->got_data = FALSE;
      ret = klass->handle_frame (enc, buf);
  
 -    if (G_LIKELY (buf))
 +    if (G_LIKELY (buf)) {
        gst_buffer_unref (buf);
 +      gst_adapter_unmap (priv->adapter);
 +    }
  
      /* no data to feed, no leftover provided, then bail out */
      if (G_UNLIKELY (!buf && !priv->got_data)) {
@@@ -835,16 -824,15 +839,16 @@@ gst_audio_encoder_set_base_gp (GstAudio
  }
  
  static GstFlowReturn
 -gst_audio_encoder_chain (GstPad * pad, GstBuffer * buffer)
 +gst_audio_encoder_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
  {
    GstAudioEncoder *enc;
    GstAudioEncoderPrivate *priv;
    GstAudioEncoderContext *ctx;
    GstFlowReturn ret = GST_FLOW_OK;
    gboolean discont;
 +  gsize size;
  
 -  enc = GST_AUDIO_ENCODER (GST_OBJECT_PARENT (pad));
 +  enc = GST_AUDIO_ENCODER (parent);
  
    priv = enc->priv;
    ctx = &enc->priv->ctx;
    if (!ctx->info.bpf)
      goto not_negotiated;
  
 +  size = gst_buffer_get_size (buffer);
 +
    GST_LOG_OBJECT (enc,
 -      "received buffer of size %d with ts %" GST_TIME_FORMAT
 -      ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer),
 +      "received buffer of size %" G_GSIZE_FORMAT " with ts %" GST_TIME_FORMAT
 +      ", duration %" GST_TIME_FORMAT, size,
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
        GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
  
    /* input shoud be whole number of sample frames */
 -  if (GST_BUFFER_SIZE (buffer) % ctx->info.bpf)
 +  if (size % ctx->info.bpf)
      goto wrong_buffer;
  
  #ifndef GST_DISABLE_GST_DEBUG
      GstClockTimeDiff diff;
  
      /* verify buffer duration */
 -    duration = gst_util_uint64_scale (GST_BUFFER_SIZE (buffer), GST_SECOND,
 +    duration = gst_util_uint64_scale (size, GST_SECOND,
          ctx->info.rate * ctx->info.bpf);
      diff = GST_CLOCK_DIFF (duration, GST_BUFFER_DURATION (buffer));
      if (GST_BUFFER_DURATION (buffer) != GST_CLOCK_TIME_NONE &&
      goto done;
    }
  
 +  size = gst_buffer_get_size (buffer);
 +
    GST_LOG_OBJECT (enc,
 -      "buffer after segment clipping has size %d with ts %" GST_TIME_FORMAT
 -      ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer),
 +      "buffer after segment clipping has size %" G_GSIZE_FORMAT " with ts %"
 +      GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT, size,
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
        GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
  
  
          diff_bytes =
              GST_CLOCK_TIME_TO_FRAMES (-diff, ctx->info.rate) * ctx->info.bpf;
 -        if (diff_bytes >= GST_BUFFER_SIZE (buffer)) {
 +        if (diff_bytes >= size) {
            gst_buffer_unref (buffer);
            goto done;
          }
 -        buffer = gst_buffer_make_metadata_writable (buffer);
 -        GST_BUFFER_DATA (buffer) += diff_bytes;
 -        GST_BUFFER_SIZE (buffer) -= diff_bytes;
 +        buffer = gst_buffer_make_writable (buffer);
 +        gst_buffer_resize (buffer, diff_bytes, size - diff_bytes);
  
          GST_BUFFER_TIMESTAMP (buffer) += diff;
          /* care even less about duration after this */
@@@ -1004,8 -989,8 +1008,8 @@@ not_negotiated
  wrong_buffer:
    {
      GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
 -        ("buffer size %d not a multiple of %d", GST_BUFFER_SIZE (buffer),
 -            ctx->info.bpf));
 +        ("buffer size %" G_GSIZE_FORMAT " not a multiple of %d",
 +            gst_buffer_get_size (buffer), ctx->info.bpf));
      gst_buffer_unref (buffer);
      ret = GST_FLOW_ERROR;
      goto done;
@@@ -1032,20 -1017,23 +1036,20 @@@ audio_info_is_equal (GstAudioInfo * fro
  }
  
  static gboolean
 -gst_audio_encoder_sink_setcaps (GstPad * pad, GstCaps * caps)
 +gst_audio_encoder_sink_setcaps (GstAudioEncoder * enc, GstCaps * caps)
  {
 -  GstAudioEncoder *enc;
    GstAudioEncoderClass *klass;
    GstAudioEncoderContext *ctx;
 -  GstAudioInfo *state, *old_state;
 +  GstAudioInfo state;
    gboolean res = TRUE, changed = FALSE;
    guint old_rate;
  
 -  enc = GST_AUDIO_ENCODER (GST_PAD_PARENT (pad));
    klass = GST_AUDIO_ENCODER_GET_CLASS (enc);
  
    /* subclass must do something here ... */
    g_return_val_if_fail (klass->set_format != NULL, FALSE);
  
    ctx = &enc->priv->ctx;
 -  state = &ctx->info;
  
    GST_AUDIO_ENCODER_STREAM_LOCK (enc);
  
      goto refuse_caps;
  
    /* adjust ts tracking to new sample rate */
 -  old_rate = GST_AUDIO_INFO_RATE (state);
 +  old_rate = GST_AUDIO_INFO_RATE (&ctx->info);
    if (GST_CLOCK_TIME_IS_VALID (enc->priv->base_ts) && old_rate) {
      enc->priv->base_ts +=
          GST_FRAMES_TO_CLOCK_TIME (enc->priv->samples, old_rate);
      enc->priv->samples = 0;
    }
  
 -  old_state = gst_audio_info_copy (state);
 -  if (!gst_audio_info_from_caps (state, caps))
 +  if (!gst_audio_info_from_caps (&state, caps))
      goto refuse_caps;
  
 -  changed = !audio_info_is_equal (state, old_state);
 -  gst_audio_info_free (old_state);
 +  changed = !audio_info_is_equal (&state, &ctx->info);
  
    if (changed) {
      GstClockTime old_min_latency;
      GST_OBJECT_UNLOCK (enc);
  
      if (klass->set_format)
 -      res = klass->set_format (enc, state);
 +      res = klass->set_format (enc, &state);
 +
 +    if (res)
 +      ctx->info = state;
  
      /* invalidate state to ensure no casual carrying on */
      if (!res) {
        GST_DEBUG_OBJECT (enc, "subclass did not accept format");
 -      gst_audio_info_clear (state);
 +      gst_audio_info_init (&state);
        goto exit;
      }
  
@@@ -1176,7 -1163,7 +1180,7 @@@ gst_audio_encoder_proxy_getcaps (GstAud
        const GValue *val;
        GstStructure *s;
  
 -      s = gst_structure_id_empty_new (q_name);
 +      s = gst_structure_new_id_empty (q_name);
        if ((val = gst_structure_get_value (allowed_s, "rate")))
          gst_structure_set_value (s, "rate", val);
        if ((val = gst_structure_get_value (allowed_s, "channels")))
@@@ -1210,11 -1197,22 +1214,11 @@@ done
  }
  
  static GstCaps *
 -gst_audio_encoder_sink_getcaps (GstPad * pad)
 +gst_audio_encoder_getcaps_default (GstAudioEncoder * enc, GstCaps * filter)
  {
 -  GstAudioEncoder *enc;
 -  GstAudioEncoderClass *klass;
    GstCaps *caps;
  
 -  enc = GST_AUDIO_ENCODER (gst_pad_get_parent (pad));
 -  klass = GST_AUDIO_ENCODER_GET_CLASS (enc);
 -  g_assert (pad == enc->sinkpad);
 -
 -  if (klass->getcaps)
 -    caps = klass->getcaps (enc);
 -  else
 -    caps = gst_audio_encoder_proxy_getcaps (enc, NULL);
 -  gst_object_unref (enc);
 -
 +  caps = gst_audio_encoder_proxy_getcaps (enc, NULL);
    GST_LOG_OBJECT (enc, "returning caps %" GST_PTR_FORMAT, caps);
  
    return caps;
@@@ -1229,17 -1227,26 +1233,17 @@@ gst_audio_encoder_sink_eventfunc (GstAu
    klass = GST_AUDIO_ENCODER_GET_CLASS (enc);
  
    switch (GST_EVENT_TYPE (event)) {
 -    case GST_EVENT_NEWSEGMENT:
 +    case GST_EVENT_SEGMENT:
      {
 -      GstFormat format;
 -      gdouble rate, arate;
 -      gint64 start, stop, time;
 -      gboolean update;
 -
 -      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
 -          &start, &stop, &time);
 -
 -      if (format == GST_FORMAT_TIME) {
 -        GST_DEBUG_OBJECT (enc, "received TIME NEW_SEGMENT %" GST_TIME_FORMAT
 -            " -- %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT
 -            ", rate %g, applied_rate %g",
 -            GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time),
 -            rate, arate);
 +      GstSegment seg;
 +
 +      gst_event_copy_segment (event, &seg);
 +
 +      if (seg.format == GST_FORMAT_TIME) {
 +        GST_DEBUG_OBJECT (enc, "received TIME SEGMENT %" GST_SEGMENT_FORMAT,
 +            &seg);
        } else {
 -        GST_DEBUG_OBJECT (enc, "received NEW_SEGMENT %" G_GINT64_FORMAT
 -            " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT
 -            ", rate %g, applied_rate %g", start, stop, time, rate, arate);
 +        GST_DEBUG_OBJECT (enc, "received SEGMENT %" GST_SEGMENT_FORMAT, &seg);
          GST_DEBUG_OBJECT (enc, "unsupported format; ignoring");
          break;
        }
        /* reset partially for new segment */
        gst_audio_encoder_reset (enc, FALSE);
        /* and follow along with segment */
 -      gst_segment_set_newsegment_full (&enc->segment, update, rate, arate,
 -          format, start, stop, time);
 +      enc->segment = seg;
        GST_AUDIO_ENCODER_STREAM_UNLOCK (enc);
        break;
      }
        break;
      }
  
 +    case GST_EVENT_CAPS:
 +    {
 +      GstCaps *caps;
 +
 +      gst_event_parse_caps (event, &caps);
 +      gst_audio_encoder_sink_setcaps (enc, caps);
 +      gst_event_unref (event);
 +      handled = TRUE;
 +      break;
 +    }
 +
      default:
        break;
    }
  }
  
  static gboolean
 -gst_audio_encoder_sink_event (GstPad * pad, GstEvent * event)
 +gst_audio_encoder_sink_event (GstPad * pad, GstObject * parent,
 +    GstEvent * event)
  {
    GstAudioEncoder *enc;
    GstAudioEncoderClass *klass;
    gboolean handled = FALSE;
    gboolean ret = TRUE;
  
 -  enc = GST_AUDIO_ENCODER (gst_pad_get_parent (pad));
 +  enc = GST_AUDIO_ENCODER (parent);
    klass = GST_AUDIO_ENCODER_GET_CLASS (enc);
  
    GST_DEBUG_OBJECT (enc, "received event %d, %s", GST_EVENT_TYPE (event),
      if (!GST_EVENT_IS_SERIALIZED (event)
          || GST_EVENT_TYPE (event) == GST_EVENT_EOS
          || GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
 -      ret = gst_pad_event_default (pad, event);
 +      ret = gst_pad_event_default (pad, parent, event);
      } else {
        GST_AUDIO_ENCODER_STREAM_LOCK (enc);
        enc->priv->pending_events =
  
    GST_DEBUG_OBJECT (enc, "event handled");
  
 -  gst_object_unref (enc);
    return ret;
  }
  
  static gboolean
 -gst_audio_encoder_sink_query (GstPad * pad, GstQuery * query)
 +gst_audio_encoder_sink_query (GstPad * pad, GstObject * parent,
 +    GstQuery * query)
  {
 -  gboolean res = TRUE;
 +  gboolean res = FALSE;
    GstAudioEncoder *enc;
  
 -  enc = GST_AUDIO_ENCODER (gst_pad_get_parent (pad));
 +  enc = GST_AUDIO_ENCODER (parent);
  
    switch (GST_QUERY_TYPE (query)) {
      case GST_QUERY_FORMATS:
                    src_fmt, src_val, dest_fmt, &dest_val)))
          goto error;
        gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
 +      res = TRUE;
 +      break;
 +    }
 +    case GST_QUERY_CAPS:
 +    {
 +      GstCaps *filter, *caps;
 +      GstAudioEncoderClass *klass;
 +
 +      gst_query_parse_caps (query, &filter);
 +
 +      klass = GST_AUDIO_ENCODER_GET_CLASS (enc);
 +      if (klass->getcaps) {
 +        caps = klass->getcaps (enc, filter);
 +        gst_query_set_caps_result (query, caps);
 +        gst_caps_unref (caps);
 +        res = TRUE;
 +      }
        break;
      }
      default:
 -      res = gst_pad_query_default (pad, query);
 +      res = gst_pad_query_default (pad, parent, query);
        break;
    }
  
  error:
 -  gst_object_unref (enc);
    return res;
  }
  
 -static const GstQueryType *
 -gst_audio_encoder_get_query_types (GstPad * pad)
 -{
 -  static const GstQueryType gst_audio_encoder_src_query_types[] = {
 -    GST_QUERY_POSITION,
 -    GST_QUERY_DURATION,
 -    GST_QUERY_CONVERT,
 -    GST_QUERY_LATENCY,
 -    0
 -  };
 -
 -  return gst_audio_encoder_src_query_types;
 -}
 -
  /*
   * gst_audio_encoded_audio_convert:
   * @fmt: audio format of the encoded audio
@@@ -1509,12 -1503,17 +1513,12 @@@ exit
   * segment stuff etc at all
   * Supposedly that's backward compatibility ... */
  static gboolean
 -gst_audio_encoder_src_query (GstPad * pad, GstQuery * query)
 +gst_audio_encoder_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
  {
    GstAudioEncoder *enc;
 -  GstPad *peerpad;
    gboolean res = FALSE;
  
 -  enc = GST_AUDIO_ENCODER (GST_PAD_PARENT (pad));
 -  if (G_UNLIKELY (enc == NULL))
 -    return FALSE;
 -
 -  peerpad = gst_pad_get_peer (GST_PAD (enc->sinkpad));
 +  enc = GST_AUDIO_ENCODER (parent);
  
    GST_LOG_OBJECT (enc, "handling query: %" GST_PTR_FORMAT, query);
  
          break;
        }
  
 -      if (!peerpad) {
 -        GST_LOG_OBJECT (enc, "no peer");
 -        break;
 -      }
 -
        gst_query_parse_position (query, &req_fmt, NULL);
        fmt = GST_FORMAT_TIME;
 -      if (!(res = gst_pad_query_position (peerpad, &fmt, &pos)))
 +      if (!(res = gst_pad_peer_query_position (enc->sinkpad, fmt, &pos)))
          break;
  
 -      if ((res = gst_pad_query_convert (peerpad, fmt, pos, &req_fmt, &val))) {
 +      if ((res =
 +              gst_pad_peer_query_convert (enc->sinkpad, fmt, pos, req_fmt,
 +                  &val))) {
          gst_query_set_position (query, req_fmt, val);
        }
        break;
          break;
        }
  
 -      if (!peerpad) {
 -        GST_LOG_OBJECT (enc, "no peer");
 -        break;
 -      }
 -
        gst_query_parse_duration (query, &req_fmt, NULL);
        fmt = GST_FORMAT_TIME;
 -      if (!(res = gst_pad_query_duration (peerpad, &fmt, &dur)))
 +      if (!(res = gst_pad_peer_query_duration (enc->sinkpad, fmt, &dur)))
          break;
  
 -      if ((res = gst_pad_query_convert (peerpad, fmt, dur, &req_fmt, &val))) {
 +      if ((res =
 +              gst_pad_peer_query_convert (enc->sinkpad, fmt, dur, req_fmt,
 +                  &val))) {
          gst_query_set_duration (query, req_fmt, val);
        }
        break;
        break;
      }
      default:
 -      res = gst_pad_query_default (pad, query);
 +      res = gst_pad_query_default (pad, parent, query);
        break;
    }
  
 -  gst_object_unref (peerpad);
    return res;
  }
  
@@@ -1684,7 -1690,7 +1688,7 @@@ gst_audio_encoder_activate (GstAudioEnc
  
      if (enc->priv->tags)
        gst_tag_list_free (enc->priv->tags);
 -    enc->priv->tags = gst_tag_list_new ();
 +    enc->priv->tags = gst_tag_list_new_empty ();
  
      if (!enc->priv->active && klass->start)
        result = klass->start (enc);
  
  
  static gboolean
 -gst_audio_encoder_sink_activate_push (GstPad * pad, gboolean active)
 +gst_audio_encoder_sink_activate_mode (GstPad * pad, GstObject * parent,
 +    GstPadMode mode, gboolean active)
  {
    gboolean result = TRUE;
    GstAudioEncoder *enc;
  
 -  enc = GST_AUDIO_ENCODER (gst_pad_get_parent (pad));
 +  enc = GST_AUDIO_ENCODER (parent);
  
    GST_DEBUG_OBJECT (enc, "sink activate push %d", active);
  
  
    GST_DEBUG_OBJECT (enc, "sink activate push return: %d", result);
  
 -  gst_object_unref (enc);
    return result;
  }
  
@@@ -18,9 -18,9 +18,9 @@@
   */
  
  /**
 - * SECTION:gstringbuffer
 + * SECTION:gstaudioringbuffer
   * @short_description: Base class for audio ringbuffer implementations
 - * @see_also: #GstBaseAudioSink, #GstAudioSink
 + * @see_also: #GstAudioBaseSink, #GstAudioSink
   *
   * <refsect2>
   * <para>
  
  #include <string.h>
  
 -#include "gstringbuffer.h"
 +#include "gstaudioringbuffer.h"
  
 -GST_DEBUG_CATEGORY_STATIC (gst_ring_buffer_debug);
 -#define GST_CAT_DEFAULT gst_ring_buffer_debug
+ #include "gst/glib-compat-private.h"
 +GST_DEBUG_CATEGORY_STATIC (gst_audio_ring_buffer_debug);
 +#define GST_CAT_DEFAULT gst_audio_ring_buffer_debug
  
 -static void gst_ring_buffer_dispose (GObject * object);
 -static void gst_ring_buffer_finalize (GObject * object);
 +static void gst_audio_ring_buffer_dispose (GObject * object);
 +static void gst_audio_ring_buffer_finalize (GObject * object);
  
 -static gboolean gst_ring_buffer_pause_unlocked (GstRingBuffer * buf);
 -static void default_clear_all (GstRingBuffer * buf);
 -static guint default_commit (GstRingBuffer * buf, guint64 * sample,
 +static gboolean gst_audio_ring_buffer_pause_unlocked (GstAudioRingBuffer * buf);
 +static void default_clear_all (GstAudioRingBuffer * buf);
 +static guint default_commit (GstAudioRingBuffer * buf, guint64 * sample,
      guchar * data, gint in_samples, gint out_samples, gint * accum);
  
  /* ringbuffer abstract base class */
 -G_DEFINE_ABSTRACT_TYPE (GstRingBuffer, gst_ring_buffer, GST_TYPE_OBJECT);
 +G_DEFINE_ABSTRACT_TYPE (GstAudioRingBuffer, gst_audio_ring_buffer,
 +    GST_TYPE_OBJECT);
  
  static void
 -gst_ring_buffer_class_init (GstRingBufferClass * klass)
 +gst_audio_ring_buffer_class_init (GstAudioRingBufferClass * klass)
  {
    GObjectClass *gobject_class;
 -  GstRingBufferClass *gstringbuffer_class;
 +  GstAudioRingBufferClass *gstaudioringbuffer_class;
  
    gobject_class = (GObjectClass *) klass;
 -  gstringbuffer_class = (GstRingBufferClass *) klass;
 +  gstaudioringbuffer_class = (GstAudioRingBufferClass *) klass;
  
 -  GST_DEBUG_CATEGORY_INIT (gst_ring_buffer_debug, "ringbuffer", 0,
 +  GST_DEBUG_CATEGORY_INIT (gst_audio_ring_buffer_debug, "ringbuffer", 0,
        "ringbuffer class");
  
 -  gobject_class->dispose = gst_ring_buffer_dispose;
 -  gobject_class->finalize = gst_ring_buffer_finalize;
 +  gobject_class->dispose = gst_audio_ring_buffer_dispose;
 +  gobject_class->finalize = gst_audio_ring_buffer_finalize;
  
 -  gstringbuffer_class->clear_all = GST_DEBUG_FUNCPTR (default_clear_all);
 -  gstringbuffer_class->commit = GST_DEBUG_FUNCPTR (default_commit);
 +  gstaudioringbuffer_class->clear_all = GST_DEBUG_FUNCPTR (default_clear_all);
 +  gstaudioringbuffer_class->commit = GST_DEBUG_FUNCPTR (default_commit);
  }
  
  static void
 -gst_ring_buffer_init (GstRingBuffer * ringbuffer)
 +gst_audio_ring_buffer_init (GstAudioRingBuffer * ringbuffer)
  {
    ringbuffer->open = FALSE;
    ringbuffer->acquired = FALSE;
 -  ringbuffer->state = GST_RING_BUFFER_STATE_STOPPED;
 +  ringbuffer->state = GST_AUDIO_RING_BUFFER_STATE_STOPPED;
    ringbuffer->cond = g_cond_new ();
    ringbuffer->waiting = 0;
    ringbuffer->empty_seg = NULL;
 -  ringbuffer->abidata.ABI.flushing = TRUE;
 +  ringbuffer->flushing = TRUE;
  }
  
  static void
 -gst_ring_buffer_dispose (GObject * object)
 +gst_audio_ring_buffer_dispose (GObject * object)
  {
 -  GstRingBuffer *ringbuffer = GST_RING_BUFFER (object);
 +  GstAudioRingBuffer *ringbuffer = GST_AUDIO_RING_BUFFER (object);
  
    gst_caps_replace (&ringbuffer->spec.caps, NULL);
  
 -  G_OBJECT_CLASS (gst_ring_buffer_parent_class)->dispose (G_OBJECT
 +  G_OBJECT_CLASS (gst_audio_ring_buffer_parent_class)->dispose (G_OBJECT
        (ringbuffer));
  }
  
  static void
 -gst_ring_buffer_finalize (GObject * object)
 +gst_audio_ring_buffer_finalize (GObject * object)
  {
 -  GstRingBuffer *ringbuffer = GST_RING_BUFFER (object);
 +  GstAudioRingBuffer *ringbuffer = GST_AUDIO_RING_BUFFER (object);
  
    g_cond_free (ringbuffer->cond);
    g_free (ringbuffer->empty_seg);
  
 -  G_OBJECT_CLASS (gst_ring_buffer_parent_class)->finalize (G_OBJECT
 +  G_OBJECT_CLASS (gst_audio_ring_buffer_parent_class)->finalize (G_OBJECT
        (ringbuffer));
  }
  
 -typedef struct
 -{
 -  const GstBufferFormat format;
 -  const guint8 silence[4];
 -} FormatDef;
 -
 -static const FormatDef linear_defs[4 * 2 * 2] = {
 -  {GST_S8, {0x00, 0x00, 0x00, 0x00}},
 -  {GST_S8, {0x00, 0x00, 0x00, 0x00}},
 -  {GST_U8, {0x80, 0x80, 0x80, 0x80}},
 -  {GST_U8, {0x80, 0x80, 0x80, 0x80}},
 -  {GST_S16_LE, {0x00, 0x00, 0x00, 0x00}},
 -  {GST_S16_BE, {0x00, 0x00, 0x00, 0x00}},
 -  {GST_U16_LE, {0x00, 0x80, 0x00, 0x80}},
 -  {GST_U16_BE, {0x80, 0x00, 0x80, 0x00}},
 -  {GST_S24_LE, {0x00, 0x00, 0x00, 0x00}},
 -  {GST_S24_BE, {0x00, 0x00, 0x00, 0x00}},
 -  {GST_U24_LE, {0x00, 0x00, 0x80, 0x00}},
 -  {GST_U24_BE, {0x80, 0x00, 0x00, 0x00}},
 -  {GST_S32_LE, {0x00, 0x00, 0x00, 0x00}},
 -  {GST_S32_BE, {0x00, 0x00, 0x00, 0x00}},
 -  {GST_U32_LE, {0x00, 0x00, 0x00, 0x80}},
 -  {GST_U32_BE, {0x80, 0x00, 0x00, 0x00}}
 -};
 -
 -static const FormatDef linear24_defs[3 * 2 * 2] = {
 -  {GST_S24_3LE, {0x00, 0x00, 0x00, 0x00}},
 -  {GST_S24_3BE, {0x00, 0x00, 0x00, 0x00}},
 -  {GST_U24_3LE, {0x00, 0x00, 0x80, 0x00}},
 -  {GST_U24_3BE, {0x80, 0x00, 0x00, 0x00}},
 -  {GST_S20_3LE, {0x00, 0x00, 0x00, 0x00}},
 -  {GST_S20_3BE, {0x00, 0x00, 0x00, 0x00}},
 -  {GST_U20_3LE, {0x00, 0x00, 0x08, 0x00}},
 -  {GST_U20_3BE, {0x08, 0x00, 0x00, 0x00}},
 -  {GST_S18_3LE, {0x00, 0x00, 0x00, 0x00}},
 -  {GST_S18_3BE, {0x00, 0x00, 0x00, 0x00}},
 -  {GST_U18_3LE, {0x00, 0x00, 0x02, 0x00}},
 -  {GST_U18_3BE, {0x02, 0x00, 0x00, 0x00}}
 -};
 -
 -static const FormatDef *
 -build_linear_format (int depth, int width, int unsignd, int big_endian)
 -{
 -  const FormatDef *formats;
 -
 -  if (width == 24) {
 -    switch (depth) {
 -      case 24:
 -        formats = &linear24_defs[0];
 -        break;
 -      case 20:
 -        formats = &linear24_defs[4];
 -        break;
 -      case 18:
 -        formats = &linear24_defs[8];
 -        break;
 -      default:
 -        return NULL;
 -    }
 -  } else {
 -    switch (depth) {
 -      case 8:
 -        formats = &linear_defs[0];
 -        break;
 -      case 16:
 -        formats = &linear_defs[4];
 -        break;
 -      case 24:
 -        formats = &linear_defs[8];
 -        break;
 -      case 32:
 -        formats = &linear_defs[12];
 -        break;
 -      default:
 -        return NULL;
 -    }
 -  }
 -  if (unsignd)
 -    formats += 2;
 -  if (big_endian)
 -    formats += 1;
 -
 -  return formats;
 -}
 -
  #ifndef GST_DISABLE_GST_DEBUG
  static const gchar *format_type_names[] = {
 -  "linear",
 -  "float",
 +  "raw",
    "mu law",
    "a law",
    "ima adpcm",
    "eac3",
    "dts"
  };
 -
 -static const gchar *format_names[] = {
 -  "unknown",
 -  "s8",
 -  "u8",
 -  "s16_le",
 -  "s16_be",
 -  "u16_le",
 -  "u16_be",
 -  "s24_le",
 -  "s24_be",
 -  "u24_le",
 -  "u24_be",
 -  "s32_le",
 -  "s32_be",
 -  "u32_le",
 -  "u32_be",
 -  "s24_3le",
 -  "s24_3be",
 -  "u24_3le",
 -  "u24_3be",
 -  "s20_3le",
 -  "s20_3be",
 -  "u20_3le",
 -  "u20_3be",
 -  "s18_3le",
 -  "s18_3be",
 -  "u18_3le",
 -  "u18_3be",
 -  "float32_le",
 -  "float32_be",
 -  "float64_le",
 -  "float64_be",
 -  "mu_law",
 -  "a_law",
 -  "ima_adpcm",
 -  "mpeg",
 -  "gsm",
 -  "iec958",
 -  "ac3",
 -  "eac3",
 -  "dts"
 -};
  #endif
  
  /**
 - * gst_ring_buffer_debug_spec_caps:
 + * gst_audio_ring_buffer_debug_spec_caps:
   * @spec: the spec to debug
   *
   * Print debug info about the parsed caps in @spec to the debug log.
   */
  void
 -gst_ring_buffer_debug_spec_caps (GstRingBufferSpec * spec)
 +gst_audio_ring_buffer_debug_spec_caps (GstAudioRingBufferSpec * spec)
  {
 +#if 0
    gint i, bytes;
 +#endif
  
    GST_DEBUG ("spec caps: %p %" GST_PTR_FORMAT, spec->caps, spec->caps);
    GST_DEBUG ("parsed caps: type:         %d, '%s'", spec->type,
        format_type_names[spec->type]);
 -  GST_DEBUG ("parsed caps: format:       %d, '%s'", spec->format,
 -      format_names[spec->format]);
 +#if 0
    GST_DEBUG ("parsed caps: width:        %d", spec->width);
 -  GST_DEBUG ("parsed caps: depth:        %d", spec->depth);
    GST_DEBUG ("parsed caps: sign:         %d", spec->sign);
    GST_DEBUG ("parsed caps: bigend:       %d", spec->bigend);
    GST_DEBUG ("parsed caps: rate:         %d", spec->rate);
    for (i = 0; i < bytes; i++) {
      GST_DEBUG ("silence byte %d: %02x", i, spec->silence_sample[i]);
    }
 +#endif
  }
  
  /**
 - * gst_ring_buffer_debug_spec_buff:
 + * gst_audio_ring_buffer_debug_spec_buff:
   * @spec: the spec to debug
   *
   * Print debug info about the buffer sized in @spec to the debug log.
   */
  void
 -gst_ring_buffer_debug_spec_buff (GstRingBufferSpec * spec)
 +gst_audio_ring_buffer_debug_spec_buff (GstAudioRingBufferSpec * spec)
  {
 +  gint bpf = GST_AUDIO_INFO_BPF (&spec->info);
 +
    GST_DEBUG ("acquire ringbuffer: buffer time: %" G_GINT64_FORMAT " usec",
        spec->buffer_time);
    GST_DEBUG ("acquire ringbuffer: latency time: %" G_GINT64_FORMAT " usec",
    GST_DEBUG ("acquire ringbuffer: total segments: %d", spec->segtotal);
    GST_DEBUG ("acquire ringbuffer: latency segments: %d", spec->seglatency);
    GST_DEBUG ("acquire ringbuffer: segment size: %d bytes = %d samples",
 -      spec->segsize, spec->segsize / spec->bytes_per_sample);
 +      spec->segsize, spec->segsize / bpf);
    GST_DEBUG ("acquire ringbuffer: buffer size: %d bytes = %d samples",
 -      spec->segsize * spec->segtotal,
 -      spec->segsize * spec->segtotal / spec->bytes_per_sample);
 +      spec->segsize * spec->segtotal, spec->segsize * spec->segtotal / bpf);
  }
  
  /**
 - * gst_ring_buffer_parse_caps:
 + * gst_audio_ring_buffer_parse_caps:
   * @spec: a spec
   * @caps: a #GstCaps
   *
   * Returns: TRUE if the caps could be parsed.
   */
  gboolean
 -gst_ring_buffer_parse_caps (GstRingBufferSpec * spec, GstCaps * caps)
 +gst_audio_ring_buffer_parse_caps (GstAudioRingBufferSpec * spec, GstCaps * caps)
  {
    const gchar *mimetype;
    GstStructure *structure;
    gint i;
 +  GstAudioInfo info;
  
    structure = gst_caps_get_structure (caps, 0);
 +  gst_audio_info_init (&info);
  
    /* we have to differentiate between int and float formats */
    mimetype = gst_structure_get_name (structure);
  
 -  if (g_str_equal (mimetype, "audio/x-raw-int")) {
 -    gint endianness;
 -    const FormatDef *def;
 -    gint j, bytes;
 -
 -    spec->type = GST_BUFTYPE_LINEAR;
 -
 -    /* extract the needed information from the cap */
 -    if (!(gst_structure_get_int (structure, "rate", &spec->rate) &&
 -            gst_structure_get_int (structure, "channels", &spec->channels) &&
 -            gst_structure_get_int (structure, "width", &spec->width) &&
 -            gst_structure_get_int (structure, "depth", &spec->depth) &&
 -            gst_structure_get_boolean (structure, "signed", &spec->sign)))
 -      goto parse_error;
 -
 -    /* extract endianness if needed */
 -    if (spec->width > 8) {
 -      if (!gst_structure_get_int (structure, "endianness", &endianness))
 -        goto parse_error;
 -    } else {
 -      endianness = G_BYTE_ORDER;
 -    }
 -
 -    spec->bigend = endianness == G_LITTLE_ENDIAN ? FALSE : TRUE;
 -
 -    def = build_linear_format (spec->depth, spec->width, spec->sign ? 0 : 1,
 -        spec->bigend ? 1 : 0);
 -
 -    if (def == NULL)
 -      goto parse_error;
 -
 -    spec->format = def->format;
 -
 -    bytes = spec->width >> 3;
 -
 -    for (i = 0; i < spec->channels; i++) {
 -      for (j = 0; j < bytes; j++) {
 -        spec->silence_sample[i * bytes + j] = def->silence[j];
 -      }
 -    }
 -  } else if (g_str_equal (mimetype, "audio/x-raw-float")) {
 -
 -    spec->type = GST_BUFTYPE_FLOAT;
 -
 -    /* extract the needed information from the cap */
 -    if (!(gst_structure_get_int (structure, "rate", &spec->rate) &&
 -            gst_structure_get_int (structure, "channels", &spec->channels) &&
 -            gst_structure_get_int (structure, "width", &spec->width)))
 +  if (g_str_equal (mimetype, "audio/x-raw")) {
 +    if (!gst_audio_info_from_caps (&info, caps))
        goto parse_error;
  
 -    /* match layout to format wrt to endianness */
 -    switch (spec->width) {
 -      case 32:
 -        spec->format =
 -            G_BYTE_ORDER == G_LITTLE_ENDIAN ? GST_FLOAT32_LE : GST_FLOAT32_BE;
 -        break;
 -      case 64:
 -        spec->format =
 -            G_BYTE_ORDER == G_LITTLE_ENDIAN ? GST_FLOAT64_LE : GST_FLOAT64_BE;
 -        break;
 -      default:
 -        goto parse_error;
 -    }
 -    /* float silence is all zeros.. */
 -    memset (spec->silence_sample, 0, 32);
 +    spec->type = GST_BUFTYPE_RAW;
    } else if (g_str_equal (mimetype, "audio/x-alaw")) {
      /* extract the needed information from the cap */
 -    if (!(gst_structure_get_int (structure, "rate", &spec->rate) &&
 -            gst_structure_get_int (structure, "channels", &spec->channels)))
 +    if (!(gst_structure_get_int (structure, "rate", &info.rate) &&
 +            gst_structure_get_int (structure, "channels", &info.channels)))
        goto parse_error;
  
      spec->type = GST_BUFTYPE_A_LAW;
 -    spec->format = GST_A_LAW;
 -    spec->width = 8;
 -    spec->depth = 8;
 -    for (i = 0; i < spec->channels; i++)
 -      spec->silence_sample[i] = 0xd5;
 +    info.bpf = info.channels;
    } else if (g_str_equal (mimetype, "audio/x-mulaw")) {
      /* extract the needed information from the cap */
 -    if (!(gst_structure_get_int (structure, "rate", &spec->rate) &&
 -            gst_structure_get_int (structure, "channels", &spec->channels)))
 +    if (!(gst_structure_get_int (structure, "rate", &info.rate) &&
 +            gst_structure_get_int (structure, "channels", &info.channels)))
        goto parse_error;
  
      spec->type = GST_BUFTYPE_MU_LAW;
 -    spec->format = GST_MU_LAW;
 -    spec->width = 8;
 -    spec->depth = 8;
 -    for (i = 0; i < spec->channels; i++)
 -      spec->silence_sample[i] = 0xff;
 +    info.bpf = info.channels;
    } else if (g_str_equal (mimetype, "audio/x-iec958")) {
      /* extract the needed information from the cap */
 -    if (!(gst_structure_get_int (structure, "rate", &spec->rate)))
 +    if (!(gst_structure_get_int (structure, "rate", &info.rate)))
        goto parse_error;
  
      spec->type = GST_BUFTYPE_IEC958;
 -    spec->format = GST_IEC958;
 -    spec->width = 16;
 -    spec->depth = 16;
 -    spec->channels = 2;
 +    info.bpf = 4;
    } else if (g_str_equal (mimetype, "audio/x-ac3")) {
      /* extract the needed information from the cap */
 -    if (!(gst_structure_get_int (structure, "rate", &spec->rate)))
 +    if (!(gst_structure_get_int (structure, "rate", &info.rate)))
        goto parse_error;
  
      spec->type = GST_BUFTYPE_AC3;
 -    spec->format = GST_AC3;
 -    spec->width = 16;
 -    spec->depth = 16;
 -    spec->channels = 2;
 +    info.bpf = 4;
    } else if (g_str_equal (mimetype, "audio/x-eac3")) {
      /* extract the needed information from the cap */
 -    if (!(gst_structure_get_int (structure, "rate", &spec->rate)))
 +    if (!(gst_structure_get_int (structure, "rate", &info.rate)))
        goto parse_error;
  
      spec->type = GST_BUFTYPE_EAC3;
 -    spec->format = GST_EAC3;
 -    spec->width = 64;
 -    spec->depth = 64;
 -    spec->channels = 2;
 +    info.bpf = 16;
    } else if (g_str_equal (mimetype, "audio/x-dts")) {
      /* extract the needed information from the cap */
 -    if (!(gst_structure_get_int (structure, "rate", &spec->rate)))
 +    if (!(gst_structure_get_int (structure, "rate", &info.rate)))
        goto parse_error;
  
      spec->type = GST_BUFTYPE_DTS;
 -    spec->format = GST_DTS;
 -    spec->width = 16;
 -    spec->depth = 16;
 -    spec->channels = 2;
 +    info.bpf = 4;
    } else if (g_str_equal (mimetype, "audio/mpeg") &&
        gst_structure_get_int (structure, "mpegaudioversion", &i) &&
        (i == 1 || i == 2)) {
      /* Now we know this is MPEG-1 or MPEG-2 (non AAC) */
      /* extract the needed information from the cap */
 -    if (!(gst_structure_get_int (structure, "rate", &spec->rate)))
 +    if (!(gst_structure_get_int (structure, "rate", &info.rate)))
        goto parse_error;
  
      spec->type = GST_BUFTYPE_MPEG;
 -    spec->format = GST_MPEG;
 -    spec->width = 16;
 -    spec->depth = 16;
 -    spec->channels = 2;
 +    info.bpf = 4;
    } else {
      goto parse_error;
    }
  
 -  spec->bytes_per_sample = (spec->width >> 3) * spec->channels;
 -
    gst_caps_replace (&spec->caps, caps);
  
    g_return_val_if_fail (spec->latency_time != 0, FALSE);
    /* calculate suggested segsize and segtotal. segsize should be one unit
     * of 'latency_time' samples, scaling for the fact that latency_time is
     * currently stored in microseconds (FIXME: in 0.11) */
 -  spec->segsize = gst_util_uint64_scale (spec->rate * spec->bytes_per_sample,
 +  spec->segsize = gst_util_uint64_scale (info.rate * info.bpf,
        spec->latency_time, GST_SECOND / GST_USECOND);
    /* Round to an integer number of samples */
 -  spec->segsize -= spec->segsize % spec->bytes_per_sample;
 +  spec->segsize -= spec->segsize % info.bpf;
  
    spec->segtotal = spec->buffer_time / spec->latency_time;
    /* leave the latency undefined now, implementations can change it but if it's
     * not changed, we assume the same value as segtotal */
    spec->seglatency = -1;
  
 -  gst_ring_buffer_debug_spec_caps (spec);
 -  gst_ring_buffer_debug_spec_buff (spec);
 +  spec->info = info;
 +
 +  gst_audio_ring_buffer_debug_spec_caps (spec);
 +  gst_audio_ring_buffer_debug_spec_buff (spec);
  
    return TRUE;
  
@@@ -299,8 -508,8 +301,8 @@@ parse_error
  }
  
  /**
 - * gst_ring_buffer_convert:
 - * @buf: the #GstRingBuffer
 + * gst_audio_ring_buffer_convert:
 + * @buf: the #GstAudioRingBuffer
   * @src_fmt: the source format
   * @src_val: the source value
   * @dest_fmt: the destination format
   * Since: 0.10.22.
   */
  gboolean
 -gst_ring_buffer_convert (GstRingBuffer * buf,
 +gst_audio_ring_buffer_convert (GstAudioRingBuffer * buf,
      GstFormat src_fmt, gint64 src_val, GstFormat dest_fmt, gint64 * dest_val)
  {
 -  gboolean res = TRUE;
 -  gint bps, rate;
 -
 -  GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s (%d) to %s (%d)",
 -      src_val, gst_format_get_name (src_fmt), src_fmt,
 -      gst_format_get_name (dest_fmt), dest_fmt);
 -
 -  if (src_fmt == dest_fmt || src_val == -1) {
 -    *dest_val = src_val;
 -    goto done;
 -  }
 +  gboolean res;
  
 -  /* get important info */
    GST_OBJECT_LOCK (buf);
 -  bps = buf->spec.bytes_per_sample;
 -  rate = buf->spec.rate;
 +  res =
 +      gst_audio_info_convert (&buf->spec.info, src_fmt, src_val, dest_fmt,
 +      dest_val);
    GST_OBJECT_UNLOCK (buf);
  
 -  if (bps == 0 || rate == 0) {
 -    GST_DEBUG ("no rate or bps configured");
 -    res = FALSE;
 -    goto done;
 -  }
 -
 -  switch (src_fmt) {
 -    case GST_FORMAT_BYTES:
 -      switch (dest_fmt) {
 -        case GST_FORMAT_TIME:
 -          *dest_val = gst_util_uint64_scale_int (src_val / bps, GST_SECOND,
 -              rate);
 -          break;
 -        case GST_FORMAT_DEFAULT:
 -          *dest_val = src_val / bps;
 -          break;
 -        default:
 -          res = FALSE;
 -          break;
 -      }
 -      break;
 -    case GST_FORMAT_DEFAULT:
 -      switch (dest_fmt) {
 -        case GST_FORMAT_TIME:
 -          *dest_val = gst_util_uint64_scale_int (src_val, GST_SECOND, rate);
 -          break;
 -        case GST_FORMAT_BYTES:
 -          *dest_val = src_val * bps;
 -          break;
 -        default:
 -          res = FALSE;
 -          break;
 -      }
 -      break;
 -    case GST_FORMAT_TIME:
 -      switch (dest_fmt) {
 -        case GST_FORMAT_DEFAULT:
 -          *dest_val = gst_util_uint64_scale_int (src_val, rate, GST_SECOND);
 -          break;
 -        case GST_FORMAT_BYTES:
 -          *dest_val = gst_util_uint64_scale_int (src_val, rate, GST_SECOND);
 -          *dest_val *= bps;
 -          break;
 -        default:
 -          res = FALSE;
 -          break;
 -      }
 -      break;
 -    default:
 -      res = FALSE;
 -      break;
 -  }
 -done:
 -  GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, res, *dest_val);
 -
    return res;
  }
  
  /**
 - * gst_ring_buffer_set_callback:
 - * @buf: the #GstRingBuffer to set the callback on
 + * gst_audio_ring_buffer_set_callback:
 + * @buf: the #GstAudioRingBuffer to set the callback on
   * @cb: the callback to set
   * @user_data: user data passed to the callback
   *
   * MT safe.
   */
  void
 -gst_ring_buffer_set_callback (GstRingBuffer * buf, GstRingBufferCallback cb,
 -    gpointer user_data)
 +gst_audio_ring_buffer_set_callback (GstAudioRingBuffer * buf,
 +    GstAudioRingBufferCallback cb, gpointer user_data)
  {
 -  g_return_if_fail (GST_IS_RING_BUFFER (buf));
 +  g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
  
    GST_OBJECT_LOCK (buf);
    buf->callback = cb;
  
  
  /**
 - * gst_ring_buffer_open_device:
 - * @buf: the #GstRingBuffer
 + * gst_audio_ring_buffer_open_device:
 + * @buf: the #GstAudioRingBuffer
   *
   * Open the audio device associated with the ring buffer. Does not perform any
   * setup on the device. You must open the device before acquiring the ring
   * MT safe.
   */
  gboolean
 -gst_ring_buffer_open_device (GstRingBuffer * buf)
 +gst_audio_ring_buffer_open_device (GstAudioRingBuffer * buf)
  {
    gboolean res = TRUE;
 -  GstRingBufferClass *rclass;
 +  GstAudioRingBufferClass *rclass;
  
 -  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
 +  g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
  
    GST_DEBUG_OBJECT (buf, "opening device");
  
    /* if this fails, something is wrong in this file */
    g_assert (!buf->acquired);
  
 -  rclass = GST_RING_BUFFER_GET_CLASS (buf);
 +  rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
    if (G_LIKELY (rclass->open_device))
      res = rclass->open_device (buf);
  
@@@ -414,23 -688,23 +416,23 @@@ open_failed
  }
  
  /**
 - * gst_ring_buffer_close_device:
 - * @buf: the #GstRingBuffer
 + * gst_audio_ring_buffer_close_device:
 + * @buf: the #GstAudioRingBuffer
   *
   * Close the audio device associated with the ring buffer. The ring buffer
 - * should already have been released via gst_ring_buffer_release().
 + * should already have been released via gst_audio_ring_buffer_release().
   *
   * Returns: TRUE if the device could be closed, FALSE on error.
   *
   * MT safe.
   */
  gboolean
 -gst_ring_buffer_close_device (GstRingBuffer * buf)
 +gst_audio_ring_buffer_close_device (GstAudioRingBuffer * buf)
  {
    gboolean res = TRUE;
 -  GstRingBufferClass *rclass;
 +  GstAudioRingBufferClass *rclass;
  
 -  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
 +  g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
  
    GST_DEBUG_OBJECT (buf, "closing device");
  
  
    buf->open = FALSE;
  
 -  rclass = GST_RING_BUFFER_GET_CLASS (buf);
 +  rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
    if (G_LIKELY (rclass->close_device))
      res = rclass->close_device (buf);
  
@@@ -481,8 -755,8 +483,8 @@@ close_error
  }
  
  /**
 - * gst_ring_buffer_device_is_open:
 - * @buf: the #GstRingBuffer
 + * gst_audio_ring_buffer_device_is_open:
 + * @buf: the #GstAudioRingBuffer
   *
   * Checks the status of the device associated with the ring buffer.
   *
   * MT safe.
   */
  gboolean
 -gst_ring_buffer_device_is_open (GstRingBuffer * buf)
 +gst_audio_ring_buffer_device_is_open (GstAudioRingBuffer * buf)
  {
    gboolean res = TRUE;
  
 -  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
 +  g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
  
    GST_OBJECT_LOCK (buf);
    res = buf->open;
  }
  
  /**
 - * gst_ring_buffer_acquire:
 - * @buf: the #GstRingBuffer to acquire
 + * gst_audio_ring_buffer_acquire:
 + * @buf: the #GstAudioRingBuffer to acquire
   * @spec: the specs of the buffer
   *
   * Allocate the resources for the ringbuffer. This function fills
   * MT safe.
   */
  gboolean
 -gst_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
 +gst_audio_ring_buffer_acquire (GstAudioRingBuffer * buf,
 +    GstAudioRingBufferSpec * spec)
  {
    gboolean res = FALSE;
 -  GstRingBufferClass *rclass;
 -  gint i, j;
 -  gint segsize, bps;
 +  GstAudioRingBufferClass *rclass;
 +  gint segsize, bpf;
  
 -  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
 +  g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
  
    GST_DEBUG_OBJECT (buf, "acquiring device %p", buf);
  
  
    buf->acquired = TRUE;
  
 -  rclass = GST_RING_BUFFER_GET_CLASS (buf);
 +  rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
    if (G_LIKELY (rclass->acquire))
      res = rclass->acquire (buf, spec);
  
    if (G_UNLIKELY (!res))
      goto acquire_failed;
  
 -  if (G_UNLIKELY ((bps = buf->spec.bytes_per_sample) == 0))
 -    goto invalid_bps;
 +  if (G_UNLIKELY ((bpf = buf->spec.info.bpf) == 0))
 +    goto invalid_bpf;
  
    /* if the seglatency was overwritten with something else than -1, use it, else
     * assume segtotal as the latency */
  
    segsize = buf->spec.segsize;
  
 -  buf->samples_per_seg = segsize / bps;
 +  buf->samples_per_seg = segsize / bpf;
  
    /* create an empty segment */
    g_free (buf->empty_seg);
    buf->empty_seg = g_malloc (segsize);
  
 -  /* FIXME, we only have 32 silence samples, which might not be enough to
 -   * represent silence in all channels */
 -  bps = MIN (bps, 32);
 -  for (i = 0, j = 0; i < segsize; i++) {
 -    buf->empty_seg[i] = buf->spec.silence_sample[j];
 -    j = (j + 1) % bps;
 +  if (buf->spec.type == GST_BUFTYPE_RAW) {
 +    gst_audio_format_fill_silence (buf->spec.info.finfo, buf->empty_seg,
 +        segsize);
 +  } else {
 +    /* FIXME, non-raw formats get 0 as the empty sample */
 +    memset (buf->empty_seg, 0, segsize);
    }
    GST_DEBUG_OBJECT (buf, "acquired device");
  
@@@ -595,10 -869,10 +597,10 @@@ acquire_failed
      GST_DEBUG_OBJECT (buf, "failed to acquire device");
      goto done;
    }
 -invalid_bps:
 +invalid_bpf:
    {
      g_warning
 -        ("invalid bytes_per_sample from acquire ringbuffer %p, fix the element",
 +        ("invalid bytes_per_frame from acquire ringbuffer %p, fix the element",
          buf);
      buf->acquired = FALSE;
      res = FALSE;
  }
  
  /**
 - * gst_ring_buffer_release:
 - * @buf: the #GstRingBuffer to release
 + * gst_audio_ring_buffer_release:
 + * @buf: the #GstAudioRingBuffer to release
   *
   * Free the resources of the ringbuffer.
   *
   * MT safe.
   */
  gboolean
 -gst_ring_buffer_release (GstRingBuffer * buf)
 +gst_audio_ring_buffer_release (GstAudioRingBuffer * buf)
  {
    gboolean res = FALSE;
 -  GstRingBufferClass *rclass;
 +  GstAudioRingBufferClass *rclass;
  
 -  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
 +  g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
  
    GST_DEBUG_OBJECT (buf, "releasing device");
  
 -  gst_ring_buffer_stop (buf);
 +  gst_audio_ring_buffer_stop (buf);
  
    GST_OBJECT_LOCK (buf);
    if (G_UNLIKELY (!buf->acquired))
    /* if this fails, something is wrong in this file */
    g_assert (buf->open == TRUE);
  
 -  rclass = GST_RING_BUFFER_GET_CLASS (buf);
 +  rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
    if (G_LIKELY (rclass->release))
      res = rclass->release (buf);
  
    /* signal any waiters */
    GST_DEBUG_OBJECT (buf, "signal waiter");
 -  GST_RING_BUFFER_SIGNAL (buf);
 +  GST_AUDIO_RING_BUFFER_SIGNAL (buf);
  
    if (G_UNLIKELY (!res))
      goto release_failed;
@@@ -673,8 -947,8 +675,8 @@@ release_failed
  }
  
  /**
 - * gst_ring_buffer_is_acquired:
 - * @buf: the #GstRingBuffer to check
 + * gst_audio_ring_buffer_is_acquired:
 + * @buf: the #GstAudioRingBuffer to check
   *
   * Check if the ringbuffer is acquired and ready to use.
   *
   * MT safe.
   */
  gboolean
 -gst_ring_buffer_is_acquired (GstRingBuffer * buf)
 +gst_audio_ring_buffer_is_acquired (GstAudioRingBuffer * buf)
  {
    gboolean res;
  
 -  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
 +  g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
  
    GST_OBJECT_LOCK (buf);
    res = buf->acquired;
  }
  
  /**
 - * gst_ring_buffer_activate:
 - * @buf: the #GstRingBuffer to activate
 + * gst_audio_ring_buffer_activate:
 + * @buf: the #GstAudioRingBuffer to activate
   * @active: the new mode
   *
   * Activate @buf to start or stop pulling data.
   * Since: 0.10.22.
   */
  gboolean
 -gst_ring_buffer_activate (GstRingBuffer * buf, gboolean active)
 +gst_audio_ring_buffer_activate (GstAudioRingBuffer * buf, gboolean active)
  {
    gboolean res = FALSE;
 -  GstRingBufferClass *rclass;
 +  GstAudioRingBufferClass *rclass;
  
 -  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
 +  g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
  
    GST_DEBUG_OBJECT (buf, "activate device");
  
    if (G_UNLIKELY (active && !buf->acquired))
      goto not_acquired;
  
 -  if (G_UNLIKELY (buf->abidata.ABI.active == active))
 +  if (G_UNLIKELY (buf->active == active))
      goto was_active;
  
 -  rclass = GST_RING_BUFFER_GET_CLASS (buf);
 +  rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
    /* if there is no activate function we assume it was started/released
     * in the acquire method */
    if (G_LIKELY (rclass->activate))
    if (G_UNLIKELY (!res))
      goto activate_failed;
  
 -  buf->abidata.ABI.active = active;
 +  buf->active = active;
  
  done:
    GST_OBJECT_UNLOCK (buf);
@@@ -767,8 -1041,8 +769,8 @@@ activate_failed
  }
  
  /**
 - * gst_ring_buffer_is_active:
 - * @buf: the #GstRingBuffer
 + * gst_audio_ring_buffer_is_active:
 + * @buf: the #GstAudioRingBuffer
   *
   * Check if @buf is activated.
   *
   * Since: 0.10.22.
   */
  gboolean
 -gst_ring_buffer_is_active (GstRingBuffer * buf)
 +gst_audio_ring_buffer_is_active (GstAudioRingBuffer * buf)
  {
    gboolean res;
  
 -  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
 +  g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
  
    GST_OBJECT_LOCK (buf);
 -  res = buf->abidata.ABI.active;
 +  res = buf->active;
    GST_OBJECT_UNLOCK (buf);
  
    return res;
  
  
  /**
 - * gst_ring_buffer_set_flushing:
 - * @buf: the #GstRingBuffer to flush
 + * gst_audio_ring_buffer_set_flushing:
 + * @buf: the #GstAudioRingBuffer to flush
   * @flushing: the new mode
   *
   * Set the ringbuffer to flushing mode or normal mode.
   * MT safe.
   */
  void
 -gst_ring_buffer_set_flushing (GstRingBuffer * buf, gboolean flushing)
 +gst_audio_ring_buffer_set_flushing (GstAudioRingBuffer * buf, gboolean flushing)
  {
 -  g_return_if_fail (GST_IS_RING_BUFFER (buf));
 +  g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
  
    GST_OBJECT_LOCK (buf);
 -  buf->abidata.ABI.flushing = flushing;
 +  buf->flushing = flushing;
  
    if (flushing) {
 -    gst_ring_buffer_pause_unlocked (buf);
 +    gst_audio_ring_buffer_pause_unlocked (buf);
    } else {
 -    gst_ring_buffer_clear_all (buf);
 +    gst_audio_ring_buffer_clear_all (buf);
    }
    GST_OBJECT_UNLOCK (buf);
  }
  
  /**
 - * gst_ring_buffer_start:
 - * @buf: the #GstRingBuffer to start
 + * gst_audio_ring_buffer_start:
 + * @buf: the #GstAudioRingBuffer to start
   *
   * Start processing samples from the ringbuffer.
   *
   * MT safe.
   */
  gboolean
 -gst_ring_buffer_start (GstRingBuffer * buf)
 +gst_audio_ring_buffer_start (GstAudioRingBuffer * buf)
  {
    gboolean res = FALSE;
 -  GstRingBufferClass *rclass;
 +  GstAudioRingBufferClass *rclass;
    gboolean resume = FALSE;
  
 -  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
 +  g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
  
    GST_DEBUG_OBJECT (buf, "starting ringbuffer");
  
    GST_OBJECT_LOCK (buf);
 -  if (G_UNLIKELY (buf->abidata.ABI.flushing))
 +  if (G_UNLIKELY (buf->flushing))
      goto flushing;
  
    if (G_UNLIKELY (!buf->acquired))
      goto not_acquired;
  
 -  if (G_UNLIKELY (g_atomic_int_get (&buf->abidata.ABI.may_start) == FALSE))
 +  if (G_UNLIKELY (g_atomic_int_get (&buf->may_start) == FALSE))
      goto may_not_start;
  
    /* if stopped, set to started */
    res = g_atomic_int_compare_and_exchange (&buf->state,
 -      GST_RING_BUFFER_STATE_STOPPED, GST_RING_BUFFER_STATE_STARTED);
 +      GST_AUDIO_RING_BUFFER_STATE_STOPPED, GST_AUDIO_RING_BUFFER_STATE_STARTED);
  
    if (!res) {
      GST_DEBUG_OBJECT (buf, "was not stopped, try paused");
      /* was not stopped, try from paused */
      res = g_atomic_int_compare_and_exchange (&buf->state,
 -        GST_RING_BUFFER_STATE_PAUSED, GST_RING_BUFFER_STATE_STARTED);
 +        GST_AUDIO_RING_BUFFER_STATE_PAUSED,
 +        GST_AUDIO_RING_BUFFER_STATE_STARTED);
      if (!res) {
        /* was not paused either, must be started then */
        res = TRUE;
      GST_DEBUG_OBJECT (buf, "resuming");
    }
  
 -  rclass = GST_RING_BUFFER_GET_CLASS (buf);
 +  rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
    if (resume) {
      if (G_LIKELY (rclass->resume))
        res = rclass->resume (buf);
    }
  
    if (G_UNLIKELY (!res)) {
 -    buf->state = GST_RING_BUFFER_STATE_PAUSED;
 +    buf->state = GST_AUDIO_RING_BUFFER_STATE_PAUSED;
      GST_DEBUG_OBJECT (buf, "failed to start");
    } else {
      GST_DEBUG_OBJECT (buf, "started");
@@@ -911,30 -1184,30 +913,30 @@@ may_not_start
  }
  
  static gboolean
 -gst_ring_buffer_pause_unlocked (GstRingBuffer * buf)
 +gst_audio_ring_buffer_pause_unlocked (GstAudioRingBuffer * buf)
  {
    gboolean res = FALSE;
 -  GstRingBufferClass *rclass;
 +  GstAudioRingBufferClass *rclass;
  
    GST_DEBUG_OBJECT (buf, "pausing ringbuffer");
  
    /* if started, set to paused */
    res = g_atomic_int_compare_and_exchange (&buf->state,
 -      GST_RING_BUFFER_STATE_STARTED, GST_RING_BUFFER_STATE_PAUSED);
 +      GST_AUDIO_RING_BUFFER_STATE_STARTED, GST_AUDIO_RING_BUFFER_STATE_PAUSED);
  
    if (!res)
      goto not_started;
  
    /* signal any waiters */
    GST_DEBUG_OBJECT (buf, "signal waiter");
 -  GST_RING_BUFFER_SIGNAL (buf);
 +  GST_AUDIO_RING_BUFFER_SIGNAL (buf);
  
 -  rclass = GST_RING_BUFFER_GET_CLASS (buf);
 +  rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
    if (G_LIKELY (rclass->pause))
      res = rclass->pause (buf);
  
    if (G_UNLIKELY (!res)) {
 -    buf->state = GST_RING_BUFFER_STATE_STARTED;
 +    buf->state = GST_AUDIO_RING_BUFFER_STATE_STARTED;
      GST_DEBUG_OBJECT (buf, "failed to pause");
    } else {
      GST_DEBUG_OBJECT (buf, "paused");
@@@ -951,8 -1224,8 +953,8 @@@ not_started
  }
  
  /**
 - * gst_ring_buffer_pause:
 - * @buf: the #GstRingBuffer to pause
 + * gst_audio_ring_buffer_pause:
 + * @buf: the #GstAudioRingBuffer to pause
   *
   * Pause processing samples from the ringbuffer.
   *
   * MT safe.
   */
  gboolean
 -gst_ring_buffer_pause (GstRingBuffer * buf)
 +gst_audio_ring_buffer_pause (GstAudioRingBuffer * buf)
  {
    gboolean res = FALSE;
  
 -  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
 +  g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
  
    GST_OBJECT_LOCK (buf);
 -  if (G_UNLIKELY (buf->abidata.ABI.flushing))
 +  if (G_UNLIKELY (buf->flushing))
      goto flushing;
  
    if (G_UNLIKELY (!buf->acquired))
      goto not_acquired;
  
 -  res = gst_ring_buffer_pause_unlocked (buf);
 +  res = gst_audio_ring_buffer_pause_unlocked (buf);
    GST_OBJECT_UNLOCK (buf);
  
    return res;
@@@ -995,8 -1268,8 +997,8 @@@ not_acquired
  }
  
  /**
 - * gst_ring_buffer_stop:
 - * @buf: the #GstRingBuffer to stop
 + * gst_audio_ring_buffer_stop:
 + * @buf: the #GstAudioRingBuffer to stop
   *
   * Stop processing samples from the ringbuffer.
   *
   * MT safe.
   */
  gboolean
 -gst_ring_buffer_stop (GstRingBuffer * buf)
 +gst_audio_ring_buffer_stop (GstAudioRingBuffer * buf)
  {
    gboolean res = FALSE;
 -  GstRingBufferClass *rclass;
 +  GstAudioRingBufferClass *rclass;
  
 -  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
 +  g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
  
    GST_DEBUG_OBJECT (buf, "stopping");
  
  
    /* if started, set to stopped */
    res = g_atomic_int_compare_and_exchange (&buf->state,
 -      GST_RING_BUFFER_STATE_STARTED, GST_RING_BUFFER_STATE_STOPPED);
 +      GST_AUDIO_RING_BUFFER_STATE_STARTED, GST_AUDIO_RING_BUFFER_STATE_STOPPED);
  
    if (!res) {
      GST_DEBUG_OBJECT (buf, "was not started, try paused");
      /* was not started, try from paused */
      res = g_atomic_int_compare_and_exchange (&buf->state,
 -        GST_RING_BUFFER_STATE_PAUSED, GST_RING_BUFFER_STATE_STOPPED);
 +        GST_AUDIO_RING_BUFFER_STATE_PAUSED,
 +        GST_AUDIO_RING_BUFFER_STATE_STOPPED);
      if (!res) {
        /* was not paused either, must have been stopped then */
        res = TRUE;
  
    /* signal any waiters */
    GST_DEBUG_OBJECT (buf, "signal waiter");
 -  GST_RING_BUFFER_SIGNAL (buf);
 +  GST_AUDIO_RING_BUFFER_SIGNAL (buf);
  
 -  rclass = GST_RING_BUFFER_GET_CLASS (buf);
 +  rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
    if (G_LIKELY (rclass->stop))
      res = rclass->stop (buf);
  
    if (G_UNLIKELY (!res)) {
 -    buf->state = GST_RING_BUFFER_STATE_STARTED;
 +    buf->state = GST_AUDIO_RING_BUFFER_STATE_STARTED;
      GST_DEBUG_OBJECT (buf, "failed to stop");
    } else {
      GST_DEBUG_OBJECT (buf, "stopped");
@@@ -1055,8 -1327,8 +1057,8 @@@ done
  }
  
  /**
 - * gst_ring_buffer_delay:
 - * @buf: the #GstRingBuffer to query
 + * gst_audio_ring_buffer_delay:
 + * @buf: the #GstAudioRingBuffer to query
   *
   * Get the number of samples queued in the audio device. This is
   * usually less than the segment size but can be bigger when the
   * MT safe.
   */
  guint
 -gst_ring_buffer_delay (GstRingBuffer * buf)
 +gst_audio_ring_buffer_delay (GstAudioRingBuffer * buf)
  {
 -  GstRingBufferClass *rclass;
 +  GstAudioRingBufferClass *rclass;
    guint res;
  
 -  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), 0);
 +  g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), 0);
  
    /* buffer must be acquired */
 -  if (G_UNLIKELY (!gst_ring_buffer_is_acquired (buf)))
 +  if (G_UNLIKELY (!gst_audio_ring_buffer_is_acquired (buf)))
      goto not_acquired;
  
 -  rclass = GST_RING_BUFFER_GET_CLASS (buf);
 +  rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
    if (G_LIKELY (rclass->delay))
      res = rclass->delay (buf);
    else
@@@ -1101,24 -1373,24 +1103,24 @@@ not_acquired
  }
  
  /**
 - * gst_ring_buffer_samples_done:
 - * @buf: the #GstRingBuffer to query
 + * gst_audio_ring_buffer_samples_done:
 + * @buf: the #GstAudioRingBuffer to query
   *
   * Get the number of samples that were processed by the ringbuffer
   * since it was last started. This does not include the number of samples not
 - * yet processed (see gst_ring_buffer_delay()).
 + * yet processed (see gst_audio_ring_buffer_delay()).
   *
   * Returns: The number of samples processed by the ringbuffer.
   *
   * MT safe.
   */
  guint64
 -gst_ring_buffer_samples_done (GstRingBuffer * buf)
 +gst_audio_ring_buffer_samples_done (GstAudioRingBuffer * buf)
  {
    gint segdone;
    guint64 samples;
  
 -  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), 0);
 +  g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), 0);
  
    /* get the amount of segments we processed */
    segdone = g_atomic_int_get (&buf->segdone);
  }
  
  /**
 - * gst_ring_buffer_set_sample:
 - * @buf: the #GstRingBuffer to use
 + * gst_audio_ring_buffer_set_sample:
 + * @buf: the #GstAudioRingBuffer to use
   * @sample: the sample number to set
   *
   * Make sure that the next sample written to the device is
   * MT safe.
   */
  void
 -gst_ring_buffer_set_sample (GstRingBuffer * buf, guint64 sample)
 +gst_audio_ring_buffer_set_sample (GstAudioRingBuffer * buf, guint64 sample)
  {
 -  g_return_if_fail (GST_IS_RING_BUFFER (buf));
 +  g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
  
    if (sample == -1)
      sample = 0;
     * offset when calculating the processed samples. */
    buf->segbase = buf->segdone - sample / buf->samples_per_seg;
  
 -  gst_ring_buffer_clear_all (buf);
 +  gst_audio_ring_buffer_clear_all (buf);
  
    GST_DEBUG_OBJECT (buf, "set sample to %" G_GUINT64_FORMAT ", segbase %d",
        sample, buf->segbase);
  }
  
  static void
 -default_clear_all (GstRingBuffer * buf)
 +default_clear_all (GstAudioRingBuffer * buf)
  {
    gint i;
  
    GST_DEBUG_OBJECT (buf, "clear all segments");
  
    for (i = 0; i < buf->spec.segtotal; i++) {
 -    gst_ring_buffer_clear (buf, i);
 +    gst_audio_ring_buffer_clear (buf, i);
    }
  }
  
  /**
 - * gst_ring_buffer_clear_all:
 - * @buf: the #GstRingBuffer to clear
 + * gst_audio_ring_buffer_clear_all:
 + * @buf: the #GstAudioRingBuffer to clear
   *
   * Fill the ringbuffer with silence.
   *
   * MT safe.
   */
  void
 -gst_ring_buffer_clear_all (GstRingBuffer * buf)
 +gst_audio_ring_buffer_clear_all (GstAudioRingBuffer * buf)
  {
 -  GstRingBufferClass *rclass;
 +  GstAudioRingBufferClass *rclass;
  
 -  g_return_if_fail (GST_IS_RING_BUFFER (buf));
 +  g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
  
 -  rclass = GST_RING_BUFFER_GET_CLASS (buf);
 +  rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
  
    if (G_LIKELY (rclass->clear_all))
      rclass->clear_all (buf);
  
  
  static gboolean
 -wait_segment (GstRingBuffer * buf)
 +wait_segment (GstAudioRingBuffer * buf)
  {
    gint segments;
    gboolean wait = TRUE;
  
    /* buffer must be started now or we deadlock since nobody is reading */
    if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
 -          GST_RING_BUFFER_STATE_STARTED)) {
 +          GST_AUDIO_RING_BUFFER_STATE_STARTED)) {
      /* see if we are allowed to start it */
 -    if (G_UNLIKELY (g_atomic_int_get (&buf->abidata.ABI.may_start) == FALSE))
 +    if (G_UNLIKELY (g_atomic_int_get (&buf->may_start) == FALSE))
        goto no_start;
  
      GST_DEBUG_OBJECT (buf, "start!");
      segments = g_atomic_int_get (&buf->segdone);
 -    gst_ring_buffer_start (buf);
 +    gst_audio_ring_buffer_start (buf);
  
      /* After starting, the writer may have wrote segments already and then we
       * don't need to wait anymore */
  
    /* take lock first, then update our waiting flag */
    GST_OBJECT_LOCK (buf);
 -  if (G_UNLIKELY (buf->abidata.ABI.flushing))
 +  if (G_UNLIKELY (buf->flushing))
      goto flushing;
  
    if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
 -          GST_RING_BUFFER_STATE_STARTED))
 +          GST_AUDIO_RING_BUFFER_STATE_STARTED))
      goto not_started;
  
    if (G_LIKELY (wait)) {
      if (g_atomic_int_compare_and_exchange (&buf->waiting, 0, 1)) {
        GST_DEBUG_OBJECT (buf, "waiting..");
 -      GST_RING_BUFFER_WAIT (buf);
 +      GST_AUDIO_RING_BUFFER_WAIT (buf);
  
 -      if (G_UNLIKELY (buf->abidata.ABI.flushing))
 +      if (G_UNLIKELY (buf->flushing))
          goto flushing;
  
        if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
 -              GST_RING_BUFFER_STATE_STARTED))
 +              GST_AUDIO_RING_BUFFER_STATE_STARTED))
          goto not_started;
      }
    }
@@@ -1277,12 -1549,12 +1279,12 @@@ no_start
  #define FWD_SAMPLES(s,se,d,de)                        \
  G_STMT_START {                                        \
    /* no rate conversion */                    \
 -  guint towrite = MIN (se + bps - s, de - d); \
 +  guint towrite = MIN (se + bpf - s, de - d); \
    /* simple copy */                           \
    if (!skip)                                  \
      memcpy (d, s, towrite);                   \
 -  in_samples -= towrite / bps;                        \
 -  out_samples -= towrite / bps;                       \
 +  in_samples -= towrite / bpf;                        \
 +  out_samples -= towrite / bpf;                       \
    s += towrite;                                       \
    GST_DEBUG ("copy %u bytes", towrite);               \
  } G_STMT_END
@@@ -1293,16 -1565,16 +1295,16 @@@ G_STMT_START {                                       
    guint8 *sb = s, *db = d;                    \
    while (s <= se && d < de) {                 \
      if (!skip)                                        \
 -      memcpy (d, s, bps);                     \
 -    s += bps;                                 \
 +      memcpy (d, s, bpf);                     \
 +    s += bpf;                                 \
      *accum += outr;                           \
      if ((*accum << 1) >= inr) {                       \
        *accum -= inr;                          \
 -      d += bps;                                       \
 +      d += bpf;                                       \
      }                                         \
    }                                           \
 -  in_samples -= (s - sb)/bps;                 \
 -  out_samples -= (d - db)/bps;                        \
 +  in_samples -= (s - sb)/bpf;                 \
 +  out_samples -= (d - db)/bpf;                        \
    GST_DEBUG ("fwd_up end %d/%d",*accum,*toprocess);   \
  } G_STMT_END
  
@@@ -1312,16 -1584,16 +1314,16 @@@ G_STMT_START {                                       
    guint8 *sb = s, *db = d;                    \
    while (s <= se && d < de) {                 \
      if (!skip)                                        \
 -      memcpy (d, s, bps);                     \
 -    d += bps;                                 \
 +      memcpy (d, s, bpf);                     \
 +    d += bpf;                                 \
      *accum += inr;                            \
      if ((*accum << 1) >= outr) {              \
        *accum -= outr;                         \
 -      s += bps;                                       \
 +      s += bpf;                                       \
      }                                         \
    }                                           \
 -  in_samples -= (s - sb)/bps;                 \
 -  out_samples -= (d - db)/bps;                        \
 +  in_samples -= (s - sb)/bpf;                 \
 +  out_samples -= (d - db)/bpf;                        \
    GST_DEBUG ("fwd_down end %d/%d",*accum,*toprocess); \
  } G_STMT_END
  
@@@ -1330,16 -1602,16 +1332,16 @@@ G_STMT_START {                                       
    guint8 *sb = se, *db = d;                   \
    while (s <= se && d < de) {                 \
      if (!skip)                                        \
 -      memcpy (d, se, bps);                    \
 -    se -= bps;                                        \
 +      memcpy (d, se, bpf);                    \
 +    se -= bpf;                                        \
      *accum += outr;                           \
      while (d < de && (*accum << 1) >= inr) {  \
        *accum -= inr;                          \
 -      d += bps;                                       \
 +      d += bpf;                                       \
      }                                         \
    }                                           \
 -  in_samples -= (sb - se)/bps;                        \
 -  out_samples -= (d - db)/bps;                        \
 +  in_samples -= (sb - se)/bpf;                        \
 +  out_samples -= (d - db)/bpf;                        \
    GST_DEBUG ("rev_up end %d/%d",*accum,*toprocess);   \
  } G_STMT_END
  
@@@ -1348,38 -1620,38 +1350,38 @@@ G_STMT_START {                                       
    guint8 *sb = se, *db = d;                   \
    while (s <= se && d < de) {                 \
      if (!skip)                                        \
 -      memcpy (d, se, bps);                    \
 -    d += bps;                                 \
 +      memcpy (d, se, bpf);                    \
 +    d += bpf;                                 \
      *accum += inr;                            \
      while (s <= se && (*accum << 1) >= outr) {        \
        *accum -= outr;                         \
 -      se -= bps;                              \
 +      se -= bpf;                              \
      }                                         \
    }                                           \
 -  in_samples -= (sb - se)/bps;                        \
 -  out_samples -= (d - db)/bps;                        \
 +  in_samples -= (sb - se)/bpf;                        \
 +  out_samples -= (d - db)/bpf;                        \
    GST_DEBUG ("rev_down end %d/%d",*accum,*toprocess); \
  } G_STMT_END
  
  static guint
 -default_commit (GstRingBuffer * buf, guint64 * sample,
 +default_commit (GstAudioRingBuffer * buf, guint64 * sample,
      guchar * data, gint in_samples, gint out_samples, gint * accum)
  {
    gint segdone;
 -  gint segsize, segtotal, bps, sps;
 +  gint segsize, segtotal, bpf, sps;
    guint8 *dest, *data_end;
    gint writeseg, sampleoff;
    gint *toprocess;
    gint inr, outr;
    gboolean reverse;
  
 -  g_return_val_if_fail (buf->data != NULL, -1);
 +  g_return_val_if_fail (buf->memory != NULL, -1);
    g_return_val_if_fail (data != NULL, -1);
  
 -  dest = GST_BUFFER_DATA (buf->data);
 +  dest = buf->memory;
    segsize = buf->spec.segsize;
    segtotal = buf->spec.segtotal;
 -  bps = buf->spec.bytes_per_sample;
 +  bpf = buf->spec.info.bpf;
    sps = buf->samples_per_seg;
  
    reverse = out_samples < 0;
  
    /* data_end points to the last sample we have to write, not past it. This is
     * needed to properly handle reverse playback: it points to the last sample. */
 -  data_end = data + (bps * inr);
 +  data_end = data + (bpf * inr);
  
    /* figure out the segment and the offset inside the segment where
     * the first sample should be written. */
    writeseg = *sample / sps;
 -  sampleoff = (*sample % sps) * bps;
 +  sampleoff = (*sample % sps) * bpf;
  
    /* write out all samples */
    while (*toprocess > 0) {
  
      /* we can write now */
      ws = writeseg % segtotal;
 -    avail = MIN (segsize - sampleoff, bps * out_samples);
 +    avail = MIN (segsize - sampleoff, bpf * out_samples);
  
      d = dest + (ws * segsize) + sampleoff;
      d_end = d + avail;
 -    *sample += avail / bps;
 +    *sample += avail / bpf;
  
      GST_DEBUG_OBJECT (buf, "write @%p seg %d, sps %d, off %d, avail %d",
          dest + ws * segsize, ws, sps, sampleoff, avail);
      sampleoff = 0;
    }
    /* we consumed all samples here */
 -  data = data_end + bps;
 +  data = data_end + bpf;
  
  done:
 -  return inr - ((data_end - data) / bps);
 +  return inr - ((data_end - data) / bpf);
  
    /* ERRORS */
  not_started:
  }
  
  /**
 - * gst_ring_buffer_commit_full:
 - * @buf: the #GstRingBuffer to commit
 + * gst_audio_ring_buffer_commit:
 + * @buf: the #GstAudioRingBuffer to commit
   * @sample: the sample position of the data
   * @data: the data to commit
   * @in_samples: the number of samples in the data to commit
   * @out_samples: the number of samples to write to the ringbuffer
   * @accum: accumulator for rate conversion.
   *
 - * Commit @in_samples samples pointed to by @data to the ringbuffer @buf. 
 + * Commit @in_samples samples pointed to by @data to the ringbuffer @buf.
   *
   * @in_samples and @out_samples define the rate conversion to perform on the
   * samples in @data. For negative rates, @out_samples must be negative and
   * @sample in reverse order.
   *
   * @out_samples does not need to be a multiple of the segment size of the ringbuffer
 - * although it is recommended for optimal performance. 
 + * although it is recommended for optimal performance.
   *
   * @accum will hold a temporary accumulator used in rate conversion and should be
   * set to 0 when this function is first called. In case the commit operation is
   * Since: 0.10.11.
   */
  guint
 -gst_ring_buffer_commit_full (GstRingBuffer * buf, guint64 * sample,
 +gst_audio_ring_buffer_commit (GstAudioRingBuffer * buf, guint64 * sample,
      guchar * data, gint in_samples, gint out_samples, gint * accum)
  {
 -  GstRingBufferClass *rclass;
 +  GstAudioRingBufferClass *rclass;
    guint res = -1;
  
 -  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), -1);
 +  g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), -1);
  
    if (G_UNLIKELY (in_samples == 0 || out_samples == 0))
      return in_samples;
  
 -  rclass = GST_RING_BUFFER_GET_CLASS (buf);
 +  rclass = GST_AUDIO_RING_BUFFER_GET_CLASS (buf);
  
    if (G_LIKELY (rclass->commit))
      res = rclass->commit (buf, sample, data, in_samples, out_samples, accum);
  }
  
  /**
 - * gst_ring_buffer_commit:
 - * @buf: the #GstRingBuffer to commit
 - * @sample: the sample position of the data
 - * @data: the data to commit
 - * @len: the number of samples in the data to commit
 - *
 - * Same as gst_ring_buffer_commit_full() but with a in_samples and out_samples
 - * equal to @len, ignoring accum.
 - *
 - * Returns: The number of samples written to the ringbuffer or -1 on
 - * error.
 - *
 - * MT safe.
 - */
 -guint
 -gst_ring_buffer_commit (GstRingBuffer * buf, guint64 sample, guchar * data,
 -    guint len)
 -{
 -  guint res;
 -  guint64 samplep = sample;
 -
 -  res = gst_ring_buffer_commit_full (buf, &samplep, data, len, len, NULL);
 -
 -  return res;
 -}
 -
 -/**
 - * gst_ring_buffer_read:
 - * @buf: the #GstRingBuffer to read from
 + * gst_audio_ring_buffer_read:
 + * @buf: the #GstAudioRingBuffer to read from
   * @sample: the sample position of the data
   * @data: where the data should be read
   * @len: the number of samples in data to read
   * MT safe.
   */
  guint
 -gst_ring_buffer_read (GstRingBuffer * buf, guint64 sample, guchar * data,
 -    guint len)
 +gst_audio_ring_buffer_read (GstAudioRingBuffer * buf, guint64 sample,
 +    guchar * data, guint len)
  {
    gint segdone;
 -  gint segsize, segtotal, bps, sps;
 +  gint segsize, segtotal, bpf, sps;
    guint8 *dest;
    guint to_read;
  
 -  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), -1);
 -  g_return_val_if_fail (buf->data != NULL, -1);
 +  g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), -1);
 +  g_return_val_if_fail (buf->memory != NULL, -1);
    g_return_val_if_fail (data != NULL, -1);
  
 -  dest = GST_BUFFER_DATA (buf->data);
 +  dest = buf->memory;
    segsize = buf->spec.segsize;
    segtotal = buf->spec.segtotal;
 -  bps = buf->spec.bytes_per_sample;
 +  bpf = buf->spec.info.bpf;
    sps = buf->samples_per_seg;
  
    to_read = len;
        if (G_UNLIKELY (diff >= segtotal)) {
          /* pretend we read an empty segment. */
          sampleslen = MIN (sps, to_read);
 -        memcpy (data, buf->empty_seg, sampleslen * bps);
 +        memcpy (data, buf->empty_seg, sampleslen * bpf);
          goto next;
        }
  
      GST_DEBUG_OBJECT (buf, "read @%p seg %d, off %d, sampleslen %d",
          dest + readseg * segsize, readseg, sampleoff, sampleslen);
  
 -    memcpy (data, dest + (readseg * segsize) + (sampleoff * bps),
 -        (sampleslen * bps));
 +    memcpy (data, dest + (readseg * segsize) + (sampleoff * bpf),
 +        (sampleslen * bpf));
  
    next:
      to_read -= sampleslen;
      sample += sampleslen;
 -    data += sampleslen * bps;
 +    data += sampleslen * bpf;
    }
  
    return len - to_read;
@@@ -1657,8 -1956,8 +1659,8 @@@ not_started
  }
  
  /**
 - * gst_ring_buffer_prepare_read:
 - * @buf: the #GstRingBuffer to read from
 + * gst_audio_ring_buffer_prepare_read:
 + * @buf: the #GstAudioRingBuffer to read from
   * @segment: the segment to read
   * @readptr: the pointer to the memory where samples can be read
   * @len: the number of bytes to read
   * MT safe.
   */
  gboolean
 -gst_ring_buffer_prepare_read (GstRingBuffer * buf, gint * segment,
 +gst_audio_ring_buffer_prepare_read (GstAudioRingBuffer * buf, gint * segment,
      guint8 ** readptr, gint * len)
  {
    guint8 *data;
    gint segdone;
  
 -  g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
 +  g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
  
    if (buf->callback == NULL) {
      /* push mode, fail when nothing is started */
 -    if (g_atomic_int_get (&buf->state) != GST_RING_BUFFER_STATE_STARTED)
 +    if (g_atomic_int_get (&buf->state) != GST_AUDIO_RING_BUFFER_STATE_STARTED)
        return FALSE;
    }
  
 -  g_return_val_if_fail (buf->data != NULL, FALSE);
 +  g_return_val_if_fail (buf->memory != NULL, FALSE);
    g_return_val_if_fail (segment != NULL, FALSE);
    g_return_val_if_fail (readptr != NULL, FALSE);
    g_return_val_if_fail (len != NULL, FALSE);
  
 -  data = GST_BUFFER_DATA (buf->data);
 +  data = buf->memory;
  
    /* get the position of the pointer */
    segdone = g_atomic_int_get (&buf->segdone);
  }
  
  /**
 - * gst_ring_buffer_advance:
 - * @buf: the #GstRingBuffer to advance
 + * gst_audio_ring_buffer_advance:
 + * @buf: the #GstAudioRingBuffer to advance
   * @advance: the number of segments written
   *
   * Subclasses should call this function to notify the fact that 
   * MT safe.
   */
  void
 -gst_ring_buffer_advance (GstRingBuffer * buf, guint advance)
 +gst_audio_ring_buffer_advance (GstAudioRingBuffer * buf, guint advance)
  {
 -  g_return_if_fail (GST_IS_RING_BUFFER (buf));
 +  g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
  
    /* update counter */
    g_atomic_int_add (&buf->segdone, advance);
    if (g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0)) {
      GST_OBJECT_LOCK (buf);
      GST_DEBUG_OBJECT (buf, "signal waiter");
 -    GST_RING_BUFFER_SIGNAL (buf);
 +    GST_AUDIO_RING_BUFFER_SIGNAL (buf);
      GST_OBJECT_UNLOCK (buf);
    }
  }
  
  /**
 - * gst_ring_buffer_clear:
 - * @buf: the #GstRingBuffer to clear
 + * gst_audio_ring_buffer_clear:
 + * @buf: the #GstAudioRingBuffer to clear
   * @segment: the segment to clear
   *
   * Clear the given segment of the buffer with silence samples.
   * MT safe.
   */
  void
 -gst_ring_buffer_clear (GstRingBuffer * buf, gint segment)
 +gst_audio_ring_buffer_clear (GstAudioRingBuffer * buf, gint segment)
  {
    guint8 *data;
  
 -  g_return_if_fail (GST_IS_RING_BUFFER (buf));
 +  g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
  
    /* no data means it's already cleared */
 -  if (G_UNLIKELY (buf->data == NULL))
 +  if (G_UNLIKELY (buf->memory == NULL))
      return;
  
    /* no empty_seg means it's not opened */
  
    segment %= buf->spec.segtotal;
  
 -  data = GST_BUFFER_DATA (buf->data);
 +  data = buf->memory;
    data += segment * buf->spec.segsize;
  
    GST_LOG ("clear segment %d @%p", segment, data);
  }
  
  /**
 - * gst_ring_buffer_may_start:
 - * @buf: the #GstRingBuffer
 + * gst_audio_ring_buffer_may_start:
 + * @buf: the #GstAudioRingBuffer
   * @allowed: the new value
   *
   * Tell the ringbuffer that it is allowed to start playback when
   * Since: 0.10.6
   */
  void
 -gst_ring_buffer_may_start (GstRingBuffer * buf, gboolean allowed)
 +gst_audio_ring_buffer_may_start (GstAudioRingBuffer * buf, gboolean allowed)
  {
 -  g_return_if_fail (GST_IS_RING_BUFFER (buf));
 +  g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
  
    GST_LOG_OBJECT (buf, "may start: %d", allowed);
 -  g_atomic_int_set (&buf->abidata.ABI.may_start, allowed);
 +  g_atomic_int_set (&buf->may_start, allowed);
  }
@@@ -23,7 -23,7 +23,7 @@@
  /**
   * SECTION:gstaudiosink
   * @short_description: Simple base class for audio sinks
 - * @see_also: #GstBaseAudioSink, #GstRingBuffer, #GstAudioSink.
 + * @see_also: #GstAudioBaseSink, #GstAudioRingBuffer, #GstAudioSink.
   *
   * This is the most simple base class for audio sinks that only requires
   * subclasses to implement a set of simple functions:
@@@ -61,8 -61,8 +61,8 @@@
   * </variablelist>
   *
   * All scheduling of samples and timestamps is done in this base class
 - * together with #GstBaseAudioSink using a default implementation of a
 - * #GstRingBuffer that uses threads.
 + * together with #GstAudioBaseSink using a default implementation of a
 + * #GstAudioRingBuffer that uses threads.
   *
   * Last reviewed on 2006-09-27 (0.10.12)
   */
  
  #include "gstaudiosink.h"
  
+ #include "gst/glib-compat-private.h"
  GST_DEBUG_CATEGORY_STATIC (gst_audio_sink_debug);
  #define GST_CAT_DEFAULT gst_audio_sink_debug
  
 -#define GST_TYPE_AUDIORING_BUFFER        \
 -        (gst_audioringbuffer_get_type())
 -#define GST_AUDIORING_BUFFER(obj)        \
 -        (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIORING_BUFFER,GstAudioRingBuffer))
 -#define GST_AUDIORING_BUFFER_CLASS(klass) \
 -        (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIORING_BUFFER,GstAudioRingBufferClass))
 -#define GST_AUDIORING_BUFFER_GET_CLASS(obj) \
 -        (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AUDIORING_BUFFER, GstAudioRingBufferClass))
 -#define GST_AUDIORING_BUFFER_CAST(obj)        \
 -        ((GstAudioRingBuffer *)obj)
 -#define GST_IS_AUDIORING_BUFFER(obj)     \
 -        (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIORING_BUFFER))
 -#define GST_IS_AUDIORING_BUFFER_CLASS(klass)\
 -        (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIORING_BUFFER))
 -
 -typedef struct _GstAudioRingBuffer GstAudioRingBuffer;
 -typedef struct _GstAudioRingBufferClass GstAudioRingBufferClass;
 -
 -#define GST_AUDIORING_BUFFER_GET_COND(buf) (((GstAudioRingBuffer *)buf)->cond)
 -#define GST_AUDIORING_BUFFER_WAIT(buf)     (g_cond_wait (GST_AUDIORING_BUFFER_GET_COND (buf), GST_OBJECT_GET_LOCK (buf)))
 -#define GST_AUDIORING_BUFFER_SIGNAL(buf)   (g_cond_signal (GST_AUDIORING_BUFFER_GET_COND (buf)))
 -#define GST_AUDIORING_BUFFER_BROADCAST(buf)(g_cond_broadcast (GST_AUDIORING_BUFFER_GET_COND (buf)))
 -
 -struct _GstAudioRingBuffer
 +#define GST_TYPE_AUDIO_SINK_RING_BUFFER        \
 +        (gst_audio_sink_ring_buffer_get_type())
 +#define GST_AUDIO_SINK_RING_BUFFER(obj)        \
 +        (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_SINK_RING_BUFFER,GstAudioSinkRingBuffer))
 +#define GST_AUDIO_SINK_RING_BUFFER_CLASS(klass) \
 +        (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_SINK_RING_BUFFER,GstAudioSinkRingBufferClass))
 +#define GST_AUDIO_SINK_RING_BUFFER_GET_CLASS(obj) \
 +        (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AUDIO_SINK_RING_BUFFER, GstAudioSinkRingBufferClass))
 +#define GST_AUDIO_SINK_RING_BUFFER_CAST(obj)        \
 +        ((GstAudioSinkRingBuffer *)obj)
 +#define GST_IS_AUDIO_SINK_RING_BUFFER(obj)     \
 +        (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_SINK_RING_BUFFER))
 +#define GST_IS_AUDIO_SINK_RING_BUFFER_CLASS(klass)\
 +        (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_SINK_RING_BUFFER))
 +
 +typedef struct _GstAudioSinkRingBuffer GstAudioSinkRingBuffer;
 +typedef struct _GstAudioSinkRingBufferClass GstAudioSinkRingBufferClass;
 +
 +#define GST_AUDIO_SINK_RING_BUFFER_GET_COND(buf) (((GstAudioSinkRingBuffer *)buf)->cond)
 +#define GST_AUDIO_SINK_RING_BUFFER_WAIT(buf)     (g_cond_wait (GST_AUDIO_SINK_RING_BUFFER_GET_COND (buf), GST_OBJECT_GET_LOCK (buf)))
 +#define GST_AUDIO_SINK_RING_BUFFER_SIGNAL(buf)   (g_cond_signal (GST_AUDIO_SINK_RING_BUFFER_GET_COND (buf)))
 +#define GST_AUDIO_SINK_RING_BUFFER_BROADCAST(buf)(g_cond_broadcast (GST_AUDIO_SINK_RING_BUFFER_GET_COND (buf)))
 +
 +struct _GstAudioSinkRingBuffer
  {
 -  GstRingBuffer object;
 +  GstAudioRingBuffer object;
  
    gboolean running;
    gint queuedseg;
    GCond *cond;
  };
  
 -struct _GstAudioRingBufferClass
 +struct _GstAudioSinkRingBufferClass
  {
 -  GstRingBufferClass parent_class;
 +  GstAudioRingBufferClass parent_class;
  };
  
 -static void gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass);
 -static void gst_audioringbuffer_init (GstAudioRingBuffer * ringbuffer,
 -    GstAudioRingBufferClass * klass);
 -static void gst_audioringbuffer_dispose (GObject * object);
 -static void gst_audioringbuffer_finalize (GObject * object);
 -
 -static GstRingBufferClass *ring_parent_class = NULL;
 -
 -static gboolean gst_audioringbuffer_open_device (GstRingBuffer * buf);
 -static gboolean gst_audioringbuffer_close_device (GstRingBuffer * buf);
 -static gboolean gst_audioringbuffer_acquire (GstRingBuffer * buf,
 -    GstRingBufferSpec * spec);
 -static gboolean gst_audioringbuffer_release (GstRingBuffer * buf);
 -static gboolean gst_audioringbuffer_start (GstRingBuffer * buf);
 -static gboolean gst_audioringbuffer_pause (GstRingBuffer * buf);
 -static gboolean gst_audioringbuffer_stop (GstRingBuffer * buf);
 -static guint gst_audioringbuffer_delay (GstRingBuffer * buf);
 -static gboolean gst_audioringbuffer_activate (GstRingBuffer * buf,
 +static void gst_audio_sink_ring_buffer_class_init (GstAudioSinkRingBufferClass *
 +    klass);
 +static void gst_audio_sink_ring_buffer_init (GstAudioSinkRingBuffer *
 +    ringbuffer, GstAudioSinkRingBufferClass * klass);
 +static void gst_audio_sink_ring_buffer_dispose (GObject * object);
 +static void gst_audio_sink_ring_buffer_finalize (GObject * object);
 +
 +static GstAudioRingBufferClass *ring_parent_class = NULL;
 +
 +static gboolean gst_audio_sink_ring_buffer_open_device (GstAudioRingBuffer *
 +    buf);
 +static gboolean gst_audio_sink_ring_buffer_close_device (GstAudioRingBuffer *
 +    buf);
 +static gboolean gst_audio_sink_ring_buffer_acquire (GstAudioRingBuffer * buf,
 +    GstAudioRingBufferSpec * spec);
 +static gboolean gst_audio_sink_ring_buffer_release (GstAudioRingBuffer * buf);
 +static gboolean gst_audio_sink_ring_buffer_start (GstAudioRingBuffer * buf);
 +static gboolean gst_audio_sink_ring_buffer_pause (GstAudioRingBuffer * buf);
 +static gboolean gst_audio_sink_ring_buffer_stop (GstAudioRingBuffer * buf);
 +static guint gst_audio_sink_ring_buffer_delay (GstAudioRingBuffer * buf);
 +static gboolean gst_audio_sink_ring_buffer_activate (GstAudioRingBuffer * buf,
      gboolean active);
  
  /* ringbuffer abstract base class */
  static GType
 -gst_audioringbuffer_get_type (void)
 +gst_audio_sink_ring_buffer_get_type (void)
  {
    static GType ringbuffer_type = 0;
  
    if (!ringbuffer_type) {
      static const GTypeInfo ringbuffer_info = {
 -      sizeof (GstAudioRingBufferClass),
 +      sizeof (GstAudioSinkRingBufferClass),
        NULL,
        NULL,
 -      (GClassInitFunc) gst_audioringbuffer_class_init,
 +      (GClassInitFunc) gst_audio_sink_ring_buffer_class_init,
        NULL,
        NULL,
 -      sizeof (GstAudioRingBuffer),
 +      sizeof (GstAudioSinkRingBuffer),
        0,
 -      (GInstanceInitFunc) gst_audioringbuffer_init,
 +      (GInstanceInitFunc) gst_audio_sink_ring_buffer_init,
        NULL
      };
  
      ringbuffer_type =
 -        g_type_register_static (GST_TYPE_RING_BUFFER, "GstAudioSinkRingBuffer",
 -        &ringbuffer_info, 0);
 +        g_type_register_static (GST_TYPE_AUDIO_RING_BUFFER,
 +        "GstAudioSinkRingBuffer", &ringbuffer_info, 0);
    }
    return ringbuffer_type;
  }
  
  static void
 -gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass)
 +gst_audio_sink_ring_buffer_class_init (GstAudioSinkRingBufferClass * klass)
  {
    GObjectClass *gobject_class;
 -  GstRingBufferClass *gstringbuffer_class;
 +  GstAudioRingBufferClass *gstringbuffer_class;
  
    gobject_class = (GObjectClass *) klass;
 -  gstringbuffer_class = (GstRingBufferClass *) klass;
 +  gstringbuffer_class = (GstAudioRingBufferClass *) klass;
  
    ring_parent_class = g_type_class_peek_parent (klass);
  
 -  gobject_class->dispose = gst_audioringbuffer_dispose;
 -  gobject_class->finalize = gst_audioringbuffer_finalize;
 +  gobject_class->dispose = gst_audio_sink_ring_buffer_dispose;
 +  gobject_class->finalize = gst_audio_sink_ring_buffer_finalize;
  
    gstringbuffer_class->open_device =
 -      GST_DEBUG_FUNCPTR (gst_audioringbuffer_open_device);
 +      GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_open_device);
    gstringbuffer_class->close_device =
 -      GST_DEBUG_FUNCPTR (gst_audioringbuffer_close_device);
 +      GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_close_device);
    gstringbuffer_class->acquire =
 -      GST_DEBUG_FUNCPTR (gst_audioringbuffer_acquire);
 +      GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_acquire);
    gstringbuffer_class->release =
 -      GST_DEBUG_FUNCPTR (gst_audioringbuffer_release);
 -  gstringbuffer_class->start = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start);
 -  gstringbuffer_class->pause = GST_DEBUG_FUNCPTR (gst_audioringbuffer_pause);
 -  gstringbuffer_class->resume = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start);
 -  gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_audioringbuffer_stop);
 -
 -  gstringbuffer_class->delay = GST_DEBUG_FUNCPTR (gst_audioringbuffer_delay);
 +      GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_release);
 +  gstringbuffer_class->start =
 +      GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_start);
 +  gstringbuffer_class->pause =
 +      GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_pause);
 +  gstringbuffer_class->resume =
 +      GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_start);
 +  gstringbuffer_class->stop =
 +      GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_stop);
 +
 +  gstringbuffer_class->delay =
 +      GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_delay);
    gstringbuffer_class->activate =
 -      GST_DEBUG_FUNCPTR (gst_audioringbuffer_activate);
 +      GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_activate);
  }
  
 -typedef guint (*WriteFunc) (GstAudioSink * sink, gpointer data, guint length);
 +typedef gint (*WriteFunc) (GstAudioSink * sink, gpointer data, guint length);
  
  /* this internal thread does nothing else but write samples to the audio device.
   * It will write each segment in the ringbuffer and will update the play
   * The start/stop methods control the thread.
   */
  static void
 -audioringbuffer_thread_func (GstRingBuffer * buf)
 +audioringbuffer_thread_func (GstAudioRingBuffer * buf)
  {
    GstAudioSink *sink;
    GstAudioSinkClass *csink;
 -  GstAudioRingBuffer *abuf = GST_AUDIORING_BUFFER_CAST (buf);
 +  GstAudioSinkRingBuffer *abuf = GST_AUDIO_SINK_RING_BUFFER_CAST (buf);
    WriteFunc writefunc;
    GstMessage *message;
    GValue val = { 0 };
  
    GST_OBJECT_LOCK (abuf);
    GST_DEBUG_OBJECT (sink, "signal wait");
 -  GST_AUDIORING_BUFFER_SIGNAL (buf);
 +  GST_AUDIO_SINK_RING_BUFFER_SIGNAL (buf);
    GST_OBJECT_UNLOCK (abuf);
  
    writefunc = csink->write;
      gint readseg;
  
      /* buffer must be started */
 -    if (gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
 +    if (gst_audio_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
        gint written;
  
        left = len;
        } while (left > 0);
  
        /* clear written samples */
 -      gst_ring_buffer_clear (buf, readseg);
 +      gst_audio_ring_buffer_clear (buf, readseg);
  
        /* we wrote one segment */
 -      gst_ring_buffer_advance (buf, 1);
 +      gst_audio_ring_buffer_advance (buf, 1);
      } else {
        GST_OBJECT_LOCK (abuf);
        if (!abuf->running)
          goto stop_running;
        if (G_UNLIKELY (g_atomic_int_get (&buf->state) ==
 -              GST_RING_BUFFER_STATE_STARTED)) {
 +              GST_AUDIO_RING_BUFFER_STATE_STARTED)) {
          GST_OBJECT_UNLOCK (abuf);
          continue;
        }
        GST_DEBUG_OBJECT (sink, "signal wait");
 -      GST_AUDIORING_BUFFER_SIGNAL (buf);
 +      GST_AUDIO_SINK_RING_BUFFER_SIGNAL (buf);
        GST_DEBUG_OBJECT (sink, "wait for action");
 -      GST_AUDIORING_BUFFER_WAIT (buf);
 +      GST_AUDIO_SINK_RING_BUFFER_WAIT (buf);
        GST_DEBUG_OBJECT (sink, "got signal");
        if (!abuf->running)
          goto stop_running;
@@@ -314,8 -308,8 +316,8 @@@ stop_running
  }
  
  static void
 -gst_audioringbuffer_init (GstAudioRingBuffer * ringbuffer,
 -    GstAudioRingBufferClass * g_class)
 +gst_audio_sink_ring_buffer_init (GstAudioSinkRingBuffer * ringbuffer,
 +    GstAudioSinkRingBufferClass * g_class)
  {
    ringbuffer->running = FALSE;
    ringbuffer->queuedseg = 0;
  }
  
  static void
 -gst_audioringbuffer_dispose (GObject * object)
 +gst_audio_sink_ring_buffer_dispose (GObject * object)
  {
    G_OBJECT_CLASS (ring_parent_class)->dispose (object);
  }
  
  static void
 -gst_audioringbuffer_finalize (GObject * object)
 +gst_audio_sink_ring_buffer_finalize (GObject * object)
  {
 -  GstAudioRingBuffer *ringbuffer = GST_AUDIORING_BUFFER_CAST (object);
 +  GstAudioSinkRingBuffer *ringbuffer = GST_AUDIO_SINK_RING_BUFFER_CAST (object);
  
    g_cond_free (ringbuffer->cond);
  
  }
  
  static gboolean
 -gst_audioringbuffer_open_device (GstRingBuffer * buf)
 +gst_audio_sink_ring_buffer_open_device (GstAudioRingBuffer * buf)
  {
    GstAudioSink *sink;
    GstAudioSinkClass *csink;
@@@ -365,7 -359,7 +367,7 @@@ could_not_open
  }
  
  static gboolean
 -gst_audioringbuffer_close_device (GstRingBuffer * buf)
 +gst_audio_sink_ring_buffer_close_device (GstAudioRingBuffer * buf)
  {
    GstAudioSink *sink;
    GstAudioSinkClass *csink;
@@@ -390,8 -384,7 +392,8 @@@ could_not_close
  }
  
  static gboolean
 -gst_audioringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
 +gst_audio_sink_ring_buffer_acquire (GstAudioRingBuffer * buf,
 +    GstAudioRingBufferSpec * spec)
  {
    GstAudioSink *sink;
    GstAudioSinkClass *csink;
    /* set latency to one more segment as we need some headroom */
    spec->seglatency = spec->segtotal + 1;
  
 -  buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize);
 -  memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data));
 +  buf->size = spec->segtotal * spec->segsize;
 +  buf->memory = g_malloc0 (buf->size);
  
    return TRUE;
  
@@@ -422,33 -415,40 +424,40 @@@ could_not_prepare
  }
  
  static gboolean
 -gst_audioringbuffer_activate (GstRingBuffer * buf, gboolean active)
 +gst_audio_sink_ring_buffer_activate (GstAudioRingBuffer * buf, gboolean active)
  {
    GstAudioSink *sink;
 -  GstAudioRingBuffer *abuf;
 +  GstAudioSinkRingBuffer *abuf;
    GError *error = NULL;
  
    sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
 -  abuf = GST_AUDIORING_BUFFER_CAST (buf);
 +  abuf = GST_AUDIO_SINK_RING_BUFFER_CAST (buf);
  
    if (active) {
      abuf->running = TRUE;
  
      GST_DEBUG_OBJECT (sink, "starting thread");
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
      sink->thread =
          g_thread_create ((GThreadFunc) audioringbuffer_thread_func, buf, TRUE,
          &error);
+ #else
+     sink->thread = g_thread_try_new ("audiosink-ringbuffer",
+         (GThreadFunc) audioringbuffer_thread_func, buf, &error);
+ #endif
      if (!sink->thread || error != NULL)
        goto thread_failed;
  
      GST_DEBUG_OBJECT (sink, "waiting for thread");
      /* the object lock is taken */
 -    GST_AUDIORING_BUFFER_WAIT (buf);
 +    GST_AUDIO_SINK_RING_BUFFER_WAIT (buf);
      GST_DEBUG_OBJECT (sink, "thread is started");
    } else {
      abuf->running = FALSE;
      GST_DEBUG_OBJECT (sink, "signal wait");
 -    GST_AUDIORING_BUFFER_SIGNAL (buf);
 +    GST_AUDIO_SINK_RING_BUFFER_SIGNAL (buf);
  
      GST_OBJECT_UNLOCK (buf);
  
@@@ -472,7 -472,7 +481,7 @@@ thread_failed
  
  /* function is called with LOCK */
  static gboolean
 -gst_audioringbuffer_release (GstRingBuffer * buf)
 +gst_audio_sink_ring_buffer_release (GstAudioRingBuffer * buf)
  {
    GstAudioSink *sink;
    GstAudioSinkClass *csink;
    csink = GST_AUDIO_SINK_GET_CLASS (sink);
  
    /* free the buffer */
 -  gst_buffer_unref (buf->data);
 -  buf->data = NULL;
 +  g_free (buf->memory);
 +  buf->memory = NULL;
  
    if (csink->unprepare)
      result = csink->unprepare (sink);
@@@ -503,20 -503,20 +512,20 @@@ could_not_unprepare
  }
  
  static gboolean
 -gst_audioringbuffer_start (GstRingBuffer * buf)
 +gst_audio_sink_ring_buffer_start (GstAudioRingBuffer * buf)
  {
    GstAudioSink *sink;
  
    sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
  
    GST_DEBUG_OBJECT (sink, "start, sending signal");
 -  GST_AUDIORING_BUFFER_SIGNAL (buf);
 +  GST_AUDIO_SINK_RING_BUFFER_SIGNAL (buf);
  
    return TRUE;
  }
  
  static gboolean
 -gst_audioringbuffer_pause (GstRingBuffer * buf)
 +gst_audio_sink_ring_buffer_pause (GstAudioRingBuffer * buf)
  {
    GstAudioSink *sink;
    GstAudioSinkClass *csink;
  }
  
  static gboolean
 -gst_audioringbuffer_stop (GstRingBuffer * buf)
 +gst_audio_sink_ring_buffer_stop (GstAudioRingBuffer * buf)
  {
    GstAudioSink *sink;
    GstAudioSinkClass *csink;
  #if 0
    if (abuf->running) {
      GST_DEBUG_OBJECT (sink, "stop, waiting...");
 -    GST_AUDIORING_BUFFER_WAIT (buf);
 +    GST_AUDIO_SINK_RING_BUFFER_WAIT (buf);
      GST_DEBUG_OBJECT (sink, "stopped");
    }
  #endif
  }
  
  static guint
 -gst_audioringbuffer_delay (GstRingBuffer * buf)
 +gst_audio_sink_ring_buffer_delay (GstAudioRingBuffer * buf)
  {
    GstAudioSink *sink;
    GstAudioSinkClass *csink;
@@@ -588,40 -588,45 +597,40 @@@ enu
    ARG_0,
  };
  
 -#define _do_init(bla) \
 +#define _do_init \
      GST_DEBUG_CATEGORY_INIT (gst_audio_sink_debug, "audiosink", 0, "audiosink element");
 +#define gst_audio_sink_parent_class parent_class
 +G_DEFINE_TYPE_WITH_CODE (GstAudioSink, gst_audio_sink,
 +    GST_TYPE_AUDIO_BASE_SINK, _do_init);
  
 -GST_BOILERPLATE_FULL (GstAudioSink, gst_audio_sink, GstBaseAudioSink,
 -    GST_TYPE_BASE_AUDIO_SINK, _do_init);
 -
 -static GstRingBuffer *gst_audio_sink_create_ringbuffer (GstBaseAudioSink *
 +static GstAudioRingBuffer *gst_audio_sink_create_ringbuffer (GstAudioBaseSink *
      sink);
  
  static void
 -gst_audio_sink_base_init (gpointer g_class)
 -{
 -}
 -
 -static void
  gst_audio_sink_class_init (GstAudioSinkClass * klass)
  {
 -  GstBaseAudioSinkClass *gstbaseaudiosink_class;
 +  GstAudioBaseSinkClass *gstaudiobasesink_class;
  
 -  gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
 +  gstaudiobasesink_class = (GstAudioBaseSinkClass *) klass;
  
 -  gstbaseaudiosink_class->create_ringbuffer =
 +  gstaudiobasesink_class->create_ringbuffer =
        GST_DEBUG_FUNCPTR (gst_audio_sink_create_ringbuffer);
  
 -  g_type_class_ref (GST_TYPE_AUDIORING_BUFFER);
 +  g_type_class_ref (GST_TYPE_AUDIO_SINK_RING_BUFFER);
  }
  
  static void
 -gst_audio_sink_init (GstAudioSink * audiosink, GstAudioSinkClass * g_class)
 +gst_audio_sink_init (GstAudioSink * audiosink)
  {
  }
  
 -static GstRingBuffer *
 -gst_audio_sink_create_ringbuffer (GstBaseAudioSink * sink)
 +static GstAudioRingBuffer *
 +gst_audio_sink_create_ringbuffer (GstAudioBaseSink * sink)
  {
 -  GstRingBuffer *buffer;
 +  GstAudioRingBuffer *buffer;
  
    GST_DEBUG_OBJECT (sink, "creating ringbuffer");
 -  buffer = g_object_new (GST_TYPE_AUDIORING_BUFFER, NULL);
 +  buffer = g_object_new (GST_TYPE_AUDIO_SINK_RING_BUFFER, NULL);
    GST_DEBUG_OBJECT (sink, "created ringbuffer @%p", buffer);
  
    return buffer;
@@@ -23,7 -23,7 +23,7 @@@
  /**
   * SECTION:gstaudiosrc
   * @short_description: Simple base class for audio sources
 - * @see_also: #GstBaseAudioSrc, #GstRingBuffer, #GstAudioSrc.
 + * @see_also: #GstAudioBaseSrc, #GstAudioRingBuffer, #GstAudioSrc.
   *
   * This is the most simple base class for audio sources that only requires
   * subclasses to implement a set of simple functions:
@@@ -61,8 -61,8 +61,8 @@@
   * </variablelist>
   *
   * All scheduling of samples and timestamps is done in this base class
 - * together with #GstBaseAudioSrc using a default implementation of a
 - * #GstRingBuffer that uses threads.
 + * together with #GstAudioBaseSrc using a default implementation of a
 + * #GstAudioRingBuffer that uses threads.
   *
   * Last reviewed on 2006-09-27 (0.10.12)
   */
  
  #include "gstaudiosrc.h"
  
+ #include "gst/glib-compat-private.h"
  GST_DEBUG_CATEGORY_STATIC (gst_audio_src_debug);
  #define GST_CAT_DEFAULT gst_audio_src_debug
  
 -#define GST_TYPE_AUDIORING_BUFFER        \
 -        (gst_audioringbuffer_get_type())
 -#define GST_AUDIORING_BUFFER(obj)        \
 -        (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIORING_BUFFER,GstAudioRingBuffer))
 -#define GST_AUDIORING_BUFFER_CLASS(klass) \
 -        (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIORING_BUFFER,GstAudioRingBufferClass))
 -#define GST_AUDIORING_BUFFER_GET_CLASS(obj) \
 -        (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AUDIORING_BUFFER, GstAudioRingBufferClass))
 -#define GST_IS_AUDIORING_BUFFER(obj)     \
 -        (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIORING_BUFFER))
 -#define GST_IS_AUDIORING_BUFFER_CLASS(klass)\
 -        (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIORING_BUFFER))
 -
 -typedef struct _GstAudioRingBuffer GstAudioRingBuffer;
 -typedef struct _GstAudioRingBufferClass GstAudioRingBufferClass;
 -
 -#define GST_AUDIORING_BUFFER_GET_COND(buf) (((GstAudioRingBuffer *)buf)->cond)
 -#define GST_AUDIORING_BUFFER_WAIT(buf)     (g_cond_wait (GST_AUDIORING_BUFFER_GET_COND (buf), GST_OBJECT_GET_LOCK (buf)))
 -#define GST_AUDIORING_BUFFER_SIGNAL(buf)   (g_cond_signal (GST_AUDIORING_BUFFER_GET_COND (buf)))
 -#define GST_AUDIORING_BUFFER_BROADCAST(buf)(g_cond_broadcast (GST_AUDIORING_BUFFER_GET_COND (buf)))
 -
 -struct _GstAudioRingBuffer
 +#define GST_TYPE_AUDIO_SRC_RING_BUFFER        \
 +        (gst_audio_src_ring_buffer_get_type())
 +#define GST_AUDIO_SRC_RING_BUFFER(obj)        \
 +        (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_SRC_RING_BUFFER,GstAudioSrcRingBuffer))
 +#define GST_AUDIO_SRC_RING_BUFFER_CLASS(klass) \
 +        (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_SRC_RING_BUFFER,GstAudioSrcRingBufferClass))
 +#define GST_AUDIO_SRC_RING_BUFFER_GET_CLASS(obj) \
 +        (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AUDIO_SRC_RING_BUFFER, GstAudioSrcRingBufferClass))
 +#define GST_IS_AUDIO_SRC_RING_BUFFER(obj)     \
 +        (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_SRC_RING_BUFFER))
 +#define GST_IS_AUDIO_SRC_RING_BUFFER_CLASS(klass)\
 +        (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_SRC_RING_BUFFER))
 +
 +typedef struct _GstAudioSrcRingBuffer GstAudioSrcRingBuffer;
 +typedef struct _GstAudioSrcRingBufferClass GstAudioSrcRingBufferClass;
 +
 +#define GST_AUDIO_SRC_RING_BUFFER_GET_COND(buf) (((GstAudioSrcRingBuffer *)buf)->cond)
 +#define GST_AUDIO_SRC_RING_BUFFER_WAIT(buf)     (g_cond_wait (GST_AUDIO_SRC_RING_BUFFER_GET_COND (buf), GST_OBJECT_GET_LOCK (buf)))
 +#define GST_AUDIO_SRC_RING_BUFFER_SIGNAL(buf)   (g_cond_signal (GST_AUDIO_SRC_RING_BUFFER_GET_COND (buf)))
 +#define GST_AUDIO_SRC_RING_BUFFER_BROADCAST(buf)(g_cond_broadcast (GST_AUDIO_SRC_RING_BUFFER_GET_COND (buf)))
 +
 +struct _GstAudioSrcRingBuffer
  {
 -  GstRingBuffer object;
 +  GstAudioRingBuffer object;
  
    gboolean running;
    gint queuedseg;
    GCond *cond;
  };
  
 -struct _GstAudioRingBufferClass
 +struct _GstAudioSrcRingBufferClass
  {
 -  GstRingBufferClass parent_class;
 +  GstAudioRingBufferClass parent_class;
  };
  
 -static void gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass);
 -static void gst_audioringbuffer_init (GstAudioRingBuffer * ringbuffer,
 -    GstAudioRingBufferClass * klass);
 -static void gst_audioringbuffer_dispose (GObject * object);
 -static void gst_audioringbuffer_finalize (GObject * object);
 -
 -static GstRingBufferClass *ring_parent_class = NULL;
 -
 -static gboolean gst_audioringbuffer_open_device (GstRingBuffer * buf);
 -static gboolean gst_audioringbuffer_close_device (GstRingBuffer * buf);
 -static gboolean gst_audioringbuffer_acquire (GstRingBuffer * buf,
 -    GstRingBufferSpec * spec);
 -static gboolean gst_audioringbuffer_release (GstRingBuffer * buf);
 -static gboolean gst_audioringbuffer_start (GstRingBuffer * buf);
 -static gboolean gst_audioringbuffer_stop (GstRingBuffer * buf);
 -static guint gst_audioringbuffer_delay (GstRingBuffer * buf);
 +static void gst_audio_src_ring_buffer_class_init (GstAudioSrcRingBufferClass *
 +    klass);
 +static void gst_audio_src_ring_buffer_init (GstAudioSrcRingBuffer * ringbuffer,
 +    GstAudioSrcRingBufferClass * klass);
 +static void gst_audio_src_ring_buffer_dispose (GObject * object);
 +static void gst_audio_src_ring_buffer_finalize (GObject * object);
 +
 +static GstAudioRingBufferClass *ring_parent_class = NULL;
 +
 +static gboolean gst_audio_src_ring_buffer_open_device (GstAudioRingBuffer *
 +    buf);
 +static gboolean gst_audio_src_ring_buffer_close_device (GstAudioRingBuffer *
 +    buf);
 +static gboolean gst_audio_src_ring_buffer_acquire (GstAudioRingBuffer * buf,
 +    GstAudioRingBufferSpec * spec);
 +static gboolean gst_audio_src_ring_buffer_release (GstAudioRingBuffer * buf);
 +static gboolean gst_audio_src_ring_buffer_start (GstAudioRingBuffer * buf);
 +static gboolean gst_audio_src_ring_buffer_stop (GstAudioRingBuffer * buf);
 +static guint gst_audio_src_ring_buffer_delay (GstAudioRingBuffer * buf);
  
  /* ringbuffer abstract base class */
  static GType
 -gst_audioringbuffer_get_type (void)
 +gst_audio_src_ring_buffer_get_type (void)
  {
    static GType ringbuffer_type = 0;
  
    if (!ringbuffer_type) {
      static const GTypeInfo ringbuffer_info = {
 -      sizeof (GstAudioRingBufferClass),
 +      sizeof (GstAudioSrcRingBufferClass),
        NULL,
        NULL,
 -      (GClassInitFunc) gst_audioringbuffer_class_init,
 +      (GClassInitFunc) gst_audio_src_ring_buffer_class_init,
        NULL,
        NULL,
 -      sizeof (GstAudioRingBuffer),
 +      sizeof (GstAudioSrcRingBuffer),
        0,
 -      (GInstanceInitFunc) gst_audioringbuffer_init,
 +      (GInstanceInitFunc) gst_audio_src_ring_buffer_init,
        NULL
      };
  
      ringbuffer_type =
 -        g_type_register_static (GST_TYPE_RING_BUFFER, "GstAudioSrcRingBuffer",
 -        &ringbuffer_info, 0);
 +        g_type_register_static (GST_TYPE_AUDIO_RING_BUFFER,
 +        "GstAudioSrcRingBuffer", &ringbuffer_info, 0);
    }
    return ringbuffer_type;
  }
  
  static void
 -gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass)
 +gst_audio_src_ring_buffer_class_init (GstAudioSrcRingBufferClass * klass)
  {
    GObjectClass *gobject_class;
 -  GstRingBufferClass *gstringbuffer_class;
 +  GstAudioRingBufferClass *gstringbuffer_class;
  
    gobject_class = (GObjectClass *) klass;
 -  gstringbuffer_class = (GstRingBufferClass *) klass;
 +  gstringbuffer_class = (GstAudioRingBufferClass *) klass;
  
    ring_parent_class = g_type_class_peek_parent (klass);
  
 -  gobject_class->dispose = gst_audioringbuffer_dispose;
 -  gobject_class->finalize = gst_audioringbuffer_finalize;
 +  gobject_class->dispose = gst_audio_src_ring_buffer_dispose;
 +  gobject_class->finalize = gst_audio_src_ring_buffer_finalize;
  
    gstringbuffer_class->open_device =
 -      GST_DEBUG_FUNCPTR (gst_audioringbuffer_open_device);
 +      GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_open_device);
    gstringbuffer_class->close_device =
 -      GST_DEBUG_FUNCPTR (gst_audioringbuffer_close_device);
 +      GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_close_device);
    gstringbuffer_class->acquire =
 -      GST_DEBUG_FUNCPTR (gst_audioringbuffer_acquire);
 +      GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_acquire);
    gstringbuffer_class->release =
 -      GST_DEBUG_FUNCPTR (gst_audioringbuffer_release);
 -  gstringbuffer_class->start = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start);
 -  gstringbuffer_class->resume = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start);
 -  gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_audioringbuffer_stop);
 -
 -  gstringbuffer_class->delay = GST_DEBUG_FUNCPTR (gst_audioringbuffer_delay);
 +      GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_release);
 +  gstringbuffer_class->start =
 +      GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_start);
 +  gstringbuffer_class->resume =
 +      GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_start);
 +  gstringbuffer_class->stop =
 +      GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_stop);
 +
 +  gstringbuffer_class->delay =
 +      GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_delay);
  }
  
  typedef guint (*ReadFunc) (GstAudioSrc * src, gpointer data, guint length);
   * The start/stop methods control the thread.
   */
  static void
 -audioringbuffer_thread_func (GstRingBuffer * buf)
 +audioringbuffer_thread_func (GstAudioRingBuffer * buf)
  {
    GstAudioSrc *src;
    GstAudioSrcClass *csrc;
 -  GstAudioRingBuffer *abuf = GST_AUDIORING_BUFFER (buf);
 +  GstAudioSrcRingBuffer *abuf = GST_AUDIO_SRC_RING_BUFFER (buf);
    ReadFunc readfunc;
    GstMessage *message;
    GValue val = { 0 };
      guint8 *readptr;
      gint readseg;
  
 -    if (gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
 +    if (gst_audio_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
        gint read;
  
        left = len;
        } while (left > 0);
  
        /* we read one segment */
 -      gst_ring_buffer_advance (buf, 1);
 +      gst_audio_ring_buffer_advance (buf, 1);
      } else {
        GST_OBJECT_LOCK (abuf);
        if (!abuf->running)
          goto stop_running;
 +      if (G_UNLIKELY (g_atomic_int_get (&buf->state) ==
 +              GST_AUDIO_RING_BUFFER_STATE_STARTED)) {
 +        GST_OBJECT_UNLOCK (abuf);
 +        continue;
 +      }
        GST_DEBUG_OBJECT (src, "signal wait");
 -      GST_AUDIORING_BUFFER_SIGNAL (buf);
 +      GST_AUDIO_SRC_RING_BUFFER_SIGNAL (buf);
        GST_DEBUG_OBJECT (src, "wait for action");
 -      GST_AUDIORING_BUFFER_WAIT (buf);
 +      GST_AUDIO_SRC_RING_BUFFER_WAIT (buf);
        GST_DEBUG_OBJECT (src, "got signal");
        if (!abuf->running)
          goto stop_running;
@@@ -295,8 -285,8 +297,8 @@@ stop_running
  }
  
  static void
 -gst_audioringbuffer_init (GstAudioRingBuffer * ringbuffer,
 -    GstAudioRingBufferClass * g_class)
 +gst_audio_src_ring_buffer_init (GstAudioSrcRingBuffer * ringbuffer,
 +    GstAudioSrcRingBufferClass * g_class)
  {
    ringbuffer->running = FALSE;
    ringbuffer->queuedseg = 0;
  }
  
  static void
 -gst_audioringbuffer_dispose (GObject * object)
 +gst_audio_src_ring_buffer_dispose (GObject * object)
  {
 -  GstAudioRingBuffer *ringbuffer = GST_AUDIORING_BUFFER (object);
 +  GstAudioSrcRingBuffer *ringbuffer = GST_AUDIO_SRC_RING_BUFFER (object);
  
    if (ringbuffer->cond) {
      g_cond_free (ringbuffer->cond);
  }
  
  static void
 -gst_audioringbuffer_finalize (GObject * object)
 +gst_audio_src_ring_buffer_finalize (GObject * object)
  {
    G_OBJECT_CLASS (ring_parent_class)->finalize (object);
  }
  
  static gboolean
 -gst_audioringbuffer_open_device (GstRingBuffer * buf)
 +gst_audio_src_ring_buffer_open_device (GstAudioRingBuffer * buf)
  {
    GstAudioSrc *src;
    GstAudioSrcClass *csrc;
@@@ -348,7 -338,7 +350,7 @@@ could_not_open
  }
  
  static gboolean
 -gst_audioringbuffer_close_device (GstRingBuffer * buf)
 +gst_audio_src_ring_buffer_close_device (GstAudioRingBuffer * buf)
  {
    GstAudioSrc *src;
    GstAudioSrcClass *csrc;
@@@ -372,12 -362,11 +374,12 @@@ could_not_open
  }
  
  static gboolean
 -gst_audioringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
 +gst_audio_src_ring_buffer_acquire (GstAudioRingBuffer * buf,
 +    GstAudioRingBufferSpec * spec)
  {
    GstAudioSrc *src;
    GstAudioSrcClass *csrc;
 -  GstAudioRingBuffer *abuf;
 +  GstAudioSrcRingBuffer *abuf;
    gboolean result = FALSE;
  
    src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
    if (!result)
      goto could_not_open;
  
 -  buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize);
 -  memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data));
 +  buf->size = spec->segtotal * spec->segsize;
 +  buf->memory = g_malloc0 (buf->size);
  
 -  abuf = GST_AUDIORING_BUFFER (buf);
 +  abuf = GST_AUDIO_SRC_RING_BUFFER (buf);
    abuf->running = TRUE;
  
+   /* FIXME: handle thread creation failure */
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
    src->thread =
        g_thread_create ((GThreadFunc) audioringbuffer_thread_func, buf, TRUE,
        NULL);
-   GST_AUDIO_SRC_RING_BUFFER_WAIT (buf);
+ #else
+   src->thread = g_thread_try_new ("audiosrc-ringbuffer",
+       (GThreadFunc) audioringbuffer_thread_func, buf, NULL);
+ #endif
 -  GST_AUDIORING_BUFFER_WAIT (buf);
++  GST_AUDIO_RING_BUFFER_WAIT (buf);
  
    return result;
  
@@@ -410,19 -406,19 +419,19 @@@ could_not_open
  
  /* function is called with LOCK */
  static gboolean
 -gst_audioringbuffer_release (GstRingBuffer * buf)
 +gst_audio_src_ring_buffer_release (GstAudioRingBuffer * buf)
  {
    GstAudioSrc *src;
    GstAudioSrcClass *csrc;
 -  GstAudioRingBuffer *abuf;
 +  GstAudioSrcRingBuffer *abuf;
    gboolean result = FALSE;
  
    src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
    csrc = GST_AUDIO_SRC_GET_CLASS (src);
 -  abuf = GST_AUDIORING_BUFFER (buf);
 +  abuf = GST_AUDIO_SRC_RING_BUFFER (buf);
  
    abuf->running = FALSE;
 -  GST_AUDIORING_BUFFER_SIGNAL (buf);
 +  GST_AUDIO_SRC_RING_BUFFER_SIGNAL (buf);
    GST_OBJECT_UNLOCK (buf);
  
    /* join the thread */
    GST_OBJECT_LOCK (buf);
  
    /* free the buffer */
 -  gst_buffer_unref (buf->data);
 -  buf->data = NULL;
 +  g_free (buf->memory);
 +  buf->memory = NULL;
  
    if (csrc->unprepare)
      result = csrc->unprepare (src);
  }
  
  static gboolean
 -gst_audioringbuffer_start (GstRingBuffer * buf)
 +gst_audio_src_ring_buffer_start (GstAudioRingBuffer * buf)
  {
    GST_DEBUG ("start, sending signal");
 -  GST_AUDIORING_BUFFER_SIGNAL (buf);
 +  GST_AUDIO_SRC_RING_BUFFER_SIGNAL (buf);
  
    return TRUE;
  }
  
  static gboolean
 -gst_audioringbuffer_stop (GstRingBuffer * buf)
 +gst_audio_src_ring_buffer_stop (GstAudioRingBuffer * buf)
  {
    GstAudioSrc *src;
    GstAudioSrcClass *csrc;
    }
  #if 0
    GST_DEBUG ("stop, waiting...");
 -  GST_AUDIORING_BUFFER_WAIT (buf);
 +  GST_AUDIO_SRC_RING_BUFFER_WAIT (buf);
    GST_DEBUG ("stoped");
  #endif
  
  }
  
  static guint
 -gst_audioringbuffer_delay (GstRingBuffer * buf)
 +gst_audio_src_ring_buffer_delay (GstAudioRingBuffer * buf)
  {
    GstAudioSrc *src;
    GstAudioSrcClass *csrc;
@@@ -501,40 -497,44 +510,40 @@@ enu
    ARG_0,
  };
  
 -#define _do_init(bla) \
 +#define _do_init \
      GST_DEBUG_CATEGORY_INIT (gst_audio_src_debug, "audiosrc", 0, "audiosrc element");
 +#define gst_audio_src_parent_class parent_class
 +G_DEFINE_TYPE_WITH_CODE (GstAudioSrc, gst_audio_src,
 +    GST_TYPE_AUDIO_BASE_SRC, _do_init);
  
 -GST_BOILERPLATE_FULL (GstAudioSrc, gst_audio_src, GstBaseAudioSrc,
 -    GST_TYPE_BASE_AUDIO_SRC, _do_init);
 -
 -static GstRingBuffer *gst_audio_src_create_ringbuffer (GstBaseAudioSrc * src);
 -
 -static void
 -gst_audio_src_base_init (gpointer g_class)
 -{
 -}
 +static GstAudioRingBuffer *gst_audio_src_create_ringbuffer (GstAudioBaseSrc *
 +    src);
  
  static void
  gst_audio_src_class_init (GstAudioSrcClass * klass)
  {
 -  GstBaseAudioSrcClass *gstbaseaudiosrc_class;
 +  GstAudioBaseSrcClass *gstaudiobasesrc_class;
  
 -  gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
 +  gstaudiobasesrc_class = (GstAudioBaseSrcClass *) klass;
  
 -  gstbaseaudiosrc_class->create_ringbuffer =
 +  gstaudiobasesrc_class->create_ringbuffer =
        GST_DEBUG_FUNCPTR (gst_audio_src_create_ringbuffer);
  
 -  g_type_class_ref (GST_TYPE_AUDIORING_BUFFER);
 +  g_type_class_ref (GST_TYPE_AUDIO_SRC_RING_BUFFER);
  }
  
  static void
 -gst_audio_src_init (GstAudioSrc * audiosrc, GstAudioSrcClass * g_class)
 +gst_audio_src_init (GstAudioSrc * audiosrc)
  {
  }
  
 -static GstRingBuffer *
 -gst_audio_src_create_ringbuffer (GstBaseAudioSrc * src)
 +static GstAudioRingBuffer *
 +gst_audio_src_create_ringbuffer (GstAudioBaseSrc * src)
  {
 -  GstRingBuffer *buffer;
 +  GstAudioRingBuffer *buffer;
  
    GST_DEBUG ("creating ringbuffer");
 -  buffer = g_object_new (GST_TYPE_AUDIORING_BUFFER, NULL);
 +  buffer = g_object_new (GST_TYPE_AUDIO_SRC_RING_BUFFER, NULL);
    GST_DEBUG ("created ringbuffer @%p", buffer);
  
    return buffer;
  #include "config.h"
  #endif
  
 +#include <gst/video/video.h>
 +
  #include "pbutils.h"
  #include "pbutils-marshal.h"
  #include "pbutils-private.h"
  
+ #include "gst/glib-compat-private.h"
  GST_DEBUG_CATEGORY_STATIC (discoverer_debug);
  #define GST_CAT_DEFAULT discoverer_debug
  
@@@ -100,7 -100,7 +102,7 @@@ struct _GstDiscovererPrivat
    GstElement *uridecodebin;
    GstBus *bus;
  
 -  GType decodebin2_type;
 +  GType decodebin_type;
  
    /* Custom main context variables */
    GMainContext *ctx;
@@@ -243,7 -243,7 +245,7 @@@ uridecodebin_element_added_cb (GstEleme
    GST_DEBUG ("New element added to uridecodebin : %s",
        GST_ELEMENT_NAME (child));
  
 -  if (G_OBJECT_TYPE (child) == dc->priv->decodebin2_type) {
 +  if (G_OBJECT_TYPE (child) == dc->priv->decodebin_type) {
      g_object_set (child, "post-stream-topology", TRUE, NULL);
    }
  }
@@@ -290,14 -290,14 +292,14 @@@ gst_discoverer_init (GstDiscoverer * dc
  
    GST_DEBUG_OBJECT (dc, "Done initializing Discoverer");
  
 -  /* This is ugly. We get the GType of decodebin2 so we can quickly detect
 -   * when a decodebin2 is added to uridecodebin so we can set the
 +  /* This is ugly. We get the GType of decodebin so we can quickly detect
 +   * when a decodebin is added to uridecodebin so we can set the
     * post-stream-topology setting to TRUE */
    dc->priv->element_added_id =
        g_signal_connect_object (dc->priv->uridecodebin, "element-added",
        G_CALLBACK (uridecodebin_element_added_cb), dc, 0);
 -  tmp = gst_element_factory_make ("decodebin2", NULL);
 -  dc->priv->decodebin2_type = G_OBJECT_TYPE (tmp);
 +  tmp = gst_element_factory_make ("decodebin", NULL);
 +  dc->priv->decodebin_type = G_OBJECT_TYPE (tmp);
    gst_object_unref (tmp);
  
    /* create queries */
@@@ -410,11 -410,9 +412,11 @@@ gst_discoverer_set_timeout (GstDiscover
    DISCO_UNLOCK (dc);
  }
  
 -static gboolean
 -_event_probe (GstPad * pad, GstEvent * event, PrivateStream * ps)
 +static GstPadProbeReturn
 +_event_probe (GstPad * pad, GstPadProbeInfo * info, PrivateStream * ps)
  {
 +  GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
 +
    if (GST_EVENT_TYPE (event) == GST_EVENT_TAG) {
      GstTagList *tl = NULL, *tmp;
  
      DISCO_UNLOCK (ps->dc);
    }
  
 -  return TRUE;
 +  return GST_PAD_PROBE_OK;
  }
  
  static gboolean
@@@ -478,7 -476,7 +480,7 @@@ uridecodebin_pad_added_cb (GstElement 
    g_object_set (ps->sink, "silent", TRUE, NULL);
    g_object_set (ps->queue, "max-size-buffers", 1, "silent", TRUE, NULL);
  
 -  caps = gst_pad_get_caps_reffed (pad);
 +  caps = gst_pad_query_caps (pad, NULL);
  
    if (is_subtitle_caps (caps)) {
      /* Subtitle streams are sparse and may not provide any information - don't
    gst_object_unref (sinkpad);
  
    /* Add an event probe */
 -  gst_pad_add_event_probe (pad, G_CALLBACK (_event_probe), ps);
 +  gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
 +      (GstPadProbeCallback) _event_probe, ps, NULL);
  
    DISCO_LOCK (dc);
    dc->priv->streams = g_list_append (dc->priv->streams, ps);
@@@ -585,15 -582,15 +587,15 @@@ collect_stream_information (GstDiscover
    gchar *stname;
  
    stname = g_strdup_printf ("stream-%02d", idx);
 -  st = gst_structure_empty_new (stname);
 +  st = gst_structure_new_empty (stname);
    g_free (stname);
  
    /* Get caps */
 -  caps = gst_pad_get_negotiated_caps (ps->pad);
 +  caps = gst_pad_get_current_caps (ps->pad);
    if (!caps) {
      GST_WARNING ("Couldn't get negotiated caps from %s:%s",
          GST_DEBUG_PAD_NAME (ps->pad));
 -    caps = gst_pad_get_caps (ps->pad);
 +    caps = gst_pad_query_caps (ps->pad, NULL);
    }
    if (caps) {
      GST_DEBUG ("Got caps %" GST_PTR_FORMAT, caps);
@@@ -617,7 -614,7 +619,7 @@@ collect_information (GstDiscoverer * dc
    GstCaps *caps;
    GstStructure *caps_st, *tags_st;
    const gchar *name;
 -  int tmp, tmp2;
 +  int tmp;
    guint utmp;
  
    if (!st || !gst_structure_id_has_field (st, _CAPS_QUARK)) {
        return parent;
      else
        return (GstDiscovererStreamInfo *)
 -          gst_mini_object_new (GST_TYPE_DISCOVERER_STREAM_INFO);
 +          g_object_new (GST_TYPE_DISCOVERER_STREAM_INFO, NULL);
    }
  
    gst_structure_id_get (st, _CAPS_QUARK, GST_TYPE_CAPS, &caps, NULL);
        info = (GstDiscovererAudioInfo *) parent;
      else {
        info = (GstDiscovererAudioInfo *)
 -          gst_mini_object_new (GST_TYPE_DISCOVERER_AUDIO_INFO);
 +          g_object_new (GST_TYPE_DISCOVERER_AUDIO_INFO, NULL);
        info->parent.caps = caps;
      }
  
    } else if (g_str_has_prefix (name, "video/") ||
        g_str_has_prefix (name, "image/")) {
      GstDiscovererVideoInfo *info;
 +    GstVideoInfo vinfo;
  
      if (parent)
        info = (GstDiscovererVideoInfo *) parent;
      else {
        info = (GstDiscovererVideoInfo *)
 -          gst_mini_object_new (GST_TYPE_DISCOVERER_VIDEO_INFO);
 +          g_object_new (GST_TYPE_DISCOVERER_VIDEO_INFO, NULL);
        info->parent.caps = caps;
      }
  
 -    if (gst_structure_get_int (caps_st, "width", &tmp) &&
 -        gst_structure_get_int (caps_st, "height", &tmp2)) {
 -      info->width = (guint) tmp;
 -      info->height = (guint) tmp2;
 -    }
 +    /* FIXME : gst_video_info_from_caps only works with raw caps,
 +     * wouldn't we want to get all the info below for non-raw caps ? 
 +     */
 +    if (g_str_has_prefix (name, "video/x-raw") &&
 +        gst_video_info_from_caps (&vinfo, caps)) {
 +      info->width = (guint) vinfo.width;
 +      info->height = (guint) vinfo.height;
  
 -    if (gst_structure_get_int (caps_st, "depth", &tmp))
 -      info->depth = (guint) tmp;
 +      info->depth = (guint) 0;
  
 -    if (gst_structure_get_fraction (caps_st, "pixel-aspect-ratio", &tmp, &tmp2)) {
 -      info->par_num = tmp;
 -      info->par_denom = tmp2;
 -    } else {
 -      info->par_num = 1;
 -      info->par_denom = 1;
 -    }
 +      info->par_num = vinfo.par_n;
 +      info->par_denom = vinfo.par_d;
  
 -    if (gst_structure_get_fraction (caps_st, "framerate", &tmp, &tmp2)) {
 -      info->framerate_num = tmp;
 -      info->framerate_denom = tmp2;
 -    }
 +      info->framerate_num = vinfo.fps_n;
 +      info->framerate_denom = vinfo.fps_d;
  
 -    if (!gst_structure_get_boolean (caps_st, "interlaced", &info->interlaced))
 -      info->interlaced = FALSE;
 +      info->interlaced = (vinfo.flags & GST_VIDEO_FLAG_INTERLACED) != 0;
 +    }
  
      if (gst_structure_id_has_field (st, _TAGS_QUARK)) {
        gst_structure_id_get (st, _TAGS_QUARK,
        info = (GstDiscovererSubtitleInfo *) parent;
      else {
        info = (GstDiscovererSubtitleInfo *)
 -          gst_mini_object_new (GST_TYPE_DISCOVERER_SUBTITLE_INFO);
 +          g_object_new (GST_TYPE_DISCOVERER_SUBTITLE_INFO, NULL);
        info->parent.caps = caps;
      }
  
        info = parent;
      else {
        info = (GstDiscovererStreamInfo *)
 -          gst_mini_object_new (GST_TYPE_DISCOVERER_STREAM_INFO);
 +          g_object_new (GST_TYPE_DISCOVERER_STREAM_INFO, NULL);
        info->caps = caps;
      }
  
@@@ -942,7 -944,7 +944,7 @@@ parse_stream_topology (GstDiscoverer * 
      GST_DEBUG ("next is a list of %d entries", len);
  
      cont = (GstDiscovererContainerInfo *)
 -        gst_mini_object_new (GST_TYPE_DISCOVERER_CONTAINER_INFO);
 +        g_object_new (GST_TYPE_DISCOVERER_CONTAINER_INFO, NULL);
      cont->parent.caps = caps;
      res = (GstDiscovererStreamInfo *) cont;
  
@@@ -999,18 -1001,20 +1001,18 @@@ discoverer_collect (GstDiscoverer * dc
      /* FIXME : Make this querying optional */
      if (TRUE) {
        GstElement *pipeline = (GstElement *) dc->priv->pipeline;
 -      GstFormat format = GST_FORMAT_TIME;
        gint64 dur;
  
        GST_DEBUG ("Attempting to query duration");
  
 -      if (gst_element_query_duration (pipeline, &format, &dur)) {
 -        if (format == GST_FORMAT_TIME) {
 -          GST_DEBUG ("Got duration %" GST_TIME_FORMAT, GST_TIME_ARGS (dur));
 -          dc->priv->current_info->duration = (guint64) dur;
 -        }
 +      if (gst_element_query_duration (pipeline, GST_FORMAT_TIME, &dur)) {
 +        GST_DEBUG ("Got duration %" GST_TIME_FORMAT, GST_TIME_ARGS (dur));
 +        dc->priv->current_info->duration = (guint64) dur;
        }
  
        if (dc->priv->seeking_query) {
          if (gst_element_query (pipeline, dc->priv->seeking_query)) {
 +          GstFormat format;
            gboolean seekable;
  
            gst_query_parse_seeking (dc->priv->seeking_query, &format,
            gst_caps_get_structure (dc->priv->current_info->stream_info->caps, 0);
  
        if (g_str_has_prefix (gst_structure_get_name (st), "image/"))
 -        ((GstDiscovererVideoInfo *) dc->priv->current_info->stream_info)->
 -            is_image = TRUE;
 +        ((GstDiscovererVideoInfo *) dc->priv->current_info->
 +            stream_info)->is_image = TRUE;
      }
    }
  
@@@ -1134,20 -1138,16 +1136,20 @@@ handle_message (GstDiscoverer * dc, Gst
  
      case GST_MESSAGE_ELEMENT:
      {
 -      GQuark sttype = gst_structure_get_name_id (msg->structure);
 +      GQuark sttype;
 +      const GstStructure *structure;
 +
 +      structure = gst_message_get_structure (msg);
 +      sttype = gst_structure_get_name_id (structure);
        GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg),
 -          "structure %" GST_PTR_FORMAT, msg->structure);
 +          "structure %" GST_PTR_FORMAT, structure);
        if (sttype == _MISSING_PLUGIN_QUARK) {
          GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg),
              "Setting result to MISSING_PLUGINS");
          dc->priv->current_info->result = GST_DISCOVERER_MISSING_PLUGINS;
 -        dc->priv->current_info->misc = gst_structure_copy (msg->structure);
 +        dc->priv->current_info->misc = gst_structure_copy (structure);
        } else if (sttype == _STREAM_TOPOLOGY_QUARK) {
 -        dc->priv->current_topology = gst_structure_copy (msg->structure);
 +        dc->priv->current_topology = gst_structure_copy (structure);
        }
      }
        break;
@@@ -1221,7 -1221,7 +1223,7 @@@ _setup_locked (GstDiscoverer * dc
  
    /* Pop URI off the pending URI list */
    dc->priv->current_info =
 -      (GstDiscovererInfo *) gst_mini_object_new (GST_TYPE_DISCOVERER_INFO);
 +      (GstDiscovererInfo *) g_object_new (GST_TYPE_DISCOVERER_INFO, NULL);
    dc->priv->current_info->uri = (gchar *) dc->priv->pending_uris->data;
    dc->priv->pending_uris =
        g_list_delete_link (dc->priv->pending_uris, dc->priv->pending_uris);
  #endif
  
  #include "gstrtspconnection.h"
 -#include "gstrtspbase64.h"
  
+ #include "gst/glib-compat-private.h"
  union gst_sockaddr
  {
    struct sockaddr sa;
@@@ -3569,3 -3572,109 +3571,3 @@@ gst_rtsp_watch_send_message (GstRTSPWat
    return gst_rtsp_watch_write_data (watch,
        (guint8 *) g_string_free (str, FALSE), size, id);
  }
 -
 -/**
 - * gst_rtsp_watch_queue_data:
 - * @watch: a #GstRTSPWatch
 - * @data: the data to queue
 - * @size: the size of @data
 - *
 - * Queue @data for transmission in @watch. It will be transmitted when the
 - * connection of the @watch becomes writable.
 - *
 - * This function will take ownership of @data and g_free() it after use.
 - *
 - * The return value of this function will be used as the id argument in the
 - * message_sent callback.
 - *
 - * Deprecated: Use gst_rtsp_watch_write_data()
 - *
 - * Returns: an id.
 - *
 - * Since: 0.10.24
 - */
 -#ifndef GST_REMOVE_DEPRECATED
 -#ifdef GST_DISABLE_DEPRECATED
 -guint
 -gst_rtsp_watch_queue_data (GstRTSPWatch * watch, const guint8 * data,
 -    guint size);
 -#endif
 -guint
 -gst_rtsp_watch_queue_data (GstRTSPWatch * watch, const guint8 * data,
 -    guint size)
 -{
 -  GstRTSPRec *rec;
 -  GMainContext *context = NULL;
 -
 -  g_return_val_if_fail (watch != NULL, GST_RTSP_EINVAL);
 -  g_return_val_if_fail (data != NULL, GST_RTSP_EINVAL);
 -  g_return_val_if_fail (size != 0, GST_RTSP_EINVAL);
 -
 -  g_mutex_lock (watch->mutex);
 -
 -  /* make a record with the data and id */
 -  rec = g_slice_new (GstRTSPRec);
 -  rec->data = (guint8 *) data;
 -  rec->size = size;
 -  do {
 -    /* make sure rec->id is never 0 */
 -    rec->id = ++watch->id;
 -  } while (G_UNLIKELY (rec->id == 0));
 -
 -  /* add the record to a queue. FIXME we would like to have an upper limit here */
 -  g_queue_push_head (watch->messages, rec);
 -
 -  /* make sure the main context will now also check for writability on the
 -   * socket */
 -  if (watch->writefd.events != WRITE_COND) {
 -    watch->writefd.events = WRITE_COND;
 -    context = ((GSource *) watch)->context;
 -  }
 -  g_mutex_unlock (watch->mutex);
 -
 -  if (context)
 -    g_main_context_wakeup (context);
 -
 -  return rec->id;
 -}
 -#endif /* GST_REMOVE_DEPRECATED */
 -
 -/**
 - * gst_rtsp_watch_queue_message:
 - * @watch: a #GstRTSPWatch
 - * @message: a #GstRTSPMessage
 - *
 - * Queue a @message for transmission in @watch. The contents of this
 - * message will be serialized and transmitted when the connection of the
 - * @watch becomes writable.
 - *
 - * The return value of this function will be used as the id argument in the
 - * message_sent callback.
 - *
 - * Deprecated: Use gst_rtsp_watch_send_message()
 - *
 - * Returns: an id.
 - *
 - * Since: 0.10.23
 - */
 -#ifndef GST_REMOVE_DEPRECATED
 -#ifdef GST_DISABLE_DEPRECATED
 -guint
 -gst_rtsp_watch_queue_message (GstRTSPWatch * watch, GstRTSPMessage * message);
 -#endif
 -guint
 -gst_rtsp_watch_queue_message (GstRTSPWatch * watch, GstRTSPMessage * message)
 -{
 -  GString *str;
 -  guint size;
 -
 -  g_return_val_if_fail (watch != NULL, GST_RTSP_EINVAL);
 -  g_return_val_if_fail (message != NULL, GST_RTSP_EINVAL);
 -
 -  /* make a record with the message as a string and id */
 -  str = message_to_string (watch->conn, message);
 -  size = str->len;
 -  return gst_rtsp_watch_queue_data (watch,
 -      (guint8 *) g_string_free (str, FALSE), size);
 -}
 -#endif /* GST_REMOVE_DEPRECATED */
@@@ -22,6 -22,8 +22,8 @@@
  #include <string.h>
  #include "video.h"
  
+ #include "gst/glib-compat-private.h"
  static gboolean
  caps_are_raw (const GstCaps * caps)
  {
@@@ -31,7 -33,8 +33,7 @@@
  
    for (i = 0; i < len; i++) {
      GstStructure *st = gst_caps_get_structure (caps, i);
 -    if (gst_structure_has_name (st, "video/x-raw-yuv") ||
 -        gst_structure_has_name (st, "video/x-raw-rgb"))
 +    if (gst_structure_has_name (st, "video/x-raw"))
        return TRUE;
    }
  
@@@ -119,7 -122,7 +121,7 @@@ build_convert_frame_pipeline (GstElemen
    /* videoscale is here to correct for the pixel-aspect-ratio for us */
    GST_DEBUG ("creating elements");
    if (!create_element ("appsrc", &src, &error) ||
 -      !create_element ("ffmpegcolorspace", &csp, &error) ||
 +      !create_element ("videoconvert", &csp, &error) ||
        !create_element ("videoscale", &vscale, &error) ||
        !create_element ("appsink", &sink, &error))
      goto no_elements;
      goto link_failed;
  
    GST_DEBUG ("linking csp->vscale");
 -  if (!gst_element_link_pads (csp, "src", vscale, "sink"))
 +  if (!gst_element_link_pads_full (csp, "src", vscale, "sink",
 +          GST_PAD_LINK_CHECK_NOTHING))
      goto link_failed;
  
    if (caps_are_raw (to_caps)) {
      GST_DEBUG ("linking vscale->sink");
  
 -    if (!gst_element_link_pads (vscale, "src", sink, "sink"))
 +    if (!gst_element_link_pads_full (vscale, "src", sink, "sink",
 +            GST_PAD_LINK_CHECK_NOTHING))
        goto link_failed;
    } else {
      encoder = get_encoder (to_caps, &error);
@@@ -232,8 -233,8 +234,8 @@@ link_failed
  }
  
  /**
 - * gst_video_convert_frame:
 - * @buf: a #GstBuffer
 + * gst_video_convert_sample:
 + * @sample: a #GstSample
   * @to_caps: the #GstCaps to convert to
   * @timeout: the maximum amount of time allowed for the processing.
   * @error: pointer to a #GError. Can be %NULL.
   *
   * The width, height and pixel-aspect-ratio can also be specified in the output caps.
   *
 - * Returns: The converted #GstBuffer, or %NULL if an error happened (in which case @err
 + * Returns: The converted #GstSample, or %NULL if an error happened (in which case @err
   * will point to the #GError).
   *
   * Since: 0.10.31
   *
   */
 -GstBuffer *
 -gst_video_convert_frame (GstBuffer * buf, const GstCaps * to_caps,
 +GstSample *
 +gst_video_convert_sample (GstSample * sample, const GstCaps * to_caps,
      GstClockTime timeout, GError ** error)
  {
    GstMessage *msg;
 -  GstBuffer *result = NULL;
 +  GstBuffer *buf;
 +  GstSample *result = NULL;
    GError *err = NULL;
    GstBus *bus;
    GstCaps *from_caps, *to_caps_copy = NULL;
    GstElement *pipeline, *src, *sink;
    guint i, n;
  
 -  g_return_val_if_fail (buf != NULL, NULL);
 +  g_return_val_if_fail (sample != NULL, NULL);
    g_return_val_if_fail (to_caps != NULL, NULL);
 -  g_return_val_if_fail (GST_BUFFER_CAPS (buf) != NULL, NULL);
  
 -  from_caps = GST_BUFFER_CAPS (buf);
 +  buf = gst_sample_get_buffer (sample);
 +  g_return_val_if_fail (buf != NULL, NULL);
 +
 +  from_caps = gst_sample_get_caps (sample);
 +  g_return_val_if_fail (from_caps != NULL, NULL);
 +
  
    to_caps_copy = gst_caps_new_empty ();
    n = gst_caps_get_size (to_caps);
    gst_element_set_state (pipeline, GST_STATE_PAUSED);
  
    /* feed buffer in appsrc */
 -  GST_DEBUG ("feeding buffer %p, size %u, caps %" GST_PTR_FORMAT,
 -      buf, GST_BUFFER_SIZE (buf), from_caps);
 +  GST_DEBUG ("feeding buffer %p, size %" G_GSIZE_FORMAT ", caps %"
 +      GST_PTR_FORMAT, buf, gst_buffer_get_size (buf), from_caps);
    g_signal_emit_by_name (src, "push-buffer", buf, &ret);
  
    /* now see what happens. We either got an error somewhere or the pipeline
@@@ -372,30 -368,28 +374,30 @@@ typedef struc
  {
    GMutex *mutex;
    GstElement *pipeline;
 -  GstVideoConvertFrameCallback callback;
 +  GstVideoConvertSampleCallback callback;
    gpointer user_data;
    GDestroyNotify destroy_notify;
    GMainContext *context;
 -  GstBuffer *buffer;
 +  GstSample *sample;
 +  //GstBuffer *buffer;
    gulong timeout_id;
    gboolean finished;
 -} GstVideoConvertFrameContext;
 +} GstVideoConvertSampleContext;
  
  typedef struct
  {
 -  GstVideoConvertFrameCallback callback;
 -  GstBuffer *buffer;
 +  GstVideoConvertSampleCallback callback;
 +  GstSample *sample;
 +  //GstBuffer *buffer;
    GError *error;
    gpointer user_data;
    GDestroyNotify destroy_notify;
  
 -  GstVideoConvertFrameContext *context;
 -} GstVideoConvertFrameCallbackContext;
 +  GstVideoConvertSampleContext *context;
 +} GstVideoConvertSampleCallbackContext;
  
  static void
 -gst_video_convert_frame_context_free (GstVideoConvertFrameContext * ctx)
 +gst_video_convert_frame_context_free (GstVideoConvertSampleContext * ctx)
  {
    /* Wait until all users of the mutex are done */
    g_mutex_lock (ctx->mutex);
    g_mutex_free (ctx->mutex);
    if (ctx->timeout_id)
      g_source_remove (ctx->timeout_id);
 -  if (ctx->buffer)
 -    gst_buffer_unref (ctx->buffer);
 +  //if (ctx->buffer)
 +  //  gst_buffer_unref (ctx->buffer);
 +  if (ctx->sample)
 +    gst_sample_unref (ctx->sample);
    g_main_context_unref (ctx->context);
  
    gst_element_set_state (ctx->pipeline, GST_STATE_NULL);
    gst_object_unref (ctx->pipeline);
  
 -  g_slice_free (GstVideoConvertFrameContext, ctx);
 +  g_slice_free (GstVideoConvertSampleContext, ctx);
  }
  
  static void
      gst_video_convert_frame_callback_context_free
 -    (GstVideoConvertFrameCallbackContext * ctx)
 +    (GstVideoConvertSampleCallbackContext * ctx)
  {
    if (ctx->context)
      gst_video_convert_frame_context_free (ctx->context);
 -  g_slice_free (GstVideoConvertFrameCallbackContext, ctx);
 +  g_slice_free (GstVideoConvertSampleCallbackContext, ctx);
  }
  
  static gboolean
 -convert_frame_dispatch_callback (GstVideoConvertFrameCallbackContext * ctx)
 +convert_frame_dispatch_callback (GstVideoConvertSampleCallbackContext * ctx)
  {
 -  ctx->callback (ctx->buffer, ctx->error, ctx->user_data);
 +  ctx->callback (ctx->sample, ctx->error, ctx->user_data);
  
    if (ctx->destroy_notify)
      ctx->destroy_notify (ctx->user_data);
  }
  
  static void
 -convert_frame_finish (GstVideoConvertFrameContext * context, GstBuffer * buffer,
 -    GError * error)
 +convert_frame_finish (GstVideoConvertSampleContext * context,
 +    GstSample * sample, GError * error)
  {
    GSource *source;
 -  GstVideoConvertFrameCallbackContext *ctx;
 +  GstVideoConvertSampleCallbackContext *ctx;
  
    if (context->timeout_id)
      g_source_remove (context->timeout_id);
    context->timeout_id = 0;
  
 -  ctx = g_slice_new (GstVideoConvertFrameCallbackContext);
 +  ctx = g_slice_new (GstVideoConvertSampleCallbackContext);
    ctx->callback = context->callback;
    ctx->user_data = context->user_data;
    ctx->destroy_notify = context->destroy_notify;
 -  ctx->buffer = buffer;
 +  ctx->sample = sample;
 +  //ctx->buffer = buffer;
    ctx->error = error;
    ctx->context = context;
  
  }
  
  static gboolean
 -convert_frame_timeout_callback (GstVideoConvertFrameContext * context)
 +convert_frame_timeout_callback (GstVideoConvertSampleContext * context)
  {
    GError *error;
  
@@@ -489,7 -480,7 +491,7 @@@ done
  
  static gboolean
  convert_frame_bus_callback (GstBus * bus, GstMessage * message,
 -    GstVideoConvertFrameContext * context)
 +    GstVideoConvertSampleContext * context)
  {
    g_mutex_lock (context->mutex);
  
@@@ -523,21 -514,19 +525,21 @@@ done
  
  static void
  convert_frame_need_data_callback (GstElement * src, guint size,
 -    GstVideoConvertFrameContext * context)
 +    GstVideoConvertSampleContext * context)
  {
    GstFlowReturn ret = GST_FLOW_ERROR;
    GError *error;
 +  GstBuffer *buffer;
  
    g_mutex_lock (context->mutex);
  
    if (context->finished)
      goto done;
  
 -  g_signal_emit_by_name (src, "push-buffer", context->buffer, &ret);
 -  gst_buffer_unref (context->buffer);
 -  context->buffer = NULL;
 +  buffer = gst_sample_get_buffer (context->sample);
 +  g_signal_emit_by_name (src, "push-buffer", buffer, &ret);
 +  gst_sample_unref (context->sample);
 +  context->sample = NULL;
  
    if (ret != GST_FLOW_OK) {
      GST_ERROR ("Could not push video frame: %s", gst_flow_get_name (ret));
@@@ -556,10 -545,10 +558,10 @@@ done
  }
  
  static void
 -convert_frame_new_buffer_callback (GstElement * sink,
 -    GstVideoConvertFrameContext * context)
 +convert_frame_new_preroll_callback (GstElement * sink,
 +    GstVideoConvertSampleContext * context)
  {
 -  GstBuffer *buf = NULL;
 +  GstSample *sample = NULL;
    GError *error = NULL;
  
    g_mutex_lock (context->mutex);
    if (context->finished)
      goto done;
  
 -  g_signal_emit_by_name (sink, "pull-preroll", &buf);
 +  g_signal_emit_by_name (sink, "pull-preroll", &sample);
  
 -  if (!buf) {
 +  if (!sample) {
      error = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_FAILED,
 -        "Could not get converted video frame");
 +        "Could not get converted video sample");
    }
 -
 -  convert_frame_finish (context, buf, error);
 +  convert_frame_finish (context, sample, error);
  
    g_signal_handlers_disconnect_by_func (sink, convert_frame_need_data_callback,
        context);
@@@ -583,11 -573,11 +585,11 @@@ done
  }
  
  /**
 - * gst_video_convert_frame_async:
 - * @buf: a #GstBuffer
 + * gst_video_convert_sample_async:
 + * @sample: a #GstSample
   * @to_caps: the #GstCaps to convert to
   * @timeout: the maximum amount of time allowed for the processing.
 - * @callback: %GstVideoConvertFrameCallback that will be called after conversion.
 + * @callback: %GstVideoConvertSampleCallback that will be called after conversion.
   * @user_data: extra data that will be passed to the @callback
   * @destroy_notify: %GDestroyNotify to be called after @user_data is not needed anymore
   *
   *
   */
  void
 -gst_video_convert_frame_async (GstBuffer * buf, const GstCaps * to_caps,
 -    GstClockTime timeout, GstVideoConvertFrameCallback callback,
 -    gpointer user_data, GDestroyNotify destroy_notify)
 +gst_video_convert_sample_async (GstSample * sample,
 +    const GstCaps * to_caps, GstClockTime timeout,
 +    GstVideoConvertSampleCallback callback, gpointer user_data,
 +    GDestroyNotify destroy_notify)
  {
    GMainContext *context = NULL;
    GError *error = NULL;
    GstBus *bus;
 +  GstBuffer *buf;
    GstCaps *from_caps, *to_caps_copy = NULL;
    GstElement *pipeline, *src, *sink;
    guint i, n;
    GSource *source;
 -  GstVideoConvertFrameContext *ctx;
 +  GstVideoConvertSampleContext *ctx;
  
 +  g_return_if_fail (sample != NULL);
 +  buf = gst_sample_get_buffer (sample);
    g_return_if_fail (buf != NULL);
 +
    g_return_if_fail (to_caps != NULL);
 -  g_return_if_fail (GST_BUFFER_CAPS (buf) != NULL);
 +
 +  from_caps = gst_sample_get_caps (sample);
 +  g_return_if_fail (from_caps != NULL);
    g_return_if_fail (callback != NULL);
  
    context = g_main_context_get_thread_default ();
    if (!context)
      context = g_main_context_default ();
  
 -  from_caps = GST_BUFFER_CAPS (buf);
 -
    to_caps_copy = gst_caps_new_empty ();
    n = gst_caps_get_size (to_caps);
    for (i = 0; i < n; i++) {
  
    bus = gst_element_get_bus (pipeline);
  
 -  ctx = g_slice_new0 (GstVideoConvertFrameContext);
 +  ctx = g_slice_new0 (GstVideoConvertSampleContext);
    ctx->mutex = g_mutex_new ();
 -  ctx->buffer = gst_buffer_ref (buf);
 +  //ctx->buffer = gst_buffer_ref (buf);
 +  ctx->sample = gst_sample_ref (sample);
    ctx->callback = callback;
    ctx->user_data = user_data;
    ctx->destroy_notify = destroy_notify;
    g_signal_connect (src, "need-data",
        G_CALLBACK (convert_frame_need_data_callback), ctx);
    g_signal_connect (sink, "new-preroll",
 -      G_CALLBACK (convert_frame_new_buffer_callback), ctx);
 +      G_CALLBACK (convert_frame_new_preroll_callback), ctx);
  
    source = gst_bus_create_watch (bus);
    g_source_set_callback (source, (GSourceFunc) convert_frame_bus_callback,
    /* ERRORS */
  no_pipeline:
    {
 -    GstVideoConvertFrameCallbackContext *ctx;
 +    GstVideoConvertSampleCallbackContext *ctx;
      GSource *source;
  
      gst_caps_unref (to_caps_copy);
  
 -    ctx = g_slice_new0 (GstVideoConvertFrameCallbackContext);
 +    ctx = g_slice_new0 (GstVideoConvertSampleCallbackContext);
      ctx->callback = callback;
      ctx->user_data = user_data;
      ctx->destroy_notify = destroy_notify;
 -    ctx->buffer = NULL;
 +    ctx->sample = NULL;
      ctx->error = error;
  
      source = g_timeout_source_new (0);
@@@ -1,6 -1,7 +1,6 @@@
 -/* GStreamer X-based Overlay
 +/* GStreamer Video Overlay interface
   * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
 - *
 - * x-overlay.c: X-based overlay interface design
 + * Copyright (C) 2011 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
   * Boston, MA 02111-1307, USA.
   */
  /**
 - * SECTION:gstxoverlay
 - * @short_description: Interface for setting/getting a Window on elements
 - * supporting it
 + * SECTION:gstvideooverlay
 + * @short_description: Interface for setting/getting a window system resource
 + *    on elements supporting it to configure a window into which to render a
 + *    video.
   *
   * <refsect2>
   * <para>
 - * The XOverlay interface is used for 2 main purposes :
 + * The #GstVideoOverlay interface is used for 2 main purposes :
   * <itemizedlist>
   * <listitem>
   * <para>
   * static GstBusSyncReply
   * create_window (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
   * {
 - *  // ignore anything but 'prepare-xwindow-id' element messages
 - *  if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
 - *    return GST_BUS_PASS;
 - *
 - *  if (!gst_structure_has_name (message-&gt;structure, "prepare-xwindow-id"))
 + *  // ignore anything but 'prepare-window-handle' element messages
 + *  if (!gst_is_video_overlay_prepare_window_handle_message (message))
   *    return GST_BUS_PASS;
   *
   *  win = XCreateSimpleWindow (disp, root, 0, 0, 320, 240, 0, 0, 0);
@@@ -75,7 -78,7 +75,7 @@@
   *
   *  XSync (disp, FALSE);
   *
 - *  gst_x_overlay_set_window_handle (GST_X_OVERLAY (GST_MESSAGE_SRC (message)),
 + *  gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message)),
   *      win);
   *
   *  gst_message_unref (message);
   * usually the case when the application creates the videosink to use
   * (e.g. #xvimagesink, #ximagesink, etc.) itself; in this case, the application
   * can just create the videosink element, create and realize the window to
 - * render the video on and then call gst_x_overlay_set_window_handle() directly
 + * render the video on and then call gst_video_overlay_set_window_handle() directly
   * with the XID or native window handle, before starting up the pipeline.
   * </para>
   * <para>
   * pipeline has been started up. When that happens, however, the video sink
   * will need to know right then whether to render onto an already existing
   * application window or whether to create its own window. This is when it
 - * posts a prepare-xwindow-id message, and that is also why this message needs
 + * posts a prepare-window-handle message, and that is also why this message needs
   * to be handled in a sync bus handler which will be called from the streaming
   * thread directly (because the video sink will need an answer right then).
   * </para>
   * <para>
 - * As response to the prepare-xwindow-id element message in the bus sync
 - * handler, the application may use gst_x_overlay_set_window_handle() to tell
 + * As response to the prepare-window-handle element message in the bus sync
 + * handler, the application may use gst_video_overlay_set_window_handle() to tell
   * the video sink to render onto an existing window surface. At this point the
   * application should already have obtained the window handle / XID, so it
   * just needs to set it. It is generally not advisable to call any GUI toolkit
   * functions or window system functions from the streaming thread in which the
 - * prepare-xwindow-id message is handled, because most GUI toolkits and
 + * prepare-window-handle message is handled, because most GUI toolkits and
   * windowing systems are not thread-safe at all and a lot of care would be
   * required to co-ordinate the toolkit and window system calls of the
   * different threads (Gtk+ users please note: prior to Gtk+ 2.18
   * </para>
   * </refsect2>
   * <refsect2>
 - * <title>GstXOverlay and Gtk+</title>
 + * <title>GstVideoOverlay and Gtk+</title>
   * <para>
   * |[
+  * #include &lt;gst/interfaces/xoverlay.h&gt;
   * #include &lt;gtk/gtk.h&gt;
   * #ifdef GDK_WINDOWING_X11
   * #include &lt;gdk/gdkx.h&gt;  // for GDK_WINDOW_XID
   * static GstBusSyncReply
   * bus_sync_handler (GstBus * bus, GstMessage * message, gpointer user_data)
   * {
 - *  // ignore anything but 'prepare-xwindow-id' element messages
 - *  if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
 - *    return GST_BUS_PASS;
 - *  if (!gst_structure_has_name (message-&gt;structure, "prepare-xwindow-id"))
 + *  // ignore anything but 'prepare-window-handle' element messages
 + *  if (!gst_is_video_overlay_prepare_window_handle_message (message))
   *    return GST_BUS_PASS;
   *
   *  if (video_window_xid != 0) {
 - *    GstXOverlay *xoverlay;
 + *    GstVideoOverlay *xoverlay;
   *
   *    // GST_MESSAGE_SRC (message) will be the video sink element
 - *    xoverlay = GST_X_OVERLAY (GST_MESSAGE_SRC (message));
 - *    gst_x_overlay_set_window_handle (xoverlay, video_window_xid);
 + *    xoverlay = GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message));
 + *    gst_video_overlay_set_window_handle (xoverlay, video_window_xid);
   *  } else {
   *    g_warning ("Should have obtained video_window_xid by now!");
   *  }
   *   // This is here just for pedagogical purposes, GDK_WINDOW_XID will call
   *   // it as well in newer Gtk versions
   *   if (!gdk_window_ensure_native (widget->window))
 - *     g_error ("Couldn't create native window needed for GstXOverlay!");
 + *     g_error ("Couldn't create native window needed for GstVideoOverlay!");
   * #endif
   *
   * #ifdef GDK_WINDOWING_X11
-  *   video_window_xid = GDK_WINDOW_XID (video_window->window);
+  *   video_window_xid = GDK_WINDOW_XID (gtk_widget_get_window (video_window));
   * #endif
   * }
   * ...
   *   // realize window now so that the video window gets created and we can
   *   // obtain its XID before the pipeline is started up and the videosink
   *   // asks for the XID of the window to render onto
-  *   gtk_widget_realize (window);
+  *   gtk_widget_realize (video_window);
   *
   *   // we should have the XID now
   *   g_assert (video_window_xid != 0);
   * </para>
   * </refsect2>
   * <refsect2>
 - * <title>GstXOverlay and Qt</title>
 + * <title>GstVideoOverlay and Qt</title>
   * <para>
   * |[
   * #include &lt;glib.h&gt;
   * #include &lt;gst/gst.h&gt;
 - * #include &lt;gst/interfaces/xoverlay.h&gt;
 + * #include &lt;gst/interfaces/videooverlay.h&gt;
   *
   * #include &lt;QApplication&gt;
   * #include &lt;QTimer&gt;
   *   window.show();
   *
   *   WId xwinid = window.winId();
 - *   gst_x_overlay_set_window_handle (GST_X_OVERLAY (sink), xwinid);
 + *   gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink), xwinid);
   *
   *   // run the pipeline
   *
  #include "config.h"
  #endif
  
 -#include "xoverlay.h"
 -
 -static void gst_x_overlay_base_init (gpointer g_class);
 +#include "videooverlay.h"
  
  GType
 -gst_x_overlay_get_type (void)
 +gst_video_overlay_get_type (void)
  {
 -  static GType gst_x_overlay_type = 0;
 +  static GType gst_video_overlay_type = 0;
  
 -  if (!gst_x_overlay_type) {
 -    static const GTypeInfo gst_x_overlay_info = {
 -      sizeof (GstXOverlayClass),
 -      gst_x_overlay_base_init,
 +  if (!gst_video_overlay_type) {
 +    static const GTypeInfo gst_video_overlay_info = {
 +      sizeof (GstVideoOverlayInterface),
 +      NULL,
        NULL,
        NULL,
        NULL,
        NULL,
      };
  
 -    gst_x_overlay_type = g_type_register_static (G_TYPE_INTERFACE,
 -        "GstXOverlay", &gst_x_overlay_info, 0);
 -    g_type_interface_add_prerequisite (gst_x_overlay_type,
 -        GST_TYPE_IMPLEMENTS_INTERFACE);
 +    gst_video_overlay_type = g_type_register_static (G_TYPE_INTERFACE,
 +        "GstVideoOverlay", &gst_video_overlay_info, 0);
    }
  
 -  return gst_x_overlay_type;
 -}
 -
 -static void
 -gst_x_overlay_base_init (gpointer g_class)
 -{
 -
 +  return gst_video_overlay_type;
  }
  
  /**
 - * gst_x_overlay_set_xwindow_id:
 - * @overlay: a #GstXOverlay to set the window on.
 - * @xwindow_id: a XID referencing the XWindow.
 - *
 - * This will call the video overlay's set_xwindow_id method. You should
 - * use this method to tell to a XOverlay to display video output to a
 - * specific XWindow. Passing 0 as the @xwindow_id will tell the overlay to
 - * stop using that window and create an internal one.
 - *
 - * Deprecated: Use gst_x_overlay_set_window_handle() instead.
 - */
 -#ifndef GST_REMOVE_DEPRECATED
 -#ifdef GST_DISABLE_DEPRECATED
 -void gst_x_overlay_set_xwindow_id (GstXOverlay * overlay, gulong xwindow_id);
 -#endif
 -void
 -gst_x_overlay_set_xwindow_id (GstXOverlay * overlay, gulong xwindow_id)
 -{
 -  GST_WARNING_OBJECT (overlay,
 -      "Using deprecated gst_x_overlay_set_xwindow_id()");
 -  gst_x_overlay_set_window_handle (overlay, xwindow_id);
 -}
 -#endif
 -
 -/**
 - * gst_x_overlay_set_window_handle:
 - * @overlay: a #GstXOverlay to set the window on.
 + * gst_video_overlay_set_window_handle:
 + * @overlay: a #GstVideoOverlay to set the window on.
   * @handle: a handle referencing the window.
   *
   * This will call the video overlay's set_window_handle method. You
   * Since: 0.10.31
   */
  void
 -gst_x_overlay_set_window_handle (GstXOverlay * overlay, guintptr handle)
 +gst_video_overlay_set_window_handle (GstVideoOverlay * overlay, guintptr handle)
  {
 -  GstXOverlayClass *klass;
 +  GstVideoOverlayInterface *iface;
  
    g_return_if_fail (overlay != NULL);
 -  g_return_if_fail (GST_IS_X_OVERLAY (overlay));
 +  g_return_if_fail (GST_IS_VIDEO_OVERLAY (overlay));
  
 -  klass = GST_X_OVERLAY_GET_CLASS (overlay);
 +  iface = GST_VIDEO_OVERLAY_GET_INTERFACE (overlay);
  
 -  if (klass->set_window_handle) {
 -    klass->set_window_handle (overlay, handle);
 -  } else {
 -#ifndef GST_REMOVE_DEPRECATED
 -#ifdef GST_DISABLE_DEPRECATED
 -#define set_xwindow_id set_xwindow_id_disabled
 -#endif
 -    if (sizeof (guintptr) <= sizeof (gulong) && klass->set_xwindow_id) {
 -      GST_WARNING_OBJECT (overlay,
 -          "Calling deprecated set_xwindow_id() method");
 -      klass->set_xwindow_id (overlay, handle);
 -    } else {
 -      g_warning ("Refusing to cast guintptr to smaller gulong");
 -    }
 -#endif
 +  if (iface->set_window_handle) {
 +    iface->set_window_handle (overlay, handle);
    }
  }
  
  /**
 - * gst_x_overlay_got_xwindow_id:
 - * @overlay: a #GstXOverlay which got a XWindow.
 - * @xwindow_id: a XID referencing the XWindow.
 - *
 - * This will post a "have-xwindow-id" element message on the bus.
 - *
 - * This function should only be used by video overlay plugin developers.
 - *
 - * Deprecated: Use gst_x_overlay_got_window_handle() instead.
 - */
 -#ifndef GST_REMOVE_DEPRECATED
 -#ifdef GST_DISABLE_DEPRECATED
 -void gst_x_overlay_got_xwindow_id (GstXOverlay * overlay, gulong xwindow_id);
 -#endif
 -void
 -gst_x_overlay_got_xwindow_id (GstXOverlay * overlay, gulong xwindow_id)
 -{
 -  GST_WARNING_OBJECT (overlay,
 -      "Using deprecated gst_x_overlay_got_xwindow_id()");
 -  gst_x_overlay_got_window_handle (overlay, xwindow_id);
 -}
 -#endif
 -
 -/**
 - * gst_x_overlay_got_window_handle:
 - * @overlay: a #GstXOverlay which got a window
 + * gst_video_overlay_got_window_handle:
 + * @overlay: a #GstVideoOverlay which got a window
   * @handle: a platform-specific handle referencing the window
   *
 - * This will post a "have-xwindow-id" element message on the bus.
 + * This will post a "have-window-handle" element message on the bus.
   *
   * This function should only be used by video overlay plugin developers.
   */
  void
 -gst_x_overlay_got_window_handle (GstXOverlay * overlay, guintptr handle)
 +gst_video_overlay_got_window_handle (GstVideoOverlay * overlay, guintptr handle)
  {
    GstStructure *s;
    GstMessage *msg;
  
    g_return_if_fail (overlay != NULL);
 -  g_return_if_fail (GST_IS_X_OVERLAY (overlay));
 +  g_return_if_fail (GST_IS_VIDEO_OVERLAY (overlay));
  
 -  GST_LOG_OBJECT (GST_OBJECT (overlay), "xwindow_id = %p", (gpointer)
 +  GST_LOG_OBJECT (GST_OBJECT (overlay), "window_handle = %p", (gpointer)
        handle);
 -  s = gst_structure_new ("have-xwindow-id",
 -      "xwindow-id", G_TYPE_ULONG, (unsigned long) handle,
 +  s = gst_structure_new ("have-window-handle",
        "window-handle", G_TYPE_UINT64, (guint64) handle, NULL);
    msg = gst_message_new_element (GST_OBJECT (overlay), s);
    gst_element_post_message (GST_ELEMENT (overlay), msg);
  }
  
  /**
 - * gst_x_overlay_prepare_xwindow_id:
 - * @overlay: a #GstXOverlay which does not yet have an XWindow.
 + * gst_video_overlay_prepare_window_handle:
 + * @overlay: a #GstVideoOverlay which does not yet have an Window handle set
   *
 - * This will post a "prepare-xwindow-id" element message on the bus
 + * This will post a "prepare-window-handle" element message on the bus
   * to give applications an opportunity to call
 - * gst_x_overlay_set_xwindow_id() before a plugin creates its own
 + * gst_video_overlay_set_window_handle() before a plugin creates its own
   * window.
   *
   * This function should only be used by video overlay plugin developers.
   */
  void
 -gst_x_overlay_prepare_xwindow_id (GstXOverlay * overlay)
 +gst_video_overlay_prepare_window_handle (GstVideoOverlay * overlay)
  {
    GstStructure *s;
    GstMessage *msg;
  
    g_return_if_fail (overlay != NULL);
 -  g_return_if_fail (GST_IS_X_OVERLAY (overlay));
 +  g_return_if_fail (GST_IS_VIDEO_OVERLAY (overlay));
  
 -  GST_LOG_OBJECT (GST_OBJECT (overlay), "prepare xwindow_id");
 -  s = gst_structure_new ("prepare-xwindow-id", NULL);
 +  GST_LOG_OBJECT (GST_OBJECT (overlay), "prepare window handle");
 +  s = gst_structure_new_empty ("prepare-window-handle");
    msg = gst_message_new_element (GST_OBJECT (overlay), s);
    gst_element_post_message (GST_ELEMENT (overlay), msg);
  }
  
  /**
 - * gst_x_overlay_expose:
 - * @overlay: a #GstXOverlay to expose.
 + * gst_video_overlay_expose:
 + * @overlay: a #GstVideoOverlay to expose.
   *
   * Tell an overlay that it has been exposed. This will redraw the current frame
   * in the drawable even if the pipeline is PAUSED.
   */
  void
 -gst_x_overlay_expose (GstXOverlay * overlay)
 +gst_video_overlay_expose (GstVideoOverlay * overlay)
  {
 -  GstXOverlayClass *klass;
 +  GstVideoOverlayInterface *iface;
  
    g_return_if_fail (overlay != NULL);
 -  g_return_if_fail (GST_IS_X_OVERLAY (overlay));
 +  g_return_if_fail (GST_IS_VIDEO_OVERLAY (overlay));
  
 -  klass = GST_X_OVERLAY_GET_CLASS (overlay);
 +  iface = GST_VIDEO_OVERLAY_GET_INTERFACE (overlay);
  
 -  if (klass->expose) {
 -    klass->expose (overlay);
 +  if (iface->expose) {
 +    iface->expose (overlay);
    }
  }
  
  /**
 - * gst_x_overlay_handle_events:
 - * @overlay: a #GstXOverlay to expose.
 + * gst_video_overlay_handle_events:
 + * @overlay: a #GstVideoOverlay to expose.
   * @handle_events: a #gboolean indicating if events should be handled or not.
   *
   * Tell an overlay that it should handle events from the window system. These
   * Since: 0.10.12
   */
  void
 -gst_x_overlay_handle_events (GstXOverlay * overlay, gboolean handle_events)
 +gst_video_overlay_handle_events (GstVideoOverlay * overlay,
 +    gboolean handle_events)
  {
 -  GstXOverlayClass *klass;
 +  GstVideoOverlayInterface *iface;
  
    g_return_if_fail (overlay != NULL);
 -  g_return_if_fail (GST_IS_X_OVERLAY (overlay));
 +  g_return_if_fail (GST_IS_VIDEO_OVERLAY (overlay));
  
 -  klass = GST_X_OVERLAY_GET_CLASS (overlay);
 +  iface = GST_VIDEO_OVERLAY_GET_INTERFACE (overlay);
  
 -  if (klass->handle_events) {
 -    klass->handle_events (overlay, handle_events);
 +  if (iface->handle_events) {
 +    iface->handle_events (overlay, handle_events);
    }
  }
  
  /**
 - * gst_x_overlay_set_render_rectangle:
 - * @overlay: a #GstXOverlay
 + * gst_video_overlay_set_render_rectangle:
 + * @overlay: a #GstVideoOverlay
   * @x: the horizontal offset of the render area inside the window
   * @y: the vertical offset of the render area inside the window
   * @width: the width of the render area inside the window
   * @height: the height of the render area inside the window
   *
   * Configure a subregion as a video target within the window set by
 - * gst_x_overlay_set_window_handle(). If this is not used or not supported
 + * gst_video_overlay_set_window_handle(). If this is not used or not supported
   * the video will fill the area of the window set as the overlay to 100%.
   * By specifying the rectangle, the video can be overlayed to a specific region
   * of that window only. After setting the new rectangle one should call
 - * gst_x_overlay_expose() to force a redraw. To unset the region pass -1 for
 + * gst_video_overlay_expose() to force a redraw. To unset the region pass -1 for
   * the @width and @height parameters.
   *
   * This method is needed for non fullscreen video overlay in UI toolkits that
   * Since: 0.10.29
   */
  gboolean
 -gst_x_overlay_set_render_rectangle (GstXOverlay * overlay,
 +gst_video_overlay_set_render_rectangle (GstVideoOverlay * overlay,
      gint x, gint y, gint width, gint height)
  {
 -  GstXOverlayClass *klass;
 +  GstVideoOverlayInterface *iface;
  
    g_return_val_if_fail (overlay != NULL, FALSE);
 -  g_return_val_if_fail (GST_IS_X_OVERLAY (overlay), FALSE);
 +  g_return_val_if_fail (GST_IS_VIDEO_OVERLAY (overlay), FALSE);
    g_return_val_if_fail ((width == -1 && height == -1) ||
        (width > 0 && height > 0), FALSE);
  
 -  klass = GST_X_OVERLAY_GET_CLASS (overlay);
 +  iface = GST_VIDEO_OVERLAY_GET_INTERFACE (overlay);
  
 -  if (klass->set_render_rectangle) {
 -    klass->set_render_rectangle (overlay, x, y, width, height);
 +  if (iface->set_render_rectangle) {
 +    iface->set_render_rectangle (overlay, x, y, width, height);
      return TRUE;
    }
    return FALSE;
  }
 +
 +/**
 + * gst_is_video_overlay_prepare_window_handle_message:
 + * @msg: a #GstMessage
 + *
 + * Convenience function to check if the given message is a
 + * "prepare-window-handle" message from a #GstVideoOverlay.
 + *
 + * Since: 0.11.2
 + *
 + * Returns: whether @msg is a "prepare-window-handle" message
 + */
 +gboolean
 +gst_is_video_overlay_prepare_window_handle_message (GstMessage * msg)
 +{
 +  g_return_val_if_fail (msg != NULL, FALSE);
 +
 +  if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ELEMENT)
 +    return FALSE;
 +
 +  return gst_message_has_name (msg, "prepare-window-handle");
 +}
  #include "config.h"
  #endif
  
+ /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+  * with newer GLib versions (>= 2.31.0) */
+ #define GLIB_DISABLE_DEPRECATION_WARNINGS
  #include <gst/gst-i18n-plugin.h>
  
  #include <string.h>
  #include <gst/gst.h>
  #include <gst/pbutils/pbutils.h>
+ #include "gst/glib-compat-private.h"
  
  #include "gstplay-marshal.h"
  
@@@ -56,7 -61,7 +61,7 @@@ GST_STATIC_PAD_TEMPLATE ("sink"
      GST_STATIC_CAPS_ANY);
  
  static GstStaticPadTemplate decoder_bin_src_template =
 -GST_STATIC_PAD_TEMPLATE ("src%d",
 +GST_STATIC_PAD_TEMPLATE ("src_%u",
      GST_PAD_SRC,
      GST_PAD_SOMETIMES,
      GST_STATIC_CAPS_ANY);
@@@ -92,7 -97,7 +97,7 @@@ struct _GstDecodeBi
    GList *probes;                /* list of PadProbeData */
  
    GList *factories;             /* factories we can use for selecting elements */
 -  gint numpads;
 +  guint numpads;
    gint numwaiting;
  
    gboolean have_type;
@@@ -287,10 -292,10 +292,10 @@@ gst_decode_bin_class_init (GstDecodeBin
            "The caps of the input data. (NULL = use typefind element)",
            GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
 -  gst_element_class_add_static_pad_template (gstelement_klass,
 -      &decoder_bin_sink_template);
 -  gst_element_class_add_static_pad_template (gstelement_klass,
 -      &decoder_bin_src_template);
 +  gst_element_class_add_pad_template (gstelement_klass,
 +      gst_static_pad_template_get (&decoder_bin_sink_template));
 +  gst_element_class_add_pad_template (gstelement_klass,
 +      gst_static_pad_template_get (&decoder_bin_src_template));
  
    gst_element_class_set_details_simple (gstelement_klass,
        "Decoder Bin", "Generic/Bin/Decoder",
@@@ -917,7 -922,7 +922,7 @@@ close_pad_link (GstElement * element, G
      }
  
      /* make a unique name for this new pad */
 -    padname = g_strdup_printf ("src%d", decode_bin->numpads);
 +    padname = g_strdup_printf ("src_%u", decode_bin->numpads);
      decode_bin->numpads++;
  
      /* make it a ghostpad */
   */
  
  /**
 - * SECTION:element-decodebin2
 + * SECTION:element-decodebin
   *
   * #GstBin that auto-magically constructs a decoding pipeline using available
   * decoders and demuxers via auto-plugging.
   *
 - * decodebin2 is considered stable now and replaces the old #decodebin element.
 - * #uridecodebin uses decodebin2 internally and is often more convenient to
 + * decodebin is considered stable now and replaces the old #decodebin element.
 + * #uridecodebin uses decodebin internally and is often more convenient to
   * use, as it creates a suitable source element as well.
   */
  
  /* Implementation notes:
   *
 - * The following section describes how decodebin2 works internally.
 + * The following section describes how decodebin works internally.
   *
 - * The first part of decodebin2 is its typefind element, which tries
 + * The first part of decodebin is its typefind element, which tries
   * to determine the media type of the input stream. If the type is found
   * autoplugging starts.
   *
 - * decodebin2 internally organizes the elements it autoplugged into GstDecodeChains
 + * decodebin internally organizes the elements it autoplugged into GstDecodeChains
   * and GstDecodeGroups. A decode chain is a single chain of decoding, this
 - * means that if decodebin2 every autoplugs an element with two+ srcpads
 + * means that if decodebin every autoplugs an element with two+ srcpads
   * (e.g. a demuxer) this will end the chain and everything following this
   * demuxer will be put into decode groups below the chain. Otherwise,
   * if an element has a single srcpad that outputs raw data the decode chain
   * chains are complete.
   *
   * If this happens at some point, all endpads of all active groups are exposed.
 - * For this decodebin2 adds the endpads, signals no-more-pads and then unblocks
 + * For this decodebin adds the endpads, signals no-more-pads and then unblocks
   * them. Now playback starts.
   *
 - * If one of the chains that end on a endpad receives EOS decodebin2 checks
 + * If one of the chains that end on a endpad receives EOS decodebin checks
   * if all chains and groups are drained. In that case everything goes into EOS.
   * If there is a chain where the active group is drained but there exist next
   * groups, the active group is hidden (endpads are removed) and the next group
  #include "config.h"
  #endif
  
+ /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+  * with newer GLib versions (>= 2.31.0) */
+ #define GLIB_DISABLE_DEPRECATION_WARNINGS
  #include <gst/gst-i18n-plugin.h>
  
  #include <string.h>
  #include "gstplayback.h"
  #include "gstrawcaps.h"
  
+ #include "gst/glib-compat-private.h"
  /* generic templates */
  static GstStaticPadTemplate decoder_bin_sink_template =
  GST_STATIC_PAD_TEMPLATE ("sink",
      GST_STATIC_CAPS_ANY);
  
  static GstStaticPadTemplate decoder_bin_src_template =
 -GST_STATIC_PAD_TEMPLATE ("src%d",
 +GST_STATIC_PAD_TEMPLATE ("src_%u",
      GST_PAD_SRC,
      GST_PAD_SOMETIMES,
      GST_STATIC_CAPS_ANY);
@@@ -119,6 -125,7 +125,6 @@@ typedef struct _GstDecodeGroup GstDecod
  typedef struct _GstDecodePad GstDecodePad;
  typedef GstGhostPadClass GstDecodePadClass;
  typedef struct _GstDecodeBin GstDecodeBin;
 -typedef struct _GstDecodeBin GstDecodeBin2;
  typedef struct _GstDecodeBinClass GstDecodeBinClass;
  
  #define GST_TYPE_DECODE_BIN             (gst_decode_bin_get_type())
  #define GST_IS_DECODE_BIN_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DECODE_BIN))
  
  /**
 - *  GstDecodeBin2:
 + *  GstDecodeBin:
   *
 - *  The opaque #DecodeBin2 data structure
 + *  The opaque #GstDecodeBin data structure
   */
  struct _GstDecodeBin
  {
  
    GMutex *expose_lock;          /* Protects exposal and removal of groups */
    GstDecodeChain *decode_chain; /* Top level decode chain */
 -  gint nbpads;                  /* unique identifier for source pads */
 +  guint nbpads;                 /* unique identifier for source pads */
  
    GMutex *factories_lock;
    guint32 factories_cookie;     /* Cookie from last time when factories was updated */
@@@ -180,6 -187,10 +186,6 @@@ struct _GstDecodeBinClas
  {
    GstBinClass parent_class;
  
 -  /* signal we fire when a new pad has been decoded into raw audio/video */
 -  void (*new_decoded_pad) (GstElement * element, GstPad * pad, gboolean last);
 -  /* signal we fire when a pad has been removed */
 -  void (*removed_decoded_pad) (GstElement * element, GstPad * pad);
    /* signal fired when we found a pad that we cannot decode */
    void (*unknown_type) (GstElement * element, GstPad * pad, GstCaps * caps);
  
  /* signals */
  enum
  {
 -  SIGNAL_NEW_DECODED_PAD,
 -  SIGNAL_REMOVED_DECODED_PAD,
    SIGNAL_UNKNOWN_TYPE,
    SIGNAL_AUTOPLUG_CONTINUE,
    SIGNAL_AUTOPLUG_FACTORIES,
@@@ -470,8 -483,6 +476,8 @@@ struct _GstDecodePa
    gboolean blocked;             /* the *target* pad is blocked */
    gboolean exposed;             /* the pad is exposed */
    gboolean drained;             /* an EOS has been seen on the pad */
 +
 +  gulong block_id;
  };
  
  GType gst_decode_pad_get_type (void);
@@@ -487,8 -498,7 +493,8 @@@ static void gst_decode_pad_unblock (Gst
  static void gst_decode_pad_set_blocked (GstDecodePad * dpad, gboolean blocked);
  
  static void gst_pending_pad_free (GstPendingPad * ppad);
 -static gboolean pad_event_cb (GstPad * pad, GstEvent * event, gpointer data);
 +static GstPadProbeReturn pad_event_cb (GstPad * pad, GstPadProbeInfo * info,
 +    gpointer data);
  
  /********************************
   * Standard GObject boilerplate *
@@@ -519,7 -529,7 +525,7 @@@ gst_decode_bin_get_type (void
      };
  
      gst_decode_bin_type =
 -        g_type_register_static (GST_TYPE_BIN, "GstDecodeBin2",
 +        g_type_register_static (GST_TYPE_BIN, "GstDecodeBin",
          &gst_decode_bin_info, 0);
    }
  
@@@ -602,7 -612,42 +608,7 @@@ gst_decode_bin_class_init (GstDecodeBin
    gobject_klass->get_property = gst_decode_bin_get_property;
  
    /**
 -   * GstDecodeBin2::new-decoded-pad:
 -   * @bin: The decodebin.
 -   * @pad: The newly created pad.
 -   * @islast: #TRUE if this is the last pad to be added. Deprecated.
 -   *
 -   * This signal gets emitted as soon as a new pad of the same type as one of
 -   * the valid 'raw' types is added.
 -   *
 -   * Deprecated: Use GstElement::pad-added instead of this signal.
 -   *
 -   */
 -  gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD] =
 -      g_signal_new ("new-decoded-pad", G_TYPE_FROM_CLASS (klass),
 -      G_SIGNAL_RUN_LAST,
 -      G_STRUCT_OFFSET (GstDecodeBinClass, new_decoded_pad), NULL, NULL,
 -      gst_play_marshal_VOID__OBJECT_BOOLEAN, G_TYPE_NONE, 2, GST_TYPE_PAD,
 -      G_TYPE_BOOLEAN);
 -
 -  /**
 -   * GstDecodeBin2::removed-decoded-pad:
 -   * @bin: The decodebin.
 -   * @pad: The pad that was removed.
 -   *
 -   * This signal is emitted when a 'final' caps pad has been removed.
 -   *
 -   * Deprecated: Use GstElement::pad-removed instead of this signal.
 -   *
 -   */
 -  gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD] =
 -      g_signal_new ("removed-decoded-pad", G_TYPE_FROM_CLASS (klass),
 -      G_SIGNAL_RUN_LAST,
 -      G_STRUCT_OFFSET (GstDecodeBinClass, removed_decoded_pad), NULL, NULL,
 -      gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
 -
 -  /**
 -   * GstDecodeBin2::unknown-type:
 +   * GstDecodeBin::unknown-type:
     * @bin: The decodebin.
     * @pad: The new pad containing caps that cannot be resolved to a 'final'
     *       stream type.
        GST_TYPE_PAD, GST_TYPE_CAPS);
  
    /**
 -   * GstDecodeBin2::autoplug-continue:
 +   * GstDecodeBin::autoplug-continue:
     * @bin: The decodebin.
     * @pad: The #GstPad.
     * @caps: The #GstCaps found.
     *
 -   * This signal is emitted whenever decodebin2 finds a new stream. It is
 +   * This signal is emitted whenever decodebin finds a new stream. It is
     * emitted before looking for any elements that can handle that stream.
     *
     * <note>
     *   connected in.
     * </note>
     *
 -   * Returns: #TRUE if you wish decodebin2 to look for elements that can
 +   * Returns: #TRUE if you wish decodebin to look for elements that can
     * handle the given @caps. If #FALSE, those caps will be considered as
 -   * final and the pad will be exposed as such (see 'new-decoded-pad'
 -   * signal).
 +   * final and the pad will be exposed as such (see 'pad-added' signal of
 +   * #GstElement).
     */
    gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE] =
        g_signal_new ("autoplug-continue", G_TYPE_FROM_CLASS (klass),
        G_TYPE_BOOLEAN, 2, GST_TYPE_PAD, GST_TYPE_CAPS);
  
    /**
 -   * GstDecodeBin2::autoplug-factories:
 +   * GstDecodeBin::autoplug-factories:
     * @bin: The decodebin.
     * @pad: The #GstPad.
     * @caps: The #GstCaps found.
     *
 -   * This function is emitted when an array of possible factories for @caps on
 -   * @pad is needed. Decodebin2 will by default return an array with all
 +   * This function is emited when an array of possible factories for @caps on
 +   * @pad is needed. Decodebin will by default return an array with all
     * compatible factories, sorted by rank.
     *
     * If this function returns NULL, @pad will be exposed as a final caps.
        GST_TYPE_PAD, GST_TYPE_CAPS);
  
    /**
 -   * GstDecodeBin2::autoplug-sort:
 +   * GstDecodeBin::autoplug-sort:
     * @bin: The decodebin.
     * @pad: The #GstPad.
     * @caps: The #GstCaps.
     * @factories: A #GValueArray of possible #GstElementFactory to use.
     *
 -   * Once decodebin2 has found the possible #GstElementFactory objects to try
 -   * for @caps on @pad, this signal is emitted. The purpose of the signal is for
 +   * Once decodebin has found the possible #GstElementFactory objects to try
 +   * for @caps on @pad, this signal is emited. The purpose of the signal is for
     * the application to perform additional sorting or filtering on the element
     * factory array.
     *
        GST_TYPE_PAD, GST_TYPE_CAPS, G_TYPE_VALUE_ARRAY);
  
    /**
 -   * GstDecodeBin2::autoplug-select:
 +   * GstDecodeBin::autoplug-select:
     * @bin: The decodebin.
     * @pad: The #GstPad.
     * @caps: The #GstCaps.
     * @factory: A #GstElementFactory to use.
     *
 -   * This signal is emitted once decodebin2 has found all the possible
 +   * This signal is emitted once decodebin has found all the possible
     * #GstElementFactory that can be used to handle the given @caps. For each of
     * those factories, this signal is emitted.
     *
     * The signal handler should return a #GST_TYPE_AUTOPLUG_SELECT_RESULT enum
 -   * value indicating what decodebin2 should do next.
 +   * value indicating what decodebin should do next.
     *
     * A value of #GST_AUTOPLUG_SELECT_TRY will try to autoplug an element from
     * @factory.
        GST_TYPE_ELEMENT_FACTORY);
  
    /**
 -   * GstDecodeBin2::drained
 +   * GstDecodeBin::drained
     * @bin: The decodebin
     *
 -   * This signal is emitted once decodebin2 has finished decoding all the data.
 +   * This signal is emitted once decodebin has finished decoding all the data.
     *
     * Since: 0.10.16
     */
            GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
    /**
 -   * GstDecodeBin2::use-buffering
 +   * GstDecodeBin::use-buffering
     *
 -   * Activate buffering in decodebin2. This will instruct the multiqueues behind
 +   * Activate buffering in decodebin. This will instruct the multiqueues behind
     * decoders to emit BUFFERING messages.
  
     * Since: 0.10.26
            DEFAULT_USE_BUFFERING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
    /**
 -   * GstDecodebin2:low-percent
 +   * GstDecodeBin:low-percent
     *
     * Low threshold percent for buffering to start.
     *
            "Low threshold for buffering to start", 0, 100,
            DEFAULT_LOW_PERCENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
    /**
 -   * GstDecodebin2:high-percent
 +   * GstDecodeBin:high-percent
     *
     * High threshold percent for buffering to finish.
     *
            DEFAULT_HIGH_PERCENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
    /**
 -   * GstDecodebin2:max-size-bytes
 +   * GstDecodeBin:max-size-bytes
     *
     * Max amount of bytes in the queue (0=automatic).
     *
            0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES,
            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
    /**
 -   * GstDecodebin2:max-size-buffers
 +   * GstDecodeBin:max-size-buffers
     *
     * Max amount of buffers in the queue (0=automatic).
     *
            0, G_MAXUINT, DEFAULT_MAX_SIZE_BUFFERS,
            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
    /**
 -   * GstDecodebin2:max-size-time
 +   * GstDecodeBin:max-size-time
     *
     * Max amount of time in the queue (in ns, 0=automatic).
     *
            DEFAULT_MAX_SIZE_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
    /**
 -   * GstDecodeBin2::post-stream-topology
 +   * GstDecodeBin::post-stream-topology
     *
     * Post stream-topology messages on the bus every time the topology changes.
     *
            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
    /**
 -   * GstDecodeBin2::expose-all-streams
 +   * GstDecodeBin::expose-all-streams
     *
     * Expose streams of unknown type.
     *
    klass->autoplug_sort = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_sort);
    klass->autoplug_select = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_select);
  
 -  gst_element_class_add_static_pad_template (gstelement_klass,
 -      &decoder_bin_sink_template);
 -  gst_element_class_add_static_pad_template (gstelement_klass,
 -      &decoder_bin_src_template);
 +  gst_element_class_add_pad_template (gstelement_klass,
 +      gst_static_pad_template_get (&decoder_bin_sink_template));
 +  gst_element_class_add_pad_template (gstelement_klass,
 +      gst_static_pad_template_get (&decoder_bin_src_template));
  
    gst_element_class_set_details_simple (gstelement_klass,
        "Decoder Bin", "Generic/Bin/Decoder",
@@@ -1686,8 -1731,7 +1692,8 @@@ setup_caps_delay
      ppad->pad = gst_object_ref (pad);
      ppad->chain = chain;
      ppad->event_probe_id =
 -        gst_pad_add_event_probe (pad, (GCallback) pad_event_cb, ppad);
 +        gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
 +        pad_event_cb, ppad, NULL);
      chain->pending_pads = g_list_prepend (chain->pending_pads, ppad);
      g_signal_connect (G_OBJECT (pad), "notify::caps",
          G_CALLBACK (caps_notify_cb), chain);
@@@ -1776,46 -1820,6 +1782,46 @@@ connect_pad (GstDecodeBin * dbin, GstEl
      /* Remove selected factory from the list. */
      g_value_array_remove (factories, 0);
  
 +    /* Check if the caps are really supported by the factory. The
 +     * factory list is non-empty-subset filtered while caps
 +     * are only accepted by a pad if they are a subset of the
 +     * pad caps.
 +     *
 +     * FIXME: Only do this for fixed caps here. Non-fixed caps
 +     * can happen if a Parser/Converter was autoplugged before
 +     * this. We then assume that it will be able to convert to
 +     * everything that the decoder would want.
 +     *
 +     * A subset check will fail here because the parser caps
 +     * will be generic and while the decoder will only
 +     * support a subset of the parser caps.
 +     */
 +    if (gst_caps_is_fixed (caps)) {
 +      const GList *templs;
 +      gboolean skip = FALSE;
 +
 +      templs = gst_element_factory_get_static_pad_templates (factory);
 +
 +      while (templs) {
 +        GstStaticPadTemplate *templ = (GstStaticPadTemplate *) templs->data;
 +
 +        if (templ->direction == GST_PAD_SINK) {
 +          GstCaps *templcaps = gst_static_caps_get (&templ->static_caps);
 +
 +          if (!gst_caps_is_subset (caps, templcaps)) {
 +            gst_caps_unref (templcaps);
 +            skip = TRUE;
 +            break;
 +          }
 +
 +          gst_caps_unref (templcaps);
 +        }
 +        templs = g_list_next (templs);
 +      }
 +      if (skip)
 +        continue;
 +    }
 +
      /* If the factory is for a parser we first check if the factory
       * was already used for the current chain. If it was used already
       * we would otherwise create an infinite loop here because the
            }
  
            g_signal_handlers_disconnect_by_func (pp->pad, caps_notify_cb, chain);
 -          gst_pad_remove_event_probe (pp->pad, pp->event_probe_id);
 +          gst_pad_remove_probe (pp->pad, pp->event_probe_id);
            gst_object_unref (pp->pad);
            g_slice_free (GstPendingPad, pp);
  
@@@ -2043,13 -2047,16 +2049,13 @@@ get_pad_caps (GstPad * pad
  
    /* first check the pad caps, if this is set, we are positively sure it is
     * fixed and exactly what the element will produce. */
 -  GST_OBJECT_LOCK (pad);
 -  if ((caps = GST_PAD_CAPS (pad)))
 -    gst_caps_ref (caps);
 -  GST_OBJECT_UNLOCK (pad);
 +  caps = gst_pad_get_current_caps (pad);
  
    /* then use the getcaps function if we don't have caps. These caps might not
     * be fixed in some cases, in which case analyze_new_pad will set up a
     * notify::caps signal to continue autoplugging. */
    if (caps == NULL)
 -    caps = gst_pad_get_caps_reffed (pad);
 +    caps = gst_pad_query_caps (pad, NULL);
  
    return caps;
  }
@@@ -2224,8 -2231,10 +2230,8 @@@ check_upstream_seekable (GstDecodeBin 
  
    /* try harder to query upstream size if we didn't get it the first time */
    if (seekable && stop == -1) {
 -    GstFormat fmt = GST_FORMAT_BYTES;
 -
      GST_DEBUG_OBJECT (dbin, "doing duration query to fix up unset stop");
 -    gst_pad_query_peer_duration (pad, &fmt, &stop);
 +    gst_pad_peer_query_duration (pad, GST_FORMAT_BYTES, &stop);
    }
  
    /* if upstream doesn't know the size, it's likely that it's not seekable in
@@@ -2253,7 -2262,7 +2259,7 @@@ type_found (GstElement * typefind, guin
    if (gst_structure_has_name (gst_caps_get_structure (caps, 0), "text/plain")) {
      GST_ELEMENT_ERROR (decode_bin, STREAM, WRONG_TYPE,
          (_("This appears to be a text file")),
 -        ("decodebin2 cannot decode plain text files"));
 +        ("decodebin cannot decode plain text files"));
      goto exit;
    }
  
@@@ -2283,10 -2292,9 +2289,10 @@@ exit
    return;
  }
  
 -static gboolean
 -pad_event_cb (GstPad * pad, GstEvent * event, gpointer data)
 +static GstPadProbeReturn
 +pad_event_cb (GstPad * pad, GstPadProbeInfo * info, gpointer data)
  {
 +  GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
    GstPendingPad *ppad = (GstPendingPad *) data;
    GstDecodeChain *chain = ppad->chain;
    GstDecodeBin *dbin = chain->dbin;
      default:
        break;
    }
 -  return TRUE;
 +  return GST_PAD_PROBE_OK;
  }
  
  static void
@@@ -2663,6 -2671,8 +2669,6 @@@ gst_decode_chain_free_internal (GstDeco
      if (chain->endpad->exposed) {
        gst_element_remove_pad (GST_ELEMENT_CAST (chain->dbin),
            GST_PAD_CAST (chain->endpad));
 -      g_signal_emit (G_OBJECT (chain->dbin),
 -          gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD], 0, chain->endpad);
      }
  
      gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (chain->endpad), NULL);
  /* gst_decode_chain_free:
   *
   * Completely frees and removes the chain and all
 - * child groups from decodebin2.
 + * child groups from decodebin.
   *
   * MT-safe, don't hold the chain lock or any child chain's lock
   * when calling this!
@@@ -2841,7 -2851,7 +2847,7 @@@ gst_decode_group_free (GstDecodeGroup 
  /* gst_decode_group_hide:
   *
   * Hide the decode group only, this means that
 - * all child endpads are removed from decodebin2
 + * all child endpads are removed from decodebin
   * and all signals are unconnected.
   *
   * No element is set to NULL state and completely
@@@ -2970,7 -2980,6 +2976,7 @@@ gst_decode_group_control_demuxer_pad (G
    GstDecodeBin *dbin;
    GstPad *srcpad, *sinkpad;
    GstIterator *it = NULL;
 +  GValue item = { 0, };
  
    dbin = group->dbin;
  
    if (G_UNLIKELY (!group->multiqueue))
      return NULL;
  
 -  if (!(sinkpad = gst_element_get_request_pad (group->multiqueue, "sink%d"))) {
 +  if (!(sinkpad = gst_element_get_request_pad (group->multiqueue, "sink_%u"))) {
      GST_ERROR_OBJECT (dbin, "Couldn't get sinkpad from multiqueue");
      return NULL;
    }
  
    it = gst_pad_iterate_internal_links (sinkpad);
  
 -  if (!it || (gst_iterator_next (it, (gpointer) & srcpad)) != GST_ITERATOR_OK
 -      || srcpad == NULL) {
 +  if (!it || (gst_iterator_next (it, &item)) != GST_ITERATOR_OK
 +      || ((srcpad = g_value_dup_object (&item)) == NULL)) {
      GST_ERROR_OBJECT (dbin,
          "Couldn't get srcpad from multiqueue for sinkpad %" GST_PTR_FORMAT,
          sinkpad);
      goto error;
    }
 -
    CHAIN_MUTEX_LOCK (group->parent);
    group->reqpads = g_list_prepend (group->reqpads, gst_object_ref (sinkpad));
    CHAIN_MUTEX_UNLOCK (group->parent);
  
  beach:
 +  g_value_unset (&item);
    if (it)
      gst_iterator_free (it);
    gst_object_unref (sinkpad);
@@@ -3334,7 -3343,7 +3340,7 @@@ sort_end_pads (GstDecodePad * da, GstDe
    namea = gst_structure_get_name (sa);
    nameb = gst_structure_get_name (sb);
  
 -  if (g_strrstr (namea, "video/x-raw-"))
 +  if (g_strrstr (namea, "video/x-raw"))
      va = 0;
    else if (g_strrstr (namea, "video/"))
      va = 1;
    else
      va = 4;
  
 -  if (g_strrstr (nameb, "video/x-raw-"))
 +  if (g_strrstr (nameb, "video/x-raw"))
      vb = 0;
    else if (g_strrstr (nameb, "video/"))
      vb = 1;
@@@ -3371,18 -3380,16 +3377,18 @@@ _gst_element_get_linked_caps (GstElemen
    GstPad *pad, *peer;
    gboolean done = FALSE;
    GstCaps *caps = NULL;
 +  GValue item = { 0, };
  
    it = gst_element_iterate_src_pads (src);
    while (!done) {
 -    switch (gst_iterator_next (it, (gpointer) & pad)) {
 +    switch (gst_iterator_next (it, &item)) {
        case GST_ITERATOR_OK:
 +        pad = g_value_get_object (&item);
          peer = gst_pad_get_peer (pad);
          if (peer) {
            parent = gst_pad_get_parent_element (peer);
            if (parent == sink) {
 -            caps = gst_pad_get_negotiated_caps (pad);
 +            caps = gst_pad_get_current_caps (pad);
              if (srcpad) {
                gst_object_ref (pad);
                *srcpad = pad;
              gst_object_unref (parent);
            gst_object_unref (peer);
          }
 -        gst_object_unref (pad);
 +        g_value_reset (&item);
          break;
        case GST_ITERATOR_RESYNC:
          gst_iterator_resync (it);
          break;
      }
    }
 -
 +  g_value_unset (&item);
    gst_iterator_free (it);
  
    return caps;
@@@ -3433,11 -3440,11 +3439,11 @@@ gst_decode_chain_get_topology (GstDecod
      return NULL;
    }
  
 -  u = gst_structure_id_empty_new (topology_structure_name);
 +  u = gst_structure_new_id_empty (topology_structure_name);
  
    /* Now at the last element */
    if (chain->elements && (chain->endpad || chain->deadend)) {
 -    s = gst_structure_id_empty_new (topology_structure_name);
 +    s = gst_structure_new_id_empty (topology_structure_name);
      gst_structure_id_set (u, topology_caps, GST_TYPE_CAPS, chain->endcaps,
          NULL);
  
      caps = _gst_element_get_linked_caps (elem_next, elem, &srcpad);
  
      if (caps) {
 -      s = gst_structure_id_empty_new (topology_structure_name);
 +      s = gst_structure_new_id_empty (topology_structure_name);
        gst_structure_id_set (u, topology_caps, GST_TYPE_CAPS, caps, NULL);
        gst_caps_unref (caps);
  
    }
  
    /* Caps that resulted in this chain */
 -  caps = gst_pad_get_negotiated_caps (chain->pad);
 +  caps = gst_pad_get_current_caps (chain->pad);
    if (!caps) {
      caps = get_pad_caps (chain->pad);
      if (G_UNLIKELY (!gst_caps_is_fixed (caps))) {
@@@ -3610,7 -3617,7 +3616,7 @@@ gst_decode_bin_expose (GstDecodeBin * d
      gchar *padname;
  
      /* 1. rewrite name */
 -    padname = g_strdup_printf ("src%d", dbin->nbpads);
 +    padname = g_strdup_printf ("src_%u", dbin->nbpads);
      dbin->nbpads++;
      GST_DEBUG_OBJECT (dbin, "About to expose dpad %s as %s",
          GST_OBJECT_NAME (dpad), padname);
      if (!dpad->exposed
          && !gst_element_add_pad (GST_ELEMENT (dbin), GST_PAD_CAST (dpad))) {
        /* not really fatal, we can try to add the other pads */
 -      g_warning ("error adding pad to decodebin2");
 +      g_warning ("error adding pad to decodebin");
        continue;
      }
      dpad->exposed = TRUE;
  
      /* 3. emit signal */
 -    GST_DEBUG_OBJECT (dbin, "emitting new-decoded-pad");
 -    g_signal_emit (G_OBJECT (dbin),
 -        gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD], 0, dpad,
 -        (tmp->next == NULL));
 -    GST_DEBUG_OBJECT (dbin, "emitted new-decoded-pad");
 +    GST_INFO_OBJECT (dpad, "added new decoded pad");
    }
  
    /* 4. Signal no-more-pads. This allows the application to hook stuff to the
@@@ -3732,39 -3743,36 +3738,39 @@@ gst_decode_pad_init (GstDecodePad * pad
    pad->blocked = FALSE;
    pad->exposed = FALSE;
    pad->drained = FALSE;
 -  gst_object_ref (pad);
 -  gst_object_sink (pad);
 +  gst_object_ref_sink (pad);
  }
  
 -static void
 -source_pad_blocked_cb (GstPad * pad, gboolean blocked, GstDecodePad * dpad)
 +static GstPadProbeReturn
 +source_pad_blocked_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
  {
 +  GstDecodePad *dpad = user_data;
    GstDecodeChain *chain;
    GstDecodeBin *dbin;
  
    chain = dpad->chain;
    dbin = chain->dbin;
  
 -  GST_LOG_OBJECT (dpad, "blocked:%d, dpad->chain:%p", blocked, chain);
 +  GST_LOG_OBJECT (dpad, "blocked: dpad->chain:%p", chain);
  
 -  dpad->blocked = blocked;
 +  dpad->blocked = TRUE;
  
 -  if (dpad->blocked) {
 -    EXPOSE_LOCK (dbin);
 -    if (gst_decode_chain_is_complete (dbin->decode_chain)) {
 -      if (!gst_decode_bin_expose (dbin))
 -        GST_WARNING_OBJECT (dbin, "Couldn't expose group");
 -    }
 -    EXPOSE_UNLOCK (dbin);
 +  EXPOSE_LOCK (dbin);
 +  if (gst_decode_chain_is_complete (dbin->decode_chain)) {
 +    if (!gst_decode_bin_expose (dbin))
 +      GST_WARNING_OBJECT (dbin, "Couldn't expose group");
    }
 +  EXPOSE_UNLOCK (dbin);
 +
 +  return GST_PAD_PROBE_OK;
  }
  
 -static gboolean
 -source_pad_event_probe (GstPad * pad, GstEvent * event, GstDecodePad * dpad)
 +static GstPadProbeReturn
 +source_pad_event_probe (GstPad * pad, GstPadProbeInfo * info,
 +    gpointer user_data)
  {
 +  GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
 +  GstDecodePad *dpad = user_data;
    gboolean res = TRUE;
  
    GST_LOG_OBJECT (pad, "%s dpad:%p", GST_EVENT_TYPE_NAME (event), dpad);
       *   first, which unlinks the peer and so drops the EOS. */
      res = gst_decode_pad_handle_eos (dpad);
    }
 -
 -  return res;
 +  if (res)
 +    return GST_PAD_PROBE_OK;
 +  else
 +    return GST_PAD_PROBE_DROP;
  }
  
  static void
@@@ -3803,21 -3809,10 +3809,21 @@@ gst_decode_pad_set_blocked (GstDecodePa
  
    /* do not block if shutting down.
     * we do not consider/expect it blocked further below, but use other trick */
 -  if (!blocked || !dbin->shutdown)
 -    gst_pad_set_blocked_async_full (opad, blocked,
 -        (GstPadBlockCallback) source_pad_blocked_cb, gst_object_ref (dpad),
 -        (GDestroyNotify) gst_object_unref);
 +  if (!blocked || !dbin->shutdown) {
 +    if (blocked) {
 +      if (dpad->block_id == 0)
 +        dpad->block_id =
 +            gst_pad_add_probe (opad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
 +            source_pad_blocked_cb, gst_object_ref (dpad),
 +            (GDestroyNotify) gst_object_unref);
 +    } else {
 +      if (dpad->block_id != 0) {
 +        gst_pad_remove_probe (opad, dpad->block_id);
 +        dpad->block_id = 0;
 +      }
 +      dpad->blocked = FALSE;
 +    }
 +  }
  
    if (blocked) {
      if (dbin->shutdown) {
@@@ -3846,8 -3841,8 +3852,8 @@@ out
  static void
  gst_decode_pad_add_drained_check (GstDecodePad * dpad)
  {
 -  gst_pad_add_event_probe (GST_PAD_CAST (dpad),
 -      G_CALLBACK (source_pad_event_probe), dpad);
 +  gst_pad_add_probe (GST_PAD_CAST (dpad), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
 +      source_pad_event_probe, dpad, NULL);
  }
  
  static void
@@@ -3898,7 -3893,7 +3904,7 @@@ gst_pending_pad_free (GstPendingPad * p
    g_assert (ppad->pad);
  
    if (ppad->event_probe_id != 0)
 -    gst_pad_remove_event_probe (ppad->pad, ppad->event_probe_id);
 +    gst_pad_remove_probe (ppad->pad, ppad->event_probe_id);
    gst_object_unref (ppad->pad);
    g_slice_free (GstPendingPad, ppad);
  }
@@@ -3914,7 -3909,7 +3920,7 @@@ do_async_start (GstDecodeBin * dbin
  
    dbin->async_pending = TRUE;
  
 -  message = gst_message_new_async_start (GST_OBJECT_CAST (dbin), FALSE);
 +  message = gst_message_new_async_start (GST_OBJECT_CAST (dbin));
    parent_class->handle_message (GST_BIN_CAST (dbin), message);
  }
  
@@@ -3924,7 -3919,7 +3930,7 @@@ do_async_done (GstDecodeBin * dbin
    GstMessage *message;
  
    if (dbin->async_pending) {
 -    message = gst_message_new_async_done (GST_OBJECT_CAST (dbin));
 +    message = gst_message_new_async_done (GST_OBJECT_CAST (dbin), FALSE);
      parent_class->handle_message (GST_BIN_CAST (dbin), message);
  
      dbin->async_pending = FALSE;
@@@ -3946,13 -3941,13 +3952,13 @@@ find_sink_pad (GstElement * element
  {
    GstIterator *it;
    GstPad *pad = NULL;
 -  gpointer point;
 +  GValue item = { 0, };
  
    it = gst_element_iterate_sink_pads (element);
  
 -  if ((gst_iterator_next (it, &point)) == GST_ITERATOR_OK)
 -    pad = (GstPad *) point;
 -
 +  if ((gst_iterator_next (it, &item)) == GST_ITERATOR_OK)
 +    pad = g_value_dup_object (&item);
 +  g_value_unset (&item);
    gst_iterator_free (it);
  
    return pad;
@@@ -3975,11 -3970,9 +3981,11 @@@ unblock_pads (GstDecodeBin * dbin
        continue;
  
      GST_DEBUG_OBJECT (dpad, "unblocking");
 -    gst_pad_set_blocked_async_full (opad, FALSE,
 -        (GstPadBlockCallback) source_pad_blocked_cb, gst_object_ref (dpad),
 -        (GDestroyNotify) gst_object_unref);
 +    if (dpad->block_id != 0) {
 +      gst_pad_remove_probe (opad, dpad->block_id);
 +      dpad->block_id = 0;
 +    }
 +    dpad->blocked = FALSE;
      /* make flushing, prevent NOT_LINKED */
      GST_PAD_SET_FLUSHING (GST_PAD_CAST (dpad));
      gst_object_unref (dpad);
@@@ -4090,7 -4083,15 +4096,7 @@@ gst_decode_bin_handle_message (GstBin 
  gboolean
  gst_decode_bin_plugin_init (GstPlugin * plugin)
  {
 -  GST_DEBUG_CATEGORY_INIT (gst_decode_bin_debug, "decodebin2", 0,
 -      "decoder bin");
 -
 -#ifdef ENABLE_NLS
 -  GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
 -      LOCALEDIR);
 -  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
 -  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 -#endif /* ENABLE_NLS */
 +  GST_DEBUG_CATEGORY_INIT (gst_decode_bin_debug, "decodebin", 0, "decoder bin");
  
    /* Register some quarks here for the stream topology message */
    topology_structure_name = g_quark_from_static_string ("stream-topology");
    topology_pad = g_quark_from_static_string ("pad");
    topology_element_srcpad = g_quark_from_static_string ("element-srcpad");
  
 -  return gst_element_register (plugin, "decodebin2", GST_RANK_NONE,
 +  return gst_element_register (plugin, "decodebin", GST_RANK_NONE,
        GST_TYPE_DECODE_BIN);
  }
   */
  
  /**
 - * SECTION:element-playbin2
 + * SECTION:element-playbin
   *
 - * Playbin2 provides a stand-alone everything-in-one abstraction for an
 + * Playbin provides a stand-alone everything-in-one abstraction for an
   * audio and/or video player.
   *
 - * playbin2 is considered stable now. It is the prefered playback API now,
 - * and replaces the old #playbin element, which is no longer supported.
 - *
 - * It can handle both audio and video files and features
 + * Playbin can handle both audio and video files and features
   * <itemizedlist>
   * <listitem>
   * automatic file type recognition and based on that automatic
@@@ -44,7 -47,7 +44,7 @@@
   * meta info (tag) extraction
   * </listitem>
   * <listitem>
 - * easy access to the last video frame
 + * easy access to the last video sample
   * </listitem>
   * <listitem>
   * buffering when playing streams over a network
@@@ -57,8 -60,8 +57,8 @@@
   * <refsect2>
   * <title>Usage</title>
   * <para>
 - * A playbin2 element can be created just like any other element using
 - * gst_element_factory_make(). The file/URI to play should be set via the #GstPlayBin2:uri
 + * A playbin element can be created just like any other element using
 + * gst_element_factory_make(). The file/URI to play should be set via the #GstPlayBin:uri
   * property. This must be an absolute URI, relative file paths are not allowed.
   * Example URIs are file:///home/joe/movie.avi or http://www.joedoe.com/foo.ogg
   *
@@@ -77,7 -80,7 +77,7 @@@
   * When playback has finished (an EOS message has been received on the bus)
   * or an error has occured (an ERROR message has been received on the bus) or
   * the user wants to play a different track, playbin should be set back to
 - * READY or NULL state, then the #GstPlayBin2:uri property should be set to the
 + * READY or NULL state, then the #GstPlayBin:uri property should be set to the
   * new location and then playbin be set to PLAYING state again.
   *
   * Seeking can be done using gst_element_seek_simple() or gst_element_seek()
   * <title>Advanced Usage: specifying the audio and video sink</title>
   * <para>
   * By default, if no audio sink or video sink has been specified via the
 - * #GstPlayBin2:audio-sink or #GstPlayBin2:video-sink property, playbin will use the autoaudiosink
 + * #GstPlayBin:audio-sink or #GstPlayBin:video-sink property, playbin will use the autoaudiosink
   * and autovideosink elements to find the first-best available output method.
   * This should work in most cases, but is not always desirable. Often either
   * the user or application might want to specify more explicitly what to use
   * If the application wants more control over how audio or video should be
   * output, it may create the audio/video sink elements itself (for example
   * using gst_element_factory_make()) and provide them to playbin using the
 - * #GstPlayBin2:audio-sink or #GstPlayBin2:video-sink property.
 + * #GstPlayBin:audio-sink or #GstPlayBin:video-sink property.
   *
   * GNOME-based applications, for example, will usually want to create
   * gconfaudiosink and gconfvideosink elements and make playbin use those,
  #include "config.h"
  #endif
  
+ /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+  * with newer GLib versions (>= 2.31.0) */
+ #define GLIB_DISABLE_DEPRECATION_WARNINGS
  #include <string.h>
  #include <gst/gst.h>
  
  #include <gst/gst-i18n-plugin.h>
  #include <gst/pbutils/pbutils.h>
 -#include <gst/interfaces/streamvolume.h>
 +#include <gst/audio/streamvolume.h>
  
  #include "gstplay-enum.h"
  #include "gstplay-marshal.h"
  #include "gstplaysink.h"
  #include "gstsubtitleoverlay.h"
  
+ #include "gst/glib-compat-private.h"
  GST_DEBUG_CATEGORY_STATIC (gst_play_bin_debug);
  #define GST_CAT_DEFAULT gst_play_bin_debug
  
@@@ -263,7 -272,6 +269,7 @@@ struct _GstSourceSelec
                                   */
    GstEvent *sinkpad_delayed_event;
    gulong sinkpad_data_probe;
 +  gulong block_id;
  };
  
  #define GST_SOURCE_GROUP_GET_LOCK(group) (((GstSourceGroup*)(group))->lock)
@@@ -322,8 -330,6 +328,8 @@@ struct _GstSourceGrou
    gulong sub_no_more_pads_id;
    gulong sub_autoplug_continue_id;
  
 +  gulong block_id;
 +
    GMutex *stream_changed_pending_lock;
    GList *stream_changed_pending;
  
@@@ -356,7 -362,7 +362,7 @@@ G_STMT_START 
    GST_PLAY_BIN_DYN_UNLOCK (bin);                  \
  
  /**
 - * GstPlayBin2:
 + * GstPlayBin:
   *
   * playbin element structure
   */
@@@ -372,7 -378,7 +378,7 @@@ struct _GstPlayBi
    GstSourceGroup *next_group;   /* pointer to the next group */
  
    /* properties */
 -  guint connection_speed;       /* connection speed in bits/sec (0 = unknown) */
 +  guint64 connection_speed;     /* connection speed in bits/sec (0 = unknown) */
    gint current_video;           /* the currently selected stream */
    gint current_audio;           /* the currently selected stream */
    gint current_text;            /* the currently selected stream */
@@@ -436,8 -442,8 +442,8 @@@ struct _GstPlayBinClas
    GstTagList *(*get_audio_tags) (GstPlayBin * playbin, gint stream);
    GstTagList *(*get_text_tags) (GstPlayBin * playbin, gint stream);
  
 -  /* get the last video frame and convert it to the given caps */
 -  GstBuffer *(*convert_frame) (GstPlayBin * playbin, GstCaps * caps);
 +  /* get the last video sample and convert it to the given caps */
 +  GstSample *(*convert_sample) (GstPlayBin * playbin, GstCaps * caps);
  
    /* get audio/video/text pad for a stream */
    GstPad *(*get_video_pad) (GstPlayBin * playbin, gint stream);
@@@ -491,7 -497,7 +497,7 @@@ enu
    PROP_TEXT_SINK,
    PROP_VOLUME,
    PROP_MUTE,
 -  PROP_FRAME,
 +  PROP_SAMPLE,
    PROP_FONT_DESC,
    PROP_CONNECTION_SPEED,
    PROP_BUFFER_SIZE,
  enum
  {
    SIGNAL_ABOUT_TO_FINISH,
 -  SIGNAL_CONVERT_FRAME,
 +  SIGNAL_CONVERT_SAMPLE,
    SIGNAL_VIDEO_CHANGED,
    SIGNAL_AUDIO_CHANGED,
    SIGNAL_TEXT_CHANGED,
@@@ -544,7 -550,7 +550,7 @@@ static GstTagList *gst_play_bin_get_aud
  static GstTagList *gst_play_bin_get_text_tags (GstPlayBin * playbin,
      gint stream);
  
 -static GstBuffer *gst_play_bin_convert_frame (GstPlayBin * playbin,
 +static GstSample *gst_play_bin_convert_sample (GstPlayBin * playbin,
      GstCaps * caps);
  
  static GstPad *gst_play_bin_get_video_pad (GstPlayBin * playbin, gint stream);
@@@ -557,8 -563,8 +563,8 @@@ static void no_more_pads_cb (GstElemen
  static void pad_removed_cb (GstElement * decodebin, GstPad * pad,
      GstSourceGroup * group);
  
 -static void gst_play_bin_suburidecodebin_block (GstElement * suburidecodebin,
 -    gboolean block);
 +static void gst_play_bin_suburidecodebin_block (GstSourceGroup * group,
 +    GstElement * suburidecodebin, gboolean block);
  static void gst_play_bin_suburidecodebin_seek_to_start (GstElement *
      suburidecodebin);
  
@@@ -595,7 -601,7 +601,7 @@@ gst_play_bin_get_type (void
      };
  
      gst_play_bin_type = g_type_register_static (GST_TYPE_PIPELINE,
 -        "GstPlayBin2", &gst_play_bin_info, 0);
 +        "GstPlayBin", &gst_play_bin_info, 0);
  
      g_type_add_interface_static (gst_play_bin_type, GST_TYPE_STREAM_VOLUME,
          &svol_info);
@@@ -623,7 -629,7 +629,7 @@@ gst_play_bin_class_init (GstPlayBinClas
    gobject_klass->finalize = gst_play_bin_finalize;
  
    /**
 -   * GstPlayBin2:uri
 +   * GstPlayBin:uri
     *
     * Set the next URI that playbin will play. This property can be set from the
     * about-to-finish signal to queue the next media file.
            NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
    /**
 -   * GstPlayBin2:suburi
 +   * GstPlayBin:suburi
     *
     * Set the next subtitle URI that playbin will play. This property can be
     * set from the about-to-finish signal to queue the next subtitle media file.
            GST_TYPE_ELEMENT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
  
    /**
 -   * GstPlayBin2:flags
 +   * GstPlayBin:flags
     *
     * Control the behaviour of playbin.
     */
            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
    /**
 -   * GstPlayBin2:n-video
 +   * GstPlayBin:n-video
     *
     * Get the total number of available video streams.
     */
            "Total number of video streams", 0, G_MAXINT, 0,
            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
    /**
 -   * GstPlayBin2:current-video
 +   * GstPlayBin:current-video
     *
     * Get or set the currently playing video stream. By default the first video
     * stream with data is played.
            "Currently playing video stream (-1 = auto)",
            -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
    /**
 -   * GstPlayBin2:n-audio
 +   * GstPlayBin:n-audio
     *
     * Get the total number of available audio streams.
     */
            "Total number of audio streams", 0, G_MAXINT, 0,
            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
    /**
 -   * GstPlayBin2:current-audio
 +   * GstPlayBin:current-audio
     *
     * Get or set the currently playing audio stream. By default the first audio
     * stream with data is played.
            "Currently playing audio stream (-1 = auto)",
            -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
    /**
 -   * GstPlayBin2:n-text
 +   * GstPlayBin:n-text
     *
     * Get the total number of available subtitle streams.
     */
            "Total number of text streams", 0, G_MAXINT, 0,
            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
    /**
 -   * GstPlayBin2:current-text:
 +   * GstPlayBin:current-text:
     *
     * Get or set the currently playing subtitle stream. By default the first
     * subtitle stream with data is played.
            GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
    /**
 -   * GstPlayBin2:volume:
 +   * GstPlayBin:volume:
     *
     * Get or set the current audio stream volume. 1.0 means 100%,
     * 0.0 means mute. This uses a linear volume scale.
            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
    /**
 -   * GstPlayBin2:frame:
 -   * @playbin: a #GstPlayBin2
 +   * GstPlayBin:sample:
 +   * @playbin: a #GstPlayBin
     *
 -   * Get the currently rendered or prerolled frame in the video sink.
 -   * The #GstCaps on the buffer will describe the format of the buffer.
 +   * Get the currently rendered or prerolled sample in the video sink.
 +   * The #GstCaps in the sample will describe the format of the buffer.
     */
 -  g_object_class_install_property (gobject_klass, PROP_FRAME,
 -      gst_param_spec_mini_object ("frame", "Frame",
 -          "The last frame (NULL = no video available)",
 -          GST_TYPE_BUFFER, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 +  g_object_class_install_property (gobject_klass, PROP_SAMPLE,
 +      g_param_spec_boxed ("sample", "Sample",
 +          "The last sample (NULL = no video available)",
 +          GST_TYPE_SAMPLE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 +
    g_object_class_install_property (gobject_klass, PROP_FONT_DESC,
        g_param_spec_string ("subtitle-font-desc",
            "Subtitle font description",
            G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
  
    g_object_class_install_property (gobject_klass, PROP_CONNECTION_SPEED,
 -      g_param_spec_uint ("connection-speed", "Connection Speed",
 +      g_param_spec_uint64 ("connection-speed", "Connection Speed",
            "Network connection speed in kbps (0 = unknown)",
 -          0, G_MAXUINT / 1000, DEFAULT_CONNECTION_SPEED,
 +          0, G_MAXUINT64 / 1000, DEFAULT_CONNECTION_SPEED,
            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
    g_object_class_install_property (gobject_klass, PROP_BUFFER_SIZE,
            -1, G_MAXINT64, DEFAULT_BUFFER_DURATION,
            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
    /**
 -   * GstPlayBin2:av-offset:
 +   * GstPlayBin:av-offset:
     *
     * Control the synchronisation offset between the audio and video streams.
     * Positive values make the audio ahead of the video and negative values make
            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
    /**
 -   * GstPlayBin2::about-to-finish
 -   * @playbin: a #GstPlayBin2
 +   * GstPlayBin::about-to-finish
 +   * @playbin: a #GstPlayBin
     *
     * This signal is emitted when the current uri is about to finish. You can
     * set the uri and suburi to make sure that playback continues.
        gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
  
    /**
 -   * GstPlayBin2::video-changed
 -   * @playbin: a #GstPlayBin2
 +   * GstPlayBin::video-changed
 +   * @playbin: a #GstPlayBin
     *
     * This signal is emitted whenever the number or order of the video
     * streams has changed. The application will most likely want to select
        G_STRUCT_OFFSET (GstPlayBinClass, video_changed), NULL, NULL,
        gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
    /**
 -   * GstPlayBin2::audio-changed
 -   * @playbin: a #GstPlayBin2
 +   * GstPlayBin::audio-changed
 +   * @playbin: a #GstPlayBin
     *
     * This signal is emitted whenever the number or order of the audio
     * streams has changed. The application will most likely want to select
        G_STRUCT_OFFSET (GstPlayBinClass, audio_changed), NULL, NULL,
        gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
    /**
 -   * GstPlayBin2::text-changed
 -   * @playbin: a #GstPlayBin2
 +   * GstPlayBin::text-changed
 +   * @playbin: a #GstPlayBin
     *
     * This signal is emitted whenever the number or order of the text
     * streams has changed. The application will most likely want to select
        gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
  
    /**
 -   * GstPlayBin2::video-tags-changed
 -   * @playbin: a #GstPlayBin2
 +   * GstPlayBin::video-tags-changed
 +   * @playbin: a #GstPlayBin
     * @stream: stream index with changed tags
     *
     * This signal is emitted whenever the tags of a video stream have changed.
        gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
  
    /**
 -   * GstPlayBin2::audio-tags-changed
 -   * @playbin: a #GstPlayBin2
 +   * GstPlayBin::audio-tags-changed
 +   * @playbin: a #GstPlayBin
     * @stream: stream index with changed tags
     *
     * This signal is emitted whenever the tags of an audio stream have changed.
        gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
  
    /**
 -   * GstPlayBin2::text-tags-changed
 -   * @playbin: a #GstPlayBin2
 +   * GstPlayBin::text-tags-changed
 +   * @playbin: a #GstPlayBin
     * @stream: stream index with changed tags
     *
     * This signal is emitted whenever the tags of a text stream have changed.
        gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
  
    /**
 -   * GstPlayBin2::source-setup:
 -   * @playbin: a #GstPlayBin2
 +   * GstPlayBin::source-setup:
 +   * @playbin: a #GstPlayBin
     * @source: source element
     *
     * This signal is emitted after the source element has been created, so
        gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
  
    /**
 -   * GstPlayBin2::get-video-tags
 -   * @playbin: a #GstPlayBin2
 +   * GstPlayBin::get-video-tags
 +   * @playbin: a #GstPlayBin
     * @stream: a video stream number
     *
     * Action signal to retrieve the tags of a specific video stream number.
        G_STRUCT_OFFSET (GstPlayBinClass, get_video_tags), NULL, NULL,
        gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
    /**
 -   * GstPlayBin2::get-audio-tags
 -   * @playbin: a #GstPlayBin2
 +   * GstPlayBin::get-audio-tags
 +   * @playbin: a #GstPlayBin
     * @stream: an audio stream number
     *
     * Action signal to retrieve the tags of a specific audio stream number.
        G_STRUCT_OFFSET (GstPlayBinClass, get_audio_tags), NULL, NULL,
        gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
    /**
 -   * GstPlayBin2::get-text-tags
 -   * @playbin: a #GstPlayBin2
 +   * GstPlayBin::get-text-tags
 +   * @playbin: a #GstPlayBin
     * @stream: a text stream number
     *
     * Action signal to retrieve the tags of a specific text stream number.
        G_STRUCT_OFFSET (GstPlayBinClass, get_text_tags), NULL, NULL,
        gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
    /**
 -   * GstPlayBin2::convert-frame
 -   * @playbin: a #GstPlayBin2
 +   * GstPlayBin::convert-sample
 +   * @playbin: a #GstPlayBin
     * @caps: the target format of the frame
     *
     * Action signal to retrieve the currently playing video frame in the format
     * %NULL is returned when no current buffer can be retrieved or when the
     * conversion failed.
     */
 -  gst_play_bin_signals[SIGNAL_CONVERT_FRAME] =
 -      g_signal_new ("convert-frame", G_TYPE_FROM_CLASS (klass),
 +  gst_play_bin_signals[SIGNAL_CONVERT_SAMPLE] =
 +      g_signal_new ("convert-sample", G_TYPE_FROM_CLASS (klass),
        G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
 -      G_STRUCT_OFFSET (GstPlayBinClass, convert_frame), NULL, NULL,
 -      gst_play_marshal_BUFFER__BOXED, GST_TYPE_BUFFER, 1, GST_TYPE_CAPS);
 +      G_STRUCT_OFFSET (GstPlayBinClass, convert_sample), NULL, NULL,
 +      gst_play_marshal_SAMPLE__BOXED, GST_TYPE_SAMPLE, 1, GST_TYPE_CAPS);
  
    /**
 -   * GstPlayBin2::get-video-pad
 -   * @playbin: a #GstPlayBin2
 +   * GstPlayBin::get-video-pad
 +   * @playbin: a #GstPlayBin
     * @stream: a video stream number
     *
     * Action signal to retrieve the stream-selector sinkpad for a specific
        G_STRUCT_OFFSET (GstPlayBinClass, get_video_pad), NULL, NULL,
        gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT);
    /**
 -   * GstPlayBin2::get-audio-pad
 -   * @playbin: a #GstPlayBin2
 +   * GstPlayBin::get-audio-pad
 +   * @playbin: a #GstPlayBin
     * @stream: an audio stream number
     *
     * Action signal to retrieve the stream-selector sinkpad for a specific
        G_STRUCT_OFFSET (GstPlayBinClass, get_audio_pad), NULL, NULL,
        gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT);
    /**
 -   * GstPlayBin2::get-text-pad
 -   * @playbin: a #GstPlayBin2
 +   * GstPlayBin::get-text-pad
 +   * @playbin: a #GstPlayBin
     * @stream: a text stream number
     *
     * Action signal to retrieve the stream-selector sinkpad for a specific
    klass->get_audio_tags = gst_play_bin_get_audio_tags;
    klass->get_text_tags = gst_play_bin_get_text_tags;
  
 -  klass->convert_frame = gst_play_bin_convert_frame;
 +  klass->convert_sample = gst_play_bin_convert_sample;
  
    klass->get_video_pad = gst_play_bin_get_video_pad;
    klass->get_audio_pad = gst_play_bin_get_audio_pad;
@@@ -1164,7 -1169,7 +1170,7 @@@ free_group (GstPlayBin * playbin, GstSo
    for (n = 0; n < PLAYBIN_STREAM_LAST; n++) {
      GstSourceSelect *select = &group->selector[n];
      if (select->sinkpad && select->sinkpad_data_probe)
 -      gst_pad_remove_data_probe (select->sinkpad, select->sinkpad_data_probe);
 +      gst_pad_remove_probe (select->sinkpad, select->sinkpad_data_probe);
      if (select->sinkpad_delayed_event)
        gst_event_unref (select->sinkpad_delayed_event);
    }
@@@ -1525,10 -1530,10 +1531,10 @@@ gst_play_bin_get_text_tags (GstPlayBin 
    return result;
  }
  
 -static GstBuffer *
 -gst_play_bin_convert_frame (GstPlayBin * playbin, GstCaps * caps)
 +static GstSample *
 +gst_play_bin_convert_sample (GstPlayBin * playbin, GstCaps * caps)
  {
 -  return gst_play_sink_convert_frame (playbin->playsink, caps);
 +  return gst_play_sink_convert_sample (playbin->playsink, caps);
  }
  
  /* Returns current stream number, or -1 if none has been selected yet */
@@@ -1656,14 -1661,19 +1662,14 @@@ no_channels
  }
  
  static void
 -_suburidecodebin_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
 -{
 -  GST_DEBUG_OBJECT (pad, "Pad blocked: %d", blocked);
 -}
 -
 -static void
  gst_play_bin_suburidecodebin_seek_to_start (GstElement * suburidecodebin)
  {
    GstIterator *it = gst_element_iterate_src_pads (suburidecodebin);
    GstPad *sinkpad;
 +  GValue item = { 0, };
  
 -  if (it && gst_iterator_next (it, (gpointer) & sinkpad) == GST_ITERATOR_OK
 -      && sinkpad) {
 +  if (it && gst_iterator_next (it, &item) == GST_ITERATOR_OK
 +      && ((sinkpad = g_value_get_object (&item)) != NULL)) {
      GstEvent *event;
  
      event =
          GST_DEBUG_OBJECT (suburidecodebin, "Seeking to the beginning failed!");
      }
  
 -    gst_object_unref (sinkpad);
 +    g_value_unset (&item);
    }
  
    if (it)
  }
  
  static void
 -gst_play_bin_suburidecodebin_block (GstElement * suburidecodebin,
 -    gboolean block)
 +gst_play_bin_suburidecodebin_block (GstSourceGroup * group,
 +    GstElement * suburidecodebin, gboolean block)
  {
    GstIterator *it = gst_element_iterate_src_pads (suburidecodebin);
    gboolean done = FALSE;
 +  GValue item = { 0, };
  
    GST_DEBUG_OBJECT (suburidecodebin, "Blocking suburidecodebin: %d", block);
  
    while (!done) {
      GstPad *sinkpad;
  
 -    switch (gst_iterator_next (it, (gpointer) & sinkpad)) {
 +    switch (gst_iterator_next (it, &item)) {
        case GST_ITERATOR_OK:
 -        gst_pad_set_blocked_async (sinkpad, block, _suburidecodebin_blocked_cb,
 -            NULL);
 -        gst_object_unref (sinkpad);
 +        sinkpad = g_value_get_object (&item);
 +        if (block) {
 +          group->block_id =
 +              gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
 +              NULL, NULL, NULL);
 +        } else if (group->block_id) {
 +          gst_pad_remove_probe (sinkpad, group->block_id);
 +          group->block_id = 0;
 +        }
 +        g_value_reset (&item);
          break;
        case GST_ITERATOR_DONE:
          done = TRUE;
          break;
      }
    }
 +  g_value_unset (&item);
    gst_iterator_free (it);
  }
  
@@@ -1798,8 -1799,7 +1804,8 @@@ gst_play_bin_set_current_text_stream (G
  
          /* Block all suburidecodebin sinkpads */
          if (need_block)
 -          gst_play_bin_suburidecodebin_block (group->suburidecodebin, TRUE);
 +          gst_play_bin_suburidecodebin_block (group, group->suburidecodebin,
 +              TRUE);
  
          /* activate the selected pad */
          g_object_set (selector, "active-pad", sinkpad, NULL);
             * currently displayed subtitles. This event will
             * never travel outside subtitleoverlay!
             */
 -          s = gst_structure_empty_new ("subtitleoverlay-flush-subtitle");
 +          s = gst_structure_new_empty ("subtitleoverlay-flush-subtitle");
            event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, s);
            gst_pad_send_event (peer, event);
            gst_object_unref (peer);
  
          /* Unblock pads if necessary */
          if (need_unblock)
 -          gst_play_bin_suburidecodebin_block (group->suburidecodebin, FALSE);
 +          gst_play_bin_suburidecodebin_block (group, group->suburidecodebin,
 +              FALSE);
  
          /* seek to the beginning */
          if (need_seek)
@@@ -1944,7 -1943,7 +1950,7 @@@ gst_play_bin_set_property (GObject * ob
        break;
      case PROP_CONNECTION_SPEED:
        GST_PLAY_BIN_LOCK (playbin);
 -      playbin->connection_speed = g_value_get_uint (value) * 1000;
 +      playbin->connection_speed = g_value_get_uint64 (value) * 1000;
        GST_PLAY_BIN_UNLOCK (playbin);
        break;
      case PROP_BUFFER_SIZE:
@@@ -2105,9 -2104,9 +2111,9 @@@ gst_play_bin_get_property (GObject * ob
      case PROP_MUTE:
        g_value_set_boolean (value, gst_play_sink_get_mute (playbin->playsink));
        break;
 -    case PROP_FRAME:
 -      gst_value_take_buffer (value,
 -          gst_play_sink_get_last_frame (playbin->playsink));
 +    case PROP_SAMPLE:
 +      gst_value_take_sample (value,
 +          gst_play_sink_get_last_sample (playbin->playsink));
        break;
      case PROP_FONT_DESC:
        g_value_take_string (value,
        break;
      case PROP_CONNECTION_SPEED:
        GST_PLAY_BIN_LOCK (playbin);
 -      g_value_set_uint (value, playbin->connection_speed / 1000);
 +      g_value_set_uint64 (value, playbin->connection_speed / 1000);
        GST_PLAY_BIN_UNLOCK (playbin);
        break;
      case PROP_BUFFER_SIZE:
@@@ -2277,7 -2276,7 +2283,7 @@@ gst_play_bin_handle_message (GstBin * b
      const GstStructure *s = gst_message_get_structure (msg);
  
      /* Drop all stream-changed messages except the last one */
 -    if (strcmp ("playbin2-stream-changed", gst_structure_get_name (s)) == 0) {
 +    if (strcmp ("playbin-stream-changed", gst_structure_get_name (s)) == 0) {
        guint32 seqnum = gst_message_get_seqnum (msg);
        GList *l, *l_prev;
  
          GstMessage *new_msg;
          GstIterator *it;
          gboolean done = FALSE;
 +        GValue item = { 0, };
  
          gst_message_parse_error (msg, &err, &debug);
          new_msg = gst_message_new_warning (msg->src, err, debug);
            GstPad *p = NULL;
            GstIteratorResult res;
  
 -          res = gst_iterator_next (it, (gpointer) & p);
 +          res = gst_iterator_next (it, &item);
  
            switch (res) {
              case GST_ITERATOR_DONE:
                done = TRUE;
                break;
              case GST_ITERATOR_OK:
 +              p = g_value_get_object (&item);
                pad_removed_cb (NULL, p, group);
 -              gst_object_unref (p);
 +              g_value_reset (&item);
                break;
  
              case GST_ITERATOR_RESYNC:
                break;
            }
          }
 +        g_value_unset (&item);
          if (it)
            gst_iterator_free (it);
  
@@@ -2442,16 -2438,22 +2448,16 @@@ selector_active_pad_changed (GObject * 
      g_object_notify (G_OBJECT (playbin), property);
  }
  
 -static void
 -selector_blocked (GstPad * pad, gboolean blocked, gpointer user_data)
 -{
 -  /* no nothing */
 -  GST_DEBUG_OBJECT (pad, "blocked callback, blocked: %d", blocked);
 -}
 -
  /* this callback sends a delayed event once the pad becomes unblocked */
 -static gboolean
 -stream_changed_data_probe (GstPad * pad, GstMiniObject * object, gpointer data)
 +static GstPadProbeReturn
 +stream_changed_data_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data)
  {
 +  GstMiniObject *object = GST_PAD_PROBE_INFO_DATA (info);
    GstSourceSelect *select = (GstSourceSelect *) data;
    GstEvent *e;
  
    /* we need do this just once, so cleanup first */
 -  gst_pad_remove_data_probe (pad, select->sinkpad_data_probe);
 +  gst_pad_remove_probe (pad, select->sinkpad_data_probe);
    select->sinkpad_data_probe = 0;
    e = select->sinkpad_delayed_event;
    select->sinkpad_delayed_event = NULL;
    /* really, this should not happen */
    if (!e) {
      GST_WARNING ("Data probed called, but no delayed event");
 -    return TRUE;
 +    return GST_PAD_PROBE_OK;
    }
  
    if (GST_IS_EVENT (object)
 -      && GST_EVENT_TYPE (GST_EVENT_CAST (object)) == GST_EVENT_NEWSEGMENT) {
 +      && GST_EVENT_TYPE (GST_EVENT_CAST (object)) == GST_EVENT_SEGMENT) {
      /* push the event first, then send the delayed one */
      gst_event_ref (GST_EVENT_CAST (object));
      gst_pad_send_event (pad, GST_EVENT_CAST (object));
      gst_pad_send_event (pad, e);
 -    return FALSE;
 +    return GST_PAD_PROBE_DROP;
    } else {
      /* send delayed event, then allow the caller to go on */
      gst_pad_send_event (pad, e);
 -    return TRUE;
 +    return GST_PAD_PROBE_OK;
    }
  }
  
@@@ -2548,7 -2550,7 +2554,7 @@@ pad_added_cb (GstElement * decodebin, G
  
    playbin = group->playbin;
  
 -  caps = gst_pad_get_caps_reffed (pad);
 +  caps = gst_pad_query_caps (pad, NULL);
    s = gst_caps_get_structure (caps, 0);
    name = gst_structure_get_name (s);
  
       * streams and connect the sinks, resulting in not-linked errors. After we
       * configured the sinks we will unblock them all. */
      GST_DEBUG_OBJECT (playbin, "blocking %" GST_PTR_FORMAT, select->srcpad);
 -    gst_pad_set_blocked_async (select->srcpad, TRUE, selector_blocked, NULL);
 +    select->block_id =
 +        gst_pad_add_probe (select->srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
 +        NULL, NULL, NULL);
    }
  
    /* get sinkpad for the new stream */
    if (select->selector) {
 -    if ((sinkpad = gst_element_get_request_pad (select->selector, "sink%d"))) {
 +    if ((sinkpad = gst_element_get_request_pad (select->selector, "sink_%u"))) {
        gulong notify_tags_handler = 0;
        NotifyTagsData *ntdata;
  
            GST_DEBUG_PAD_NAME (sinkpad));
  
        /* store the selector for the pad */
 -      g_object_set_data (G_OBJECT (sinkpad), "playbin2.select", select);
 +      g_object_set_data (G_OBJECT (sinkpad), "playbin.select", select);
  
        /* connect to the notify::tags signal for our
         * own *-tags-changed signals
            g_signal_connect_data (G_OBJECT (sinkpad), "notify::tags",
            G_CALLBACK (notify_tags_cb), ntdata, (GClosureNotify) g_free,
            (GConnectFlags) 0);
 -      g_object_set_data (G_OBJECT (sinkpad), "playbin2.notify_tags_handler",
 +      g_object_set_data (G_OBJECT (sinkpad), "playbin.notify_tags_handler",
            (gpointer) (guintptr) notify_tags_handler);
  
        /* store the pad in the array */
          goto link_failed;
  
        /* store selector pad so we can release it */
 -      g_object_set_data (G_OBJECT (pad), "playbin2.sinkpad", sinkpad);
 +      g_object_set_data (G_OBJECT (pad), "playbin.sinkpad", sinkpad);
  
        changed = TRUE;
        GST_DEBUG_OBJECT (playbin, "linked pad %s:%s to selector %p",
        case GST_PLAY_SINK_TYPE_VIDEO_RAW:
          /* we want to return NOT_LINKED for unselected pads but only for pads
           * from the normal uridecodebin. This makes sure that subtitle streams
 -         * are not raced past audio/video from decodebin2's multiqueue.
 +         * are not raced past audio/video from decodebin's multiqueue.
           * For pads from suburidecodebin OK should always be returned, otherwise
           * it will most likely stop. */
          g_object_set (sinkpad, "always-ok", always_ok, NULL);
@@@ -2746,18 -2746,18 +2752,18 @@@ pad_removed_cb (GstElement * decodebin
  
    GST_SOURCE_GROUP_LOCK (group);
    /* get the selector sinkpad */
 -  if (!(peer = g_object_get_data (G_OBJECT (pad), "playbin2.sinkpad")))
 +  if (!(peer = g_object_get_data (G_OBJECT (pad), "playbin.sinkpad")))
      goto not_linked;
  
 -  if ((select = g_object_get_data (G_OBJECT (peer), "playbin2.select"))) {
 +  if ((select = g_object_get_data (G_OBJECT (peer), "playbin.select"))) {
      gulong notify_tags_handler;
  
      notify_tags_handler =
          (guintptr) g_object_get_data (G_OBJECT (peer),
 -        "playbin2.notify_tags_handler");
 +        "playbin.notify_tags_handler");
      if (notify_tags_handler != 0)
        g_signal_handler_disconnect (G_OBJECT (peer), notify_tags_handler);
 -    g_object_set_data (G_OBJECT (peer), "playbin2.notify_tags_handler", NULL);
 +    g_object_set_data (G_OBJECT (peer), "playbin.notify_tags_handler", NULL);
  
      /* remove the pad from the array */
      g_ptr_array_remove (select->channels, peer);
@@@ -2907,7 -2907,7 +2913,7 @@@ no_more_pads_cb (GstElement * decodebin
          GstEvent *event;
          guint32 seqnum;
  
 -        s = gst_structure_new ("playbin2-stream-changed", "uri", G_TYPE_STRING,
 +        s = gst_structure_new ("playbin-stream-changed", "uri", G_TYPE_STRING,
              group->uri, NULL);
          if (group->suburi)
            gst_structure_set (s, "suburi", G_TYPE_STRING, group->suburi, NULL);
            gst_event_unref (select->sinkpad_delayed_event);
          select->sinkpad_delayed_event = event;
          if (select->sinkpad_data_probe)
 -          gst_pad_remove_data_probe (select->sinkpad,
 -              select->sinkpad_data_probe);
 +          gst_pad_remove_probe (select->sinkpad, select->sinkpad_data_probe);
  
          /* we go to the trouble of setting a probe on the pad to send
 -           the playbin2-stream-changed event as sending it here might
 +           the playbin-stream-changed event as sending it here might
             find that the pad is blocked, so we'd block here, and the
             pad might not be linked yet. Additionally, sending it here
             apparently would be on the wrong thread */
          select->sinkpad_data_probe =
 -            gst_pad_add_data_probe (select->sinkpad,
 -            (GCallback) stream_changed_data_probe, (gpointer) select);
 +            gst_pad_add_probe (select->sinkpad,
 +            GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM,
 +            stream_changed_data_probe, (gpointer) select, NULL);
  
          g_mutex_unlock (group->stream_changed_pending_lock);
          gst_message_unref (msg);
        if (select->srcpad) {
          GST_DEBUG_OBJECT (playbin, "unblocking %" GST_PTR_FORMAT,
              select->srcpad);
 -        gst_pad_set_blocked_async (select->srcpad, FALSE, selector_blocked,
 -            NULL);
 +        if (select->block_id) {
 +          gst_pad_remove_probe (select->srcpad, select->block_id);
 +          select->block_id = 0;
 +        }
        }
      }
      GST_SOURCE_GROUP_UNLOCK (group);
@@@ -2978,10 -2976,8 +2984,10 @@@ shutdown
          }
          GST_DEBUG_OBJECT (playbin, "unblocking %" GST_PTR_FORMAT,
              select->srcpad);
 -        gst_pad_set_blocked_async (select->srcpad, FALSE, selector_blocked,
 -            NULL);
 +        if (select->block_id) {
 +          gst_pad_remove_probe (select->srcpad, select->block_id);
 +          select->block_id = 0;
 +        }
        }
      }
      GST_SOURCE_GROUP_UNLOCK (group);
@@@ -3148,9 -3144,9 +3154,9 @@@ autoplug_continue_cb (GstElement * elem
      if (GST_STATE (sink) < GST_STATE_READY)
        gst_element_set_state (sink, GST_STATE_READY);
  
 -    sinkcaps = gst_pad_get_caps_reffed (sinkpad);
 +    sinkcaps = gst_pad_query_caps (sinkpad, NULL);
      if (!gst_caps_is_any (sinkcaps))
 -      ret = !gst_pad_accept_caps (sinkpad, caps);
 +      ret = !gst_pad_query_accept_caps (sinkpad, caps);
      gst_caps_unref (sinkcaps);
      gst_object_unref (sinkpad);
    } else {
        if (GST_STATE (sink) < GST_STATE_READY)
          gst_element_set_state (sink, GST_STATE_READY);
  
 -      sinkcaps = gst_pad_get_caps_reffed (sinkpad);
 +      sinkcaps = gst_pad_query_caps (sinkpad, NULL);
        if (!gst_caps_is_any (sinkcaps))
 -        ret = !gst_pad_accept_caps (sinkpad, caps);
 +        ret = !gst_pad_query_accept_caps (sinkpad, caps);
        gst_caps_unref (sinkcaps);
        gst_object_unref (sinkpad);
      }
        if (GST_STATE (sink) < GST_STATE_READY)
          gst_element_set_state (sink, GST_STATE_READY);
  
 -      sinkcaps = gst_pad_get_caps_reffed (sinkpad);
 +      sinkcaps = gst_pad_query_caps (sinkpad, NULL);
        if (!gst_caps_is_any (sinkcaps))
 -        ret = !gst_pad_accept_caps (sinkpad, caps);
 +        ret = !gst_pad_query_accept_caps (sinkpad, caps);
        gst_caps_unref (sinkcaps);
        gst_object_unref (sinkpad);
      }
@@@ -3237,7 -3233,7 +3243,7 @@@ sink_accepts_caps (GstElement * sink, G
    if ((sinkpad = gst_element_get_static_pad (sink, "sink"))) {
      /* Got the sink pad, now let's see if the element actually does accept the
       * caps that we have */
 -    if (!gst_pad_accept_caps (sinkpad, caps)) {
 +    if (!gst_pad_query_accept_caps (sinkpad, caps)) {
        gst_object_unref (sinkpad);
        return FALSE;
      }
@@@ -3271,7 -3267,8 +3277,7 @@@ autoplug_select_cb (GstElement * decode
    GST_DEBUG_OBJECT (playbin, "select group %p for %s:%s, %" GST_PTR_FORMAT,
        group, GST_DEBUG_PAD_NAME (pad), caps);
  
 -  GST_DEBUG_OBJECT (playbin, "checking factory %s",
 -      GST_PLUGIN_FEATURE_NAME (factory));
 +  GST_DEBUG_OBJECT (playbin, "checking factory %s", GST_OBJECT_NAME (factory));
  
    /* if it's not a sink, we make sure the element is compatible with
     * the fixed sink */
              (isaudiodec) ? gst_static_caps_get (&raw_audio_caps) :
              gst_static_caps_get (&raw_video_caps);
  
 -        caps = gst_pad_get_caps_reffed (sinkpad);
 +        caps = gst_pad_query_caps (sinkpad, NULL);
  
          /* If the sink supports raw audio/video, we first check
           * if the decoder could output any raw audio/video format
          return GST_AUTOPLUG_SELECT_TRY;
  
        GST_DEBUG_OBJECT (playbin, "%s not compatible with the fixed sink",
 -          GST_PLUGIN_FEATURE_NAME (factory));
 +          GST_OBJECT_NAME (factory));
  
        return GST_AUTOPLUG_SELECT_SKIP;
      } else
@@@ -3626,7 -3623,7 +3632,7 @@@ activate_group (GstPlayBin * playbin, G
      goto uridecodebin_failure;
  
    GST_SOURCE_GROUP_LOCK (group);
 -  /* alow state changes of the playbin2 affect the group elements now */
 +  /* alow state changes of the playbin affect the group elements now */
    group_set_locked_state_unlocked (playbin, group, FALSE);
    group->active = TRUE;
    GST_SOURCE_GROUP_UNLOCK (group);
@@@ -4023,8 -4020,8 +4029,8 @@@ failure
  gboolean
  gst_play_bin2_plugin_init (GstPlugin * plugin)
  {
 -  GST_DEBUG_CATEGORY_INIT (gst_play_bin_debug, "playbin2", 0, "play bin");
 +  GST_DEBUG_CATEGORY_INIT (gst_play_bin_debug, "playbin", 0, "play bin");
  
 -  return gst_element_register (plugin, "playbin2", GST_RANK_NONE,
 +  return gst_element_register (plugin, "playbin", GST_RANK_NONE,
        GST_TYPE_PLAY_BIN);
  }
  #include "config.h"
  #endif
  
+ /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+  * with newer GLib versions (>= 2.31.0) */
+ #define GLIB_DISABLE_DEPRECATION_WARNINGS
  #include <string.h>
  #include <gst/gst.h>
  
@@@ -166,7 -170,6 +170,7 @@@ struct _GstPlaySin
    gboolean audio_pad_blocked;
    GstPad *audio_srcpad_stream_synchronizer;
    GstPad *audio_sinkpad_stream_synchronizer;
 +  gulong audio_block_id;
    /* audio tee */
    GstElement *audio_tee;
    GstPad *audio_tee_sink;
    gboolean video_pad_blocked;
    GstPad *video_srcpad_stream_synchronizer;
    GstPad *video_sinkpad_stream_synchronizer;
 +  gulong video_block_id;
    /* text */
    GstPad *text_pad;
    gboolean text_pad_blocked;
    GstPad *text_srcpad_stream_synchronizer;
    GstPad *text_sinkpad_stream_synchronizer;
 +  gulong text_block_id;
  
    guint32 pending_blocked_pads;
  
    gchar *font_desc;             /* font description */
    gchar *subtitle_encoding;     /* subtitle encoding */
    guint connection_speed;       /* connection speed in bits/sec (0 = unknown) */
 -  gint count;
 +  guint count;
    gboolean volume_changed;      /* volume/mute changed while no audiochain */
    gboolean mute_changed;        /* ... has been created yet */
    gint64 av_offset;
@@@ -210,7 -211,7 +214,7 @@@ struct _GstPlaySinkClas
  
      gboolean (*reconfigure) (GstPlaySink * playsink);
  
 -  GstBuffer *(*convert_frame) (GstPlaySink * playsink, GstCaps * caps);
 +  GstSample *(*convert_sample) (GstPlaySink * playsink, GstCaps * caps);
  };
  
  
@@@ -252,7 -253,7 +256,7 @@@ enu
    PROP_FONT_DESC,
    PROP_SUBTITLE_ENCODING,
    PROP_VIS_PLUGIN,
 -  PROP_FRAME,
 +  PROP_SAMPLE,
    PROP_AV_OFFSET,
    PROP_VIDEO_SINK,
    PROP_AUDIO_SINK,
@@@ -274,7 -275,7 +278,7 @@@ static void gst_play_sink_get_property 
      GValue * value, GParamSpec * spec);
  
  static GstPad *gst_play_sink_request_new_pad (GstElement * element,
 -    GstPadTemplate * templ, const gchar * name);
 +    GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
  static void gst_play_sink_release_request_pad (GstElement * element,
      GstPad * pad);
  static gboolean gst_play_sink_send_event (GstElement * element,
@@@ -292,18 -293,18 +296,18 @@@ static void notify_mute_cb (GObject * o
  static void update_av_offset (GstPlaySink * playsink);
  
  void
 -gst_play_marshal_BUFFER__BOXED (GClosure * closure,
 +gst_play_marshal_SAMPLE__BOXED (GClosure * closure,
      GValue * return_value G_GNUC_UNUSED,
      guint n_param_values,
      const GValue * param_values,
      gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data)
  {
 -  typedef GstBuffer *(*GMarshalFunc_OBJECT__BOXED) (gpointer data1,
 +  typedef GstSample *(*GMarshalFunc_OBJECT__BOXED) (gpointer data1,
        gpointer arg_1, gpointer data2);
    register GMarshalFunc_OBJECT__BOXED callback;
    register GCClosure *cc = (GCClosure *) closure;
    register gpointer data1, data2;
 -  GstBuffer *v_return;
 +  GstSample *v_return;
    g_return_if_fail (return_value != NULL);
    g_return_if_fail (n_param_values == 2);
  
  
    v_return = callback (data1, g_value_get_boxed (param_values + 1), data2);
  
 -  gst_value_take_buffer (return_value, v_return);
 +  gst_value_take_sample (return_value, v_return);
  }
  
  /* static guint gst_play_sink_signals[LAST_SIGNAL] = { 0 }; */
@@@ -386,15 -387,17 +390,15 @@@ gst_play_sink_class_init (GstPlaySinkCl
            "the visualization element to use (NULL = default)",
            GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
    /**
 -   * GstPlaySink:frame:
 +   * GstPlaySink:sample:
     *
 -   * Get the currently rendered or prerolled frame in the video sink.
 -   * The #GstCaps on the buffer will describe the format of the buffer.
 -   *
 -   * Since: 0.10.30
 +   * Get the currently rendered or prerolled sample in the video sink.
 +   * The #GstCaps in the sample will describe the format of the buffer.
     */
 -  g_object_class_install_property (gobject_klass, PROP_FRAME,
 -      gst_param_spec_mini_object ("frame", "Frame",
 -          "The last frame (NULL = no video available)",
 -          GST_TYPE_BUFFER, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 +  g_object_class_install_property (gobject_klass, PROP_SAMPLE,
 +      g_param_spec_boxed ("sample", "Sample",
 +          "The last sample (NULL = no video available)",
 +          GST_TYPE_SAMPLE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
    /**
     * GstPlaySink:av-offset:
     *
            reconfigure), NULL, NULL, gst_marshal_BOOLEAN__VOID, G_TYPE_BOOLEAN,
        0, G_TYPE_NONE);
    /**
 -   * GstPlaySink::convert-frame
 +   * GstPlaySink::convert-sample
     * @playsink: a #GstPlaySink
 -   * @caps: the target format of the frame
 +   * @caps: the target format of the sample
     *
 -   * Action signal to retrieve the currently playing video frame in the format
 +   * Action signal to retrieve the currently playing video sample in the format
     * specified by @caps.
     * If @caps is %NULL, no conversion will be performed and this function is
 -   * equivalent to the #GstPlaySink::frame property.
 +   * equivalent to the #GstPlaySink::sample property.
     *
 -   * Returns: a #GstBuffer of the current video frame converted to #caps.
 -   * The caps on the buffer will describe the final layout of the buffer data.
 -   * %NULL is returned when no current buffer can be retrieved or when the
 +   * Returns: a #GstSample of the current video sample converted to #caps.
 +   * The caps in the sample will describe the final layout of the buffer data.
 +   * %NULL is returned when no current sample can be retrieved or when the
     * conversion failed.
 -   *
 -   * Since: 0.10.30
     */
 -  g_signal_new ("convert-frame", G_TYPE_FROM_CLASS (klass),
 +  g_signal_new ("convert-sample", G_TYPE_FROM_CLASS (klass),
        G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
 -      G_STRUCT_OFFSET (GstPlaySinkClass, convert_frame), NULL, NULL,
 -      gst_play_marshal_BUFFER__BOXED, GST_TYPE_BUFFER, 1, GST_TYPE_CAPS);
 -
 -  gst_element_class_add_static_pad_template (gstelement_klass,
 -      &audiorawtemplate);
 -  gst_element_class_add_static_pad_template (gstelement_klass,
 -      &audiotemplate);
 -  gst_element_class_add_static_pad_template (gstelement_klass,
 -      &videorawtemplate);
 -  gst_element_class_add_static_pad_template (gstelement_klass,
 -      &videotemplate);
 -  gst_element_class_add_static_pad_template (gstelement_klass,
 -      &texttemplate);
 +      G_STRUCT_OFFSET (GstPlaySinkClass, convert_sample), NULL, NULL,
 +      gst_play_marshal_SAMPLE__BOXED, GST_TYPE_SAMPLE, 1, GST_TYPE_CAPS);
 +
 +  gst_element_class_add_pad_template (gstelement_klass,
 +      gst_static_pad_template_get (&audiorawtemplate));
 +  gst_element_class_add_pad_template (gstelement_klass,
 +      gst_static_pad_template_get (&audiotemplate));
 +  gst_element_class_add_pad_template (gstelement_klass,
 +      gst_static_pad_template_get (&videorawtemplate));
 +  gst_element_class_add_pad_template (gstelement_klass,
 +      gst_static_pad_template_get (&videotemplate));
 +  gst_element_class_add_pad_template (gstelement_klass,
 +      gst_static_pad_template_get (&texttemplate));
    gst_element_class_set_details_simple (gstelement_klass, "Player Sink",
        "Generic/Bin/Sink",
        "Convenience sink for multiple streams",
        GST_DEBUG_FUNCPTR (gst_play_sink_handle_message);
  
    klass->reconfigure = GST_DEBUG_FUNCPTR (gst_play_sink_reconfigure);
 -  klass->convert_frame = GST_DEBUG_FUNCPTR (gst_play_sink_convert_frame);
 +  klass->convert_sample = GST_DEBUG_FUNCPTR (gst_play_sink_convert_sample);
  }
  
  static void
@@@ -521,7 -526,7 +525,7 @@@ gst_play_sink_init (GstPlaySink * plays
        GST_ELEMENT_CAST (playsink->stream_synchronizer));
  
    g_static_rec_mutex_init (&playsink->lock);
 -  GST_OBJECT_FLAG_SET (playsink, GST_ELEMENT_IS_SINK);
 +  GST_OBJECT_FLAG_SET (playsink, GST_ELEMENT_FLAG_SINK);
  }
  
  static void
@@@ -716,8 -721,20 +720,8 @@@ gst_play_sink_get_sink (GstPlaySink * p
    return result;
  }
  
 -static void
 -gst_play_sink_vis_unblocked (GstPad * tee_pad, gboolean blocked,
 -    gpointer user_data)
 -{
 -  GstPlaySink *playsink;
 -
 -  playsink = GST_PLAY_SINK (user_data);
 -  /* nothing to do here, we need a dummy callback here to make the async call
 -   * non-blocking. */
 -  GST_DEBUG_OBJECT (playsink, "vis pad unblocked");
 -}
 -
 -static void
 -gst_play_sink_vis_blocked (GstPad * tee_pad, gboolean blocked,
 +static GstPadProbeReturn
 +gst_play_sink_vis_blocked (GstPad * tee_pad, GstPadProbeInfo * info,
      gpointer user_data)
  {
    GstPlaySink *playsink;
        chain->vissrcpad);
  
  done:
 -  /* Unblock the pad */
 -  gst_pad_set_blocked_async (tee_pad, FALSE, gst_play_sink_vis_unblocked,
 -      playsink);
    GST_PLAY_SINK_UNLOCK (playsink);
 +
 +  /* remove the probe and unblock the pad */
 +  return GST_PAD_PROBE_REMOVE;
  }
  
  void
@@@ -795,8 -812,8 +799,8 @@@ gst_play_sink_set_vis_plugin (GstPlaySi
     * function returns FALSE but the previous pad block will do the right thing
     * anyway. */
    GST_DEBUG_OBJECT (playsink, "blocking vis pad");
 -  gst_pad_set_blocked_async (chain->blockpad, TRUE, gst_play_sink_vis_blocked,
 -      playsink);
 +  gst_pad_add_probe (chain->blockpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
 +      gst_play_sink_vis_blocked, playsink, NULL);
  done:
    GST_PLAY_SINK_UNLOCK (playsink);
  
@@@ -928,7 -945,7 +932,7 @@@ add_chain (GstPlayChain * chain, gboole
    else {
      gst_bin_remove (GST_BIN_CAST (chain->playsink), chain->bin);
      /* we don't want to lose our sink status */
 -    GST_OBJECT_FLAG_SET (chain->playsink, GST_ELEMENT_IS_SINK);
 +    GST_OBJECT_FLAG_SET (chain->playsink, GST_ELEMENT_FLAG_SINK);
    }
  
    chain->added = add;
@@@ -964,7 -981,7 +968,7 @@@ element_is_sink (GstElement * element
    gboolean is_sink;
  
    GST_OBJECT_LOCK (element);
 -  is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK);
 +  is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SINK);
    GST_OBJECT_UNLOCK (element);
  
    GST_DEBUG_OBJECT (element, "is a sink: %s", (is_sink) ? "yes" : "no");
@@@ -1005,14 -1022,15 +1009,14 @@@ typedef struc
  } FindPropertyHelper;
  
  static gint
 -find_property (GstElement * element, FindPropertyHelper * helper)
 +find_property (const GValue * item, FindPropertyHelper * helper)
  {
 +  GstElement *element = g_value_get_object (item);
    if (helper->need_sink && !element_is_sink (element)) {
 -    gst_object_unref (element);
      return 1;
    }
  
    if (!element_has_property (element, helper->prop_name, helper->prop_type)) {
 -    gst_object_unref (element);
      return 1;
    }
  
@@@ -1035,19 -1053,15 +1039,19 @@@ gst_play_sink_find_property_sinks (GstP
    if (element_has_property (obj, name, expected_type)) {
      result = obj;
    } else if (GST_IS_BIN (obj)) {
 +    gboolean found;
 +    GValue item = { 0, };
      FindPropertyHelper helper = { name, expected_type, TRUE };
  
      it = gst_bin_iterate_recurse (GST_BIN_CAST (obj));
 -    result = gst_iterator_find_custom (it,
 -        (GCompareFunc) find_property, &helper);
 +    found = gst_iterator_find_custom (it,
 +        (GCompareFunc) find_property, &item, &helper);
      gst_iterator_free (it);
 -    /* we don't need the extra ref */
 -    if (result)
 -      gst_object_unref (result);
 +    if (found) {
 +      result = g_value_get_object (&item);
 +      /* we don't need the extra ref */
 +      g_value_unset (&item);
 +    }
    }
    return result;
  }
@@@ -1061,17 -1075,12 +1065,17 @@@ gst_play_sink_find_property (GstPlaySin
    GstIterator *it;
  
    if (GST_IS_BIN (obj)) {
 +    gboolean found;
 +    GValue item = { 0, };
      FindPropertyHelper helper = { name, expected_type, FALSE };
  
      it = gst_bin_iterate_recurse (GST_BIN_CAST (obj));
 -    result = gst_iterator_find_custom (it,
 -        (GCompareFunc) find_property, &helper);
 +    found = gst_iterator_find_custom (it,
 +        (GCompareFunc) find_property, &item, &helper);
      gst_iterator_free (it);
 +    if (found)
 +      result = g_value_dup_object (&item);
 +    g_value_unset (&item);
    } else {
      if (element_has_property (obj, name, expected_type)) {
        result = obj;
@@@ -1094,7 -1103,7 +1098,7 @@@ do_async_start (GstPlaySink * playsink
    playsink->async_pending = TRUE;
  
    GST_INFO_OBJECT (playsink, "Sending async_start message");
 -  message = gst_message_new_async_start (GST_OBJECT_CAST (playsink), FALSE);
 +  message = gst_message_new_async_start (GST_OBJECT_CAST (playsink));
    GST_BIN_CLASS (gst_play_sink_parent_class)->handle_message (GST_BIN_CAST
        (playsink), message);
  }
@@@ -1106,7 -1115,7 +1110,7 @@@ do_async_done (GstPlaySink * playsink
  
    if (playsink->async_pending) {
      GST_INFO_OBJECT (playsink, "Sending async_done message");
 -    message = gst_message_new_async_done (GST_OBJECT_CAST (playsink));
 +    message = gst_message_new_async_done (GST_OBJECT_CAST (playsink), FALSE);
      GST_BIN_CLASS (gst_play_sink_parent_class)->handle_message (GST_BIN_CAST
          (playsink), message);
  
@@@ -2250,18 -2259,16 +2254,18 @@@ gst_play_sink_reconfigure (GstPlaySink 
        goto no_chain;
  
      if (!playsink->video_sinkpad_stream_synchronizer) {
 +      GValue item = { 0, };
        GstIterator *it;
  
        playsink->video_sinkpad_stream_synchronizer =
            gst_element_get_request_pad (GST_ELEMENT_CAST
 -          (playsink->stream_synchronizer), "sink_%d");
 +          (playsink->stream_synchronizer), "sink_%u");
        it = gst_pad_iterate_internal_links
            (playsink->video_sinkpad_stream_synchronizer);
        g_assert (it);
 -      gst_iterator_next (it,
 -          (gpointer *) & playsink->video_srcpad_stream_synchronizer);
 +      gst_iterator_next (it, &item);
 +      playsink->video_srcpad_stream_synchronizer = g_value_dup_object (&item);
 +      g_value_unset (&item);
        g_assert (playsink->video_srcpad_stream_synchronizer);
        gst_iterator_free (it);
      }
      }
  
      if (!playsink->audio_sinkpad_stream_synchronizer) {
 +      GValue item = { 0, };
        GstIterator *it;
  
        playsink->audio_sinkpad_stream_synchronizer =
            gst_element_get_request_pad (GST_ELEMENT_CAST
 -          (playsink->stream_synchronizer), "sink_%d");
 +          (playsink->stream_synchronizer), "sink_%u");
        it = gst_pad_iterate_internal_links
            (playsink->audio_sinkpad_stream_synchronizer);
        g_assert (it);
 -      gst_iterator_next (it,
 -          (gpointer *) & playsink->audio_srcpad_stream_synchronizer);
 +      gst_iterator_next (it, &item);
 +      playsink->audio_srcpad_stream_synchronizer = g_value_dup_object (&item);
 +      g_value_unset (&item);
        g_assert (playsink->audio_srcpad_stream_synchronizer);
        gst_iterator_free (it);
      }
        GST_DEBUG_OBJECT (playsink, "adding audio chain");
        if (playsink->audio_tee_asrc == NULL) {
          playsink->audio_tee_asrc =
 -            gst_element_get_request_pad (playsink->audio_tee, "src%d");
 +            gst_element_get_request_pad (playsink->audio_tee, "src_%u");
        }
        add_chain (GST_PLAY_CHAIN (playsink->audiochain), TRUE);
        activate_chain (GST_PLAY_CHAIN (playsink->audiochain), TRUE);
        activate_chain (GST_PLAY_CHAIN (playsink->vischain), TRUE);
        if (playsink->audio_tee_vissrc == NULL) {
          playsink->audio_tee_vissrc =
 -            gst_element_get_request_pad (playsink->audio_tee, "src%d");
 +            gst_element_get_request_pad (playsink->audio_tee, "src_%u");
        }
        gst_pad_link_full (playsink->audio_tee_vissrc,
            playsink->vischain->sinkpad, GST_PAD_LINK_CHECK_NOTHING);
        add_chain (GST_PLAY_CHAIN (playsink->textchain), TRUE);
  
        if (!playsink->text_sinkpad_stream_synchronizer) {
 +        GValue item = { 0, };
 +
          playsink->text_sinkpad_stream_synchronizer =
              gst_element_get_request_pad (GST_ELEMENT_CAST
 -            (playsink->stream_synchronizer), "sink_%d");
 +            (playsink->stream_synchronizer), "sink_%u");
          it = gst_pad_iterate_internal_links
              (playsink->text_sinkpad_stream_synchronizer);
          g_assert (it);
 -        gst_iterator_next (it,
 -            (gpointer *) & playsink->text_srcpad_stream_synchronizer);
 +        gst_iterator_next (it, &item);
 +        playsink->text_srcpad_stream_synchronizer = g_value_dup_object (&item);
 +        g_value_unset (&item);
          g_assert (playsink->text_srcpad_stream_synchronizer);
          gst_iterator_free (it);
  
@@@ -2793,24 -2795,24 +2797,24 @@@ gst_play_sink_get_av_offset (GstPlaySin
  }
  
  /**
 - * gst_play_sink_get_last_frame:
 + * gst_play_sink_get_last_sample:
   * @playsink: a #GstPlaySink
   *
 - * Get the last displayed frame from @playsink. This frame is in the native
 - * format of the sink element, the caps on the result buffer contain the format
 + * Get the last displayed sample from @playsink. This sample is in the native
 + * format of the sink element, the caps in the result sample contain the format
   * of the frame data.
   *
 - * Returns: a #GstBuffer with the frame data or %NULL when no video frame is
 + * Returns: a #GstSample with the frame data or %NULL when no video frame is
   * available.
   */
 -GstBuffer *
 -gst_play_sink_get_last_frame (GstPlaySink * playsink)
 +GstSample *
 +gst_play_sink_get_last_sample (GstPlaySink * playsink)
  {
 -  GstBuffer *result = NULL;
 +  GstSample *result = NULL;
    GstPlayVideoChain *chain;
  
    GST_PLAY_SINK_LOCK (playsink);
 -  GST_DEBUG_OBJECT (playsink, "taking last frame");
 +  GST_DEBUG_OBJECT (playsink, "taking last sample");
    /* get the video chain if we can */
    if ((chain = (GstPlayVideoChain *) playsink->videochain)) {
      GST_DEBUG_OBJECT (playsink, "found video chain");
        /* find and get the last-buffer property now */
        if ((elem =
                gst_play_sink_find_property (playsink, chain->sink,
 -                  "last-buffer", GST_TYPE_BUFFER))) {
 -        GST_DEBUG_OBJECT (playsink, "getting last-buffer property");
 -        g_object_get (elem, "last-buffer", &result, NULL);
 +                  "last-sample", GST_TYPE_SAMPLE))) {
 +        GST_DEBUG_OBJECT (playsink, "getting last-sample property");
 +        g_object_get (elem, "last-sample", &result, NULL);
          gst_object_unref (elem);
        }
      }
  }
  
  /**
 - * gst_play_sink_convert_frame:
 + * gst_play_sink_convert_sample:
   * @playsink: a #GstPlaySink
   * @caps: a #GstCaps
   *
   * Returns: a #GstBuffer with the frame data or %NULL when no video frame is
   * available or when the conversion failed.
   */
 -GstBuffer *
 -gst_play_sink_convert_frame (GstPlaySink * playsink, GstCaps * caps)
 +GstSample *
 +gst_play_sink_convert_sample (GstPlaySink * playsink, GstCaps * caps)
  {
 -  GstBuffer *result;
 +  GstSample *result;
 +  GError *err = NULL;
  
 -  result = gst_play_sink_get_last_frame (playsink);
 +  result = gst_play_sink_get_last_sample (playsink);
    if (result != NULL && caps != NULL) {
 -    GstBuffer *temp;
 -    GError *err = NULL;
 +    GstSample *temp;
  
 -    temp = gst_video_convert_frame (result, caps, 25 * GST_SECOND, &err);
 -    gst_buffer_unref (result);
 -    if (temp == NULL && err) {
 -      /* I'm really uncertain whether we should make playsink post an error
 -       * on the bus or not. It's not like it's a critical issue regarding
 -       * playsink behaviour. */
 -      GST_ERROR ("Error converting frame: %s", err->message);
 -    }
 +    temp = gst_video_convert_sample (result, caps, 25 * GST_SECOND, &err);
 +    if (temp == NULL && err)
 +      goto error;
 +
 +    gst_sample_unref (result);
      result = temp;
    }
    return result;
 +
 +  /* ERRORS */
 +error:
 +  {
 +    /* I'm really uncertain whether we should make playsink post an error
 +     * on the bus or not. It's not like it's a critical issue regarding
 +     * playsink behaviour. */
 +    GST_ERROR ("Error converting frame: %s", err->message);
 +    gst_sample_unref (result);
 +    g_error_free (err);
 +    return NULL;
 +  }
  }
  
  static gboolean
@@@ -2887,8 -2880,8 +2891,8 @@@ is_raw_structure (GstStructure * s
  
    name = gst_structure_get_name (s);
  
 -  if (g_str_has_prefix (name, "video/x-raw-") ||
 -      g_str_has_prefix (name, "audio/x-raw-"))
 +  if (g_str_has_prefix (name, "video/x-raw") ||
 +      g_str_has_prefix (name, "audio/x-raw"))
      return TRUE;
    return FALSE;
  }
@@@ -2903,11 -2896,11 +2907,11 @@@ is_raw_pad (GstPad * pad
    if (!peer)
      return raw;
  
 -  caps = gst_pad_get_negotiated_caps (peer);
 +  caps = gst_pad_get_current_caps (peer);
    if (!caps) {
      guint i, n;
  
 -    caps = gst_pad_get_caps_reffed (peer);
 +    caps = gst_pad_query_caps (peer, NULL);
  
      n = gst_caps_get_size (caps);
      for (i = 0; i < n; i++) {
    return raw;
  }
  
 +static GstPadProbeReturn
 +sinkpad_blocked_cb (GstPad * blockedpad, GstPadProbeInfo * info,
 +    gpointer user_data);
 +
 +static void
 +video_set_blocked (GstPlaySink * playsink, gboolean blocked)
 +{
 +  if (playsink->video_pad) {
 +    GstPad *opad =
 +        GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
 +            (playsink->video_pad)));
 +    if (blocked && playsink->video_block_id == 0) {
 +      playsink->video_block_id =
 +          gst_pad_add_probe (opad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
 +          sinkpad_blocked_cb, gst_object_ref (playsink),
 +          (GDestroyNotify) gst_object_unref);
 +    } else if (!blocked && playsink->video_block_id) {
 +      gst_pad_remove_probe (opad, playsink->video_block_id);
 +      PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_VIDEO_RAW);
 +      PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_VIDEO);
 +      playsink->video_block_id = 0;
 +      playsink->video_pad_blocked = FALSE;
 +    }
 +    gst_object_unref (opad);
 +  }
 +}
 +
  static void
 -sinkpad_blocked_cb (GstPad * blockedpad, gboolean blocked, gpointer user_data)
 +audio_set_blocked (GstPlaySink * playsink, gboolean blocked)
 +{
 +  if (playsink->audio_pad) {
 +    GstPad *opad =
 +        GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
 +            (playsink->audio_pad)));
 +    if (blocked && playsink->audio_block_id == 0) {
 +      playsink->audio_block_id =
 +          gst_pad_add_probe (opad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
 +          sinkpad_blocked_cb, gst_object_ref (playsink),
 +          (GDestroyNotify) gst_object_unref);
 +    } else if (!blocked && playsink->audio_block_id) {
 +      gst_pad_remove_probe (opad, playsink->audio_block_id);
 +      PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_AUDIO_RAW);
 +      PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_AUDIO);
 +      playsink->audio_block_id = 0;
 +      playsink->audio_pad_blocked = FALSE;
 +    }
 +    gst_object_unref (opad);
 +  }
 +}
 +
 +static void
 +text_set_blocked (GstPlaySink * playsink, gboolean blocked)
 +{
 +  if (playsink->text_pad) {
 +    GstPad *opad =
 +        GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
 +            (playsink->text_pad)));
 +    if (blocked && playsink->text_block_id == 0) {
 +      playsink->text_block_id =
 +          gst_pad_add_probe (opad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
 +          sinkpad_blocked_cb, gst_object_ref (playsink),
 +          (GDestroyNotify) gst_object_unref);
 +    } else if (!blocked && playsink->text_block_id) {
 +      gst_pad_remove_probe (opad, playsink->text_block_id);
 +      PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_TEXT);
 +      playsink->text_block_id = 0;
 +      playsink->text_pad_blocked = FALSE;
 +    }
 +    gst_object_unref (opad);
 +  }
 +}
 +
 +static GstPadProbeReturn
 +sinkpad_blocked_cb (GstPad * blockedpad, GstPadProbeInfo * info,
 +    gpointer user_data)
  {
    GstPlaySink *playsink = (GstPlaySink *) user_data;
    GstPad *pad;
  
    pad = GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD (blockedpad)));
    if (pad == playsink->video_pad) {
 -    playsink->video_pad_blocked = blocked;
 -    GST_DEBUG_OBJECT (pad, "Video pad blocked: %d", blocked);
 -    if (!blocked) {
 -      PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_VIDEO_RAW);
 -      PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_VIDEO);
 -    }
 +    playsink->video_pad_blocked = TRUE;
 +    GST_DEBUG_OBJECT (pad, "Video pad blocked");
    } else if (pad == playsink->audio_pad) {
 -    playsink->audio_pad_blocked = blocked;
 -    GST_DEBUG_OBJECT (pad, "Audio pad blocked: %d", blocked);
 -    if (!blocked) {
 -      PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_AUDIO_RAW);
 -      PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_AUDIO);
 -    }
 +    playsink->audio_pad_blocked = TRUE;
 +    GST_DEBUG_OBJECT (pad, "Audio pad blocked");
    } else if (pad == playsink->text_pad) {
 -    playsink->text_pad_blocked = blocked;
 -    GST_DEBUG_OBJECT (pad, "Text pad blocked: %d", blocked);
 -    if (!blocked)
 -      PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_TEXT);
 -  }
 -
 -  if (!blocked) {
 -    gst_object_unref (pad);
 -    GST_PLAY_SINK_UNLOCK (playsink);
 -    return;
 +    playsink->text_pad_blocked = TRUE;
 +    GST_DEBUG_OBJECT (pad, "Text pad blocked");
    }
  
    /* We reconfigure when for ALL streams:
  
      gst_play_sink_reconfigure (playsink);
  
 -    if (playsink->video_pad) {
 -      GstPad *opad =
 -          GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
 -              (playsink->video_pad)));
 -      gst_pad_set_blocked_async_full (opad, FALSE, sinkpad_blocked_cb,
 -          gst_object_ref (playsink), (GDestroyNotify) gst_object_unref);
 -      gst_object_unref (opad);
 -    }
 -
 -    if (playsink->audio_pad) {
 -      GstPad *opad =
 -          GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
 -              (playsink->audio_pad)));
 -      gst_pad_set_blocked_async_full (opad, FALSE, sinkpad_blocked_cb,
 -          gst_object_ref (playsink), (GDestroyNotify) gst_object_unref);
 -      gst_object_unref (opad);
 -    }
 -
 -    if (playsink->text_pad) {
 -      GstPad *opad =
 -          GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
 -              (playsink->text_pad)));
 -      gst_pad_set_blocked_async_full (opad, FALSE, sinkpad_blocked_cb,
 -          gst_object_ref (playsink), (GDestroyNotify) gst_object_unref);
 -      gst_object_unref (opad);
 -    }
 +    video_set_blocked (playsink, FALSE);
 +    audio_set_blocked (playsink, FALSE);
 +    text_set_blocked (playsink, FALSE);
    }
  
    gst_object_unref (pad);
  
    GST_PLAY_SINK_UNLOCK (playsink);
 +
 +  return GST_PAD_PROBE_OK;
  }
  
  static void
@@@ -3076,14 -3033,14 +3080,14 @@@ caps_notify_cb (GstPad * pad, GParamSpe
  
    if (pad == playsink->audio_pad) {
      raw = is_raw_pad (pad);
 -    reconfigure = (!!playsink->audio_pad_raw != !!raw)
 +    reconfigure = (! !playsink->audio_pad_raw != ! !raw)
          && playsink->audiochain;
      GST_DEBUG_OBJECT (pad,
          "Audio caps changed: raw %d reconfigure %d caps %" GST_PTR_FORMAT, raw,
          reconfigure, caps);
    } else if (pad == playsink->video_pad) {
      raw = is_raw_pad (pad);
 -    reconfigure = (!!playsink->video_pad_raw != !!raw)
 +    reconfigure = (! !playsink->video_pad_raw != ! !raw)
          && playsink->videochain;
      GST_DEBUG_OBJECT (pad,
          "Video caps changed: raw %d reconfigure %d caps %" GST_PTR_FORMAT, raw,
  
    if (reconfigure) {
      GST_PLAY_SINK_LOCK (playsink);
 -    if (playsink->video_pad) {
 -      GstPad *opad =
 -          GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
 -              (playsink->video_pad)));
 -      gst_pad_set_blocked_async_full (opad, TRUE, sinkpad_blocked_cb,
 -          gst_object_ref (playsink), (GDestroyNotify) gst_object_unref);
 -      gst_object_unref (opad);
 -    }
 -
 -    if (playsink->audio_pad) {
 -      GstPad *opad =
 -          GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
 -              (playsink->audio_pad)));
 -      gst_pad_set_blocked_async_full (opad, TRUE, sinkpad_blocked_cb,
 -          gst_object_ref (playsink), (GDestroyNotify) gst_object_unref);
 -      gst_object_unref (opad);
 -    }
 -
 -    if (playsink->text_pad) {
 -      GstPad *opad =
 -          GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
 -              (playsink->text_pad)));
 -      gst_pad_set_blocked_async_full (opad, TRUE, sinkpad_blocked_cb,
 -          gst_object_ref (playsink), (GDestroyNotify) gst_object_unref);
 -      gst_object_unref (opad);
 -    }
 +    video_set_blocked (playsink, TRUE);
 +    audio_set_blocked (playsink, TRUE);
 +    text_set_blocked (playsink, TRUE);
      GST_PLAY_SINK_UNLOCK (playsink);
    }
  }
@@@ -3117,7 -3097,6 +3121,7 @@@ gst_play_sink_request_pad (GstPlaySink 
    gboolean created = FALSE;
    gboolean activate = TRUE;
    const gchar *pad_name = NULL;
 +  gulong *block_id = NULL;
  
    GST_DEBUG_OBJECT (playsink, "request pad type %d", type);
  
        }
        playsink->audio_pad_raw = FALSE;
        res = playsink->audio_pad;
 +      block_id = &playsink->audio_block_id;
        break;
      case GST_PLAY_SINK_TYPE_VIDEO_RAW:
      case GST_PLAY_SINK_TYPE_VIDEO:
        }
        playsink->video_pad_raw = FALSE;
        res = playsink->video_pad;
 +      block_id = &playsink->video_block_id;
        break;
      case GST_PLAY_SINK_TYPE_TEXT:
        GST_LOG_OBJECT (playsink, "ghosting text");
          created = TRUE;
        }
        res = playsink->text_pad;
 +      block_id = &playsink->text_block_id;
        break;
      case GST_PLAY_SINK_TYPE_FLUSHING:
      {
        gchar *padname;
  
        /* we need a unique padname for the flushing pad. */
 -      padname = g_strdup_printf ("flushing_%d", playsink->count);
 +      padname = g_strdup_printf ("flushing_%u", playsink->count);
        res = gst_ghost_pad_new_no_target (padname, GST_PAD_SINK);
        g_free (padname);
        playsink->count++;
       * element is 'running' */
      gst_pad_set_active (res, TRUE);
      gst_element_add_pad (GST_ELEMENT_CAST (playsink), res);
 -    if (type != GST_PLAY_SINK_TYPE_FLUSHING) {
 +    if (block_id && *block_id == 0) {
        GstPad *blockpad =
            GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD (res)));
  
 -      gst_pad_set_blocked_async_full (blockpad, TRUE, sinkpad_blocked_cb,
 -          gst_object_ref (playsink), (GDestroyNotify) gst_object_unref);
 +      *block_id =
 +          gst_pad_add_probe (blockpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
 +          sinkpad_blocked_cb, gst_object_ref (playsink),
 +          (GDestroyNotify) gst_object_unref);
        PENDING_FLAG_SET (playsink, type);
        gst_object_unref (blockpad);
      }
  
  static GstPad *
  gst_play_sink_request_new_pad (GstElement * element, GstPadTemplate * templ,
 -    const gchar * name)
 +    const gchar * name, const GstCaps * caps)
  {
    GstPlaySink *psink;
    GstPad *pad;
@@@ -3463,9 -3437,42 +3467,9 @@@ gst_play_sink_change_state (GstElement 
      case GST_STATE_CHANGE_PAUSED_TO_READY:
        /* unblock all pads here */
        GST_PLAY_SINK_LOCK (playsink);
 -      if (playsink->video_pad) {
 -        GstPad *opad =
 -            GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
 -                (playsink->video_pad)));
 -        if (gst_pad_is_blocked (opad)) {
 -          gst_pad_set_blocked_async_full (opad, FALSE, sinkpad_blocked_cb,
 -              gst_object_ref (playsink), (GDestroyNotify) gst_object_unref);
 -        }
 -        gst_object_unref (opad);
 -        playsink->video_pad_blocked = FALSE;
 -      }
 -
 -      if (playsink->audio_pad) {
 -        GstPad *opad =
 -            GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
 -                (playsink->audio_pad)));
 -
 -        if (gst_pad_is_blocked (opad)) {
 -          gst_pad_set_blocked_async_full (opad, FALSE, sinkpad_blocked_cb,
 -              gst_object_ref (playsink), (GDestroyNotify) gst_object_unref);
 -        }
 -        gst_object_unref (opad);
 -        playsink->audio_pad_blocked = FALSE;
 -      }
 -
 -      if (playsink->text_pad) {
 -        GstPad *opad =
 -            GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
 -                (playsink->text_pad)));
 -        if (gst_pad_is_blocked (opad)) {
 -          gst_pad_set_blocked_async_full (opad, FALSE, sinkpad_blocked_cb,
 -              gst_object_ref (playsink), (GDestroyNotify) gst_object_unref);
 -        }
 -        gst_object_unref (opad);
 -        playsink->text_pad_blocked = FALSE;
 -      }
 +      video_set_blocked (playsink, FALSE);
 +      audio_set_blocked (playsink, FALSE);
 +      text_set_blocked (playsink, FALSE);
        GST_PLAY_SINK_UNLOCK (playsink);
        /* fall through */
      case GST_STATE_CHANGE_READY_TO_NULL:
@@@ -3704,8 -3711,8 +3708,8 @@@ gst_play_sink_get_property (GObject * o
      case PROP_VIS_PLUGIN:
        g_value_take_object (value, gst_play_sink_get_vis_plugin (playsink));
        break;
 -    case PROP_FRAME:
 -      gst_value_take_buffer (value, gst_play_sink_get_last_frame (playsink));
 +    case PROP_SAMPLE:
 +      gst_value_take_sample (value, gst_play_sink_get_last_sample (playsink));
        break;
      case PROP_AV_OFFSET:
        g_value_set_int64 (value, gst_play_sink_get_av_offset (playsink));
  
  #include <gst/pbutils/pbutils.h>
  #include <gst/gst-i18n-plugin.h>
+ #include "gst/glib-compat-private.h"
  
  GST_DEBUG_CATEGORY_STATIC (gst_play_sink_convert_bin_debug);
  #define GST_CAT_DEFAULT gst_play_sink_convert_bin_debug
  
  #define parent_class gst_play_sink_convert_bin_parent_class
  
 +static gboolean gst_play_sink_convert_bin_sink_setcaps (GstPlaySinkConvertBin *
 +    self, GstCaps * caps);
 +
  G_DEFINE_TYPE (GstPlaySinkConvertBin, gst_play_sink_convert_bin, GST_TYPE_BIN);
  
  static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
@@@ -85,10 -83,18 +86,10 @@@ distribute_running_time (GstElement * e
    pad = gst_element_get_static_pad (element, "sink");
  
    gst_pad_send_event (pad, gst_event_new_flush_start ());
 -  gst_pad_send_event (pad, gst_event_new_flush_stop ());
 -
 -  if (segment->accum && segment->format != GST_FORMAT_UNDEFINED) {
 -    event = gst_event_new_new_segment_full (FALSE, segment->rate,
 -        segment->applied_rate, segment->format, 0, segment->accum, 0);
 -    gst_pad_send_event (pad, event);
 -  }
 +  gst_pad_send_event (pad, gst_event_new_flush_stop (FALSE));
  
    if (segment->format != GST_FORMAT_UNDEFINED) {
 -    event = gst_event_new_new_segment_full (FALSE, segment->rate,
 -        segment->applied_rate, segment->format,
 -        segment->start, segment->stop, segment->time);
 +    event = gst_event_new_segment (segment);
      gst_pad_send_event (pad, event);
    }
  
@@@ -199,22 -205,24 +200,22 @@@ gst_play_sink_convert_bin_on_element_ad
    distribute_running_time (element, &self->segment);
  }
  
 -static void
 -pad_blocked_cb (GstPad * pad, gboolean blocked, GstPlaySinkConvertBin * self)
 +static GstPadProbeReturn
 +pad_blocked_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
  {
 +  GstPlaySinkConvertBin *self = user_data;
    GstPad *peer;
    GstCaps *caps;
    gboolean raw;
  
    GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
 -  self->sink_proxypad_blocked = blocked;
 -  GST_DEBUG_OBJECT (self, "Pad blocked: %d", blocked);
 -  if (!blocked)
 -    goto done;
 +  GST_DEBUG_OBJECT (self, "Pad blocked");
  
    /* There must be a peer at this point */
    peer = gst_pad_get_peer (self->sinkpad);
 -  caps = gst_pad_get_negotiated_caps (peer);
 +  caps = gst_pad_get_current_caps (peer);
    if (!caps)
 -    caps = gst_pad_get_caps_reffed (peer);
 +    caps = gst_pad_query_caps (peer, NULL);
    gst_object_unref (peer);
  
    raw = is_raw_caps (caps, self->audio);
    gst_play_sink_convert_bin_set_targets (self, !raw);
  
  unblock:
 -  gst_pad_set_blocked_async_full (self->sink_proxypad, FALSE,
 -      (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self),
 -      (GDestroyNotify) gst_object_unref);
 -
 -done:
 +  self->sink_proxypad_block_id = 0;
    GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self);
 -  return;
 +
 +  return GST_PAD_PROBE_REMOVE;
  }
  
  static gboolean
 -gst_play_sink_convert_bin_sink_event (GstPad * pad, GstEvent * event)
 +gst_play_sink_convert_bin_sink_event (GstPad * pad, GstObject * parent,
 +    GstEvent * event)
  {
 -  GstPlaySinkConvertBin *self =
 -      GST_PLAY_SINK_CONVERT_BIN (gst_pad_get_parent (pad));
 +  GstPlaySinkConvertBin *self = GST_PLAY_SINK_CONVERT_BIN (parent);
    gboolean ret;
  
 -  ret = gst_proxy_pad_event_default (pad, gst_event_ref (event));
 +  switch (GST_EVENT_TYPE (event)) {
 +    case GST_EVENT_CAPS:
 +    {
 +      GstCaps *caps;
 +
 +      gst_event_parse_caps (event, &caps);
 +      ret = gst_play_sink_convert_bin_sink_setcaps (self, caps);
 +      break;
 +    }
 +    default:
 +      break;
 +  }
 +
 +  ret = gst_proxy_pad_event_default (pad, parent, gst_event_ref (event));
  
 -  if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
 -    gboolean update;
 -    gdouble rate, applied_rate;
 -    GstFormat format;
 -    gint64 start, stop, position;
 +  if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
 +    GstSegment seg;
  
      GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
 -    gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
 -        &format, &start, &stop, &position);
 +    gst_event_copy_segment (event, &seg);
  
      GST_DEBUG_OBJECT (self, "Segment before %" GST_SEGMENT_FORMAT,
          &self->segment);
 -    gst_segment_set_newsegment_full (&self->segment, update, rate, applied_rate,
 -        format, start, stop, position);
 +    self->segment = seg;
      GST_DEBUG_OBJECT (self, "Segment after %" GST_SEGMENT_FORMAT,
          &self->segment);
      GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self);
    }
  
    gst_event_unref (event);
 -  gst_object_unref (self);
  
    return ret;
  }
  
 +static void
 +block_proxypad (GstPlaySinkConvertBin * self)
 +{
 +  if (self->sink_proxypad_block_id == 0) {
 +    self->sink_proxypad_block_id =
 +        gst_pad_add_probe (self->sink_proxypad,
 +        GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, pad_blocked_cb,
 +        gst_object_ref (self), (GDestroyNotify) gst_object_unref);
 +  }
 +}
 +
 +static void
 +unblock_proxypad (GstPlaySinkConvertBin * self)
 +{
 +  if (self->sink_proxypad_block_id != 0) {
 +    gst_pad_remove_probe (self->sink_proxypad, self->sink_proxypad_block_id);
 +    self->sink_proxypad_block_id = 0;
 +  }
 +}
 +
  static gboolean
 -gst_play_sink_convert_bin_sink_setcaps (GstPad * pad, GstCaps * caps)
 +gst_play_sink_convert_bin_sink_setcaps (GstPlaySinkConvertBin * self,
 +    GstCaps * caps)
  {
 -  GstPlaySinkConvertBin *self =
 -      GST_PLAY_SINK_CONVERT_BIN (gst_pad_get_parent (pad));
 -  gboolean ret;
    GstStructure *s;
    const gchar *name;
    gboolean reconfigure = FALSE;
    gboolean raw;
  
 -  GST_DEBUG_OBJECT (pad, "setcaps: %" GST_PTR_FORMAT, caps);
 +  GST_DEBUG_OBJECT (self, "setcaps");
    GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
    s = gst_caps_get_structure (caps, 0);
    name = gst_structure_get_name (s);
      if (!gst_pad_is_blocked (self->sink_proxypad)) {
        GstPad *target = gst_ghost_pad_get_target (GST_GHOST_PAD (self->sinkpad));
  
 -      if (!self->raw || (target && !gst_pad_accept_caps (target, caps))) {
 +      if (!self->raw || (target && !gst_pad_query_accept_caps (target, caps))) {
          if (!self->raw)
            GST_DEBUG_OBJECT (self, "Changing caps from non-raw to raw");
          else
            GST_DEBUG_OBJECT (self, "Changing caps in an incompatible way");
  
          reconfigure = TRUE;
 -        gst_pad_set_blocked_async_full (self->sink_proxypad, TRUE,
 -            (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self),
 -            (GDestroyNotify) gst_object_unref);
 +        block_proxypad (self);
        }
  
        if (target)
      if (self->raw && !gst_pad_is_blocked (self->sink_proxypad)) {
        GST_DEBUG_OBJECT (self, "Changing caps from raw to non-raw");
        reconfigure = TRUE;
 -      gst_pad_set_blocked_async_full (self->sink_proxypad, TRUE,
 -          (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self),
 -          (GDestroyNotify) gst_object_unref);
 +      block_proxypad (self);
      }
    }
  
    }
  
    GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self);
 -  ret = gst_ghost_pad_setcaps_default (pad, caps);
  
 -  GST_DEBUG_OBJECT (self, "Setting sink caps %" GST_PTR_FORMAT ": %d", caps,
 -      ret);
 +  GST_DEBUG_OBJECT (self, "Setting sink caps %" GST_PTR_FORMAT, caps);
  
 -  gst_object_unref (self);
 -
 -  return ret;
 +  return TRUE;
  }
  
  static GstCaps *
 -gst_play_sink_convert_bin_getcaps (GstPad * pad)
 +gst_play_sink_convert_bin_getcaps (GstPad * pad, GstCaps * filter)
  {
    GstPlaySinkConvertBin *self =
        GST_PLAY_SINK_CONVERT_BIN (gst_pad_get_parent (pad));
    if (otherpad) {
      peer = gst_pad_get_peer (otherpad);
      if (peer) {
 -      GstCaps *peer_caps = gst_pad_get_caps_reffed (peer);
 +      GstCaps *peer_caps = gst_pad_query_caps (peer, filter);
        gst_object_unref (peer);
        if (self->converter_caps && is_raw_caps (peer_caps, self->audio)) {
          peer_caps = gst_caps_make_writable (peer_caps);
@@@ -428,7 -422,7 +429,7 @@@ gst_play_sink_convert_bin_acceptcaps (G
    GstCaps *allowed_caps;
    gboolean ret;
  
 -  allowed_caps = gst_pad_get_caps_reffed (pad);
 +  allowed_caps = gst_pad_query_caps (pad, NULL);
    /* FIXME 0.11: Should be a subset check now */
    ret = gst_caps_can_intersect (caps, allowed_caps);
    gst_caps_unref (allowed_caps);
    return ret;
  }
  
 +static gboolean
 +gst_play_sink_convert_bin_query (GstPad * pad, GstObject * parent,
 +    GstQuery * query)
 +{
 +  gboolean res = FALSE;
 +
 +  switch (GST_QUERY_TYPE (query)) {
 +    case GST_QUERY_ACCEPT_CAPS:
 +    {
 +      GstCaps *caps;
 +
 +      gst_query_parse_accept_caps (query, &caps);
 +      gst_query_set_accept_caps_result (query,
 +          gst_play_sink_convert_bin_acceptcaps (pad, caps));
 +      res = TRUE;
 +      break;
 +    }
 +    case GST_QUERY_CAPS:
 +    {
 +      GstCaps *filter, *caps;
 +
 +      gst_query_parse_caps (query, &filter);
 +      caps = gst_play_sink_convert_bin_getcaps (pad, filter);
 +      gst_query_set_caps_result (query, caps);
 +      gst_caps_unref (caps);
 +      res = TRUE;
 +      break;
 +    }
 +    default:
 +      res = gst_pad_query_default (pad, parent, query);
 +      break;
 +  }
 +  return res;
 +}
 +
  void
  gst_play_sink_convert_bin_remove_elements (GstPlaySinkConvertBin * self)
  {
@@@ -530,7 -489,7 +531,7 @@@ gst_play_sink_convert_bin_cache_convert
      return;
    }
  
 -  self->converter_caps = gst_pad_get_caps_reffed (pad);
 +  self->converter_caps = gst_pad_query_caps (pad, NULL);
    GST_INFO_OBJECT (self, "Converter caps: %" GST_PTR_FORMAT,
        self->converter_caps);
  
@@@ -547,7 -506,10 +548,7 @@@ gst_play_sink_convert_bin_change_state 
    switch (transition) {
      case GST_STATE_CHANGE_PAUSED_TO_READY:
        GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
 -      if (gst_pad_is_blocked (self->sink_proxypad))
 -        gst_pad_set_blocked_async_full (self->sink_proxypad, FALSE,
 -            (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self),
 -            (GDestroyNotify) gst_object_unref);
 +      unblock_proxypad (self);
        GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self);
        break;
      case GST_STATE_CHANGE_READY_TO_PAUSED:
        break;
      case GST_STATE_CHANGE_READY_TO_PAUSED:
        GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
 -      if (!gst_pad_is_blocked (self->sink_proxypad))
 -        gst_pad_set_blocked_async_full (self->sink_proxypad, TRUE,
 -            (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self),
 -            (GDestroyNotify) gst_object_unref);
 +      unblock_proxypad (self);
        GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self);
        break;
      default:
@@@ -625,8 -590,12 +626,8 @@@ gst_play_sink_convert_bin_init (GstPlay
    self->sinkpad = gst_ghost_pad_new_no_target_from_template ("sink", templ);
    gst_pad_set_event_function (self->sinkpad,
        GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_sink_event));
 -  gst_pad_set_setcaps_function (self->sinkpad,
 -      GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_sink_setcaps));
 -  gst_pad_set_getcaps_function (self->sinkpad,
 -      GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_getcaps));
 -  gst_pad_set_acceptcaps_function (self->sinkpad,
 -      GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_acceptcaps));
 +  gst_pad_set_query_function (self->sinkpad,
 +      GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_query));
  
    self->sink_proxypad =
        GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD (self->sinkpad)));
  
    templ = gst_static_pad_template_get (&srctemplate);
    self->srcpad = gst_ghost_pad_new_no_target_from_template ("src", templ);
 -  gst_pad_set_getcaps_function (self->srcpad,
 -      GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_getcaps));
 -  gst_pad_set_acceptcaps_function (self->srcpad,
 -      GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_acceptcaps));
 +  gst_pad_set_query_function (self->srcpad,
 +      GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_query));
    gst_element_add_pad (GST_ELEMENT_CAST (self), self->srcpad);
    gst_object_unref (templ);
  
  #include "config.h"
  #endif
  
+ /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+  * with newer GLib versions (>= 2.31.0) */
+ #define GLIB_DISABLE_DEPRECATION_WARNINGS
  #include "gststreamsynchronizer.h"
+ #include "gst/glib-compat-private.h"
  
  GST_DEBUG_CATEGORY_STATIC (stream_synchronizer_debug);
  #define GST_CAT_DEFAULT stream_synchronizer_debug
      g_mutex_unlock (GST_STREAM_SYNCHRONIZER_CAST(obj)->lock);              \
  } G_STMT_END
  
 -static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src_%d",
 +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src_%u",
      GST_PAD_SRC,
      GST_PAD_SOMETIMES,
      GST_STATIC_CAPS_ANY);
 -static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink_%d",
 +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink_%u",
      GST_PAD_SINK,
      GST_PAD_REQUEST,
      GST_STATIC_CAPS_ANY);
  
  static const gboolean passthrough = TRUE;
  
 -GST_BOILERPLATE (GstStreamSynchronizer, gst_stream_synchronizer,
 -    GstElement, GST_TYPE_ELEMENT);
 +#define gst_stream_synchronizer_parent_class parent_class
 +G_DEFINE_TYPE (GstStreamSynchronizer, gst_stream_synchronizer,
 +    GST_TYPE_ELEMENT);
  
  typedef struct
  {
@@@ -114,20 -118,15 +119,20 @@@ out
  
  /* Generic pad functions */
  static GstIterator *
 -gst_stream_synchronizer_iterate_internal_links (GstPad * pad)
 +gst_stream_synchronizer_iterate_internal_links (GstPad * pad,
 +    GstObject * parent)
  {
    GstIterator *it = NULL;
    GstPad *opad;
  
    opad = gst_stream_get_other_pad_from_pad (pad);
    if (opad) {
 -    it = gst_iterator_new_single (GST_TYPE_PAD, opad,
 -        (GstCopyFunction) gst_object_ref, (GFreeFunc) gst_object_unref);
 +    GValue value = { 0, };
 +
 +    g_value_init (&value, GST_TYPE_PAD);
 +    g_value_set_object (&value, opad);
 +    it = gst_iterator_new_single (GST_TYPE_PAD, &value);
 +    g_value_unset (&value);
      gst_object_unref (opad);
    }
  
  }
  
  static gboolean
 -gst_stream_synchronizer_query (GstPad * pad, GstQuery * query)
 +gst_stream_synchronizer_query (GstPad * pad, GstObject * parent,
 +    GstQuery * query)
  {
    GstPad *opad;
    gboolean ret = FALSE;
    return ret;
  }
  
 -static GstCaps *
 -gst_stream_synchronizer_getcaps (GstPad * pad)
 -{
 -  GstPad *opad;
 -  GstCaps *ret = NULL;
 -
 -  opad = gst_stream_get_other_pad_from_pad (pad);
 -  if (opad) {
 -    ret = gst_pad_peer_get_caps (opad);
 -    gst_object_unref (opad);
 -  }
 -
 -  if (ret == NULL)
 -    ret = gst_caps_new_any ();
 -
 -  GST_LOG_OBJECT (pad, "Returning caps: %" GST_PTR_FORMAT, ret);
 -
 -  return ret;
 -}
 -
 -static gboolean
 -gst_stream_synchronizer_acceptcaps (GstPad * pad, GstCaps * caps)
 -{
 -  GstPad *opad;
 -  gboolean ret = FALSE;
 -
 -  opad = gst_stream_get_other_pad_from_pad (pad);
 -  if (opad) {
 -    ret = gst_pad_peer_accept_caps (opad, caps);
 -    gst_object_unref (opad);
 -  }
 -
 -  GST_LOG_OBJECT (pad, "Caps%s accepted: %" GST_PTR_FORMAT, (ret ? "" : " not"),
 -      caps);
 -
 -  return ret;
 -}
 -
  /* srcpad functions */
  static gboolean
 -gst_stream_synchronizer_src_event (GstPad * pad, GstEvent * event)
 +gst_stream_synchronizer_src_event (GstPad * pad, GstObject * parent,
 +    GstEvent * event)
  {
 -  GstStreamSynchronizer *self =
 -      GST_STREAM_SYNCHRONIZER (gst_pad_get_parent (pad));
 +  GstStreamSynchronizer *self = GST_STREAM_SYNCHRONIZER (parent);
    GstPad *opad;
    gboolean ret = FALSE;
  
      goto skip_adjustments;
  
    GST_LOG_OBJECT (pad, "Handling event %s: %" GST_PTR_FORMAT,
 -      GST_EVENT_TYPE_NAME (event), event->structure);
 +      GST_EVENT_TYPE_NAME (event), event);
  
    switch (GST_EVENT_TYPE (event)) {
      case GST_EVENT_QOS:{
        gint64 running_time_diff;
        GstStream *stream;
  
 -      gst_event_parse_qos (event, &proportion, &diff, &timestamp);
 +      gst_event_parse_qos (event, NULL, &proportion, &diff, &timestamp);
        gst_event_unref (event);
  
        GST_STREAM_SYNCHRONIZER_LOCK (self);
          goto out;
        }
  
 -      event = gst_event_new_qos (proportion, diff, timestamp);
 +      event =
 +          gst_event_new_qos (GST_QOS_TYPE_UNDERFLOW, proportion, diff,
 +          timestamp);
        break;
      }
      default:
@@@ -227,15 -261,17 +232,15 @@@ skip_adjustments
    }
  
  out:
 -  gst_object_unref (self);
 -
    return ret;
  }
  
  /* sinkpad functions */
  static gboolean
 -gst_stream_synchronizer_sink_event (GstPad * pad, GstEvent * event)
 +gst_stream_synchronizer_sink_event (GstPad * pad, GstObject * parent,
 +    GstEvent * event)
  {
 -  GstStreamSynchronizer *self =
 -      GST_STREAM_SYNCHRONIZER (gst_pad_get_parent (pad));
 +  GstStreamSynchronizer *self = GST_STREAM_SYNCHRONIZER (parent);
    GstPad *opad;
    gboolean ret = FALSE;
  
      goto skip_adjustments;
  
    GST_LOG_OBJECT (pad, "Handling event %s: %" GST_PTR_FORMAT,
 -      GST_EVENT_TYPE_NAME (event), event->structure);
 +      GST_EVENT_TYPE_NAME (event), event);
  
    switch (GST_EVENT_TYPE (event)) {
      case GST_EVENT_SINK_MESSAGE:{
        GstMessage *message;
  
        gst_event_parse_sink_message (event, &message);
 -      if (message->structure
 -          && gst_structure_has_name (message->structure,
 -              "playbin2-stream-changed")) {
 +      if (gst_message_has_name (message, "playbin-stream-changed")) {
          GstStream *stream;
  
          GST_STREAM_SYNCHRONIZER_LOCK (self);
                break;
            }
            if (all_wait) {
 -            gint64 last_stop = 0;
 +            gint64 position = 0;
  
              GST_DEBUG_OBJECT (self, "All streams have changed -- unblocking");
  
              for (l = self->streams; l; l = l->next) {
                GstStream *ostream = l->data;
                gint64 stop_running_time;
 -              gint64 last_stop_running_time;
 +              gint64 position_running_time;
  
                ostream->wait = FALSE;
  
                stop_running_time =
                    gst_segment_to_running_time (&ostream->segment,
                    GST_FORMAT_TIME, ostream->segment.stop);
 -              last_stop_running_time =
 +              position_running_time =
                    gst_segment_to_running_time (&ostream->segment,
 -                  GST_FORMAT_TIME, ostream->segment.last_stop);
 -              last_stop =
 -                  MAX (last_stop, MAX (stop_running_time,
 -                      last_stop_running_time));
 +                  GST_FORMAT_TIME, ostream->segment.position);
 +              position =
 +                  MAX (position, MAX (stop_running_time,
 +                      position_running_time));
              }
 -            last_stop = MAX (0, last_stop);
 -            self->group_start_time = MAX (self->group_start_time, last_stop);
 +            position = MAX (0, position);
 +            self->group_start_time = MAX (self->group_start_time, position);
  
              GST_DEBUG_OBJECT (self, "New group start time: %" GST_TIME_FORMAT,
                  GST_TIME_ARGS (self->group_start_time));
        gst_message_unref (message);
        break;
      }
 -    case GST_EVENT_NEWSEGMENT:{
 +    case GST_EVENT_SEGMENT:{
        GstStream *stream;
 -      gboolean update;
 -      gdouble rate, applied_rate;
 -      GstFormat format;
 -      gint64 start, stop, position;
 +      GstSegment segment;
  
 -      gst_event_parse_new_segment_full (event,
 -          &update, &rate, &applied_rate, &format, &start, &stop, &position);
 +      gst_event_copy_segment (event, &segment);
  
        GST_STREAM_SYNCHRONIZER_LOCK (self);
        stream = gst_pad_get_element_private (pad);
          goto done;
        }
  
 -      if (stream && format == GST_FORMAT_TIME) {
 +      if (stream && segment.format == GST_FORMAT_TIME) {
          if (stream->new_stream) {
 -          gint64 last_stop_running_time = 0;
 +          gint64 position_running_time = 0;
            gint64 stop_running_time = 0;
  
            if (stream->segment.format == GST_FORMAT_TIME) {
 -            last_stop_running_time =
 +            position_running_time =
                  gst_segment_to_running_time (&stream->segment, GST_FORMAT_TIME,
 -                stream->segment.last_stop);
 -            last_stop_running_time = MAX (last_stop_running_time, 0);
 +                stream->segment.position);
 +            position_running_time = MAX (position_running_time, 0);
              stop_running_time =
                  gst_segment_to_running_time (&stream->segment, GST_FORMAT_TIME,
                  stream->segment.stop);
 -            stop_running_time = MAX (last_stop_running_time, 0);
 +            stop_running_time = MAX (position_running_time, 0);
  
 -            if (stop_running_time != last_stop_running_time) {
 +            if (stop_running_time != position_running_time) {
                GST_WARNING_OBJECT (pad,
 -                  "Gap between last_stop and segment stop: %" GST_TIME_FORMAT
 +                  "Gap between position and segment stop: %" GST_TIME_FORMAT
                    " != %" GST_TIME_FORMAT, GST_TIME_ARGS (stop_running_time),
 -                  GST_TIME_ARGS (last_stop_running_time));
 +                  GST_TIME_ARGS (position_running_time));
              }
  
 -            if (stop_running_time < last_stop_running_time) {
 +            if (stop_running_time < position_running_time) {
                GST_DEBUG_OBJECT (pad, "Updating stop position");
 +              stream->segment.stop = stream->segment.position;
                gst_pad_push_event (stream->srcpad,
 -                  gst_event_new_new_segment_full (TRUE, stream->segment.rate,
 -                      stream->segment.applied_rate, GST_FORMAT_TIME,
 -                      stream->segment.start, stream->segment.last_stop,
 -                      stream->segment.time));
 -              gst_segment_set_newsegment_full (&stream->segment, TRUE,
 -                  stream->segment.rate, stream->segment.applied_rate,
 -                  GST_FORMAT_TIME, stream->segment.start,
 -                  stream->segment.last_stop, stream->segment.time);
 +                  gst_event_new_segment (&stream->segment));
              }
 -            stop_running_time = MAX (stop_running_time, last_stop_running_time);
 +            stop_running_time = MAX (stop_running_time, position_running_time);
              GST_DEBUG_OBJECT (pad,
                  "Stop running time of last group: %" GST_TIME_FORMAT,
                  GST_TIME_ARGS (stop_running_time));
              GST_DEBUG_OBJECT (pad,
                  "Advancing running time for other streams by: %"
                  GST_TIME_FORMAT, GST_TIME_ARGS (diff));
 -            gst_pad_push_event (stream->srcpad,
 -                gst_event_new_new_segment_full (FALSE, 1.0, 1.0,
 -                    GST_FORMAT_TIME, 0, diff, 0));
 -            gst_segment_set_newsegment_full (&stream->segment, FALSE, 1.0, 1.0,
 -                GST_FORMAT_TIME, 0, diff, 0);
 +
 +            segment.base += diff;
            }
          }
  
          GST_DEBUG_OBJECT (pad, "Segment was: %" GST_SEGMENT_FORMAT,
              &stream->segment);
 -        gst_segment_set_newsegment_full (&stream->segment, update, rate,
 -            applied_rate, format, start, stop, position);
 +        gst_segment_copy_into (&segment, &stream->segment);
          GST_DEBUG_OBJECT (pad, "Segment now is: %" GST_SEGMENT_FORMAT,
              &stream->segment);
  
          GST_DEBUG_OBJECT (pad, "Stream start running time: %" GST_TIME_FORMAT,
 -            GST_TIME_ARGS (stream->segment.accum));
 -        stream->running_time_diff = stream->segment.accum;
 +            GST_TIME_ARGS (stream->segment.base));
 +        stream->running_time_diff = stream->segment.base;
        } else if (stream) {
          GST_WARNING_OBJECT (pad, "Non-TIME segment: %s",
 -            gst_format_get_name (format));
 +            gst_format_get_name (segment.format));
          gst_segment_init (&stream->segment, GST_FORMAT_UNDEFINED);
        }
        GST_STREAM_SYNCHRONIZER_UNLOCK (self);
          if (!seen_data) {
            GstBuffer *buf = gst_buffer_new ();
  
 -          GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_PREROLL);
            gst_pad_push (srcpad, buf);
          }
        }
@@@ -496,14 -549,36 +501,14 @@@ skip_adjustments
    }
  
  done:
 -  gst_object_unref (self);
 -
 -  return ret;
 -}
 -
 -static GstFlowReturn
 -gst_stream_synchronizer_sink_bufferalloc (GstPad * pad, guint64 offset,
 -    guint size, GstCaps * caps, GstBuffer ** buf)
 -{
 -  GstPad *opad;
 -  GstFlowReturn ret = GST_FLOW_ERROR;
 -
 -  GST_LOG_OBJECT (pad, "Allocating buffer: size=%u", size);
 -
 -  opad = gst_stream_get_other_pad_from_pad (pad);
 -  if (opad) {
 -    ret = gst_pad_alloc_buffer (opad, offset, size, caps, buf);
 -    gst_object_unref (opad);
 -  }
 -
 -  GST_LOG_OBJECT (pad, "Allocation: %s", gst_flow_get_name (ret));
 -
    return ret;
  }
  
  static GstFlowReturn
 -gst_stream_synchronizer_sink_chain (GstPad * pad, GstBuffer * buffer)
 +gst_stream_synchronizer_sink_chain (GstPad * pad, GstObject * parent,
 +    GstBuffer * buffer)
  {
 -  GstStreamSynchronizer *self =
 -      GST_STREAM_SYNCHRONIZER (gst_pad_get_parent (pad));
 +  GstStreamSynchronizer *self = GST_STREAM_SYNCHRONIZER (parent);
    GstPad *opad;
    GstFlowReturn ret = GST_FLOW_ERROR;
    GstStream *stream;
      goto done;
    }
  
 -  GST_LOG_OBJECT (pad, "Handling buffer %p: size=%u, timestamp=%"
 -      GST_TIME_FORMAT " duration=%" GST_TIME_FORMAT
 +  GST_LOG_OBJECT (pad, "Handling buffer %p: size=%" G_GSIZE_FORMAT
 +      ", timestamp=%" GST_TIME_FORMAT " duration=%" GST_TIME_FORMAT
        " offset=%" G_GUINT64_FORMAT " offset_end=%" G_GUINT64_FORMAT,
 -      buffer, GST_BUFFER_SIZE (buffer),
 +      buffer, gst_buffer_get_size (buffer),
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
        GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)),
        GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET_END (buffer));
  
    stream->seen_data = TRUE;
    if (stream && stream->drop_discont) {
 -    buffer = gst_buffer_make_metadata_writable (buffer);
 +    buffer = gst_buffer_make_writable (buffer);
      GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DISCONT);
      stream->drop_discont = FALSE;
    }
        && GST_CLOCK_TIME_IS_VALID (timestamp)) {
      GST_LOG_OBJECT (pad,
          "Updating last-stop from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
 -        GST_TIME_ARGS (stream->segment.last_stop), GST_TIME_ARGS (timestamp));
 -    gst_segment_set_last_stop (&stream->segment, GST_FORMAT_TIME, timestamp);
 +        GST_TIME_ARGS (stream->segment.position), GST_TIME_ARGS (timestamp));
 +    stream->segment.position = timestamp;
    }
    GST_STREAM_SYNCHRONIZER_UNLOCK (self);
  
          && GST_CLOCK_TIME_IS_VALID (timestamp_end)) {
        GST_LOG_OBJECT (pad,
            "Updating last-stop from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
 -          GST_TIME_ARGS (stream->segment.last_stop),
 +          GST_TIME_ARGS (stream->segment.position),
            GST_TIME_ARGS (timestamp_end));
 -      gst_segment_set_last_stop (&stream->segment, GST_FORMAT_TIME,
 -          timestamp_end);
 +      stream->segment.position = timestamp_end;
      }
  
      /* Advance EOS streams if necessary. For non-EOS
       * streams the demuxers should already do this! */
      for (l = self->streams; l; l = l->next) {
        GstStream *ostream = l->data;
 -      gint64 last_stop;
 +      gint64 position;
  
        if (!ostream->is_eos || ostream->segment.format != GST_FORMAT_TIME)
          continue;
  
 -      if (ostream->segment.last_stop != -1)
 -        last_stop = ostream->segment.last_stop;
 +      if (ostream->segment.position != -1)
 +        position = ostream->segment.position;
        else
 -        last_stop = ostream->segment.start;
 +        position = ostream->segment.start;
  
        /* Is there a 1 second lag? */
 -      if (last_stop != -1 && last_stop + GST_SECOND < timestamp_end) {
 +      if (position != -1 && position + GST_SECOND < timestamp_end) {
          gint64 new_start, new_stop;
  
          new_start = timestamp_end - GST_SECOND;
  
          GST_DEBUG_OBJECT (ostream->sinkpad,
              "Advancing stream %u from %" GST_TIME_FORMAT " to %"
 -            GST_TIME_FORMAT, ostream->stream_number, GST_TIME_ARGS (last_stop),
 +            GST_TIME_FORMAT, ostream->stream_number, GST_TIME_ARGS (position),
              GST_TIME_ARGS (new_start));
  
 +        ostream->segment.start = new_start;
 +        ostream->segment.stop = new_stop;
 +        ostream->segment.time = new_start;
 +        ostream->segment.position = new_start;
 +
          gst_pad_push_event (ostream->srcpad,
 -            gst_event_new_new_segment_full (TRUE, ostream->segment.rate,
 -                ostream->segment.applied_rate, ostream->segment.format,
 -                new_start, new_stop, new_start));
 -        gst_segment_set_newsegment_full (&ostream->segment, TRUE,
 -            ostream->segment.rate, ostream->segment.applied_rate,
 -            ostream->segment.format, new_start, new_stop, new_start);
 -        gst_segment_set_last_stop (&ostream->segment, GST_FORMAT_TIME,
 -            new_start);
 +            gst_event_new_segment (&ostream->segment));
        }
      }
      GST_STREAM_SYNCHRONIZER_UNLOCK (self);
    }
  
  done:
 -
 -  gst_object_unref (self);
 -
    return ret;
  }
  
  /* GstElement vfuncs */
  static GstPad *
  gst_stream_synchronizer_request_new_pad (GstElement * element,
 -    GstPadTemplate * temp, const gchar * name)
 +    GstPadTemplate * temp, const gchar * name, const GstCaps * caps)
  {
    GstStreamSynchronizer *self = GST_STREAM_SYNCHRONIZER (element);
    GstStream *stream;
    stream->transform = self;
    stream->stream_number = self->current_stream_number;
  
 -  tmp = g_strdup_printf ("sink_%d", self->current_stream_number);
 +  tmp = g_strdup_printf ("sink_%u", self->current_stream_number);
    stream->sinkpad = gst_pad_new_from_static_template (&sinktemplate, tmp);
    g_free (tmp);
    gst_pad_set_element_private (stream->sinkpad, stream);
        GST_DEBUG_FUNCPTR (gst_stream_synchronizer_iterate_internal_links));
    gst_pad_set_query_function (stream->sinkpad,
        GST_DEBUG_FUNCPTR (gst_stream_synchronizer_query));
 -  gst_pad_set_getcaps_function (stream->sinkpad,
 -      GST_DEBUG_FUNCPTR (gst_stream_synchronizer_getcaps));
 -  gst_pad_set_acceptcaps_function (stream->sinkpad,
 -      GST_DEBUG_FUNCPTR (gst_stream_synchronizer_acceptcaps));
    gst_pad_set_event_function (stream->sinkpad,
        GST_DEBUG_FUNCPTR (gst_stream_synchronizer_sink_event));
    gst_pad_set_chain_function (stream->sinkpad,
        GST_DEBUG_FUNCPTR (gst_stream_synchronizer_sink_chain));
 -  gst_pad_set_bufferalloc_function (stream->sinkpad,
 -      GST_DEBUG_FUNCPTR (gst_stream_synchronizer_sink_bufferalloc));
  
 -  tmp = g_strdup_printf ("src_%d", self->current_stream_number);
 +  tmp = g_strdup_printf ("src_%u", self->current_stream_number);
    stream->srcpad = gst_pad_new_from_static_template (&srctemplate, tmp);
    g_free (tmp);
    gst_pad_set_element_private (stream->srcpad, stream);
        GST_DEBUG_FUNCPTR (gst_stream_synchronizer_iterate_internal_links));
    gst_pad_set_query_function (stream->srcpad,
        GST_DEBUG_FUNCPTR (gst_stream_synchronizer_query));
 -  gst_pad_set_getcaps_function (stream->srcpad,
 -      GST_DEBUG_FUNCPTR (gst_stream_synchronizer_getcaps));
 -  gst_pad_set_acceptcaps_function (stream->srcpad,
 -      GST_DEBUG_FUNCPTR (gst_stream_synchronizer_acceptcaps));
    gst_pad_set_event_function (stream->srcpad,
        GST_DEBUG_FUNCPTR (gst_stream_synchronizer_src_event));
  
@@@ -708,15 -799,15 +713,15 @@@ gst_stream_synchronizer_release_stream 
  
    if (stream->segment.format == GST_FORMAT_TIME) {
      gint64 stop_running_time;
 -    gint64 last_stop_running_time;
 +    gint64 position_running_time;
  
      stop_running_time =
          gst_segment_to_running_time (&stream->segment, GST_FORMAT_TIME,
          stream->segment.stop);
 -    last_stop_running_time =
 +    position_running_time =
          gst_segment_to_running_time (&stream->segment, GST_FORMAT_TIME,
 -        stream->segment.last_stop);
 -    stop_running_time = MAX (stop_running_time, last_stop_running_time);
 +        stream->segment.position);
 +    stop_running_time = MAX (stop_running_time, position_running_time);
  
      GST_DEBUG_OBJECT (stream->sinkpad,
          "Stop running time was: %" GST_TIME_FORMAT,
@@@ -857,13 -948,28 +862,13 @@@ gst_stream_synchronizer_finalize (GObje
  
  /* GObject type initialization */
  static void
 -gst_stream_synchronizer_init (GstStreamSynchronizer * self,
 -    GstStreamSynchronizerClass * klass)
 +gst_stream_synchronizer_init (GstStreamSynchronizer * self)
  {
    self->lock = g_mutex_new ();
    self->stream_finish_cond = g_cond_new ();
  }
  
  static void
 -gst_stream_synchronizer_base_init (gpointer g_class)
 -{
 -  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
 -
 -  gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
 -  gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate);
 -
 -  gst_element_class_set_details_simple (gstelement_class,
 -      "Stream Synchronizer", "Generic",
 -      "Synchronizes a group of streams to have equal durations and starting points",
 -      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
 -}
 -
 -static void
  gst_stream_synchronizer_class_init (GstStreamSynchronizerClass * klass)
  {
    GObjectClass *gobject_class = (GObjectClass *) klass;
  
    gobject_class->finalize = gst_stream_synchronizer_finalize;
  
 +  gst_element_class_add_pad_template (element_class,
 +      gst_static_pad_template_get (&srctemplate));
 +  gst_element_class_add_pad_template (element_class,
 +      gst_static_pad_template_get (&sinktemplate));
 +
 +  gst_element_class_set_details_simple (element_class,
 +      "Stream Synchronizer", "Generic",
 +      "Synchronizes a group of streams to have equal durations and starting points",
 +      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
 +
    element_class->change_state =
        GST_DEBUG_FUNCPTR (gst_stream_synchronizer_change_state);
    element_class->request_new_pad =
@@@ -29,7 -29,7 +29,7 @@@
   * <refsect2>
   * <title>Examples</title>
   * |[
 - * gst-launch -v filesrc location=test.mkv ! matroskademux name=demux ! "video/x-h264" ! queue2 ! decodebin2 ! subtitleoverlay name=overlay ! ffmpegcolorspace ! autovideosink  demux. ! "video/x-dvd-subpicture" ! queue2 ! overlay.
 + * gst-launch -v filesrc location=test.mkv ! matroskademux name=demux ! "video/x-h264" ! queue2 ! decodebin ! subtitleoverlay name=overlay ! videoconvert ! autovideosink  demux. ! "video/x-dvd-subpicture" ! queue2 ! overlay.
   * ]| This will play back the given Matroska file with h264 video and subpicture subtitles.
   * </refsect2>
   */
  
  #include "gstsubtitleoverlay.h"
  
 -#include <gst/gstfilter.h>
  #include <gst/pbutils/missing-plugins.h>
  #include <gst/video/video.h>
  #include <string.h>
  
+ #include "gst/glib-compat-private.h"
  GST_DEBUG_CATEGORY_STATIC (subtitle_overlay_debug);
  #define GST_CAT_DEFAULT subtitle_overlay_debug
  
@@@ -78,8 -81,11 +80,8 @@@ enu
    PROP_SUBTITLE_ENCODING
  };
  
 -GST_BOILERPLATE (GstSubtitleOverlay, gst_subtitle_overlay, GstBin,
 -    GST_TYPE_BIN);
 -
 -static void _pad_blocked_cb (GstPad * pad, gboolean blocked,
 -    gpointer user_data);
 +#define gst_subtitle_overlay_parent_class parent_class
 +G_DEFINE_TYPE (GstSubtitleOverlay, gst_subtitle_overlay, GST_TYPE_BIN);
  
  static GQuark _subtitle_overlay_event_marker_id = 0;
  
@@@ -87,10 -93,11 +89,10 @@@ static voi
  do_async_start (GstSubtitleOverlay * self)
  {
    if (!self->do_async) {
 -    GstMessage *msg =
 -        gst_message_new_async_start (GST_OBJECT_CAST (self), FALSE);
 +    GstMessage *msg = gst_message_new_async_start (GST_OBJECT_CAST (self));
  
      GST_DEBUG_OBJECT (self, "Posting async-start");
 -    parent_class->handle_message (GST_BIN_CAST (self), msg);
 +    GST_BIN_CLASS (parent_class)->handle_message (GST_BIN_CAST (self), msg);
      self->do_async = TRUE;
    }
  }
@@@ -99,64 -106,14 +101,64 @@@ static voi
  do_async_done (GstSubtitleOverlay * self)
  {
    if (self->do_async) {
 -    GstMessage *msg = gst_message_new_async_done (GST_OBJECT_CAST (self));
 +    GstMessage *msg =
 +        gst_message_new_async_done (GST_OBJECT_CAST (self), FALSE);
  
      GST_DEBUG_OBJECT (self, "Posting async-done");
 -    parent_class->handle_message (GST_BIN_CAST (self), msg);
 +    GST_BIN_CLASS (parent_class)->handle_message (GST_BIN_CAST (self), msg);
      self->do_async = FALSE;
    }
  }
  
 +static GstPadProbeReturn
 +_pad_blocked_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data);
 +
 +static void
 +block_video (GstSubtitleOverlay * self)
 +{
 +  if (self->video_block_id != 0)
 +    return;
 +
 +  if (self->video_block_pad) {
 +    self->video_block_id =
 +        gst_pad_add_probe (self->video_block_pad,
 +        GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, _pad_blocked_cb, self, NULL);
 +  }
 +}
 +
 +static void
 +unblock_video (GstSubtitleOverlay * self)
 +{
 +  if (self->video_block_id) {
 +    gst_pad_remove_probe (self->video_block_pad, self->video_block_id);
 +    self->video_sink_blocked = FALSE;
 +    self->video_block_id = 0;
 +  }
 +}
 +
 +static void
 +block_subtitle (GstSubtitleOverlay * self)
 +{
 +  if (self->subtitle_block_id != 0)
 +    return;
 +
 +  if (self->subtitle_block_pad) {
 +    self->subtitle_block_id =
 +        gst_pad_add_probe (self->subtitle_block_pad,
 +        GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, _pad_blocked_cb, self, NULL);
 +  }
 +}
 +
 +static void
 +unblock_subtitle (GstSubtitleOverlay * self)
 +{
 +  if (self->subtitle_block_id) {
 +    gst_pad_remove_probe (self->subtitle_block_pad, self->subtitle_block_id);
 +    self->subtitle_sink_blocked = FALSE;
 +    self->subtitle_block_id = 0;
 +  }
 +}
 +
  static void
  gst_subtitle_overlay_finalize (GObject * object)
  {
@@@ -230,22 -187,50 +232,38 @@@ _is_raw_video (GstStructure * s
  
    name = gst_structure_get_name (s);
  
 -  if (g_str_has_prefix (name, "video/x-raw-"))
 +  if (g_str_has_prefix (name, "video/x-raw"))
      return TRUE;
    return FALSE;
  }
  
  static gboolean
- _is_raw_video_pad (GstPad * pad)
+ _is_video_pad (GstPad * pad, gboolean * hw_accelerated)
  {
 -  GstPad *peer = gst_pad_get_peer (pad);
 -  GstCaps *caps;
 +  GstCaps *caps = gst_pad_get_current_caps (pad);
-   gboolean raw;
+   gboolean ret;
+   const gchar *name;
 -  if (peer) {
 -    caps = gst_pad_get_negotiated_caps (peer);
 -    if (!caps) {
 -      caps = gst_pad_get_caps_reffed (peer);
 -    }
 -    gst_object_unref (peer);
 -  } else {
 -    caps = gst_pad_get_caps_reffed (pad);
 -  }
 -
 -
+   name = gst_structure_get_name (gst_caps_get_structure (caps, 0));
+   if (g_str_has_prefix (name, "video/x-raw-")) {
+     ret = TRUE;
+     if (hw_accelerated)
+       *hw_accelerated = FALSE;
  
-   raw = _is_raw_video (gst_caps_get_structure (caps, 0));
+   } else if (g_str_has_prefix (name, "video/x-surface")) {
+     ret = TRUE;
+     if (hw_accelerated)
+       *hw_accelerated = TRUE;
+   } else {
+     ret = FALSE;
+     if (hw_accelerated)
+       *hw_accelerated = FALSE;
+   }
  
    gst_caps_unref (caps);
  
-   return raw;
+   return ret;
  }
  
  static GstCaps *
@@@ -575,16 -560,26 +593,16 @@@ _remove_element (GstSubtitleOverlay * s
  }
  
  static void
 -_generate_update_newsegment_event (GstSegment * segment, GstEvent ** event1,
 -    GstEvent ** event2)
 +_generate_update_segment_event (GstSegment * segment, GstEvent ** event1)
  {
    GstEvent *event;
 +  GstStructure *structure;
  
 -  *event1 = NULL;
 -  *event2 = NULL;
 -
 -  event = gst_event_new_new_segment_full (FALSE, segment->rate,
 -      segment->applied_rate, segment->format, 0, segment->accum, 0);
 -  gst_structure_id_set (event->structure, _subtitle_overlay_event_marker_id,
 +  event = gst_event_new_segment (segment);
 +  structure = gst_event_writable_structure (event);
 +  gst_structure_id_set (structure, _subtitle_overlay_event_marker_id,
        G_TYPE_BOOLEAN, TRUE, NULL);
    *event1 = event;
 -
 -  event = gst_event_new_new_segment_full (FALSE, segment->rate,
 -      segment->applied_rate, segment->format,
 -      segment->start, segment->stop, segment->time);
 -  gst_structure_id_set (event->structure, _subtitle_overlay_event_marker_id,
 -      G_TYPE_BOOLEAN, TRUE, NULL);
 -  *event2 = event;
  }
  
  static gboolean
@@@ -648,12 -643,17 +666,12 @@@ _setup_passthrough (GstSubtitleOverlay 
    /* Send segment to the identity. This is dropped because identity
     * is not linked downstream yet */
    if (self->video_segment.format != GST_FORMAT_UNDEFINED) {
 -    GstEvent *event1, *event2;
 +    GstEvent *event1;
  
 -    _generate_update_newsegment_event (&self->video_segment, &event1, &event2);
 -    GST_DEBUG_OBJECT (self,
 -        "Pushing video accumulate newsegment event: %" GST_PTR_FORMAT,
 -        event1->structure);
 +    _generate_update_segment_event (&self->video_segment, &event1);
      GST_DEBUG_OBJECT (self,
 -        "Pushing video update newsegment event: %" GST_PTR_FORMAT,
 -        event2->structure);
 +        "Pushing video segment event: %" GST_PTR_FORMAT, event1);
      gst_pad_send_event (sink, event1);
 -    gst_pad_send_event (sink, event2);
    }
  
    /* Link sink ghostpads to identity */
  
  out:
    /* Unblock pads */
 -  gst_pad_set_blocked_async_full (self->video_block_pad, FALSE,
 -      _pad_blocked_cb, self, NULL);
 -
 -  if (self->subtitle_sink_blocked)
 -    gst_pad_set_blocked_async_full (self->subtitle_block_pad, FALSE,
 -        _pad_blocked_cb, self, NULL);
 +  unblock_video (self);
 +  unblock_subtitle (self);
  
    return TRUE;
  }
@@@ -742,20 -746,25 +760,20 @@@ _has_font_desc_property (GstElement * e
    return (pspec && pspec->value_type == G_TYPE_STRING);
  }
  
 -static void
 -_pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
 +static GstPadProbeReturn
 +_pad_blocked_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
  {
    GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY_CAST (user_data);
    GstCaps *subcaps;
    GList *l, *factories = NULL;
  
 -  GST_DEBUG_OBJECT (pad, "Pad blocked: %d", blocked);
 +  GST_DEBUG_OBJECT (pad, "Pad blocked");
  
    GST_SUBTITLE_OVERLAY_LOCK (self);
    if (pad == self->video_block_pad)
 -    self->video_sink_blocked = blocked;
 +    self->video_sink_blocked = TRUE;
    else if (pad == self->subtitle_block_pad)
 -    self->subtitle_sink_blocked = blocked;
 -
 -  if (!blocked) {
 -    GST_SUBTITLE_OVERLAY_UNLOCK (self);
 -    return;
 -  }
 +    self->subtitle_sink_blocked = TRUE;
  
    /* Now either both or the video sink are blocked */
  
  
      peer = gst_pad_get_peer (self->subtitle_sinkpad);
      if (peer) {
 -      subcaps = gst_pad_get_negotiated_caps (peer);
 +      subcaps = gst_pad_get_current_caps (peer);
        if (!subcaps) {
 -        subcaps = gst_pad_get_caps_reffed (peer);
 +        subcaps = gst_pad_query_caps (peer, NULL);
          if (!gst_caps_is_fixed (subcaps)) {
            gst_caps_unref (subcaps);
            subcaps = NULL;
      GstPad *target =
          gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (self->subtitle_sinkpad));
  
 -    if (target && gst_pad_accept_caps (target, subcaps)) {
 +    if (target && gst_pad_query_accept_caps (target, subcaps)) {
        GST_DEBUG_OBJECT (pad, "Target accepts caps");
  
        gst_object_unref (target);
  
        /* Unblock pads */
 -      gst_pad_set_blocked_async_full (self->video_block_pad, FALSE,
 -          _pad_blocked_cb, self, NULL);
 -
 -      if (self->subtitle_sink_blocked)
 -        gst_pad_set_blocked_async_full (self->subtitle_block_pad, FALSE,
 -            _pad_blocked_cb, self, NULL);
 +      unblock_video (self);
 +      unblock_subtitle (self);
        goto out;
      } else if (target) {
        gst_object_unref (target);
  
    if (self->subtitle_sink_blocked && !self->video_sink_blocked) {
      GST_DEBUG_OBJECT (self, "Subtitle sink blocked but video not blocked");
 -    gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
 -        _pad_blocked_cb, self, NULL);
 +    block_video (self);
      goto out;
    }
  
  
    for (l = factories; l; l = l->next) {
      GstElementFactory *factory = l->data;
-     gboolean is_renderer = _is_renderer (factory);
+     gboolean is_video, is_hw, is_renderer = _is_renderer (factory);
      GstElement *element;
      GstPad *sink, *src;
  
  
      element = is_renderer ? self->renderer : self->parser;
  
+     is_video = _is_video_pad (self->video_sinkpad, &is_hw);
      /* If this is a parser, create textoverlay and link video and the parser to it
       * Else link the renderer to the output colorspace */
      if (!is_renderer) {
        video_peer = gst_pad_get_peer (self->video_sinkpad);
        if (video_peer) {
          GstCaps *video_caps;
 -        gint fps_n, fps_d;
  
 -        video_caps = gst_pad_get_negotiated_caps (video_peer);
 +        video_caps = gst_pad_get_current_caps (video_peer);
          if (!video_caps) {
 -          video_caps = gst_pad_get_caps_reffed (video_peer);
 +          video_caps = gst_pad_query_caps (video_peer, NULL);
            if (!gst_caps_is_fixed (video_caps)) {
              gst_caps_unref (video_caps);
              video_caps = NULL;
            }
          }
  
 -        if (video_caps
 -            && gst_video_parse_caps_framerate (video_caps, &fps_n, &fps_d)) {
 -          if (self->fps_n != fps_n || self->fps_d != fps_d) {
 -            GST_DEBUG_OBJECT (self, "New video fps: %d/%d", fps_n, fps_d);
 -            self->fps_n = fps_n;
 -            self->fps_d = fps_d;
 +        if (video_caps) {
 +          GstVideoInfo info;
 +
 +          if (gst_video_info_from_caps (&info, video_caps)) {
 +            if (self->fps_n != info.fps_n || self->fps_d != info.fps_d) {
 +              GST_DEBUG_OBJECT (self, "New video fps: %d/%d", info.fps_n,
 +                  info.fps_d);
 +              self->fps_n = info.fps_n;
 +              self->fps_d = info.fps_d;
 +            }
            }
          }
  
        gst_object_unref (sink);
        gst_object_unref (src);
  
-       if (G_UNLIKELY (!_create_element (self, &self->post_colorspace,
-                   COLORSPACE, NULL, "post-colorspace", FALSE))) {
-         continue;
-       }
+       /* If we are working with video/x-surface, we do not add
+        * colorspace conversion elements */
+       if (is_video && !is_hw) {
+         if (G_UNLIKELY (!_create_element (self, &self->post_colorspace,
+                     COLORSPACE, NULL, "post-colorspace", FALSE))) {
+           continue;
+         }
  
-       src = gst_element_get_static_pad (overlay, "src");
-       if (G_UNLIKELY (!src)) {
-         GST_WARNING_OBJECT (self, "Can't get src pad from overlay");
-         continue;
-       }
+         src = gst_element_get_static_pad (overlay, "src");
+         if (G_UNLIKELY (!src)) {
+           GST_WARNING_OBJECT (self, "Can't get src pad from overlay");
+           continue;
+         }
  
-       sink = gst_element_get_static_pad (self->post_colorspace, "sink");
-       if (G_UNLIKELY (!sink)) {
-         GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
-         gst_object_unref (src);
-         continue;
-       }
+         sink = gst_element_get_static_pad (self->post_colorspace, "sink");
+         if (G_UNLIKELY (!sink)) {
+           GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
+           gst_object_unref (src);
+           continue;
+         }
  
-       if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
-         GST_WARNING_OBJECT (self, "Can't link overlay with " COLORSPACE);
+         if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
+           GST_WARNING_OBJECT (self, "Can't link overlay with " COLORSPACE);
+           gst_object_unref (src);
+           gst_object_unref (sink);
+           continue;
+         }
          gst_object_unref (src);
          gst_object_unref (sink);
-         continue;
-       }
-       gst_object_unref (src);
-       gst_object_unref (sink);
  
-       if (G_UNLIKELY (!_create_element (self, &self->pre_colorspace,
-                   COLORSPACE, NULL, "pre-colorspace", FALSE))) {
-         continue;
-       }
+         if (G_UNLIKELY (!_create_element (self, &self->pre_colorspace,
+                     "identity", NULL, "pre-colorspace", FALSE))) {
+           continue;
+         }
  
-       sink = gst_element_get_static_pad (overlay, "video_sink");
-       if (G_UNLIKELY (!sink)) {
-         GST_WARNING_OBJECT (self, "Can't get video sink from textoverlay");
-         continue;
-       }
+         sink = gst_element_get_static_pad (overlay, "video_sink");
+         if (G_UNLIKELY (!sink)) {
+           GST_WARNING_OBJECT (self, "Can't get video sink from textoverlay");
+           continue;
+         }
  
-       src = gst_element_get_static_pad (self->pre_colorspace, "src");
-       if (G_UNLIKELY (!src)) {
-         GST_WARNING_OBJECT (self, "Can't get srcpad from " COLORSPACE);
-         gst_object_unref (sink);
-         continue;
-       }
+         src = gst_element_get_static_pad (self->pre_colorspace, "src");
+         if (G_UNLIKELY (!src)) {
+           GST_WARNING_OBJECT (self, "Can't get srcpad from " COLORSPACE);
+           gst_object_unref (sink);
+           continue;
+         }
  
-       if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
-         GST_WARNING_OBJECT (self, "Can't link " COLORSPACE " to textoverlay");
+         if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
+           GST_WARNING_OBJECT (self, "Can't link " COLORSPACE " to textoverlay");
+           gst_object_unref (src);
+           gst_object_unref (sink);
+           continue;
+         }
          gst_object_unref (src);
          gst_object_unref (sink);
-         continue;
-       }
-       gst_object_unref (src);
-       gst_object_unref (sink);
  
-       /* Set src ghostpad target */
-       src = gst_element_get_static_pad (self->post_colorspace, "src");
-       if (G_UNLIKELY (!src)) {
-         GST_WARNING_OBJECT (self, "Can't get src pad from " COLORSPACE);
-         continue;
-       }
+         /* Set src ghostpad target */
+         src = gst_element_get_static_pad (self->post_colorspace, "src");
+         if (G_UNLIKELY (!src)) {
+           GST_WARNING_OBJECT (self, "Can't get src pad from " COLORSPACE);
+           continue;
+         }
  
-       if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
-                   (self->srcpad), src))) {
-         GST_WARNING_OBJECT (self, "Can't set srcpad target");
+         if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
+                     (self->srcpad), src))) {
+           GST_WARNING_OBJECT (self, "Can't set srcpad target");
+           gst_object_unref (src);
+           continue;
+         }
+         gst_object_unref (src);
+       } else if (is_hw) {
+         GST_DEBUG_OBJECT (self,
+             "Is Hardware, not adding colorspace converters, ");
+         /* Set src ghostpad target */
+         src = gst_element_get_static_pad (self->overlay, "src");
+         if (G_UNLIKELY (!src)) {
+           GST_WARNING_OBJECT (self, "Can't get src pad from textoverlay");
+           continue;
+         }
+         if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
+                     (self->srcpad), src))) {
+           GST_WARNING_OBJECT (self, "Can't set srcpad target");
+           gst_object_unref (src);
+           continue;
+         }
          gst_object_unref (src);
-         continue;
        }
-       gst_object_unref (src);
  
        /* Send segments to the parser/overlay if necessary. These are not sent
         * outside this element because of the proxy pad event function */
        if (self->video_segment.format != GST_FORMAT_UNDEFINED) {
 -        GstEvent *event1, *event2;
 +        GstEvent *event1;
  
-         sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
-         if (G_UNLIKELY (!sink)) {
-           GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
-           continue;
+         if (is_video) {
+           sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
+           if (G_UNLIKELY (!sink)) {
+             GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
+             continue;
+           }
+         } else {
+           sink = gst_element_get_static_pad (self->overlay, "video_sink");
+           if (G_UNLIKELY (!sink)) {
+             GST_WARNING_OBJECT (self, "Can't get sink pad from textoverlay");
+             continue;
+           }
          }
  
 -        _generate_update_newsegment_event (&self->video_segment, &event1,
 -            &event2);
 -        GST_DEBUG_OBJECT (self,
 -            "Pushing video accumulate newsegment event: %" GST_PTR_FORMAT,
 -            event1->structure);
 +        _generate_update_segment_event (&self->video_segment, &event1);
          GST_DEBUG_OBJECT (self,
 -            "Pushing video update newsegment event: %" GST_PTR_FORMAT,
 -            event2->structure);
 +            "Pushing video segment event: %" GST_PTR_FORMAT, event1);
          gst_pad_send_event (sink, event1);
 -        gst_pad_send_event (sink, event2);
  
          gst_object_unref (sink);
        }
  
        if (self->subtitle_segment.format != GST_FORMAT_UNDEFINED) {
 -        GstEvent *event1, *event2;
 +        GstEvent *event1;
  
          sink = gst_element_get_static_pad (element, "sink");
          if (G_UNLIKELY (!sink)) {
            continue;
          }
  
 -        _generate_update_newsegment_event (&self->subtitle_segment, &event1,
 -            &event2);
 +        _generate_update_segment_event (&self->subtitle_segment, &event1);
          GST_DEBUG_OBJECT (self,
 -            "Pushing subtitle accumulate newsegment event: %" GST_PTR_FORMAT,
 -            event1->structure);
 -        GST_DEBUG_OBJECT (self,
 -            "Pushing subtitle update newsegment event: %" GST_PTR_FORMAT,
 -            event2->structure);
 +            "Pushing subtitle segment event: %" GST_PTR_FORMAT, event1);
          gst_pad_send_event (sink, event1);
 -        gst_pad_send_event (sink, event2);
  
          gst_object_unref (sink);
        }
  
        /* Set the sink ghostpad targets */
-       sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
-       if (G_UNLIKELY (!sink)) {
-         GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
-         continue;
+       if (is_video && !is_hw) {
+         sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
+         if (G_UNLIKELY (!sink)) {
+           GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
+           continue;
+         }
+       } else if (is_video && is_hw) {
+         GST_DEBUG_OBJECT (self, "Setting ghostpad to overlay video sink");
+         sink = gst_element_get_static_pad (self->overlay, "video_sink");
+         if (G_UNLIKELY (!sink)) {
+           GST_WARNING_OBJECT (self, "Can't get sink pad from overlay");
+           continue;
+         }
        }
  
        if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
      } else {
        const gchar *name =
            gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (factory));
-       gboolean is_raw_video = _is_raw_video_pad (self->video_sinkpad);
  
        if (strcmp (name, "textoverlay") == 0) {
          /* Set some textoverlay specific properties */
            g_object_set (self->renderer, "font-desc", self->font_desc, NULL);
        }
  
-       if (is_raw_video) {
-         /* First check that renderer also supports raw video */
+       if (is_video) {
+         gboolean render_is_hw;
+         /* First check that renderer also supports the video format */
          sink = _get_video_pad (element);
          if (G_UNLIKELY (!sink)) {
            GST_WARNING_OBJECT (self, "Can't get video sink from renderer");
            continue;
          }
  
-         if (G_UNLIKELY (!_is_raw_video_pad (sink))) {
-           GST_DEBUG_OBJECT (self, "Renderer doesn't support raw video");
+         if (is_video != _is_video_pad (sink, &render_is_hw) ||
+             is_hw != render_is_hw) {
+           GST_DEBUG_OBJECT (self, "Renderer doesn't support %s video",
+               is_hw ? "surface" : "raw");
            gst_object_unref (sink);
            continue;
          }
          gst_object_unref (sink);
  
-         /* First link everything internally */
-         if (G_UNLIKELY (!_create_element (self, &self->post_colorspace,
-                     COLORSPACE, NULL, "post-colorspace", FALSE))) {
-           continue;
-         }
-         src = gst_element_get_static_pad (element, "src");
-         if (G_UNLIKELY (!src)) {
-           GST_WARNING_OBJECT (self, "Can't get src pad from renderer");
-           continue;
-         }
+         if (!is_hw) {
+           /* First link everything internally */
+           if (G_UNLIKELY (!_create_element (self, &self->post_colorspace,
+                       COLORSPACE, NULL, "post-colorspace", FALSE))) {
+             continue;
+           }
+           src = gst_element_get_static_pad (element, "src");
+           if (G_UNLIKELY (!src)) {
+             GST_WARNING_OBJECT (self, "Can't get src pad from renderer");
+             continue;
+           }
  
-         sink = gst_element_get_static_pad (self->post_colorspace, "sink");
-         if (G_UNLIKELY (!sink)) {
-           GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
-           gst_object_unref (src);
-           continue;
-         }
+           sink = gst_element_get_static_pad (self->post_colorspace, "sink");
+           if (G_UNLIKELY (!sink)) {
+             GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
+             gst_object_unref (src);
+             continue;
+           }
  
-         if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
-           GST_WARNING_OBJECT (self, "Can't link renderer with " COLORSPACE);
+           if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
+             GST_WARNING_OBJECT (self, "Can't link renderer with " COLORSPACE);
+             gst_object_unref (src);
+             gst_object_unref (sink);
+             continue;
+           }
            gst_object_unref (src);
            gst_object_unref (sink);
-           continue;
-         }
-         gst_object_unref (src);
-         gst_object_unref (sink);
  
-         if (G_UNLIKELY (!_create_element (self, &self->pre_colorspace,
-                     COLORSPACE, NULL, "pre-colorspace", FALSE))) {
-           continue;
-         }
+           if (G_UNLIKELY (!_create_element (self, &self->pre_colorspace,
+                       COLORSPACE, NULL, "pre-colorspace", FALSE))) {
+             continue;
+           }
  
-         sink = _get_video_pad (element);
-         if (G_UNLIKELY (!sink)) {
-           GST_WARNING_OBJECT (self, "Can't get video sink from renderer");
-           continue;
-         }
+           sink = _get_video_pad (element);
+           if (G_UNLIKELY (!sink)) {
+             GST_WARNING_OBJECT (self, "Can't get video sink from renderer");
+             continue;
+           }
  
-         src = gst_element_get_static_pad (self->pre_colorspace, "src");
-         if (G_UNLIKELY (!src)) {
-           GST_WARNING_OBJECT (self, "Can't get srcpad from " COLORSPACE);
-           gst_object_unref (sink);
-           continue;
-         }
+           src = gst_element_get_static_pad (self->pre_colorspace, "src");
+           if (G_UNLIKELY (!src)) {
+             GST_WARNING_OBJECT (self, "Can't get srcpad from " COLORSPACE);
+             gst_object_unref (sink);
+             continue;
+           }
  
-         if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
-           GST_WARNING_OBJECT (self, "Can't link " COLORSPACE " to renderer");
+           if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
+             GST_WARNING_OBJECT (self, "Can't link " COLORSPACE " to renderer");
+             gst_object_unref (src);
+             gst_object_unref (sink);
+             continue;
+           }
            gst_object_unref (src);
            gst_object_unref (sink);
-           continue;
-         }
-         gst_object_unref (src);
-         gst_object_unref (sink);
  
-         /* Set src ghostpad target */
-         src = gst_element_get_static_pad (self->post_colorspace, "src");
-         if (G_UNLIKELY (!src)) {
-           GST_WARNING_OBJECT (self, "Can't get src pad from " COLORSPACE);
-           continue;
+           /* Set src ghostpad target */
+           src = gst_element_get_static_pad (self->post_colorspace, "src");
+           if (G_UNLIKELY (!src)) {
+             GST_WARNING_OBJECT (self, "Can't get src pad from " COLORSPACE);
+             continue;
+           }
+         } else {
+           /* Set src ghostpad target in the harware accelerated case */
+           src = gst_element_get_static_pad (self->renderer, "src");
+           if (G_UNLIKELY (!src)) {
+             GST_WARNING_OBJECT (self, "Can't get src pad from renderer");
+             continue;
+           }
          }
-       } else {                  /* No raw video pad */
+       } else {                  /* No video pad */
          GstCaps *allowed_caps, *video_caps = NULL;
          GstPad *video_peer;
          gboolean can_intersect = FALSE;
  
          video_peer = gst_pad_get_peer (self->video_sinkpad);
          if (video_peer) {
 -          video_caps = gst_pad_get_negotiated_caps (video_peer);
 +          video_caps = gst_pad_get_current_caps (video_peer);
            if (!video_caps) {
 -            video_caps = gst_pad_get_caps_reffed (video_peer);
 +            video_caps = gst_pad_query_caps (video_peer, NULL);
            }
            gst_object_unref (video_peer);
          }
            GST_WARNING_OBJECT (self, "Can't get video sink from renderer");
            continue;
          }
 -        allowed_caps = gst_pad_get_caps_reffed (sink);
 +        allowed_caps = gst_pad_query_caps (sink, NULL);
          gst_object_unref (sink);
  
          if (allowed_caps && video_caps)
        /* Send segments to the renderer if necessary. These are not sent
         * outside this element because of the proxy pad event handler */
        if (self->video_segment.format != GST_FORMAT_UNDEFINED) {
 -        GstEvent *event1, *event2;
 +        GstEvent *event1;
  
          sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
          if (G_UNLIKELY (!sink)) {
            continue;
          }
  
 -        _generate_update_newsegment_event (&self->video_segment, &event1,
 -            &event2);
 -        GST_DEBUG_OBJECT (self,
 -            "Pushing video accumulate newsegment event: %" GST_PTR_FORMAT,
 -            event1->structure);
 +        _generate_update_segment_event (&self->video_segment, &event1);
          GST_DEBUG_OBJECT (self,
 -            "Pushing video update newsegment event: %" GST_PTR_FORMAT,
 -            event2->structure);
 +            "Pushing video segment event: %" GST_PTR_FORMAT, event1);
          gst_pad_send_event (sink, event1);
 -        gst_pad_send_event (sink, event2);
          gst_object_unref (sink);
        }
  
        if (self->subtitle_segment.format != GST_FORMAT_UNDEFINED) {
 -        GstEvent *event1, *event2;
 +        GstEvent *event1;
  
          sink = _get_sub_pad (element);
          if (G_UNLIKELY (!sink)) {
            continue;
          }
  
 -        _generate_update_newsegment_event (&self->subtitle_segment, &event1,
 -            &event2);
 -        GST_DEBUG_OBJECT (self,
 -            "Pushing subtitle accumulate newsegment event: %" GST_PTR_FORMAT,
 -            event1->structure);
 +        _generate_update_segment_event (&self->subtitle_segment, &event1);
          GST_DEBUG_OBJECT (self,
 -            "Pushing subtitle update newsegment event: %" GST_PTR_FORMAT,
 -            event2->structure);
 +            "Pushing subtitle segment event: %" GST_PTR_FORMAT, event1);
          gst_pad_send_event (sink, event1);
 -        gst_pad_send_event (sink, event2);
          gst_object_unref (sink);
        }
  
      do_async_done (self);
    } else {
      GST_DEBUG_OBJECT (self, "Everything worked, unblocking pads");
 -    gst_pad_set_blocked_async_full (self->video_block_pad, FALSE,
 -        _pad_blocked_cb, self, NULL);
 -    gst_pad_set_blocked_async_full (self->subtitle_block_pad, FALSE,
 -        _pad_blocked_cb, self, NULL);
 +    unblock_video (self);
 +    unblock_subtitle (self);
      do_async_done (self);
    }
  
@@@ -1344,8 -1433,6 +1414,8 @@@ out
    if (factories)
      gst_plugin_feature_list_free (factories);
    GST_SUBTITLE_OVERLAY_UNLOCK (self);
 +
 +  return GST_PAD_PROBE_OK;
  }
  
  static GstStateChangeReturn
@@@ -1367,8 -1454,10 +1437,8 @@@ gst_subtitle_overlay_change_state (GstE
  
        GST_SUBTITLE_OVERLAY_LOCK (self);
        /* Set the internal pads to blocking */
 -      gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
 -          _pad_blocked_cb, self, NULL);
 -      gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
 -          _pad_blocked_cb, self, NULL);
 +      block_video (self);
 +      block_subtitle (self);
        GST_SUBTITLE_OVERLAY_UNLOCK (self);
        break;
      case GST_STATE_CHANGE_READY_TO_PAUSED:
        do_async_done (self);
  
        break;
 -    case GST_STATE_CHANGE_READY_TO_NULL:{
 -      GstPad *pad;
 -
 +    case GST_STATE_CHANGE_READY_TO_NULL:
        GST_DEBUG_OBJECT (self, "State change READY->NULL");
  
        GST_SUBTITLE_OVERLAY_LOCK (self);
            NULL);
  
        /* Unblock pads */
 -      if (self->video_block_pad) {
 -        pad = self->video_block_pad;
 -        gst_pad_set_blocked_async_full (pad, FALSE, _pad_blocked_cb,
 -            self, NULL);
 -      }
 -
 -      if (self->subtitle_block_pad) {
 -        pad = self->subtitle_block_pad;
 -        gst_pad_set_blocked_async_full (pad, FALSE, _pad_blocked_cb,
 -            self, NULL);
 -      }
 +      unblock_video (self);
 +      unblock_subtitle (self);
  
        /* Remove elements */
        self->silent_property = NULL;
        GST_SUBTITLE_OVERLAY_UNLOCK (self);
  
        break;
 -    }
      default:
        break;
    }
@@@ -1488,8 -1589,11 +1558,8 @@@ gst_subtitle_overlay_handle_message (Gs
        GST_SUBTITLE_OVERLAY_LOCK (self);
        self->subtitle_error = TRUE;
  
 -      gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
 -          _pad_blocked_cb, self, NULL);
 -
 -      gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
 -          _pad_blocked_cb, self, NULL);
 +      block_subtitle (self);
 +      block_video (self);
        GST_SUBTITLE_OVERLAY_UNLOCK (self);
      }
    }
@@@ -1544,8 -1648,11 +1614,8 @@@ gst_subtitle_overlay_set_property (GObj
          else if (self->renderer)
            g_object_set (self->renderer, self->silent_property, silent, NULL);
        } else {
 -        gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
 -            _pad_blocked_cb, self, NULL);
 -
 -        gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
 -            _pad_blocked_cb, self, NULL);
 +        block_subtitle (self);
 +        block_video (self);
        }
        GST_SUBTITLE_OVERLAY_UNLOCK (self);
        break;
  }
  
  static void
 -gst_subtitle_overlay_base_init (gpointer g_class)
 -{
 -  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
 -
 -  gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
 -
 -  gst_element_class_add_static_pad_template (gstelement_class,
 -      &video_sinktemplate);
 -  gst_element_class_add_static_pad_template (gstelement_class,
 -      &subtitle_sinktemplate);
 -
 -  gst_element_class_set_details_simple (gstelement_class, "Subtitle Overlay",
 -      "Video/Overlay/Subtitle",
 -      "Overlays a video stream with subtitles",
 -      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
 -}
 -
 -static void
  gst_subtitle_overlay_class_init (GstSubtitleOverlayClass * klass)
  {
    GObjectClass *gobject_class = (GObjectClass *) klass;
            "ISO-8859-15 will be assumed.", NULL,
            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
 +  gst_element_class_add_pad_template (element_class,
 +      gst_static_pad_template_get (&srctemplate));
 +
 +  gst_element_class_add_pad_template (element_class,
 +      gst_static_pad_template_get (&video_sinktemplate));
 +  gst_element_class_add_pad_template (element_class,
 +      gst_static_pad_template_get (&subtitle_sinktemplate));
 +
 +  gst_element_class_set_details_simple (element_class, "Subtitle Overlay",
 +      "Video/Overlay/Subtitle",
 +      "Overlays a video stream with subtitles",
 +      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
 +
    element_class->change_state =
        GST_DEBUG_FUNCPTR (gst_subtitle_overlay_change_state);
  
  }
  
  static GstFlowReturn
 -gst_subtitle_overlay_src_proxy_chain (GstPad * proxypad, GstBuffer * buffer)
 +gst_subtitle_overlay_src_proxy_chain (GstPad * proxypad, GstObject * parent,
 +    GstBuffer * buffer)
  {
    GstPad *ghostpad;
    GstSubtitleOverlay *self;
    GstFlowReturn ret;
  
 -  ghostpad = GST_PAD_CAST (gst_pad_get_parent (proxypad));
 +  ghostpad = GST_PAD_CAST (parent);
    if (G_UNLIKELY (!ghostpad)) {
      gst_buffer_unref (buffer);
      return GST_FLOW_ERROR;
      return GST_FLOW_ERROR;
    }
  
 -  ret = gst_proxy_pad_chain_default (proxypad, buffer);
 +  ret = gst_proxy_pad_chain_default (proxypad, parent, buffer);
  
    if (IS_VIDEO_CHAIN_IGNORE_ERROR (ret)) {
      GST_ERROR_OBJECT (self, "Downstream chain error: %s",
    }
  
    gst_object_unref (self);
 -  gst_object_unref (ghostpad);
  
    return ret;
  }
  
  static gboolean
 -gst_subtitle_overlay_src_proxy_event (GstPad * proxypad, GstEvent * event)
 +gst_subtitle_overlay_src_proxy_event (GstPad * proxypad, GstObject * parent,
 +    GstEvent * event)
  {
    GstPad *ghostpad = NULL;
    GstSubtitleOverlay *self = NULL;
    gboolean ret = FALSE;
    const GstStructure *s;
  
 -  ghostpad = GST_PAD_CAST (gst_pad_get_parent (proxypad));
 +  ghostpad = GST_PAD_CAST (parent);
    if (G_UNLIKELY (!ghostpad))
      goto out;
    self = GST_SUBTITLE_OVERLAY_CAST (gst_pad_get_parent (ghostpad));
    s = gst_event_get_structure (event);
    if (s && gst_structure_id_has_field (s, _subtitle_overlay_event_marker_id)) {
      GST_DEBUG_OBJECT (ghostpad, "Dropping event with marker: %" GST_PTR_FORMAT,
 -        event->structure);
 +        event);
      gst_event_unref (event);
      event = NULL;
      ret = TRUE;
    } else {
 -    ret = gst_proxy_pad_event_default (proxypad, event);
 +    ret = gst_proxy_pad_event_default (proxypad, parent, event);
      event = NULL;
    }
  
      gst_event_unref (event);
    if (self)
      gst_object_unref (self);
 -  if (ghostpad)
 -    gst_object_unref (ghostpad);
 +
    return ret;
  }
  
  static gboolean
 -gst_subtitle_overlay_video_sink_setcaps (GstPad * pad, GstCaps * caps)
 +gst_subtitle_overlay_video_sink_setcaps (GstSubtitleOverlay * self,
 +    GstCaps * caps)
  {
 -  GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad));
    GstPad *target;
    gboolean ret = TRUE;
 -  gint fps_n, fps_d;
 +  GstVideoInfo info;
  
 -  GST_DEBUG_OBJECT (pad, "Setting caps: %" GST_PTR_FORMAT, caps);
 +  GST_DEBUG_OBJECT (self, "Setting caps: %" GST_PTR_FORMAT, caps);
 +
 +  if (!gst_video_info_from_caps (&info, caps)) {
 +    GST_ERROR_OBJECT (self, "Failed to parse caps");
 +    ret = FALSE;
 +    GST_SUBTITLE_OVERLAY_UNLOCK (self);
 +    goto out;
 +  }
  
    target = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (self->video_sinkpad));
  
    GST_SUBTITLE_OVERLAY_LOCK (self);
  
 -  if (!target || !gst_pad_accept_caps (target, caps)) {
 -    GST_DEBUG_OBJECT (pad, "Target did not accept caps -- reconfiguring");
 +  if (!target || !gst_pad_query_accept_caps (target, caps)) {
 +    GST_DEBUG_OBJECT (target, "Target did not accept caps -- reconfiguring");
  
 -    gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
 -        _pad_blocked_cb, self, NULL);
 -
 -    gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
 -        _pad_blocked_cb, self, NULL);
 -  }
 -
 -  if (!gst_video_parse_caps_framerate (caps, &fps_n, &fps_d)) {
 -    GST_ERROR_OBJECT (pad, "Failed to parse framerate from caps");
 -    ret = FALSE;
 -    GST_SUBTITLE_OVERLAY_UNLOCK (self);
 -    goto out;
 +    block_subtitle (self);
 +    block_video (self);
    }
  
 -  if (self->fps_n != fps_n || self->fps_d != fps_d) {
 -    GST_DEBUG_OBJECT (self, "New video fps: %d/%d", fps_n, fps_d);
 -    self->fps_n = fps_n;
 -    self->fps_d = fps_d;
 +  GST_SUBTITLE_OVERLAY_LOCK (self);
 +  if (self->fps_n != info.fps_n || self->fps_d != info.fps_d) {
 +    GST_DEBUG_OBJECT (self, "New video fps: %d/%d", info.fps_n, info.fps_d);
 +    self->fps_n = info.fps_n;
 +    self->fps_d = info.fps_d;
      gst_subtitle_overlay_set_fps (self);
    }
    GST_SUBTITLE_OVERLAY_UNLOCK (self);
  
 -  ret = gst_ghost_pad_setcaps_default (pad, caps);
 -
 -out:
    if (target)
      gst_object_unref (target);
 -  gst_object_unref (self);
 +
 +out:
 +
    return ret;
  }
  
  static gboolean
 -gst_subtitle_overlay_video_sink_event (GstPad * pad, GstEvent * event)
 +gst_subtitle_overlay_video_sink_event (GstPad * pad, GstObject * parent,
 +    GstEvent * event)
  {
 -  GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad));
 +  GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (parent);
    gboolean ret;
  
 -  if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
 -    GST_DEBUG_OBJECT (pad,
 -        "Resetting video segment because of flush-stop event");
 -    gst_segment_init (&self->video_segment, GST_FORMAT_UNDEFINED);
 -    self->fps_n = self->fps_d = 0;
 +  switch (GST_EVENT_TYPE (event)) {
 +    case GST_EVENT_FLUSH_STOP:
 +    {
 +      GST_DEBUG_OBJECT (pad,
 +          "Resetting video segment because of flush-stop event");
 +      gst_segment_init (&self->video_segment, GST_FORMAT_UNDEFINED);
 +      self->fps_n = self->fps_d = 0;
 +      break;
 +    }
 +    case GST_EVENT_CAPS:
 +    {
 +      GstCaps *caps;
 +
 +      gst_event_parse_caps (event, &caps);
 +      ret = gst_subtitle_overlay_video_sink_setcaps (self, caps);
 +      if (!ret)
 +        goto done;
 +      break;
 +    }
 +    default:
 +      break;
    }
  
 -  ret = gst_proxy_pad_event_default (pad, gst_event_ref (event));
 -
 -  if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
 -    gboolean update;
 -    gdouble rate, applied_rate;
 -    GstFormat format;
 -    gint64 start, stop, position;
 +  ret = gst_proxy_pad_event_default (pad, parent, gst_event_ref (event));
  
 -    GST_DEBUG_OBJECT (pad, "Newsegment event: %" GST_PTR_FORMAT,
 -        event->structure);
 -    gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
 -        &format, &start, &stop, &position);
 +  if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
 +    GST_DEBUG_OBJECT (pad, "segment event: %" GST_PTR_FORMAT, event);
 +    gst_event_copy_segment (event, &self->video_segment);
  
 -    if (format != GST_FORMAT_TIME) {
 -      GST_ERROR_OBJECT (pad, "Newsegment event in non-time format: %s",
 -          gst_format_get_name (format));
 -      gst_event_unref (event);
 -      gst_object_unref (self);
 -      return FALSE;
 -    }
 -
 -    GST_DEBUG_OBJECT (pad, "Old video segment: %" GST_SEGMENT_FORMAT,
 -        &self->video_segment);
 -    gst_segment_set_newsegment_full (&self->video_segment, update, rate,
 -        applied_rate, format, start, stop, position);
 -    GST_DEBUG_OBJECT (pad, "New video segment: %" GST_SEGMENT_FORMAT,
 -        &self->video_segment);
 +    if (self->video_segment.format != GST_FORMAT_TIME)
 +      goto invalid_format;
    }
  
 +done:
    gst_event_unref (event);
 -  gst_object_unref (self);
 +
    return ret;
 +
 +  /* ERRORS */
 +invalid_format:
 +  {
 +    GST_ERROR_OBJECT (pad, "Newsegment event in non-time format: %s",
 +        gst_format_get_name (self->video_segment.format));
 +    ret = FALSE;
 +    goto done;
 +  }
  }
  
  static GstFlowReturn
 -gst_subtitle_overlay_video_sink_chain (GstPad * pad, GstBuffer * buffer)
 +gst_subtitle_overlay_video_sink_chain (GstPad * pad, GstObject * parent,
 +    GstBuffer * buffer)
  {
 -  GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (GST_PAD_PARENT (pad));
 -  GstFlowReturn ret = gst_proxy_pad_chain_default (pad, buffer);
 +  GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (parent);
 +  GstFlowReturn ret = gst_proxy_pad_chain_default (pad, parent, buffer);
  
    if (G_UNLIKELY (self->downstream_chain_error) || self->passthrough_identity) {
      return ret;
          gst_flow_get_name (ret));
      GST_SUBTITLE_OVERLAY_LOCK (self);
      self->subtitle_error = TRUE;
 -    gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
 -        _pad_blocked_cb, self, NULL);
 -
 -    gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
 -        _pad_blocked_cb, self, NULL);
 +    block_subtitle (self);
 +    block_video (self);
      GST_SUBTITLE_OVERLAY_UNLOCK (self);
  
      return GST_FLOW_OK;
  }
  
  static GstFlowReturn
 -gst_subtitle_overlay_subtitle_sink_chain (GstPad * pad, GstBuffer * buffer)
 +gst_subtitle_overlay_subtitle_sink_chain (GstPad * pad, GstObject * parent,
 +    GstBuffer * buffer)
  {
 -  GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (GST_PAD_PARENT (pad));
 +  GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (parent);
  
    if (self->subtitle_error) {
      gst_buffer_unref (buffer);
      return GST_FLOW_OK;
    } else {
 -    GstFlowReturn ret = gst_proxy_pad_chain_default (pad, buffer);
 +    GstFlowReturn ret = gst_proxy_pad_chain_default (pad, parent, buffer);
  
      if (IS_SUBTITLE_CHAIN_IGNORE_ERROR (ret)) {
        GST_DEBUG_OBJECT (self, "Subtitle chain error: %s",
            gst_flow_get_name (ret));
        GST_SUBTITLE_OVERLAY_LOCK (self);
        self->subtitle_error = TRUE;
 -      gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
 -          _pad_blocked_cb, self, NULL);
 -
 -      gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
 -          _pad_blocked_cb, self, NULL);
 +      block_subtitle (self);
 +      block_video (self);
        GST_SUBTITLE_OVERLAY_UNLOCK (self);
  
        return GST_FLOW_OK;
  }
  
  static GstCaps *
 -gst_subtitle_overlay_subtitle_sink_getcaps (GstPad * pad)
 +gst_subtitle_overlay_subtitle_sink_getcaps (GstPad * pad, GstCaps * filter)
  {
    GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad));
    GstCaps *ret;
    g_mutex_lock (self->factories_lock);
    if (G_UNLIKELY (!gst_subtitle_overlay_update_factory_list (self)))
      ret = GST_CAPS_NONE;
 +  else if (filter)
 +    ret =
 +        gst_caps_intersect_full (filter, self->factory_caps,
 +        GST_CAPS_INTERSECT_FIRST);
    else
      ret = gst_caps_ref (self->factory_caps);
    g_mutex_unlock (self->factories_lock);
  }
  
  static gboolean
 -gst_subtitle_overlay_subtitle_sink_acceptcaps (GstPad * pad, GstCaps * caps)
 -{
 -  GstCaps *othercaps = gst_subtitle_overlay_subtitle_sink_getcaps (pad);
 -  gboolean ret = gst_caps_is_subset (caps, othercaps);
 -
 -  gst_caps_unref (othercaps);
 -
 -  return ret;
 -}
 -
 -static gboolean
 -gst_subtitle_overlay_subtitle_sink_setcaps (GstPad * pad, GstCaps * caps)
 +gst_subtitle_overlay_subtitle_sink_setcaps (GstSubtitleOverlay * self,
 +    GstCaps * caps)
  {
 -  GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad));
    gboolean ret = TRUE;
    GstPad *target = NULL;;
  
 -  GST_DEBUG_OBJECT (pad, "Setting caps: %" GST_PTR_FORMAT, caps);
 +  GST_DEBUG_OBJECT (self, "Setting caps: %" GST_PTR_FORMAT, caps);
  
    target =
        gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (self->subtitle_sinkpad));
    GST_SUBTITLE_OVERLAY_LOCK (self);
    gst_caps_replace (&self->subcaps, caps);
  
 -  if (target && gst_pad_accept_caps (target, caps)) {
 -    GST_DEBUG_OBJECT (pad, "Target accepts caps");
 -    ret = gst_ghost_pad_setcaps_default (pad, caps);
 +  if (target && gst_pad_query_accept_caps (target, caps)) {
 +    GST_DEBUG_OBJECT (self, "Target accepts caps");
      GST_SUBTITLE_OVERLAY_UNLOCK (self);
      goto out;
    }
  
 -  GST_DEBUG_OBJECT (pad, "Target did not accept caps");
 +  GST_DEBUG_OBJECT (self, "Target did not accept caps");
  
    self->subtitle_error = FALSE;
 -
 -  gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
 -      _pad_blocked_cb, self, NULL);
 -
 -  gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
 -      _pad_blocked_cb, self, NULL);
 +  block_subtitle (self);
 +  block_video (self);
    GST_SUBTITLE_OVERLAY_UNLOCK (self);
  
  out:
    if (target)
      gst_object_unref (target);
 -  gst_object_unref (self);
 +
    return ret;
  }
  
@@@ -1918,9 -2041,9 +1988,9 @@@ gst_subtitle_overlay_subtitle_sink_lin
  
    GST_DEBUG_OBJECT (pad, "Linking pad to peer %" GST_PTR_FORMAT, peer);
  
 -  caps = gst_pad_get_negotiated_caps (peer);
 +  caps = gst_pad_get_current_caps (peer);
    if (!caps) {
 -    caps = gst_pad_get_caps_reffed (peer);
 +    caps = gst_pad_query_caps (peer, NULL);
      if (!gst_caps_is_fixed (caps)) {
        gst_caps_unref (caps);
        caps = NULL;
  
      self->subtitle_error = FALSE;
  
 -    gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
 -        _pad_blocked_cb, self, NULL);
 -
 -    gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
 -        _pad_blocked_cb, self, NULL);
 +    block_subtitle (self);
 +    block_video (self);
      GST_SUBTITLE_OVERLAY_UNLOCK (self);
      gst_caps_unref (caps);
    }
@@@ -1964,125 -2090,120 +2034,125 @@@ gst_subtitle_overlay_subtitle_sink_unli
    GST_SUBTITLE_OVERLAY_LOCK (self);
    self->subtitle_error = FALSE;
  
 -  if (self->subtitle_block_pad)
 -    gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
 -        _pad_blocked_cb, self, NULL);
 -
 -  if (self->video_block_pad)
 -    gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
 -        _pad_blocked_cb, self, NULL);
 +  block_subtitle (self);
 +  block_video (self);
    GST_SUBTITLE_OVERLAY_UNLOCK (self);
  
    gst_object_unref (self);
  }
  
  static gboolean
 -gst_subtitle_overlay_subtitle_sink_event (GstPad * pad, GstEvent * event)
 +gst_subtitle_overlay_subtitle_sink_event (GstPad * pad, GstObject * parent,
 +    GstEvent * event)
  {
 -  GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad));
 +  GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (parent);
    gboolean ret;
 -  GstFormat format;
  
    if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB &&
 -      event->structure
 -      && strcmp (gst_structure_get_name (event->structure),
 -          "subtitleoverlay-flush-subtitle") == 0) {
 +      gst_event_has_name (event, "subtitleoverlay-flush-subtitle")) {
      GST_DEBUG_OBJECT (pad, "Custom subtitle flush event");
      GST_SUBTITLE_OVERLAY_LOCK (self);
      self->subtitle_flush = TRUE;
      self->subtitle_error = FALSE;
 -    if (self->subtitle_block_pad)
 -      gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
 -          _pad_blocked_cb, self, NULL);
 -    if (self->video_block_pad)
 -      gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
 -          _pad_blocked_cb, self, NULL);
 +    block_subtitle (self);
 +    block_video (self);
      GST_SUBTITLE_OVERLAY_UNLOCK (self);
  
      gst_event_unref (event);
      event = NULL;
      ret = TRUE;
      goto out;
 -  } else if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
 -    gst_event_parse_new_segment_full (event, NULL, NULL, NULL,
 -        &format, NULL, NULL, NULL);
 -    if (self->subtitle_segment.format != GST_FORMAT_UNDEFINED &&
 -        self->subtitle_segment.format != format) {
 -      GST_DEBUG_OBJECT (pad, "Subtitle segment format changed: %s -> %s",
 -          gst_format_get_name (self->subtitle_segment.format),
 -          gst_format_get_name (format));
 -      gst_segment_init (&self->subtitle_segment, GST_FORMAT_UNDEFINED);
 -    }
    }
  
    switch (GST_EVENT_TYPE (event)) {
 +    case GST_EVENT_CAPS:
 +    {
 +      GstCaps *caps;
 +
 +      gst_event_parse_caps (event, &caps);
 +      ret = gst_subtitle_overlay_subtitle_sink_setcaps (self, caps);
 +      if (!ret)
 +        goto out;
 +      break;
 +    }
      case GST_EVENT_FLUSH_STOP:
        GST_DEBUG_OBJECT (pad,
            "Resetting subtitle segment because of flush-stop");
        gst_segment_init (&self->subtitle_segment, GST_FORMAT_UNDEFINED);
        /* fall through */
      case GST_EVENT_FLUSH_START:
 -    case GST_EVENT_NEWSEGMENT:
 +    case GST_EVENT_SEGMENT:
      case GST_EVENT_EOS:
 +    {
 +      GstStructure *structure;
 +
        /* Add our event marker to make sure no events from here go ever outside
         * the element, they're only interesting for our internal elements */
 -      event =
 -          GST_EVENT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST
 -              (event)));
 -      if (!event->structure) {
 -        event->structure =
 -            gst_structure_id_empty_new (_subtitle_overlay_event_marker_id);
 -        gst_structure_set_parent_refcount (event->structure,
 -            &event->mini_object.refcount);
 -      }
 -      gst_structure_id_set (event->structure, _subtitle_overlay_event_marker_id,
 +      event = GST_EVENT_CAST (gst_event_make_writable (event));
 +      structure = gst_event_writable_structure (event);
 +
 +      gst_structure_id_set (structure, _subtitle_overlay_event_marker_id,
            G_TYPE_BOOLEAN, TRUE, NULL);
        break;
 +    }
      default:
        break;
    }
  
 -  ret = gst_proxy_pad_event_default (pad, gst_event_ref (event));
 -
 -  if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
 -    gboolean update;
 -    gdouble rate, applied_rate;
 -    gint64 start, stop, position;
 +  ret = gst_proxy_pad_event_default (pad, parent, gst_event_ref (event));
  
 -    GST_DEBUG_OBJECT (pad, "Newsegment event: %" GST_PTR_FORMAT,
 -        event->structure);
 -    gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
 -        &format, &start, &stop, &position);
 -
 -    GST_DEBUG_OBJECT (pad, "Old subtitle segment: %" GST_SEGMENT_FORMAT,
 -        &self->subtitle_segment);
 -    if (self->subtitle_segment.format != format) {
 -      GST_DEBUG_OBJECT (pad, "Subtitle segment format changed: %s -> %s",
 -          gst_format_get_name (self->subtitle_segment.format),
 -          gst_format_get_name (format));
 -      gst_segment_init (&self->subtitle_segment, format);
 -    }
 -
 -    gst_segment_set_newsegment_full (&self->subtitle_segment, update, rate,
 -        applied_rate, format, start, stop, position);
 +  if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
 +    GST_DEBUG_OBJECT (pad, "segment event: %" GST_PTR_FORMAT, event);
 +    gst_event_copy_segment (event, &self->subtitle_segment);
      GST_DEBUG_OBJECT (pad, "New subtitle segment: %" GST_SEGMENT_FORMAT,
          &self->subtitle_segment);
    }
    gst_event_unref (event);
  
  out:
 -  gst_object_unref (self);
 +  return ret;
 +}
 +
 +static gboolean
 +gst_subtitle_overlay_subtitle_sink_query (GstPad * pad, GstObject * parent,
 +    GstQuery * query)
 +{
 +  gboolean ret;
 +
 +  switch (GST_QUERY_TYPE (query)) {
 +    case GST_QUERY_ACCEPT_CAPS:
 +    {
 +      GstCaps *caps, *othercaps;
 +
 +      gst_query_parse_accept_caps (query, &caps);
 +      othercaps = gst_subtitle_overlay_subtitle_sink_getcaps (pad, NULL);
 +      ret = gst_caps_is_subset (caps, othercaps);
 +      gst_caps_unref (othercaps);
 +      gst_query_set_accept_caps_result (query, ret);
 +      ret = TRUE;
 +      break;
 +    }
 +    case GST_QUERY_CAPS:
 +    {
 +      GstCaps *filter, *caps;
 +
 +      gst_query_parse_caps (query, &filter);
 +      caps = gst_subtitle_overlay_subtitle_sink_getcaps (pad, filter);
 +      gst_query_set_caps_result (query, caps);
 +      gst_caps_unref (caps);
 +      ret = TRUE;
 +      break;
 +    }
 +    default:
 +      ret = gst_pad_query_default (pad, parent, query);
 +      break;
 +  }
 +
    return ret;
  }
  
  static void
 -gst_subtitle_overlay_init (GstSubtitleOverlay * self,
 -    GstSubtitleOverlayClass * klass)
 +gst_subtitle_overlay_init (GstSubtitleOverlay * self)
  {
    GstPadTemplate *templ;
    GstPad *proxypad = NULL;
    gst_object_unref (templ);
    gst_pad_set_event_function (self->video_sinkpad,
        GST_DEBUG_FUNCPTR (gst_subtitle_overlay_video_sink_event));
 -  gst_pad_set_setcaps_function (self->video_sinkpad,
 -      GST_DEBUG_FUNCPTR (gst_subtitle_overlay_video_sink_setcaps));
    gst_pad_set_chain_function (self->video_sinkpad,
        GST_DEBUG_FUNCPTR (gst_subtitle_overlay_video_sink_chain));
  
        GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_unlink));
    gst_pad_set_event_function (self->subtitle_sinkpad,
        GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_event));
 -  gst_pad_set_setcaps_function (self->subtitle_sinkpad,
 -      GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_setcaps));
 +  gst_pad_set_query_function (self->subtitle_sinkpad,
 +      GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_query));
    gst_pad_set_chain_function (self->subtitle_sinkpad,
        GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_chain));
 -  gst_pad_set_getcaps_function (self->subtitle_sinkpad,
 -      GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_getcaps));
 -  gst_pad_set_acceptcaps_function (self->subtitle_sinkpad,
 -      GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_acceptcaps));
 -  gst_pad_set_bufferalloc_function (self->subtitle_sinkpad, NULL);
  
    proxypad =
        GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
@@@ -21,7 -21,7 +21,7 @@@
   * SECTION:element-uridecodebin
   *
   * Decodes data from a URI into raw media. It selects a source element that can
 - * handle the given #GstURIDecodeBin:uri scheme and connects it to a decodebin2.
 + * handle the given #GstURIDecodeBin:uri scheme and connects it to a decodebin.
   */
  
  #ifdef HAVE_CONFIG_H
  #include "gstplay-marshal.h"
  #include "gstplay-enum.h"
  #include "gstrawcaps.h"
 +#include "gstplayback.h"
  
+ #include "gst/glib-compat-private.h"
  #define GST_TYPE_URI_DECODE_BIN \
    (gst_uri_decode_bin_get_type())
  #define GST_URI_DECODE_BIN(obj) \
@@@ -80,7 -81,7 +82,7 @@@ struct _GstURIDecodeBi
    GList *factories;             /* factories we can use for selecting elements */
  
    gchar *uri;
 -  guint connection_speed;
 +  guint64 connection_speed;
    GstCaps *caps;
    gchar *encoding;
  
    GSList *decodebins;
    GSList *pending_decodebins;
    GHashTable *streams;
 -  gint numpads;
 +  guint numpads;
  
    /* for dynamic sources */
    guint src_np_sig_id;          /* new-pad signal id */
@@@ -137,7 -138,7 +139,7 @@@ struct _GstURIDecodeBinClas
    void (*drained) (GstElement * element);
  };
  
 -static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src%d",
 +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src_%u",
      GST_PAD_SRC,
      GST_PAD_SOMETIMES,
      GST_STATIC_CAPS_ANY);
@@@ -193,8 -194,7 +195,8 @@@ enu
  static guint gst_uri_decode_bin_signals[LAST_SIGNAL] = { 0 };
  
  GType gst_uri_decode_bin_get_type (void);
 -GST_BOILERPLATE (GstURIDecodeBin, gst_uri_decode_bin, GstBin, GST_TYPE_BIN);
 +#define gst_uri_decode_bin_parent_class parent_class
 +G_DEFINE_TYPE (GstURIDecodeBin, gst_uri_decode_bin, GST_TYPE_BIN);
  
  static void remove_decoders (GstURIDecodeBin * bin, gboolean force);
  static void gst_uri_decode_bin_set_property (GObject * object, guint prop_id,
@@@ -210,6 -210,18 +212,6 @@@ static gboolean gst_uri_decode_bin_quer
  static GstStateChangeReturn gst_uri_decode_bin_change_state (GstElement *
      element, GstStateChange transition);
  
 -static void
 -gst_uri_decode_bin_base_init (gpointer g_class)
 -{
 -  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
 -
 -  gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
 -  gst_element_class_set_details_simple (gstelement_class,
 -      "URI Decoder", "Generic/Bin/Decoder",
 -      "Autoplug and decode an URI to raw media",
 -      "Wim Taymans <wim.taymans@gmail.com>");
 -}
 -
  static gboolean
  _gst_boolean_accumulator (GSignalInvocationHint * ihint,
      GValue * return_accu, const GValue * handler_return, gpointer dummy)
@@@ -366,9 -378,9 +368,9 @@@ gst_uri_decode_bin_class_init (GstURIDe
            GST_TYPE_ELEMENT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
  
    g_object_class_install_property (gobject_class, PROP_CONNECTION_SPEED,
 -      g_param_spec_uint ("connection-speed", "Connection Speed",
 +      g_param_spec_uint64 ("connection-speed", "Connection Speed",
            "Network connection speed in kbps (0 = unknown)",
 -          0, G_MAXUINT / 1000, DEFAULT_CONNECTION_SPEED,
 +          0, G_MAXUINT64 / 1000, DEFAULT_CONNECTION_SPEED,
            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
    g_object_class_install_property (gobject_class, PROP_CAPS,
     *
     * Returns: #TRUE if you wish uridecodebin to look for elements that can
     * handle the given @caps. If #FALSE, those caps will be considered as
 -   * final and the pad will be exposed as such (see 'new-decoded-pad'
 -   * signal).
 +   * final and the pad will be exposed as such (see 'pad-added' signal of
 +   * #GstElement).
     */
    gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE] =
        g_signal_new ("autoplug-continue", G_TYPE_FROM_CLASS (klass),
     * @caps: The #GstCaps.
     * @factories: A #GValueArray of possible #GstElementFactory to use.
     *
 -   * Once decodebin2 has found the possible #GstElementFactory objects to try
 -   * for @caps on @pad, this signal is emitted. The purpose of the signal is for
 +   * Once decodebin has found the possible #GstElementFactory objects to try
 +   * for @caps on @pad, this signal is emited. The purpose of the signal is for
     * the application to perform additional sorting or filtering on the element
     * factory array.
     *
     * those factories, this signal is emitted.
     *
     * The signal handler should return a #GST_TYPE_AUTOPLUG_SELECT_RESULT enum
 -   * value indicating what decodebin2 should do next.
 +   * value indicating what decodebin should do next.
     *
     * A value of #GST_AUTOPLUG_SELECT_TRY will try to autoplug an element from
     * @factory.
        G_SIGNAL_RUN_LAST, 0, NULL, NULL,
        gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
  
 +  gst_element_class_add_pad_template (gstelement_class,
 +      gst_static_pad_template_get (&srctemplate));
 +  gst_element_class_set_details_simple (gstelement_class,
 +      "URI Decoder", "Generic/Bin/Decoder",
 +      "Autoplug and decode an URI to raw media",
 +      "Wim Taymans <wim.taymans@gmail.com>");
 +
    gstelement_class->query = GST_DEBUG_FUNCPTR (gst_uri_decode_bin_query);
    gstelement_class->change_state =
        GST_DEBUG_FUNCPTR (gst_uri_decode_bin_change_state);
  }
  
  static void
 -gst_uri_decode_bin_init (GstURIDecodeBin * dec, GstURIDecodeBinClass * klass)
 +gst_uri_decode_bin_init (GstURIDecodeBin * dec)
  {
    /* first filter out the interesting element factories */
    dec->factories_lock = g_mutex_new ();
    dec->expose_allstreams = DEFAULT_EXPOSE_ALL_STREAMS;
    dec->ring_buffer_max_size = DEFAULT_RING_BUFFER_MAX_SIZE;
  
 -  GST_OBJECT_FLAG_SET (dec, GST_ELEMENT_IS_SOURCE);
 +  GST_OBJECT_FLAG_SET (dec, GST_ELEMENT_FLAG_SOURCE);
  }
  
  static void
@@@ -732,7 -737,7 +734,7 @@@ gst_uri_decode_bin_set_property (GObjec
        break;
      case PROP_CONNECTION_SPEED:
        GST_OBJECT_LOCK (dec);
 -      dec->connection_speed = g_value_get_uint (value) * 1000;
 +      dec->connection_speed = g_value_get_uint64 (value) * 1000;
        GST_OBJECT_UNLOCK (dec);
        break;
      case PROP_CAPS:
@@@ -788,7 -793,7 +790,7 @@@ gst_uri_decode_bin_get_property (GObjec
        break;
      case PROP_CONNECTION_SPEED:
        GST_OBJECT_LOCK (dec);
 -      g_value_set_uint (value, dec->connection_speed / 1000);
 +      g_value_set_uint64 (value, dec->connection_speed / 1000);
        GST_OBJECT_UNLOCK (dec);
        break;
      case PROP_CAPS:
@@@ -836,8 -841,8 +838,8 @@@ do_async_start (GstURIDecodeBin * dbin
  
    dbin->async_pending = TRUE;
  
 -  message = gst_message_new_async_start (GST_OBJECT_CAST (dbin), FALSE);
 -  parent_class->handle_message (GST_BIN_CAST (dbin), message);
 +  message = gst_message_new_async_start (GST_OBJECT_CAST (dbin));
 +  GST_BIN_CLASS (parent_class)->handle_message (GST_BIN_CAST (dbin), message);
  }
  
  static void
@@@ -847,8 -852,8 +849,8 @@@ do_async_done (GstURIDecodeBin * dbin
  
    if (dbin->async_pending) {
      GST_DEBUG_OBJECT (dbin, "posting ASYNC_DONE");
 -    message = gst_message_new_async_done (GST_OBJECT_CAST (dbin));
 -    parent_class->handle_message (GST_BIN_CAST (dbin), message);
 +    message = gst_message_new_async_done (GST_OBJECT_CAST (dbin), FALSE);
 +    GST_BIN_CLASS (parent_class)->handle_message (GST_BIN_CAST (dbin), message);
  
      dbin->async_pending = FALSE;
    }
@@@ -987,13 -992,10 +989,13 @@@ configure_stream_buffering (GstURIDecod
    gst_object_unref (queue);
  }
  
 -static gboolean
 -decoded_pad_event_probe (GstPad * pad, GstEvent * event,
 -    GstURIDecodeBin * decoder)
 +static GstPadProbeReturn
 +decoded_pad_event_probe (GstPad * pad, GstPadProbeInfo * info,
 +    gpointer user_data)
  {
 +  GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
 +  GstURIDecodeBin *decoder = user_data;
 +
    GST_LOG_OBJECT (pad, "%s, decoder %p", GST_EVENT_TYPE_NAME (event), decoder);
  
    /* look for a bitrate tag */
          if (stream) {
            stream->bitrate = bitrate;
            /* no longer need this probe now */
 -          gst_pad_remove_event_probe (pad, stream->probe_id);
 +          gst_pad_remove_probe (pad, stream->probe_id);
            /* configure buffer if possible */
            configure_stream_buffering (decoder);
          }
    }
  
    /* never drop */
 -  return TRUE;
 +  return GST_PAD_PROBE_OK;
  }
  
 -/* Called by the signal handlers when a decodebin has
 - * found a new raw pad.  
 - */
 +/* Called by the signal handlers when a decodebin has found a new raw pad */
  static void
 -new_decoded_pad_cb (GstElement * element, GstPad * pad, gboolean last,
 +new_decoded_pad_added_cb (GstElement * element, GstPad * pad,
      GstURIDecodeBin * decoder)
  {
    GstPad *newpad;
    gchar *padname;
    GstURIDecodeBinStream *stream;
  
 -  GST_DEBUG_OBJECT (element, "new decoded pad, name: <%s>. Last: %d",
 -      GST_PAD_NAME (pad), last);
 +  GST_DEBUG_OBJECT (element, "new decoded pad, name: <%s>", GST_PAD_NAME (pad));
  
    GST_URI_DECODE_BIN_LOCK (decoder);
 -  padname = g_strdup_printf ("src%d", decoder->numpads);
 +  padname = g_strdup_printf ("src_%u", decoder->numpads);
    decoder->numpads++;
    GST_URI_DECODE_BIN_UNLOCK (decoder);
  
    /* add event probe to monitor tags */
    stream = g_slice_alloc0 (sizeof (GstURIDecodeBinStream));
    stream->probe_id =
 -      gst_pad_add_event_probe (pad, G_CALLBACK (decoded_pad_event_probe),
 -      decoder);
 +      gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
 +      decoded_pad_event_probe, decoder, NULL);
    GST_URI_DECODE_BIN_LOCK (decoder);
    g_hash_table_insert (decoder->streams, pad, stream);
    GST_URI_DECODE_BIN_UNLOCK (decoder);
    gst_element_add_pad (GST_ELEMENT_CAST (decoder), newpad);
  }
  
 -static gboolean
 -source_pad_event_probe (GstPad * pad, GstEvent * event,
 -    GstURIDecodeBin * decoder)
 +static GstPadProbeReturn
 +source_pad_event_probe (GstPad * pad, GstPadProbeInfo * info,
 +    gpointer user_data)
  {
 +  GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
 +  GstURIDecodeBin *decoder = user_data;
 +
    GST_LOG_OBJECT (pad, "%s, decoder %p", GST_EVENT_TYPE_NAME (event), decoder);
  
    if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
          gst_uri_decode_bin_signals[SIGNAL_DRAINED], 0, NULL);
    }
    /* never drop events */
 -  return TRUE;
 +  return GST_PAD_PROBE_OK;
  }
  
  /* called when we found a raw pad on the source element. We need to set up a
@@@ -1095,10 -1097,9 +1097,10 @@@ static voi
  expose_decoded_pad (GstElement * element, GstPad * pad,
      GstURIDecodeBin * decoder)
  {
 -  gst_pad_add_event_probe (pad, G_CALLBACK (source_pad_event_probe), decoder);
 +  gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
 +      source_pad_event_probe, decoder, NULL);
  
 -  new_decoded_pad_cb (element, pad, FALSE, decoder);
 +  new_decoded_pad_added_cb (element, pad, decoder);
  }
  
  static void
@@@ -1198,9 -1199,7 +1200,9 @@@ static const gchar *download_media[] = 
  static GstElement *
  gen_source_element (GstURIDecodeBin * decoder)
  {
 +  GObjectClass *source_class;
    GstElement *source;
 +  GParamSpec *pspec;
  
    if (!decoder->uri)
      goto no_uri;
    decoder->need_queue = IS_QUEUE_URI (decoder->uri);
    GST_LOG_OBJECT (decoder, "source needs queue: %d", decoder->need_queue);
  
 +  source_class = G_OBJECT_GET_CLASS (source);
 +
    /* make HTTP sources send extra headers so we get icecast
     * metadata in case the stream is an icecast stream */
    if (!strncmp (decoder->uri, "http://", 7) &&
 -      g_object_class_find_property (G_OBJECT_GET_CLASS (source),
 -          "iradio-mode")) {
 +      g_object_class_find_property (source_class, "iradio-mode")) {
      GST_LOG_OBJECT (decoder, "configuring iradio-mode");
      g_object_set (source, "iradio-mode", TRUE, NULL);
    }
  
 -  if (g_object_class_find_property (G_OBJECT_GET_CLASS (source),
 -          "connection-speed")) {
 -    GST_DEBUG_OBJECT (decoder,
 -        "setting connection-speed=%d to source element",
 -        decoder->connection_speed / 1000);
 -    g_object_set (source, "connection-speed",
 -        decoder->connection_speed / 1000, NULL);
 +  pspec = g_object_class_find_property (source_class, "connection-speed");
 +  if (pspec != NULL) {
 +    if (G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_UINT64 ||
 +        G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_INT64) {
 +      GST_DEBUG_OBJECT (decoder,
 +          "setting connection-speed=%" G_GUINT64_FORMAT " on source element %s",
 +          decoder->connection_speed / 1000, G_OBJECT_TYPE_NAME (source));
 +
 +      g_object_set (source, "connection-speed",
 +          decoder->connection_speed / 1000, NULL);
 +    } else {
 +      g_warning ("connection-speed property of '%s' is not a 64-bit int type",
 +          G_OBJECT_TYPE_NAME (source));
 +    }
    }
 -  if (g_object_class_find_property (G_OBJECT_GET_CLASS (source),
 -          "subtitle-encoding")) {
 +
 +  pspec = g_object_class_find_property (source_class, "subtitle-encoding");
 +  if (pspec != NULL && G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_STRING) {
      GST_DEBUG_OBJECT (decoder,
          "setting subtitle-encoding=%s to source element", decoder->encoding);
      g_object_set (source, "subtitle-encoding", decoder->encoding, NULL);
@@@ -1318,7 -1308,7 +1320,7 @@@ has_all_raw_caps (GstPad * pad, GstCap
    gint capssize;
    gboolean res = FALSE;
  
 -  caps = gst_pad_get_caps_reffed (pad);
 +  caps = gst_pad_query_caps (pad, NULL);
    if (caps == NULL)
      return FALSE;
  
@@@ -1384,7 -1374,6 +1386,7 @@@ analyse_source (GstURIDecodeBin * decod
    gboolean res = TRUE;
    GstCaps *rawcaps;
    GstPad *pad;
 +  GValue item = { 0, };
  
    *have_out = FALSE;
    *is_raw = FALSE;
  
    pads_iter = gst_element_iterate_src_pads (decoder->source);
    while (!done) {
 -    switch (gst_iterator_next (pads_iter, (gpointer) & pad)) {
 +    switch (gst_iterator_next (pads_iter, &item)) {
        case GST_ITERATOR_ERROR:
          res = FALSE;
          /* FALLTROUGH */
          gst_iterator_resync (pads_iter);
          break;
        case GST_ITERATOR_OK:
 -        /* we now officially have an output pad */
 +        pad = g_value_get_object (&item);
 +        /* we now officially have an ouput pad */
          *have_out = TRUE;
  
          /* if FALSE, this pad has no caps and we continue with the next pad. */
          if (!has_all_raw_caps (pad, rawcaps, is_raw)) {
 -          gst_object_unref (pad);
 +          g_value_reset (&item);
            break;
          }
  
            }
            expose_decoded_pad (outelem, pad, decoder);
          }
 -        gst_object_unref (pad);
 +        g_value_reset (&item);
          break;
      }
    }
 +  g_value_unset (&item);
    gst_iterator_free (pads_iter);
    gst_caps_unref (rawcaps);
  
@@@ -1485,7 -1472,7 +1487,7 @@@ no_queue2
    {
      post_missing_plugin_error (GST_ELEMENT_CAST (decoder), "queue2");
  
 -    gst_object_unref (pad);
 +    g_value_unset (&item);
      gst_iterator_free (pads_iter);
      gst_caps_unref (rawcaps);
  
    }
  }
  
 -/* Remove all decodebin2 from ourself 
 - * If force is FALSE, then the decodebin2 instances will be stored in
 +/* Remove all decodebin from ourself
 + * If force is FALSE, then the decodebin instances will be stored in
   * pending_decodebins for re-use later on.
 - * If force is TRUE, then all decodebin2 instances will be unreferenced
 + * If force is TRUE, then all decodebin instances will be unreferenced
   * and cleared, including the pending ones. */
  static void
  remove_decoders (GstURIDecodeBin * bin, gboolean force)
    }
  
    /* Don't loose the SOURCE flag */
 -  GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_IS_SOURCE);
 +  GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_FLAG_SOURCE);
  }
  
  static void
@@@ -1629,18 -1616,18 +1631,18 @@@ make_decoder (GstURIDecodeBin * decoder
  {
    GstElement *decodebin;
  
 -  /* re-use pending decodebin2 */
 +  /* re-use pending decodebin */
    if (decoder->pending_decodebins) {
      GSList *first = decoder->pending_decodebins;
 -    GST_LOG_OBJECT (decoder, "re-using pending decodebin2");
 +    GST_LOG_OBJECT (decoder, "re-using pending decodebin");
      decodebin = (GstElement *) first->data;
      decoder->pending_decodebins =
          g_slist_delete_link (decoder->pending_decodebins, first);
    } else {
 -    GST_LOG_OBJECT (decoder, "making new decodebin2");
 +    GST_LOG_OBJECT (decoder, "making new decodebin");
  
      /* now create the decoder element */
 -    decodebin = gst_element_factory_make ("decodebin2", NULL);
 +    decodebin = gst_element_factory_make ("decodebin", NULL);
  
      if (!decodebin)
        goto no_decodebin;
      /* set up callbacks to create the links between decoded data
       * and video/audio/subtitle rendering/output. */
      g_signal_connect (decodebin,
 -        "new-decoded-pad", G_CALLBACK (new_decoded_pad_cb), decoder);
 +        "pad-added", G_CALLBACK (new_decoded_pad_added_cb), decoder);
      g_signal_connect (decodebin,
          "pad-removed", G_CALLBACK (pad_removed_cb), decoder);
      g_signal_connect (decodebin, "no-more-pads",
    /* ERRORS */
  no_decodebin:
    {
 -    post_missing_plugin_error (GST_ELEMENT_CAST (decoder), "decodebin2");
 +    post_missing_plugin_error (GST_ELEMENT_CAST (decoder), "decodebin");
      GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN, (NULL),
 -        ("No decodebin2 element, check your installation"));
 +        ("No decodebin element, check your installation"));
      return NULL;
    }
  no_typefind:
    {
      gst_object_unref (decodebin);
      GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN, (NULL),
 -        ("No typefind element, decodebin2 is unusable, check your installation"));
 +        ("No typefind element, decodebin is unusable, check your installation"));
      return NULL;
    }
  }
@@@ -1751,11 -1738,11 +1753,11 @@@ type_found (GstElement * typefind, guin
    decoder->is_download = IS_DOWNLOAD_MEDIA (media_type) && decoder->download;
    /* only enable download buffering if the upstream duration is known */
    if (decoder->is_download) {
 -    GstFormat fmt = GST_FORMAT_BYTES;
      gint64 dur;
  
 -    decoder->is_download = (gst_element_query_duration (typefind, &fmt, &dur)
 -        && fmt == GST_FORMAT_BYTES && dur != -1);
 +    decoder->is_download =
 +        (gst_element_query_duration (typefind, GST_FORMAT_BYTES, &dur)
 +        && dur != -1);
    }
  
    dec_elem = make_decoder (decoder);
@@@ -1837,7 -1824,7 +1839,7 @@@ no_decodebin
  could_not_link:
    {
      GST_ELEMENT_ERROR (decoder, CORE, NEGOTIATION,
 -        (NULL), ("Can't link typefind to decodebin2 element"));
 +        (NULL), ("Can't link typefind to decodebin element"));
      return;
    }
  no_queue2:
  
  /* setup a streaming source. This will first plug a typefind element to the
   * source. After we find the type, we decide to plug a queue2 and continue to
 - * plug a decodebin2 starting from the found caps */
 + * plug a decodebin starting from the found caps */
  static gboolean
  setup_streaming (GstURIDecodeBin * decoder)
  {
@@@ -1891,7 -1878,7 +1893,7 @@@ could_not_link
          (NULL), ("Can't link source to typefind element"));
      gst_bin_remove (GST_BIN_CAST (decoder), typefind);
      /* Don't loose the SOURCE flag */
 -    GST_OBJECT_FLAG_SET (decoder, GST_ELEMENT_IS_SOURCE);
 +    GST_OBJECT_FLAG_SET (decoder, GST_ELEMENT_FLAG_SOURCE);
      return FALSE;
    }
  }
@@@ -1940,7 -1927,7 +1942,7 @@@ remove_source (GstURIDecodeBin * bin
      bin->streams = NULL;
    }
    /* Don't loose the SOURCE flag */
 -  GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_IS_SOURCE);
 +  GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_FLAG_SOURCE);
  }
  
  /* is called when a dynamic source element created a new pad. */
@@@ -2153,17 -2140,14 +2155,17 @@@ handle_redirect_message (GstURIDecodeBi
    GList *l_good = NULL, *l_neutral = NULL, *l_bad = NULL;
    GValue new_list = { 0, };
    guint size, i;
 +  const GstStructure *structure;
  
    GST_DEBUG_OBJECT (dec, "redirect message: %" GST_PTR_FORMAT, msg);
 -  GST_DEBUG_OBJECT (dec, "connection speed: %u", dec->connection_speed);
 +  GST_DEBUG_OBJECT (dec, "connection speed: %" G_GUINT64_FORMAT,
 +      dec->connection_speed);
  
 -  if (dec->connection_speed == 0 || msg->structure == NULL)
 +  structure = gst_message_get_structure (msg);
 +  if (dec->connection_speed == 0 || structure == NULL)
      return msg;
  
 -  locations_list = gst_structure_get_value (msg->structure, "locations");
 +  locations_list = gst_structure_get_value (structure, "locations");
    if (locations_list == NULL)
      return msg;
  
  static void
  handle_message (GstBin * bin, GstMessage * msg)
  {
 -  if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ELEMENT && msg->structure != NULL
 -      && gst_structure_has_name (msg->structure, "redirect")) {
 +  if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ELEMENT
 +      && gst_message_has_name (msg, "redirect")) {
      /* sort redirect messages based on the connection speed. This simplifies
       * the user of this element as it can in most cases just pick the first item
       * of the sorted list as a good redirection candidate. It can of course
@@@ -2253,12 -2237,9 +2255,12 @@@ decoder_query_init (GstURIDecodeBin * d
  }
  
  static gboolean
 -decoder_query_duration_fold (GstPad * item, GValue * ret, QueryFold * fold)
 +decoder_query_duration_fold (const GValue * item, GValue * ret,
 +    QueryFold * fold)
  {
 -  if (gst_pad_query (item, fold->query)) {
 +  GstPad *pad = g_value_get_object (item);
 +
 +  if (gst_pad_query (pad, fold->query)) {
      gint64 duration;
  
      g_value_set_boolean (ret, TRUE);
      if (duration > fold->max)
        fold->max = duration;
    }
 -  gst_object_unref (item);
    return TRUE;
  }
  
@@@ -2286,12 -2268,9 +2288,12 @@@ decoder_query_duration_done (GstURIDeco
  }
  
  static gboolean
 -decoder_query_position_fold (GstPad * item, GValue * ret, QueryFold * fold)
 +decoder_query_position_fold (const GValue * item, GValue * ret,
 +    QueryFold * fold)
  {
 -  if (gst_pad_query (item, fold->query)) {
 +  GstPad *pad = g_value_get_object (item);
 +
 +  if (gst_pad_query (pad, fold->query)) {
      gint64 position;
  
      g_value_set_boolean (ret, TRUE);
        fold->max = position;
    }
  
 -  gst_object_unref (item);
    return TRUE;
  }
  
@@@ -2320,11 -2300,9 +2322,11 @@@ decoder_query_position_done (GstURIDeco
  }
  
  static gboolean
 -decoder_query_latency_fold (GstPad * item, GValue * ret, QueryFold * fold)
 +decoder_query_latency_fold (const GValue * item, GValue * ret, QueryFold * fold)
  {
 -  if (gst_pad_query (item, fold->query)) {
 +  GstPad *pad = g_value_get_object (item);
 +
 +  if (gst_pad_query (pad, fold->query)) {
      GstClockTime min, max;
      gboolean live;
  
        fold->live = live;
    }
  
 -  gst_object_unref (item);
    return TRUE;
  }
  
@@@ -2365,11 -2344,9 +2367,11 @@@ decoder_query_latency_done (GstURIDecod
  
  /* we are seekable if all srcpads are seekable */
  static gboolean
 -decoder_query_seeking_fold (GstPad * item, GValue * ret, QueryFold * fold)
 +decoder_query_seeking_fold (const GValue * item, GValue * ret, QueryFold * fold)
  {
 -  if (gst_pad_query (item, fold->query)) {
 +  GstPad *pad = g_value_get_object (item);
 +
 +  if (gst_pad_query (pad, fold->query)) {
      gboolean seekable;
  
      g_value_set_boolean (ret, TRUE);
      if (fold->seekable == TRUE)
        fold->seekable = seekable;
    }
 -  gst_object_unref (item);
  
    return TRUE;
  }
@@@ -2397,16 -2375,17 +2399,16 @@@ decoder_query_seeking_done (GstURIDecod
  
  /* generic fold, return first valid result */
  static gboolean
 -decoder_query_generic_fold (GstPad * item, GValue * ret, QueryFold * fold)
 +decoder_query_generic_fold (const GValue * item, GValue * ret, QueryFold * fold)
  {
 +  GstPad *pad = g_value_get_object (item);
    gboolean res;
  
 -  if ((res = gst_pad_query (item, fold->query))) {
 +  if ((res = gst_pad_query (pad, fold->query))) {
      g_value_set_boolean (ret, TRUE);
      GST_DEBUG_OBJECT (item, "answered query %p", fold->query);
    }
  
 -  gst_object_unref (item);
 -
    /* and stop as soon as we have a valid result */
    return !res;
  }
@@@ -2554,12 -2533,38 +2556,12 @@@ setup_failed
    }
  }
  
 -gboolean gst_decode_bin_plugin_init (GstPlugin * plugin);
 -
 -static gboolean
 +gboolean
  gst_uri_decode_bin_plugin_init (GstPlugin * plugin)
  {
    GST_DEBUG_CATEGORY_INIT (gst_uri_decode_bin_debug, "uridecodebin", 0,
        "URI decoder element");
  
 -#ifdef ENABLE_NLS
 -  GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
 -      LOCALEDIR);
 -  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
 -  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 -#endif /* ENABLE_NLS */
 -
    return gst_element_register (plugin, "uridecodebin", GST_RANK_NONE,
        GST_TYPE_URI_DECODE_BIN);
  }
 -
 -static gboolean
 -plugin_init (GstPlugin * plugin)
 -{
 -  if (!gst_decode_bin_plugin_init (plugin))
 -    return FALSE;
 -  if (!gst_uri_decode_bin_plugin_init (plugin))
 -    return FALSE;
 -
 -  return TRUE;
 -}
 -
 -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
 -    GST_VERSION_MINOR,
 -    "uridecodebin",
 -    "URI Decoder bin", plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME,
 -    GST_PACKAGE_ORIGIN)
diff --combined gst/tcp/gstmultifdsink.c
  #ifdef HAVE_CONFIG_H
  #include "config.h"
  #endif
+ /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+  * with newer GLib versions (>= 2.31.0) */
+ #define GLIB_DISABLE_DEPRECATION_WARNINGS
  #include <gst/gst-i18n-plugin.h>
  
  #include <sys/ioctl.h>
@@@ -153,6 -158,7 +158,6 @@@ enu
  
  
  /* this is really arbitrarily chosen */
 -#define DEFAULT_PROTOCOL                GST_TCP_PROTOCOL_NONE
  #define DEFAULT_MODE                    1
  #define DEFAULT_BUFFERS_MAX             -1
  #define DEFAULT_BUFFERS_SOFT_MAX        -1
  enum
  {
    PROP_0,
 -  PROP_PROTOCOL,
    PROP_MODE,
    PROP_BUFFERS_QUEUED,
    PROP_BYTES_QUEUED,
@@@ -343,12 -350,26 +348,12 @@@ static void gst_multi_fd_sink_set_prope
  static void gst_multi_fd_sink_get_property (GObject * object, guint prop_id,
      GValue * value, GParamSpec * pspec);
  
 -GST_BOILERPLATE (GstMultiFdSink, gst_multi_fd_sink, GstBaseSink,
 -    GST_TYPE_BASE_SINK);
 +#define gst_multi_fd_sink_parent_class parent_class
 +G_DEFINE_TYPE (GstMultiFdSink, gst_multi_fd_sink, GST_TYPE_BASE_SINK);
  
  static guint gst_multi_fd_sink_signals[LAST_SIGNAL] = { 0 };
  
  static void
 -gst_multi_fd_sink_base_init (gpointer g_class)
 -{
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 -
 -  gst_element_class_add_static_pad_template (element_class, &sinktemplate);
 -
 -  gst_element_class_set_details_simple (element_class,
 -      "Multi filedescriptor sink", "Sink/Network",
 -      "Send data to multiple filedescriptors",
 -      "Thomas Vander Stichele <thomas at apestaart dot org>, "
 -      "Wim Taymans <wim@fluendo.com>");
 -}
 -
 -static void
  gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
  {
    GObjectClass *gobject_class;
    gobject_class->get_property = gst_multi_fd_sink_get_property;
    gobject_class->finalize = gst_multi_fd_sink_finalize;
  
 -  g_object_class_install_property (gobject_class, PROP_PROTOCOL,
 -      g_param_spec_enum ("protocol", "Protocol", "The protocol to wrap data in"
 -          ". GDP protocol here is deprecated. Please use gdppay element.",
 -          GST_TYPE_TCP_PROTOCOL, DEFAULT_PROTOCOL,
 -          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 -
    /**
     * GstMultiFdSink::mode
     *
            client_fd_removed), NULL, NULL, gst_tcp_marshal_VOID__INT,
        G_TYPE_NONE, 1, G_TYPE_INT);
  
 +  gst_element_class_add_pad_template (gstelement_class,
 +      gst_static_pad_template_get (&sinktemplate));
 +
 +  gst_element_class_set_details_simple (gstelement_class,
 +      "Multi filedescriptor sink", "Sink/Network",
 +      "Send data to multiple filedescriptors",
 +      "Thomas Vander Stichele <thomas at apestaart dot org>, "
 +      "Wim Taymans <wim@fluendo.com>");
 +
    gstelement_class->change_state =
        GST_DEBUG_FUNCPTR (gst_multi_fd_sink_change_state);
  
  }
  
  static void
 -gst_multi_fd_sink_init (GstMultiFdSink * this, GstMultiFdSinkClass * klass)
 +gst_multi_fd_sink_init (GstMultiFdSink * this)
  {
    GST_OBJECT_FLAG_UNSET (this, GST_MULTI_FD_SINK_OPEN);
  
 -  this->protocol = DEFAULT_PROTOCOL;
    this->mode = DEFAULT_MODE;
  
    CLIENTS_LOCK_INIT (this);
@@@ -1279,6 -1298,60 +1284,6 @@@ ioctl_failed
    }
  }
  
 -/* Queue raw data for this client, creating a new buffer.
 - * This takes ownership of the data by
 - * setting it as GST_BUFFER_MALLOCDATA() on the created buffer so
 - * be sure to pass g_free()-able @data.
 - */
 -static gboolean
 -gst_multi_fd_sink_client_queue_data (GstMultiFdSink * sink,
 -    GstTCPClient * client, gchar * data, gint len)
 -{
 -  GstBuffer *buf;
 -
 -  buf = gst_buffer_new ();
 -  GST_BUFFER_DATA (buf) = (guint8 *) data;
 -  GST_BUFFER_MALLOCDATA (buf) = (guint8 *) data;
 -  GST_BUFFER_SIZE (buf) = len;
 -
 -  GST_LOG_OBJECT (sink, "[fd %5d] queueing data of length %d",
 -      client->fd.fd, len);
 -
 -  client->sending = g_slist_append (client->sending, buf);
 -
 -  return TRUE;
 -}
 -
 -/* GDP-encode given caps and queue them for sending */
 -static gboolean
 -gst_multi_fd_sink_client_queue_caps (GstMultiFdSink * sink,
 -    GstTCPClient * client, const GstCaps * caps)
 -{
 -  guint8 *header;
 -  guint8 *payload;
 -  guint length;
 -  gchar *string;
 -
 -  g_return_val_if_fail (caps != NULL, FALSE);
 -
 -  string = gst_caps_to_string (caps);
 -  GST_DEBUG_OBJECT (sink, "[fd %5d] Queueing caps %s through GDP",
 -      client->fd.fd, string);
 -  g_free (string);
 -
 -  if (!gst_dp_packet_from_caps (caps, sink->header_flags, &length, &header,
 -          &payload)) {
 -    GST_DEBUG_OBJECT (sink, "Could not create GDP packet from caps");
 -    return FALSE;
 -  }
 -  gst_multi_fd_sink_client_queue_data (sink, client, (gchar *) header, length);
 -
 -  length = gst_dp_header_payload_length (header);
 -  gst_multi_fd_sink_client_queue_data (sink, client, (gchar *) payload, length);
 -
 -  return TRUE;
 -}
 -
  static gboolean
  is_sync_frame (GstMultiFdSink * sink, GstBuffer * buffer)
  {
@@@ -1303,13 -1376,9 +1308,13 @@@ gst_multi_fd_sink_client_queue_buffer (
    gboolean send_streamheader = FALSE;
    GstStructure *s;
  
 +#if 0
    /* before we queue the buffer, we check if we need to queue streamheader
     * buffers (because it's a new client, or because they changed) */
    caps = gst_buffer_get_caps (buffer);  /* cleaned up after streamheader */
 +#else
 +  caps = NULL;
 +#endif
    if (!client->caps) {
      GST_DEBUG_OBJECT (sink,
          "[fd %5d] no previous caps for this client, send streamheader",
          g_assert (G_VALUE_TYPE (bufval) == GST_TYPE_BUFFER);
          buffer = g_value_peek_pointer (bufval);
          GST_DEBUG_OBJECT (sink,
 -            "[fd %5d] queueing streamheader buffer of length %d",
 -            client->fd.fd, GST_BUFFER_SIZE (buffer));
 +            "[fd %5d] queueing streamheader buffer of length %" G_GSIZE_FORMAT,
 +            client->fd.fd, gst_buffer_get_size (buffer));
          gst_buffer_ref (buffer);
  
 -        if (sink->protocol == GST_TCP_PROTOCOL_GDP) {
 -          guint8 *header;
 -          guint len;
 -
 -          if (!gst_dp_header_from_buffer (buffer, sink->header_flags, &len,
 -                  &header)) {
 -            GST_DEBUG_OBJECT (sink,
 -                "[fd %5d] could not create header, removing client",
 -                client->fd.fd);
 -            return FALSE;
 -          }
 -          gst_multi_fd_sink_client_queue_data (sink, client, (gchar *) header,
 -              len);
 -        }
 -
          client->sending = g_slist_append (client->sending, buffer);
        }
      }
  
    gst_caps_unref (caps);
    caps = NULL;
 -  /* now we can send the buffer, possibly sending a GDP header first */
 -  if (sink->protocol == GST_TCP_PROTOCOL_GDP) {
 -    guint8 *header;
 -    guint len;
  
 -    if (!gst_dp_header_from_buffer (buffer, sink->header_flags, &len, &header)) {
 -      GST_DEBUG_OBJECT (sink,
 -          "[fd %5d] could not create header, removing client", client->fd.fd);
 -      return FALSE;
 -    }
 -    gst_multi_fd_sink_client_queue_data (sink, client, (gchar *) header, len);
 -  }
 -
 -  GST_LOG_OBJECT (sink, "[fd %5d] queueing buffer of length %d",
 -      client->fd.fd, GST_BUFFER_SIZE (buffer));
 +  GST_LOG_OBJECT (sink, "[fd %5d] queueing buffer of length %" G_GSIZE_FORMAT,
 +      client->fd.fd, gst_buffer_get_size (buffer));
  
    gst_buffer_ref (buffer);
    client->sending = g_slist_append (client->sending, buffer);
@@@ -1491,7 -1587,7 +1496,7 @@@ get_buffers_max (GstMultiFdSink * sink
  
        for (i = 0; i < len; i++) {
          buf = g_array_index (sink->bufqueue, GstBuffer *, i);
 -        acc += GST_BUFFER_SIZE (buf);
 +        acc += gst_buffer_get_size (buf);
  
          if (acc > max)
            return i + 1;
@@@ -1574,7 -1670,7 +1579,7 @@@ find_limits (GstMultiFdSink * sink
      }
      buf = g_array_index (sink->bufqueue, GstBuffer *, i);
  
 -    bytes += GST_BUFFER_SIZE (buf);
 +    bytes += gst_buffer_get_size (buf);
  
      /* take timestamp and save for the base first timestamp */
      if ((time = GST_BUFFER_TIMESTAMP (buf)) != -1) {
@@@ -1900,6 -1996,7 +1905,6 @@@ gst_multi_fd_sink_handle_client_write (
  {
    int fd = client->fd.fd;
    gboolean more;
 -  gboolean res;
    gboolean flushing;
    GstClockTime now;
    GTimeVal nowtv;
  
    flushing = client->status == GST_CLIENT_STATUS_FLUSHING;
  
 -  /* when using GDP, first check if we have queued caps yet */
 -  if (sink->protocol == GST_TCP_PROTOCOL_GDP) {
 -    /* don't need to do anything when the client is flushing */
 -    if (!client->caps_sent && !flushing) {
 -      GstPad *peer;
 -      GstCaps *caps;
 -
 -      peer = gst_pad_get_peer (GST_BASE_SINK_PAD (sink));
 -      if (!peer) {
 -        GST_WARNING_OBJECT (sink, "pad has no peer");
 -        return FALSE;
 -      }
 -      gst_object_unref (peer);
 -
 -      caps = gst_pad_get_negotiated_caps (GST_BASE_SINK_PAD (sink));
 -      if (!caps) {
 -        GST_WARNING_OBJECT (sink, "pad caps not yet negotiated");
 -        return FALSE;
 -      }
 -
 -      /* queue caps for sending */
 -      res = gst_multi_fd_sink_client_queue_caps (sink, client, caps);
 -
 -      gst_caps_unref (caps);
 -
 -      if (!res) {
 -        GST_DEBUG_OBJECT (sink, "Failed queueing caps, removing client");
 -        return FALSE;
 -      }
 -      client->caps_sent = TRUE;
 -    }
 -  }
 -
    more = TRUE;
    do {
      gint maxsize;
      if (client->sending) {
        ssize_t wrote;
        GstBuffer *head;
 +      guint8 *data;
 +      gsize size;
  
        /* pick first buffer from list */
        head = GST_BUFFER (client->sending->data);
 -      maxsize = GST_BUFFER_SIZE (head) - client->bufoffset;
 +
 +      data = gst_buffer_map (head, &size, NULL, GST_MAP_READ);
 +      maxsize = size - client->bufoffset;
  
        /* try to write the complete buffer */
  #ifdef MSG_NOSIGNAL
  #define FLAGS 0
  #endif
        if (client->is_socket) {
 -        wrote =
 -            send (fd, GST_BUFFER_DATA (head) + client->bufoffset, maxsize,
 -            FLAGS);
 +        wrote = send (fd, data + client->bufoffset, maxsize, FLAGS);
        } else {
 -        wrote = write (fd, GST_BUFFER_DATA (head) + client->bufoffset, maxsize);
 +        wrote = write (fd, data + client->bufoffset, maxsize);
        }
 +      gst_buffer_unmap (head, data, size);
  
        if (wrote < 0) {
          /* hmm error.. */
@@@ -2480,16 -2607,13 +2485,16 @@@ gst_multi_fd_sink_render (GstBaseSink 
  {
    GstMultiFdSink *sink;
    gboolean in_caps;
 +#if 0
    GstCaps *bufcaps, *padcaps;
 +#endif
  
    sink = GST_MULTI_FD_SINK (bsink);
  
    g_return_val_if_fail (GST_OBJECT_FLAG_IS_SET (sink, GST_MULTI_FD_SINK_OPEN),
        GST_FLOW_WRONG_STATE);
  
 +#if 0
    /* since we check every buffer for streamheader caps, we need to make
     * sure every buffer has caps set */
    bufcaps = gst_buffer_get_caps (buf);
    /* make sure we have caps on the pad */
    if (!padcaps && !bufcaps)
      goto no_caps;
 +#endif
  
    /* get IN_CAPS first, code below might mess with the flags */
    in_caps = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
  
 +#if 0
    /* stamp the buffer with previous caps if no caps set */
    if (!bufcaps) {
 -    if (!gst_buffer_is_metadata_writable (buf)) {
 +    if (!gst_buffer_is_writable (buf)) {
        /* metadata is not writable, copy will be made and original buffer
         * will be unreffed so we need to ref so that we don't lose the
         * buffer in the render method. */
        gst_buffer_ref (buf);
        /* the new buffer is ours only, we keep it out of the scope of this
         * function */
 -      buf = gst_buffer_make_metadata_writable (buf);
 +      buf = gst_buffer_make_writable (buf);
      } else {
        /* else the metadata is writable, we ref because we keep the buffer
         * out of the scope of this method */
      /* since we keep this buffer out of the scope of this method */
      gst_buffer_ref (buf);
    }
 +#endif
  
    GST_LOG_OBJECT (sink, "received buffer %p, in_caps: %s, offset %"
        G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT
     * We don't send the buffer to the client, since streamheaders are sent
     * separately when necessary. */
    if (in_caps) {
 -    GST_DEBUG_OBJECT (sink,
 -        "appending IN_CAPS buffer with length %d to streamheader",
 -        GST_BUFFER_SIZE (buf));
 +    GST_DEBUG_OBJECT (sink, "appending IN_CAPS buffer with length %"
 +        G_GSIZE_FORMAT " to streamheader", gst_buffer_get_size (buf));
      sink->streamheader = g_slist_append (sink->streamheader, buf);
    } else {
      /* queue the buffer, this is a regular data buffer. */
      gst_multi_fd_sink_queue_buffer (sink, buf);
  
 -    sink->bytes_to_serve += GST_BUFFER_SIZE (buf);
 +    sink->bytes_to_serve += gst_buffer_get_size (buf);
    }
    return GST_FLOW_OK;
  
    /* ERRORS */
 +#if 0
  no_caps:
    {
      GST_ELEMENT_ERROR (sink, CORE, NEGOTIATION, (NULL),
          ("Received first buffer without caps set"));
      return GST_FLOW_NOT_NEGOTIATED;
    }
 +#endif
  }
  
  static void
@@@ -2591,6 -2711,9 +2596,6 @@@ gst_multi_fd_sink_set_property (GObjec
    multifdsink = GST_MULTI_FD_SINK (object);
  
    switch (prop_id) {
 -    case PROP_PROTOCOL:
 -      multifdsink->protocol = g_value_get_enum (value);
 -      break;
      case PROP_MODE:
        multifdsink->mode = g_value_get_enum (value);
        break;
@@@ -2659,6 -2782,9 +2664,6 @@@ gst_multi_fd_sink_get_property (GObjec
    multifdsink = GST_MULTI_FD_SINK (object);
  
    switch (prop_id) {
 -    case PROP_PROTOCOL:
 -      g_value_set_enum (value, multifdsink->protocol);
 -      break;
      case PROP_MODE:
        g_value_set_enum (value, multifdsink->mode);
        break;
@@@ -2762,8 -2888,14 +2767,14 @@@ gst_multi_fd_sink_start (GstBaseSink * 
    }
  
    this->running = TRUE;
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
    this->thread = g_thread_create ((GThreadFunc) gst_multi_fd_sink_thread,
        this, TRUE, NULL);
+ #else
+   this->thread = g_thread_new ("multifdsink",
+       (GThreadFunc) gst_multi_fd_sink_thread, this);
+ #endif
  
    GST_OBJECT_FLAG_SET (this, GST_MULTI_FD_SINK_OPEN);
  
   * <refsect2>
   * <title>Example pipelines</title>
   * |[
 - * gst-launch -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! videorate ! video/x-raw-yuv,framerate=15/1 ! xvimagesink
 + * gst-launch -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! videorate ! video/x-raw,framerate=15/1 ! xvimagesink
   * ]| Decode an Ogg/Theora file and adjust the framerate to 15 fps before playing.
   * To create the test Ogg/Theora file refer to the documentation of theoraenc.
   * |[
 - * gst-launch -v v4lsrc ! videorate ! video/x-raw-yuv,framerate=25/2 ! theoraenc ! oggmux ! filesink location=v4l.ogg
 + * gst-launch -v v4l2src ! videorate ! video/x-raw,framerate=25/2 ! theoraenc ! oggmux ! filesink location=recording.ogg
   * ]| Capture video from a V4L device, and adjust the stream to 12.5 fps before
   * encoding to Ogg/Theora.
   * </refsect2>
@@@ -89,6 -89,8 +89,6 @@@ enu
  #define DEFAULT_DROP_ONLY       FALSE
  #define DEFAULT_AVERAGE_PERIOD  0
  #define DEFAULT_MAX_RATE        G_MAXINT
 -#define DEFAULT_FORCE_FPS_N     -1
 -#define DEFAULT_FORCE_FPS_D     1
  
  enum
  {
    PROP_SKIP_TO_FIRST,
    PROP_DROP_ONLY,
    PROP_AVERAGE_PERIOD,
 -  PROP_MAX_RATE,
 -  PROP_FORCE_FPS
 -      /* FILL ME */
 +  PROP_MAX_RATE
  };
  
  static GstStaticPadTemplate gst_video_rate_src_template =
      GST_STATIC_PAD_TEMPLATE ("src",
      GST_PAD_SRC,
      GST_PAD_ALWAYS,
 -    GST_STATIC_CAPS ("video/x-raw-yuv;"
 -        "video/x-raw-rgb;" "video/x-raw-gray;" "image/jpeg;" "image/png")
 +    GST_STATIC_CAPS ("video/x-raw;" "image/jpeg;" "image/png")
      );
  
  static GstStaticPadTemplate gst_video_rate_sink_template =
      GST_STATIC_PAD_TEMPLATE ("sink",
      GST_PAD_SINK,
      GST_PAD_ALWAYS,
 -    GST_STATIC_CAPS ("video/x-raw-yuv;"
 -        "video/x-raw-rgb;" "video/x-raw-gray;" "image/jpeg;" "image/png")
 +    GST_STATIC_CAPS ("video/x-raw;" "image/jpeg;" "image/png")
      );
  
  static void gst_video_rate_swap_prev (GstVideoRate * videorate,
      GstBuffer * buffer, gint64 time);
 -static gboolean gst_video_rate_event (GstBaseTransform * trans,
 +static gboolean gst_video_rate_sink_event (GstBaseTransform * trans,
      GstEvent * event);
  static gboolean gst_video_rate_query (GstBaseTransform * trans,
      GstPadDirection direction, GstQuery * query);
@@@ -130,15 -136,18 +130,16 @@@ static gboolean gst_video_rate_setcaps 
      GstCaps * in_caps, GstCaps * out_caps);
  
  static GstCaps *gst_video_rate_transform_caps (GstBaseTransform * trans,
 -    GstPadDirection direction, GstCaps * caps);
 +    GstPadDirection direction, GstCaps * caps, GstCaps * filter);
  
  static void gst_video_rate_fixate_caps (GstBaseTransform * trans,
      GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
  
 -static GstFlowReturn gst_video_rate_prepare_output_buffer (GstBaseTransform *
 -    trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf);
  static GstFlowReturn gst_video_rate_transform_ip (GstBaseTransform * trans,
      GstBuffer * buf);
  
  static gboolean gst_video_rate_start (GstBaseTransform * trans);
+ static gboolean gst_video_rate_stop (GstBaseTransform * trans);
  
  
  static void gst_video_rate_set_property (GObject * object,
@@@ -149,16 -158,33 +150,16 @@@ static void gst_video_rate_get_propert
  static GParamSpec *pspec_drop = NULL;
  static GParamSpec *pspec_duplicate = NULL;
  
 -GST_BOILERPLATE (GstVideoRate, gst_video_rate,
 -    GstBaseTransform, GST_TYPE_BASE_TRANSFORM);
 -
 -static void
 -gst_video_rate_base_init (gpointer g_class)
 -{
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 -
 -  gst_element_class_set_details_simple (element_class,
 -      "Video rate adjuster", "Filter/Effect/Video",
 -      "Drops/duplicates/adjusts timestamps on video frames to make a perfect stream",
 -      "Wim Taymans <wim@fluendo.com>");
 -
 -  gst_element_class_add_static_pad_template (element_class,
 -      &gst_video_rate_sink_template);
 -  gst_element_class_add_static_pad_template (element_class,
 -      &gst_video_rate_src_template);
 -}
 +#define gst_video_rate_parent_class parent_class
 +G_DEFINE_TYPE (GstVideoRate, gst_video_rate, GST_TYPE_BASE_TRANSFORM);
  
  static void
  gst_video_rate_class_init (GstVideoRateClass * klass)
  {
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
 +  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
    GstBaseTransformClass *base_class = GST_BASE_TRANSFORM_CLASS (klass);
  
 -  parent_class = g_type_class_peek_parent (klass);
 -
    object_class->set_property = gst_video_rate_set_property;
    object_class->get_property = gst_video_rate_get_property;
  
    base_class->transform_caps =
        GST_DEBUG_FUNCPTR (gst_video_rate_transform_caps);
    base_class->transform_ip = GST_DEBUG_FUNCPTR (gst_video_rate_transform_ip);
 -  base_class->prepare_output_buffer =
 -      GST_DEBUG_FUNCPTR (gst_video_rate_prepare_output_buffer);
 -  base_class->event = GST_DEBUG_FUNCPTR (gst_video_rate_event);
 +  base_class->sink_event = GST_DEBUG_FUNCPTR (gst_video_rate_sink_event);
    base_class->start = GST_DEBUG_FUNCPTR (gst_video_rate_start);
+   base_class->stop = GST_DEBUG_FUNCPTR (gst_video_rate_stop);
    base_class->fixate_caps = GST_DEBUG_FUNCPTR (gst_video_rate_fixate_caps);
    base_class->query = GST_DEBUG_FUNCPTR (gst_video_rate_query);
  
            1, G_MAXINT, DEFAULT_MAX_RATE,
            G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
  
 -  /**
 -   * GstVideoRate:force-fps:
 -   *
 -   * Forced output framerate
 -   *
 -   * Since: 0.10.36
 -   */
 -  g_object_class_install_property (object_class, PROP_FORCE_FPS,
 -      gst_param_spec_fraction ("force-fps", "Force output framerate",
 -          "Force output framerate (negative means negotiate via caps)",
 -          -1, 1, G_MAXINT, 1, DEFAULT_FORCE_FPS_N, DEFAULT_FORCE_FPS_D,
 -          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
 +  gst_element_class_set_details_simple (element_class,
 +      "Video rate adjuster", "Filter/Effect/Video",
 +      "Drops/duplicates/adjusts timestamps on video frames to make a perfect stream",
 +      "Wim Taymans <wim@fluendo.com>");
 +
 +  gst_element_class_add_pad_template (element_class,
 +      gst_static_pad_template_get (&gst_video_rate_sink_template));
 +  gst_element_class_add_pad_template (element_class,
 +      gst_static_pad_template_get (&gst_video_rate_src_template));
  }
  
  static void
@@@ -359,7 -391,7 +361,7 @@@ out
  
  static GstCaps *
  gst_video_rate_transform_caps (GstBaseTransform * trans,
 -    GstPadDirection direction, GstCaps * caps)
 +    GstPadDirection direction, GstCaps * caps, GstCaps * filter)
  {
    GstVideoRate *videorate = GST_VIDEO_RATE (trans);
    GstCaps *ret;
    s = gst_caps_get_structure (ret, 0);
    s2 = gst_structure_copy (s);
  
 -  if (videorate->force_fps_n >= 0 && videorate->force_fps_d >= 0) {
 -    if (direction == GST_PAD_SINK) {
 -      gst_caps_remove_structure (ret, 0);
 -      gst_structure_set (s2, "framerate", GST_TYPE_FRACTION,
 -          videorate->force_fps_n, videorate->force_fps_d, NULL);
 -    } else {
 -      gst_structure_set (s2, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1,
 -          G_MAXINT, 1, NULL);
 -    }
 -  } else if (videorate->drop_only) {
 +  if (videorate->drop_only) {
      gint min_num = 0, min_denom = 1;
      gint max_num = G_MAXINT, max_denom = 1;
  
@@@ -459,7 -500,7 +461,7 @@@ static gboolea
  gst_video_rate_setcaps (GstBaseTransform * trans, GstCaps * in_caps,
      GstCaps * out_caps)
  {
 -  GstVideoRate *videorate;
 +  GstVideoRate *videorate = GST_VIDEO_RATE (trans);
    GstStructure *structure;
    gboolean ret = TRUE;
    gint rate_numerator, rate_denominator;
@@@ -540,7 -581,7 +542,7 @@@ gst_video_rate_reset (GstVideoRate * vi
  }
  
  static void
 -gst_video_rate_init (GstVideoRate * videorate, GstVideoRateClass * klass)
 +gst_video_rate_init (GstVideoRate * videorate)
  {
    gst_video_rate_reset (videorate);
    videorate->silent = DEFAULT_SILENT;
    videorate->average_period = DEFAULT_AVERAGE_PERIOD;
    videorate->average_period_set = DEFAULT_AVERAGE_PERIOD;
    videorate->max_rate = DEFAULT_MAX_RATE;
 -  videorate->force_fps_n = DEFAULT_FORCE_FPS_N;
 -  videorate->force_fps_d = DEFAULT_FORCE_FPS_D;
  
    videorate->from_rate_numerator = 0;
    videorate->from_rate_denominator = 0;
@@@ -570,7 -613,8 +572,7 @@@ gst_video_rate_flush_prev (GstVideoRat
      goto eos_before_buffers;
  
    /* make sure we can write to the metadata */
 -  outbuf = gst_buffer_make_metadata_writable
 -      (gst_buffer_ref (videorate->prevbuf));
 +  outbuf = gst_buffer_make_writable (gst_buffer_ref (videorate->prevbuf));
  
    GST_BUFFER_OFFSET (outbuf) = videorate->out;
    GST_BUFFER_OFFSET_END (outbuf) = videorate->out + 1;
    if (videorate->to_rate_numerator) {
      /* interpolate next expected timestamp in the segment */
      videorate->next_ts =
 -        videorate->segment.accum + videorate->segment.start +
 +        videorate->segment.base + videorate->segment.start +
          videorate->base_ts + gst_util_uint64_scale (videorate->out_frame_count,
          videorate->to_rate_denominator * GST_SECOND,
          videorate->to_rate_numerator);
    /* We do not need to update time in VFR (variable frame rate) mode */
    if (!videorate->drop_only) {
      /* adapt for looping, bring back to time in current segment. */
 -    GST_BUFFER_TIMESTAMP (outbuf) = push_ts - videorate->segment.accum;
 +    GST_BUFFER_TIMESTAMP (outbuf) = push_ts - videorate->segment.base;
    }
  
    GST_LOG_OBJECT (videorate,
@@@ -656,26 -700,30 +658,26 @@@ gst_video_rate_notify_duplicate (GstVid
  
  #define MAGIC_LIMIT  25
  static gboolean
 -gst_video_rate_event (GstBaseTransform * trans, GstEvent * event)
 +gst_video_rate_sink_event (GstBaseTransform * trans, GstEvent * event)
  {
    GstVideoRate *videorate;
  
    videorate = GST_VIDEO_RATE (trans);
  
    switch (GST_EVENT_TYPE (event)) {
 -    case GST_EVENT_NEWSEGMENT:
 +    case GST_EVENT_SEGMENT:
      {
 -      gint64 start, stop, time;
 -      gdouble rate, arate;
 -      gboolean update;
 -      GstFormat format;
 +      const GstSegment *segment;
  
 -      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
 -          &start, &stop, &time);
 +      gst_event_parse_segment (event, &segment);
  
 -      if (format != GST_FORMAT_TIME)
 +      if (segment->format != GST_FORMAT_TIME)
          goto format_error;
  
        GST_DEBUG_OBJECT (videorate, "handle NEWSEGMENT");
  
        /* close up the previous segment, if appropriate */
 -      if (!update && videorate->prevbuf) {
 +      if (videorate->prevbuf) {
          gint count = 0;
          GstFlowReturn res;
  
           * regardless, prevent going loopy in strange cases */
          while (res == GST_FLOW_OK && count <= MAGIC_LIMIT &&
              ((GST_CLOCK_TIME_IS_VALID (videorate->segment.stop) &&
 -                    videorate->next_ts - videorate->segment.accum
 +                    videorate->next_ts - videorate->segment.base
                      < videorate->segment.stop)
                  || count < 1)) {
            res = gst_video_rate_flush_prev (videorate, count > 0);
        }
  
        /* We just want to update the accumulated stream_time  */
 -      gst_segment_set_newsegment_full (&videorate->segment, update, rate, arate,
 -          format, start, stop, time);
 +      gst_segment_copy_into (segment, &videorate->segment);
  
        GST_DEBUG_OBJECT (videorate, "updated segment: %" GST_SEGMENT_FORMAT,
            &videorate->segment);
           * or only send out the stored buffer if there is no specific stop.
           * regardless, prevent going loopy in strange cases */
          while (res == GST_FLOW_OK && count <= MAGIC_LIMIT &&
 -            ((videorate->next_ts - videorate->segment.accum <
 +            ((videorate->next_ts - videorate->segment.base <
                      videorate->segment.stop)
                  || count < 1)) {
            res = gst_video_rate_flush_prev (videorate, count > 0);
                videorate->next_ts + GST_BUFFER_DURATION (videorate->prevbuf);
  
            while (res == GST_FLOW_OK && count <= MAGIC_LIMIT &&
 -              ((videorate->next_ts - videorate->segment.accum < end_ts)
 +              ((videorate->next_ts - videorate->segment.base < end_ts)
                    || count < 1)) {
              res = gst_video_rate_flush_prev (videorate, count > 0);
              count++;
@@@ -847,9 -896,7 +849,9 @@@ gst_video_rate_query (GstBaseTransform 
         * can't ask about its latency yet.. */
      }
      default:
 -      res = parent_class->query (trans, direction, query);
 +      res =
 +          GST_BASE_TRANSFORM_CLASS (parent_class)->query (trans, direction,
 +          query);
        break;
    }
  
@@@ -910,6 -957,21 +912,6 @@@ drop
  }
  
  static GstFlowReturn
 -gst_video_rate_prepare_output_buffer (GstBaseTransform * trans,
 -    GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf)
 -{
 -  if (gst_buffer_is_metadata_writable (input)) {
 -    gst_buffer_set_caps (input, caps);
 -    *buf = gst_buffer_ref (input);
 -  } else {
 -    *buf = gst_buffer_create_sub (input, 0, GST_BUFFER_SIZE (input));
 -    gst_buffer_set_caps (*buf, caps);
 -  }
 -
 -  return GST_FLOW_OK;
 -}
 -
 -static GstFlowReturn
  gst_video_rate_transform_ip (GstBaseTransform * trans, GstBuffer * buffer)
  {
    GstVideoRate *videorate;
  
    /* the input time is the time in the segment + all previously accumulated
     * segments */
 -  intime = in_ts + videorate->segment.accum;
 +  intime = in_ts + videorate->segment.base;
  
    /* we need to have two buffers to compare */
    if (videorate->prevbuf == NULL) {
          videorate->base_ts = in_ts - videorate->segment.start;
          videorate->out_frame_count = 0;
        } else {
 -        videorate->next_ts =
 -            videorate->segment.start + videorate->segment.accum;
 +        videorate->next_ts = videorate->segment.start + videorate->segment.base;
        }
      }
    } else {
@@@ -1114,6 -1177,13 +1116,13 @@@ gst_video_rate_start (GstBaseTransform 
    return TRUE;
  }
  
+ static gboolean
+ gst_video_rate_stop (GstBaseTransform * trans)
+ {
+   gst_video_rate_reset (GST_VIDEO_RATE (trans));
+   return TRUE;
+ }
  static void
  gst_video_rate_set_property (GObject * object,
      guint prop_id, const GValue * value, GParamSpec * pspec)
        g_atomic_int_set (&videorate->max_rate, g_value_get_int (value));
        goto reconfigure;
        break;
 -    case PROP_FORCE_FPS:
 -      videorate->force_fps_n = gst_value_get_fraction_numerator (value);
 -      videorate->force_fps_d = gst_value_get_fraction_denominator (value);
 -      goto reconfigure;
 -      break;
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
@@@ -1192,6 -1267,10 +1201,6 @@@ gst_video_rate_get_property (GObject * 
      case PROP_MAX_RATE:
        g_value_set_int (value, g_atomic_int_get (&videorate->max_rate));
        break;
 -    case PROP_FORCE_FPS:
 -      gst_value_set_fraction (value, videorate->force_fps_n,
 -          videorate->force_fps_d);
 -      break;
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
diff --combined sys/ximage/ximagesink.c
@@@ -22,9 -22,9 +22,9 @@@
   *
   * XImageSink renders video frames to a drawable (XWindow) on a local or remote
   * display. This element can receive a Window ID from the application through
 - * the XOverlay interface and will then render video frames in this drawable.
 - * If no Window ID was provided by the application, the element will create its
 - * own internal window and render into it.
 + * the #GstVideoOverlay interface and will then render video frames in this
 + * drawable. If no Window ID was provided by the application, the element will
 + * create its own internal window and render into it.
   *
   * <refsect2>
   * <title>Scaling</title>
@@@ -81,7 -81,7 +81,7 @@@
   * size are allocated along the way. If you take away the queue, scaling will
   * happen almost immediately.
   * |[
 - * gst-launch -v videotestsrc ! navigationtest ! ffmpegcolorspace ! ximagesink
 + * gst-launch -v videotestsrc ! navigationtest ! videoconvert ! ximagesink
   * ]| A pipeline to test navigation events.
   * While moving the mouse pointer over the test signal you will see a black box
   * following the mouse pointer. If you press the mouse button somewhere on the 
@@@ -89,7 -89,7 +89,7 @@@
   * the button and a red one where you released it. (The navigationtest element
   * is part of gst-plugins-good.)
   * |[
 - * gst-launch -v videotestsrc ! video/x-raw-rgb, pixel-aspect-ratio=(fraction)4/3 ! videoscale ! ximagesink
 + * gst-launch -v videotestsrc ! video/x-raw, pixel-aspect-ratio=(fraction)4/3 ! videoscale ! ximagesink
   * ]| This is faking a 4/3 pixel aspect ratio caps on video frames produced by
   * videotestsrc, in most cases the pixel aspect ratio of the display will be
   * 1/1. This means that videoscale will have to do the scaling to convert 
  
  /* Our interfaces */
  #include <gst/interfaces/navigation.h>
 -#include <gst/interfaces/xoverlay.h>
 +#include <gst/video/videooverlay.h>
 +
 +#include <gst/video/gstvideometa.h>
  
  /* Object header */
  #include "ximagesink.h"
  /* Debugging category */
  #include <gst/gstinfo.h>
  
+ #include "gst/glib-compat-private.h"
  GST_DEBUG_CATEGORY_EXTERN (gst_debug_ximagesink);
 +GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE);
  #define GST_CAT_DEFAULT gst_debug_ximagesink
  
  typedef struct
@@@ -132,14 -131,16 +134,14 @@@ MotifWmHints, MwmHints
  #define MWM_HINTS_DECORATIONS   (1L << 1)
  
  static void gst_ximagesink_reset (GstXImageSink * ximagesink);
 -static void gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
 -    GstXImageBuffer * ximage);
  static void gst_ximagesink_xwindow_update_geometry (GstXImageSink * ximagesink);
 -static void gst_ximagesink_expose (GstXOverlay * overlay);
 +static void gst_ximagesink_expose (GstVideoOverlay * overlay);
  
  static GstStaticPadTemplate gst_ximagesink_sink_template_factory =
  GST_STATIC_PAD_TEMPLATE ("sink",
      GST_PAD_SINK,
      GST_PAD_ALWAYS,
 -    GST_STATIC_CAPS ("video/x-raw-rgb, "
 +    GST_STATIC_CAPS ("video/x-raw, "
          "framerate = (fraction) [ 0, MAX ], "
          "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
      );
@@@ -157,34 -158,489 +159,34 @@@ enu
    PROP_WINDOW_HEIGHT
  };
  
 -static GstVideoSinkClass *parent_class = NULL;
 -
  /* ============================================================= */
  /*                                                               */
 -/*                       Private Methods                         */
 +/*                       Public Methods                          */
  /*                                                               */
  /* ============================================================= */
  
 -/* ximage buffers */
 -
 -static GstBufferClass *ximage_buffer_parent_class = NULL;
 -
 -#define GST_TYPE_XIMAGE_BUFFER (gst_ximage_buffer_get_type())
 -
 -#define GST_IS_XIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XIMAGE_BUFFER))
 -#define GST_XIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XIMAGE_BUFFER, GstXImageBuffer))
 -#define GST_XIMAGE_BUFFER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_XIMAGE_BUFFER, GstXImageBufferClass))
 -
 -/* So some words about GstMiniObject, this is pretty messy...
 -   GstMiniObject does not use the standard finalizing of GObjects, you are 
 -   supposed to call gst_buffer_unref that's going to call gst_mini_objec_unref
 -   which will handle its own refcount system and call gst_mini_object_free.
 -   gst_mini_object_free will call the class finalize method which is not the 
 -   one from GObject, after calling this finalize method it will free the object
 -   instance for you if the refcount is still 0 so you should not chain up */
 -static void
 -gst_ximage_buffer_finalize (GstXImageBuffer * ximage)
 -{
 -  GstXImageSink *ximagesink = NULL;
 -  gboolean recycled = FALSE;
 -  gboolean running;
 -
 -  g_return_if_fail (ximage != NULL);
 -
 -  ximagesink = ximage->ximagesink;
 -  if (G_UNLIKELY (ximagesink == NULL)) {
 -    GST_WARNING_OBJECT (ximagesink, "no sink found");
 -    goto beach;
 -  }
 -
 -  GST_OBJECT_LOCK (ximagesink);
 -  running = ximagesink->running;
 -  GST_OBJECT_UNLOCK (ximagesink);
 -
 -  if (running == FALSE) {
 -    /* If the sink is shutting down, need to clear the image */
 -    GST_DEBUG_OBJECT (ximagesink,
 -        "destroy image %p because the sink is shutting down", ximage);
 -    gst_ximagesink_ximage_destroy (ximagesink, ximage);
 -  } else if ((ximage->width != GST_VIDEO_SINK_WIDTH (ximagesink)) ||
 -      (ximage->height != GST_VIDEO_SINK_HEIGHT (ximagesink))) {
 -    /* If our geometry changed we can't reuse that image. */
 -    GST_DEBUG_OBJECT (ximagesink,
 -        "destroy image %p as its size changed %dx%d vs current %dx%d",
 -        ximage, ximage->width, ximage->height,
 -        GST_VIDEO_SINK_WIDTH (ximagesink), GST_VIDEO_SINK_HEIGHT (ximagesink));
 -    gst_ximagesink_ximage_destroy (ximagesink, ximage);
 -  } else {
 -    /* In that case we can reuse the image and add it to our image pool. */
 -    GST_LOG_OBJECT (ximagesink, "recycling image %p in pool", ximage);
 -    /* need to increment the refcount again to recycle */
 -    gst_buffer_ref (GST_BUFFER_CAST (ximage));
 -    g_mutex_lock (ximagesink->pool_lock);
 -    ximagesink->buffer_pool = g_slist_prepend (ximagesink->buffer_pool, ximage);
 -    g_mutex_unlock (ximagesink->pool_lock);
 -    recycled = TRUE;
 -  }
 -
 -  if (!recycled)
 -    GST_MINI_OBJECT_CLASS (ximage_buffer_parent_class)->finalize
 -        (GST_MINI_OBJECT (ximage));
 -
 -beach:
 -  return;
 -}
 -
 -static void
 -gst_ximage_buffer_free (GstXImageBuffer * ximage)
 -{
 -  /* make sure it is not recycled */
 -  ximage->width = -1;
 -  ximage->height = -1;
 -  gst_buffer_unref (GST_BUFFER_CAST (ximage));
 -}
 -
 -static void
 -gst_ximage_buffer_init (GstXImageBuffer * ximage_buffer, gpointer g_class)
 -{
 -#ifdef HAVE_XSHM
 -  ximage_buffer->SHMInfo.shmaddr = ((void *) -1);
 -  ximage_buffer->SHMInfo.shmid = -1;
 -#endif
 -}
 -
 -static void
 -gst_ximage_buffer_class_init (gpointer g_class, gpointer class_data)
 -{
 -  GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
 -
 -  ximage_buffer_parent_class = g_type_class_peek_parent (g_class);
 -
 -  mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
 -      gst_ximage_buffer_finalize;
 -}
 +/* =========================================== */
 +/*                                             */
 +/*          Object typing & Creation           */
 +/*                                             */
 +/* =========================================== */
 +static void gst_ximagesink_navigation_init (GstNavigationInterface * iface);
 +static void gst_ximagesink_video_overlay_init (GstVideoOverlayInterface *
 +    iface);
 +#define gst_ximagesink_parent_class parent_class
 +G_DEFINE_TYPE_WITH_CODE (GstXImageSink, gst_ximagesink, GST_TYPE_VIDEO_SINK,
 +    G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION, gst_ximagesink_navigation_init);
 +    G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY,
 +        gst_ximagesink_video_overlay_init));
  
 -static GType
 -gst_ximage_buffer_get_type (void)
 -{
 -  static GType _gst_ximage_buffer_type;
 -
 -  if (G_UNLIKELY (_gst_ximage_buffer_type == 0)) {
 -    static const GTypeInfo ximage_buffer_info = {
 -      sizeof (GstBufferClass),
 -      NULL,
 -      NULL,
 -      gst_ximage_buffer_class_init,
 -      NULL,
 -      NULL,
 -      sizeof (GstXImageBuffer),
 -      0,
 -      (GInstanceInitFunc) gst_ximage_buffer_init,
 -      NULL
 -    };
 -    _gst_ximage_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
 -        "GstXImageBuffer", &ximage_buffer_info, 0);
 -  }
 -  return _gst_ximage_buffer_type;
 -}
 +/* ============================================================= */
 +/*                                                               */
 +/*                       Private Methods                         */
 +/*                                                               */
 +/* ============================================================= */
  
  /* X11 stuff */
  
 -static gboolean error_caught = FALSE;
 -
 -static int
 -gst_ximagesink_handle_xerror (Display * display, XErrorEvent * xevent)
 -{
 -  char error_msg[1024];
 -
 -  XGetErrorText (display, xevent->error_code, error_msg, 1024);
 -  GST_DEBUG ("ximagesink triggered an XError. error: %s", error_msg);
 -  error_caught = TRUE;
 -  return 0;
 -}
 -
 -#ifdef HAVE_XSHM                /* Check that XShm calls actually work */
 -
 -static gboolean
 -gst_ximagesink_check_xshm_calls (GstXImageSink * ximagesink,
 -    GstXContext * xcontext)
 -{
 -  XImage *ximage;
 -  XShmSegmentInfo SHMInfo;
 -  size_t size;
 -  int (*handler) (Display *, XErrorEvent *);
 -  gboolean result = FALSE;
 -  gboolean did_attach = FALSE;
 -
 -  g_return_val_if_fail (xcontext != NULL, FALSE);
 -
 -  /* Sync to ensure any older errors are already processed */
 -  XSync (xcontext->disp, FALSE);
 -
 -  /* Set defaults so we don't free these later unnecessarily */
 -  SHMInfo.shmaddr = ((void *) -1);
 -  SHMInfo.shmid = -1;
 -
 -  /* Setting an error handler to catch failure */
 -  error_caught = FALSE;
 -  handler = XSetErrorHandler (gst_ximagesink_handle_xerror);
 -
 -  /* Trying to create a 1x1 ximage */
 -  GST_DEBUG ("XShmCreateImage of 1x1");
 -
 -  ximage = XShmCreateImage (xcontext->disp, xcontext->visual,
 -      xcontext->depth, ZPixmap, NULL, &SHMInfo, 1, 1);
 -
 -  /* Might cause an error, sync to ensure it is noticed */
 -  XSync (xcontext->disp, FALSE);
 -  if (!ximage || error_caught) {
 -    GST_WARNING ("could not XShmCreateImage a 1x1 image");
 -    goto beach;
 -  }
 -  size = ximage->height * ximage->bytes_per_line;
 -
 -  SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
 -  if (SHMInfo.shmid == -1) {
 -    GST_WARNING ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
 -        size);
 -    goto beach;
 -  }
 -
 -  SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0);
 -  if (SHMInfo.shmaddr == ((void *) -1)) {
 -    GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
 -    /* Clean up shm seg */
 -    shmctl (SHMInfo.shmid, IPC_RMID, NULL);
 -    goto beach;
 -  }
 -
 -  ximage->data = SHMInfo.shmaddr;
 -  SHMInfo.readOnly = FALSE;
 -
 -  if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
 -    GST_WARNING ("Failed to XShmAttach");
 -    /* Clean up shm seg */
 -    shmctl (SHMInfo.shmid, IPC_RMID, NULL);
 -    goto beach;
 -  }
 -
 -  /* Sync to ensure we see any errors we caused */
 -  XSync (xcontext->disp, FALSE);
 -
 -  /* Delete the shared memory segment as soon as everyone is attached. 
 -   * This way, it will be deleted as soon as we detach later, and not
 -   * leaked if we crash. */
 -  shmctl (SHMInfo.shmid, IPC_RMID, NULL);
 -
 -  if (!error_caught) {
 -    did_attach = TRUE;
 -    /* store whether we succeeded in result */
 -    result = TRUE;
 -  }
 -
 -beach:
 -  /* Sync to ensure we swallow any errors we caused and reset error_caught */
 -  XSync (xcontext->disp, FALSE);
 -  error_caught = FALSE;
 -  XSetErrorHandler (handler);
 -
 -  if (did_attach) {
 -    XShmDetach (xcontext->disp, &SHMInfo);
 -    XSync (xcontext->disp, FALSE);
 -  }
 -  if (SHMInfo.shmaddr != ((void *) -1))
 -    shmdt (SHMInfo.shmaddr);
 -  if (ximage)
 -    XDestroyImage (ximage);
 -  return result;
 -}
 -#endif /* HAVE_XSHM */
 -
 -/* This function handles GstXImageBuffer creation depending on XShm availability */
 -static GstXImageBuffer *
 -gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
 -{
 -  GstXImageBuffer *ximage = NULL;
 -  GstStructure *structure = NULL;
 -  gboolean succeeded = FALSE;
 -  int (*handler) (Display *, XErrorEvent *);
 -
 -  g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
 -
 -  ximage = (GstXImageBuffer *) gst_mini_object_new (GST_TYPE_XIMAGE_BUFFER);
 -
 -  structure = gst_caps_get_structure (caps, 0);
 -
 -  if (!gst_structure_get_int (structure, "width", &ximage->width) ||
 -      !gst_structure_get_int (structure, "height", &ximage->height)) {
 -    GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps);
 -  }
 -
 -  GST_DEBUG_OBJECT (ximagesink, "creating image %p (%dx%d)", ximage,
 -      ximage->width, ximage->height);
 -
 -  g_mutex_lock (ximagesink->x_lock);
 -
 -  /* Setting an error handler to catch failure */
 -  error_caught = FALSE;
 -  handler = XSetErrorHandler (gst_ximagesink_handle_xerror);
 -
 -#ifdef HAVE_XSHM
 -  if (ximagesink->xcontext->use_xshm) {
 -    ximage->ximage = XShmCreateImage (ximagesink->xcontext->disp,
 -        ximagesink->xcontext->visual,
 -        ximagesink->xcontext->depth,
 -        ZPixmap, NULL, &ximage->SHMInfo, ximage->width, ximage->height);
 -    if (!ximage->ximage || error_caught) {
 -      g_mutex_unlock (ximagesink->x_lock);
 -
 -      /* Reset error flag */
 -      error_caught = FALSE;
 -
 -      /* Push a warning */
 -      GST_ELEMENT_WARNING (ximagesink, RESOURCE, WRITE,
 -          ("Failed to create output image buffer of %dx%d pixels",
 -              ximage->width, ximage->height),
 -          ("could not XShmCreateImage a %dx%d image",
 -              ximage->width, ximage->height));
 -
 -      /* Retry without XShm */
 -      ximagesink->xcontext->use_xshm = FALSE;
 -
 -      /* Hold X mutex again to try without XShm */
 -      g_mutex_lock (ximagesink->x_lock);
 -      goto no_xshm;
 -    }
 -
 -    /* we have to use the returned bytes_per_line for our shm size */
 -    ximage->size = ximage->ximage->bytes_per_line * ximage->ximage->height;
 -    GST_LOG_OBJECT (ximagesink,
 -        "XShm image size is %" G_GSIZE_FORMAT ", width %d, stride %d",
 -        ximage->size, ximage->width, ximage->ximage->bytes_per_line);
 -
 -    ximage->SHMInfo.shmid = shmget (IPC_PRIVATE, ximage->size,
 -        IPC_CREAT | 0777);
 -    if (ximage->SHMInfo.shmid == -1) {
 -      g_mutex_unlock (ximagesink->x_lock);
 -      GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
 -          ("Failed to create output image buffer of %dx%d pixels",
 -              ximage->width, ximage->height),
 -          ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
 -              ximage->size));
 -      goto beach;
 -    }
 -
 -    ximage->SHMInfo.shmaddr = shmat (ximage->SHMInfo.shmid, NULL, 0);
 -    if (ximage->SHMInfo.shmaddr == ((void *) -1)) {
 -      g_mutex_unlock (ximagesink->x_lock);
 -      GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
 -          ("Failed to create output image buffer of %dx%d pixels",
 -              ximage->width, ximage->height),
 -          ("Failed to shmat: %s", g_strerror (errno)));
 -      /* Clean up the shared memory segment */
 -      shmctl (ximage->SHMInfo.shmid, IPC_RMID, NULL);
 -      goto beach;
 -    }
 -
 -    ximage->ximage->data = ximage->SHMInfo.shmaddr;
 -    ximage->SHMInfo.readOnly = FALSE;
 -
 -    if (XShmAttach (ximagesink->xcontext->disp, &ximage->SHMInfo) == 0) {
 -      /* Clean up shm seg */
 -      shmctl (ximage->SHMInfo.shmid, IPC_RMID, NULL);
 -
 -      g_mutex_unlock (ximagesink->x_lock);
 -      GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
 -          ("Failed to create output image buffer of %dx%d pixels",
 -              ximage->width, ximage->height), ("Failed to XShmAttach"));
 -      goto beach;
 -    }
 -
 -    XSync (ximagesink->xcontext->disp, FALSE);
 -
 -    /* Now that everyone has attached, we can delete the shared memory segment.
 -     * This way, it will be deleted as soon as we detach later, and not
 -     * leaked if we crash. */
 -    shmctl (ximage->SHMInfo.shmid, IPC_RMID, NULL);
 -
 -  } else
 -  no_xshm:
 -#endif /* HAVE_XSHM */
 -  {
 -    guint allocsize;
 -
 -    ximage->ximage = XCreateImage (ximagesink->xcontext->disp,
 -        ximagesink->xcontext->visual,
 -        ximagesink->xcontext->depth,
 -        ZPixmap, 0, NULL,
 -        ximage->width, ximage->height, ximagesink->xcontext->bpp, 0);
 -    if (!ximage->ximage || error_caught) {
 -      g_mutex_unlock (ximagesink->x_lock);
 -      /* Reset error handler */
 -      error_caught = FALSE;
 -      XSetErrorHandler (handler);
 -      /* Push an error */
 -      GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
 -          ("Failed to create output image buffer of %dx%d pixels",
 -              ximage->width, ximage->height),
 -          ("could not XCreateImage a %dx%d image",
 -              ximage->width, ximage->height));
 -      goto beach;
 -    }
 -
 -    /* upstream will assume that rowstrides are multiples of 4, but this
 -     * doesn't always seem to be the case with XCreateImage() */
 -    if ((ximage->ximage->bytes_per_line % 4) != 0) {
 -      GST_WARNING_OBJECT (ximagesink, "returned stride not a multiple of 4 as "
 -          "usually assumed");
 -    }
 -
 -    /* we have to use the returned bytes_per_line for our image size */
 -    ximage->size = ximage->ximage->bytes_per_line * ximage->ximage->height;
 -
 -    /* alloc a bit more for unexpected strides to avoid crashes upstream.
 -     * FIXME: if we get an unrounded stride, the image will be displayed
 -     * distorted, since all upstream elements assume a rounded stride */
 -    allocsize =
 -        GST_ROUND_UP_4 (ximage->ximage->bytes_per_line) *
 -        ximage->ximage->height;
 -    ximage->ximage->data = g_malloc (allocsize);
 -    GST_LOG_OBJECT (ximagesink,
 -        "non-XShm image size is %" G_GSIZE_FORMAT " (alloced: %u), width %d, "
 -        "stride %d", ximage->size, allocsize, ximage->width,
 -        ximage->ximage->bytes_per_line);
 -
 -    XSync (ximagesink->xcontext->disp, FALSE);
 -  }
 -
 -  /* Reset error handler */
 -  error_caught = FALSE;
 -  XSetErrorHandler (handler);
 -
 -  succeeded = TRUE;
 -
 -  GST_BUFFER_DATA (ximage) = (guchar *) ximage->ximage->data;
 -  GST_BUFFER_SIZE (ximage) = ximage->size;
 -
 -  /* Keep a ref to our sink */
 -  ximage->ximagesink = gst_object_ref (ximagesink);
 -
 -  g_mutex_unlock (ximagesink->x_lock);
 -beach:
 -  if (!succeeded) {
 -    gst_ximage_buffer_free (ximage);
 -    ximage = NULL;
 -  }
 -
 -  return ximage;
 -}
 -
 -/* This function destroys a GstXImageBuffer handling XShm availability */
 -static void
 -gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
 -    GstXImageBuffer * ximage)
 -{
 -  g_return_if_fail (ximage != NULL);
 -  g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
 -
 -  /* Hold the object lock to ensure the XContext doesn't disappear */
 -  GST_OBJECT_LOCK (ximagesink);
 -
 -  /* If the destroyed image is the current one we destroy our reference too */
 -  if (ximagesink->cur_image == ximage) {
 -    ximagesink->cur_image = NULL;
 -  }
 -
 -  /* We might have some buffers destroyed after changing state to NULL */
 -  if (!ximagesink->xcontext) {
 -    GST_DEBUG_OBJECT (ximagesink, "Destroying XImage after XContext");
 -#ifdef HAVE_XSHM
 -    if (ximage->SHMInfo.shmaddr != ((void *) -1)) {
 -      shmdt (ximage->SHMInfo.shmaddr);
 -    }
 -#endif
 -    goto beach;
 -  }
 -
 -  g_mutex_lock (ximagesink->x_lock);
 -
 -#ifdef HAVE_XSHM
 -  if (ximagesink->xcontext->use_xshm) {
 -    if (ximage->SHMInfo.shmaddr != ((void *) -1)) {
 -      XShmDetach (ximagesink->xcontext->disp, &ximage->SHMInfo);
 -      XSync (ximagesink->xcontext->disp, 0);
 -      shmdt (ximage->SHMInfo.shmaddr);
 -    }
 -    if (ximage->ximage)
 -      XDestroyImage (ximage->ximage);
 -
 -  } else
 -#endif /* HAVE_XSHM */
 -  {
 -    if (ximage->ximage) {
 -      XDestroyImage (ximage->ximage);
 -    }
 -  }
 -
 -  XSync (ximagesink->xcontext->disp, FALSE);
 -
 -  g_mutex_unlock (ximagesink->x_lock);
 -
 -beach:
 -  GST_OBJECT_UNLOCK (ximagesink);
 -
 -  if (ximage->ximagesink) {
 -    /* Release the ref to our sink */
 -    ximage->ximagesink = NULL;
 -    gst_object_unref (ximagesink);
 -  }
 -
 -  return;
 -}
 -
  /* We are called with the x_lock taken */
  static void
  gst_ximagesink_xwindow_draw_borders (GstXImageSink * ximagesink,
  
  /* This function puts a GstXImageBuffer on a GstXImageSink's window */
  static gboolean
 -gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
 +gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstBuffer * ximage)
  {
 +  GstXImageMeta *meta;
 +  GstVideoCropMeta *crop;
    GstVideoRectangle src, dst, result;
    gboolean draw_border = FALSE;
  
 -  g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), FALSE);
 -
    /* We take the flow_lock. If expose is in there we don't want to run
       concurrently from the data flow thread */
    g_mutex_lock (ximagesink->flow_lock);
    if (ximage && ximagesink->cur_image != ximage) {
      if (ximagesink->cur_image) {
        GST_LOG_OBJECT (ximagesink, "unreffing %p", ximagesink->cur_image);
 -      gst_buffer_unref (GST_BUFFER_CAST (ximagesink->cur_image));
 +      gst_buffer_unref (ximagesink->cur_image);
      }
      GST_LOG_OBJECT (ximagesink, "reffing %p as our current image", ximage);
 -    ximagesink->cur_image =
 -        GST_XIMAGE_BUFFER (gst_buffer_ref (GST_BUFFER_CAST (ximage)));
 +    ximagesink->cur_image = gst_buffer_ref (ximage);
    }
  
    /* Expose sends a NULL image, we take the latest frame */
      }
    }
  
 -  src.w = ximage->width;
 -  src.h = ximage->height;
 +  meta = gst_buffer_get_ximage_meta (ximage);
 +  crop = gst_buffer_get_video_crop_meta (ximage);
 +
 +  if (crop) {
 +    src.x = crop->x + meta->x;
 +    src.y = crop->y + meta->y;
 +    src.w = crop->width;
 +    src.h = crop->height;
 +  } else {
 +    src.x = meta->x;
 +    src.y = meta->y;
 +    src.w = meta->width;
 +    src.h = meta->height;
 +  }
    dst.w = ximagesink->xwindow->width;
    dst.h = ximagesink->xwindow->height;
  
          ximage, 0, 0, result.x, result.y, result.w, result.h,
          ximagesink->xwindow->width, ximagesink->xwindow->height);
      XShmPutImage (ximagesink->xcontext->disp, ximagesink->xwindow->win,
 -        ximagesink->xwindow->gc, ximage->ximage, 0, 0, result.x, result.y,
 +        ximagesink->xwindow->gc, meta->ximage, src.x, src.y, result.x, result.y,
          result.w, result.h, FALSE);
    } else
  #endif /* HAVE_XSHM */
          ximage, 0, 0, result.x, result.y, result.w, result.h,
          ximagesink->xwindow->width, ximagesink->xwindow->height);
      XPutImage (ximagesink->xcontext->disp, ximagesink->xwindow->win,
 -        ximagesink->xwindow->gc, ximage->ximage, 0, 0, result.x, result.y,
 +        ximagesink->xwindow->gc, meta->ximage, src.x, src.y, result.x, result.y,
          result.w, result.h);
    }
  
@@@ -334,8 -779,7 +336,8 @@@ gst_ximagesink_xwindow_decorate (GstXIm
  
    g_mutex_lock (ximagesink->x_lock);
  
 -  hints_atom = XInternAtom (ximagesink->xcontext->disp, "_MOTIF_WM_HINTS", 1);
 +  hints_atom = XInternAtom (ximagesink->xcontext->disp, "_MOTIF_WM_HINTS",
 +      True);
    if (hints_atom == None) {
      g_mutex_unlock (ximagesink->x_lock);
      return FALSE;
@@@ -419,7 -863,7 +421,7 @@@ gst_ximagesink_xwindow_new (GstXImageSi
  
    xwindow->win = XCreateSimpleWindow (ximagesink->xcontext->disp,
        ximagesink->xcontext->root,
 -      0, 0, xwindow->width, xwindow->height, 0, 0, ximagesink->xcontext->black);
 +      0, 0, width, height, 0, 0, ximagesink->xcontext->black);
  
    /* We have to do that to prevent X from redrawing the background on 
       ConfigureNotify. This takes away flickering of video when resizing. */
  
    gst_ximagesink_xwindow_decorate (ximagesink, xwindow);
  
 -  gst_x_overlay_got_window_handle (GST_X_OVERLAY (ximagesink), xwindow->win);
 +  gst_video_overlay_got_window_handle (GST_VIDEO_OVERLAY (ximagesink),
 +      xwindow->win);
  
    return xwindow;
  }
@@@ -489,7 -932,6 +491,7 @@@ static voi
  gst_ximagesink_xwindow_update_geometry (GstXImageSink * ximagesink)
  {
    XWindowAttributes attr;
 +  gboolean reconfigure;
  
    g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
  
    XGetWindowAttributes (ximagesink->xcontext->disp,
        ximagesink->xwindow->win, &attr);
  
 +  /* Check if we would suggest a different width/height now */
 +  reconfigure = (ximagesink->xwindow->width != attr.width)
 +      || (ximagesink->xwindow->height != attr.height);
    ximagesink->xwindow->width = attr.width;
    ximagesink->xwindow->height = attr.height;
  
    g_mutex_unlock (ximagesink->x_lock);
 +
 +  if (reconfigure)
 +    gst_pad_push_event (GST_BASE_SINK (ximagesink)->sinkpad,
 +        gst_event_new_reconfigure ());
  }
  
  static void
@@@ -627,6 -1062,7 +629,6 @@@ gst_ximagesink_handle_xevents (GstXImag
            g_mutex_unlock (ximagesink->x_lock);
            gst_navigation_send_key_event (GST_NAVIGATION (ximagesink),
                e.type == KeyPress ? "key-press" : "key-release", key_str);
 -
          } else {
            gst_navigation_send_key_event (GST_NAVIGATION (ximagesink),
                e.type == KeyPress ? "key-press" : "key-release", "unknown");
      g_mutex_lock (ximagesink->x_lock);
    }
  
 +  /* Handle Expose */
    while (XCheckWindowEvent (ximagesink->xcontext->disp,
            ximagesink->xwindow->win, ExposureMask | StructureNotifyMask, &e)) {
      switch (e.type) {
      g_mutex_unlock (ximagesink->x_lock);
      g_mutex_unlock (ximagesink->flow_lock);
  
 -    gst_ximagesink_expose (GST_X_OVERLAY (ximagesink));
 +    gst_ximagesink_expose (GST_VIDEO_OVERLAY (ximagesink));
  
      g_mutex_lock (ximagesink->flow_lock);
      g_mutex_lock (ximagesink->x_lock);
@@@ -738,8 -1173,13 +740,13 @@@ gst_ximagesink_manage_event_thread (Gst
        GST_DEBUG_OBJECT (ximagesink, "run xevent thread, expose %d, events %d",
            ximagesink->handle_expose, ximagesink->handle_events);
        ximagesink->running = TRUE;
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
        ximagesink->event_thread = g_thread_create (
            (GThreadFunc) gst_ximagesink_event_thread, ximagesink, TRUE, NULL);
+ #else
+       ximagesink->event_thread = g_thread_try_new ("ximagesink-events",
+           (GThreadFunc) gst_ximagesink_event_thread, ximagesink, NULL);
+ #endif
      }
    } else {
      if (ximagesink->event_thread) {
@@@ -828,8 -1268,6 +835,8 @@@ gst_ximagesink_xcontext_get (GstXImageS
    GstXContext *xcontext = NULL;
    XPixmapFormatValues *px_formats = NULL;
    gint nb_formats = 0, i;
 +  gint endianness;
 +  GstVideoFormat vformat;
  
    g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
  
      g_mutex_unlock (ximagesink->x_lock);
      g_free (xcontext->par);
      g_free (xcontext);
 -    GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
 +    GST_ELEMENT_ERROR (ximagesink, RESOURCE, SETTINGS,
          ("Could not get supported pixmap formats"), (NULL));
      return NULL;
    }
  
    XFree (px_formats);
  
 -  xcontext->endianness =
 -      (ImageByteOrder (xcontext->disp) ==
 +  endianness = (ImageByteOrder (xcontext->disp) ==
        LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;
  
    /* Search for XShm extension support */
      xcontext->use_xshm = TRUE;
      GST_DEBUG ("ximagesink is using XShm extension");
    } else
 -#endif
 +#endif /* HAVE_XSHM */
    {
      xcontext->use_xshm = FALSE;
      GST_DEBUG ("ximagesink is not using XShm extension");
    }
  
 -  /* our caps system handles 24/32bpp RGB as big-endian. */
 -  if ((xcontext->bpp == 24 || xcontext->bpp == 32) &&
 -      xcontext->endianness == G_LITTLE_ENDIAN) {
 -    xcontext->endianness = G_BIG_ENDIAN;
 -    xcontext->visual->red_mask = GUINT32_TO_BE (xcontext->visual->red_mask);
 -    xcontext->visual->green_mask = GUINT32_TO_BE (xcontext->visual->green_mask);
 -    xcontext->visual->blue_mask = GUINT32_TO_BE (xcontext->visual->blue_mask);
 -    if (xcontext->bpp == 24) {
 -      xcontext->visual->red_mask >>= 8;
 -      xcontext->visual->green_mask >>= 8;
 -      xcontext->visual->blue_mask >>= 8;
 -    }
 -  }
 +  vformat = gst_video_format_from_masks (xcontext->depth, xcontext->bpp,
 +      endianness, xcontext->visual->red_mask, xcontext->visual->green_mask,
 +      xcontext->visual->blue_mask, 0);
 +
 +  if (vformat == GST_VIDEO_FORMAT_UNKNOWN)
 +    goto unknown_format;
  
    /* update object's par with calculated one if not set yet */
    if (!ximagesink->par) {
      gst_value_init_and_copy (ximagesink->par, xcontext->par);
      GST_DEBUG_OBJECT (ximagesink, "set calculated PAR on object's PAR");
    }
 -  xcontext->caps = gst_caps_new_simple ("video/x-raw-rgb",
 -      "bpp", G_TYPE_INT, xcontext->bpp,
 -      "depth", G_TYPE_INT, xcontext->depth,
 -      "endianness", G_TYPE_INT, xcontext->endianness,
 -      "red_mask", G_TYPE_INT, xcontext->visual->red_mask,
 -      "green_mask", G_TYPE_INT, xcontext->visual->green_mask,
 -      "blue_mask", G_TYPE_INT, xcontext->visual->blue_mask,
 +  xcontext->caps = gst_caps_new_simple ("video/x-raw",
 +      "format", G_TYPE_STRING, gst_video_format_to_string (vformat),
        "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
        "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
        "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
    g_mutex_unlock (ximagesink->x_lock);
  
    return xcontext;
 +
 +  /* ERRORS */
 +unknown_format:
 +  {
 +    GST_ERROR_OBJECT (ximagesink, "unknown format");
 +    return NULL;
 +  }
  }
  
  /* This function cleans the X context. Closing the Display and unrefing the
@@@ -981,10 -1425,27 +988,10 @@@ gst_ximagesink_xcontext_clear (GstXImag
    g_free (xcontext);
  }
  
 -static void
 -gst_ximagesink_bufferpool_clear (GstXImageSink * ximagesink)
 -{
 -
 -  g_mutex_lock (ximagesink->pool_lock);
 -
 -  while (ximagesink->buffer_pool) {
 -    GstXImageBuffer *ximage = ximagesink->buffer_pool->data;
 -
 -    ximagesink->buffer_pool = g_slist_delete_link (ximagesink->buffer_pool,
 -        ximagesink->buffer_pool);
 -    gst_ximage_buffer_free (ximage);
 -  }
 -
 -  g_mutex_unlock (ximagesink->pool_lock);
 -}
 -
  /* Element stuff */
  
  static GstCaps *
 -gst_ximagesink_getcaps (GstBaseSink * bsink)
 +gst_ximagesink_getcaps (GstBaseSink * bsink, GstCaps * filter)
  {
    GstXImageSink *ximagesink;
    GstCaps *caps;
  
    ximagesink = GST_XIMAGESINK (bsink);
  
 -  if (ximagesink->xcontext)
 -    return gst_caps_ref (ximagesink->xcontext->caps);
 +  g_mutex_lock (ximagesink->x_lock);
 +  if (ximagesink->xcontext) {
 +    GstCaps *caps;
 +
 +    caps = gst_caps_ref (ximagesink->xcontext->caps);
  
 -  /* get a template copy and add the pixel aspect ratio */
 -  caps =
 -      gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK
 -          (ximagesink)->sinkpad));
 -  for (i = 0; i < gst_caps_get_size (caps); ++i) {
 -    GstStructure *structure = gst_caps_get_structure (caps, i);
 +    if (filter) {
 +      GstCaps *intersection;
  
 -    if (ximagesink->par) {
 +      intersection =
 +          gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
 +      gst_caps_unref (caps);
 +      caps = intersection;
 +    }
 +
 +    if (ximagesink->xwindow && ximagesink->xwindow->width) {
 +      GstStructure *s0, *s1;
 +
 +      caps = gst_caps_make_writable (caps);
 +
 +      /* There can only be a single structure because the xcontext
 +       * caps only have a single structure */
 +      s0 = gst_caps_get_structure (caps, 0);
 +      s1 = gst_structure_copy (gst_caps_get_structure (caps, 0));
 +
 +      gst_structure_set (s0, "width", G_TYPE_INT, ximagesink->xwindow->width,
 +          "height", G_TYPE_INT, ximagesink->xwindow->height, NULL);
 +      gst_caps_append_structure (caps, s1);
 +
 +      /* This will not change the order but will remove the
 +       * fixed width/height caps again if not possible
 +       * upstream */
 +      if (filter) {
 +        GstCaps *intersection;
 +
 +        intersection =
 +            gst_caps_intersect_full (caps, filter, GST_CAPS_INTERSECT_FIRST);
 +        gst_caps_unref (caps);
 +        caps = intersection;
 +      }
 +    }
 +
 +    g_mutex_unlock (ximagesink->x_lock);
 +    return caps;
 +  }
 +  g_mutex_unlock (ximagesink->x_lock);
 +
 +  /* get a template copy and add the pixel aspect ratio */
 +  caps = gst_pad_get_pad_template_caps (GST_BASE_SINK (ximagesink)->sinkpad);
 +  if (ximagesink->par) {
 +    caps = gst_caps_make_writable (caps);
 +    for (i = 0; i < gst_caps_get_size (caps); ++i) {
 +      GstStructure *structure = gst_caps_get_structure (caps, i);
        int nom, den;
  
        nom = gst_value_get_fraction_numerator (ximagesink->par);
      }
    }
  
 +  if (filter) {
 +    GstCaps *intersection;
 +
 +    intersection =
 +        gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
 +    gst_caps_unref (caps);
 +    caps = intersection;
 +  }
 +
    return caps;
  }
  
@@@ -1070,11 -1480,11 +1077,11 @@@ static gboolea
  gst_ximagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
  {
    GstXImageSink *ximagesink;
 -  gboolean ret = TRUE;
    GstStructure *structure;
 +  GstVideoInfo info;
 +  GstBufferPool *newpool, *oldpool;
    const GValue *par;
 -  gint new_width, new_height;
 -  const GValue *fps;
 +  gint size;
  
    ximagesink = GST_XIMAGESINK (bsink);
  
    if (!gst_caps_can_intersect (ximagesink->xcontext->caps, caps))
      goto incompatible_caps;
  
 -  structure = gst_caps_get_structure (caps, 0);
 +  if (!gst_video_info_from_caps (&info, caps))
 +    goto invalid_format;
  
 -  ret &= gst_structure_get_int (structure, "width", &new_width);
 -  ret &= gst_structure_get_int (structure, "height", &new_height);
 -  fps = gst_structure_get_value (structure, "framerate");
 -  ret &= (fps != NULL);
 -  if (!ret)
 -    return FALSE;
 +  size = info.size;
  
 +  structure = gst_caps_get_structure (caps, 0);
    /* if the caps contain pixel-aspect-ratio, they have to match ours,
     * otherwise linking should fail */
    par = gst_structure_get_value (structure, "pixel-aspect-ratio");
      }
    }
  
 -  GST_VIDEO_SINK_WIDTH (ximagesink) = new_width;
 -  GST_VIDEO_SINK_HEIGHT (ximagesink) = new_height;
 -  ximagesink->fps_n = gst_value_get_fraction_numerator (fps);
 -  ximagesink->fps_d = gst_value_get_fraction_denominator (fps);
 +  GST_VIDEO_SINK_WIDTH (ximagesink) = info.width;
 +  GST_VIDEO_SINK_HEIGHT (ximagesink) = info.height;
 +  ximagesink->fps_n = info.fps_n;
 +  ximagesink->fps_d = info.fps_d;
  
    /* Notify application to set xwindow id now */
    g_mutex_lock (ximagesink->flow_lock);
    if (!ximagesink->xwindow) {
      g_mutex_unlock (ximagesink->flow_lock);
 -    gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (ximagesink));
 +    gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (ximagesink));
    } else {
      g_mutex_unlock (ximagesink->flow_lock);
    }
  
    /* Creating our window and our image */
    if (GST_VIDEO_SINK_WIDTH (ximagesink) <= 0 ||
 -      GST_VIDEO_SINK_HEIGHT (ximagesink) <= 0) {
 -    GST_ELEMENT_ERROR (ximagesink, CORE, NEGOTIATION, (NULL),
 -        ("Invalid image size."));
 -    return FALSE;
 -  }
 +      GST_VIDEO_SINK_HEIGHT (ximagesink) <= 0)
 +    goto invalid_size;
  
    g_mutex_lock (ximagesink->flow_lock);
    if (!ximagesink->xwindow) {
      ximagesink->xwindow = gst_ximagesink_xwindow_new (ximagesink,
          GST_VIDEO_SINK_WIDTH (ximagesink), GST_VIDEO_SINK_HEIGHT (ximagesink));
    }
 +
 +  ximagesink->info = info;
 +
    /* Remember to draw borders for next frame */
    ximagesink->draw_border = TRUE;
 -  g_mutex_unlock (ximagesink->flow_lock);
  
 -  /* If our ximage has changed we destroy it, next chain iteration will create
 -     a new one */
 -  if ((ximagesink->ximage) &&
 -      ((GST_VIDEO_SINK_WIDTH (ximagesink) != ximagesink->ximage->width) ||
 -          (GST_VIDEO_SINK_HEIGHT (ximagesink) != ximagesink->ximage->height))) {
 -    GST_DEBUG_OBJECT (ximagesink, "our image is not usable anymore, unref %p",
 -        ximagesink->ximage);
 -    gst_buffer_unref (GST_BUFFER_CAST (ximagesink->ximage));
 -    ximagesink->ximage = NULL;
 +  /* create a new pool for the new configuration */
 +  newpool = gst_ximage_buffer_pool_new (ximagesink);
 +
 +  structure = gst_buffer_pool_get_config (newpool);
 +  gst_buffer_pool_config_set (structure, caps, size, 2, 0, 0, 15);
 +  if (!gst_buffer_pool_set_config (newpool, structure))
 +    goto config_failed;
 +
 +  oldpool = ximagesink->pool;
 +  ximagesink->pool = newpool;
 +
 +  /* unref the old sink */
 +  if (oldpool) {
 +    /* we don't deactivate, some elements might still be using it, it will be
 +     * deactivated when the last ref is gone */
 +    gst_object_unref (oldpool);
    }
 +  g_mutex_unlock (ximagesink->flow_lock);
  
    return TRUE;
  
@@@ -1167,41 -1573,25 +1174,41 @@@ incompatible_caps
      GST_ERROR_OBJECT (ximagesink, "caps incompatible");
      return FALSE;
    }
 +invalid_format:
 +  {
 +    GST_ERROR_OBJECT (ximagesink, "caps invalid");
 +    return FALSE;
 +  }
  wrong_aspect:
    {
      GST_INFO_OBJECT (ximagesink, "pixel aspect ratio does not match");
      return FALSE;
    }
 +invalid_size:
 +  {
 +    GST_ELEMENT_ERROR (ximagesink, CORE, NEGOTIATION, (NULL),
 +        ("Invalid image size."));
 +    return FALSE;
 +  }
 +config_failed:
 +  {
 +    GST_ERROR_OBJECT (ximagesink, "failed to set config.");
 +    g_mutex_unlock (ximagesink->flow_lock);
 +    return FALSE;
 +  }
  }
  
  static GstStateChangeReturn
  gst_ximagesink_change_state (GstElement * element, GstStateChange transition)
  {
 -  GstXImageSink *ximagesink;
    GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
 +  GstXImageSink *ximagesink;
    GstXContext *xcontext = NULL;
  
    ximagesink = GST_XIMAGESINK (element);
  
    switch (transition) {
      case GST_STATE_CHANGE_NULL_TO_READY:
 -
        /* Initializing the XContext */
        if (ximagesink->xcontext == NULL) {
          xcontext = gst_ximagesink_xcontext_get (ximagesink);
        ximagesink->fps_d = 1;
        GST_VIDEO_SINK_WIDTH (ximagesink) = 0;
        GST_VIDEO_SINK_HEIGHT (ximagesink) = 0;
 +      g_mutex_lock (ximagesink->flow_lock);
 +      if (ximagesink->pool)
 +        gst_buffer_pool_set_active (ximagesink->pool, FALSE);
 +      g_mutex_unlock (ximagesink->flow_lock);
        break;
      case GST_STATE_CHANGE_READY_TO_NULL:
        gst_ximagesink_reset (ximagesink);
@@@ -1286,115 -1672,70 +1293,115 @@@ gst_ximagesink_get_times (GstBaseSink 
  static GstFlowReturn
  gst_ximagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
  {
 +  GstFlowReturn res;
    GstXImageSink *ximagesink;
 -
 -  g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
 +  GstXImageMeta *meta;
 +  GstBuffer *to_put = NULL;
  
    ximagesink = GST_XIMAGESINK (vsink);
  
 -  /* This shouldn't really happen because state changes will fail
 -   * if the xcontext can't be allocated */
 -  if (!ximagesink->xcontext)
 -    return GST_FLOW_ERROR;
 +  meta = gst_buffer_get_ximage_meta (buf);
  
 -  /* If this buffer has been allocated using our buffer management we simply
 -     put the ximage which is in the PRIVATE pointer */
 -  if (GST_IS_XIMAGE_BUFFER (buf)) {
 +  if (meta && meta->sink == ximagesink) {
 +    /* If this buffer has been allocated using our buffer management we simply
 +       put the ximage which is in the PRIVATE pointer */
      GST_LOG_OBJECT (ximagesink, "buffer from our pool, writing directly");
 -    if (!gst_ximagesink_ximage_put (ximagesink, GST_XIMAGE_BUFFER (buf)))
 -      goto no_window;
 +    to_put = buf;
 +    res = GST_FLOW_OK;
    } else {
 +    GstVideoFrame src, dest;
 +
      /* Else we have to copy the data into our private image, */
      /* if we have one... */
 -    GST_LOG_OBJECT (ximagesink, "normal buffer, copying from it");
 -    if (!ximagesink->ximage) {
 -      GST_DEBUG_OBJECT (ximagesink, "creating our ximage");
 -      ximagesink->ximage = gst_ximagesink_ximage_new (ximagesink,
 -          GST_BUFFER_CAPS (buf));
 -      if (!ximagesink->ximage)
 -        /* The create method should have posted an informative error */
 -        goto no_ximage;
 -
 -      if (ximagesink->ximage->size < GST_BUFFER_SIZE (buf)) {
 -        GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
 -            ("Failed to create output image buffer of %dx%d pixels",
 -                ximagesink->ximage->width, ximagesink->ximage->height),
 -            ("XServer allocated buffer size did not match input buffer"));
 -
 -        gst_ximagesink_ximage_destroy (ximagesink, ximagesink->ximage);
 -        ximagesink->ximage = NULL;
 -        goto no_ximage;
 -      }
 +    GST_LOG_OBJECT (ximagesink, "buffer not from our pool, copying");
 +
 +    /* we should have a pool, configured in setcaps */
 +    if (ximagesink->pool == NULL)
 +      goto no_pool;
 +
 +    if (!gst_buffer_pool_set_active (ximagesink->pool, TRUE))
 +      goto activate_failed;
 +
 +    /* take a buffer form our pool */
 +    res = gst_buffer_pool_acquire_buffer (ximagesink->pool, &to_put, NULL);
 +    if (res != GST_FLOW_OK)
 +      goto no_buffer;
 +
 +    if (gst_buffer_get_size (to_put) < gst_buffer_get_size (buf))
 +      goto wrong_size;
 +
 +    GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, ximagesink,
 +        "slow copy into bufferpool buffer %p", to_put);
 +
 +    if (!gst_video_frame_map (&src, &ximagesink->info, buf, GST_MAP_READ))
 +      goto invalid_buffer;
 +
 +    if (!gst_video_frame_map (&dest, &ximagesink->info, to_put, GST_MAP_WRITE)) {
 +      gst_video_frame_unmap (&src);
 +      goto invalid_buffer;
      }
 -    memcpy (GST_BUFFER_DATA (ximagesink->ximage), GST_BUFFER_DATA (buf),
 -        MIN (GST_BUFFER_SIZE (buf), ximagesink->ximage->size));
 -    if (!gst_ximagesink_ximage_put (ximagesink, ximagesink->ximage))
 -      goto no_window;
 +
 +    gst_video_frame_copy (&dest, &src);
 +
 +    gst_video_frame_unmap (&dest);
 +    gst_video_frame_unmap (&src);
    }
  
 -  return GST_FLOW_OK;
 +  if (!gst_ximagesink_ximage_put (ximagesink, to_put))
 +    goto no_window;
 +
 +done:
 +  if (to_put != buf)
 +    gst_buffer_unref (to_put);
 +
 +  return res;
  
    /* ERRORS */
 -no_ximage:
 +no_pool:
 +  {
 +    GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
 +        ("Internal error: can't allocate images"),
 +        ("We don't have a bufferpool negotiated"));
 +    return GST_FLOW_ERROR;
 +  }
 +no_buffer:
    {
      /* No image available. That's very bad ! */
      GST_WARNING_OBJECT (ximagesink, "could not create image");
 -    return GST_FLOW_ERROR;
 +    return res;
 +  }
 +wrong_size:
 +  {
 +    GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
 +        ("Failed to create output image buffer"),
 +        ("XServer allocated buffer size did not match input buffer %"
 +            G_GSIZE_FORMAT " - %" G_GSIZE_FORMAT, gst_buffer_get_size (to_put),
 +            gst_buffer_get_size (buf)));
 +    res = GST_FLOW_ERROR;
 +    goto done;
 +  }
 +invalid_buffer:
 +  {
 +    /* No Window available to put our image into */
 +    GST_WARNING_OBJECT (ximagesink, "could map image");
 +    res = GST_FLOW_OK;
 +    goto done;
    }
  no_window:
    {
      /* No Window available to put our image into */
      GST_WARNING_OBJECT (ximagesink, "could not output image - no window");
 -    return GST_FLOW_ERROR;
 +    res = GST_FLOW_ERROR;
 +    goto done;
 +  }
 +activate_failed:
 +  {
 +    GST_ERROR_OBJECT (ximagesink, "failed to activate bufferpool.");
 +    res = GST_FLOW_ERROR;
 +    goto done;
    }
  }
  
 -
  static gboolean
  gst_ximagesink_event (GstBaseSink * sink, GstEvent * event)
  {
      default:
        break;
    }
 -  if (GST_BASE_SINK_CLASS (parent_class)->event)
 -    return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
 -  else
 -    return TRUE;
 +  return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
  }
  
 -
 -/* Buffer management
 - *
 - * The buffer_alloc function must either return a buffer with given size and
 - * caps or create a buffer with different caps attached to the buffer. This
 - * last option is called reverse negotiation, ie, where the sink suggests a
 - * different format from the upstream peer. 
 - *
 - * We try to do reverse negotiation when our geometry changes and we like a
 - * resized buffer.
 - */
 -static GstFlowReturn
 -gst_ximagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
 -    GstCaps * caps, GstBuffer ** buf)
 +static gboolean
 +gst_ximagesink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
  {
 -  GstXImageSink *ximagesink;
 -  GstXImageBuffer *ximage = NULL;
 -  GstStructure *structure = NULL;
 -  GstFlowReturn ret = GST_FLOW_OK;
 -  GstCaps *alloc_caps;
 -  gboolean alloc_unref = FALSE;
 -  gint width, height;
 -  GstVideoRectangle dst, src, result;
 -  gboolean caps_accepted = FALSE;
 -
 -  ximagesink = GST_XIMAGESINK (bsink);
 -
 -  if (G_UNLIKELY (!caps)) {
 -    GST_WARNING_OBJECT (ximagesink, "have no caps, doing fallback allocation");
 -    *buf = NULL;
 -    ret = GST_FLOW_OK;
 -    goto beach;
 -  }
 -
 -  /* This shouldn't really happen because state changes will fail
 -   * if the xcontext can't be allocated */
 -  if (!ximagesink->xcontext)
 -    return GST_FLOW_ERROR;
 -
 -  GST_LOG_OBJECT (ximagesink,
 -      "a buffer of %d bytes was requested with caps %" GST_PTR_FORMAT
 -      " and offset %" G_GUINT64_FORMAT, size, caps, offset);
 -
 -  /* assume we're going to alloc what was requested, keep track of
 -   * whether we need to unref or not. When we suggest a new format 
 -   * upstream we will create a new caps that we need to unref. */
 -  alloc_caps = caps;
 -  alloc_unref = FALSE;
 +  GstXImageSink *ximagesink = GST_XIMAGESINK (bsink);
 +  GstBufferPool *pool;
 +  GstStructure *config;
 +  GstCaps *caps;
 +  guint size;
 +  gboolean need_pool;
  
 -  /* get struct to see what is requested */
 -  structure = gst_caps_get_structure (caps, 0);
 -  if (!gst_structure_get_int (structure, "width", &width) ||
 -      !gst_structure_get_int (structure, "height", &height)) {
 -    GST_WARNING_OBJECT (ximagesink, "invalid caps for buffer allocation %"
 -        GST_PTR_FORMAT, caps);
 -    ret = GST_FLOW_NOT_NEGOTIATED;
 -    goto beach;
 -  }
 +  gst_query_parse_allocation (query, &caps, &need_pool);
  
 -  src.w = width;
 -  src.h = height;
 +  if (caps == NULL)
 +    goto no_caps;
  
 -  /* We take the flow_lock because the window might go away */
    g_mutex_lock (ximagesink->flow_lock);
 -  if (!ximagesink->xwindow) {
 -    g_mutex_unlock (ximagesink->flow_lock);
 -    goto alloc;
 -  }
 -
 -  /* What is our geometry */
 -  dst.w = ximagesink->xwindow->width;
 -  dst.h = ximagesink->xwindow->height;
 -
 +  if ((pool = ximagesink->pool))
 +    gst_object_ref (pool);
    g_mutex_unlock (ximagesink->flow_lock);
  
 -  if (ximagesink->keep_aspect) {
 -    GST_LOG_OBJECT (ximagesink, "enforcing aspect ratio in reverse caps "
 -        "negotiation");
 -    gst_video_sink_center_rect (src, dst, &result, TRUE);
 -  } else {
 -    GST_LOG_OBJECT (ximagesink, "trying to resize to window geometry "
 -        "ignoring aspect ratio");
 -    result.x = result.y = 0;
 -    result.w = dst.w;
 -    result.h = dst.h;
 -  }
 -
 -  /* We would like another geometry */
 -  if (width != result.w || height != result.h) {
 -    int nom, den;
 -    GstCaps *desired_caps;
 -    GstStructure *desired_struct;
 -
 -    /* make a copy of the incomming caps to create the new
 -     * suggestion. We can't use make_writable because we might
 -     * then destroy the original caps which we still need when the
 -     * peer does not accept the suggestion. */
 -    desired_caps = gst_caps_copy (caps);
 -    desired_struct = gst_caps_get_structure (desired_caps, 0);
 +  if (pool != NULL) {
 +    const GstCaps *pcaps;
  
 -    GST_DEBUG ("we would love to receive a %dx%d video", result.w, result.h);
 -    gst_structure_set (desired_struct, "width", G_TYPE_INT, result.w, NULL);
 -    gst_structure_set (desired_struct, "height", G_TYPE_INT, result.h, NULL);
 +    /* we had a pool, check caps */
 +    config = gst_buffer_pool_get_config (pool);
 +    gst_buffer_pool_config_get (config, &pcaps, &size, NULL, NULL, NULL, NULL);
  
 -    /* PAR property overrides the X calculated one */
 -    if (ximagesink->par) {
 -      nom = gst_value_get_fraction_numerator (ximagesink->par);
 -      den = gst_value_get_fraction_denominator (ximagesink->par);
 -      gst_structure_set (desired_struct, "pixel-aspect-ratio",
 -          GST_TYPE_FRACTION, nom, den, NULL);
 -    } else if (ximagesink->xcontext->par) {
 -      nom = gst_value_get_fraction_numerator (ximagesink->xcontext->par);
 -      den = gst_value_get_fraction_denominator (ximagesink->xcontext->par);
 -      gst_structure_set (desired_struct, "pixel-aspect-ratio",
 -          GST_TYPE_FRACTION, nom, den, NULL);
 +    GST_DEBUG_OBJECT (ximagesink,
 +        "we had a pool with caps %" GST_PTR_FORMAT, pcaps);
 +    if (!gst_caps_is_equal (caps, pcaps)) {
 +      /* different caps, we can't use this pool */
 +      GST_DEBUG_OBJECT (ximagesink, "pool has different caps");
 +      gst_object_unref (pool);
 +      pool = NULL;
      }
 +  }
 +  if (pool == NULL && need_pool) {
 +    GstVideoInfo info;
  
 +    GST_DEBUG_OBJECT (ximagesink, "create new pool");
 +    pool = gst_ximage_buffer_pool_new (ximagesink);
  
 -    /* see if peer accepts our new suggestion, if there is no peer, this 
 -     * function returns true. */
 -    if (!ximagesink->xcontext->last_caps ||
 -        !gst_caps_is_equal (desired_caps, ximagesink->xcontext->last_caps)) {
 -      caps_accepted =
 -          gst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (ximagesink),
 -          desired_caps);
 +    if (!gst_video_info_from_caps (&info, caps))
 +      goto invalid_caps;
  
 -      /* Suggestion failed, prevent future attempts for the same caps
 -       * to fail as well. */
 -      if (!caps_accepted)
 -        gst_caps_replace (&ximagesink->xcontext->last_caps, desired_caps);
 -    }
 +    /* the normal size of a frame */
 +    size = info.size;
  
 -    if (caps_accepted) {
 -      /* we will not alloc a buffer of the new suggested caps. Make sure
 -       * we also unref this new caps after we set it on the buffer. */
 -      alloc_caps = desired_caps;
 -      alloc_unref = TRUE;
 -      width = result.w;
 -      height = result.h;
 -      GST_DEBUG ("peer pad accepts our desired caps %" GST_PTR_FORMAT,
 -          desired_caps);
 -    } else {
 -      GST_DEBUG ("peer pad does not accept our desired caps %" GST_PTR_FORMAT,
 -          desired_caps);
 -      /* we alloc a buffer with the original incomming caps already in the
 -       * width and height variables */
 -      gst_caps_unref (desired_caps);
 -    }
 +    config = gst_buffer_pool_get_config (pool);
 +    gst_buffer_pool_config_set (config, caps, size, 0, 0, 0, 0);
 +    if (!gst_buffer_pool_set_config (pool, config))
 +      goto config_failed;
    }
 +  /* we need at least 2 buffer because we hold on to the last one */
 +  gst_query_set_allocation_params (query, size, 2, 0, 0, 0, pool);
  
 -alloc:
 -  /* Inspect our buffer pool */
 -  g_mutex_lock (ximagesink->pool_lock);
 -  while (ximagesink->buffer_pool) {
 -    ximage = (GstXImageBuffer *) ximagesink->buffer_pool->data;
 +  /* we also support various metadata */
 +  gst_query_add_allocation_meta (query, GST_VIDEO_META_API);
 +  gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API);
  
 -    if (ximage) {
 -      /* Removing from the pool */
 -      ximagesink->buffer_pool = g_slist_delete_link (ximagesink->buffer_pool,
 -          ximagesink->buffer_pool);
 +  gst_object_unref (pool);
  
 -      /* If the ximage is invalid for our need, destroy */
 -      if ((ximage->width != width) || (ximage->height != height)) {
 -        gst_ximage_buffer_free (ximage);
 -        ximage = NULL;
 -      } else {
 -        /* We found a suitable ximage */
 -        break;
 -      }
 -    }
 -  }
 -  g_mutex_unlock (ximagesink->pool_lock);
 +  return TRUE;
  
 -  /* We haven't found anything, creating a new one */
 -  if (!ximage) {
 -    ximage = gst_ximagesink_ximage_new (ximagesink, alloc_caps);
 +  /* ERRORS */
 +no_caps:
 +  {
 +    GST_DEBUG_OBJECT (bsink, "no caps specified");
 +    return FALSE;
    }
 -  /* Now we should have a ximage, set appropriate caps on it */
 -  if (ximage) {
 -    /* Make sure the buffer is cleared of any previously used flags */
 -    GST_MINI_OBJECT_CAST (ximage)->flags = 0;
 -    gst_buffer_set_caps (GST_BUFFER_CAST (ximage), alloc_caps);
 +invalid_caps:
 +  {
 +    GST_DEBUG_OBJECT (bsink, "invalid caps specified");
 +    return FALSE;
    }
 -
 -  /* could be our new reffed suggestion or the original unreffed caps */
 -  if (alloc_unref)
 -    gst_caps_unref (alloc_caps);
 -
 -  *buf = GST_BUFFER_CAST (ximage);
 -
 -beach:
 -  return ret;
 -}
 -
 -/* Interfaces stuff */
 -
 -static gboolean
 -gst_ximagesink_interface_supported (GstImplementsInterface * iface, GType type)
 -{
 -  if (type == GST_TYPE_NAVIGATION || type == GST_TYPE_X_OVERLAY)
 -    return TRUE;
 -  else
 +config_failed:
 +  {
 +    GST_DEBUG_OBJECT (bsink, "failed setting config");
      return FALSE;
 +  }
  }
  
 -static void
 -gst_ximagesink_interface_init (GstImplementsInterfaceClass * klass)
 -{
 -  klass->supported = gst_ximagesink_interface_supported;
 -}
 -
 +/* Interfaces stuff */
  static void
  gst_ximagesink_navigation_send_event (GstNavigation * navigation,
      GstStructure * structure)
@@@ -1562,7 -2034,7 +1569,7 @@@ gst_ximagesink_navigation_init (GstNavi
  }
  
  static void
 -gst_ximagesink_set_window_handle (GstXOverlay * overlay, guintptr id)
 +gst_ximagesink_set_window_handle (GstVideoOverlay * overlay, guintptr id)
  {
    XID xwindow_id = id;
    GstXImageSink *ximagesink = GST_XIMAGESINK (overlay);
  }
  
  static void
 -gst_ximagesink_expose (GstXOverlay * overlay)
 +gst_ximagesink_expose (GstVideoOverlay * overlay)
  {
    GstXImageSink *ximagesink = GST_XIMAGESINK (overlay);
  
  }
  
  static void
 -gst_ximagesink_set_event_handling (GstXOverlay * overlay,
 +gst_ximagesink_set_event_handling (GstVideoOverlay * overlay,
      gboolean handle_events)
  {
    GstXImageSink *ximagesink = GST_XIMAGESINK (overlay);
  }
  
  static void
 -gst_ximagesink_xoverlay_init (GstXOverlayClass * iface)
 +gst_ximagesink_video_overlay_init (GstVideoOverlayInterface * iface)
  {
    iface->set_window_handle = gst_ximagesink_set_window_handle;
    iface->expose = gst_ximagesink_expose;
@@@ -1738,7 -2210,7 +1745,7 @@@ gst_ximagesink_set_property (GObject * 
      }
        break;
      case PROP_HANDLE_EVENTS:
 -      gst_ximagesink_set_event_handling (GST_X_OVERLAY (ximagesink),
 +      gst_ximagesink_set_event_handling (GST_VIDEO_OVERLAY (ximagesink),
            g_value_get_boolean (value));
        gst_ximagesink_manage_event_thread (ximagesink);
        break;
@@@ -1816,18 -2288,18 +1823,18 @@@ gst_ximagesink_reset (GstXImageSink * x
    if (thread)
      g_thread_join (thread);
  
 -  if (ximagesink->ximage) {
 -    gst_buffer_unref (GST_BUFFER_CAST (ximagesink->ximage));
 -    ximagesink->ximage = NULL;
 -  }
    if (ximagesink->cur_image) {
 -    gst_buffer_unref (GST_BUFFER_CAST (ximagesink->cur_image));
 +    gst_buffer_unref (ximagesink->cur_image);
      ximagesink->cur_image = NULL;
    }
  
 -  gst_ximagesink_bufferpool_clear (ximagesink);
 -
    g_mutex_lock (ximagesink->flow_lock);
 +
 +  if (ximagesink->pool) {
 +    gst_object_unref (ximagesink->pool);
 +    ximagesink->pool = NULL;
 +  }
 +
    if (ximagesink->xwindow) {
      gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow);
      gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow);
@@@ -1863,6 -2335,10 +1870,6 @@@ gst_ximagesink_finalize (GObject * obje
      g_mutex_free (ximagesink->flow_lock);
      ximagesink->flow_lock = NULL;
    }
 -  if (ximagesink->pool_lock) {
 -    g_mutex_free (ximagesink->pool_lock);
 -    ximagesink->pool_lock = NULL;
 -  }
  
    g_free (ximagesink->media_title);
  
@@@ -1875,6 -2351,7 +1882,6 @@@ gst_ximagesink_init (GstXImageSink * xi
    ximagesink->display_name = NULL;
    ximagesink->xcontext = NULL;
    ximagesink->xwindow = NULL;
 -  ximagesink->ximage = NULL;
    ximagesink->cur_image = NULL;
  
    ximagesink->event_thread = NULL;
  
    ximagesink->par = NULL;
  
 -  ximagesink->pool_lock = g_mutex_new ();
 -  ximagesink->buffer_pool = NULL;
 +  ximagesink->pool = NULL;
  
    ximagesink->synchronous = FALSE;
    ximagesink->keep_aspect = FALSE;
  }
  
  static void
 -gst_ximagesink_base_init (gpointer g_class)
 -{
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 -
 -  gst_element_class_set_details_simple (element_class,
 -      "Video sink", "Sink/Video",
 -      "A standard X based videosink", "Julien Moutte <julien@moutte.net>");
 -
 -  gst_element_class_add_static_pad_template (element_class,
 -      &gst_ximagesink_sink_template_factory);
 -}
 -
 -static void
  gst_ximagesink_class_init (GstXImageSinkClass * klass)
  {
    GObjectClass *gobject_class;
    gstbasesink_class = (GstBaseSinkClass *) klass;
    videosink_class = (GstVideoSinkClass *) klass;
  
 -  parent_class = g_type_class_peek_parent (klass);
 -
    gobject_class->finalize = gst_ximagesink_finalize;
    gobject_class->set_property = gst_ximagesink_set_property;
    gobject_class->get_property = gst_ximagesink_get_property;
            "Height of the window", 0, G_MAXUINT64, 0,
            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
  
 +  gst_element_class_set_details_simple (gstelement_class,
 +      "Video sink", "Sink/Video",
 +      "A standard X based videosink", "Julien Moutte <julien@moutte.net>");
 +
 +  gst_element_class_add_pad_template (gstelement_class,
 +      gst_static_pad_template_get (&gst_ximagesink_sink_template_factory));
 +
    gstelement_class->change_state = gst_ximagesink_change_state;
  
    gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_getcaps);
    gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_setcaps);
 -  gstbasesink_class->buffer_alloc =
 -      GST_DEBUG_FUNCPTR (gst_ximagesink_buffer_alloc);
    gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_ximagesink_get_times);
 +  gstbasesink_class->propose_allocation =
 +      GST_DEBUG_FUNCPTR (gst_ximagesink_propose_allocation);
    gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_ximagesink_event);
  
    videosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_ximagesink_show_frame);
  }
 -
 -/* ============================================================= */
 -/*                                                               */
 -/*                       Public Methods                          */
 -/*                                                               */
 -/* ============================================================= */
 -
 -/* =========================================== */
 -/*                                             */
 -/*          Object typing & Creation           */
 -/*                                             */
 -/* =========================================== */
 -
 -GType
 -gst_ximagesink_get_type (void)
 -{
 -  static GType ximagesink_type = 0;
 -
 -  if (!ximagesink_type) {
 -    static const GTypeInfo ximagesink_info = {
 -      sizeof (GstXImageSinkClass),
 -      gst_ximagesink_base_init,
 -      NULL,
 -      (GClassInitFunc) gst_ximagesink_class_init,
 -      NULL,
 -      NULL,
 -      sizeof (GstXImageSink), 0, (GInstanceInitFunc) gst_ximagesink_init,
 -    };
 -    static const GInterfaceInfo iface_info = {
 -      (GInterfaceInitFunc) gst_ximagesink_interface_init, NULL, NULL,
 -    };
 -    static const GInterfaceInfo navigation_info = {
 -      (GInterfaceInitFunc) gst_ximagesink_navigation_init, NULL, NULL,
 -    };
 -    static const GInterfaceInfo overlay_info = {
 -      (GInterfaceInitFunc) gst_ximagesink_xoverlay_init, NULL, NULL,
 -    };
 -
 -    ximagesink_type = g_type_register_static (GST_TYPE_VIDEO_SINK,
 -        "GstXImageSink", &ximagesink_info, 0);
 -
 -    g_type_add_interface_static (ximagesink_type, GST_TYPE_IMPLEMENTS_INTERFACE,
 -        &iface_info);
 -    g_type_add_interface_static (ximagesink_type, GST_TYPE_NAVIGATION,
 -        &navigation_info);
 -    g_type_add_interface_static (ximagesink_type, GST_TYPE_X_OVERLAY,
 -        &overlay_info);
 -
 -    /* register type and create class in a more safe place instead of at
 -     * runtime since the type registration and class creation is not
 -     * threadsafe. */
 -    g_type_class_ref (gst_ximage_buffer_get_type ());
 -  }
 -
 -  return ximagesink_type;
 -}
@@@ -94,7 -94,7 +94,7 @@@
   * position. This also handles borders correctly, limiting coordinates to the
   * image area
   * |[
 - * gst-launch -v videotestsrc ! video/x-raw-yuv, pixel-aspect-ratio=(fraction)4/3 ! xvimagesink
 + * gst-launch -v videotestsrc ! video/x-raw, pixel-aspect-ratio=(fraction)4/3 ! xvimagesink
   * ]| This is faking a 4/3 pixel aspect ratio caps on video frames produced by
   * videotestsrc, in most cases the pixel aspect ratio of the display will be
   * 1/1. This means that XvImageSink will have to do the scaling to convert
  
  /* Our interfaces */
  #include <gst/interfaces/navigation.h>
 -#include <gst/interfaces/xoverlay.h>
 -#include <gst/interfaces/colorbalance.h>
  #include <gst/interfaces/propertyprobe.h>
 +#include <gst/video/videooverlay.h>
 +#include <gst/video/colorbalance.h>
  /* Helper functions */
 -#include <gst/video/video.h>
 +#include <gst/video/gstvideometa.h>
  
  /* Object header */
  #include "xvimagesink.h"
  /* Debugging category */
  #include <gst/gstinfo.h>
  
 -GST_DEBUG_CATEGORY_STATIC (gst_debug_xvimagesink);
+ #include "gst/glib-compat-private.h"
 +GST_DEBUG_CATEGORY_EXTERN (gst_debug_xvimagesink);
 +GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE);
  #define GST_CAT_DEFAULT gst_debug_xvimagesink
 -GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
  
  typedef struct
  {
@@@ -144,17 -146,27 +146,17 @@@ MotifWmHints, MwmHints
  #define MWM_HINTS_DECORATIONS   (1L << 1)
  
  static void gst_xvimagesink_reset (GstXvImageSink * xvimagesink);
 -
 -static GstBufferClass *xvimage_buffer_parent_class = NULL;
 -static void gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage);
 -
  static void gst_xvimagesink_xwindow_update_geometry (GstXvImageSink *
      xvimagesink);
 -static gint gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
 -    GstCaps * caps);
 -static void gst_xvimagesink_expose (GstXOverlay * overlay);
 +static void gst_xvimagesink_expose (GstVideoOverlay * overlay);
  
  /* Default template - initiated with class struct to allow gst-register to work
     without X running */
  static GstStaticPadTemplate gst_xvimagesink_sink_template_factory =
 -    GST_STATIC_PAD_TEMPLATE ("sink",
 +GST_STATIC_PAD_TEMPLATE ("sink",
      GST_PAD_SINK,
      GST_PAD_ALWAYS,
 -    GST_STATIC_CAPS ("video/x-raw-rgb, "
 -        "framerate = (fraction) [ 0, MAX ], "
 -        "width = (int) [ 1, MAX ], "
 -        "height = (int) [ 1, MAX ]; "
 -        "video/x-raw-yuv, "
 +    GST_STATIC_CAPS ("video/x-raw, "
          "framerate = (fraction) [ 0, MAX ], "
          "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
      );
@@@ -182,43 -194,548 +184,43 @@@ enu
    PROP_WINDOW_HEIGHT
  };
  
 -static void gst_xvimagesink_init_interfaces (GType type);
 -
 -GST_BOILERPLATE_FULL (GstXvImageSink, gst_xvimagesink, GstVideoSink,
 -    GST_TYPE_VIDEO_SINK, gst_xvimagesink_init_interfaces);
 -
 -
  /* ============================================================= */
  /*                                                               */
 -/*                       Private Methods                         */
 +/*                       Public Methods                          */
  /*                                                               */
  /* ============================================================= */
  
 -/* xvimage buffers */
 -
 -#define GST_TYPE_XVIMAGE_BUFFER (gst_xvimage_buffer_get_type())
 -
 -#define GST_IS_XVIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XVIMAGE_BUFFER))
 -#define GST_XVIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XVIMAGE_BUFFER, GstXvImageBuffer))
 -#define GST_XVIMAGE_BUFFER_CAST(obj) ((GstXvImageBuffer *)(obj))
 -
 -/* This function destroys a GstXvImage handling XShm availability */
 -static void
 -gst_xvimage_buffer_destroy (GstXvImageBuffer * xvimage)
 -{
 -  GstXvImageSink *xvimagesink;
 -
 -  GST_DEBUG_OBJECT (xvimage, "Destroying buffer");
 -
 -  xvimagesink = xvimage->xvimagesink;
 -  if (G_UNLIKELY (xvimagesink == NULL))
 -    goto no_sink;
 -
 -  g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
 -
 -  GST_OBJECT_LOCK (xvimagesink);
 -
 -  /* If the destroyed image is the current one we destroy our reference too */
 -  if (xvimagesink->cur_image == xvimage)
 -    xvimagesink->cur_image = NULL;
 -
 -  /* We might have some buffers destroyed after changing state to NULL */
 -  if (xvimagesink->xcontext == NULL) {
 -    GST_DEBUG_OBJECT (xvimagesink, "Destroying XvImage after Xcontext");
 -#ifdef HAVE_XSHM
 -    /* Need to free the shared memory segment even if the x context
 -     * was already cleaned up */
 -    if (xvimage->SHMInfo.shmaddr != ((void *) -1)) {
 -      shmdt (xvimage->SHMInfo.shmaddr);
 -    }
 -#endif
 -    goto beach;
 -  }
 -
 -  g_mutex_lock (xvimagesink->x_lock);
 -
 -#ifdef HAVE_XSHM
 -  if (xvimagesink->xcontext->use_xshm) {
 -    if (xvimage->SHMInfo.shmaddr != ((void *) -1)) {
 -      GST_DEBUG_OBJECT (xvimagesink, "XServer ShmDetaching from 0x%x id 0x%lx",
 -          xvimage->SHMInfo.shmid, xvimage->SHMInfo.shmseg);
 -      XShmDetach (xvimagesink->xcontext->disp, &xvimage->SHMInfo);
 -      XSync (xvimagesink->xcontext->disp, FALSE);
 -
 -      shmdt (xvimage->SHMInfo.shmaddr);
 -    }
 -    if (xvimage->xvimage)
 -      XFree (xvimage->xvimage);
 -  } else
 -#endif /* HAVE_XSHM */
 -  {
 -    if (xvimage->xvimage) {
 -      if (xvimage->xvimage->data) {
 -        g_free (xvimage->xvimage->data);
 -      }
 -      XFree (xvimage->xvimage);
 -    }
 -  }
 -
 -  XSync (xvimagesink->xcontext->disp, FALSE);
 -
 -  g_mutex_unlock (xvimagesink->x_lock);
 -
 -beach:
 -  GST_OBJECT_UNLOCK (xvimagesink);
 -  xvimage->xvimagesink = NULL;
 -  gst_object_unref (xvimagesink);
 -
 -  GST_MINI_OBJECT_CLASS (xvimage_buffer_parent_class)->finalize (GST_MINI_OBJECT
 -      (xvimage));
 -
 -  return;
 -
 -no_sink:
 -  {
 -    GST_WARNING ("no sink found");
 -    return;
 -  }
 -}
 -
 -static void
 -gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage)
 -{
 -  GstXvImageSink *xvimagesink;
 -  gboolean running;
 -
 -  xvimagesink = xvimage->xvimagesink;
 -  if (G_UNLIKELY (xvimagesink == NULL))
 -    goto no_sink;
 -
 -  g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
 -
 -  GST_OBJECT_LOCK (xvimagesink);
 -  running = xvimagesink->running;
 -  GST_OBJECT_UNLOCK (xvimagesink);
 -
 -  /* If our geometry changed we can't reuse that image. */
 -  if (running == FALSE) {
 -    GST_LOG_OBJECT (xvimage, "destroy image as sink is shutting down");
 -    gst_xvimage_buffer_destroy (xvimage);
 -  } else if ((xvimage->width != xvimagesink->video_width) ||
 -      (xvimage->height != xvimagesink->video_height)) {
 -    GST_LOG_OBJECT (xvimage,
 -        "destroy image as its size changed %dx%d vs current %dx%d",
 -        xvimage->width, xvimage->height,
 -        xvimagesink->video_width, xvimagesink->video_height);
 -    gst_xvimage_buffer_destroy (xvimage);
 -  } else {
 -    /* In that case we can reuse the image and add it to our image pool. */
 -    GST_LOG_OBJECT (xvimage, "recycling image in pool");
 -    /* need to increment the refcount again to recycle */
 -    gst_buffer_ref (GST_BUFFER_CAST (xvimage));
 -    g_mutex_lock (xvimagesink->pool_lock);
 -    xvimagesink->image_pool = g_slist_prepend (xvimagesink->image_pool,
 -        xvimage);
 -    g_mutex_unlock (xvimagesink->pool_lock);
 -  }
 -  return;
 -
 -no_sink:
 -  {
 -    GST_WARNING ("no sink found");
 -    return;
 -  }
 -}
 -
 -static void
 -gst_xvimage_buffer_free (GstXvImageBuffer * xvimage)
 -{
 -  /* make sure it is not recycled */
 -  xvimage->width = -1;
 -  xvimage->height = -1;
 -  gst_buffer_unref (GST_BUFFER (xvimage));
 -}
 -
 -static void
 -gst_xvimage_buffer_init (GstXvImageBuffer * xvimage, gpointer g_class)
 -{
 -#ifdef HAVE_XSHM
 -  xvimage->SHMInfo.shmaddr = ((void *) -1);
 -  xvimage->SHMInfo.shmid = -1;
 -#endif
 -}
 -
 +/* =========================================== */
 +/*                                             */
 +/*          Object typing & Creation           */
 +/*                                             */
 +/* =========================================== */
 +static void gst_xvimagesink_navigation_init (GstNavigationInterface * iface);
 +static void gst_xvimagesink_video_overlay_init (GstVideoOverlayInterface *
 +    iface);
 +static void gst_xvimagesink_colorbalance_init (GstColorBalanceInterface *
 +    iface);
  static void
 -gst_xvimage_buffer_class_init (gpointer g_class, gpointer class_data)
 -{
 -  GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
 -
 -  xvimage_buffer_parent_class = g_type_class_peek_parent (g_class);
 -
 -  mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
 -      gst_xvimage_buffer_finalize;
 -}
 -
 -static GType
 -gst_xvimage_buffer_get_type (void)
 -{
 -  static GType _gst_xvimage_buffer_type;
 -
 -  if (G_UNLIKELY (_gst_xvimage_buffer_type == 0)) {
 -    static const GTypeInfo xvimage_buffer_info = {
 -      sizeof (GstBufferClass),
 -      NULL,
 -      NULL,
 -      gst_xvimage_buffer_class_init,
 -      NULL,
 -      NULL,
 -      sizeof (GstXvImageBuffer),
 -      0,
 -      (GInstanceInitFunc) gst_xvimage_buffer_init,
 -      NULL
 -    };
 -    _gst_xvimage_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
 -        "GstXvImageBuffer", &xvimage_buffer_info, 0);
 -  }
 -  return _gst_xvimage_buffer_type;
 -}
 -
 -/* X11 stuff */
 -
 -static gboolean error_caught = FALSE;
 -
 -static int
 -gst_xvimagesink_handle_xerror (Display * display, XErrorEvent * xevent)
 -{
 -  char error_msg[1024];
 -
 -  XGetErrorText (display, xevent->error_code, error_msg, 1024);
 -  GST_DEBUG ("xvimagesink triggered an XError. error: %s", error_msg);
 -  error_caught = TRUE;
 -  return 0;
 -}
 -
 -#ifdef HAVE_XSHM
 -/* This function checks that it is actually really possible to create an image
 -   using XShm */
 -static gboolean
 -gst_xvimagesink_check_xshm_calls (GstXContext * xcontext)
 -{
 -  XvImage *xvimage;
 -  XShmSegmentInfo SHMInfo;
 -  gint size;
 -  int (*handler) (Display *, XErrorEvent *);
 -  gboolean result = FALSE;
 -  gboolean did_attach = FALSE;
 -
 -  g_return_val_if_fail (xcontext != NULL, FALSE);
 -
 -  /* Sync to ensure any older errors are already processed */
 -  XSync (xcontext->disp, FALSE);
 -
 -  /* Set defaults so we don't free these later unnecessarily */
 -  SHMInfo.shmaddr = ((void *) -1);
 -  SHMInfo.shmid = -1;
 -
 -  /* Setting an error handler to catch failure */
 -  error_caught = FALSE;
 -  handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);
 -
 -  /* Trying to create a 1x1 picture */
 -  GST_DEBUG ("XvShmCreateImage of 1x1");
 -  xvimage = XvShmCreateImage (xcontext->disp, xcontext->xv_port_id,
 -      xcontext->im_format, NULL, 1, 1, &SHMInfo);
 -
 -  /* Might cause an error, sync to ensure it is noticed */
 -  XSync (xcontext->disp, FALSE);
 -  if (!xvimage || error_caught) {
 -    GST_WARNING ("could not XvShmCreateImage a 1x1 image");
 -    goto beach;
 -  }
 -  size = xvimage->data_size;
 -
 -  SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
 -  if (SHMInfo.shmid == -1) {
 -    GST_WARNING ("could not get shared memory of %d bytes", size);
 -    goto beach;
 -  }
 -
 -  SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0);
 -  if (SHMInfo.shmaddr == ((void *) -1)) {
 -    GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
 -    /* Clean up the shared memory segment */
 -    shmctl (SHMInfo.shmid, IPC_RMID, NULL);
 -    goto beach;
 -  }
 -
 -  xvimage->data = SHMInfo.shmaddr;
 -  SHMInfo.readOnly = FALSE;
 -
 -  if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
 -    GST_WARNING ("Failed to XShmAttach");
 -    /* Clean up the shared memory segment */
 -    shmctl (SHMInfo.shmid, IPC_RMID, NULL);
 -    goto beach;
 -  }
 -
 -  /* Sync to ensure we see any errors we caused */
 -  XSync (xcontext->disp, FALSE);
 -
 -  /* Delete the shared memory segment as soon as everyone is attached.
 -   * This way, it will be deleted as soon as we detach later, and not
 -   * leaked if we crash. */
 -  shmctl (SHMInfo.shmid, IPC_RMID, NULL);
 -
 -  if (!error_caught) {
 -    GST_DEBUG ("XServer ShmAttached to 0x%x, id 0x%lx", SHMInfo.shmid,
 -        SHMInfo.shmseg);
 -
 -    did_attach = TRUE;
 -    /* store whether we succeeded in result */
 -    result = TRUE;
 -  } else {
 -    GST_WARNING ("MIT-SHM extension check failed at XShmAttach. "
 -        "Not using shared memory.");
 -  }
 -
 -beach:
 -  /* Sync to ensure we swallow any errors we caused and reset error_caught */
 -  XSync (xcontext->disp, FALSE);
 -
 -  error_caught = FALSE;
 -  XSetErrorHandler (handler);
 -
 -  if (did_attach) {
 -    GST_DEBUG ("XServer ShmDetaching from 0x%x id 0x%lx",
 -        SHMInfo.shmid, SHMInfo.shmseg);
 -    XShmDetach (xcontext->disp, &SHMInfo);
 -    XSync (xcontext->disp, FALSE);
 -  }
 -  if (SHMInfo.shmaddr != ((void *) -1))
 -    shmdt (SHMInfo.shmaddr);
 -  if (xvimage)
 -    XFree (xvimage);
 -  return result;
 -}
 -#endif /* HAVE_XSHM */
 -
 -/* This function handles GstXvImage creation depending on XShm availability */
 -static GstXvImageBuffer *
 -gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
 -{
 -  GstXvImageBuffer *xvimage = NULL;
 -  GstStructure *structure = NULL;
 -  gboolean succeeded = FALSE;
 -  int (*handler) (Display *, XErrorEvent *);
 -
 -  g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
 -
 -  if (caps == NULL)
 -    return NULL;
 -
 -  xvimage = (GstXvImageBuffer *) gst_mini_object_new (GST_TYPE_XVIMAGE_BUFFER);
 -  GST_DEBUG_OBJECT (xvimage, "Creating new XvImageBuffer");
 -
 -  structure = gst_caps_get_structure (caps, 0);
 -
 -  if (!gst_structure_get_int (structure, "width", &xvimage->width) ||
 -      !gst_structure_get_int (structure, "height", &xvimage->height)) {
 -    GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps);
 -  }
 -
 -  GST_LOG_OBJECT (xvimagesink, "creating %dx%d", xvimage->width,
 -      xvimage->height);
 -
 -  xvimage->im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
 -  if (xvimage->im_format == -1) {
 -    GST_WARNING_OBJECT (xvimagesink, "failed to get format from caps %"
 -        GST_PTR_FORMAT, caps);
 -    GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
 -        ("Failed to create output image buffer of %dx%d pixels",
 -            xvimage->width, xvimage->height), ("Invalid input caps"));
 -    goto beach_unlocked;
 -  }
 -  xvimage->xvimagesink = gst_object_ref (xvimagesink);
 -
 -  g_mutex_lock (xvimagesink->x_lock);
 -
 -  /* Setting an error handler to catch failure */
 -  error_caught = FALSE;
 -  handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);
 -
 -#ifdef HAVE_XSHM
 -  if (xvimagesink->xcontext->use_xshm) {
 -    int expected_size;
 -
 -    xvimage->xvimage = XvShmCreateImage (xvimagesink->xcontext->disp,
 -        xvimagesink->xcontext->xv_port_id,
 -        xvimage->im_format, NULL,
 -        xvimage->width, xvimage->height, &xvimage->SHMInfo);
 -    if (!xvimage->xvimage || error_caught) {
 -      g_mutex_unlock (xvimagesink->x_lock);
 -
 -      /* Reset error flag */
 -      error_caught = FALSE;
 -
 -      /* Push a warning */
 -      GST_ELEMENT_WARNING (xvimagesink, RESOURCE, WRITE,
 -          ("Failed to create output image buffer of %dx%d pixels",
 -              xvimage->width, xvimage->height),
 -          ("could not XvShmCreateImage a %dx%d image",
 -              xvimage->width, xvimage->height));
 -
 -      /* Retry without XShm */
 -      xvimagesink->xcontext->use_xshm = FALSE;
 -
 -      /* Hold X mutex again to try without XShm */
 -      g_mutex_lock (xvimagesink->x_lock);
 -      goto no_xshm;
 -    }
 -
 -    /* we have to use the returned data_size for our shm size */
 -    xvimage->size = xvimage->xvimage->data_size;
 -    GST_LOG_OBJECT (xvimagesink, "XShm image size is %" G_GSIZE_FORMAT,
 -        xvimage->size);
 -
 -    /* calculate the expected size.  This is only for sanity checking the
 -     * number we get from X. */
 -    switch (xvimage->im_format) {
 -      case GST_MAKE_FOURCC ('I', '4', '2', '0'):
 -      case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
 -      {
 -        gint pitches[3];
 -        gint offsets[3];
 -        guint plane;
 -
 -        offsets[0] = 0;
 -        pitches[0] = GST_ROUND_UP_4 (xvimage->width);
 -        offsets[1] = offsets[0] + pitches[0] * GST_ROUND_UP_2 (xvimage->height);
 -        pitches[1] = GST_ROUND_UP_8 (xvimage->width) / 2;
 -        offsets[2] =
 -            offsets[1] + pitches[1] * GST_ROUND_UP_2 (xvimage->height) / 2;
 -        pitches[2] = GST_ROUND_UP_8 (pitches[0]) / 2;
 -
 -        expected_size =
 -            offsets[2] + pitches[2] * GST_ROUND_UP_2 (xvimage->height) / 2;
 -
 -        for (plane = 0; plane < xvimage->xvimage->num_planes; plane++) {
 -          GST_DEBUG_OBJECT (xvimagesink,
 -              "Plane %u has a expected pitch of %d bytes, " "offset of %d",
 -              plane, pitches[plane], offsets[plane]);
 -        }
 -        break;
 -      }
 -      case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
 -      case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
 -        expected_size = xvimage->height * GST_ROUND_UP_4 (xvimage->width * 2);
 -        break;
 -      default:
 -        expected_size = 0;
 -        break;
 -    }
 -    if (expected_size != 0 && xvimage->size != expected_size) {
 -      GST_WARNING_OBJECT (xvimagesink,
 -          "unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)",
 -          xvimage->size, expected_size);
 -    }
 -
 -    /* Be verbose about our XvImage stride */
 -    {
 -      guint plane;
 -
 -      for (plane = 0; plane < xvimage->xvimage->num_planes; plane++) {
 -        GST_DEBUG_OBJECT (xvimagesink, "Plane %u has a pitch of %d bytes, "
 -            "offset of %d", plane, xvimage->xvimage->pitches[plane],
 -            xvimage->xvimage->offsets[plane]);
 -      }
 -    }
 -
 -    xvimage->SHMInfo.shmid = shmget (IPC_PRIVATE, xvimage->size,
 -        IPC_CREAT | 0777);
 -    if (xvimage->SHMInfo.shmid == -1) {
 -      g_mutex_unlock (xvimagesink->x_lock);
 -      GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
 -          ("Failed to create output image buffer of %dx%d pixels",
 -              xvimage->width, xvimage->height),
 -          ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
 -              xvimage->size));
 -      goto beach_unlocked;
 -    }
 -
 -    xvimage->SHMInfo.shmaddr = shmat (xvimage->SHMInfo.shmid, NULL, 0);
 -    if (xvimage->SHMInfo.shmaddr == ((void *) -1)) {
 -      g_mutex_unlock (xvimagesink->x_lock);
 -      GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
 -          ("Failed to create output image buffer of %dx%d pixels",
 -              xvimage->width, xvimage->height),
 -          ("Failed to shmat: %s", g_strerror (errno)));
 -      /* Clean up the shared memory segment */
 -      shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
 -      goto beach_unlocked;
 -    }
 -
 -    xvimage->xvimage->data = xvimage->SHMInfo.shmaddr;
 -    xvimage->SHMInfo.readOnly = FALSE;
 -
 -    if (XShmAttach (xvimagesink->xcontext->disp, &xvimage->SHMInfo) == 0) {
 -      /* Clean up the shared memory segment */
 -      shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
 -
 -      g_mutex_unlock (xvimagesink->x_lock);
 -      GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
 -          ("Failed to create output image buffer of %dx%d pixels",
 -              xvimage->width, xvimage->height), ("Failed to XShmAttach"));
 -      goto beach_unlocked;
 -    }
 -
 -    XSync (xvimagesink->xcontext->disp, FALSE);
 -
 -    /* Delete the shared memory segment as soon as we everyone is attached.
 -     * This way, it will be deleted as soon as we detach later, and not
 -     * leaked if we crash. */
 -    shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
 -
 -    GST_DEBUG_OBJECT (xvimagesink, "XServer ShmAttached to 0x%x, id 0x%lx",
 -        xvimage->SHMInfo.shmid, xvimage->SHMInfo.shmseg);
 -  } else
 -  no_xshm:
 -#endif /* HAVE_XSHM */
 -  {
 -    xvimage->xvimage = XvCreateImage (xvimagesink->xcontext->disp,
 -        xvimagesink->xcontext->xv_port_id,
 -        xvimage->im_format, NULL, xvimage->width, xvimage->height);
 -    if (!xvimage->xvimage || error_caught) {
 -      g_mutex_unlock (xvimagesink->x_lock);
 -      /* Reset error handler */
 -      error_caught = FALSE;
 -      XSetErrorHandler (handler);
 -      /* Push an error */
 -      GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
 -          ("Failed to create outputimage buffer of %dx%d pixels",
 -              xvimage->width, xvimage->height),
 -          ("could not XvCreateImage a %dx%d image",
 -              xvimage->width, xvimage->height));
 -      goto beach_unlocked;
 -    }
 -
 -    /* we have to use the returned data_size for our image size */
 -    xvimage->size = xvimage->xvimage->data_size;
 -    xvimage->xvimage->data = g_malloc (xvimage->size);
 -
 -    XSync (xvimagesink->xcontext->disp, FALSE);
 -  }
 -
 -  /* Reset error handler */
 -  error_caught = FALSE;
 -  XSetErrorHandler (handler);
 -
 -  succeeded = TRUE;
 -
 -  GST_BUFFER_DATA (xvimage) = (guchar *) xvimage->xvimage->data;
 -  GST_BUFFER_SIZE (xvimage) = xvimage->size;
 +gst_xvimagesink_property_probe_interface_init (GstPropertyProbeInterface *
 +    iface);
 +#define gst_xvimagesink_parent_class parent_class
 +G_DEFINE_TYPE_WITH_CODE (GstXvImageSink, gst_xvimagesink, GST_TYPE_VIDEO_SINK,
 +    G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION,
 +        gst_xvimagesink_navigation_init);
 +    G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY,
 +        gst_xvimagesink_video_overlay_init);
 +    G_IMPLEMENT_INTERFACE (GST_TYPE_COLOR_BALANCE,
 +        gst_xvimagesink_colorbalance_init);
 +    G_IMPLEMENT_INTERFACE (GST_TYPE_PROPERTY_PROBE,
 +        gst_xvimagesink_property_probe_interface_init));
  
 -  g_mutex_unlock (xvimagesink->x_lock);
  
 -beach_unlocked:
 -  if (!succeeded) {
 -    gst_xvimage_buffer_free (xvimage);
 -    xvimage = NULL;
 -  }
 +/* ============================================================= */
 +/*                                                               */
 +/*                       Private Methods                         */
 +/*                                                               */
 +/* ============================================================= */
  
 -  return xvimage;
 -}
  
  /* We are called with the x_lock taken */
  static void
@@@ -267,13 -784,11 +269,13 @@@ gst_xvimagesink_xwindow_draw_borders (G
  /* This function puts a GstXvImage on a GstXvImageSink's window. Returns FALSE
   * if no window was available  */
  static gboolean
 -gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
 -    GstXvImageBuffer * xvimage)
 +gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, GstBuffer * xvimage)
  {
 +  GstXvImageMeta *meta;
 +  GstVideoCropMeta *crop;
    GstVideoRectangle result;
    gboolean draw_border = FALSE;
 +  GstVideoRectangle src, dst;
  
    /* We take the flow_lock. If expose is in there we don't want to run
       concurrently from the data flow thread */
    if (xvimage && xvimagesink->cur_image != xvimage) {
      if (xvimagesink->cur_image) {
        GST_LOG_OBJECT (xvimagesink, "unreffing %p", xvimagesink->cur_image);
 -      gst_buffer_unref (GST_BUFFER_CAST (xvimagesink->cur_image));
 +      gst_buffer_unref (xvimagesink->cur_image);
      }
      GST_LOG_OBJECT (xvimagesink, "reffing %p as our current image", xvimage);
 -    xvimagesink->cur_image =
 -        GST_XVIMAGE_BUFFER_CAST (gst_buffer_ref (GST_BUFFER_CAST (xvimage)));
 +    xvimagesink->cur_image = gst_buffer_ref (xvimage);
    }
  
    /* Expose sends a NULL image, we take the latest frame */
      }
    }
  
 -  if (xvimagesink->keep_aspect) {
 -    GstVideoRectangle src, dst;
 +  meta = gst_buffer_get_xvimage_meta (xvimage);
  
 -    /* We use the calculated geometry from _setcaps as a source to respect
 -       source and screen pixel aspect ratios. */
 -    src.w = GST_VIDEO_SINK_WIDTH (xvimagesink);
 -    src.h = GST_VIDEO_SINK_HEIGHT (xvimagesink);
 +  crop = gst_buffer_get_video_crop_meta (xvimage);
 +
 +  if (crop) {
 +    src.x = crop->x + meta->x;
 +    src.y = crop->y + meta->y;
 +    src.w = crop->width;
 +    src.h = crop->height;
 +  } else {
 +    src.x = meta->x;
 +    src.y = meta->y;
 +    src.w = meta->width;
 +    src.h = meta->height;
 +  }
 +
 +  if (xvimagesink->keep_aspect) {
      dst.w = xvimagesink->render_rect.w;
      dst.h = xvimagesink->render_rect.h;
  
          result);
      xvimagesink->redraw_border = FALSE;
    }
 -
 -  /* We scale to the window's geometry */
  #ifdef HAVE_XSHM
    if (xvimagesink->xcontext->use_xshm) {
      GST_LOG_OBJECT (xvimagesink,
          "XvShmPutImage with image %dx%d and window %dx%d, from xvimage %"
 -        GST_PTR_FORMAT,
 -        xvimage->width, xvimage->height,
 +        GST_PTR_FORMAT, meta->width, meta->height,
          xvimagesink->render_rect.w, xvimagesink->render_rect.h, xvimage);
  
      XvShmPutImage (xvimagesink->xcontext->disp,
          xvimagesink->xcontext->xv_port_id,
          xvimagesink->xwindow->win,
 -        xvimagesink->xwindow->gc, xvimage->xvimage,
 -        xvimagesink->disp_x, xvimagesink->disp_y,
 -        xvimagesink->disp_width, xvimagesink->disp_height,
 +        xvimagesink->xwindow->gc, meta->xvimage,
 +        src.x, src.y, src.w, src.h,
          result.x, result.y, result.w, result.h, FALSE);
    } else
  #endif /* HAVE_XSHM */
      XvPutImage (xvimagesink->xcontext->disp,
          xvimagesink->xcontext->xv_port_id,
          xvimagesink->xwindow->win,
 -        xvimagesink->xwindow->gc, xvimage->xvimage,
 -        xvimagesink->disp_x, xvimagesink->disp_y,
 -        xvimagesink->disp_width, xvimagesink->disp_height,
 -        result.x, result.y, result.w, result.h);
 +        xvimagesink->xwindow->gc, meta->xvimage,
 +        src.x, src.y, src.w, src.h, result.x, result.y, result.w, result.h);
    }
  
    XSync (xvimagesink->xcontext->disp, FALSE);
@@@ -517,8 -1029,7 +519,8 @@@ gst_xvimagesink_xwindow_new (GstXvImage
  
    gst_xvimagesink_xwindow_decorate (xvimagesink, xwindow);
  
 -  gst_x_overlay_got_window_handle (GST_X_OVERLAY (xvimagesink), xwindow->win);
 +  gst_video_overlay_got_window_handle (GST_VIDEO_OVERLAY (xvimagesink),
 +      xwindow->win);
  
    return xwindow;
  }
@@@ -700,7 -1211,6 +702,7 @@@ gst_xvimagesink_handle_xevents (GstXvIm
      g_mutex_lock (xvimagesink->flow_lock);
      g_mutex_lock (xvimagesink->x_lock);
    }
 +
    if (pointer_moved) {
      g_mutex_unlock (xvimagesink->x_lock);
      g_mutex_unlock (xvimagesink->flow_lock);
          }
          break;
        default:
 -        GST_DEBUG ("xvimagesink unhandled X event (%d)", e.type);
 +        GST_DEBUG_OBJECT (xvimagesink, "xvimagesink unhandled X event (%d)",
 +            e.type);
      }
      g_mutex_lock (xvimagesink->flow_lock);
      g_mutex_lock (xvimagesink->x_lock);
      g_mutex_unlock (xvimagesink->x_lock);
      g_mutex_unlock (xvimagesink->flow_lock);
  
 -    gst_xvimagesink_expose (GST_X_OVERLAY (xvimagesink));
 +    gst_xvimagesink_expose (GST_VIDEO_OVERLAY (xvimagesink));
  
      g_mutex_lock (xvimagesink->flow_lock);
      g_mutex_lock (xvimagesink->x_lock);
@@@ -1045,7 -1554,6 +1047,7 @@@ gst_xvimagesink_get_xv_support (GstXvIm
    for (i = 0; i < nb_formats; i++) {
      GstCaps *format_caps = NULL;
      gboolean is_rgb_format = FALSE;
 +    GstVideoFormat vformat;
  
      /* We set the image format of the xcontext to an existing one. This
         is just some valid image format for making our xshm calls check before
        case XvRGB:
        {
          XvImageFormatValues *fmt = &(formats[i]);
 -        gint endianness = G_BIG_ENDIAN;
 -
 -        if (fmt->byte_order == LSBFirst) {
 -          /* our caps system handles 24/32bpp RGB as big-endian. */
 -          if (fmt->bits_per_pixel == 24 || fmt->bits_per_pixel == 32) {
 -            fmt->red_mask = GUINT32_TO_BE (fmt->red_mask);
 -            fmt->green_mask = GUINT32_TO_BE (fmt->green_mask);
 -            fmt->blue_mask = GUINT32_TO_BE (fmt->blue_mask);
 -
 -            if (fmt->bits_per_pixel == 24) {
 -              fmt->red_mask >>= 8;
 -              fmt->green_mask >>= 8;
 -              fmt->blue_mask >>= 8;
 -            }
 -          } else
 -            endianness = G_LITTLE_ENDIAN;
 -        }
 +        gint endianness;
 +
 +        endianness =
 +            (fmt->byte_order == LSBFirst ? G_LITTLE_ENDIAN : G_BIG_ENDIAN);
  
 -        format_caps = gst_caps_new_simple ("video/x-raw-rgb",
 -            "endianness", G_TYPE_INT, endianness,
 -            "depth", G_TYPE_INT, fmt->depth,
 -            "bpp", G_TYPE_INT, fmt->bits_per_pixel,
 -            "red_mask", G_TYPE_INT, fmt->red_mask,
 -            "green_mask", G_TYPE_INT, fmt->green_mask,
 -            "blue_mask", G_TYPE_INT, fmt->blue_mask,
 +        vformat = gst_video_format_from_masks (fmt->depth, fmt->bits_per_pixel,
 +            endianness, fmt->red_mask, fmt->green_mask, fmt->blue_mask, 0);
 +        if (vformat == GST_VIDEO_FORMAT_UNKNOWN)
 +          break;
 +
 +        format_caps = gst_caps_new_simple ("video/x-raw",
 +            "format", G_TYPE_STRING, gst_video_format_to_string (vformat),
              "width", GST_TYPE_INT_RANGE, 1, max_w,
              "height", GST_TYPE_INT_RANGE, 1, max_h,
              "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
          break;
        }
        case XvYUV:
 -        format_caps = gst_caps_new_simple ("video/x-raw-yuv",
 -            "format", GST_TYPE_FOURCC, formats[i].id,
 +      {
 +        vformat = gst_video_format_from_fourcc (formats[i].id);
 +        if (vformat == GST_VIDEO_FORMAT_UNKNOWN)
 +          break;
 +
 +        format_caps = gst_caps_new_simple ("video/x-raw",
 +            "format", G_TYPE_STRING, gst_video_format_to_string (vformat),
              "width", GST_TYPE_INT_RANGE, 1, max_w,
              "height", GST_TYPE_INT_RANGE, 1, max_h,
              "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
          break;
 +      }
        default:
 +        vformat = GST_VIDEO_FORMAT_UNKNOWN;
          g_assert_not_reached ();
          break;
      }
        format = g_new0 (GstXvImageFormat, 1);
        if (format) {
          format->format = formats[i].id;
 +        format->vformat = vformat;
          format->caps = gst_caps_copy (format_caps);
          xcontext->formats_list = g_list_append (xcontext->formats_list, format);
        }
@@@ -1175,8 -1688,13 +1177,13 @@@ gst_xvimagesink_manage_event_thread (Gs
        GST_DEBUG_OBJECT (xvimagesink, "run xevent thread, expose %d, events %d",
            xvimagesink->handle_expose, xvimagesink->handle_events);
        xvimagesink->running = TRUE;
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
        xvimagesink->event_thread = g_thread_create (
            (GThreadFunc) gst_xvimagesink_event_thread, xvimagesink, TRUE, NULL);
+ #else
+       xvimagesink->event_thread = g_thread_try_new ("xvimagesink-events",
+           (GThreadFunc) gst_xvimagesink_event_thread, xvimagesink, NULL);
+ #endif
      }
    } else {
      if (xvimagesink->event_thread) {
@@@ -1229,7 -1747,6 +1236,7 @@@ gst_xvimagesink_calculate_pixel_aspect_
      ratio = 4.0 * 576 / (3.0 * 720);
    }
    GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);
 +
    /* now find the one from par[][2] with the lowest delta to the real one */
    delta = DELTA (0);
    index = 0;
@@@ -1346,10 -1863,18 +1353,10 @@@ gst_xvimagesink_xcontext_get (GstXvImag
  
    xcontext->caps = gst_xvimagesink_get_xv_support (xvimagesink, xcontext);
  
 -  if (!xcontext->caps) {
 -    XCloseDisplay (xcontext->disp);
 -    g_mutex_unlock (xvimagesink->x_lock);
 -    g_free (xcontext->par);
 -    g_free (xcontext);
 -    /* GST_ELEMENT_ERROR is thrown by gst_xvimagesink_get_xv_support */
 -    return NULL;
 -  }
 -#ifdef HAVE_XSHM
    /* Search for XShm extension support */
 +#ifdef HAVE_XSHM
    if (XShmQueryExtension (xcontext->disp) &&
 -      gst_xvimagesink_check_xshm_calls (xcontext)) {
 +      gst_xvimagesink_check_xshm_calls (xvimagesink, xcontext)) {
      xcontext->use_xshm = TRUE;
      GST_DEBUG ("xvimagesink is using XShm extension");
    } else
      GST_DEBUG ("xvimagesink is not using XShm extension");
    }
  
 +  if (!xcontext->caps) {
 +    XCloseDisplay (xcontext->disp);
 +    g_mutex_unlock (xvimagesink->x_lock);
 +    g_free (xcontext->par);
 +    g_free (xcontext);
 +    /* GST_ELEMENT_ERROR is thrown by gst_xvimagesink_get_xv_support */
 +    return NULL;
 +  }
 +
    xv_attr = XvQueryPortAttributes (xcontext->disp,
        xcontext->xv_port_id, &N_attr);
  
  
        channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL);
        channel->label = g_strdup (channels[i]);
 -      channel->min_value = matching_attr->min_value;
 -      channel->max_value = matching_attr->max_value;
 +      channel->min_value = matching_attr ? matching_attr->min_value : -1000;
 +      channel->max_value = matching_attr ? matching_attr->max_value : 1000;
  
        xcontext->channels_list = g_list_append (xcontext->channels_list,
            channel);
@@@ -1504,34 -2020,63 +1511,34 @@@ gst_xvimagesink_xcontext_clear (GstXvIm
    g_free (xcontext);
  }
  
 -static void
 -gst_xvimagesink_imagepool_clear (GstXvImageSink * xvimagesink)
 -{
 -  g_mutex_lock (xvimagesink->pool_lock);
 -
 -  while (xvimagesink->image_pool) {
 -    GstXvImageBuffer *xvimage = xvimagesink->image_pool->data;
 -
 -    xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
 -        xvimagesink->image_pool);
 -    gst_xvimage_buffer_free (xvimage);
 -  }
 -
 -  g_mutex_unlock (xvimagesink->pool_lock);
 -}
 -
  /* Element stuff */
  
 -/* This function tries to get a format matching with a given caps in the
 -   supported list of formats we generated in gst_xvimagesink_get_xv_support */
 -static gint
 -gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
 -    GstCaps * caps)
 -{
 -  GList *list = NULL;
 -
 -  g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), 0);
 -
 -  list = xvimagesink->xcontext->formats_list;
 -
 -  while (list) {
 -    GstXvImageFormat *format = list->data;
 -
 -    if (format) {
 -      if (gst_caps_can_intersect (caps, format->caps)) {
 -        return format->format;
 -      }
 -    }
 -    list = g_list_next (list);
 -  }
 -
 -  return -1;
 -}
 -
  static GstCaps *
 -gst_xvimagesink_getcaps (GstBaseSink * bsink)
 +gst_xvimagesink_getcaps (GstBaseSink * bsink, GstCaps * filter)
  {
    GstXvImageSink *xvimagesink;
 +  GstCaps *caps;
  
    xvimagesink = GST_XVIMAGESINK (bsink);
  
 -  if (xvimagesink->xcontext)
 -    return gst_caps_ref (xvimagesink->xcontext->caps);
 +  if (xvimagesink->xcontext) {
 +    if (filter)
 +      return gst_caps_intersect_full (filter, xvimagesink->xcontext->caps,
 +          GST_CAPS_INTERSECT_FIRST);
 +    else
 +      return gst_caps_ref (xvimagesink->xcontext->caps);
 +  }
  
 -  return
 -      gst_caps_copy (gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD
 -          (xvimagesink)));
 +  caps = gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD (xvimagesink));
 +  if (filter) {
 +    GstCaps *intersection;
 +
 +    intersection =
 +        gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
 +    gst_caps_unref (caps);
 +    caps = intersection;
 +  }
 +  return caps;
  }
  
  static gboolean
@@@ -1539,13 -2084,17 +1546,13 @@@ gst_xvimagesink_setcaps (GstBaseSink * 
  {
    GstXvImageSink *xvimagesink;
    GstStructure *structure;
 +  GstBufferPool *newpool, *oldpool;
 +  GstVideoInfo info;
    guint32 im_format = 0;
 -  gboolean ret;
 -  gint video_width, video_height;
 -  gint disp_x, disp_y;
 -  gint disp_width, disp_height;
    gint video_par_n, video_par_d;        /* video's PAR */
    gint display_par_n, display_par_d;    /* display's PAR */
 -  const GValue *caps_par;
 -  const GValue *caps_disp_reg;
 -  const GValue *fps;
    guint num, den;
 +  gint size;
  
    xvimagesink = GST_XVIMAGESINK (bsink);
  
    if (!gst_caps_can_intersect (xvimagesink->xcontext->caps, caps))
      goto incompatible_caps;
  
 -  structure = gst_caps_get_structure (caps, 0);
 -  ret = gst_structure_get_int (structure, "width", &video_width);
 -  ret &= gst_structure_get_int (structure, "height", &video_height);
 -  fps = gst_structure_get_value (structure, "framerate");
 -  ret &= (fps != NULL);
 +  if (!gst_video_info_from_caps (&info, caps))
 +    goto invalid_format;
  
 -  if (!ret)
 -    goto incomplete_caps;
 +  structure = gst_caps_get_structure (caps, 0);
  
 -  xvimagesink->fps_n = gst_value_get_fraction_numerator (fps);
 -  xvimagesink->fps_d = gst_value_get_fraction_denominator (fps);
 +  xvimagesink->fps_n = info.fps_n;
 +  xvimagesink->fps_d = info.fps_d;
  
 -  xvimagesink->video_width = video_width;
 -  xvimagesink->video_height = video_height;
 +  xvimagesink->video_width = info.width;
 +  xvimagesink->video_height = info.height;
  
 -  im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
 +  im_format = gst_xvimagesink_get_format_from_info (xvimagesink, &info);
    if (im_format == -1)
      goto invalid_format;
  
 +  size = info.size;
 +
    /* get aspect ratio from caps if it's present, and
     * convert video width and height to a display width and height
     * using wd / hd = wv / hv * PARv / PARd */
  
    /* get video's PAR */
 -  caps_par = gst_structure_get_value (structure, "pixel-aspect-ratio");
 -  if (caps_par) {
 -    video_par_n = gst_value_get_fraction_numerator (caps_par);
 -    video_par_d = gst_value_get_fraction_denominator (caps_par);
 -  } else {
 -    video_par_n = 1;
 -    video_par_d = 1;
 -  }
 +  video_par_n = info.par_n;
 +  video_par_d = info.par_d;
 +
    /* get display's PAR */
    if (xvimagesink->par) {
      display_par_n = gst_value_get_fraction_numerator (xvimagesink->par);
      display_par_d = 1;
    }
  
 -  /* get the display region */
 -  caps_disp_reg = gst_structure_get_value (structure, "display-region");
 -  if (caps_disp_reg) {
 -    disp_x = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 0));
 -    disp_y = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 1));
 -    disp_width = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 2));
 -    disp_height =
 -        g_value_get_int (gst_value_array_get_value (caps_disp_reg, 3));
 -  } else {
 -    disp_x = disp_y = 0;
 -    disp_width = video_width;
 -    disp_height = video_height;
 -  }
 -
 -  if (!gst_video_calculate_display_ratio (&num, &den, video_width,
 -          video_height, video_par_n, video_par_d, display_par_n, display_par_d))
 +  if (!gst_video_calculate_display_ratio (&num, &den, info.width,
 +          info.height, video_par_n, video_par_d, display_par_n, display_par_d))
      goto no_disp_ratio;
  
 -  xvimagesink->disp_x = disp_x;
 -  xvimagesink->disp_y = disp_y;
 -  xvimagesink->disp_width = disp_width;
 -  xvimagesink->disp_height = disp_height;
 -
    GST_DEBUG_OBJECT (xvimagesink,
        "video width/height: %dx%d, calculated display ratio: %d/%d",
 -      video_width, video_height, num, den);
 +      info.width, info.height, num, den);
  
    /* now find a width x height that respects this display ratio.
     * prefer those that have one of w/h the same as the incoming video
  
    /* start with same height, because of interlaced video */
    /* check hd / den is an integer scale factor, and scale wd with the PAR */
 -  if (video_height % den == 0) {
 +  if (info.height % den == 0) {
      GST_DEBUG_OBJECT (xvimagesink, "keeping video height");
      GST_VIDEO_SINK_WIDTH (xvimagesink) = (guint)
 -        gst_util_uint64_scale_int (video_height, num, den);
 -    GST_VIDEO_SINK_HEIGHT (xvimagesink) = video_height;
 -  } else if (video_width % num == 0) {
 +        gst_util_uint64_scale_int (info.height, num, den);
 +    GST_VIDEO_SINK_HEIGHT (xvimagesink) = info.height;
 +  } else if (info.width % num == 0) {
      GST_DEBUG_OBJECT (xvimagesink, "keeping video width");
 -    GST_VIDEO_SINK_WIDTH (xvimagesink) = video_width;
 +    GST_VIDEO_SINK_WIDTH (xvimagesink) = info.width;
      GST_VIDEO_SINK_HEIGHT (xvimagesink) = (guint)
 -        gst_util_uint64_scale_int (video_width, den, num);
 +        gst_util_uint64_scale_int (info.width, den, num);
    } else {
      GST_DEBUG_OBJECT (xvimagesink, "approximating while keeping video height");
      GST_VIDEO_SINK_WIDTH (xvimagesink) = (guint)
 -        gst_util_uint64_scale_int (video_height, num, den);
 -    GST_VIDEO_SINK_HEIGHT (xvimagesink) = video_height;
 +        gst_util_uint64_scale_int (info.height, num, den);
 +    GST_VIDEO_SINK_HEIGHT (xvimagesink) = info.height;
    }
    GST_DEBUG_OBJECT (xvimagesink, "scaling to %dx%d",
        GST_VIDEO_SINK_WIDTH (xvimagesink), GST_VIDEO_SINK_HEIGHT (xvimagesink));
    g_mutex_lock (xvimagesink->flow_lock);
    if (!xvimagesink->xwindow) {
      g_mutex_unlock (xvimagesink->flow_lock);
 -    gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (xvimagesink));
 +    gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (xvimagesink));
    } else {
      g_mutex_unlock (xvimagesink->flow_lock);
    }
          GST_VIDEO_SINK_HEIGHT (xvimagesink));
    }
  
 +  xvimagesink->info = info;
 +
    /* After a resize, we want to redraw the borders in case the new frame size
     * doesn't cover the same area */
    xvimagesink->redraw_border = TRUE;
  
 -  /* We renew our xvimage only if size or format changed;
 -   * the xvimage is the same size as the video pixel size */
 -  if ((xvimagesink->xvimage) &&
 -      ((im_format != xvimagesink->xvimage->im_format) ||
 -          (video_width != xvimagesink->xvimage->width) ||
 -          (video_height != xvimagesink->xvimage->height))) {
 -    GST_DEBUG_OBJECT (xvimagesink,
 -        "old format %" GST_FOURCC_FORMAT ", new format %" GST_FOURCC_FORMAT,
 -        GST_FOURCC_ARGS (xvimagesink->xvimage->im_format),
 -        GST_FOURCC_ARGS (im_format));
 -    GST_DEBUG_OBJECT (xvimagesink, "renewing xvimage");
 -    gst_buffer_unref (GST_BUFFER (xvimagesink->xvimage));
 -    xvimagesink->xvimage = NULL;
 -  }
 +  /* create a new pool for the new configuration */
 +  newpool = gst_xvimage_buffer_pool_new (xvimagesink);
 +
 +  structure = gst_buffer_pool_get_config (newpool);
 +  gst_buffer_pool_config_set (structure, caps, size, 2, 0, 0, 15);
 +  if (!gst_buffer_pool_set_config (newpool, structure))
 +    goto config_failed;
  
 +  oldpool = xvimagesink->pool;
 +  xvimagesink->pool = newpool;
    g_mutex_unlock (xvimagesink->flow_lock);
  
 +  /* unref the old sink */
 +  if (oldpool) {
 +    /* we don't deactivate, some elements might still be using it, it will
 +     * be deactivated when the last ref is gone */
 +    gst_object_unref (oldpool);
 +  }
 +
    return TRUE;
  
    /* ERRORS */
@@@ -1677,6 -2248,12 +1684,6 @@@ incompatible_caps
      GST_ERROR_OBJECT (xvimagesink, "caps incompatible");
      return FALSE;
    }
 -incomplete_caps:
 -  {
 -    GST_DEBUG_OBJECT (xvimagesink, "Failed to retrieve either width, "
 -        "height or framerate from intersected caps");
 -    return FALSE;
 -  }
  invalid_format:
    {
      GST_DEBUG_OBJECT (xvimagesink,
@@@ -1695,12 -2272,6 +1702,12 @@@ no_display_size
          ("Error calculating the output display ratio of the video."));
      return FALSE;
    }
 +config_failed:
 +  {
 +    GST_ERROR_OBJECT (xvimagesink, "failed to set config.");
 +    g_mutex_unlock (xvimagesink->flow_lock);
 +    return FALSE;
 +  }
  }
  
  static GstStateChangeReturn
@@@ -1717,10 -2288,8 +1724,10 @@@ gst_xvimagesink_change_state (GstElemen
        /* Initializing the XContext */
        if (xvimagesink->xcontext == NULL) {
          xcontext = gst_xvimagesink_xcontext_get (xvimagesink);
 -        if (xcontext == NULL)
 -          return GST_STATE_CHANGE_FAILURE;
 +        if (xcontext == NULL) {
 +          ret = GST_STATE_CHANGE_FAILURE;
 +          goto beach;
 +        }
          GST_OBJECT_LOCK (xvimagesink);
          if (xcontext)
            xvimagesink->xcontext = xcontext;
        gst_xvimagesink_manage_event_thread (xvimagesink);
        break;
      case GST_STATE_CHANGE_READY_TO_PAUSED:
 -      g_mutex_lock (xvimagesink->pool_lock);
 -      xvimagesink->pool_invalid = FALSE;
 -      g_mutex_unlock (xvimagesink->pool_lock);
        break;
      case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
        break;
      case GST_STATE_CHANGE_PAUSED_TO_READY:
 -      g_mutex_lock (xvimagesink->pool_lock);
 -      xvimagesink->pool_invalid = TRUE;
 -      g_mutex_unlock (xvimagesink->pool_lock);
        break;
      default:
        break;
        xvimagesink->fps_d = 1;
        GST_VIDEO_SINK_WIDTH (xvimagesink) = 0;
        GST_VIDEO_SINK_HEIGHT (xvimagesink) = 0;
 +      g_mutex_lock (xvimagesink->flow_lock);
 +      if (xvimagesink->pool)
 +        gst_buffer_pool_set_active (xvimagesink->pool, FALSE);
 +      g_mutex_unlock (xvimagesink->flow_lock);
        break;
      case GST_STATE_CHANGE_READY_TO_NULL:
        gst_xvimagesink_reset (xvimagesink);
        break;
    }
  
 +beach:
    return ret;
  }
  
@@@ -1801,113 -2371,66 +1808,113 @@@ gst_xvimagesink_get_times (GstBaseSink 
  static GstFlowReturn
  gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
  {
 +  GstFlowReturn res;
    GstXvImageSink *xvimagesink;
 +  GstXvImageMeta *meta;
 +  GstBuffer *to_put;
  
    xvimagesink = GST_XVIMAGESINK (vsink);
  
 -  /* If this buffer has been allocated using our buffer management we simply
 -     put the ximage which is in the PRIVATE pointer */
 -  if (GST_IS_XVIMAGE_BUFFER (buf)) {
 -    GST_LOG_OBJECT (xvimagesink, "fast put of bufferpool buffer %p", buf);
 -    if (!gst_xvimagesink_xvimage_put (xvimagesink,
 -            GST_XVIMAGE_BUFFER_CAST (buf)))
 -      goto no_window;
 +  meta = gst_buffer_get_xvimage_meta (buf);
 +
 +  if (meta && meta->sink == xvimagesink) {
 +    /* If this buffer has been allocated using our buffer management we simply
 +       put the ximage which is in the PRIVATE pointer */
 +    GST_LOG_OBJECT (xvimagesink, "buffer %p from our pool, writing directly",
 +        buf);
 +    to_put = buf;
 +    res = GST_FLOW_OK;
    } else {
 -    GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, xvimagesink,
 -        "slow copy into bufferpool buffer %p", buf);
 +    GstVideoFrame src, dest;
 +
      /* Else we have to copy the data into our private image, */
      /* if we have one... */
 -    if (!xvimagesink->xvimage) {
 -      GST_DEBUG_OBJECT (xvimagesink, "creating our xvimage");
 +    GST_LOG_OBJECT (xvimagesink, "buffer %p not from our pool, copying", buf);
  
 -      xvimagesink->xvimage = gst_xvimagesink_xvimage_new (xvimagesink,
 -          GST_BUFFER_CAPS (buf));
 +    /* we should have a pool, configured in setcaps */
 +    if (xvimagesink->pool == NULL)
 +      goto no_pool;
  
 -      if (!xvimagesink->xvimage)
 -        /* The create method should have posted an informative error */
 -        goto no_image;
 +    if (!gst_buffer_pool_set_active (xvimagesink->pool, TRUE))
 +      goto activate_failed;
  
 -      if (xvimagesink->xvimage->size < GST_BUFFER_SIZE (buf)) {
 -        GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
 -            ("Failed to create output image buffer of %dx%d pixels",
 -                xvimagesink->xvimage->width, xvimagesink->xvimage->height),
 -            ("XServer allocated buffer size did not match input buffer"));
 +    /* take a buffer form our pool */
 +    res = gst_buffer_pool_acquire_buffer (xvimagesink->pool, &to_put, NULL);
 +    if (res != GST_FLOW_OK)
 +      goto no_buffer;
  
 -        gst_xvimage_buffer_destroy (xvimagesink->xvimage);
 -        xvimagesink->xvimage = NULL;
 -        goto no_image;
 -      }
 +    if (gst_buffer_get_size (to_put) < gst_buffer_get_size (buf))
 +      goto wrong_size;
 +
 +    GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, xvimagesink,
 +        "slow copy into bufferpool buffer %p", to_put);
 +
 +    if (!gst_video_frame_map (&src, &xvimagesink->info, buf, GST_MAP_READ))
 +      goto invalid_buffer;
 +
 +    if (!gst_video_frame_map (&dest, &xvimagesink->info, to_put, GST_MAP_WRITE)) {
 +      gst_video_frame_unmap (&src);
 +      goto invalid_buffer;
      }
  
 -    memcpy (xvimagesink->xvimage->xvimage->data,
 -        GST_BUFFER_DATA (buf),
 -        MIN (GST_BUFFER_SIZE (buf), xvimagesink->xvimage->size));
 +    gst_video_frame_copy (&dest, &src);
  
 -    if (!gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage))
 -      goto no_window;
 +    gst_video_frame_unmap (&dest);
 +    gst_video_frame_unmap (&src);
    }
  
 -  return GST_FLOW_OK;
 +  if (!gst_xvimagesink_xvimage_put (xvimagesink, to_put))
 +    goto no_window;
 +
 +done:
 +  if (to_put != buf)
 +    gst_buffer_unref (to_put);
 +
 +  return res;
  
    /* ERRORS */
 -no_image:
 +no_pool:
 +  {
 +    GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
 +        ("Internal error: can't allocate images"),
 +        ("We don't have a bufferpool negotiated"));
 +    return GST_FLOW_ERROR;
 +  }
 +no_buffer:
    {
      /* No image available. That's very bad ! */
      GST_WARNING_OBJECT (xvimagesink, "could not create image");
 -    return GST_FLOW_ERROR;
 +    return res;
 +  }
 +wrong_size:
 +  {
 +    GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
 +        ("Failed to create output image buffer"),
 +        ("XServer allocated buffer size did not match input buffer %"
 +            G_GSIZE_FORMAT " - %" G_GSIZE_FORMAT, gst_buffer_get_size (to_put),
 +            gst_buffer_get_size (buf)));
 +    res = GST_FLOW_ERROR;
 +    goto done;
 +  }
 +invalid_buffer:
 +  {
 +    /* No Window available to put our image into */
 +    GST_WARNING_OBJECT (xvimagesink, "could map image");
 +    res = GST_FLOW_OK;
 +    goto done;
    }
  no_window:
    {
      /* No Window available to put our image into */
      GST_WARNING_OBJECT (xvimagesink, "could not output image - no window");
 -    return GST_FLOW_ERROR;
 +    res = GST_FLOW_ERROR;
 +    goto done;
 +  }
 +activate_failed:
 +  {
 +    GST_ERROR_OBJECT (xvimagesink, "failed to activate bufferpool.");
 +    res = GST_FLOW_ERROR;
 +    goto done;
    }
  }
  
@@@ -1936,91 -2459,298 +1943,91 @@@ gst_xvimagesink_event (GstBaseSink * si
      default:
        break;
    }
 -  if (GST_BASE_SINK_CLASS (parent_class)->event)
 -    return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
 -  else
 -    return TRUE;
 +  return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
  }
  
 -/* Buffer management */
 -
 -static GstCaps *
 -gst_xvimage_sink_different_size_suggestion (GstXvImageSink * xvimagesink,
 -    GstCaps * caps)
 -{
 -  GstCaps *intersection;
 -  GstCaps *new_caps;
 -  GstStructure *s;
 -  gint width, height;
 -  gint par_n = 1, par_d = 1;
 -  gint dar_n, dar_d;
 -  gint w, h;
 -
 -  new_caps = gst_caps_copy (caps);
 -
 -  s = gst_caps_get_structure (new_caps, 0);
 -
 -  gst_structure_get_int (s, "width", &width);
 -  gst_structure_get_int (s, "height", &height);
 -  gst_structure_get_fraction (s, "pixel-aspect-ratio", &par_n, &par_d);
 -
 -  gst_structure_remove_field (s, "width");
 -  gst_structure_remove_field (s, "height");
 -  gst_structure_remove_field (s, "pixel-aspect-ratio");
 -
 -  intersection = gst_caps_intersect (xvimagesink->xcontext->caps, new_caps);
 -  gst_caps_unref (new_caps);
 -
 -  if (gst_caps_is_empty (intersection))
 -    return intersection;
 -
 -  s = gst_caps_get_structure (intersection, 0);
 -
 -  gst_util_fraction_multiply (width, height, par_n, par_d, &dar_n, &dar_d);
 -
 -  /* xvimagesink supports all PARs */
 -
 -  gst_structure_fixate_field_nearest_int (s, "width", width);
 -  gst_structure_fixate_field_nearest_int (s, "height", height);
 -  gst_structure_get_int (s, "width", &w);
 -  gst_structure_get_int (s, "height", &h);
 -
 -  gst_util_fraction_multiply (h, w, dar_n, dar_d, &par_n, &par_d);
 -  gst_structure_set (s, "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d,
 -      NULL);
 -
 -  return intersection;
 -}
 -
 -static GstFlowReturn
 -gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
 -    GstCaps * caps, GstBuffer ** buf)
 +static gboolean
 +gst_xvimagesink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
  {
 -  GstFlowReturn ret = GST_FLOW_OK;
 -  GstXvImageSink *xvimagesink;
 -  GstXvImageBuffer *xvimage = NULL;
 -  GstCaps *intersection = NULL;
 -  GstStructure *structure = NULL;
 -  gint width, height, image_format;
 +  GstXvImageSink *xvimagesink = GST_XVIMAGESINK (bsink);
 +  GstBufferPool *pool;
 +  GstStructure *config;
 +  GstCaps *caps;
 +  guint size;
 +  gboolean need_pool;
  
 -  xvimagesink = GST_XVIMAGESINK (bsink);
 +  gst_query_parse_allocation (query, &caps, &need_pool);
  
 -  if (G_UNLIKELY (!caps))
 +  if (caps == NULL)
      goto no_caps;
  
 -  g_mutex_lock (xvimagesink->pool_lock);
 -  if (G_UNLIKELY (xvimagesink->pool_invalid))
 -    goto invalid;
 -
 -  if (G_LIKELY (xvimagesink->xcontext->last_caps &&
 -          gst_caps_is_equal (caps, xvimagesink->xcontext->last_caps))) {
 -    GST_LOG_OBJECT (xvimagesink,
 -        "buffer alloc for same last_caps, reusing caps");
 -    intersection = gst_caps_ref (caps);
 -    image_format = xvimagesink->xcontext->last_format;
 -    width = xvimagesink->xcontext->last_width;
 -    height = xvimagesink->xcontext->last_height;
 -
 -    goto reuse_last_caps;
 -  }
 -
 -  GST_DEBUG_OBJECT (xvimagesink, "buffer alloc requested size %d with caps %"
 -      GST_PTR_FORMAT ", intersecting with our caps %" GST_PTR_FORMAT, size,
 -      caps, xvimagesink->xcontext->caps);
 -
 -  /* Check the caps against our xcontext */
 -  intersection = gst_caps_intersect (xvimagesink->xcontext->caps, caps);
 -
 -  GST_DEBUG_OBJECT (xvimagesink, "intersection in buffer alloc returned %"
 -      GST_PTR_FORMAT, intersection);
 -
 -  if (gst_caps_is_empty (intersection)) {
 -    GstCaps *new_caps;
 -
 -    gst_caps_unref (intersection);
 -
 -    /* So we don't support this kind of buffer, let's define one we'd like */
 -    new_caps = gst_caps_copy (caps);
 -
 -    structure = gst_caps_get_structure (new_caps, 0);
 -    if (!gst_structure_has_field (structure, "width") ||
 -        !gst_structure_has_field (structure, "height")) {
 -      gst_caps_unref (new_caps);
 -      goto invalid;
 -    }
 -
 -    /* Try different dimensions */
 -    intersection =
 -        gst_xvimage_sink_different_size_suggestion (xvimagesink, new_caps);
 -
 -    if (gst_caps_is_empty (intersection)) {
 -      /* Try with different YUV formats first */
 -      gst_structure_set_name (structure, "video/x-raw-yuv");
 -
 -      /* Remove format specific fields */
 -      gst_structure_remove_field (structure, "format");
 -      gst_structure_remove_field (structure, "endianness");
 -      gst_structure_remove_field (structure, "depth");
 -      gst_structure_remove_field (structure, "bpp");
 -      gst_structure_remove_field (structure, "red_mask");
 -      gst_structure_remove_field (structure, "green_mask");
 -      gst_structure_remove_field (structure, "blue_mask");
 -      gst_structure_remove_field (structure, "alpha_mask");
 -
 -      /* Reuse intersection with Xcontext */
 -      intersection = gst_caps_intersect (xvimagesink->xcontext->caps, new_caps);
 -    }
 +  g_mutex_lock (xvimagesink->flow_lock);
 +  if ((pool = xvimagesink->pool))
 +    gst_object_ref (pool);
 +  g_mutex_unlock (xvimagesink->flow_lock);
  
 -    if (gst_caps_is_empty (intersection)) {
 -      /* Try with different dimensions and YUV formats */
 -      intersection =
 -          gst_xvimage_sink_different_size_suggestion (xvimagesink, new_caps);
 -    }
 +  if (pool != NULL) {
 +    const GstCaps *pcaps;
  
 -    if (gst_caps_is_empty (intersection)) {
 -      /* Now try with RGB */
 -      gst_structure_set_name (structure, "video/x-raw-rgb");
 -      /* And interset again */
 -      gst_caps_unref (intersection);
 -      intersection = gst_caps_intersect (xvimagesink->xcontext->caps, new_caps);
 -    }
 +    /* we had a pool, check caps */
 +    GST_DEBUG_OBJECT (xvimagesink, "check existing pool caps");
 +    config = gst_buffer_pool_get_config (pool);
 +    gst_buffer_pool_config_get (config, &pcaps, &size, NULL, NULL, NULL, NULL);
  
 -    if (gst_caps_is_empty (intersection)) {
 -      /* Try with different dimensions and RGB formats */
 -      intersection =
 -          gst_xvimage_sink_different_size_suggestion (xvimagesink, new_caps);
 +    if (!gst_caps_is_equal (caps, pcaps)) {
 +      GST_DEBUG_OBJECT (xvimagesink, "pool has different caps");
 +      /* different caps, we can't use this pool */
 +      gst_object_unref (pool);
 +      pool = NULL;
      }
 -
 -    /* Clean this copy */
 -    gst_caps_unref (new_caps);
 -
 -    if (gst_caps_is_empty (intersection))
 -      goto incompatible;
    }
 +  if (pool == NULL && need_pool) {
 +    GstVideoInfo info;
  
 -  /* Ensure the returned caps are fixed */
 -  gst_caps_truncate (intersection);
 +    GST_DEBUG_OBJECT (xvimagesink, "create new pool");
 +    pool = gst_xvimage_buffer_pool_new (xvimagesink);
  
 -  GST_DEBUG_OBJECT (xvimagesink, "allocating a buffer with caps %"
 -      GST_PTR_FORMAT, intersection);
 -  if (gst_caps_is_equal (intersection, caps)) {
 -    /* Things work better if we return a buffer with the same caps ptr
 -     * as was asked for when we can */
 -    gst_caps_replace (&intersection, caps);
 -  }
 -
 -  /* Get image format from caps */
 -  image_format = gst_xvimagesink_get_format_from_caps (xvimagesink,
 -      intersection);
 -
 -  /* Get geometry from caps */
 -  structure = gst_caps_get_structure (intersection, 0);
 -  if (!gst_structure_get_int (structure, "width", &width) ||
 -      !gst_structure_get_int (structure, "height", &height) ||
 -      image_format == -1)
 -    goto invalid_caps;
 -
 -  /* Store our caps and format as the last_caps to avoid expensive
 -   * caps intersection next time */
 -  gst_caps_replace (&xvimagesink->xcontext->last_caps, intersection);
 -  xvimagesink->xcontext->last_format = image_format;
 -  xvimagesink->xcontext->last_width = width;
 -  xvimagesink->xcontext->last_height = height;
 +    if (!gst_video_info_from_caps (&info, caps))
 +      goto invalid_caps;
  
 -reuse_last_caps:
 +    /* the normal size of a frame */
 +    size = info.size;
  
 -  /* Walking through the pool cleaning unusable images and searching for a
 -     suitable one */
 -  while (xvimagesink->image_pool) {
 -    xvimage = xvimagesink->image_pool->data;
 -
 -    if (xvimage) {
 -      /* Removing from the pool */
 -      xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
 -          xvimagesink->image_pool);
 -
 -      /* We check for geometry or image format changes */
 -      if ((xvimage->width != width) ||
 -          (xvimage->height != height) || (xvimage->im_format != image_format)) {
 -        /* This image is unusable. Destroying... */
 -        gst_xvimage_buffer_free (xvimage);
 -        xvimage = NULL;
 -      } else {
 -        /* We found a suitable image */
 -        GST_LOG_OBJECT (xvimagesink, "found usable image in pool");
 -        break;
 -      }
 -    }
 -  }
 -
 -  if (!xvimage) {
 -    /* We found no suitable image in the pool. Creating... */
 -    GST_DEBUG_OBJECT (xvimagesink, "no usable image in pool, creating xvimage");
 -    xvimage = gst_xvimagesink_xvimage_new (xvimagesink, intersection);
 +    config = gst_buffer_pool_get_config (pool);
 +    gst_buffer_pool_config_set (config, caps, size, 0, 0, 0, 0);
 +    if (!gst_buffer_pool_set_config (pool, config))
 +      goto config_failed;
    }
 -  g_mutex_unlock (xvimagesink->pool_lock);
 +  /* we need at least 2 buffer because we hold on to the last one */
 +  gst_query_set_allocation_params (query, size, 2, 0, 0, 0, pool);
  
 -  if (xvimage) {
 -    /* Make sure the buffer is cleared of any previously used flags */
 -    GST_MINI_OBJECT_CAST (xvimage)->flags = 0;
 -    gst_buffer_set_caps (GST_BUFFER_CAST (xvimage), intersection);
 -  }
 +  /* we also support various metadata */
 +  gst_query_add_allocation_meta (query, GST_VIDEO_META_API);
 +  gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API);
  
 -  *buf = GST_BUFFER_CAST (xvimage);
 +  gst_object_unref (pool);
  
 -beach:
 -  if (intersection) {
 -    gst_caps_unref (intersection);
 -  }
 -
 -  return ret;
 +  return TRUE;
  
    /* ERRORS */
 -invalid:
 -  {
 -    GST_DEBUG_OBJECT (xvimagesink, "the pool is flushing");
 -    ret = GST_FLOW_WRONG_STATE;
 -    g_mutex_unlock (xvimagesink->pool_lock);
 -    goto beach;
 -  }
 -incompatible:
 +no_caps:
    {
 -    GST_WARNING_OBJECT (xvimagesink, "we were requested a buffer with "
 -        "caps %" GST_PTR_FORMAT ", but our xcontext caps %" GST_PTR_FORMAT
 -        " are completely incompatible with those caps", caps,
 -        xvimagesink->xcontext->caps);
 -    ret = GST_FLOW_NOT_NEGOTIATED;
 -    g_mutex_unlock (xvimagesink->pool_lock);
 -    goto beach;
 +    GST_DEBUG_OBJECT (bsink, "no caps specified");
 +    return FALSE;
    }
  invalid_caps:
    {
 -    GST_WARNING_OBJECT (xvimagesink, "invalid caps for buffer allocation %"
 -        GST_PTR_FORMAT, intersection);
 -    ret = GST_FLOW_NOT_NEGOTIATED;
 -    g_mutex_unlock (xvimagesink->pool_lock);
 -    goto beach;
 +    GST_DEBUG_OBJECT (bsink, "invalid caps specified");
 +    return FALSE;
    }
 -no_caps:
 +config_failed:
    {
 -    GST_WARNING_OBJECT (xvimagesink, "have no caps, doing fallback allocation");
 -    *buf = NULL;
 -    ret = GST_FLOW_OK;
 -    goto beach;
 +    GST_DEBUG_OBJECT (bsink, "failed setting config");
 +    return FALSE;
    }
  }
  
  /* Interfaces stuff */
 -
 -static gboolean
 -gst_xvimagesink_interface_supported (GstImplementsInterface * iface, GType type)
 -{
 -  if (type == GST_TYPE_NAVIGATION || type == GST_TYPE_X_OVERLAY ||
 -      type == GST_TYPE_COLOR_BALANCE || type == GST_TYPE_PROPERTY_PROBE)
 -    return TRUE;
 -  else
 -    return FALSE;
 -}
 -
 -static void
 -gst_xvimagesink_interface_init (GstImplementsInterfaceClass * klass)
 -{
 -  klass->supported = gst_xvimagesink_interface_supported;
 -}
 -
  static void
  gst_xvimagesink_navigation_send_event (GstNavigation * navigation,
      GstStructure * structure)
@@@ -2091,7 -2821,7 +2098,7 @@@ gst_xvimagesink_navigation_init (GstNav
  }
  
  static void
 -gst_xvimagesink_set_window_handle (GstXOverlay * overlay, guintptr id)
 +gst_xvimagesink_set_window_handle (GstVideoOverlay * overlay, guintptr id)
  {
    XID xwindow_id = id;
    GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay);
  
    gst_xvimagesink_update_colorbalance (xvimagesink);
  
 -  /* Clear image pool as the images are unusable anyway */
 -  gst_xvimagesink_imagepool_clear (xvimagesink);
 -
 -  /* Clear the xvimage */
 -  if (xvimagesink->xvimage) {
 -    gst_xvimage_buffer_free (xvimagesink->xvimage);
 -    xvimagesink->xvimage = NULL;
 -  }
 -
    /* If a window is there already we destroy it */
    if (xvimagesink->xwindow) {
      gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
  }
  
  static void
 -gst_xvimagesink_expose (GstXOverlay * overlay)
 +gst_xvimagesink_expose (GstVideoOverlay * overlay)
  {
    GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay);
  
 +  GST_DEBUG ("doing expose");
    gst_xvimagesink_xwindow_update_geometry (xvimagesink);
    gst_xvimagesink_xvimage_put (xvimagesink, NULL);
  }
  
  static void
 -gst_xvimagesink_set_event_handling (GstXOverlay * overlay,
 +gst_xvimagesink_set_event_handling (GstVideoOverlay * overlay,
      gboolean handle_events)
  {
    GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay);
  }
  
  static void
 -gst_xvimagesink_set_render_rectangle (GstXOverlay * overlay, gint x, gint y,
 +gst_xvimagesink_set_render_rectangle (GstVideoOverlay * overlay, gint x, gint y,
      gint width, gint height)
  {
    GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay);
  }
  
  static void
 -gst_xvimagesink_xoverlay_init (GstXOverlayClass * iface)
 +gst_xvimagesink_video_overlay_init (GstVideoOverlayInterface * iface)
  {
    iface->set_window_handle = gst_xvimagesink_set_window_handle;
    iface->expose = gst_xvimagesink_expose;
@@@ -2321,7 -3059,7 +2328,7 @@@ gst_xvimagesink_colorbalance_get_value 
  }
  
  static void
 -gst_xvimagesink_colorbalance_init (GstColorBalanceClass * iface)
 +gst_xvimagesink_colorbalance_init (GstColorBalanceInterface * iface)
  {
    GST_COLOR_BALANCE_TYPE (iface) = GST_COLOR_BALANCE_HARDWARE;
    iface->list_channels = gst_xvimagesink_colorbalance_list_channels;
@@@ -2552,7 -3290,7 +2559,7 @@@ gst_xvimagesink_set_property (GObject 
        xvimagesink->keep_aspect = g_value_get_boolean (value);
        break;
      case PROP_HANDLE_EVENTS:
 -      gst_xvimagesink_set_event_handling (GST_X_OVERLAY (xvimagesink),
 +      gst_xvimagesink_set_event_handling (GST_VIDEO_OVERLAY (xvimagesink),
            g_value_get_boolean (value));
        gst_xvimagesink_manage_event_thread (xvimagesink);
        break;
@@@ -2681,28 -3419,32 +2688,28 @@@ gst_xvimagesink_reset (GstXvImageSink 
    xvimagesink->event_thread = NULL;
    GST_OBJECT_UNLOCK (xvimagesink);
  
 -  /* invalidate the pool, current allocations continue, new buffer_alloc fails
 -   * with wrong_state */
 -  g_mutex_lock (xvimagesink->pool_lock);
 -  xvimagesink->pool_invalid = TRUE;
 -  g_mutex_unlock (xvimagesink->pool_lock);
 -
    /* Wait for our event thread to finish before we clean up our stuff. */
    if (thread)
      g_thread_join (thread);
  
    if (xvimagesink->cur_image) {
 -    gst_buffer_unref (GST_BUFFER_CAST (xvimagesink->cur_image));
 +    gst_buffer_unref (xvimagesink->cur_image);
      xvimagesink->cur_image = NULL;
    }
 -  if (xvimagesink->xvimage) {
 -    gst_buffer_unref (GST_BUFFER_CAST (xvimagesink->xvimage));
 -    xvimagesink->xvimage = NULL;
 -  }
  
 -  gst_xvimagesink_imagepool_clear (xvimagesink);
 +  g_mutex_lock (xvimagesink->flow_lock);
 +
 +  if (xvimagesink->pool) {
 +    gst_object_unref (xvimagesink->pool);
 +    xvimagesink->pool = NULL;
 +  }
  
    if (xvimagesink->xwindow) {
      gst_xvimagesink_xwindow_clear (xvimagesink, xvimagesink->xwindow);
      gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
      xvimagesink->xwindow = NULL;
    }
 +  g_mutex_unlock (xvimagesink->flow_lock);
  
    xvimagesink->render_rect.x = xvimagesink->render_rect.y =
        xvimagesink->render_rect.w = xvimagesink->render_rect.h = 0;
@@@ -2740,6 -3482,10 +2747,6 @@@ gst_xvimagesink_finalize (GObject * obj
      g_mutex_free (xvimagesink->flow_lock);
      xvimagesink->flow_lock = NULL;
    }
 -  if (xvimagesink->pool_lock) {
 -    g_mutex_free (xvimagesink->pool_lock);
 -    xvimagesink->pool_lock = NULL;
 -  }
  
    g_free (xvimagesink->media_title);
  
  }
  
  static void
 -gst_xvimagesink_init (GstXvImageSink * xvimagesink,
 -    GstXvImageSinkClass * xvimagesinkclass)
 +gst_xvimagesink_init (GstXvImageSink * xvimagesink)
  {
    xvimagesink->display_name = NULL;
    xvimagesink->adaptor_no = 0;
    xvimagesink->xcontext = NULL;
    xvimagesink->xwindow = NULL;
 -  xvimagesink->xvimage = NULL;
    xvimagesink->cur_image = NULL;
  
    xvimagesink->hue = xvimagesink->saturation = 0;
    xvimagesink->x_lock = g_mutex_new ();
    xvimagesink->flow_lock = g_mutex_new ();
  
 -  xvimagesink->image_pool = NULL;
 -  xvimagesink->pool_lock = g_mutex_new ();
 +  xvimagesink->pool = NULL;
  
    xvimagesink->synchronous = FALSE;
    xvimagesink->double_buffer = TRUE;
  }
  
  static void
 -gst_xvimagesink_base_init (gpointer g_class)
 -{
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 -
 -  gst_element_class_set_details_simple (element_class,
 -      "Video sink", "Sink/Video",
 -      "A Xv based videosink", "Julien Moutte <julien@moutte.net>");
 -
 -  gst_element_class_add_static_pad_template (element_class,
 -      &gst_xvimagesink_sink_template_factory);
 -}
 -
 -static void
  gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
  {
    GObjectClass *gobject_class;
    gstbasesink_class = (GstBaseSinkClass *) klass;
    videosink_class = (GstVideoSinkClass *) klass;
  
 +  parent_class = g_type_class_peek_parent (klass);
 +
    gobject_class->set_property = gst_xvimagesink_set_property;
    gobject_class->get_property = gst_xvimagesink_get_property;
  
  
    gobject_class->finalize = gst_xvimagesink_finalize;
  
 +  gst_element_class_set_details_simple (gstelement_class,
 +      "Video sink", "Sink/Video",
 +      "A Xv based videosink", "Julien Moutte <julien@moutte.net>");
 +
 +  gst_element_class_add_pad_template (gstelement_class,
 +      gst_static_pad_template_get (&gst_xvimagesink_sink_template_factory));
 +
    gstelement_class->change_state =
        GST_DEBUG_FUNCPTR (gst_xvimagesink_change_state);
  
    gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_getcaps);
    gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_setcaps);
 -  gstbasesink_class->buffer_alloc =
 -      GST_DEBUG_FUNCPTR (gst_xvimagesink_buffer_alloc);
    gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_xvimagesink_get_times);
 +  gstbasesink_class->propose_allocation =
 +      GST_DEBUG_FUNCPTR (gst_xvimagesink_propose_allocation);
    gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_xvimagesink_event);
  
    videosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_xvimagesink_show_frame);
  }
 -
 -/* ============================================================= */
 -/*                                                               */
 -/*                       Public Methods                          */
 -/*                                                               */
 -/* ============================================================= */
 -
 -/* =========================================== */
 -/*                                             */
 -/*          Object typing & Creation           */
 -/*                                             */
 -/* =========================================== */
 -static void
 -gst_xvimagesink_init_interfaces (GType type)
 -{
 -  static const GInterfaceInfo iface_info = {
 -    (GInterfaceInitFunc) gst_xvimagesink_interface_init,
 -    NULL,
 -    NULL,
 -  };
 -  static const GInterfaceInfo navigation_info = {
 -    (GInterfaceInitFunc) gst_xvimagesink_navigation_init,
 -    NULL,
 -    NULL,
 -  };
 -  static const GInterfaceInfo overlay_info = {
 -    (GInterfaceInitFunc) gst_xvimagesink_xoverlay_init,
 -    NULL,
 -    NULL,
 -  };
 -  static const GInterfaceInfo colorbalance_info = {
 -    (GInterfaceInitFunc) gst_xvimagesink_colorbalance_init,
 -    NULL,
 -    NULL,
 -  };
 -  static const GInterfaceInfo propertyprobe_info = {
 -    (GInterfaceInitFunc) gst_xvimagesink_property_probe_interface_init,
 -    NULL,
 -    NULL,
 -  };
 -
 -  g_type_add_interface_static (type,
 -      GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info);
 -  g_type_add_interface_static (type, GST_TYPE_NAVIGATION, &navigation_info);
 -  g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &overlay_info);
 -  g_type_add_interface_static (type, GST_TYPE_COLOR_BALANCE,
 -      &colorbalance_info);
 -  g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
 -      &propertyprobe_info);
 -
 -  /* register type and create class in a more safe place instead of at
 -   * runtime since the type registration and class creation is not
 -   * threadsafe. */
 -  g_type_class_ref (gst_xvimage_buffer_get_type ());
 -}
 -
 -static gboolean
 -plugin_init (GstPlugin * plugin)
 -{
 -  if (!gst_element_register (plugin, "xvimagesink",
 -          GST_RANK_PRIMARY, GST_TYPE_XVIMAGESINK))
 -    return FALSE;
 -
 -  GST_DEBUG_CATEGORY_INIT (gst_debug_xvimagesink, "xvimagesink", 0,
 -      "xvimagesink element");
 -  GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
 -
 -  return TRUE;
 -}
 -
 -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
 -    GST_VERSION_MINOR,
 -    "xvimagesink",
 -    "XFree86 video output plugin using Xv extension",
 -    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --combined tests/check/libs/video.c
@@@ -2,7 -2,7 +2,7 @@@
   *
   * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
   * Copyright (C) <2006> Jan Schmidt <thaytan@mad.scientist.com>
-  * Copyright (C) <2008> Tim-Philipp Müller <tim centricular net>
+  * Copyright (C) <2008,2011> 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
@@@ -29,6 -29,7 +29,7 @@@
  #include <gst/check/gstcheck.h>
  
  #include <gst/video/video.h>
+ #include <gst/video/video-overlay-composition.h>
  #include <string.h>
  
  /* These are from the current/old videotestsrc; we check our new public API
@@@ -358,49 -359,11 +359,49 @@@ video_format_is_packed (GstVideoFormat 
    return FALSE;
  }
  
 +GST_START_TEST (test_video_formats_all)
 +{
 +  GstStructure *s;
 +  const GValue *val, *list_val;
 +  GstCaps *caps;
 +  guint num, n, num_formats;
 +
 +  num_formats = 100;
 +  fail_unless (gst_video_format_to_string (num_formats) == NULL);
 +  while (gst_video_format_to_string (num_formats) == NULL)
 +    --num_formats;
 +  GST_INFO ("number of known video formats: %d", num_formats);
 +
 +  caps = gst_caps_from_string ("video/x-raw, format=" GST_VIDEO_FORMATS_ALL);
 +  s = gst_caps_get_structure (caps, 0);
 +  val = gst_structure_get_value (s, "format");
 +  fail_unless (val != NULL);
 +  fail_unless (GST_VALUE_HOLDS_LIST (val));
 +  num = gst_value_list_get_size (val);
 +  fail_unless (num > 0);
 +  for (n = 0; n < num; ++n) {
 +    const gchar *fmt_str;
 +
 +    list_val = gst_value_list_get_value (val, n);
 +    fail_unless (G_VALUE_HOLDS_STRING (list_val));
 +    fmt_str = g_value_get_string (list_val);
 +    GST_INFO ("format: %s", fmt_str);
 +    fail_if (gst_video_format_from_string (fmt_str) ==
 +        GST_VIDEO_FORMAT_UNKNOWN);
 +  }
 +  fail_unless_equals_int (num, num_formats);
 +
 +  gst_caps_unref (caps);
 +}
 +
 +GST_END_TEST;
 +
  GST_START_TEST (test_video_formats)
  {
    guint i;
  
    for (i = 0; i < G_N_ELEMENTS (fourcc_list); ++i) {
 +    const GstVideoFormatInfo *vf_info;
      GstVideoFormat fmt;
      const gchar *s;
      guint32 fourcc;
      if (fmt == GST_VIDEO_FORMAT_UNKNOWN)
        continue;
  
 -    GST_INFO ("Fourcc %s, packed=%d", fourcc_list[i].fourcc,
 +    vf_info = gst_video_format_get_info (fmt);
 +    fail_unless (vf_info != NULL);
 +
 +    fail_unless_equals_int (GST_VIDEO_FORMAT_INFO_FORMAT (vf_info), fmt);
 +
 +    GST_INFO ("Fourcc %s, packed=%", fourcc_list[i].fourcc,
          gst_video_format_is_packed (fmt));
  
 -    fail_unless (gst_video_format_is_yuv (fmt));
 +    fail_unless (GST_VIDEO_FORMAT_INFO_IS_YUV (vf_info));
  
      /* use any non-NULL pointer so we can compare against NULL */
      {
        paintinfo paintinfo = { 0, };
        fourcc_list[i].paint_setup (&paintinfo, (unsigned char *) s);
        if (paintinfo.ap != NULL) {
 -        fail_unless (gst_video_format_has_alpha (fmt));
 +        fail_unless (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (vf_info));
        } else {
 -        fail_if (gst_video_format_has_alpha (fmt));
 +        fail_if (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (vf_info));
        }
      }
  
      for (w = 1; w <= 65; ++w) {
        for (h = 1; h <= 65; ++h) {
 +        GstVideoInfo vinfo;
          paintinfo paintinfo = { 0, };
          guint off0, off1, off2, off3;
          guint size;
  
          GST_LOG ("%s, %dx%d", fourcc_list[i].fourcc, w, h);
  
 +        gst_video_info_init (&vinfo);
 +        gst_video_info_set_format (&vinfo, fmt, w, h);
 +
          paintinfo.width = w;
          paintinfo.height = h;
          fourcc_list[i].paint_setup (&paintinfo, NULL);
 -        fail_unless_equals_int (gst_video_format_get_row_stride (fmt, 0, w),
 +        fail_unless_equals_int (GST_VIDEO_INFO_COMP_STRIDE (&vinfo, 0),
              paintinfo.ystride);
          if (!gst_video_format_is_packed (fmt)
 -            && !gst_video_format_is_gray (fmt)) {
 +            && !GST_VIDEO_FORMAT_INFO_IS_GRAY (vf_info)) {
            /* planar */
 -          fail_unless_equals_int (gst_video_format_get_row_stride (fmt, 1, w),
 +          fail_unless_equals_int (GST_VIDEO_INFO_COMP_STRIDE (&vinfo, 1),
                paintinfo.ustride);
 -          fail_unless_equals_int (gst_video_format_get_row_stride (fmt, 2, w),
 +          fail_unless_equals_int (GST_VIDEO_INFO_COMP_STRIDE (&vinfo, 2),
                paintinfo.vstride);
            /* check component_width * height against offsets/size somehow? */
          }
  
 -        size = gst_video_format_get_size (fmt, w, h);
 -        off0 = gst_video_format_get_component_offset (fmt, 0, w, h);
 -        off1 = gst_video_format_get_component_offset (fmt, 1, w, h);
 -        off2 = gst_video_format_get_component_offset (fmt, 2, w, h);
 +        size = GST_VIDEO_INFO_SIZE (&vinfo);
 +        off0 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 0);
 +        off1 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 1);
 +        off2 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 2);
  
          fail_unless_equals_int (size, (unsigned long) paintinfo.endptr);
          fail_unless_equals_int (off0, (unsigned long) paintinfo.yp);
          fail_unless_equals_int (off2, (unsigned long) paintinfo.vp);
  
          /* should be 0 if there's no alpha component */
 -        off3 = gst_video_format_get_component_offset (fmt, 3, w, h);
 +        off3 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 3);
          fail_unless_equals_int (off3, (unsigned long) paintinfo.ap);
  
          /* some gstvideo checks ... (FIXME: fails for Y41B and Y42B; not sure
              && fmt != GST_VIDEO_FORMAT_Y800) {
            guint cs0, cs1, cs2, cs3;
  
 -          cs0 = gst_video_format_get_component_width (fmt, 0, w) *
 -              gst_video_format_get_component_height (fmt, 0, h);
 -          cs1 = gst_video_format_get_component_width (fmt, 1, w) *
 -              gst_video_format_get_component_height (fmt, 1, h);
 -          cs2 = gst_video_format_get_component_width (fmt, 2, w) *
 -              gst_video_format_get_component_height (fmt, 2, h);
 +          cs0 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 0) *
 +              GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 0);
 +          cs1 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 1) *
 +              GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 1);
 +          cs2 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 2) *
 +              GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 2);
  
            /* GST_LOG ("cs0=%d,cs1=%d,cs2=%d,off0=%d,off1=%d,off2=%d,size=%d",
               cs0, cs1, cs2, off0, off1, off2, size); */
            if (!gst_video_format_is_packed (fmt))
              fail_unless (cs0 <= off1);
  
 -          if (gst_video_format_has_alpha (fmt)) {
 -            cs3 = gst_video_format_get_component_width (fmt, 3, w) *
 -                gst_video_format_get_component_height (fmt, 3, h);
 +          if (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (vinfo.finfo)) {
 +            cs3 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 3) *
 +                GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 2);
              fail_unless (cs3 < size);
              /* U/V/alpha shouldn't take up more space than the Y component */
              fail_if (cs1 > cs0, "cs1 (%d) should be <= cs0 (%d)", cs1, cs0);
@@@ -525,17 -479,11 +526,17 @@@ GST_END_TEST
  
  GST_START_TEST (test_video_formats_rgb)
  {
 +  GstVideoInfo vinfo;
    gint width, height, framerate_n, framerate_d, par_n, par_d;
 -  GstCaps *caps =
 -      gst_video_format_new_caps (GST_VIDEO_FORMAT_RGB, 800, 600, 0, 1, 1, 1);
 +  GstCaps *caps;
    GstStructure *structure;
  
 +  gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_RGB, 800, 600);
 +  vinfo.par_n = 1;
 +  vinfo.par_d = 1;
 +  vinfo.fps_n = 0;
 +  vinfo.fps_d = 1;
 +  caps = gst_video_info_to_caps (&vinfo);
    structure = gst_caps_get_structure (caps, 0);
  
    fail_unless (gst_structure_get_int (structure, "width", &width));
  
  GST_END_TEST;
  
 -GST_START_TEST (test_video_template_caps)
 -{
 -  GstCaps *caps = gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGB);
 -  gst_caps_unref (caps);
 -}
 -
 -GST_END_TEST;
 -
 -
  GST_START_TEST (test_dar_calc)
  {
    guint display_ratio_n, display_ratio_d;
@@@ -590,26 -547,27 +591,26 @@@ GST_START_TEST (test_parse_caps_rgb
    } formats[] = {
      /* 24 bit */
      {
 -    GST_VIDEO_CAPS_RGB, GST_VIDEO_FORMAT_RGB}, {
 -    GST_VIDEO_CAPS_BGR, GST_VIDEO_FORMAT_BGR},
 +    GST_VIDEO_CAPS_MAKE ("RGB"), GST_VIDEO_FORMAT_RGB}, {
 +    GST_VIDEO_CAPS_MAKE ("BGR"), GST_VIDEO_FORMAT_BGR},
          /* 32 bit (no alpha) */
      {
 -    GST_VIDEO_CAPS_RGBx, GST_VIDEO_FORMAT_RGBx}, {
 -    GST_VIDEO_CAPS_xRGB, GST_VIDEO_FORMAT_xRGB}, {
 -    GST_VIDEO_CAPS_BGRx, GST_VIDEO_FORMAT_BGRx}, {
 -    GST_VIDEO_CAPS_xBGR, GST_VIDEO_FORMAT_xBGR},
 +    GST_VIDEO_CAPS_MAKE ("RGBx"), GST_VIDEO_FORMAT_RGBx}, {
 +    GST_VIDEO_CAPS_MAKE ("xRGB"), GST_VIDEO_FORMAT_xRGB}, {
 +    GST_VIDEO_CAPS_MAKE ("BGRx"), GST_VIDEO_FORMAT_BGRx}, {
 +    GST_VIDEO_CAPS_MAKE ("xBGR"), GST_VIDEO_FORMAT_xBGR},
          /* 32 bit (with alpha) */
      {
 -    GST_VIDEO_CAPS_RGBA, GST_VIDEO_FORMAT_RGBA}, {
 -    GST_VIDEO_CAPS_ARGB, GST_VIDEO_FORMAT_ARGB}, {
 -    GST_VIDEO_CAPS_BGRA, GST_VIDEO_FORMAT_BGRA}, {
 -    GST_VIDEO_CAPS_ABGR, GST_VIDEO_FORMAT_ABGR}
 +    GST_VIDEO_CAPS_MAKE ("RGBA"), GST_VIDEO_FORMAT_RGBA}, {
 +    GST_VIDEO_CAPS_MAKE ("ARGB"), GST_VIDEO_FORMAT_ARGB}, {
 +    GST_VIDEO_CAPS_MAKE ("BGRA"), GST_VIDEO_FORMAT_BGRA}, {
 +    GST_VIDEO_CAPS_MAKE ("ABGR"), GST_VIDEO_FORMAT_ABGR}
    };
    gint i;
  
    for (i = 0; i < G_N_ELEMENTS (formats); ++i) {
 -    GstVideoFormat fmt = GST_VIDEO_FORMAT_UNKNOWN;
 +    GstVideoInfo vinfo;
      GstCaps *caps, *caps2;
 -    int w = -1, h = -1;
  
      caps = gst_caps_from_string (formats[i].tmpl_caps_string);
      gst_caps_set_simple (caps, "width", G_TYPE_INT, 2 * (i + 1), "height",
  
      GST_DEBUG ("testing caps: %" GST_PTR_FORMAT, caps);
  
 -    fail_unless (gst_video_format_parse_caps (caps, &fmt, &w, &h));
 -    fail_unless_equals_int (fmt, formats[i].fmt);
 -    fail_unless_equals_int (w, 2 * (i + 1));
 -    fail_unless_equals_int (h, i + 1);
 +    gst_video_info_init (&vinfo);
 +    fail_unless (gst_video_info_from_caps (&vinfo, caps));
 +    fail_unless_equals_int (GST_VIDEO_INFO_FORMAT (&vinfo), formats[i].fmt);
 +    fail_unless_equals_int (GST_VIDEO_INFO_WIDTH (&vinfo), 2 * (i + 1));
 +    fail_unless_equals_int (GST_VIDEO_INFO_HEIGHT (&vinfo), i + 1);
  
      /* make sure they're serialised back correctly */
 -    caps2 = gst_video_format_new_caps (fmt, w, h, 15, 1, 1, 1);
 +    caps2 = gst_video_info_to_caps (&vinfo);
      fail_unless (caps != NULL);
      fail_unless (gst_caps_is_equal (caps, caps2));
  
@@@ -665,10 -622,8 +666,10 @@@ GST_END_TEST
  
  GST_START_TEST (test_convert_frame)
  {
 +  GstVideoInfo vinfo;
    GstCaps *from_caps, *to_caps;
 -  GstBuffer *from_buffer, *to_buffer;
 +  GstBuffer *from_buffer;
 +  GstSample *from_sample, *to_sample;
    GError *error = NULL;
    gint i;
    guint8 *data;
    gst_debug_set_threshold_for_name ("default", GST_LEVEL_NONE);
  
    from_buffer = gst_buffer_new_and_alloc (640 * 480 * 4);
 -  data = GST_BUFFER_DATA (from_buffer);
  
 +  data = gst_buffer_map (from_buffer, NULL, NULL, GST_MAP_WRITE);
    for (i = 0; i < 640 * 480; i++) {
      data[4 * i + 0] = 0;        /* x */
      data[4 * i + 1] = 255;      /* R */
      data[4 * i + 2] = 0;        /* G */
      data[4 * i + 3] = 0;        /* B */
    }
 -  from_caps = gst_video_format_new_caps (GST_VIDEO_FORMAT_xRGB,
 -      640, 480, 25, 1, 1, 1);
 -  gst_buffer_set_caps (from_buffer, from_caps);
 +  gst_buffer_unmap (from_buffer, data, 640 * 480 * 4);
 +
 +  gst_video_info_init (&vinfo);
 +  gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_xRGB, 640, 480);
 +  vinfo.fps_n = 25;
 +  vinfo.fps_d = 1;
 +  vinfo.par_n = 1;
 +  vinfo.par_d = 1;
 +  from_caps = gst_video_info_to_caps (&vinfo);
 +
 +  from_sample = gst_sample_new (from_buffer, from_caps, NULL, NULL);
  
    to_caps =
        gst_caps_from_string
        ("something/that, does=(string)not, exist=(boolean)FALSE");
  
 -  to_buffer =
 -      gst_video_convert_frame (from_buffer, to_caps, GST_CLOCK_TIME_NONE,
 -      &error);
 -  fail_if (to_buffer != NULL);
 +  to_sample =
 +      gst_video_convert_sample (from_sample, to_caps,
 +      GST_CLOCK_TIME_NONE, &error);
 +  fail_if (to_sample != NULL);
    fail_unless (error != NULL);
    g_error_free (error);
    error = NULL;
  
    gst_caps_unref (to_caps);
 -  to_caps =
 -      gst_video_format_new_caps (GST_VIDEO_FORMAT_I420, 240, 320, 25, 1, 1, 2);
 -  to_buffer =
 -      gst_video_convert_frame (from_buffer, to_caps, GST_CLOCK_TIME_NONE,
 -      &error);
 -  fail_unless (to_buffer != NULL);
 -  fail_unless (gst_caps_can_intersect (to_caps, GST_BUFFER_CAPS (to_buffer)));
 +  gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_I420, 240, 320);
 +  vinfo.fps_n = 25;
 +  vinfo.fps_d = 1;
 +  vinfo.par_n = 1;
 +  vinfo.par_d = 2;
 +  to_caps = gst_video_info_to_caps (&vinfo);
 +
 +  to_sample =
 +      gst_video_convert_sample (from_sample, to_caps,
 +      GST_CLOCK_TIME_NONE, &error);
 +  fail_unless (to_sample != NULL);
    fail_unless (error == NULL);
  
    gst_buffer_unref (from_buffer);
    gst_caps_unref (from_caps);
 -  gst_buffer_unref (to_buffer);
 +  gst_sample_unref (from_sample);
 +  gst_sample_unref (to_sample);
    gst_caps_unref (to_caps);
  }
  
@@@ -734,15 -676,15 +735,15 @@@ GST_END_TEST
  typedef struct
  {
    GMainLoop *loop;
 -  GstBuffer *buffer;
 +  GstSample *sample;
    GError *error;
  } ConvertFrameContext;
  
  static void
 -convert_frame_async_callback (GstBuffer * buf, GError * err,
 +convert_sample_async_callback (GstSample * sample, GError * err,
      ConvertFrameContext * cf_data)
  {
 -  cf_data->buffer = buf;
 +  cf_data->sample = sample;
    cf_data->error = err;
  
    g_main_loop_quit (cf_data->loop);
  
  GST_START_TEST (test_convert_frame_async)
  {
 +  GstVideoInfo vinfo;
    GstCaps *from_caps, *to_caps;
    GstBuffer *from_buffer;
 +  GstSample *from_sample;
    gint i;
    guint8 *data;
    GMainLoop *loop;
    gst_debug_set_threshold_for_name ("default", GST_LEVEL_NONE);
  
    from_buffer = gst_buffer_new_and_alloc (640 * 480 * 4);
 -  data = GST_BUFFER_DATA (from_buffer);
  
 +  data = gst_buffer_map (from_buffer, NULL, NULL, GST_MAP_WRITE);
    for (i = 0; i < 640 * 480; i++) {
      data[4 * i + 0] = 0;        /* x */
      data[4 * i + 1] = 255;      /* R */
      data[4 * i + 2] = 0;        /* G */
      data[4 * i + 3] = 0;        /* B */
    }
 -  from_caps = gst_video_format_new_caps (GST_VIDEO_FORMAT_xRGB,
 -      640, 480, 25, 1, 1, 1);
 -  gst_buffer_set_caps (from_buffer, from_caps);
 +  gst_buffer_unmap (from_buffer, data, 640 * 480 * 4);
 +
 +  gst_video_info_init (&vinfo);
 +  gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_xRGB, 640, 470);
 +  vinfo.par_n = 1;
 +  vinfo.par_d = 1;
 +  vinfo.fps_n = 25;
 +  vinfo.fps_d = 1;
 +  from_caps = gst_video_info_to_caps (&vinfo);
  
    to_caps =
        gst_caps_from_string
  
    loop = cf_data.loop = g_main_loop_new (NULL, FALSE);
  
 -  gst_video_convert_frame_async (from_buffer, to_caps, GST_CLOCK_TIME_NONE,
 -      (GstVideoConvertFrameCallback) convert_frame_async_callback, &cf_data,
 +  from_sample = gst_sample_new (from_buffer, from_caps, NULL, NULL);
 +  gst_buffer_unref (from_buffer);
 +  gst_caps_unref (from_caps);
 +
 +  gst_video_convert_sample_async (from_sample, to_caps,
 +      GST_CLOCK_TIME_NONE,
 +      (GstVideoConvertSampleCallback) convert_sample_async_callback, &cf_data,
        NULL);
  
    g_main_loop_run (loop);
  
 -  fail_if (cf_data.buffer != NULL);
 +  fail_if (cf_data.sample != NULL);
    fail_unless (cf_data.error != NULL);
    g_error_free (cf_data.error);
    cf_data.error = NULL;
  
    gst_caps_unref (to_caps);
 -  to_caps =
 -      gst_video_format_new_caps (GST_VIDEO_FORMAT_I420, 240, 320, 25, 1, 1, 2);
 -  gst_video_convert_frame_async (from_buffer, to_caps, GST_CLOCK_TIME_NONE,
 -      (GstVideoConvertFrameCallback) convert_frame_async_callback, &cf_data,
 +  gst_video_info_init (&vinfo);
 +  gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_I420, 240, 320);
 +  vinfo.par_n = 1;
 +  vinfo.par_d = 2;
 +  vinfo.fps_n = 25;
 +  vinfo.fps_d = 1;
 +  to_caps = gst_video_info_to_caps (&vinfo);
 +  gst_video_convert_sample_async (from_sample, to_caps,
 +      GST_CLOCK_TIME_NONE,
 +      (GstVideoConvertSampleCallback) convert_sample_async_callback, &cf_data,
        NULL);
    g_main_loop_run (loop);
 -  fail_unless (cf_data.buffer != NULL);
 -  fail_unless (gst_caps_can_intersect (to_caps,
 -          GST_BUFFER_CAPS (cf_data.buffer)));
 +  fail_unless (cf_data.sample != NULL);
    fail_unless (cf_data.error == NULL);
  
 -  gst_buffer_unref (from_buffer);
 -  gst_caps_unref (from_caps);
 -  gst_buffer_unref (cf_data.buffer);
 +  gst_sample_unref (cf_data.sample);
    gst_caps_unref (to_caps);
  
    g_main_loop_unref (loop);
@@@ -828,23 -755,171 +829,168 @@@ GST_END_TEST
  
  GST_START_TEST (test_video_size_from_caps)
  {
 -  gint size;
 -  guint32 fourcc = GST_MAKE_FOURCC ('Y', 'V', '1', '2');
 -  GstCaps *caps = gst_caps_new_simple ("video/x-raw-yuv",
 -      "format", GST_TYPE_FOURCC, fourcc,
 +  GstVideoInfo vinfo;
 +  GstCaps *caps;
 +
 +  caps = gst_caps_new_simple ("video/x-raw",
 +      "format", G_TYPE_STRING, "YV12",
        "width", G_TYPE_INT, 640,
 -      "height", G_TYPE_INT, 480,
 -      "framerate", GST_TYPE_FRACTION, 25, 1,
 -      NULL);
 +      "height", G_TYPE_INT, 480, "framerate", GST_TYPE_FRACTION, 25, 1, NULL);
  
 -  fail_unless (gst_video_get_size_from_caps (caps, &size));
 -  fail_unless (size ==
 -      gst_video_format_get_size (gst_video_format_from_fourcc (fourcc), 640,
 -          480));
 -  fail_unless (size == (640 * 480 * 12 / 8));
 +  gst_video_info_init (&vinfo);
 +  fail_unless (gst_video_info_from_caps (&vinfo, caps));
 +  fail_unless (GST_VIDEO_INFO_SIZE (&vinfo) == (640 * 480 * 12 / 8));
  
    gst_caps_unref (caps);
  }
  
  GST_END_TEST;
  
+ #undef ASSERT_CRITICAL
+ #define ASSERT_CRITICAL(code) while(0){}        /* nothing */
+ GST_START_TEST (test_overlay_composition)
+ {
+   GstVideoOverlayComposition *comp1, *comp2;
+   GstVideoOverlayRectangle *rect1, *rect2;
+   GstBuffer *pix1, *pix2, *buf;
+   guint seq1, seq2;
+   guint w, h, stride;
+   gint x, y;
+   pix1 = gst_buffer_new_and_alloc (200 * sizeof (guint32) * 50);
+   memset (GST_BUFFER_DATA (pix1), 0, GST_BUFFER_SIZE (pix1));
+   rect1 = gst_video_overlay_rectangle_new_argb (pix1, 200, 50, 200 * 4,
+       600, 50, 300, 50, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
+   gst_buffer_unref (pix1);
+   pix1 = NULL;
+   comp1 = gst_video_overlay_composition_new (rect1);
+   fail_unless (gst_video_overlay_composition_n_rectangles (comp1) == 1);
+   fail_unless (gst_video_overlay_composition_get_rectangle (comp1, 0) == rect1);
+   fail_unless (gst_video_overlay_composition_get_rectangle (comp1, 1) == NULL);
+   /* rectangle was created first, sequence number should be smaller */
+   seq1 = gst_video_overlay_rectangle_get_seqnum (rect1);
+   seq2 = gst_video_overlay_composition_get_seqnum (comp1);
+   fail_unless (seq1 < seq2);
+   /* composition took own ref, so refcount is 2 now, so this should fail */
+   ASSERT_CRITICAL (gst_video_overlay_rectangle_set_render_rectangle (rect1, 50,
+           600, 300, 50));
+   /* drop our ref, so refcount is 1 (we know it will continue to be valid) */
+   gst_video_overlay_rectangle_unref (rect1);
+   gst_video_overlay_rectangle_set_render_rectangle (rect1, 50, 600, 300, 50);
+   comp2 = gst_video_overlay_composition_new (rect1);
+   fail_unless (gst_video_overlay_composition_n_rectangles (comp2) == 1);
+   fail_unless (gst_video_overlay_composition_get_rectangle (comp2, 0) == rect1);
+   fail_unless (gst_video_overlay_composition_get_rectangle (comp2, 1) == NULL);
+   fail_unless (seq1 < gst_video_overlay_composition_get_seqnum (comp2));
+   fail_unless (seq2 < gst_video_overlay_composition_get_seqnum (comp2));
+   /* now refcount is 2 again because comp2 has also taken a ref, so must fail */
+   ASSERT_CRITICAL (gst_video_overlay_rectangle_set_render_rectangle (rect1, 0,
+           0, 1, 1));
+   /* this should make a copy of the rectangles so drop the original
+    * second ref on rect1 */
+   comp2 = gst_video_overlay_composition_make_writable (comp2);
+   gst_video_overlay_rectangle_set_render_rectangle (rect1, 51, 601, 301, 51);
+   rect2 = gst_video_overlay_composition_get_rectangle (comp2, 0);
+   fail_unless (gst_video_overlay_composition_n_rectangles (comp2) == 1);
+   fail_unless (gst_video_overlay_composition_get_rectangle (comp2, 0) == rect2);
+   fail_unless (gst_video_overlay_composition_get_rectangle (comp2, 1) == NULL);
+   fail_unless (rect1 != rect2);
+   gst_video_overlay_composition_add_rectangle (comp1, rect2);
+   gst_video_overlay_composition_ref (comp1);
+   ASSERT_CRITICAL (gst_video_overlay_composition_add_rectangle (comp1, rect2));
+   gst_video_overlay_composition_unref (comp1);
+   /* make sure the copy really worked */
+   gst_video_overlay_rectangle_get_render_rectangle (rect1, &x, &y, &w, &h);
+   fail_unless_equals_int (x, 51);
+   fail_unless_equals_int (y, 601);
+   fail_unless_equals_int (w, 301);
+   fail_unless_equals_int (h, 51);
+   /* get scaled pixbuf and touch last byte */
+   pix1 = gst_video_overlay_rectangle_get_pixels_argb (rect1, &stride,
+       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
+   fail_unless (GST_BUFFER_SIZE (pix1) > ((h - 1) * stride + (w * 4) - 1),
+       "size %u vs. last pixel offset %u", GST_BUFFER_SIZE (pix1),
+       ((h - 1) * stride + (w * 4) - 1));
+   fail_unless_equals_int (*(GST_BUFFER_DATA (pix1) + ((h - 1) * stride +
+               (w * 4) - 1)), 0);
+   gst_video_overlay_rectangle_get_render_rectangle (rect2, &x, &y, &w, &h);
+   fail_unless_equals_int (x, 50);
+   fail_unless_equals_int (y, 600);
+   fail_unless_equals_int (w, 300);
+   fail_unless_equals_int (h, 50);
+   /* get scaled pixbuf and touch last byte */
+   pix2 = gst_video_overlay_rectangle_get_pixels_argb (rect2, &stride,
+       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
+   fail_unless (GST_BUFFER_SIZE (pix2) > ((h - 1) * stride + (w * 4) - 1),
+       "size %u vs. last pixel offset %u", GST_BUFFER_SIZE (pix1),
+       ((h - 1) * stride + (w * 4) - 1));
+   fail_unless_equals_int (*(GST_BUFFER_DATA (pix2) + ((h - 1) * stride +
+               (w * 4) - 1)), 0);
+   /* get scaled pixbuf again, should be the same buffer as before (caching) */
+   pix1 = gst_video_overlay_rectangle_get_pixels_argb (rect2, &stride,
+       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
+   fail_unless (pix1 == pix2);
+   /* now compare the original unscaled ones */
+   pix1 = gst_video_overlay_rectangle_get_pixels_unscaled_argb (rect1, &w, &h,
+       &stride, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
+   pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_argb (rect2, &w, &h,
+       &stride, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
+   /* the original pixel buffers should be identical */
+   fail_unless (pix1 == pix2);
+   fail_unless_equals_int (w, 200);
+   fail_unless_equals_int (h, 50);
+   /* touch last byte */
+   fail_unless (GST_BUFFER_SIZE (pix1) > ((h - 1) * stride + (w * 4) - 1),
+       "size %u vs. last pixel offset %u", GST_BUFFER_SIZE (pix1),
+       ((h - 1) * stride + (w * 4) - 1));
+   fail_unless_equals_int (*(GST_BUFFER_DATA (pix1) + ((h - 1) * stride +
+               (w * 4) - 1)), 0);
+   /* test attaching and retrieving of compositions to/from buffers */
+   buf = gst_buffer_new ();
+   fail_unless (gst_video_buffer_get_overlay_composition (buf) == NULL);
+   gst_buffer_ref (buf);
+   ASSERT_CRITICAL (gst_video_buffer_set_overlay_composition (buf, comp1));
+   gst_buffer_unref (buf);
+   gst_video_buffer_set_overlay_composition (buf, comp1);
+   fail_unless (gst_video_buffer_get_overlay_composition (buf) == comp1);
+   gst_video_buffer_set_overlay_composition (buf, comp2);
+   fail_unless (gst_video_buffer_get_overlay_composition (buf) == comp2);
+   gst_video_buffer_set_overlay_composition (buf, NULL);
+   fail_unless (gst_video_buffer_get_overlay_composition (buf) == NULL);
+   /* make sure the buffer cleans up its composition ref when unreffed */
+   gst_video_buffer_set_overlay_composition (buf, comp2);
+   gst_buffer_unref (buf);
+   gst_video_overlay_composition_unref (comp2);
+   gst_video_overlay_composition_unref (comp1);
+ }
+ GST_END_TEST;
  static Suite *
  video_suite (void)
  {
    suite_add_tcase (s, tc_chain);
    tcase_add_test (tc_chain, test_video_formats);
    tcase_add_test (tc_chain, test_video_formats_rgb);
 -  tcase_add_test (tc_chain, test_video_template_caps);
 +  tcase_add_test (tc_chain, test_video_formats_all);
    tcase_add_test (tc_chain, test_dar_calc);
    tcase_add_test (tc_chain, test_parse_caps_rgb);
    tcase_add_test (tc_chain, test_events);
    tcase_add_test (tc_chain, test_convert_frame);
    tcase_add_test (tc_chain, test_convert_frame_async);
    tcase_add_test (tc_chain, test_video_size_from_caps);
+   tcase_add_test (tc_chain, test_overlay_composition);
  
    return s;
  }
@@@ -8,9 -8,9 +8,8 @@@ if USE_GI
  GIO_SUBDIRS = gio
  endif
  
- SUBDIRS = app audio dynamic $(FT2_SUBDIRS) $(GIO_SUBDIRS) overlay playrec encoding
 -SUBDIRS = app audio dynamic fft $(FT2_SUBDIRS) $(GIO_SUBDIRS) overlay playrec v4l encoding
--
- DIST_SUBDIRS = app audio dynamic gio overlay seek snapshot playrec encoding
 -DIST_SUBDIRS = app audio dynamic fft gio overlay seek snapshot playrec v4l encoding
++SUBDIRS = app audio dynamic fft $(FT2_SUBDIRS) $(GIO_SUBDIRS) overlay playrec encoding
++DIST_SUBDIRS = app audio dynamic fft gio overlay seek snapshot playrec encoding
  
  include $(top_srcdir)/common/parallel-subdirs.mak
  
@@@ -225,7 -225,7 +225,7 @@@ pad_added_cb (GstElement * uridecodebin
      GstCaps *caps;
  
      /* Ask encodebin for a compatible pad */
 -    caps = gst_pad_get_caps (pad);
 +    caps = gst_pad_query_caps (pad, NULL);
      g_signal_emit_by_name (encodebin, "request-pad", caps, &sinkpad);
      if (caps)
        gst_caps_unref (caps);
@@@ -395,8 -395,10 +395,10 @@@ main (int argc, char **argv
    GstEncodingProfile *prof;
    gchar *inputuri;
  
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
    if (!g_thread_supported ())
      g_thread_init (NULL);
+ #endif
  
    ctx = g_option_context_new ("- encode URIs with GstProfile and encodebin");
    g_option_context_add_main_entries (ctx, options, NULL);
@@@ -1,7 -1,7 +1,7 @@@
  /* GStreamer
   * Copyright (C) <2010> Stefan Kost <ensonic@users.sf.net>
   *
 - * gtk-xoverlay: demonstrate overlay handling using gtk
 + * gtk-videooverlay: demonstrate overlay handling using gtk
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Library General Public
@@@ -28,7 -28,7 +28,7 @@@
  #include <gtk/gtk.h>
  
  #include <gst/gst.h>
 -#include <gst/interfaces/xoverlay.h>
 +#include <gst/video/videooverlay.h>
  
  #include <string.h>
  
@@@ -98,8 -98,10 +98,10 @@@ main (int argc, char **argv
    gulong embed_xid;
    GstStateChangeReturn sret;
  
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
    if (!g_thread_supported ())
      g_thread_init (NULL);
+ #endif
  
    gst_init (&argc, &argv);
    gtk_init (&argc, &argv);
  
    video_window_xwindow = gtk_widget_get_window (video_window);
    embed_xid = GDK_WINDOW_XID (video_window_xwindow);
 -  gst_x_overlay_set_window_handle (GST_X_OVERLAY (sink), embed_xid);
 +  gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink), embed_xid);
  
    /* run the pipeline */
  
@@@ -25,7 -25,7 +25,7 @@@
  
  #include <glib.h>
  #include <gst/gst.h>
 -#include <gst/interfaces/xoverlay.h>
 +#include <gst/video/videooverlay.h>
  
  #include <QApplication>
  #include <QTimer>
@@@ -80,8 -80,10 +80,10 @@@ find_video_sink (void
  
  int main(int argc, char *argv[])
  {
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
    if (!g_thread_supported ())
      g_thread_init (NULL);
+ #endif
  
    gst_init (&argc, &argv);
    QApplication app(argc, argv);
    window.show();
    
    WId xwinid = window.winId();
 -  gst_x_overlay_set_window_handle (GST_X_OVERLAY (sink), xwinid);
 +  gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink), xwinid);
  
    /* run the pipeline */
  
  #ifdef HAVE_X
  #include <gdk/gdkx.h>
  #endif
 -#include <gst/interfaces/xoverlay.h>
 +#include <gst/video/videooverlay.h>
  
  GST_DEBUG_CATEGORY_STATIC (seek_debug);
  #define GST_CAT_DEFAULT (seek_debug)
  
  /* configuration */
 -
 -//#define SOURCE "filesrc"
 -#define SOURCE "gnomevfssrc"
 +#define SOURCE "filesrc"
  
  #define ASINK "alsasink"
  //#define ASINK "osssink"
@@@ -468,7 -470,7 +468,7 @@@ make_theora_pipeline (const gchar * loc
    src = gst_element_factory_make_or_warn (SOURCE, "src");
    demux = gst_element_factory_make_or_warn ("oggdemux", "demux");
    decoder = gst_element_factory_make_or_warn ("theoradec", "decoder");
 -  convert = gst_element_factory_make_or_warn ("ffmpegcolorspace", "convert");
 +  convert = gst_element_factory_make_or_warn ("videoconvert", "convert");
    videosink = gst_element_factory_make_or_warn (VSINK, "sink");
  
    g_object_set (G_OBJECT (src), "location", location, NULL);
@@@ -550,7 -552,8 +550,7 @@@ make_vorbis_theora_pipeline (const gcha
    video_bin = gst_bin_new ("v_decoder_bin");
    v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
    v_decoder = gst_element_factory_make_or_warn ("theoradec", "v_dec");
 -  v_convert =
 -      gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_convert");
 +  v_convert = gst_element_factory_make_or_warn ("videoconvert", "v_convert");
    v_scale = gst_element_factory_make_or_warn ("videoscale", "v_scale");
    videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
  
@@@ -629,7 -632,8 +629,7 @@@ make_avi_msmpeg4v3_mp3_pipeline (const 
    video_bin = gst_bin_new ("v_decoder_bin");
    v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
    v_decoder = gst_element_factory_make_or_warn ("ffdec_msmpeg4", "v_dec");
 -  v_convert =
 -      gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_convert");
 +  v_convert = gst_element_factory_make_or_warn ("videoconvert", "v_convert");
    videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
  
    gst_bin_add (GST_BIN (video_bin), v_queue);
@@@ -809,7 -813,7 +809,7 @@@ make_mpeg_pipeline (const gchar * locat
    video_bin = gst_bin_new ("v_decoder_bin");
    v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec");
    v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
 -  v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter");
 +  v_filter = gst_element_factory_make_or_warn ("videoconvert", "v_filter");
    videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
  
    gst_bin_add (GST_BIN (video_bin), v_decoder);
@@@ -887,7 -891,7 +887,7 @@@ make_mpegnt_pipeline (const gchar * loc
  
    video_bin = gst_bin_new ("v_decoder_bin");
    v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec");
 -  v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter");
 +  v_filter = gst_element_factory_make_or_warn ("videoconvert", "v_filter");
    videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
    gst_element_link_many (v_decoder, v_filter, videosink, NULL);
  
@@@ -1060,7 -1064,7 +1060,7 @@@ query_rates (void
  
        format = seek_formats[i].format;
  
 -      if (gst_pad_query_convert (pad, GST_FORMAT_TIME, GST_SECOND, &format,
 +      if (gst_pad_query_convert (pad, GST_FORMAT_TIME, GST_SECOND, format,
                &value)) {
          g_print ("%s %13" G_GINT64_FORMAT " | ", seek_formats[i].name, value);
        } else {
@@@ -1091,8 -1095,8 +1091,8 @@@ query_positions_elems (void
  
        format = seek_formats[i].format;
  
 -      if (gst_element_query_position (element, &format, &position) &&
 -          gst_element_query_duration (element, &format, &total)) {
 +      if (gst_element_query_position (element, format, &position) &&
 +          gst_element_query_duration (element, format, &total)) {
          g_print ("%s %13" G_GINT64_FORMAT " / %13" G_GINT64_FORMAT " | ",
              seek_formats[i].name, position, total);
        } else {
@@@ -1123,8 -1127,8 +1123,8 @@@ query_positions_pads (void
  
        format = seek_formats[i].format;
  
 -      if (gst_pad_query_position (pad, &format, &position) &&
 -          gst_pad_query_duration (pad, &format, &total)) {
 +      if (gst_pad_query_position (pad, format, &position) &&
 +          gst_pad_query_duration (pad, format, &total)) {
          g_print ("%s %13" G_GINT64_FORMAT " / %13" G_GINT64_FORMAT " | ",
              seek_formats[i].name, position, total);
        } else {
@@@ -1212,19 -1216,24 +1212,19 @@@ update_fill (gpointer data
  static gboolean
  update_scale (gpointer data)
  {
 -  GstFormat format = GST_FORMAT_TIME;
 -
 -  //position = 0;
 -  //duration = 0;
 -
    if (elem_seek) {
      if (seekable_elements) {
        GstElement *element = GST_ELEMENT (seekable_elements->data);
  
 -      gst_element_query_position (element, &format, &position);
 -      gst_element_query_duration (element, &format, &duration);
 +      gst_element_query_position (element, GST_FORMAT_TIME, &position);
 +      gst_element_query_duration (element, GST_FORMAT_TIME, &duration);
      }
    } else {
      if (seekable_pads) {
        GstPad *pad = GST_PAD (seekable_pads->data);
  
 -      gst_pad_query_position (pad, &format, &position);
 -      gst_pad_query_duration (pad, &format, &duration);
 +      gst_pad_query_position (pad, GST_FORMAT_TIME, &position);
 +      gst_pad_query_duration (pad, GST_FORMAT_TIME, &duration);
      }
    }
  
@@@ -2021,18 -2030,12 +2021,18 @@@ shot_cb (GtkButton * button, gpointer d
      gint width, height;
      GdkPixbuf *pixbuf;
      GError *error = NULL;
 +    gsize size;
 +    guint8 *data;
  
      /* get the snapshot buffer format now. We set the caps on the appsink so
       * that it can only be an rgb buffer. The only thing we have not specified
       * on the caps is the height, which is dependant on the pixel-aspect-ratio
       * of the source material */
 +#if 0
      caps = GST_BUFFER_CAPS (buffer);
 +#endif
 +    /* FIXME, get the caps on the buffer somehow */
 +    caps = NULL;
      if (!caps) {
        g_warning ("could not get snapshot format\n");
        goto done;
  
      /* create pixmap from buffer and save, gstreamer video buffers have a stride
       * that is rounded up to the nearest multiple of 4 */
 -    pixbuf = gdk_pixbuf_new_from_data (GST_BUFFER_DATA (buffer),
 +    data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
 +    pixbuf = gdk_pixbuf_new_from_data (data,
          GDK_COLORSPACE_RGB, FALSE, 8, width, height,
          GST_ROUND_UP_4 (width * 3), NULL, NULL);
  
      /* save the pixbuf */
      gdk_pixbuf_save (pixbuf, "snapshot.png", "png", &error, NULL);
 +    gst_buffer_unmap (buffer, data, size);
 +
 +    /* save the pixbuf */
 +    gdk_pixbuf_save (pixbuf, "snapshot.png", "png", &error, NULL);
  
    done:
      gst_buffer_unref (buffer);
@@@ -2424,7 -2422,7 +2424,7 @@@ msg_clock_lost (GstBus * bus, GstMessag
  
  static gulong embed_xid = 0;
  
 -/* We set the xid here in response to the prepare-xwindow-id message via a
 +/* We set the xid here in response to the prepare-window-handle message via a
   * bus sync handler because we don't know the actual videosink used from the
   * start (as we don't know the pipeline, or bin elements such as autovideosink
   * or gconfvideosink may be used which create the actual videosink only once
  static GstBusSyncReply
  bus_sync_handler (GstBus * bus, GstMessage * message, GstPipeline * data)
  {
 -  if ((GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT) &&
 -      gst_structure_has_name (message->structure, "prepare-xwindow-id")) {
 -    GstElement *element = GST_ELEMENT (GST_MESSAGE_SRC (message));
 +  GstElement *element;
  
 -    g_print ("got prepare-xwindow-id, setting XID %lu\n", embed_xid);
 +  if (!gst_is_video_overlay_prepare_window_handle_message (message))
 +    return GST_BUS_PASS;
  
 -    if (g_object_class_find_property (G_OBJECT_GET_CLASS (element),
 -            "force-aspect-ratio")) {
 -      g_object_set (element, "force-aspect-ratio", TRUE, NULL);
 -    }
 +  element = GST_ELEMENT (GST_MESSAGE_SRC (message));
  
 -    /* Should have been initialised from main thread before (can't use
 -     * GDK_WINDOW_XID here with Gtk+ >= 2.18, because the sync handler will
 -     * be called from a streaming thread and GDK_WINDOW_XID maps to more than
 -     * a simple structure lookup with Gtk+ >= 2.18, where 'more' is stuff that
 -     * shouldn't be done from a non-GUI thread without explicit locking).  */
 -    g_assert (embed_xid != 0);
 +  g_print ("got prepare-window-handle, setting XID %lu\n", embed_xid);
  
 -    gst_x_overlay_set_window_handle (GST_X_OVERLAY (element), embed_xid);
 +  if (g_object_class_find_property (G_OBJECT_GET_CLASS (element),
 +          "force-aspect-ratio")) {
 +    g_object_set (element, "force-aspect-ratio", TRUE, NULL);
    }
 +
 +  /* Should have been initialised from main thread before (can't use
 +   * GDK_WINDOW_XID here with Gtk+ >= 2.18, because the sync handler will
 +   * be called from a streaming thread and GDK_WINDOW_XID maps to more than
 +   * a simple structure lookup with Gtk+ >= 2.18, where 'more' is stuff that
 +   * shouldn't be done from a non-GUI thread without explicit locking).  */
 +  g_assert (embed_xid != 0);
 +
 +  gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (element), embed_xid);
    return GST_BUS_PASS;
  }
  #endif
@@@ -2519,7 -2515,7 +2519,7 @@@ connect_bus_signals (GstElement * pipel
    GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
  
  #ifdef HAVE_X
 -  /* handle prepare-xwindow-id element message synchronously */
 +  /* handle prepare-window-handle element message synchronously */
    gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bus_sync_handler,
        pipeline);
  #endif
@@@ -2676,8 -2672,10 +2676,10 @@@ main (int argc, char **argv
    GOptionContext *ctx;
    GError *err = NULL;
  
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
    if (!g_thread_supported ())
      g_thread_init (NULL);
+ #endif
  
    ctx = g_option_context_new ("- test seeking in gsteamer");
    g_option_context_add_main_entries (ctx, options, NULL);
@@@ -21,7 -21,8 +21,7 @@@ static guint update_id = 0
  static guint changed_id = 0;
  static guint schanged_id = 0;
  
 -//#define SOURCE "filesrc"
 -#define SOURCE "gnomevfssrc"
 +#define SOURCE "filesrc"
  #define ASINK "alsasink"
  //#define ASINK "osssink"
  #define VSINK "xvimagesink"
@@@ -145,11 -146,15 +145,11 @@@ format_value (GtkScale * scale, gdoubl
  static gboolean
  update_scale (gpointer data)
  {
 -  GstFormat format;
 -
    position = 0;
    duration = 0;
  
 -  format = GST_FORMAT_TIME;
 -
 -  gst_element_query_position (pipeline, &format, &position);
 -  gst_element_query_duration (pipeline, &format, &duration);
 +  gst_element_query_position (pipeline, GST_FORMAT_TIME, &position);
 +  gst_element_query_duration (pipeline, GST_FORMAT_TIME, &duration);
  
    if (position >= duration)
      duration = position;
@@@ -458,8 -463,10 +458,10 @@@ main (int argc, char **argv
    GOptionContext *ctx;
    GError *err = NULL;
  
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
    if (!g_thread_supported ())
      g_thread_init (NULL);
+ #endif
  
    ctx = g_option_context_new ("seek");
    g_option_context_add_main_entries (ctx, options, NULL);
@@@ -39,7 -39,7 +39,7 @@@
  #include <gdk/gdkwin32.h>
  #endif
  
 -#include <gst/interfaces/xoverlay.h>
 +#include <gst/video/videooverlay.h>
  
  GST_DEBUG_CATEGORY_STATIC (seek_debug);
  #define GST_CAT_DEFAULT (seek_debug)
@@@ -69,6 -69,8 +69,6 @@@ static gchar *opt_videosink_str
  
  #define N_GRAD 1000.0
  
 -static GList *seekable_pads = NULL;
 -static GList *rate_pads = NULL;
  static GList *seekable_elements = NULL;
  
  static gboolean accurate_seek = FALSE;
@@@ -89,6 -91,7 +89,6 @@@ static GtkAdjustment *adjustment
  static GtkWidget *hscale, *statusbar;
  static guint status_id = 0;
  static gboolean stats = FALSE;
 -static gboolean elem_seek = FALSE;
  static gboolean verbose = FALSE;
  
  static gboolean is_live = FALSE;
@@@ -164,6 -167,744 +164,6 @@@ gst_element_factory_make_or_warn (cons
  }
  
  static void
 -dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer data)
 -{
 -  gchar *padname;
 -  dyn_link *connect = (dyn_link *) data;
 -
 -  padname = gst_pad_get_name (newpad);
 -
 -  if (connect->padname == NULL || !strcmp (padname, connect->padname)) {
 -    if (connect->bin)
 -      gst_bin_add (GST_BIN (pipeline), connect->bin);
 -    gst_pad_link (newpad, connect->target);
 -
 -    //seekable_pads = g_list_prepend (seekable_pads, newpad);
 -    rate_pads = g_list_prepend (rate_pads, newpad);
 -  }
 -  g_free (padname);
 -}
 -
 -static void
 -setup_dynamic_link (GstElement * element, const gchar * padname,
 -    GstPad * target, GstElement * bin)
 -{
 -  dyn_link *connect;
 -
 -  connect = g_new0 (dyn_link, 1);
 -  connect->padname = g_strdup (padname);
 -  connect->target = target;
 -  connect->bin = bin;
 -
 -  g_signal_connect (G_OBJECT (element), "pad-added", G_CALLBACK (dynamic_link),
 -      connect);
 -}
 -
 -static GstElement *
 -make_mod_pipeline (const gchar * location)
 -{
 -  GstElement *pipeline;
 -  GstElement *src, *decoder, *audiosink;
 -  GstPad *seekable;
 -
 -  pipeline = gst_pipeline_new ("app");
 -
 -  src = gst_element_factory_make_or_warn (SOURCE, "src");
 -  decoder = gst_element_factory_make_or_warn ("modplug", "decoder");
 -  audiosink = gst_element_factory_make_or_warn (opt_audiosink_str, "sink");
 -  //g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
 -
 -  g_object_set (G_OBJECT (src), "location", location, NULL);
 -
 -  gst_bin_add (GST_BIN (pipeline), src);
 -  gst_bin_add (GST_BIN (pipeline), decoder);
 -  gst_bin_add (GST_BIN (pipeline), audiosink);
 -
 -  gst_element_link (src, decoder);
 -  gst_element_link (decoder, audiosink);
 -
 -  seekable = gst_element_get_static_pad (decoder, "src");
 -  seekable_pads = g_list_prepend (seekable_pads, seekable);
 -  rate_pads = g_list_prepend (rate_pads, seekable);
 -  rate_pads =
 -      g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink"));
 -
 -  return pipeline;
 -}
 -
 -static GstElement *
 -make_dv_pipeline (const gchar * location)
 -{
 -  GstElement *pipeline;
 -  GstElement *src, *demux, *decoder, *audiosink, *videosink;
 -  GstElement *a_queue, *v_queue;
 -  GstPad *seekable;
 -
 -  pipeline = gst_pipeline_new ("app");
 -
 -  src = gst_element_factory_make_or_warn (SOURCE, "src");
 -  demux = gst_element_factory_make_or_warn ("dvdemux", "demuxer");
 -  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
 -  decoder = gst_element_factory_make_or_warn ("ffdec_dvvideo", "decoder");
 -  videosink = gst_element_factory_make_or_warn (opt_videosink_str, "v_sink");
 -  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
 -  audiosink = gst_element_factory_make_or_warn ("alsasink", "a_sink");
 -
 -  g_object_set (G_OBJECT (src), "location", location, NULL);
 -
 -  gst_bin_add (GST_BIN (pipeline), src);
 -  gst_bin_add (GST_BIN (pipeline), demux);
 -  gst_bin_add (GST_BIN (pipeline), a_queue);
 -  gst_bin_add (GST_BIN (pipeline), audiosink);
 -  gst_bin_add (GST_BIN (pipeline), v_queue);
 -  gst_bin_add (GST_BIN (pipeline), decoder);
 -  gst_bin_add (GST_BIN (pipeline), videosink);
 -
 -  gst_element_link (src, demux);
 -  gst_element_link (a_queue, audiosink);
 -  gst_element_link (v_queue, decoder);
 -  gst_element_link (decoder, videosink);
 -
 -  setup_dynamic_link (demux, "video", gst_element_get_static_pad (v_queue,
 -          "sink"), NULL);
 -  setup_dynamic_link (demux, "audio", gst_element_get_static_pad (a_queue,
 -          "sink"), NULL);
 -
 -  seekable = gst_element_get_static_pad (decoder, "src");
 -  seekable_pads = g_list_prepend (seekable_pads, seekable);
 -  rate_pads = g_list_prepend (rate_pads, seekable);
 -
 -  return pipeline;
 -}
 -
 -static GstElement *
 -make_wav_pipeline (const gchar * location)
 -{
 -  GstElement *pipeline;
 -  GstElement *src, *decoder, *audiosink;
 -
 -  pipeline = gst_pipeline_new ("app");
 -
 -  src = gst_element_factory_make_or_warn (SOURCE, "src");
 -  decoder = gst_element_factory_make_or_warn ("wavparse", "decoder");
 -  audiosink = gst_element_factory_make_or_warn (opt_audiosink_str, "sink");
 -
 -  g_object_set (G_OBJECT (src), "location", location, NULL);
 -
 -  gst_bin_add (GST_BIN (pipeline), src);
 -  gst_bin_add (GST_BIN (pipeline), decoder);
 -  gst_bin_add (GST_BIN (pipeline), audiosink);
 -
 -  gst_element_link (src, decoder);
 -
 -  setup_dynamic_link (decoder, "src", gst_element_get_static_pad (audiosink,
 -          "sink"), NULL);
 -
 -  seekable_elements = g_list_prepend (seekable_elements, audiosink);
 -
 -  /* force element seeking on this pipeline */
 -  elem_seek = TRUE;
 -
 -  return pipeline;
 -}
 -
 -static GstElement *
 -make_flac_pipeline (const gchar * location)
 -{
 -  GstElement *pipeline;
 -  GstElement *src, *decoder, *audiosink;
 -  GstPad *seekable;
 -
 -  pipeline = gst_pipeline_new ("app");
 -
 -  src = gst_element_factory_make_or_warn (SOURCE, "src");
 -  decoder = gst_element_factory_make_or_warn ("flacdec", "decoder");
 -  audiosink = gst_element_factory_make_or_warn (opt_audiosink_str, "sink");
 -  g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
 -
 -  g_object_set (G_OBJECT (src), "location", location, NULL);
 -
 -  gst_bin_add (GST_BIN (pipeline), src);
 -  gst_bin_add (GST_BIN (pipeline), decoder);
 -  gst_bin_add (GST_BIN (pipeline), audiosink);
 -
 -  gst_element_link (src, decoder);
 -  gst_element_link (decoder, audiosink);
 -
 -  seekable = gst_element_get_static_pad (decoder, "src");
 -  seekable_pads = g_list_prepend (seekable_pads, seekable);
 -  rate_pads = g_list_prepend (rate_pads, seekable);
 -  rate_pads =
 -      g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink"));
 -
 -  return pipeline;
 -}
 -
 -static GstElement *
 -make_sid_pipeline (const gchar * location)
 -{
 -  GstElement *pipeline;
 -  GstElement *src, *decoder, *audiosink;
 -  GstPad *seekable;
 -
 -  pipeline = gst_pipeline_new ("app");
 -
 -  src = gst_element_factory_make_or_warn (SOURCE, "src");
 -  decoder = gst_element_factory_make_or_warn ("siddec", "decoder");
 -  audiosink = gst_element_factory_make_or_warn (opt_audiosink_str, "sink");
 -  //g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
 -
 -  g_object_set (G_OBJECT (src), "location", location, NULL);
 -
 -  gst_bin_add (GST_BIN (pipeline), src);
 -  gst_bin_add (GST_BIN (pipeline), decoder);
 -  gst_bin_add (GST_BIN (pipeline), audiosink);
 -
 -  gst_element_link (src, decoder);
 -  gst_element_link (decoder, audiosink);
 -
 -  seekable = gst_element_get_static_pad (decoder, "src");
 -  seekable_pads = g_list_prepend (seekable_pads, seekable);
 -  rate_pads = g_list_prepend (rate_pads, seekable);
 -  rate_pads =
 -      g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink"));
 -
 -  return pipeline;
 -}
 -
 -static GstElement *
 -make_parse_pipeline (const gchar * location)
 -{
 -  GstElement *pipeline;
 -  GstElement *src, *parser, *fakesink;
 -  GstPad *seekable;
 -
 -  pipeline = gst_pipeline_new ("app");
 -
 -  src = gst_element_factory_make_or_warn (SOURCE, "src");
 -  parser = gst_element_factory_make_or_warn ("mpegparse", "parse");
 -  fakesink = gst_element_factory_make_or_warn ("fakesink", "sink");
 -  g_object_set (G_OBJECT (fakesink), "silent", TRUE, NULL);
 -  g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
 -
 -  g_object_set (G_OBJECT (src), "location", location, NULL);
 -
 -  gst_bin_add (GST_BIN (pipeline), src);
 -  gst_bin_add (GST_BIN (pipeline), parser);
 -  gst_bin_add (GST_BIN (pipeline), fakesink);
 -
 -  gst_element_link (src, parser);
 -  gst_element_link (parser, fakesink);
 -
 -  seekable = gst_element_get_static_pad (parser, "src");
 -  seekable_pads = g_list_prepend (seekable_pads, seekable);
 -  rate_pads = g_list_prepend (rate_pads, seekable);
 -  rate_pads =
 -      g_list_prepend (rate_pads, gst_element_get_static_pad (parser, "sink"));
 -
 -  return pipeline;
 -}
 -
 -static GstElement *
 -make_vorbis_pipeline (const gchar * location)
 -{
 -  GstElement *pipeline, *audio_bin;
 -  GstElement *src, *demux, *decoder, *convert, *audiosink;
 -  GstPad *pad, *seekable;
 -
 -  pipeline = gst_pipeline_new ("app");
 -
 -  src = gst_element_factory_make_or_warn (SOURCE, "src");
 -  demux = gst_element_factory_make_or_warn ("oggdemux", "demux");
 -  decoder = gst_element_factory_make_or_warn ("vorbisdec", "decoder");
 -  convert = gst_element_factory_make_or_warn ("audioconvert", "convert");
 -  audiosink = gst_element_factory_make_or_warn (opt_audiosink_str, "sink");
 -  g_object_set (G_OBJECT (audiosink), "sync", TRUE, NULL);
 -
 -  g_object_set (G_OBJECT (src), "location", location, NULL);
 -
 -  audio_bin = gst_bin_new ("a_decoder_bin");
 -
 -  gst_bin_add (GST_BIN (pipeline), src);
 -  gst_bin_add (GST_BIN (pipeline), demux);
 -  gst_bin_add (GST_BIN (audio_bin), decoder);
 -  gst_bin_add (GST_BIN (audio_bin), convert);
 -  gst_bin_add (GST_BIN (audio_bin), audiosink);
 -  gst_bin_add (GST_BIN (pipeline), audio_bin);
 -
 -  gst_element_link (src, demux);
 -  gst_element_link (decoder, convert);
 -  gst_element_link (convert, audiosink);
 -
 -  pad = gst_element_get_static_pad (decoder, "sink");
 -  gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
 -  gst_object_unref (pad);
 -
 -  setup_dynamic_link (demux, NULL, gst_element_get_static_pad (audio_bin,
 -          "sink"), NULL);
 -
 -  seekable = gst_element_get_static_pad (decoder, "src");
 -  seekable_pads = g_list_prepend (seekable_pads, seekable);
 -  rate_pads = g_list_prepend (rate_pads, seekable);
 -  rate_pads =
 -      g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink"));
 -
 -  return pipeline;
 -}
 -
 -static GstElement *
 -make_theora_pipeline (const gchar * location)
 -{
 -  GstElement *pipeline, *video_bin;
 -  GstElement *src, *demux, *decoder, *convert, *videosink;
 -  GstPad *pad, *seekable;
 -
 -  pipeline = gst_pipeline_new ("app");
 -
 -  src = gst_element_factory_make_or_warn (SOURCE, "src");
 -  demux = gst_element_factory_make_or_warn ("oggdemux", "demux");
 -  decoder = gst_element_factory_make_or_warn ("theoradec", "decoder");
 -  convert = gst_element_factory_make_or_warn ("ffmpegcolorspace", "convert");
 -  videosink = gst_element_factory_make_or_warn (opt_videosink_str, "sink");
 -
 -  g_object_set (G_OBJECT (src), "location", location, NULL);
 -
 -  video_bin = gst_bin_new ("v_decoder_bin");
 -
 -  gst_bin_add (GST_BIN (pipeline), src);
 -  gst_bin_add (GST_BIN (pipeline), demux);
 -  gst_bin_add (GST_BIN (video_bin), decoder);
 -  gst_bin_add (GST_BIN (video_bin), convert);
 -  gst_bin_add (GST_BIN (video_bin), videosink);
 -  gst_bin_add (GST_BIN (pipeline), video_bin);
 -
 -  gst_element_link (src, demux);
 -  gst_element_link (decoder, convert);
 -  gst_element_link (convert, videosink);
 -
 -  pad = gst_element_get_static_pad (decoder, "sink");
 -  gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
 -  gst_object_unref (pad);
 -
 -  setup_dynamic_link (demux, NULL, gst_element_get_static_pad (video_bin,
 -          "sink"), NULL);
 -
 -  seekable = gst_element_get_static_pad (decoder, "src");
 -  seekable_pads = g_list_prepend (seekable_pads, seekable);
 -  rate_pads = g_list_prepend (rate_pads, seekable);
 -  rate_pads =
 -      g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink"));
 -
 -  return pipeline;
 -}
 -
 -static GstElement *
 -make_vorbis_theora_pipeline (const gchar * location)
 -{
 -  GstElement *pipeline, *audio_bin, *video_bin;
 -  GstElement *src, *demux, *a_decoder, *a_convert, *v_decoder, *v_convert;
 -  GstElement *audiosink, *videosink;
 -  GstElement *a_queue, *v_queue, *v_scale;
 -  GstPad *seekable;
 -  GstPad *pad;
 -
 -  pipeline = gst_pipeline_new ("app");
 -
 -  src = gst_element_factory_make_or_warn (SOURCE, "src");
 -  g_object_set (G_OBJECT (src), "location", location, NULL);
 -
 -  demux = gst_element_factory_make_or_warn ("oggdemux", "demux");
 -
 -  gst_bin_add (GST_BIN (pipeline), src);
 -  gst_bin_add (GST_BIN (pipeline), demux);
 -  gst_element_link (src, demux);
 -
 -  audio_bin = gst_bin_new ("a_decoder_bin");
 -  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
 -  a_decoder = gst_element_factory_make_or_warn ("vorbisdec", "a_dec");
 -  a_convert = gst_element_factory_make_or_warn ("audioconvert", "a_convert");
 -  audiosink = gst_element_factory_make_or_warn (opt_audiosink_str, "a_sink");
 -
 -  gst_bin_add (GST_BIN (pipeline), audio_bin);
 -
 -  gst_bin_add (GST_BIN (audio_bin), a_queue);
 -  gst_bin_add (GST_BIN (audio_bin), a_decoder);
 -  gst_bin_add (GST_BIN (audio_bin), a_convert);
 -  gst_bin_add (GST_BIN (audio_bin), audiosink);
 -
 -  gst_element_link (a_queue, a_decoder);
 -  gst_element_link (a_decoder, a_convert);
 -  gst_element_link (a_convert, audiosink);
 -
 -  pad = gst_element_get_static_pad (a_queue, "sink");
 -  gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
 -  gst_object_unref (pad);
 -
 -  setup_dynamic_link (demux, NULL, gst_element_get_static_pad (audio_bin,
 -          "sink"), NULL);
 -
 -  video_bin = gst_bin_new ("v_decoder_bin");
 -  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
 -  v_decoder = gst_element_factory_make_or_warn ("theoradec", "v_dec");
 -  v_convert =
 -      gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_convert");
 -  v_scale = gst_element_factory_make_or_warn ("videoscale", "v_scale");
 -  videosink = gst_element_factory_make_or_warn (opt_videosink_str, "v_sink");
 -
 -  gst_bin_add (GST_BIN (pipeline), video_bin);
 -
 -  gst_bin_add (GST_BIN (video_bin), v_queue);
 -  gst_bin_add (GST_BIN (video_bin), v_decoder);
 -  gst_bin_add (GST_BIN (video_bin), v_convert);
 -  gst_bin_add (GST_BIN (video_bin), v_scale);
 -  gst_bin_add (GST_BIN (video_bin), videosink);
 -
 -  gst_element_link_many (v_queue, v_decoder, v_convert, v_scale, videosink,
 -      NULL);
 -
 -  pad = gst_element_get_static_pad (v_queue, "sink");
 -  gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
 -  gst_object_unref (pad);
 -
 -  setup_dynamic_link (demux, NULL, gst_element_get_static_pad (video_bin,
 -          "sink"), NULL);
 -
 -  seekable = gst_element_get_static_pad (a_decoder, "src");
 -  seekable_pads = g_list_prepend (seekable_pads, seekable);
 -  rate_pads = g_list_prepend (rate_pads, seekable);
 -  rate_pads =
 -      g_list_prepend (rate_pads, gst_element_get_static_pad (a_decoder,
 -          "sink"));
 -
 -  return pipeline;
 -}
 -
 -static GstElement *
 -make_avi_msmpeg4v3_mp3_pipeline (const gchar * location)
 -{
 -  GstElement *pipeline, *audio_bin, *video_bin;
 -  GstElement *src, *demux, *a_decoder, *a_convert, *v_decoder, *v_convert;
 -  GstElement *audiosink, *videosink;
 -  GstElement *a_queue, *v_queue;
 -  GstPad *seekable, *pad;
 -
 -  pipeline = gst_pipeline_new ("app");
 -
 -  src = gst_element_factory_make_or_warn (SOURCE, "src");
 -  g_object_set (G_OBJECT (src), "location", location, NULL);
 -
 -  demux = gst_element_factory_make_or_warn ("avidemux", "demux");
 -
 -  gst_bin_add (GST_BIN (pipeline), src);
 -  gst_bin_add (GST_BIN (pipeline), demux);
 -  gst_element_link (src, demux);
 -
 -  audio_bin = gst_bin_new ("a_decoder_bin");
 -  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
 -  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
 -  a_convert = gst_element_factory_make_or_warn ("audioconvert", "a_convert");
 -  audiosink = gst_element_factory_make_or_warn (opt_audiosink_str, "a_sink");
 -
 -  gst_bin_add (GST_BIN (audio_bin), a_queue);
 -  gst_bin_add (GST_BIN (audio_bin), a_decoder);
 -  gst_bin_add (GST_BIN (audio_bin), a_convert);
 -  gst_bin_add (GST_BIN (audio_bin), audiosink);
 -
 -  gst_element_link (a_queue, a_decoder);
 -  gst_element_link (a_decoder, a_convert);
 -  gst_element_link (a_convert, audiosink);
 -
 -  gst_bin_add (GST_BIN (pipeline), audio_bin);
 -
 -  pad = gst_element_get_static_pad (a_queue, "sink");
 -  gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
 -  gst_object_unref (pad);
 -
 -  setup_dynamic_link (demux, NULL, gst_element_get_static_pad (audio_bin,
 -          "sink"), NULL);
 -
 -  video_bin = gst_bin_new ("v_decoder_bin");
 -  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
 -  v_decoder = gst_element_factory_make_or_warn ("ffdec_msmpeg4", "v_dec");
 -  v_convert =
 -      gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_convert");
 -  videosink = gst_element_factory_make_or_warn (opt_videosink_str, "v_sink");
 -
 -  gst_bin_add (GST_BIN (video_bin), v_queue);
 -  gst_bin_add (GST_BIN (video_bin), v_decoder);
 -  gst_bin_add (GST_BIN (video_bin), v_convert);
 -  gst_bin_add (GST_BIN (video_bin), videosink);
 -
 -  gst_element_link_many (v_queue, v_decoder, v_convert, videosink, NULL);
 -
 -  gst_bin_add (GST_BIN (pipeline), video_bin);
 -
 -  pad = gst_element_get_static_pad (v_queue, "sink");
 -  gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
 -  gst_object_unref (pad);
 -
 -  setup_dynamic_link (demux, NULL, gst_element_get_static_pad (video_bin,
 -          "sink"), NULL);
 -
 -  seekable = gst_element_get_static_pad (a_decoder, "src");
 -  seekable_pads = g_list_prepend (seekable_pads, seekable);
 -  rate_pads = g_list_prepend (rate_pads, seekable);
 -  rate_pads =
 -      g_list_prepend (rate_pads, gst_element_get_static_pad (a_decoder,
 -          "sink"));
 -
 -  return pipeline;
 -}
 -
 -static GstElement *
 -make_mp3_pipeline (const gchar * location)
 -{
 -  GstElement *pipeline;
 -  GstElement *src, *parser, *decoder, *audiosink, *queue;
 -  GstPad *seekable;
 -
 -  pipeline = gst_pipeline_new ("app");
 -
 -  src = gst_element_factory_make_or_warn (SOURCE, "src");
 -  parser = gst_element_factory_make_or_warn ("mp3parse", "parse");
 -  decoder = gst_element_factory_make_or_warn ("mad", "dec");
 -  queue = gst_element_factory_make_or_warn ("queue", "queue");
 -  audiosink = gst_element_factory_make_or_warn (opt_audiosink_str, "sink");
 -
 -  seekable_elements = g_list_prepend (seekable_elements, audiosink);
 -
 -  g_object_set (G_OBJECT (src), "location", location, NULL);
 -  //g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL);
 -
 -  gst_bin_add (GST_BIN (pipeline), src);
 -  gst_bin_add (GST_BIN (pipeline), parser);
 -  gst_bin_add (GST_BIN (pipeline), decoder);
 -  gst_bin_add (GST_BIN (pipeline), queue);
 -  gst_bin_add (GST_BIN (pipeline), audiosink);
 -
 -  gst_element_link (src, parser);
 -  gst_element_link (parser, decoder);
 -  gst_element_link (decoder, queue);
 -  gst_element_link (queue, audiosink);
 -
 -  seekable = gst_element_get_static_pad (queue, "src");
 -  seekable_pads = g_list_prepend (seekable_pads, seekable);
 -  rate_pads = g_list_prepend (rate_pads, seekable);
 -  rate_pads =
 -      g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink"));
 -
 -  return pipeline;
 -}
 -
 -static GstElement *
 -make_avi_pipeline (const gchar * location)
 -{
 -  GstElement *pipeline, *audio_bin, *video_bin;
 -  GstElement *src, *demux, *a_decoder, *v_decoder, *audiosink, *videosink;
 -  GstElement *a_queue = NULL, *v_queue = NULL;
 -  GstPad *seekable;
 -
 -  pipeline = gst_pipeline_new ("app");
 -
 -  src = gst_element_factory_make_or_warn (SOURCE, "src");
 -  g_object_set (G_OBJECT (src), "location", location, NULL);
 -
 -  demux = gst_element_factory_make_or_warn ("avidemux", "demux");
 -  seekable_elements = g_list_prepend (seekable_elements, demux);
 -
 -  gst_bin_add (GST_BIN (pipeline), src);
 -  gst_bin_add (GST_BIN (pipeline), demux);
 -  gst_element_link (src, demux);
 -
 -  audio_bin = gst_bin_new ("a_decoder_bin");
 -  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
 -  audiosink = gst_element_factory_make_or_warn (opt_audiosink_str, "a_sink");
 -  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
 -  gst_element_link (a_decoder, a_queue);
 -  gst_element_link (a_queue, audiosink);
 -  gst_bin_add (GST_BIN (audio_bin), a_decoder);
 -  gst_bin_add (GST_BIN (audio_bin), a_queue);
 -  gst_bin_add (GST_BIN (audio_bin), audiosink);
 -  gst_element_set_state (audio_bin, GST_STATE_PAUSED);
 -
 -  setup_dynamic_link (demux, "audio_00", gst_element_get_static_pad (a_decoder,
 -          "sink"), audio_bin);
 -
 -  seekable = gst_element_get_static_pad (a_queue, "src");
 -  seekable_pads = g_list_prepend (seekable_pads, seekable);
 -  rate_pads = g_list_prepend (rate_pads, seekable);
 -  rate_pads =
 -      g_list_prepend (rate_pads, gst_element_get_static_pad (a_decoder,
 -          "sink"));
 -
 -  video_bin = gst_bin_new ("v_decoder_bin");
 -  v_decoder = gst_element_factory_make_or_warn ("ffmpegdecall", "v_dec");
 -  videosink = gst_element_factory_make_or_warn (opt_videosink_str, "v_sink");
 -  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
 -  gst_element_link (v_decoder, v_queue);
 -  gst_element_link (v_queue, videosink);
 -  gst_bin_add (GST_BIN (video_bin), v_decoder);
 -  gst_bin_add (GST_BIN (video_bin), v_queue);
 -  gst_bin_add (GST_BIN (video_bin), videosink);
 -
 -  gst_element_set_state (video_bin, GST_STATE_PAUSED);
 -
 -  setup_dynamic_link (demux, "video_00", gst_element_get_static_pad (v_decoder,
 -          "sink"), video_bin);
 -
 -  seekable = gst_element_get_static_pad (v_queue, "src");
 -  seekable_pads = g_list_prepend (seekable_pads, seekable);
 -  rate_pads = g_list_prepend (rate_pads, seekable);
 -  rate_pads =
 -      g_list_prepend (rate_pads, gst_element_get_static_pad (v_decoder,
 -          "sink"));
 -
 -  return pipeline;
 -}
 -
 -static GstElement *
 -make_mpeg_pipeline (const gchar * location)
 -{
 -  GstElement *pipeline, *audio_bin, *video_bin;
 -  GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter;
 -  GstElement *audiosink, *videosink;
 -  GstElement *a_queue, *v_queue;
 -  GstPad *seekable;
 -  GstPad *pad;
 -
 -  pipeline = gst_pipeline_new ("app");
 -
 -  src = gst_element_factory_make_or_warn (SOURCE, "src");
 -  g_object_set (G_OBJECT (src), "location", location, NULL);
 -
 -  //demux = gst_element_factory_make_or_warn ("mpegdemux", "demux");
 -  demux = gst_element_factory_make_or_warn ("flupsdemux", "demux");
 -
 -  gst_bin_add (GST_BIN (pipeline), src);
 -  gst_bin_add (GST_BIN (pipeline), demux);
 -  gst_element_link (src, demux);
 -
 -  audio_bin = gst_bin_new ("a_decoder_bin");
 -  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
 -  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
 -  audiosink = gst_element_factory_make_or_warn (opt_audiosink_str, "a_sink");
 -  gst_bin_add (GST_BIN (audio_bin), a_decoder);
 -  gst_bin_add (GST_BIN (audio_bin), a_queue);
 -  gst_bin_add (GST_BIN (audio_bin), audiosink);
 -
 -  gst_element_link (a_decoder, a_queue);
 -  gst_element_link (a_queue, audiosink);
 -
 -  gst_bin_add (GST_BIN (pipeline), audio_bin);
 -
 -  pad = gst_element_get_static_pad (a_decoder, "sink");
 -  gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
 -  gst_object_unref (pad);
 -
 -  setup_dynamic_link (demux, "audio_c0", gst_element_get_static_pad (audio_bin,
 -          "sink"), NULL);
 -
 -  video_bin = gst_bin_new ("v_decoder_bin");
 -  v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec");
 -  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
 -  v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter");
 -  videosink = gst_element_factory_make_or_warn (opt_videosink_str, "v_sink");
 -
 -  gst_bin_add (GST_BIN (video_bin), v_decoder);
 -  gst_bin_add (GST_BIN (video_bin), v_queue);
 -  gst_bin_add (GST_BIN (video_bin), v_filter);
 -  gst_bin_add (GST_BIN (video_bin), videosink);
 -
 -  gst_element_link (v_decoder, v_queue);
 -  gst_element_link (v_queue, v_filter);
 -  gst_element_link (v_filter, videosink);
 -
 -  gst_bin_add (GST_BIN (pipeline), video_bin);
 -
 -  pad = gst_element_get_static_pad (v_decoder, "sink");
 -  gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
 -  gst_object_unref (pad);
 -
 -  setup_dynamic_link (demux, "video_e0", gst_element_get_static_pad (video_bin,
 -          "sink"), NULL);
 -
 -  seekable = gst_element_get_static_pad (v_filter, "src");
 -  seekable_pads = g_list_prepend (seekable_pads, seekable);
 -  rate_pads = g_list_prepend (rate_pads, seekable);
 -  rate_pads =
 -      g_list_prepend (rate_pads, gst_element_get_static_pad (v_decoder,
 -          "sink"));
 -
 -  return pipeline;
 -}
 -
 -static GstElement *
 -make_mpegnt_pipeline (const gchar * location)
 -{
 -  GstElement *pipeline, *audio_bin, *video_bin;
 -  GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter;
 -  GstElement *audiosink, *videosink;
 -  GstElement *a_queue;
 -  GstPad *seekable;
 -
 -  pipeline = gst_pipeline_new ("app");
 -
 -  src = gst_element_factory_make_or_warn (SOURCE, "src");
 -  g_object_set (G_OBJECT (src), "location", location, NULL);
 -
 -  demux = gst_element_factory_make_or_warn ("mpegdemux", "demux");
 -  //g_object_set (G_OBJECT (demux), "sync", TRUE, NULL);
 -
 -  seekable_elements = g_list_prepend (seekable_elements, demux);
 -
 -  gst_bin_add (GST_BIN (pipeline), src);
 -  gst_bin_add (GST_BIN (pipeline), demux);
 -  gst_element_link (src, demux);
 -
 -  audio_bin = gst_bin_new ("a_decoder_bin");
 -  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
 -  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
 -  audiosink = gst_element_factory_make_or_warn (opt_audiosink_str, "a_sink");
 -  //g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL);
 -  g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
 -  gst_element_link (a_decoder, a_queue);
 -  gst_element_link (a_queue, audiosink);
 -  gst_bin_add (GST_BIN (audio_bin), a_decoder);
 -  gst_bin_add (GST_BIN (audio_bin), a_queue);
 -  gst_bin_add (GST_BIN (audio_bin), audiosink);
 -
 -  setup_dynamic_link (demux, "audio_00", gst_element_get_static_pad (a_decoder,
 -          "sink"), audio_bin);
 -
 -  seekable = gst_element_get_static_pad (a_queue, "src");
 -  seekable_pads = g_list_prepend (seekable_pads, seekable);
 -  rate_pads = g_list_prepend (rate_pads, seekable);
 -  rate_pads =
 -      g_list_prepend (rate_pads, gst_element_get_static_pad (a_decoder,
 -          "sink"));
 -
 -  video_bin = gst_bin_new ("v_decoder_bin");
 -  v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec");
 -  v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter");
 -  videosink = gst_element_factory_make_or_warn (opt_videosink_str, "v_sink");
 -  gst_element_link_many (v_decoder, v_filter, videosink, NULL);
 -
 -  gst_bin_add_many (GST_BIN (video_bin), v_decoder, v_filter, videosink, NULL);
 -
 -  setup_dynamic_link (demux, "video_00", gst_element_get_static_pad (v_decoder,
 -          "sink"), video_bin);
 -
 -  seekable = gst_element_get_static_pad (v_decoder, "src");
 -  seekable_pads = g_list_prepend (seekable_pads, seekable);
 -  rate_pads = g_list_prepend (rate_pads, seekable);
 -  rate_pads =
 -      g_list_prepend (rate_pads, gst_element_get_static_pad (v_decoder,
 -          "sink"));
 -
 -  return pipeline;
 -}
 -
 -static void
  playerbin_set_uri (GstElement * player, const gchar * location)
  {
    gchar *uri;
  }
  
  static GstElement *
 -construct_playerbin (const gchar * name, const gchar * location)
 +construct_playbin (const gchar * name, const gchar * location)
  {
    GstElement *player;
    GstElement *avsink;
  
    seekable_elements = g_list_prepend (seekable_elements, player);
  
 -  /* force element seeking on this pipeline */
 -  elem_seek = TRUE;
 -
    avsink = gst_element_factory_make_or_warn (opt_audiosink_str, "a_sink");
    if (avsink)
      g_object_set (player, "audio-sink", avsink, NULL);
  }
  
  static GstElement *
 -make_playerbin_pipeline (const gchar * location)
 -{
 -  return construct_playerbin ("playbin", location);
 -}
 -
 -static GstElement *
 -make_playerbin2_pipeline (const gchar * location)
 +make_playbin_pipeline (const gchar * location)
  {
 -  GstElement *pipeline = construct_playerbin ("playbin2", location);
 +  GstElement *pipeline = construct_playbin ("playbin", location);
  
 -  /* FIXME: this is not triggered, playbin2 is not forwarding it from the sink */
 +  /* FIXME: this is not triggered, playbin is not forwarding it from the sink */
    g_signal_connect (pipeline, "notify::volume", G_CALLBACK (volume_notify_cb),
        NULL);
    return pipeline;
@@@ -226,6 -976,8 +226,6 @@@ make_parselaunch_pipeline (const gchar 
  
    seekable_elements = g_list_prepend (seekable_elements, pipeline);
  
 -  elem_seek = TRUE;
 -
    return pipeline;
  }
  #endif
@@@ -238,10 -990,25 +238,10 @@@ typedef struc
  Pipeline;
  
  static Pipeline pipelines[] = {
 -  {"mp3", make_mp3_pipeline},
 -  {"avi", make_avi_pipeline},
 -  {"mpeg1", make_mpeg_pipeline},
 -  {"mpegparse", make_parse_pipeline},
 -  {"vorbis", make_vorbis_pipeline},
 -  {"theora", make_theora_pipeline},
 -  {"ogg/v/t", make_vorbis_theora_pipeline},
 -  {"avi/msmpeg4v3/mp3", make_avi_msmpeg4v3_mp3_pipeline},
 -  {"sid", make_sid_pipeline},
 -  {"flac", make_flac_pipeline},
 -  {"wav", make_wav_pipeline},
 -  {"mod", make_mod_pipeline},
 -  {"dv", make_dv_pipeline},
 -  {"mpeg1nothreads", make_mpegnt_pipeline},
 -  {"playerbin", make_playerbin_pipeline},
 +  {"playbin", make_playbin_pipeline},
  #ifndef GST_DISABLE_PARSE
    {"parse-launch", make_parselaunch_pipeline},
  #endif
 -  {"playerbin2", make_playerbin2_pipeline},
    {NULL, NULL},
  };
  
@@@ -287,6 -1054,37 +287,6 @@@ static seek_format seek_formats[] = 
  };
  
  G_GNUC_UNUSED static void
 -query_rates (void)
 -{
 -  GList *walk = rate_pads;
 -
 -  while (walk) {
 -    GstPad *pad = GST_PAD (walk->data);
 -    gint i = 0;
 -
 -    g_print ("rate/sec  %8.8s: ", GST_PAD_NAME (pad));
 -    while (seek_formats[i].name) {
 -      gint64 value;
 -      GstFormat format;
 -
 -      format = seek_formats[i].format;
 -
 -      if (gst_pad_query_convert (pad, GST_FORMAT_TIME, GST_SECOND, &format,
 -              &value)) {
 -        g_print ("%s %13" G_GINT64_FORMAT " | ", seek_formats[i].name, value);
 -      } else {
 -        g_print ("%s %13.13s | ", seek_formats[i].name, "*NA*");
 -      }
 -
 -      i++;
 -    }
 -    g_print (" %s:%s\n", GST_DEBUG_PAD_NAME (pad));
 -
 -    walk = g_list_next (walk);
 -  }
 -}
 -
 -G_GNUC_UNUSED static void
  query_positions_elems (void)
  {
    GList *walk = seekable_elements;
  
        format = seek_formats[i].format;
  
 -      if (gst_element_query_position (element, &format, &position) &&
 -          gst_element_query_duration (element, &format, &total)) {
 +      if (gst_element_query_position (element, format, &position) &&
 +          gst_element_query_duration (element, format, &total)) {
          g_print ("%s %13" G_GINT64_FORMAT " / %13" G_GINT64_FORMAT " | ",
              seek_formats[i].name, position, total);
        } else {
    }
  }
  
 -G_GNUC_UNUSED static void
 -query_positions_pads (void)
 -{
 -  GList *walk = seekable_pads;
 -
 -  while (walk) {
 -    GstPad *pad = GST_PAD (walk->data);
 -    gint i = 0;
 -
 -    g_print ("positions %8.8s: ", GST_PAD_NAME (pad));
 -    while (seek_formats[i].name) {
 -      GstFormat format;
 -      gint64 position, total;
 -
 -      format = seek_formats[i].format;
 -
 -      if (gst_pad_query_position (pad, &format, &position) &&
 -          gst_pad_query_duration (pad, &format, &total)) {
 -        g_print ("%s %13" G_GINT64_FORMAT " / %13" G_GINT64_FORMAT " | ",
 -            seek_formats[i].name, position, total);
 -      } else {
 -        g_print ("%s %13.13s / %13.13s | ", seek_formats[i].name, "*NA*",
 -            "*NA*");
 -      }
 -
 -      i++;
 -    }
 -    g_print (" %s:%s\n", GST_DEBUG_PAD_NAME (pad));
 -
 -    walk = g_list_next (walk);
 -  }
 -}
 -
  static gboolean start_seek (GtkWidget * widget, GdkEventButton * event,
      gpointer user_data);
  static gboolean stop_seek (GtkWidget * widget, GdkEventButton * event,
@@@ -345,42 -1176,44 +345,42 @@@ set_scale (gdouble value
  static gboolean
  update_fill (gpointer data)
  {
 -  if (elem_seek) {
 -    if (seekable_elements) {
 -      GstElement *element = GST_ELEMENT (seekable_elements->data);
 -      GstQuery *query;
 -
 -      query = gst_query_new_buffering (GST_FORMAT_PERCENT);
 -      if (gst_element_query (element, query)) {
 -        gint64 start, stop, buffering_total;
 -        GstFormat format;
 -        gdouble fill;
 -        gboolean busy;
 -        gint percent;
 -        GstBufferingMode mode;
 -        gint avg_in, avg_out;
 -        gint64 buffering_left;
 -
 -        gst_query_parse_buffering_percent (query, &busy, &percent);
 -        gst_query_parse_buffering_range (query, &format, &start, &stop,
 -            &buffering_total);
 -        gst_query_parse_buffering_stats (query, &mode, &avg_in, &avg_out,
 -            &buffering_left);
 -
 -        /* note that we could start the playback when buffering_left < remaining
 -         * playback time */
 -        GST_DEBUG ("buffering total %" G_GINT64_FORMAT " ms, left %"
 -            G_GINT64_FORMAT " ms", buffering_total, buffering_left);
 -        GST_DEBUG ("start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT,
 -            start, stop);
 -
 -        if (stop != -1)
 -          fill = N_GRAD * stop / GST_FORMAT_PERCENT_MAX;
 -        else
 -          fill = N_GRAD;
 -
 -        gtk_range_set_fill_level (GTK_RANGE (hscale), fill);
 -      }
 -      gst_query_unref (query);
 +  if (seekable_elements) {
 +    GstElement *element = GST_ELEMENT (seekable_elements->data);
 +    GstQuery *query;
 +
 +    query = gst_query_new_buffering (GST_FORMAT_PERCENT);
 +    if (gst_element_query (element, query)) {
 +      gint64 start, stop, buffering_total;
 +      GstFormat format;
 +      gdouble fill;
 +      gboolean busy;
 +      gint percent;
 +      GstBufferingMode mode;
 +      gint avg_in, avg_out;
 +      gint64 buffering_left;
 +
 +      gst_query_parse_buffering_percent (query, &busy, &percent);
 +      gst_query_parse_buffering_range (query, &format, &start, &stop,
 +          &buffering_total);
 +      gst_query_parse_buffering_stats (query, &mode, &avg_in, &avg_out,
 +          &buffering_left);
 +
 +      /* note that we could start the playback when buffering_left < remaining
 +       * playback time */
 +      GST_DEBUG ("buffering total %" G_GINT64_FORMAT " ms, left %"
 +          G_GINT64_FORMAT " ms", buffering_total, buffering_left);
 +      GST_DEBUG ("start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT,
 +          start, stop);
 +
 +      if (stop != -1)
 +        fill = N_GRAD * stop / GST_FORMAT_PERCENT_MAX;
 +      else
 +        fill = N_GRAD;
 +
 +      gtk_range_set_fill_level (GTK_RANGE (hscale), fill);
      }
 +    gst_query_unref (query);
    }
    return TRUE;
  }
  static gboolean
  update_scale (gpointer data)
  {
 -  GstFormat format = GST_FORMAT_TIME;
 -
 -  //position = 0;
 -  //duration = 0;
 +  if (seekable_elements) {
 +    GstElement *element = GST_ELEMENT (seekable_elements->data);
  
 -  if (elem_seek) {
 -    if (seekable_elements) {
 -      GstElement *element = GST_ELEMENT (seekable_elements->data);
 -
 -      gst_element_query_position (element, &format, &position);
 -      gst_element_query_duration (element, &format, &duration);
 -    }
 -  } else {
 -    if (seekable_pads) {
 -      GstPad *pad = GST_PAD (seekable_pads->data);
 -
 -      gst_pad_query_position (pad, &format, &position);
 -      gst_pad_query_duration (pad, &format, &duration);
 -    }
 +    gst_element_query_position (element, GST_FORMAT_TIME, &position);
 +    gst_element_query_duration (element, GST_FORMAT_TIME, &duration);
    }
  
    if (stats) {
 -    if (elem_seek) {
 -      query_positions_elems ();
 -    } else {
 -      query_positions_pads ();
 -    }
 -    query_rates ();
 +    query_positions_elems ();
    }
  
    if (position >= duration)
@@@ -433,17 -1285,33 +433,17 @@@ static gboolea
  send_event (GstEvent * event)
  {
    gboolean res = FALSE;
 +  GList *walk = seekable_elements;
  
 -  if (!elem_seek) {
 -    GList *walk = seekable_pads;
 -
 -    while (walk) {
 -      GstPad *seekable = GST_PAD (walk->data);
 -
 -      GST_DEBUG ("send event on pad %s:%s", GST_DEBUG_PAD_NAME (seekable));
 -
 -      gst_event_ref (event);
 -      res = gst_pad_send_event (seekable, event);
 -
 -      walk = g_list_next (walk);
 -    }
 -  } else {
 -    GList *walk = seekable_elements;
 -
 -    while (walk) {
 -      GstElement *seekable = GST_ELEMENT (walk->data);
 +  while (walk) {
 +    GstElement *seekable = GST_ELEMENT (walk->data);
  
 -      GST_DEBUG ("send event on element %s", GST_ELEMENT_NAME (seekable));
 +    GST_DEBUG ("send event on element %s", GST_ELEMENT_NAME (seekable));
  
 -      gst_event_ref (event);
 -      res = gst_element_send_event (seekable, event);
 +    gst_event_ref (event);
 +    res = gst_element_send_event (seekable, event);
  
 -      walk = g_list_next (walk);
 -    }
 +    walk = g_list_next (walk);
    }
    gst_event_unref (event);
    return res;
@@@ -721,6 -1589,10 +721,6 @@@ stop_cb (GtkButton * button, gpointer d
  
        g_list_free (seekable_elements);
        seekable_elements = NULL;
 -      g_list_free (seekable_pads);
 -      seekable_pads = NULL;
 -      g_list_free (rate_pads);
 -      rate_pads = NULL;
  
        pipeline = pipelines[pipeline_type].func (pipeline_spec);
        g_assert (pipeline);
@@@ -1126,9 -1998,6 +1126,9 @@@ volume_notify_cb (GstElement * pipeline
  {
    gdouble cur_volume, new_volume;
  
 +  if (volume_spinbutton == NULL)
 +    return;
 +
    g_object_get (pipeline, "volume", &new_volume, NULL);
    cur_volume = gtk_spin_button_get_value (GTK_SPIN_BUTTON (volume_spinbutton));
    if (fabs (cur_volume - new_volume) > 0.001) {
  static void
  shot_cb (GtkButton * button, gpointer data)
  {
 -  GstBuffer *buffer;
 +  GstSample *sample = NULL;
    GstCaps *caps;
  
 +  GST_DEBUG ("taking snapshot");
 +
    /* convert to our desired format (RGB24) */
 -  caps = gst_caps_new_simple ("video/x-raw-rgb",
 -      "bpp", G_TYPE_INT, 24, "depth", G_TYPE_INT, 24,
 +  caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING, "RGB",
        /* Note: we don't ask for a specific width/height here, so that
         * videoscale can adjust dimensions from a non-1/1 pixel aspect
         * ratio to a 1/1 pixel-aspect-ratio */
 -      "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
 -      "endianness", G_TYPE_INT, G_BIG_ENDIAN,
 -      "red_mask", G_TYPE_INT, 0xff0000,
 -      "green_mask", G_TYPE_INT, 0x00ff00,
 -      "blue_mask", G_TYPE_INT, 0x0000ff, NULL);
 -
 -  /* convert the latest frame to the requested format */
 -  g_signal_emit_by_name (pipeline, "convert-frame", caps, &buffer);
 +      "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);
 +
 +  /* convert the latest sample to the requested format */
 +  g_signal_emit_by_name (pipeline, "convert-sample", caps, &sample);
    gst_caps_unref (caps);
  
 -  if (buffer) {
 +  if (sample) {
 +    GstBuffer *buffer;
      GstCaps *caps;
      GstStructure *s;
      gboolean res;
      gint width, height;
      GdkPixbuf *pixbuf;
      GError *error = NULL;
 +    guint8 *data;
 +    gsize size;
  
      /* get the snapshot buffer format now. We set the caps on the appsink so
       * that it can only be an rgb buffer. The only thing we have not specified
       * on the caps is the height, which is dependant on the pixel-aspect-ratio
       * of the source material */
 -    caps = GST_BUFFER_CAPS (buffer);
 +    caps = gst_sample_get_caps (sample);
      if (!caps) {
        g_warning ("could not get snapshot format\n");
        goto done;
  
      /* create pixmap from buffer and save, gstreamer video buffers have a stride
       * that is rounded up to the nearest multiple of 4 */
 -    pixbuf = gdk_pixbuf_new_from_data (GST_BUFFER_DATA (buffer),
 +    buffer = gst_sample_get_buffer (sample);
 +    data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
 +    pixbuf = gdk_pixbuf_new_from_data (data,
          GDK_COLORSPACE_RGB, FALSE, 8, width, height,
          GST_ROUND_UP_4 (width * 3), NULL, NULL);
  
      /* save the pixbuf */
      gdk_pixbuf_save (pixbuf, "snapshot.png", "png", &error, NULL);
 +    gst_buffer_unmap (buffer, data, size);
  
    done:
 -    gst_buffer_unref (buffer);
 +    gst_sample_unref (sample);
    }
  }
  
@@@ -1592,7 -2458,7 +1592,7 @@@ msg_clock_lost (GstBus * bus, GstMessag
  
  static gulong embed_xid = 0;
  
 -/* We set the xid here in response to the prepare-xwindow-id message via a
 +/* We set the xid here in response to the prepare-window-handle message via a
   * bus sync handler because we don't know the actual videosink used from the
   * start (as we don't know the pipeline, or bin elements such as autovideosink
   * or gconfvideosink may be used which create the actual videosink only once
  static GstBusSyncReply
  bus_sync_handler (GstBus * bus, GstMessage * message, GstPipeline * data)
  {
 -  if ((GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT) &&
 -      gst_structure_has_name (message->structure, "prepare-xwindow-id")) {
 -    GstElement *element = GST_ELEMENT (GST_MESSAGE_SRC (message));
 +  GstElement *element;
  
 -    g_print ("got prepare-xwindow-id, setting XID %lu\n", embed_xid);
 +  if (!gst_is_video_overlay_prepare_window_handle_message (message))
 +    return GST_BUS_PASS;
  
 -    if (g_object_class_find_property (G_OBJECT_GET_CLASS (element),
 -            "force-aspect-ratio")) {
 -      g_object_set (element, "force-aspect-ratio", TRUE, NULL);
 -    }
 +  element = GST_ELEMENT (GST_MESSAGE_SRC (message));
  
 -    /* Should have been initialised from main thread before (can't use
 -     * GDK_WINDOW_XID here with Gtk+ >= 2.18, because the sync handler will
 -     * be called from a streaming thread and GDK_WINDOW_XID maps to more than
 -     * a simple structure lookup with Gtk+ >= 2.18, where 'more' is stuff that
 -     * shouldn't be done from a non-GUI thread without explicit locking).  */
 -    g_assert (embed_xid != 0);
 +  g_print ("got prepare-window-handle, setting XID %lu\n", embed_xid);
  
 -    gst_x_overlay_set_window_handle (GST_X_OVERLAY (element), embed_xid);
 +  if (g_object_class_find_property (G_OBJECT_GET_CLASS (element),
 +          "force-aspect-ratio")) {
 +    g_object_set (element, "force-aspect-ratio", TRUE, NULL);
    }
 +
 +  /* Should have been initialised from main thread before (can't use
 +   * GDK_WINDOW_XID here with Gtk+ >= 2.18, because the sync handler will
 +   * be called from a streaming thread and GDK_WINDOW_XID maps to more than
 +   * a simple structure lookup with Gtk+ >= 2.18, where 'more' is stuff that
 +   * shouldn't be done from a non-GUI thread without explicit locking).  */
 +  g_assert (embed_xid != 0);
 +
 +  gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (element), embed_xid);
    return GST_BUS_PASS;
  }
  #endif
@@@ -1690,7 -2554,7 +1690,7 @@@ connect_bus_signals (GstElement * pipel
    GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
  
  #if defined (GDK_WINDOWING_X11) || defined (GDK_WINDOWING_WIN32)
 -  /* handle prepare-xwindow-id element message synchronously */
 +  /* handle prepare-window-handle element message synchronously */
    gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bus_sync_handler,
        pipeline);
  #endif
@@@ -1800,6 -2664,8 +1800,6 @@@ main (int argc, char **argv
          "audio sink to use (default: " DEFAULT_AUDIOSINK ")", NULL},
      {"stats", 's', 0, G_OPTION_ARG_NONE, &stats,
          "Show pad stats", NULL},
 -    {"elem", 'e', 0, G_OPTION_ARG_NONE, &elem_seek,
 -        "Seek on elements instead of pads", NULL},
      {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
          "Verbose properties", NULL},
      {"videosink", '\0', 0, G_OPTION_ARG_STRING, &opt_videosink_str,
    GOptionContext *ctx;
    GError *err = NULL;
  
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
    if (!g_thread_supported ())
      g_thread_init (NULL);
+ #endif
  
    ctx = g_option_context_new ("- test seeking in gsteamer");
    g_option_context_add_main_entries (ctx, options, NULL);
    g_signal_connect (hscale, "format_value", G_CALLBACK (format_value),
        pipeline);
  
 -  if (pipeline_type == 16) {
 +  if (pipeline_type == 0) {
      /* the playbin2 panel controls for the video/audio/subtitle tracks */
      panel = gtk_hbox_new (FALSE, 0);
      video_combo = gtk_combo_box_text_new ();
@@@ -31,7 -31,7 +31,7 @@@
  #include <gtk/gtk.h>
  
  #include <gst/gst.h>
 -#include <gst/interfaces/xoverlay.h>
 +#include <gst/video/videooverlay.h>
  #include <gst/interfaces/propertyprobe.h>
  
  static GtkWidget *video_window = NULL;
@@@ -172,8 -172,10 +172,10 @@@ main (int argc, char **argv
    GstPropertyProbe *probe;
    GValueArray *arr;
  
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
    if (!g_thread_supported ())
      g_thread_init (NULL);
+ #endif
  
    gst_init (&argc, &argv);
    gtk_init (&argc, &argv);
    g_assert (embed_xid != 0);
  
    /* we know what the video sink is in this case (xvimagesink), so we can
 -   * just set it directly here now (instead of waiting for a prepare-xwindow-id
 -   * element message in a sync bus handler and setting it there) */
 +   * just set it directly here now (instead of waiting for a
 +   * prepare-window-handle element message in a sync bus handler and setting
 +   * it there) */
    g_print ("setting XID %lu\n", embed_xid);
 -  gst_x_overlay_set_window_handle (GST_X_OVERLAY (sink), embed_xid);
 +  gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink), embed_xid);
  
    g_idle_add (start_pipeline, pipeline);
    gtk_main ();
@@@ -1,7 -1,7 +1,7 @@@
  /* GStreamer
   * Copyright (C) <2008> Stefan Kost <ensonic@users.sf.net>
   *
 - * test-xoverlay: test xoverlay custom event handling and subregions
 + * test-videooverlay: test videooverlay custom event handling and subregions
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Library General Public
  #include <gtk/gtk.h>
  
  #include <gst/gst.h>
 -#include <gst/interfaces/xoverlay.h>
 +#include <gst/video/videooverlay.h>
  #include <gst/video/gstvideosink.h>
  
  static struct
  {
    gint w, h;
 -  GstXOverlay *overlay;
 +  GstVideoOverlay *overlay;
    GtkWidget *widget;
    gdouble a, p;
    GstVideoRectangle rect;
@@@ -64,7 -64,7 +64,7 @@@ animate_render_rect (gpointer user_data
      r->h = anim_state.h / 2;
      r->y = (r->h - (r->h / 2)) + s * (r->h / 2);
  
 -    gst_x_overlay_set_render_rectangle (anim_state.overlay, r->x, r->y,
 +    gst_video_overlay_set_render_rectangle (anim_state.overlay, r->x, r->y,
          r->w, r->h);
      gtk_widget_queue_draw (anim_state.widget);
    }
@@@ -116,7 -116,7 +116,7 @@@ handle_draw_cb (GtkWidget * widget, cai
    if (verbose) {
      g_print ("draw(%p)\n", widget);
    }
 -  gst_x_overlay_expose (anim_state.overlay);
 +  gst_video_overlay_expose (anim_state.overlay);
    return FALSE;
  }
  
@@@ -144,8 -144,10 +144,10 @@@ main (gint argc, gchar ** argv
    gulong embed_xid = 0;
    gboolean force_aspect = FALSE, draw_borders = FALSE;
  
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
    if (!g_thread_supported ())
      g_thread_init (NULL);
+ #endif
  
    gst_init (&argc, &argv);
    gtk_init (&argc, &argv);
    }
  
    /* we know what the video sink is in this case (xvimagesink), so we can
 -   * just set it directly here now (instead of waiting for a prepare-xwindow-id
 -   * element message in a sync bus handler and setting it there) */
 -  gst_x_overlay_set_window_handle (GST_X_OVERLAY (sink), embed_xid);
 +   * just set it directly here now (instead of waiting for a
 +   * prepare-window-handle element message in a sync bus handler and setting
 +   * it there) */
 +  gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink), embed_xid);
  
 -  anim_state.overlay = GST_X_OVERLAY (sink);
 +  anim_state.overlay = GST_VIDEO_OVERLAY (sink);
    anim_state.widget = video_window;
    anim_state.w = 320;
    anim_state.h = 240;
diff --combined tools/gst-discoverer.c
@@@ -307,9 -307,7 +307,9 @@@ print_tag_each (GQuark field_id, const 
      ser = g_value_dup_string (value);
    else if (GST_VALUE_HOLDS_BUFFER (value)) {
      GstBuffer *buf = gst_value_get_buffer (value);
 -    ser = g_strdup_printf ("<GstBuffer [%d bytes]>", GST_BUFFER_SIZE (buf));
 +    ser =
 +        g_strdup_printf ("<GstBuffer [%" G_GSIZE_FORMAT " bytes]>",
 +        gst_buffer_get_size (buf));
    } else
      ser = gst_value_serialize (value);
  
@@@ -499,8 -497,10 +499,10 @@@ main (int argc, char **argv
    };
    GOptionContext *ctx;
  
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
    if (!g_thread_supported ())
      g_thread_init (NULL);
+ #endif
  
    ctx =
        g_option_context_new