Imported Upstream version 1.5.0.1+git20150513
diff --git a/INSTALL b/INSTALL
index b42a17a..2099840 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,48 +1,80 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
+Inc.
+
+   Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.  This file is offered as-is,
+without warranty of any kind.
+
 Basic Installation
 ==================
 
-   These are generic installation instructions.
+   Briefly, the shell command `./configure && make && make install'
+should configure, build, and install this package.  The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.  Some packages provide this
+`INSTALL' file but do not implement all of the features documented
+below.  The lack of an optional feature in a given package is not
+necessarily a bug.  More recommendations for GNU packages can be found
+in *note Makefile Conventions: (standards)Makefile Conventions.
 
    The `configure' shell script attempts to guess correct values for
 various system-dependent variables used during compilation.  It uses
 those values to create a `Makefile' in each directory of the package.
 It may also create one or more `.h' files containing system-dependent
 definitions.  Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, a file
-`config.cache' that saves the results of its tests to speed up
-reconfiguring, and a file `config.log' containing compiler output
-(useful mainly for debugging `configure').
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
 
    If you need to do unusual things to compile the package, please try
 to figure out how `configure' could check whether to do them, and mail
 diffs or instructions to the address given in the `README' so they can
-be considered for the next release.  If at some point `config.cache'
-contains results you don't want to keep, you may remove or edit it.
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
 
-   The file `configure.in' is used to create `configure' by a program
-called `autoconf'.  You only need `configure.in' if you want to change
-it or regenerate `configure' using a newer version of `autoconf'.
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
 
-The simplest way to compile this package is:
+   The simplest way to compile this package is:
 
   1. `cd' to the directory containing the package's source code and type
-     `./configure' to configure the package for your system.  If you're
-     using `csh' on an old version of System V, you might need to type
-     `sh ./configure' instead to prevent `csh' from trying to execute
-     `configure' itself.
+     `./configure' to configure the package for your system.
 
-     Running `configure' takes awhile.  While running, it prints some
-     messages telling which features it is checking for.
+     Running `configure' might take a while.  While running, it prints
+     some messages telling which features it is checking for.
 
   2. Type `make' to compile the package.
 
   3. Optionally, type `make check' to run any self-tests that come with
-     the package.
+     the package, generally using the just-built uninstalled binaries.
 
   4. Type `make install' to install the programs and any data files and
-     documentation.
+     documentation.  When installing into a prefix owned by root, it is
+     recommended that the package be configured and built as a regular
+     user, and only the `make install' phase executed with root
+     privileges.
 
-  5. You can remove the program binaries and object files from the
+  5. Optionally, type `make installcheck' to repeat any self-tests, but
+     this time using the binaries in their final installed location.
+     This target does not install anything.  Running this target as a
+     regular user, particularly if the prior `make install' required
+     root privileges, verifies that the installation completed
+     correctly.
+
+  6. You can remove the program binaries and object files from the
      source code directory by typing `make clean'.  To also remove the
      files that `configure' created (so you can compile the package for
      a different kind of computer), type `make distclean'.  There is
@@ -51,62 +83,119 @@
      all sorts of other programs in order to regenerate files that came
      with the distribution.
 
+  7. Often, you can also type `make uninstall' to remove the installed
+     files again.  In practice, not all packages have tested that
+     uninstallation works correctly, even though it is required by the
+     GNU Coding Standards.
+
+  8. Some packages, particularly those that use Automake, provide `make
+     distcheck', which can by used by developers to test that all other
+     targets like `make install' and `make uninstall' work correctly.
+     This target is generally not run by end users.
+
 Compilers and Options
 =====================
 
    Some systems require unusual options for compilation or linking that
-the `configure' script does not know about.  You can give `configure'
-initial values for variables by setting them in the environment.  Using
-a Bourne-compatible shell, you can do that on the command line like
-this:
-     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+the `configure' script does not know about.  Run `./configure --help'
+for details on some of the pertinent environment variables.
 
-Or on systems that have the `env' program, you can do it like this:
-     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
 
 Compiling For Multiple Architectures
 ====================================
 
    You can compile the package for more than one kind of computer at the
 same time, by placing the object files for each architecture in their
-own directory.  To do this, you must use a version of `make' that
-supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+own directory.  To do this, you can use GNU `make'.  `cd' to the
 directory where you want the object files and executables to go and run
 the `configure' script.  `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'.
+source code in the directory that `configure' is in and in `..'.  This
+is known as a "VPATH" build.
 
-   If you have to use a `make' that does not supports the `VPATH'
-variable, you have to compile the package for one architecture at a time
-in the source code directory.  After you have installed the package for
-one architecture, use `make distclean' before reconfiguring for another
-architecture.
+   With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory.  After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+   On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple `-arch' options to the
+compiler but only a single `-arch' option to the preprocessor.  Like
+this:
+
+     ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CPP="gcc -E" CXXCPP="g++ -E"
+
+   This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the `lipo' tool if you have problems.
 
 Installation Names
 ==================
 
-   By default, `make install' will install the package's files in
-`/usr/local/bin', `/usr/local/man', etc.  You can specify an
-installation prefix other than `/usr/local' by giving `configure' the
-option `--prefix=PATH'.
+   By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc.  You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX', where PREFIX must be an
+absolute file name.
 
    You can specify separate installation prefixes for
 architecture-specific files and architecture-independent files.  If you
-give `configure' the option `--exec-prefix=PATH', the package will use
-PATH as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix.
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
 
    In addition, if you use an unusual directory layout you can give
-options like `--bindir=PATH' to specify different values for particular
+options like `--bindir=DIR' to specify different values for particular
 kinds of files.  Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them.
+you can set and what kinds of files go in them.  In general, the
+default for these options is expressed in terms of `${prefix}', so that
+specifying just `--prefix' will affect all of the other directory
+specifications that were not explicitly provided.
+
+   The most portable way to affect installation locations is to pass the
+correct locations to `configure'; however, many packages provide one or
+both of the following shortcuts of passing variable assignments to the
+`make install' command line to change installation locations without
+having to reconfigure or recompile.
+
+   The first method involves providing an override variable for each
+affected directory.  For example, `make install
+prefix=/alternate/directory' will choose an alternate location for all
+directory configuration variables that were expressed in terms of
+`${prefix}'.  Any directories that were specified during `configure',
+but not in terms of `${prefix}', must each be overridden at install
+time for the entire installation to be relocated.  The approach of
+makefile variable overrides for each directory variable is required by
+the GNU Coding Standards, and ideally causes no recompilation.
+However, some platforms have known limitations with the semantics of
+shared libraries that end up requiring recompilation when using this
+method, particularly noticeable in packages that use GNU Libtool.
+
+   The second method involves providing the `DESTDIR' variable.  For
+example, `make install DESTDIR=/alternate/directory' will prepend
+`/alternate/directory' before all installation names.  The approach of
+`DESTDIR' overrides is not required by the GNU Coding Standards, and
+does not work on platforms that have drive letters.  On the other hand,
+it does better at avoiding recompilation issues, and works well even
+when some directory options were not specified in terms of `${prefix}'
+at `configure' time.
+
+Optional Features
+=================
 
    If the package supports it, you can cause programs to be installed
 with an extra prefix or suffix on their names by giving `configure' the
 option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
 
-Optional Features
-=================
-
    Some packages pay attention to `--enable-FEATURE' options to
 `configure', where FEATURE indicates an optional part of the package.
 They may also pay attention to `--with-PACKAGE' options, where PACKAGE
@@ -119,25 +208,80 @@
 you can use the `configure' options `--x-includes=DIR' and
 `--x-libraries=DIR' to specify their locations.
 
+   Some packages offer the ability to configure how verbose the
+execution of `make' will be.  For these packages, running `./configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with `make V=1'; while running `./configure
+--disable-silent-rules' sets the default to verbose, which can be
+overridden with `make V=0'.
+
+Particular systems
+==================
+
+   On HP-UX, the default C compiler is not ANSI C compatible.  If GNU
+CC is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+     ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+   HP-UX `make' updates targets which have the same time stamps as
+their prerequisites, which makes it generally unusable when shipped
+generated files such as `configure' are involved.  Use GNU `make'
+instead.
+
+   On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its `<wchar.h>' header file.  The option `-nodtk' can be used as
+a workaround.  If GNU CC is not installed, it is therefore recommended
+to try
+
+     ./configure CC="cc"
+
+and if that doesn't work, try
+
+     ./configure CC="cc -nodtk"
+
+   On Solaris, don't put `/usr/ucb' early in your `PATH'.  This
+directory contains several dysfunctional programs; working variants of
+these programs are available in `/usr/bin'.  So, if you need `/usr/ucb'
+in your `PATH', put it _after_ `/usr/bin'.
+
+   On Haiku, software installed for all users goes in `/boot/common',
+not `/usr/local'.  It is recommended to use the following options:
+
+     ./configure --prefix=/boot/common
+
 Specifying the System Type
 ==========================
 
-   There may be some features `configure' can not figure out
-automatically, but needs to determine by the type of host the package
-will run on.  Usually `configure' can figure that out, but if it prints
-a message saying it can not guess the host type, give it the
-`--host=TYPE' option.  TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name with three fields:
+   There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on.  Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
      CPU-COMPANY-SYSTEM
 
-See the file `config.sub' for the possible values of each field.  If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the host type.
+where SYSTEM can have one of these forms:
 
-   If you are building compiler tools for cross-compiling, you can also
-use the `--target=TYPE' option to select the type of system they will
-produce code for and the `--build=TYPE' option to select the type of
-system on which you are compiling the package.
+     OS
+     KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
 
 Sharing Defaults
 ================
@@ -150,19 +294,56 @@
 `CONFIG_SITE' environment variable to the location of the site script.
 A warning: not all `configure' scripts look for a site script.
 
-Operation Controls
+Defining Variables
 ==================
 
+   Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf limitation.  Until the limitation is lifted, you can use
+this workaround:
+
+     CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
    `configure' recognizes the following options to control how it
 operates.
 
-`--cache-file=FILE'
-     Use and save the results of the tests in FILE instead of
-     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
-     debugging `configure'.
-
 `--help'
-     Print a summary of the options to `configure', and exit.
+`-h'
+     Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+     Print a summary of the options unique to this package's
+     `configure', and exit.  The `short' variant lists options used
+     only in the top level, while the `recursive' variant lists options
+     also present in any nested packages.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
 
 `--quiet'
 `--silent'
@@ -175,8 +356,15 @@
      Look for the package's source code in directory DIR.  Usually
      `configure' can determine that directory automatically.
 
-`--version'
-     Print the version of Autoconf used to generate the `configure'
-     script, and exit.
+`--prefix=DIR'
+     Use DIR as the installation prefix.  *note Installation Names::
+     for more details, including other options available for fine-tuning
+     the installation locations.
 
-`configure' also accepts some other, not widely useful, options.
+`--no-create'
+`-n'
+     Run the configure checks, but stop before creating any output
+     files.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
diff --git a/autogen.sh b/autogen.sh
index a4e27b7..4e8ed7a 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -57,24 +57,13 @@
 
 printf "+ check for build tools"
 if test ! -z "$NOCHECK"; then echo ": skipped version checks"; else  echo; fi
-version_check "autoconf" "$AUTOCONF autoconf autoconf270 autoconf269 autoconf268 " \
+version_check "autoreconf" "autoreconf " \
               "ftp://ftp.gnu.org/pub/gnu/autoconf/" 2 68 || DIE=1
-version_check "automake" "$AUTOMAKE automake automake-1.11" \
-              "ftp://ftp.gnu.org/pub/gnu/automake/" 1 11 || DIE=1
-version_check "autopoint" "autopoint" \
-              "ftp://ftp.gnu.org/pub/gnu/gettext/" 0 17 || DIE=1
-version_check "libtoolize" "$LIBTOOLIZE libtoolize glibtoolize" \
-              "ftp://ftp.gnu.org/pub/gnu/libtool/" 2 2 6 || DIE=1
 version_check "pkg-config" "" \
               "http://www.freedesktop.org/software/pkgconfig" 0 8 0 || DIE=1
 
 die_check $DIE
 
-aclocal_check || DIE=1
-autoheader_check || DIE=1
-
-die_check $DIE
-
 # if no arguments specified then this will be printed
 if test -z "$*" && test -z "$NOCONFIGURE"; then
   echo "+ checking for autogen.sh options"
@@ -88,22 +77,13 @@
 
 # autopoint
 if test -d po ; then
-  tool_run "$autopoint" "--force"
+  tool_run "autopoint" "--force"
 fi
 
 # aclocal
 if test -f acinclude.m4; then rm acinclude.m4; fi
 
-tool_run "$libtoolize" "--copy --force"
-tool_run "$aclocal" "-I m4 -I common/m4 $ACLOCAL_FLAGS"
-tool_run "$autoheader"
-
-# touch the stamp-h.in build stamp so we don't re-run autoheader in maintainer mode
-echo timestamp > stamp-h.in 2> /dev/null
-
-tool_run "$autoconf"
-debug "automake: $automake"
-tool_run "$automake" "--add-missing --copy"
+autoreconf --force --install || exit 1
 
 test -n "$NOCONFIGURE" && {
   echo "+ skipping configure stage for package $package, as requested."
diff --git a/common/check.mak b/common/check.mak
index efd5458..8a90b5d 100644
--- a/common/check.mak
+++ b/common/check.mak
@@ -16,38 +16,38 @@
 # run any given test by running make test.check
 # if the test fails, run it again at at least debug level 2
 %.check: %
-	@$(TESTS_ENVIRONMENT)					\
+	@$(AM_TESTS_ENVIRONMENT)					\
 	CK_DEFAULT_TIMEOUT=20					\
 	$* ||							\
-	$(TESTS_ENVIRONMENT)					\
+	$(AM_TESTS_ENVIRONMENT)					\
 	GST_DEBUG=$$GST_DEBUG,*:2				\
 	CK_DEFAULT_TIMEOUT=20					\
 	$*
 
 # just like 'check', but don't run it again if it fails (useful for debugging)
 %.check-norepeat: %
-	@$(TESTS_ENVIRONMENT)					\
+	@$(AM_TESTS_ENVIRONMENT)					\
 	CK_DEFAULT_TIMEOUT=20					\
 	$*
 
 # run any given test in a loop
 %.torture: %
 	@for i in `seq 1 $(LOOPS)`; do				\
-	$(TESTS_ENVIRONMENT)					\
+	$(AM_TESTS_ENVIRONMENT)					\
 	CK_DEFAULT_TIMEOUT=20					\
 	$*; done
 
 # run any given test in an infinite loop
 %.forever: %
 	@while true; do						\
-	$(TESTS_ENVIRONMENT)					\
+	$(AM_TESTS_ENVIRONMENT)					\
 	CK_DEFAULT_TIMEOUT=20					\
 	$* || break; done
 
 # valgrind any given test by running make test.valgrind
 %.valgrind: %
 	@valgrind_log=$(subst /,-,$*-valgrind.log);		\
-	$(TESTS_ENVIRONMENT)					\
+	$(AM_TESTS_ENVIRONMENT)					\
 	CK_DEFAULT_TIMEOUT=360					\
 	G_SLICE=always-malloc					\
 	$(LIBTOOL) --mode=execute				\
@@ -65,7 +65,7 @@
 
 # valgrind any given test and generate suppressions for it
 %.valgrind.gen-suppressions: %
-	@$(TESTS_ENVIRONMENT)					\
+	@$(AM_TESTS_ENVIRONMENT)					\
 	CK_DEFAULT_TIMEOUT=360					\
 	G_SLICE=always-malloc					\
 	$(LIBTOOL) --mode=execute				\
@@ -95,7 +95,7 @@
 
 # gdb any given test by running make test.gdb
 %.gdb: %
-	@$(TESTS_ENVIRONMENT)					\
+	@$(AM_TESTS_ENVIRONMENT)					\
 	CK_FORK=no						\
 	$(LIBTOOL) --mode=execute				\
 	gdb $*
@@ -205,7 +205,7 @@
 GST_INSPECT = $(GST_TOOLS_DIR)/gst-inspect-$(GST_API_VERSION)
 inspect:
 	@echo "Inspecting features ..."
-	@for e in `$(TESTS_ENVIRONMENT) $(GST_INSPECT) | head -n -2 	\
+	@for e in `$(AM_TESTS_ENVIRONMENT) $(GST_INSPECT) | head -n -2 	\
 	  | cut -d: -f2`;						\
 	  do echo Inspecting $$e;					\
 	     $(GST_INSPECT) $$e > /dev/null 2>&1; done
diff --git a/common/gst-autogen.sh b/common/gst-autogen.sh
index 78cab66..c5798d0 100644
--- a/common/gst-autogen.sh
+++ b/common/gst-autogen.sh
@@ -169,54 +169,6 @@
   return 1;
 }
 
-aclocal_check ()
-{
-  # normally aclocal is part of automake
-  # so we expect it to be in the same place as automake
-  # so if a different automake is supplied, we need to adapt as well
-  # so how's about replacing automake with aclocal in the set var,
-  # and saving that in $aclocal ?
-  # note, this will fail if the actual automake isn't called automake*
-  # or if part of the path before it contains it
-  if [ -z "$automake" ]; then
-    echo "Error: no automake variable set !"
-    return 1
-  else
-    aclocal=`echo $automake | sed s/automake/aclocal/`
-    debug "aclocal: $aclocal"
-    if [ "$aclocal" != "aclocal" ];
-    then
-      CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-aclocal=$aclocal"
-    fi
-    if [ ! -x `which $aclocal` ]; then
-      echo "Error: cannot execute $aclocal !"
-      return 1
-    fi
-  fi
-}
-
-autoheader_check ()
-{
-  # same here - autoheader is part of autoconf
-  # use the same voodoo
-  if [ -z "$autoconf" ]; then
-    echo "Error: no autoconf variable set !"
-    return 1
-  else
-    autoheader=`echo $autoconf | sed s/autoconf/autoheader/`
-    debug "autoheader: $autoheader"
-    if [ "$autoheader" != "autoheader" ];
-    then
-      CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-autoheader=$autoheader"
-    fi
-    if [ ! -x `which $autoheader` ]; then
-      echo "Error: cannot execute $autoheader !"
-      return 1
-    fi
-  fi
-
-}
-
 die_check ()
 {
   # call with $DIE
diff --git a/common/gst.supp b/common/gst.supp
index c08f660..5e2aaf9 100644
--- a/common/gst.supp
+++ b/common/gst.supp
@@ -3972,3 +3972,37 @@
   timer_create(evp)
   fun:timer_create@@GLIBC_2.3.3
 }
+
+{
+   closures aren't valgrind friendly (bgo#739850)
+   Memcheck:Leak
+   match-leak-kinds: possible
+   fun:calloc
+   ...
+   fun:g_cclosure_new
+}
+
+{
+   closures aren't valgrind friendly (bgo#739850)
+   Memcheck:Leak
+   match-leak-kinds: possible
+   fun:malloc
+   ...
+   fun:g_closure_add_invalidate_notifier
+}
+
+{
+   closures aren't valgrind friendly (bgo#739850)
+   Memcheck:Leak
+   match-leak-kinds: possible
+   fun:calloc
+   ...
+   fun:g_closure_new_simple
+}
+
+{
+   glib/giomodules2 (from libsoup.supp)
+   Memcheck:Leak
+   ...
+   fun:_g_io_module_get_default
+}
diff --git a/config.h.in b/config.h.in
index 87312f8..49084ff 100644
--- a/config.h.in
+++ b/config.h.in
@@ -301,9 +301,6 @@
 /* Define if gudev is installed */
 #undef HAVE_GUDEV
 
-/* Define to 1 if you have the <highgui.h> header file. */
-#undef HAVE_HIGHGUI_H
-
 /* Define to enable http live streaming plugin (used by hls). */
 #undef HAVE_HLS
 
@@ -412,9 +409,41 @@
 /* Define to enable opencv plugins (used by opencv). */
 #undef HAVE_OPENCV
 
+/* Define to 1 if you have the <opencv2/contrib/contrib.hpp> header file. */
+#undef HAVE_OPENCV2_CONTRIB_CONTRIB_HPP
+
+/* Define to 1 if you have the <opencv2/core/core_c.h> header file. */
+#undef HAVE_OPENCV2_CORE_CORE_C_H
+
+/* Define to 1 if you have the <opencv2/core/types_c.h> header file. */
+#undef HAVE_OPENCV2_CORE_TYPES_C_H
+
+/* Define to 1 if you have the <opencv2/core/version.hpp> header file. */
+#undef HAVE_OPENCV2_CORE_VERSION_HPP
+
 /* Define to 1 if you have the <opencv2/highgui/highgui_c.h> header file. */
 #undef HAVE_OPENCV2_HIGHGUI_HIGHGUI_C_H
 
+/* Define to 1 if you have the <opencv2/imgproc/imgproc_c.h> header file. */
+#undef HAVE_OPENCV2_IMGPROC_IMGPROC_C_H
+
+/* Define to 1 if you have the <opencv2/imgproc/imgproc.hpp> header file. */
+#undef HAVE_OPENCV2_IMGPROC_IMGPROC_HPP
+
+/* Define to 1 if you have the <opencv2/legacy/compat.hpp> header file. */
+#undef HAVE_OPENCV2_LEGACY_COMPAT_HPP
+
+/* Define to 1 if you have the <opencv2/legacy/legacy.hpp> header file. */
+#undef HAVE_OPENCV2_LEGACY_LEGACY_HPP
+
+/* Define to 1 if you have the <opencv2/objdetect/objdetect.hpp> header file.
+   */
+#undef HAVE_OPENCV2_OBJDETECT_OBJDETECT_HPP
+
+/* Define to 1 if you have the <opencv2/video/background_segm.hpp> header
+   file. */
+#undef HAVE_OPENCV2_VIDEO_BACKGROUND_SEGM_HPP
+
 /* Define to enable openexr library (used by openexr). */
 #undef HAVE_OPENEXR
 
diff --git a/configure b/configure
index 4e6402f..3c13b3c 100755
--- a/configure
+++ b/configure
@@ -34540,7 +34540,7 @@
   save_LIBS="$LIBS"
   CFLAGS="$CFLAGS $DIRECTX_CFLAGS"
   LDFLAGS="$LDFLAGS $DIRECTX_LDFLAGS"
-  LIBS="$LIBS -ldsound -ldxerr9 -luser32"
+  LIBS="$LIBS -lwinmm -ldsound -ldxerr9 -luser32"
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DirectSound LDFLAGS" >&5
 $as_echo_n "checking for DirectSound LDFLAGS... " >&6; }
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -34549,6 +34549,7 @@
 #include <windows.h>
 #include <dxerr9.h>
 #include <dsound.h>
+#include <mmsystem.h>
 
 int
 main ()
@@ -34575,7 +34576,7 @@
   LIBS=$save_LIBS
 
   if test "x$HAVE_DIRECTSOUND" = "xyes";  then
-        DIRECTSOUND_LIBS="-ldsound -ldxerr9 -luser32"
+        DIRECTSOUND_LIBS="-lwinmm -ldsound -ldxerr9 -luser32"
 
 
 
@@ -38592,6 +38593,9 @@
 
    HAVE_DECKLINK=no
    case "$host" in
+     *android*)
+       HAVE_DECKLINK=no
+       ;;
      *-*linux*)
        if test "x$HAVE_PTHREAD_H" = "xyes"; then
          { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
@@ -38683,7 +38687,7 @@
             HAVE_DECKLINK=yes
             DECKLINK_CXXFLAGS=
             DECKLINK_LIBS="-lpthread -ldl"
-	    HAVE_DECKLINK_OSX=yes
+            HAVE_DECKLINK_OSX=yes
 
 fi
 
@@ -44811,7 +44815,18 @@
 
     OLD_CPPFLAGS=$CPPFLAGS
     CPPFLAGS=$OPENCV_CFLAGS
-    for ac_header in highgui.h opencv2/highgui/highgui_c.h
+    something_not_found=no
+    for ac_header in opencv2/contrib/contrib.hpp \
+                      opencv2/core/core_c.h \
+                      opencv2/core/types_c.h \
+                      opencv2/core/version.hpp \
+                      opencv2/highgui/highgui_c.h \
+                      opencv2/imgproc/imgproc.hpp \
+                      opencv2/imgproc/imgproc_c.h \
+                      opencv2/legacy/compat.hpp \
+                      opencv2/legacy/legacy.hpp \
+                      opencv2/objdetect/objdetect.hpp \
+                      opencv2/video/background_segm.hpp
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -44820,6 +44835,8 @@
 #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
 _ACEOF
 
+else
+  something_not_found=yes
 fi
 
 done
@@ -44832,12 +44849,12 @@
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
-    if test $ac_cv_header_highgui_h = "yes" -o $ac_cv_header_opencv2_highgui_highgui_c_h = "yes" ; then
-      HAVE_OPENCV="yes"
-    else
-      { $as_echo "$as_me:${as_lineno-$LINENO}: result: neither highgui.h nor opencv2/highgui/highgui_c.h could not be found" >&5
-$as_echo "neither highgui.h nor opencv2/highgui/highgui_c.h could not be found" >&6; }
+    if test $something_not_found = "yes"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: not all opencv2 headers were found" >&5
+$as_echo "not all opencv2 headers were found" >&6; }
       HAVE_OPENCV="no"
+    else
+      HAVE_OPENCV="yes"
     fi
 
 fi
@@ -45122,7 +45139,7 @@
   HAVE_OPENH264=no
 
 
-  which="openh264"
+  which="openh264 >= 1.3.0"
     required="no"
 
 
diff --git a/configure.ac b/configure.ac
index f466a3e..f5ce28c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_PREREQ([2.68])
+AC_PREREQ([2.69])
 
 dnl initialize autoconf
 dnl when going to/from release please set the nano (fourth number) right !
@@ -8,7 +8,7 @@
 AG_GST_INIT
 
 dnl initialize automake
-AM_INIT_AUTOMAKE([-Wno-portability 1.11 no-dist-gzip dist-xz tar-ustar subdir-objects])
+AM_INIT_AUTOMAKE([-Wno-portability 1.14 no-dist-gzip dist-xz tar-ustar subdir-objects])
 
 dnl define PACKAGE_VERSION_* variables
 AS_VERSION
@@ -1397,12 +1397,13 @@
   save_LIBS="$LIBS"
   CFLAGS="$CFLAGS $DIRECTX_CFLAGS"
   LDFLAGS="$LDFLAGS $DIRECTX_LDFLAGS"
-  LIBS="$LIBS -ldsound -ldxerr9 -luser32"
+  LIBS="$LIBS -lwinmm -ldsound -ldxerr9 -luser32"
   AC_MSG_CHECKING(for DirectSound LDFLAGS)
   AC_LINK_IFELSE([AC_LANG_PROGRAM([[
 #include <windows.h>
 #include <dxerr9.h>
 #include <dsound.h>
+#include <mmsystem.h>
 ]], [[
   DXGetErrorString9 (0);
   DirectSoundCreate(NULL, NULL, NULL);
@@ -1416,7 +1417,7 @@
 
   if test "x$HAVE_DIRECTSOUND" = "xyes";  then
     dnl this is much more than we want
-    DIRECTSOUND_LIBS="-ldsound -ldxerr9 -luser32"
+    DIRECTSOUND_LIBS="-lwinmm -ldsound -ldxerr9 -luser32"
     AC_SUBST(DIRECTX_CFLAGS)
     AC_SUBST(DIRECTX_LDFLAGS)
     AC_SUBST(DIRECTSOUND_LIBS)
@@ -1866,6 +1867,9 @@
 AG_GST_CHECK_FEATURE(DECKLINK, [decklink], decklink, [
    HAVE_DECKLINK=no
    case "$host" in
+     *android*)
+       HAVE_DECKLINK=no
+       ;;
      *-*linux*)
        if test "x$HAVE_PTHREAD_H" = "xyes"; then
          AC_CHECK_LIB(dl, dlopen,
@@ -1883,7 +1887,7 @@
             HAVE_DECKLINK=yes
             DECKLINK_CXXFLAGS=
             DECKLINK_LIBS="-lpthread -ldl"
-	    HAVE_DECKLINK_OSX=yes
+            HAVE_DECKLINK_OSX=yes
            ])
        fi
        ;;
@@ -2446,15 +2450,26 @@
     AC_LANG([C++])
     OLD_CPPFLAGS=$CPPFLAGS
     CPPFLAGS=$OPENCV_CFLAGS
-    AC_CHECK_HEADERS([highgui.h opencv2/highgui/highgui_c.h])
+    something_not_found=no
+    AC_CHECK_HEADERS([opencv2/contrib/contrib.hpp \
+                      opencv2/core/core_c.h \
+                      opencv2/core/types_c.h \
+                      opencv2/core/version.hpp \
+                      opencv2/highgui/highgui_c.h \
+                      opencv2/imgproc/imgproc.hpp \
+                      opencv2/imgproc/imgproc_c.h \
+                      opencv2/legacy/compat.hpp \
+                      opencv2/legacy/legacy.hpp \
+                      opencv2/objdetect/objdetect.hpp \
+                      opencv2/video/background_segm.hpp], [], [something_not_found=yes])
     CPPFLAGS=$OLD_CPPFLAGS
     AC_LANG([C])
 
-    if test $ac_cv_header_highgui_h = "yes" -o $ac_cv_header_opencv2_highgui_highgui_c_h = "yes" ; then
-      HAVE_OPENCV="yes"
-    else
-      AC_MSG_RESULT([neither highgui.h nor opencv2/highgui/highgui_c.h could not be found])
+    if test $something_not_found = "yes"; then
+      AC_MSG_RESULT([not all opencv2 headers were found])
       HAVE_OPENCV="no"
+    else
+      HAVE_OPENCV="yes"
     fi
   ], [
     HAVE_OPENCV="no"
@@ -2475,7 +2490,7 @@
 dnl *** openh264 ***
 translit(dnm, m, l) AM_CONDITIONAL(USE_OPENH264, true)
 AG_GST_CHECK_FEATURE(OPENH264, [openh264 library], openh264, [
-  AG_GST_PKG_CHECK_MODULES(OPENH264, openh264)
+  AG_GST_PKG_CHECK_MODULES(OPENH264, openh264 >= 1.3.0)
 ])
 
 dnl *** OpenJPEG ***
diff --git a/docs/libs/Makefile.am b/docs/libs/Makefile.am
index 5c6c919..967e3c8 100644
--- a/docs/libs/Makefile.am
+++ b/docs/libs/Makefile.am
@@ -58,6 +58,9 @@
 	$(top_builddir)/gst-libs/gst/uridownloader/libgsturidownloader-@GST_API_VERSION@.la \
 	$(top_builddir)/gst-libs/gst/mpegts/libgstmpegts-@GST_API_VERSION@.la \
 	$(top_builddir)/gst-libs/gst/gl/libgstgl-@GST_API_VERSION@.la \
+	-L$(top_builddir)/gst-libs/gst/adaptivedemux/.libs \
+	-L$(top_builddir)/gst-libs/gst/video/.libs \
+	-L$(top_builddir)/gst-libs/gst/base/.libs \
   $(GST_BASE_LIBS)
 
 GTKDOC_CC=$(LIBTOOL) --tag=CC --mode=compile $(CC)
diff --git a/docs/libs/Makefile.in b/docs/libs/Makefile.in
index 8e0f369..7b5a0bc 100644
--- a/docs/libs/Makefile.in
+++ b/docs/libs/Makefile.in
@@ -732,6 +732,9 @@
 	$(top_builddir)/gst-libs/gst/uridownloader/libgsturidownloader-@GST_API_VERSION@.la \
 	$(top_builddir)/gst-libs/gst/mpegts/libgstmpegts-@GST_API_VERSION@.la \
 	$(top_builddir)/gst-libs/gst/gl/libgstgl-@GST_API_VERSION@.la \
+	-L$(top_builddir)/gst-libs/gst/adaptivedemux/.libs \
+	-L$(top_builddir)/gst-libs/gst/video/.libs \
+	-L$(top_builddir)/gst-libs/gst/base/.libs \
   $(GST_BASE_LIBS)
 
 GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC)
diff --git a/docs/libs/html/GstGLBufferPool.html b/docs/libs/html/GstGLBufferPool.html
index 605fa76..ab0041d 100644
--- a/docs/libs/html/GstGLBufferPool.html
+++ b/docs/libs/html/GstGLBufferPool.html
@@ -99,8 +99,8 @@
 <col width="200px" class="parameters_annotations">
 </colgroup>
 <tbody><tr>
-<td class="parameter_name"><p>display</p></td>
-<td class="parameter_description"><p>the <a class="link" href="GstGLDisplay.html" title="GstGLDisplay"><span class="type">GstGLDisplay</span></a> to use</p></td>
+<td class="parameter_name"><p>context</p></td>
+<td class="parameter_description"><p>the <a class="link" href="GstGLContext.html" title="GstGLContext"><span class="type">GstGLContext</span></a> to use</p></td>
 <td class="parameter_annotations"> </td>
 </tr></tbody>
 </table></div>
diff --git a/docs/libs/html/GstGLColorConvert.html b/docs/libs/html/GstGLColorConvert.html
index cb7261c..707852a 100644
--- a/docs/libs/html/GstGLColorConvert.html
+++ b/docs/libs/html/GstGLColorConvert.html
@@ -169,13 +169,13 @@
 <td class="parameter_annotations"> </td>
 </tr>
 <tr>
-<td class="parameter_name"><p>in_info</p></td>
-<td class="parameter_description"><p>input <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-libs/html/gst-plugins-base-libs-gstvideo.html#GstVideoInfo"><span class="type">GstVideoInfo</span></a></p></td>
+<td class="parameter_name"><p>in_caps</p></td>
+<td class="parameter_description"><p>input <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstCaps.html"><span class="type">GstCaps</span></a></p></td>
 <td class="parameter_annotations"> </td>
 </tr>
 <tr>
-<td class="parameter_name"><p>out_info</p></td>
-<td class="parameter_description"><p>output <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-libs/html/gst-plugins-base-libs-gstvideo.html#GstVideoInfo"><span class="type">GstVideoInfo</span></a></p></td>
+<td class="parameter_name"><p>out_caps</p></td>
+<td class="parameter_description"><p>output <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstCaps.html"><span class="type">GstCaps</span></a></p></td>
 <td class="parameter_annotations"> </td>
 </tr>
 </tbody>
diff --git a/docs/libs/html/GstGLContext.html b/docs/libs/html/GstGLContext.html
index 3045885..45187b2 100644
--- a/docs/libs/html/GstGLContext.html
+++ b/docs/libs/html/GstGLContext.html
@@ -839,11 +839,6 @@
 </colgroup>
 <tbody>
 <tr>
-<td class="parameter_name"><p>context_type</p></td>
-<td class="parameter_description"><p>a <a class="link" href="gst-plugins-bad-libs-GstGLAPI.html#GstGLPlatform" title="enum GstGLPlatform"><span class="type">GstGLPlatform</span></a> specifying the type of context to retreive</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
 <td class="parameter_name"><p>major</p></td>
 <td class="parameter_description"><p> (allow-none): the major version. </p></td>
 <td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
diff --git a/docs/libs/html/GstGLDisplay.html b/docs/libs/html/GstGLDisplay.html
index c9f7367..1a38293 100644
--- a/docs/libs/html/GstGLDisplay.html
+++ b/docs/libs/html/GstGLDisplay.html
@@ -229,11 +229,18 @@
 <col class="parameters_description">
 <col width="200px" class="parameters_annotations">
 </colgroup>
-<tbody><tr>
+<tbody>
+<tr>
 <td class="parameter_name"><p>display</p></td>
 <td class="parameter_description"><p>a <a class="link" href="GstGLDisplay.html" title="GstGLDisplay"><span class="type">GstGLDisplay</span></a></p></td>
 <td class="parameter_annotations"> </td>
-</tr></tbody>
+</tr>
+<tr>
+<td class="parameter_name"><p>gl_api</p></td>
+<td class="parameter_description"><p>a <a class="link" href="gst-plugins-bad-libs-GstGLAPI.html#GstGLAPI" title="enum GstGLAPI"><span class="type">GstGLAPI</span></a> to filter with</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
 </table></div>
 </div>
 </div>
@@ -299,6 +306,7 @@
 was successfully added. <a href="https://developer.gnome.org/glib/unstable/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> may be returned
 if there already exists another context for <em class="parameter"><code>context</code></em>
 's active thread.</p>
+<p>Must be called with the object lock held.</p>
 <p></p>
 </div>
 <p class="since">Since 1.6</p>
@@ -335,7 +343,8 @@
 <div class="refsect3">
 <a name="id-1.2.9.11.7.7.5"></a><h4>Returns</h4>
 <p> the <a class="link" href="GstGLContext.html" title="GstGLContext"><span class="type">GstGLContext</span></a> current on <em class="parameter"><code>thread</code></em>
-or <a href="https://developer.gnome.org/glib/unstable/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>. </p>
+or <a href="https://developer.gnome.org/glib/unstable/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a></p>
+<p>Must be called with the object lock held. </p>
 <p><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
 </div>
 <p class="since">Since 1.6</p>
diff --git a/docs/libs/html/GstGLDownload.html b/docs/libs/html/GstGLDownload.html
index 9a19fcb..0e2fce7 100644
--- a/docs/libs/html/GstGLDownload.html
+++ b/docs/libs/html/GstGLDownload.html
@@ -151,18 +151,8 @@
 <td class="parameter_annotations"> </td>
 </tr>
 <tr>
-<td class="parameter_name"><p>v_format</p></td>
-<td class="parameter_description"><p>a <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-libs/html/gst-plugins-base-libs-gstvideo.html#GstVideoFormat"><span class="type">GstVideoFormat</span></a></p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>out_width</p></td>
-<td class="parameter_description"><p>the width to download to</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>out_height</p></td>
-<td class="parameter_description"><p>the height to download to</p></td>
+<td class="parameter_name"><p>out_info</p></td>
+<td class="parameter_description"><p>a <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-libs/html/gst-plugins-base-libs-gstvideo.html#GstVideoInfo"><span class="type">GstVideoInfo</span></a></p></td>
 <td class="parameter_annotations"> </td>
 </tr>
 </tbody>
diff --git a/docs/libs/html/GstGLFilter.html b/docs/libs/html/GstGLFilter.html
index 2a64b24..3c96b06 100644
--- a/docs/libs/html/GstGLFilter.html
+++ b/docs/libs/html/GstGLFilter.html
@@ -351,11 +351,7 @@
   gboolean (*set_caps)          (GstGLFilter* filter, GstCaps* incaps, GstCaps* outcaps);
   gboolean (*filter)            (GstGLFilter *filter, GstBuffer *inbuf, GstBuffer *outbuf);
   gboolean (*filter_texture)    (GstGLFilter *filter, guint in_tex, guint out_tex);
-  gboolean (*onInitFBO)         (GstGLFilter *filter);
-
-  void (*onStart)               (GstGLFilter *filter);
-  void (*onStop)                (GstGLFilter *filter);
-  void (*onReset)               (GstGLFilter *filter);
+  gboolean (*init_fbo)          (GstGLFilter *filter);
 
   /* useful to init and cleanup custom gl resources */
   void (*display_init_cb)       (GstGLFilter *filter);
@@ -401,27 +397,11 @@
 <td class="struct_member_annotations"> </td>
 </tr>
 <tr>
-<td class="struct_member_name"><p><em class="structfield"><code><a name="GstGLFilterClass.onInitFBO"></a>onInitFBO</code></em> ()</p></td>
+<td class="struct_member_name"><p><em class="structfield"><code><a name="GstGLFilterClass.init-fbo"></a>init_fbo</code></em> ()</p></td>
 <td class="struct_member_description"><p>perform initialization when the Framebuffer object is created</p></td>
 <td class="struct_member_annotations"> </td>
 </tr>
 <tr>
-<td class="struct_member_name"><p><em class="structfield"><code><a name="GstGLFilterClass.onStart"></a>onStart</code></em> ()</p></td>
-<td class="struct_member_description"><p>called when element activates see also <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-libs/html/GstBaseTransform.html"><span class="type">GstBaseTransform</span></a></p></td>
-<td class="struct_member_annotations"> </td>
-</tr>
-<tr>
-<td class="struct_member_name"><p><em class="structfield"><code><a name="GstGLFilterClass.onStop"></a>onStop</code></em> ()</p></td>
-<td class="struct_member_description"><p>called when the element deactivates e also <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-libs/html/GstBaseTransform.html"><span class="type">GstBaseTransform</span></a></p></td>
-<td class="struct_member_annotations"> </td>
-</tr>
-<tr>
-<td class="struct_member_name"><p><em class="structfield"><code><a name="GstGLFilterClass.onReset"></a>onReset</code></em> ()</p></td>
-<td class="struct_member_description"><p>called on inizialation and after <em class="parameter"><code>onStop</code></em>
-</p></td>
-<td class="struct_member_annotations"> </td>
-</tr>
-<tr>
 <td class="struct_member_name"><p><em class="structfield"><code><a name="GstGLFilterClass.display-init-cb"></a>display_init_cb</code></em> ()</p></td>
 <td class="struct_member_description"><p>execute arbitrary gl code on start</p></td>
 <td class="struct_member_annotations"> </td>
diff --git a/docs/libs/html/GstGLUpload.html b/docs/libs/html/GstGLUpload.html
index 8e4c7db..f7bcfa9 100644
--- a/docs/libs/html/GstGLUpload.html
+++ b/docs/libs/html/GstGLUpload.html
@@ -175,13 +175,13 @@
 </tr>
 <tr>
 <td class="parameter_name"><p>in_caps</p></td>
-<td class="parameter_description"><p> (allow-none): (out): the input <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstCaps.html"><span class="type">GstCaps</span></a>. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></td>
+<td class="parameter_description"><p> the input <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstCaps.html"><span class="type">GstCaps</span></a>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>][<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
 </tr>
 <tr>
-<td class="parameter_name"><p>ou_caps</p></td>
-<td class="parameter_description"><p> (allow-none): (out): the output <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstCaps.html"><span class="type">GstCaps</span></a>. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></td>
+<td class="parameter_name"><p>out_caps</p></td>
+<td class="parameter_description"><p> the output <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstCaps.html"><span class="type">GstCaps</span></a>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>][<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
 </tr>
 </tbody>
 </table></div>
diff --git a/docs/libs/html/api-index-full.html b/docs/libs/html/api-index-full.html
index ea51afe..bcac363 100644
--- a/docs/libs/html/api-index-full.html
+++ b/docs/libs/html/api-index-full.html
@@ -68,6 +68,10 @@
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="gst-plugins-bad-libs-GstAggregator.html#gst-aggregator-get-latency" title="gst_aggregator_get_latency ()">gst_aggregator_get_latency</a>, function in <a class="link" href="gst-plugins-bad-libs-GstAggregator.html" title="GstAggregator">GstAggregator</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="gst-plugins-bad-libs-GstAggregator.html#gst-aggregator-iterate-sinkpads" title="gst_aggregator_iterate_sinkpads ()">gst_aggregator_iterate_sinkpads</a>, function in <a class="link" href="gst-plugins-bad-libs-GstAggregator.html" title="GstAggregator">GstAggregator</a>
 </dt>
 <dd></dd>
diff --git a/docs/libs/html/gst-plugins-bad-libs-1.0.devhelp2 b/docs/libs/html/gst-plugins-bad-libs-1.0.devhelp2
index 65c43c3..a197a40 100644
--- a/docs/libs/html/gst-plugins-bad-libs-1.0.devhelp2
+++ b/docs/libs/html/gst-plugins-bad-libs-1.0.devhelp2
@@ -390,6 +390,7 @@
     <keyword type="function" name="gst_aggregator_finish_buffer ()" link="gst-plugins-bad-libs-GstAggregator.html#gst-aggregator-finish-buffer"/>
     <keyword type="function" name="gst_aggregator_set_src_caps ()" link="gst-plugins-bad-libs-GstAggregator.html#gst-aggregator-set-src-caps"/>
     <keyword type="function" name="gst_aggregator_iterate_sinkpads ()" link="gst-plugins-bad-libs-GstAggregator.html#gst-aggregator-iterate-sinkpads"/>
+    <keyword type="function" name="gst_aggregator_get_latency ()" link="gst-plugins-bad-libs-GstAggregator.html#gst-aggregator-get-latency"/>
     <keyword type="struct" name="struct GstAggregator" link="gst-plugins-bad-libs-GstAggregator.html#GstAggregator"/>
     <keyword type="struct" name="struct GstAggregatorClass" link="gst-plugins-bad-libs-GstAggregator.html#GstAggregatorClass"/>
     <keyword type="function" name="gst_aggregator_pad_steal_buffer ()" link="gst-plugins-bad-libs-GstAggregatorPad.html#gst-aggregator-pad-steal-buffer"/>
diff --git a/docs/libs/html/gst-plugins-bad-libs-Base-MPEG-TS-sections.html b/docs/libs/html/gst-plugins-bad-libs-Base-MPEG-TS-sections.html
index b6fbd67..7c2c876 100644
--- a/docs/libs/html/gst-plugins-bad-libs-Base-MPEG-TS-sections.html
+++ b/docs/libs/html/gst-plugins-bad-libs-Base-MPEG-TS-sections.html
@@ -549,7 +549,7 @@
 gst_mpegts_section_from_pat (<em class="parameter"><code><a href="https://developer.gnome.org/glib/unstable/glib-Pointer-Arrays.html#GPtrArray"><span class="type">GPtrArray</span></a> *programs</code></em>,
                              <em class="parameter"><code><span class="type">guint16</span> ts_id</code></em>);</pre>
 <p>Creates a PAT <a class="link" href="gst-plugins-bad-libs-Base-MPEG-TS-sections.html#GstMpegtsSection"><span class="type">GstMpegtsSection</span></a> from the <em class="parameter"><code>programs</code></em>
- array of <a href="../gst-plugins-bad-libs-1.0/gst-plugins-bad-libs-Base-MPEG-TS-sections.html#GstMpegtsPatProgram"><span class="type">GstMpegtsPatPrograms</span></a></p>
+ array of <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-bad-libs/html/gst-plugins-bad-libs-Base-MPEG-TS-sections.html#GstMpegtsPatProgram"><span class="type">GstMpegtsPatPrograms</span></a></p>
 <div class="refsect3">
 <a name="id-1.2.5.4.9.14.5"></a><h4>Parameters</h4>
 <div class="informaltable"><table width="100%" border="0">
diff --git a/docs/libs/html/gst-plugins-bad-libs-GstAggregator.html b/docs/libs/html/gst-plugins-bad-libs-GstAggregator.html
index b54fb8d..d3de038 100644
--- a/docs/libs/html/gst-plugins-bad-libs-GstAggregator.html
+++ b/docs/libs/html/gst-plugins-bad-libs-GstAggregator.html
@@ -64,6 +64,14 @@
 <a class="link" href="gst-plugins-bad-libs-GstAggregator.html#gst-aggregator-iterate-sinkpads" title="gst_aggregator_iterate_sinkpads ()">gst_aggregator_iterate_sinkpads</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
+<tr>
+<td class="function_type">
+<a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstClock.html#GstClockTime"><span class="returnvalue">GstClockTime</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="gst-plugins-bad-libs-GstAggregator.html#gst-aggregator-get-latency" title="gst_aggregator_get_latency ()">gst_aggregator_get_latency</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
 </tbody>
 </table></div>
 </div>
@@ -117,6 +125,12 @@
    subclass, it should instead return GST_FLOW_EOS in its aggregate
    implementation.
  </p></li>
+<li class="listitem"><p>
+   Note that the aggregator logic regarding gap event handling is to turn
+   these into gap buffers with matching PTS and duration. It will also
+   flag these buffers with GST_BUFFER_FLAG_GAP and GST_BUFFER_FLAG_DROPPABLE
+   to ease their identification and subsequent processing.
+ </p></li>
 </ul></div>
 </div>
 <div class="refsect1">
@@ -222,6 +236,37 @@
 </table></div>
 </div>
 </div>
+<hr>
+<div class="refsect2">
+<a name="gst-aggregator-get-latency"></a><h3>gst_aggregator_get_latency ()</h3>
+<pre class="programlisting"><a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstClock.html#GstClockTime"><span class="returnvalue">GstClockTime</span></a>
+gst_aggregator_get_latency (<em class="parameter"><code><a class="link" href="gst-plugins-bad-libs-GstAggregator.html#GstAggregator" title="struct GstAggregator"><span class="type">GstAggregator</span></a> *self</code></em>);</pre>
+<p>Retrieves the latency values reported by <em class="parameter"><code>self</code></em>
+ in response to the latency
+query, or <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstClock.html#GST-CLOCK-TIME-NONE:CAPS"><code class="literal">GST_CLOCK_TIME_NONE</code></a> if there is not live source connected and the element
+will not wait for the clock.</p>
+<p>Typically only called by subclasses.</p>
+<div class="refsect3">
+<a name="id-1.2.7.2.6.5.6"></a><h4>Parameters</h4>
+<div class="informaltable"><table width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>a <a class="link" href="gst-plugins-bad-libs-GstAggregator.html#GstAggregator" title="struct GstAggregator"><span class="type">GstAggregator</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="id-1.2.7.2.6.5.7"></a><h4>Returns</h4>
+<p> The latency or <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstClock.html#GST-CLOCK-TIME-NONE:CAPS"><code class="literal">GST_CLOCK_TIME_NONE</code></a> if the element does not sync</p>
+<p></p>
+</div>
+</div>
 </div>
 <div class="refsect1">
 <a name="gst-plugins-bad-libs-GstAggregator.other_details"></a><h2>Types and Values</h2>
@@ -395,7 +440,7 @@
 <td class="struct_member_description"><p>Mandatory.
 Called when buffers are queued on all sinkpads. Classes
 should iterate the GstElement-&gt;sinkpads and peek or steal
-buffers from the <a href="../gst-plugins-bad-libs-1.0/gst-plugins-bad-libs-GstAggregatorPad.html#GstAggregatorPad"><span class="type">GstAggregatorPads</span></a>. If the subclass returns
+buffers from the <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-bad-libs/html/gst-plugins-bad-libs-GstAggregatorPad.html#GstAggregatorPad"><span class="type">GstAggregatorPads</span></a>. If the subclass returns
 GST_FLOW_EOS, sending of the eos event will be taken care
 of. Once / if a buffer has been constructed from the
 aggregated buffers, the subclass should call _finish_buffer.</p></td>
diff --git a/docs/libs/html/gst-plugins-bad-libs-GstVideoAggregatorPad.html b/docs/libs/html/gst-plugins-bad-libs-GstVideoAggregatorPad.html
index a6c3729..d30038b 100644
--- a/docs/libs/html/gst-plugins-bad-libs-GstVideoAggregatorPad.html
+++ b/docs/libs/html/gst-plugins-bad-libs-GstVideoAggregatorPad.html
@@ -66,6 +66,12 @@
   GstVideoInfo info;
 
   GstBuffer *buffer;
+  /* The caps on the pad may not match the buffer above because of two reasons:
+   * 1) When caps change, the info above will get updated, but the buffer might
+   *    not since it might be pending on the GstAggregatorPad
+   * 2) We might reject the new buffer in fill_queues() and reuse a previous
+   *    buffer which has older GstVideoInfo
+   * Hence, we need to maintain a GstVideoInfo for mapping buffers separately */
   GstVideoInfo buffer_vinfo;
 
   GstVideoFrame *aggregated_frame;
diff --git a/docs/libs/html/gst-plugins-bad-libs-gstglmemory.html b/docs/libs/html/gst-plugins-bad-libs-gstglmemory.html
index 1acf1f6..42e3417 100644
--- a/docs/libs/html/gst-plugins-bad-libs-gstglmemory.html
+++ b/docs/libs/html/gst-plugins-bad-libs-gstglmemory.html
@@ -627,7 +627,7 @@
 <td class="parameter_annotations"> </td>
 </tr>
 <tr>
-<td class="parameter_name"><p>param</p></td>
+<td class="parameter_name"><p>params</p></td>
 <td class="parameter_description"><p>a <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstAllocator.html#GstAllocationParams"><span class="type">GstAllocationParams</span></a></p></td>
 <td class="parameter_annotations"> </td>
 </tr>
diff --git a/docs/libs/html/index.sgml b/docs/libs/html/index.sgml
index aa1f534..53e6bf4 100644
--- a/docs/libs/html/index.sgml
+++ b/docs/libs/html/index.sgml
@@ -427,6 +427,7 @@
 <ANCHOR id="gst-aggregator-finish-buffer" href="gst-plugins-bad-libs-1.0/gst-plugins-bad-libs-GstAggregator.html#gst-aggregator-finish-buffer">
 <ANCHOR id="gst-aggregator-set-src-caps" href="gst-plugins-bad-libs-1.0/gst-plugins-bad-libs-GstAggregator.html#gst-aggregator-set-src-caps">
 <ANCHOR id="gst-aggregator-iterate-sinkpads" href="gst-plugins-bad-libs-1.0/gst-plugins-bad-libs-GstAggregator.html#gst-aggregator-iterate-sinkpads">
+<ANCHOR id="gst-aggregator-get-latency" href="gst-plugins-bad-libs-1.0/gst-plugins-bad-libs-GstAggregator.html#gst-aggregator-get-latency">
 <ANCHOR id="gst-plugins-bad-libs-GstAggregator.other_details" href="gst-plugins-bad-libs-1.0/gst-plugins-bad-libs-GstAggregator.html#gst-plugins-bad-libs-GstAggregator.other_details">
 <ANCHOR id="GstAggregator" href="gst-plugins-bad-libs-1.0/gst-plugins-bad-libs-GstAggregator.html#GstAggregator">
 <ANCHOR id="GstAggregatorClass" href="gst-plugins-bad-libs-1.0/gst-plugins-bad-libs-GstAggregator.html#GstAggregatorClass">
diff --git a/docs/plugins/html/gst-plugins-bad-plugins-audiomixer.html b/docs/plugins/html/gst-plugins-bad-plugins-audiomixer.html
index c383c94..5bd0b3f 100644
--- a/docs/plugins/html/gst-plugins-bad-plugins-audiomixer.html
+++ b/docs/plugins/html/gst-plugins-bad-plugins-audiomixer.html
@@ -91,7 +91,7 @@
     <span class="lineart">╰──</span> <a href="https://developer.gnome.org/gobject/unstable/gobject-The-Base-Object-Type.html#GInitiallyUnowned">GInitiallyUnowned</a>
         <span class="lineart">╰──</span> <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstObject.html">GstObject</a>
             <span class="lineart">╰──</span> <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstElement.html">GstElement</a>
-                <span class="lineart">╰──</span> GstAggregator
+                <span class="lineart">╰──</span> <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-bad-libs/html/gst-plugins-bad-libs-GstAggregator.html#GstAggregator">GstAggregator</a>
                     <span class="lineart">╰──</span> GstAudioMixer
 </pre>
 </div>
diff --git a/docs/plugins/html/gst-plugins-bad-plugins-compositor.html b/docs/plugins/html/gst-plugins-bad-plugins-compositor.html
index 3c0aee4..f3c1c3f 100644
--- a/docs/plugins/html/gst-plugins-bad-plugins-compositor.html
+++ b/docs/plugins/html/gst-plugins-bad-plugins-compositor.html
@@ -54,12 +54,12 @@
     <span class="lineart">╰──</span> <a href="https://developer.gnome.org/gobject/unstable/gobject-The-Base-Object-Type.html#GInitiallyUnowned">GInitiallyUnowned</a>
         <span class="lineart">╰──</span> <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstObject.html">GstObject</a>
             <span class="lineart">├──</span> <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstElement.html">GstElement</a>
-            <span class="lineart">│</span>   <span class="lineart">╰──</span> GstAggregator
-            <span class="lineart">│</span>       <span class="lineart">╰──</span> GstVideoAggregator
+            <span class="lineart">│</span>   <span class="lineart">╰──</span> <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-bad-libs/html/gst-plugins-bad-libs-GstAggregator.html#GstAggregator">GstAggregator</a>
+            <span class="lineart">│</span>       <span class="lineart">╰──</span> <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-bad-libs/html/gst-plugins-bad-libs-GstVideoAggregator.html#GstVideoAggregator">GstVideoAggregator</a>
             <span class="lineart">│</span>           <span class="lineart">╰──</span> GstCompositor
             <span class="lineart">╰──</span> <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstPad.html">GstPad</a>
-                <span class="lineart">╰──</span> GstAggregatorPad
-                    <span class="lineart">╰──</span> GstVideoAggregatorPad
+                <span class="lineart">╰──</span> <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-bad-libs/html/gst-plugins-bad-libs-GstAggregatorPad.html#GstAggregatorPad">GstAggregatorPad</a>
+                    <span class="lineart">╰──</span> <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-bad-libs/html/gst-plugins-bad-libs-GstVideoAggregatorPad.html#GstVideoAggregatorPad">GstVideoAggregatorPad</a>
                         <span class="lineart">╰──</span> GstCompositorPad
 </pre>
 </div>
diff --git a/docs/plugins/html/gst-plugins-bad-plugins-fpsdisplaysink.html b/docs/plugins/html/gst-plugins-bad-plugins-fpsdisplaysink.html
index 355eacb..d32bd8e 100644
--- a/docs/plugins/html/gst-plugins-bad-plugins-fpsdisplaysink.html
+++ b/docs/plugins/html/gst-plugins-bad-plugins-fpsdisplaysink.html
@@ -163,7 +163,7 @@
 4</pre></td>
         <td class="listing_code"><pre class="programlisting">gst<span class="gtkdoc opt">-</span>launch videotestsrc <span class="gtkdoc opt">!</span> fpsdisplaysink
 gst<span class="gtkdoc opt">-</span>launch videotestsrc <span class="gtkdoc opt">!</span> fpsdisplaysink text<span class="gtkdoc opt">-</span>overlay<span class="gtkdoc opt">=</span><span class="keyword">false</span>
-gst<span class="gtkdoc opt">-</span>launch filesrc location<span class="gtkdoc opt">=</span>video<span class="gtkdoc opt">.</span>avi <span class="gtkdoc opt">!</span> decodebin2 name<span class="gtkdoc opt">=</span>d <span class="gtkdoc opt">!</span> queue <span class="gtkdoc opt">!</span> fpsdisplaysink d<span class="gtkdoc opt">. !</span> queue <span class="gtkdoc opt">!</span> fakesink sync<span class="gtkdoc opt">=</span><span class="keyword">true</span>
+gst<span class="gtkdoc opt">-</span>launch filesrc location<span class="gtkdoc opt">=</span>video<span class="gtkdoc opt">.</span>avi <span class="gtkdoc opt">!</span> decodebin name<span class="gtkdoc opt">=</span>d <span class="gtkdoc opt">!</span> queue <span class="gtkdoc opt">!</span> fpsdisplaysink d<span class="gtkdoc opt">. !</span> queue <span class="gtkdoc opt">!</span> fakesink sync<span class="gtkdoc opt">=</span><span class="keyword">true</span>
 gst<span class="gtkdoc opt">-</span>launch playbin uri<span class="gtkdoc opt">=</span>file<span class="gtkdoc opt">:</span><span class="gtkdoc slc">///path/to/video.avi video-sink=&quot;fpsdisplaysink&quot; audio-sink=fakesink</span></pre></td>
       </tr>
     </tbody>
diff --git a/ext/apexsink/gstapexraop.c b/ext/apexsink/gstapexraop.c
index 0a78096..af4f573 100644
--- a/ext/apexsink/gstapexraop.c
+++ b/ext/apexsink/gstapexraop.c
@@ -252,7 +252,7 @@
   {
     struct asvals
     {
-      gulong url_key;
+      guint32 url_key;
       guint64 conn_id;
       guchar challenge[16];
     } v;
@@ -284,7 +284,7 @@
     return GST_RTSP_STS_DESTINATION_UNREACHABLE;
 
   RAND_bytes (randbuf.buf, sizeof (randbuf));
-  sprintf ((gchar *) conn->url_abspath, "%lu", randbuf.v.url_key);
+  sprintf ((gchar *) conn->url_abspath, "%u", randbuf.v.url_key);
   sprintf ((char *) conn->cid, "%16" G_GINT64_MODIFIER "x", randbuf.v.conn_id);
 
   RAND_bytes (conn->aes_ky, AES_BLOCK_SIZE);
diff --git a/ext/dash/gstdashdemux.c b/ext/dash/gstdashdemux.c
index 16c5488..1b18ec1 100644
--- a/ext/dash/gstdashdemux.c
+++ b/ext/dash/gstdashdemux.c
@@ -214,7 +214,7 @@
 static gint64
 gst_dash_demux_get_manifest_update_interval (GstAdaptiveDemux * demux);
 static GstFlowReturn
-gst_dash_demux_update_manifest (GstAdaptiveDemux * demux, GstBuffer * buf);
+gst_dash_demux_update_manifest_data (GstAdaptiveDemux * demux, GstBuffer * buf);
 static gint64
 gst_dash_demux_stream_get_fragment_waiting_time (GstAdaptiveDemuxStream *
     stream);
@@ -354,7 +354,8 @@
   gstadaptivedemux_class->seek = gst_dash_demux_seek;
 
   gstadaptivedemux_class->process_manifest = gst_dash_demux_process_manifest;
-  gstadaptivedemux_class->update_manifest = gst_dash_demux_update_manifest;
+  gstadaptivedemux_class->update_manifest_data =
+      gst_dash_demux_update_manifest_data;
   gstadaptivedemux_class->get_manifest_update_interval =
       gst_dash_demux_get_manifest_update_interval;
 
@@ -484,6 +485,9 @@
     active_stream = gst_mpdparser_get_active_stream_by_index (demux->client, i);
     if (active_stream == NULL)
       continue;
+    /* TODO: support 'application' mimeType */
+    if (active_stream->mimeType == GST_STREAM_APPLICATION)
+      continue;
 
     srcpad = gst_dash_demux_create_pad (demux, active_stream);
     caps = gst_dash_demux_get_input_caps (demux, active_stream);
@@ -1142,7 +1146,8 @@
 }
 
 static GstFlowReturn
-gst_dash_demux_update_manifest (GstAdaptiveDemux * demux, GstBuffer * buffer)
+gst_dash_demux_update_manifest_data (GstAdaptiveDemux * demux,
+    GstBuffer * buffer)
 {
   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
   GstMpdClient *new_client = NULL;
diff --git a/ext/dash/gstmpdparser.c b/ext/dash/gstmpdparser.c
index 369aca4..21f84f1 100644
--- a/ext/dash/gstmpdparser.c
+++ b/ext/dash/gstmpdparser.c
@@ -1329,6 +1329,9 @@
     return;
   }
 
+  mult_seg_base_type->duration = 0;
+  mult_seg_base_type->startNumber = 1;
+
   /* Inherit attribute values from parent */
   if (parent) {
     mult_seg_base_type->duration = parent->duration;
@@ -1345,8 +1348,10 @@
     mult_seg_base_type->duration = intval;
   }
 
-  gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "startNumber", 1,
-      &mult_seg_base_type->startNumber);
+  if (gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "startNumber", 1,
+          &intval)) {
+    mult_seg_base_type->startNumber = intval;
+  }
 
   GST_LOG ("extension of MultipleSegmentBaseType extension:");
   gst_mpdparser_parse_seg_base_type_ext (&mult_seg_base_type->SegBaseType,
diff --git a/ext/dtls/gstdtlsagent.c b/ext/dtls/gstdtlsagent.c
index 837ef30..af5b75c 100644
--- a/ext/dtls/gstdtlsagent.c
+++ b/ext/dtls/gstdtlsagent.c
@@ -42,9 +42,7 @@
 GST_DEBUG_CATEGORY_STATIC (gst_dtls_agent_debug);
 #define GST_CAT_DEFAULT gst_dtls_agent_debug
 
-G_DEFINE_TYPE_WITH_CODE (GstDtlsAgent, gst_dtls_agent, G_TYPE_OBJECT,
-    GST_DEBUG_CATEGORY_INIT (gst_dtls_agent_debug, "dtlsagent", 0,
-        "DTLS Agent"));
+G_DEFINE_TYPE (GstDtlsAgent, gst_dtls_agent, G_TYPE_OBJECT);
 
 #define GST_DTLS_AGENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), GST_TYPE_DTLS_AGENT, GstDtlsAgentPrivate))
 
@@ -115,6 +113,9 @@
   gint num_locks;
 
   if (g_once_init_enter (&is_init)) {
+    GST_DEBUG_CATEGORY_INIT (gst_dtls_agent_debug, "dtlsagent", 0,
+        "DTLS Agent");
+
     if (OPENSSL_VERSION_NUMBER < 0x1000100fL) {
       GST_WARNING_OBJECT (NULL,
           "Incorrect OpenSSL version, should be >= 1.0.1, is %s",
diff --git a/ext/dtls/gstdtlsconnection.c b/ext/dtls/gstdtlsconnection.c
index c84e9f2..0d6d827 100644
--- a/ext/dtls/gstdtlsconnection.c
+++ b/ext/dtls/gstdtlsconnection.c
@@ -74,16 +74,17 @@
 
 static int connection_ex_index;
 
+static GstClock *system_clock;
+static void handle_timeout (gpointer data, gpointer user_data);
+
 struct _GstDtlsConnectionPrivate
 {
   SSL *ssl;
   BIO *bio;
-  GThread *thread;
 
   gboolean is_client;
   gboolean is_alive;
   gboolean keys_exported;
-  gboolean timeout_set;
 
   GMutex mutex;
   GCond condition;
@@ -92,6 +93,9 @@
   gint bio_buffer_offset;
 
   GClosure *send_closure;
+
+  gboolean timeout_pending;
+  GThreadPool *thread_pool;
 };
 
 static void gst_dtls_connection_finalize (GObject * gobject);
@@ -99,7 +103,6 @@
     const GValue *, GParamSpec *);
 
 static void log_state (GstDtlsConnection *, const gchar * str);
-static gpointer connection_timeout_thread_func (GstDtlsConnection *);
 static void export_srtp_keys (GstDtlsConnection *);
 static void openssl_poll (GstDtlsConnection *);
 static int openssl_verify_callback (int preverify_ok,
@@ -154,6 +157,8 @@
   _gst_dtls_init_openssl ();
 
   gobject_class->finalize = gst_dtls_connection_finalize;
+
+  system_clock = gst_system_clock_obtain ();
 }
 
 static void
@@ -164,14 +169,12 @@
 
   priv->ssl = NULL;
   priv->bio = NULL;
-  priv->thread = NULL;
 
   priv->send_closure = NULL;
 
   priv->is_client = FALSE;
   priv->is_alive = TRUE;
   priv->keys_exported = FALSE;
-  priv->timeout_set = FALSE;
 
   priv->bio_buffer = NULL;
   priv->bio_buffer_len = 0;
@@ -179,6 +182,13 @@
 
   g_mutex_init (&priv->mutex);
   g_cond_init (&priv->condition);
+
+  /* Thread pool for handling timeouts, we only need one thread for that
+   * really and share threads with all other thread pools around there as
+   * this is not going to happen very often */
+  priv->thread_pool = g_thread_pool_new (handle_timeout, self, 1, FALSE, NULL);
+  g_assert (priv->thread_pool);
+  priv->timeout_pending = FALSE;
 }
 
 static void
@@ -187,6 +197,8 @@
   GstDtlsConnection *self = GST_DTLS_CONNECTION (gobject);
   GstDtlsConnectionPrivate *priv = self->priv;
 
+  g_thread_pool_free (priv->thread_pool, TRUE, TRUE);
+  priv->thread_pool = NULL;
 
   SSL_free (priv->ssl);
   priv->ssl = NULL;
@@ -247,8 +259,6 @@
 {
   GstDtlsConnectionPrivate *priv;
 
-  g_return_if_fail (GST_IS_DTLS_CONNECTION (self));
-
   priv = self->priv;
 
   g_return_if_fail (priv->send_closure);
@@ -260,7 +270,6 @@
   GST_TRACE_OBJECT (self, "locked @ start");
 
   priv->is_alive = TRUE;
-  priv->timeout_set = FALSE;
   priv->bio_buffer = NULL;
   priv->bio_buffer_len = 0;
   priv->bio_buffer_offset = 0;
@@ -277,42 +286,114 @@
   openssl_poll (self);
 
   log_state (self, "first poll done");
-  priv->thread = NULL;
 
   GST_TRACE_OBJECT (self, "unlocking @ start");
   g_mutex_unlock (&priv->mutex);
 }
 
-void
-gst_dtls_connection_start_timeout (GstDtlsConnection * self)
+static void
+handle_timeout (gpointer data, gpointer user_data)
+{
+  GstDtlsConnection *self = user_data;
+  GstDtlsConnectionPrivate *priv;
+  gint ret;
+
+  priv = self->priv;
+
+  g_mutex_lock (&priv->mutex);
+  priv->timeout_pending = FALSE;
+  if (priv->is_alive) {
+    ret = DTLSv1_handle_timeout (priv->ssl);
+
+    GST_DEBUG_OBJECT (self, "handle timeout returned %d, is_alive: %d", ret,
+        priv->is_alive);
+
+    if (ret < 0) {
+      GST_WARNING_OBJECT (self, "handling timeout failed");
+    } else if (ret > 0) {
+      log_state (self, "handling timeout before poll");
+      openssl_poll (self);
+      log_state (self, "handling timeout after poll");
+    }
+  }
+  g_mutex_unlock (&priv->mutex);
+}
+
+static gboolean
+schedule_timeout_handling (GstClock * clock, GstClockTime time, GstClockID id,
+    gpointer user_data)
+{
+  GstDtlsConnection *self = user_data;
+
+  g_mutex_lock (&self->priv->mutex);
+  if (self->priv->is_alive && !self->priv->timeout_pending) {
+    self->priv->timeout_pending = TRUE;
+
+    GST_TRACE_OBJECT (self, "Schedule timeout now");
+    g_thread_pool_push (self->priv->thread_pool, GINT_TO_POINTER (0xc0ffee),
+        NULL);
+  }
+  g_mutex_unlock (&self->priv->mutex);
+
+  return TRUE;
+}
+
+static void
+gst_dtls_connection_check_timeout_locked (GstDtlsConnection * self)
 {
   GstDtlsConnectionPrivate *priv;
-  GError *error = NULL;
-  gchar *thread_name;
+  struct timeval timeout;
+  gint64 end_time, wait_time;
 
   g_return_if_fail (GST_IS_DTLS_CONNECTION (self));
 
   priv = self->priv;
 
-  thread_name = g_strdup_printf ("connection_thread_%p", self);
+  if (DTLSv1_get_timeout (priv->ssl, &timeout)) {
+    wait_time = timeout.tv_sec * G_USEC_PER_SEC + timeout.tv_usec;
+
+    GST_DEBUG_OBJECT (self, "waiting for %" G_GINT64_FORMAT " usec", wait_time);
+    if (wait_time) {
+      GstClockID clock_id;
+      GstClockReturn clock_return;
+
+      end_time = gst_clock_get_time (system_clock) + wait_time * GST_USECOND;
+
+      clock_id = gst_clock_new_single_shot_id (system_clock, end_time);
+      clock_return =
+          gst_clock_id_wait_async (clock_id, schedule_timeout_handling,
+          g_object_ref (self), (GDestroyNotify) g_object_unref);
+      g_assert (clock_return == GST_CLOCK_OK);
+      gst_clock_id_unref (clock_id);
+    } else {
+      if (self->priv->is_alive && !self->priv->timeout_pending) {
+        self->priv->timeout_pending = TRUE;
+        GST_TRACE_OBJECT (self, "Schedule timeout now");
+
+        g_thread_pool_push (self->priv->thread_pool, GINT_TO_POINTER (0xc0ffee),
+            NULL);
+      }
+    }
+  } else {
+    GST_DEBUG_OBJECT (self, "no timeout set");
+  }
+}
+
+void
+gst_dtls_connection_check_timeout (GstDtlsConnection * self)
+{
+  GstDtlsConnectionPrivate *priv;
+
+  g_return_if_fail (GST_IS_DTLS_CONNECTION (self));
+
+  priv = self->priv;
 
   GST_TRACE_OBJECT (self, "locking @ start_timeout");
   g_mutex_lock (&priv->mutex);
   GST_TRACE_OBJECT (self, "locked @ start_timeout");
-
-  GST_INFO_OBJECT (self, "starting connection timeout");
-  priv->thread = g_thread_try_new (thread_name,
-      (GThreadFunc) connection_timeout_thread_func, self, &error);
-  if (error) {
-    GST_WARNING_OBJECT (self, "error creating connection thread: %s (%d)",
-        error->message, error->code);
-    g_clear_error (&error);
-  }
-
-  g_free (thread_name);
-
-  GST_TRACE_OBJECT (self, "unlocking @ start_timeout");
+  gst_dtls_connection_check_timeout_locked (self);
   g_mutex_unlock (&priv->mutex);
+  GST_TRACE_OBJECT (self, "unlocking @ start_timeout");
 }
 
 void
@@ -360,11 +441,6 @@
   GST_TRACE_OBJECT (self, "unlocking @ close");
   g_mutex_unlock (&self->priv->mutex);
 
-  if (self->priv->thread) {
-    g_thread_join (self->priv->thread);
-    self->priv->thread = NULL;
-  }
-
   GST_DEBUG_OBJECT (self, "closed connection");
 }
 
@@ -497,70 +573,6 @@
       states, SSL_get_state (priv->ssl), SSL_state_string_long (priv->ssl));
 }
 
-static gpointer
-connection_timeout_thread_func (GstDtlsConnection * self)
-{
-  GstDtlsConnectionPrivate *priv = self->priv;
-  struct timeval timeout;
-  gint64 end_time, wait_time;
-  gint ret;
-
-  while (priv->is_alive) {
-    GST_TRACE_OBJECT (self, "locking @ timeout");
-    g_mutex_lock (&priv->mutex);
-    GST_TRACE_OBJECT (self, "locked @ timeout");
-
-    if (DTLSv1_get_timeout (priv->ssl, &timeout)) {
-      wait_time = timeout.tv_sec * G_USEC_PER_SEC + timeout.tv_usec;
-
-      if (wait_time) {
-        GST_DEBUG_OBJECT (self, "waiting for %" G_GINT64_FORMAT " usec",
-            wait_time);
-
-        end_time = g_get_monotonic_time () + wait_time;
-
-        GST_TRACE_OBJECT (self, "wait @ timeout");
-        g_cond_wait_until (&priv->condition, &priv->mutex, end_time);
-        GST_TRACE_OBJECT (self, "continued @ timeout");
-      }
-
-      ret = DTLSv1_handle_timeout (priv->ssl);
-
-      GST_DEBUG_OBJECT (self, "handle timeout returned %d, is_alive: %d", ret,
-          priv->is_alive);
-
-      if (ret < 0) {
-        GST_TRACE_OBJECT (self, "unlocking @ timeout failed");
-        g_mutex_unlock (&priv->mutex);
-        break;                  /* self failed after DTLS1_TMO_ALERT_COUNT (12) attempts */
-      }
-
-      if (ret > 0) {
-        log_state (self, "handling timeout before poll");
-        openssl_poll (self);
-        log_state (self, "handling timeout after poll");
-      }
-    } else {
-      GST_DEBUG_OBJECT (self, "waiting indefinitely");
-
-      priv->timeout_set = FALSE;
-
-      while (!priv->timeout_set && priv->is_alive) {
-        GST_TRACE_OBJECT (self, "wait @ timeout");
-        g_cond_wait (&priv->condition, &priv->mutex);
-      }
-      GST_TRACE_OBJECT (self, "continued @ timeout");
-    }
-
-    GST_TRACE_OBJECT (self, "unlocking @ timeout");
-    g_mutex_unlock (&priv->mutex);
-  }
-
-  log_state (self, "timeout thread exiting");
-
-  return NULL;
-}
-
 static void
 export_srtp_keys (GstDtlsConnection * self)
 {
@@ -577,16 +589,16 @@
   struct
   {
     Key client_key;
-    Key servgst_key;
+    Key server_key;
     Salt client_salt;
-    Salt servgst_salt;
+    Salt server_salt;
   } exported_keys;
 
   struct
   {
     Key key;
     Salt salt;
-  } client_key, servgst_key;
+  } client_key, server_key;
 
   SRTP_PROTECTION_PROFILE *profile;
   GstDtlsSrtpCipher cipher;
@@ -623,17 +635,17 @@
   }
 
   client_key.key = exported_keys.client_key;
-  servgst_key.key = exported_keys.servgst_key;
+  server_key.key = exported_keys.server_key;
   client_key.salt = exported_keys.client_salt;
-  servgst_key.salt = exported_keys.servgst_salt;
+  server_key.salt = exported_keys.server_salt;
 
   if (self->priv->is_client) {
     g_signal_emit (self, signals[SIGNAL_ON_ENCODER_KEY], 0, &client_key, cipher,
         auth);
-    g_signal_emit (self, signals[SIGNAL_ON_DECODER_KEY], 0, &servgst_key,
+    g_signal_emit (self, signals[SIGNAL_ON_DECODER_KEY], 0, &server_key,
         cipher, auth);
   } else {
-    g_signal_emit (self, signals[SIGNAL_ON_ENCODER_KEY], 0, &servgst_key,
+    g_signal_emit (self, signals[SIGNAL_ON_ENCODER_KEY], 0, &server_key,
         cipher, auth);
     g_signal_emit (self, signals[SIGNAL_ON_DECODER_KEY], 0, &client_key, cipher,
         auth);
@@ -853,8 +865,7 @@
     case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
     case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
       GST_LOG_OBJECT (self, "BIO: Timeout set");
-      priv->timeout_set = TRUE;
-      g_cond_signal (&priv->condition);
+      gst_dtls_connection_check_timeout_locked (self);
       return 1;
     case BIO_CTRL_RESET:
       priv->bio_buffer = NULL;
diff --git a/ext/dtls/gstdtlsconnection.h b/ext/dtls/gstdtlsconnection.h
index 1f901ac..6260b93 100644
--- a/ext/dtls/gstdtlsconnection.h
+++ b/ext/dtls/gstdtlsconnection.h
@@ -85,7 +85,7 @@
 GType gst_dtls_connection_get_type(void) G_GNUC_CONST;
 
 void gst_dtls_connection_start(GstDtlsConnection *, gboolean is_client);
-void gst_dtls_connection_start_timeout(GstDtlsConnection *);
+void gst_dtls_connection_check_timeout(GstDtlsConnection *);
 
 /*
  * Stops the connections, it is not required to call this function.
@@ -102,7 +102,7 @@
  * Sets the closure that will be called whenever data needs to be sent.
  *
  * The closure will get called with the following arguments:
- * void cb(GstDtlsConnection *, gpointer data, gint length, gpointer usgst_data)
+ * void cb(GstDtlsConnection *, gpointer data, gint length, gpointer user_data)
  */
 void gst_dtls_connection_set_send_callback(GstDtlsConnection *, GClosure *);
 
diff --git a/ext/dtls/gstdtlsdec.c b/ext/dtls/gstdtlsdec.c
index a8aa806..0881a8f 100644
--- a/ext/dtls/gstdtlsdec.c
+++ b/ext/dtls/gstdtlsdec.c
@@ -96,9 +96,11 @@
 
 static void on_key_received (GstDtlsConnection *, gpointer key, guint cipher,
     guint auth, GstDtlsDec *);
-static gboolean on_pegst_certificate_received (GstDtlsConnection *, gchar * pem,
+static gboolean on_peer_certificate_received (GstDtlsConnection *, gchar * pem,
     GstDtlsDec *);
 static GstFlowReturn sink_chain (GstPad *, GstObject * parent, GstBuffer *);
+static GstFlowReturn sink_chain_list (GstPad *, GstObject * parent,
+    GstBufferList *);
 
 static GstDtlsAgent *get_agent_by_pem (const gchar * pem);
 static void agent_weak_ref_notify (gchar * pem, GstDtlsAgent *);
@@ -150,7 +152,7 @@
   properties[PROP_DECODER_KEY] =
       g_param_spec_boxed ("decoder-key",
       "Decoder key",
-      "SRTP key that should be used by the decider",
+      "SRTP key that should be used by the decoder",
       GST_TYPE_CAPS, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
 
   properties[PROP_SRTP_CIPHER] =
@@ -189,9 +191,9 @@
   self->agent = get_agent_by_pem (NULL);
   self->connection_id = NULL;
   self->connection = NULL;
-  self->pegst_pem = NULL;
+  self->peer_pem = NULL;
 
-  self->decodgst_key = NULL;
+  self->decoder_key = NULL;
   self->srtp_cipher = DEFAULT_SRTP_CIPHER;
   self->srtp_auth = DEFAULT_SRTP_AUTH;
 
@@ -202,6 +204,7 @@
   g_return_if_fail (sink);
 
   gst_pad_set_chain_function (sink, GST_DEBUG_FUNCPTR (sink_chain));
+  gst_pad_set_chain_list_function (sink, GST_DEBUG_FUNCPTR (sink_chain_list));
 
   gst_element_add_pad (GST_ELEMENT (self), sink);
 }
@@ -211,16 +214,16 @@
 {
   GstDtlsDec *self = GST_DTLS_DEC (object);
 
-  if (self->decodgst_key) {
-    gst_buffer_unref (self->decodgst_key);
-    self->decodgst_key = NULL;
+  if (self->decoder_key) {
+    gst_buffer_unref (self->decoder_key);
+    self->decoder_key = NULL;
   }
 
   g_free (self->connection_id);
   self->connection_id = NULL;
 
-  g_free (self->pegst_pem);
-  self->pegst_pem = NULL;
+  g_free (self->peer_pem);
+  self->peer_pem = NULL;
 
   g_mutex_clear (&self->src_mutex);
 
@@ -287,10 +290,10 @@
           gst_dtls_agent_get_certificate_pem (self->agent));
       break;
     case PROP_PEER_PEM:
-      g_value_set_string (value, self->pegst_pem);
+      g_value_set_string (value, self->peer_pem);
       break;
     case PROP_DECODER_KEY:
-      g_value_set_boxed (value, self->decodgst_key);
+      g_value_set_boxed (value, self->decoder_key);
       break;
     case PROP_SRTP_CIPHER:
       g_value_set_uint (value, self->srtp_cipher);
@@ -315,7 +318,7 @@
         g_signal_connect_object (self->connection,
             "on-decoder-key", G_CALLBACK (on_key_received), self, 0);
         g_signal_connect_object (self->connection,
-            "on-peer-certificate", G_CALLBACK (on_pegst_certificate_received),
+            "on-peer-certificate", G_CALLBACK (on_peer_certificate_received),
             self, 0);
       } else {
         GST_WARNING_OBJECT (self,
@@ -337,6 +340,7 @@
     GstPadTemplate * tmpl, const gchar * name, const GstCaps * caps)
 {
   GstDtlsDec *self = GST_DTLS_DEC (element);
+  GstPad *pad;
 
   GST_DEBUG_OBJECT (element, "requesting pad");
 
@@ -344,20 +348,26 @@
   g_return_val_if_fail (tmpl->direction == GST_PAD_SRC, NULL);
 
   g_mutex_lock (&self->src_mutex);
-
-  self->src = gst_pad_new_from_template (tmpl, name);
-  g_return_val_if_fail (self->src, NULL);
-
-  if (caps) {
-    g_object_set (self->src, "caps", caps, NULL);
+  if (self->src) {
+    GST_ERROR_OBJECT (self, "Pad %s:%s exists already",
+        GST_DEBUG_PAD_NAME (self->src));
+    g_mutex_unlock (&self->src_mutex);
+    return NULL;
   }
 
-  gst_pad_set_active (self->src, TRUE);
-  gst_element_add_pad (element, self->src);
-
+  self->src = pad = gst_pad_new_from_template (tmpl, name);
+  gst_object_ref (pad);
   g_mutex_unlock (&self->src_mutex);
 
-  return self->src;
+  gst_pad_set_active (pad, TRUE);
+
+  if (caps)
+    gst_pad_set_caps (pad, (GstCaps *) caps);
+
+  gst_element_add_pad (element, pad);
+  gst_object_unref (pad);
+
+  return pad;
 }
 
 static void
@@ -365,16 +375,17 @@
 {
   GstDtlsDec *self = GST_DTLS_DEC (element);
 
-  g_mutex_lock (&self->src_mutex);
-
   g_return_if_fail (self->src == pad);
-  gst_element_remove_pad (element, self->src);
+
+  g_mutex_lock (&self->src_mutex);
+  gst_object_unref (self->src);
   self->src = NULL;
+  g_mutex_unlock (&self->src_mutex);
+
+  gst_element_remove_pad (element, pad);
 
   GST_DEBUG_OBJECT (self, "releasing src pad");
 
-  g_mutex_unlock (&self->src_mutex);
-
   GST_ELEMENT_GET_CLASS (element)->release_pad (element, pad);
 }
 
@@ -391,7 +402,7 @@
   self->srtp_auth = auth;
 
   key_dup = g_memdup (key, GST_DTLS_SRTP_MASTER_KEY_LENGTH);
-  self->decodgst_key =
+  self->decoder_key =
       gst_buffer_new_wrapped (key_dup, GST_DTLS_SRTP_MASTER_KEY_LENGTH);
 
   key_str = g_base64_encode (key, GST_DTLS_SRTP_MASTER_KEY_LENGTH);
@@ -402,7 +413,7 @@
 }
 
 static gboolean
-signal_pegst_certificate_received (GWeakRef * ref)
+signal_peer_certificate_received (GWeakRef * ref)
 {
   GstDtlsDec *self;
 
@@ -421,7 +432,7 @@
 }
 
 static gboolean
-on_pegst_certificate_received (GstDtlsConnection * connection, gchar * pem,
+on_peer_certificate_received (GstDtlsConnection * connection, gchar * pem,
     GstDtlsDec * self)
 {
   GWeakRef *ref;
@@ -430,23 +441,101 @@
 
   GST_DEBUG_OBJECT (self, "Received peer certificate PEM: \n%s", pem);
 
-  self->pegst_pem = g_strdup (pem);
+  self->peer_pem = g_strdup (pem);
 
   ref = g_new (GWeakRef, 1);
   g_weak_ref_init (ref, self);
 
-  g_idle_add ((GSourceFunc) signal_pegst_certificate_received, ref);
+  g_idle_add ((GSourceFunc) signal_peer_certificate_received, ref);
 
   return TRUE;
 }
 
+static gint
+process_buffer (GstDtlsDec * self, GstBuffer * buffer)
+{
+  GstMapInfo map_info;
+  gint size;
+
+  if (!gst_buffer_map (buffer, &map_info, GST_MAP_READWRITE))
+    return 0;
+
+  if (!map_info.size) {
+    gst_buffer_unmap (buffer, &map_info);
+    return 0;
+  }
+
+  size =
+      gst_dtls_connection_process (self->connection, map_info.data,
+      map_info.size);
+  gst_buffer_unmap (buffer, &map_info);
+
+  if (size <= 0)
+    return size;
+
+  gst_buffer_set_size (buffer, size);
+
+  return size;
+}
+
+static gboolean
+process_buffer_from_list (GstBuffer ** buffer, guint idx, gpointer user_data)
+{
+  GstDtlsDec *self = GST_DTLS_DEC (user_data);
+  gint size;
+
+  *buffer = gst_buffer_make_writable (*buffer);
+  size = process_buffer (self, *buffer);
+  if (size <= 0)
+    gst_buffer_replace (buffer, NULL);
+
+  return TRUE;
+}
+
+static GstFlowReturn
+sink_chain_list (GstPad * pad, GstObject * parent, GstBufferList * list)
+{
+  GstDtlsDec *self = GST_DTLS_DEC (parent);
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstPad *other_pad;
+
+  list = gst_buffer_list_make_writable (list);
+  gst_buffer_list_foreach (list, process_buffer_from_list, self);
+
+  if (gst_buffer_list_length (list) == 0) {
+    GST_DEBUG_OBJECT (self, "Not produced any buffers");
+    gst_buffer_list_unref (list);
+
+    return GST_FLOW_OK;
+  }
+
+  g_mutex_lock (&self->src_mutex);
+  other_pad = self->src;
+  if (other_pad)
+    gst_object_ref (other_pad);
+  g_mutex_unlock (&self->src_mutex);
+
+  if (other_pad) {
+    GST_LOG_OBJECT (self, "decoded buffer list with length %u, pushing",
+        gst_buffer_list_length (list));
+    ret = gst_pad_push_list (other_pad, list);
+    gst_object_unref (other_pad);
+  } else {
+    GST_LOG_OBJECT (self, "dropped buffer list with length %d, not linked",
+        gst_buffer_list_length (list));
+    gst_buffer_list_unref (list);
+  }
+
+  return ret;
+}
+
 static GstFlowReturn
 sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   GstDtlsDec *self = GST_DTLS_DEC (parent);
   GstFlowReturn ret = GST_FLOW_OK;
-  GstMapInfo map_info = GST_MAP_INFO_INIT;
   gint size;
+  GstPad *other_pad;
 
   if (!self->agent) {
     gst_buffer_unref (buffer);
@@ -456,17 +545,8 @@
   GST_DEBUG_OBJECT (self, "received buffer from %s with length %zd",
       self->connection_id, gst_buffer_get_size (buffer));
 
-  gst_buffer_map (buffer, &map_info, GST_MAP_READWRITE);
-
-  if (!map_info.size) {
-    gst_buffer_unmap (buffer, &map_info);
-    return GST_FLOW_OK;
-  }
-
-  size =
-      gst_dtls_connection_process (self->connection, map_info.data,
-      map_info.size);
-  gst_buffer_unmap (buffer, &map_info);
+  buffer = gst_buffer_make_writable (buffer);
+  size = process_buffer (self, buffer);
 
   if (size <= 0) {
     gst_buffer_unref (buffer);
@@ -475,18 +555,20 @@
   }
 
   g_mutex_lock (&self->src_mutex);
+  other_pad = self->src;
+  if (other_pad)
+    gst_object_ref (other_pad);
+  g_mutex_unlock (&self->src_mutex);
 
-  if (self->src) {
-    gst_buffer_set_size (buffer, size);
+  if (other_pad) {
     GST_LOG_OBJECT (self, "decoded buffer with length %d, pushing", size);
-    ret = gst_pad_push (self->src, buffer);
+    ret = gst_pad_push (other_pad, buffer);
+    gst_object_unref (other_pad);
   } else {
     GST_LOG_OBJECT (self, "dropped buffer with length %d, not linked", size);
     gst_buffer_unref (buffer);
   }
 
-  g_mutex_unlock (&self->src_mutex);
-
   return ret;
 }
 
diff --git a/ext/dtls/gstdtlsdec.h b/ext/dtls/gstdtlsdec.h
index 2c5fc4a..8d2560e 100644
--- a/ext/dtls/gstdtlsdec.h
+++ b/ext/dtls/gstdtlsdec.h
@@ -57,9 +57,9 @@
     GstDtlsConnection *connection;
     GMutex connection_mutex;
     gchar *connection_id;
-    gchar *pegst_pem;
+    gchar *peer_pem;
 
-    GstBuffer *decodgst_key;
+    GstBuffer *decoder_key;
     guint srtp_cipher;
     guint srtp_auth;
 };
diff --git a/ext/dtls/gstdtlsenc.c b/ext/dtls/gstdtlsenc.c
index ff4b4d2..477af10 100644
--- a/ext/dtls/gstdtlsenc.c
+++ b/ext/dtls/gstdtlsenc.c
@@ -182,12 +182,11 @@
 
   self->is_client = DEFAULT_IS_CLIENT;
 
-  self->encodgst_key = NULL;
+  self->encoder_key = NULL;
   self->srtp_cipher = DEFAULT_SRTP_CIPHER;
   self->srtp_auth = DEFAULT_SRTP_AUTH;
 
-  self->queue = g_ptr_array_sized_new (INITIAL_QUEUE_SIZE);
-
+  g_queue_init (&self->queue);
   g_mutex_init (&self->queue_lock);
   g_cond_init (&self->queue_cond_add);
 
@@ -205,17 +204,14 @@
 {
   GstDtlsEnc *self = GST_DTLS_ENC (object);
 
-  if (self->encodgst_key) {
-    gst_buffer_unref (self->encodgst_key);
-    self->encodgst_key = NULL;
+  if (self->encoder_key) {
+    gst_buffer_unref (self->encoder_key);
+    self->encoder_key = NULL;
   }
 
   g_mutex_lock (&self->queue_lock);
-
-  g_ptr_array_set_free_func (self->queue, (GDestroyNotify) gst_buffer_unref);
-  g_ptr_array_unref (self->queue);
-  self->queue = NULL;
-
+  g_queue_foreach (&self->queue, (GFunc) gst_buffer_unref, NULL);
+  g_queue_clear (&self->queue);
   g_mutex_unlock (&self->queue_lock);
 
   g_mutex_clear (&self->queue_lock);
@@ -258,7 +254,7 @@
       g_value_set_boolean (value, self->is_client);
       break;
     case PROP_ENCODER_KEY:
-      g_value_set_boxed (value, self->encodgst_key);
+      g_value_set_boxed (value, self->encoder_key);
       break;
     case PROP_SRTP_CIPHER:
       g_value_set_uint (value, self->srtp_cipher);
@@ -300,15 +296,8 @@
         return GST_STATE_CHANGE_FAILURE;
       }
       break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      GST_DEBUG_OBJECT (self, "starting connection %s", self->connection_id);
-      gst_dtls_connection_start (self->connection, self->is_client);
-
-      gst_pad_set_active (self->src, TRUE);
-      break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
       GST_DEBUG_OBJECT (self, "stopping connection %s", self->connection_id);
-      gst_pad_set_active (self->src, FALSE);
 
       gst_dtls_connection_stop (self->connection);
       break;
@@ -328,6 +317,15 @@
 
   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
 
+  switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      GST_DEBUG_OBJECT (self, "starting connection %s", self->connection_id);
+      gst_dtls_connection_start (self->connection, self->is_client);
+      break;
+    default:
+      break;
+  }
+
   return ret;
 }
 
@@ -370,6 +368,7 @@
   if (active) {
     GST_DEBUG_OBJECT (self, "src pad activating in push mode");
 
+    self->flushing = FALSE;
     self->send_initial_events = TRUE;
     success =
         gst_pad_start_task (pad, (GstTaskFunction) src_task_loop, self->src,
@@ -381,7 +380,9 @@
     GST_DEBUG_OBJECT (self, "deactivating src pad");
 
     g_mutex_lock (&self->queue_lock);
-    GST_PAD_MODE (pad) = GST_PAD_MODE_NONE;
+    g_queue_foreach (&self->queue, (GFunc) gst_buffer_unref, NULL);
+    g_queue_clear (&self->queue);
+    self->flushing = TRUE;
     g_cond_signal (&self->queue_cond_add);
     g_mutex_unlock (&self->queue_lock);
     success = gst_pad_stop_task (pad);
@@ -398,26 +399,26 @@
 {
   GstDtlsEnc *self = GST_DTLS_ENC (GST_PAD_PARENT (pad));
   GstFlowReturn ret;
-  GstPad *peer;
-  gboolean pegst_is_active;
+  GstBuffer *buffer;
+  gboolean check_connection_timeout = FALSE;
 
   GST_TRACE_OBJECT (self, "src loop: acquiring lock");
   g_mutex_lock (&self->queue_lock);
   GST_TRACE_OBJECT (self, "src loop: acquired lock");
 
-  if (!gst_pad_is_active (pad)) {
+  if (self->flushing) {
     GST_LOG_OBJECT (self, "src task loop entered on inactive pad");
     GST_TRACE_OBJECT (self, "src loop: releasing lock");
     g_mutex_unlock (&self->queue_lock);
     return;
   }
 
-  while (!self->queue->len) {
+  while (g_queue_is_empty (&self->queue)) {
     GST_TRACE_OBJECT (self, "src loop: queue empty, waiting for add");
     g_cond_wait (&self->queue_cond_add, &self->queue_lock);
     GST_TRACE_OBJECT (self, "src loop: add signaled");
 
-    if (!gst_pad_is_active (pad)) {
+    if (self->flushing) {
       GST_LOG_OBJECT (self, "pad inactive, task returning");
       GST_TRACE_OBJECT (self, "src loop: releasing lock");
       g_mutex_unlock (&self->queue_lock);
@@ -426,47 +427,35 @@
   }
   GST_TRACE_OBJECT (self, "src loop: queue has element");
 
-  peer = gst_pad_get_peer (pad);
-  pegst_is_active = gst_pad_is_active (peer);
-  gst_object_unref (peer);
+  buffer = g_queue_pop_head (&self->queue);
+  g_mutex_unlock (&self->queue_lock);
 
-  if (pegst_is_active) {
-    GstBuffer *buffer;
-    gboolean start_connection_timeout = FALSE;
+  if (self->send_initial_events) {
+    GstSegment segment;
+    gchar s_id[32];
+    GstCaps *caps;
 
-    if (self->send_initial_events) {
-      GstSegment segment;
-      gchar s_id[32];
-      GstCaps *caps;
+    self->send_initial_events = FALSE;
 
-      g_snprintf (s_id, sizeof (s_id), "dtlsenc-%08x", g_random_int ());
-      gst_pad_push_event (self->src, gst_event_new_stream_start (s_id));
-      caps = gst_caps_new_empty_simple ("application/x-dtls");
-      gst_pad_push_event (self->src, gst_event_new_caps (caps));
-      gst_caps_unref (caps);
-      gst_segment_init (&segment, GST_FORMAT_BYTES);
-      gst_pad_push_event (self->src, gst_event_new_segment (&segment));
-      self->send_initial_events = FALSE;
-      start_connection_timeout = TRUE;
-    }
+    g_snprintf (s_id, sizeof (s_id), "dtlsenc-%08x", g_random_int ());
+    gst_pad_push_event (self->src, gst_event_new_stream_start (s_id));
+    caps = gst_caps_new_empty_simple ("application/x-dtls");
+    gst_pad_push_event (self->src, gst_event_new_caps (caps));
+    gst_caps_unref (caps);
+    gst_segment_init (&segment, GST_FORMAT_BYTES);
+    gst_pad_push_event (self->src, gst_event_new_segment (&segment));
+    check_connection_timeout = TRUE;
+  }
 
-    buffer = g_ptr_array_remove_index (self->queue, 0);
+  GST_TRACE_OBJECT (self, "src loop: releasing lock");
 
-    GST_TRACE_OBJECT (self, "src loop: releasing lock");
-    g_mutex_unlock (&self->queue_lock);
+  ret = gst_pad_push (self->src, buffer);
+  if (check_connection_timeout)
+    gst_dtls_connection_check_timeout (self->connection);
 
-    ret = gst_pad_push (self->src, buffer);
-    if (start_connection_timeout)
-      gst_dtls_connection_start_timeout (self->connection);
-
-    if (G_UNLIKELY (ret != GST_FLOW_OK)) {
-      GST_WARNING_OBJECT (self, "failed to push buffer on src pad: %s",
-          gst_flow_get_name (ret));
-    }
-  } else {
-    g_warn_if_reached ();
-    GST_TRACE_OBJECT (self, "src loop: releasing lock");
-    g_mutex_unlock (&self->queue_lock);
+  if (G_UNLIKELY (ret != GST_FLOW_OK)) {
+    GST_WARNING_OBJECT (self, "failed to push buffer on src pad: %s",
+        gst_flow_get_name (ret));
   }
 }
 
@@ -511,7 +500,7 @@
   self->srtp_auth = auth;
 
   key_dup = g_memdup (key, GST_DTLS_SRTP_MASTER_KEY_LENGTH);
-  self->encodgst_key =
+  self->encoder_key =
       gst_buffer_new_wrapped (key_dup, GST_DTLS_SRTP_MASTER_KEY_LENGTH);
 
   key_str = g_base64_encode (key, GST_DTLS_SRTP_MASTER_KEY_LENGTH);
@@ -536,7 +525,7 @@
   g_mutex_lock (&self->queue_lock);
   GST_TRACE_OBJECT (self, "send data: acquired lock");
 
-  g_ptr_array_add (self->queue, buffer);
+  g_queue_push_tail (&self->queue, buffer);
 
   GST_TRACE_OBJECT (self, "send data: signaling add");
   g_cond_signal (&self->queue_cond_add);
diff --git a/ext/dtls/gstdtlsenc.h b/ext/dtls/gstdtlsenc.h
index 6dc6bbd..622936f 100644
--- a/ext/dtls/gstdtlsenc.h
+++ b/ext/dtls/gstdtlsenc.h
@@ -47,16 +47,17 @@
 
     GstPad *src;
 
-    GPtrArray *queue;
+    GQueue queue;
     GMutex queue_lock;
     GCond queue_cond_add;
+    gboolean flushing;
 
     GstDtlsConnection *connection;
     gchar *connection_id;
 
     gboolean is_client;
 
-    GstBuffer *encodgst_key;
+    GstBuffer *encoder_key;
     guint srtp_cipher;
     guint srtp_auth;
 
diff --git a/ext/dtls/gstdtlssrtpdec.c b/ext/dtls/gstdtlssrtpdec.c
index 347fefd..d80328d 100644
--- a/ext/dtls/gstdtlssrtpdec.c
+++ b/ext/dtls/gstdtlssrtpdec.c
@@ -37,10 +37,17 @@
     GST_STATIC_CAPS_ANY);
 
 static GstStaticPadTemplate rtp_src_template =
-    GST_STATIC_PAD_TEMPLATE ("rtp_src",
+GST_STATIC_PAD_TEMPLATE ("rtp_src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("application/x-rtp;application/x-rtcp")
+    GST_STATIC_CAPS ("application/x-rtp")
+    );
+
+static GstStaticPadTemplate rtcp_src_template =
+GST_STATIC_PAD_TEMPLATE ("rtcp_src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("application/x-rtcp")
     );
 
 static GstStaticPadTemplate data_src_template =
@@ -77,18 +84,15 @@
 
 static GstPad *gst_dtls_srtp_dec_request_new_pad (GstElement *,
     GstPadTemplate *, const gchar * name, const GstCaps *);
-static GstCaps *on_decodgst_request_key (GstElement * srtp_decoder, guint ssrc,
+static GstCaps *on_decoder_request_key (GstElement * srtp_decoder, guint ssrc,
     GstDtlsSrtpBin *);
-static void on_pegst_pem (GstElement * srtp_decoder, GParamSpec * pspec,
+static void on_peer_pem (GstElement * srtp_decoder, GParamSpec * pspec,
     GstDtlsSrtpDec * self);
 
 static void gst_dtls_srtp_dec_remove_dtls_element (GstDtlsSrtpBin *);
-static GstPadProbeReturn remove_dtls_decodgst_probe_callback (GstPad *,
+static GstPadProbeReturn remove_dtls_decoder_probe_callback (GstPad *,
     GstPadProbeInfo *, GstElement *);
 
-static GstPadProbeReturn drop_funnel_rtcp_caps (GstPad *, GstPadProbeInfo *,
-    gpointer);
-
 static void
 gst_dtls_srtp_dec_class_init (GstDtlsSrtpDecClass * klass)
 {
@@ -130,6 +134,8 @@
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&rtp_src_template));
   gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&rtcp_src_template));
+  gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&data_src_template));
 
   gst_element_class_set_static_metadata (element_class,
@@ -144,19 +150,19 @@
 {
   GstElementClass *klass = GST_ELEMENT_GET_CLASS (GST_ELEMENT (self));
   GstPadTemplate *templ;
-  GstPad *target_pad, *ghost_pad, *pad;
+  GstPad *target_pad, *ghost_pad;
   gboolean ret;
 
 /*
-                                 +--------------------+
-            +--------------+  .-o|       dtlsdec      |o-R----------data
-            |          dtls|o-'  +--------------------+
+                                 +-----------+
+            +--------------+  .-o|  dtlsdec  |o-R----data
+            |          dtls|o-'  +-----------+
     sink---o|  dtlsdemux   |
-            |       srt(c)p|o-.  +-----------+     +-----------+
-            +--------------+  '-o|srtp    rtp|o---o|rtp        |
-                                 |  srtpdec  |     |   funnel  |o---rt(c)p
-                                o|srtcp  rtcp|o---o|rtcp       |
-                                 +-----------+     +-----------+
+            |       srt(c)p|o-.  +-----------+
+            +--------------+  '-o|srtp    rtp|o------rtp
+                                 |  srtpdec  |
+                                o|srtcp  rtcp|o------rtcp
+                                 +-----------+
 */
 
   self->srtp_dec = gst_element_factory_make ("srtpdec", "srtp-decoder");
@@ -176,15 +182,9 @@
     GST_ERROR_OBJECT (self, "failed to create dtls_dec");
     return;
   }
-  self->funnel = gst_element_factory_make ("funnel", "funnel");
-  if (!self->funnel) {
-    GST_ERROR_OBJECT (self, "failed to create funnel");
-    return;
-  }
 
   gst_bin_add_many (GST_BIN (self),
-      self->dtls_srtp_demux,
-      self->bin.dtls_element, self->srtp_dec, self->funnel, NULL);
+      self->dtls_srtp_demux, self->bin.dtls_element, self->srtp_dec, NULL);
 
   ret =
       gst_element_link_pads (self->dtls_srtp_demux, "dtls_src",
@@ -194,21 +194,9 @@
       gst_element_link_pads (self->dtls_srtp_demux, "rtp_src", self->srtp_dec,
       "rtp_sink");
   g_return_if_fail (ret);
-  ret =
-      gst_element_link_pads (self->srtp_dec, "rtp_src", self->funnel, "sink_0");
-  g_return_if_fail (ret);
-  ret =
-      gst_element_link_pads (self->srtp_dec, "rtcp_src", self->funnel,
-      "sink_1");
-  g_return_if_fail (ret);
-
-  pad = gst_element_get_static_pad (self->funnel, "sink_1");
-  gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
-      drop_funnel_rtcp_caps, NULL, NULL);
-  gst_object_unref (pad);
 
   templ = gst_element_class_get_pad_template (klass, "rtp_src");
-  target_pad = gst_element_get_static_pad (self->funnel, "src");
+  target_pad = gst_element_get_static_pad (self->srtp_dec, "rtp_src");
   ghost_pad = gst_ghost_pad_new_from_template ("rtp_src", target_pad, templ);
   gst_object_unref (target_pad);
   g_return_if_fail (ghost_pad);
@@ -216,6 +204,15 @@
   ret = gst_element_add_pad (GST_ELEMENT (self), ghost_pad);
   g_return_if_fail (ret);
 
+  templ = gst_element_class_get_pad_template (klass, "rtcp_src");
+  target_pad = gst_element_get_static_pad (self->srtp_dec, "rtcp_src");
+  ghost_pad = gst_ghost_pad_new_from_template ("rtcp_src", target_pad, templ);
+  gst_object_unref (target_pad);
+  g_return_if_fail (ghost_pad);
+
+  ret = gst_element_add_pad (GST_ELEMENT (self), ghost_pad);
+  g_return_if_fail (ret);
+
   templ = gst_element_class_get_pad_template (klass, "sink");
   target_pad = gst_element_get_static_pad (self->dtls_srtp_demux, "sink");
   ghost_pad = gst_ghost_pad_new_from_template ("sink", target_pad, templ);
@@ -226,9 +223,9 @@
   g_return_if_fail (ret);
 
   g_signal_connect (self->srtp_dec, "request-key",
-      G_CALLBACK (on_decodgst_request_key), self);
+      G_CALLBACK (on_decoder_request_key), self);
   g_signal_connect (self->bin.dtls_element, "notify::peer-pem",
-      G_CALLBACK (on_pegst_pem), self);
+      G_CALLBACK (on_peer_pem), self);
 }
 
 static void
@@ -318,7 +315,7 @@
 }
 
 static GstCaps *
-on_decodgst_request_key (GstElement * srtp_decoder,
+on_decoder_request_key (GstElement * srtp_decoder,
     guint ssrc, GstDtlsSrtpBin * bin)
 {
   GstCaps *key_caps;
@@ -385,13 +382,15 @@
     }
 
     return key_caps;
+  } else {
+    GST_WARNING_OBJECT (bin, "no srtp key available yet");
   }
 
   return NULL;
 }
 
 static void
-on_pegst_pem (GstElement * srtp_decoder, GParamSpec * pspec,
+on_peer_pem (GstElement * srtp_decoder, GParamSpec * pspec,
     GstDtlsSrtpDec * self)
 {
   g_return_if_fail (self);
@@ -412,7 +411,7 @@
   demux_pad = gst_element_get_static_pad (self->dtls_srtp_demux, "dtls_src");
 
   id = gst_pad_add_probe (demux_pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
-      (GstPadProbeCallback) remove_dtls_decodgst_probe_callback,
+      (GstPadProbeCallback) remove_dtls_decoder_probe_callback,
       bin->dtls_element, NULL);
   g_return_if_fail (id);
   bin->dtls_element = NULL;
@@ -425,7 +424,7 @@
 }
 
 static GstPadProbeReturn
-remove_dtls_decodgst_probe_callback (GstPad * pad,
+remove_dtls_decoder_probe_callback (GstPad * pad,
     GstPadProbeInfo * info, GstElement * element)
 {
   gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info));
@@ -435,40 +434,3 @@
 
   return GST_PAD_PROBE_OK;
 }
-
-static GstPadProbeReturn
-drop_funnel_rtcp_caps (GstPad * pad, GstPadProbeInfo * info, gpointer data)
-{
-  /* FIXME: This is needed for setting the proper caps until
-   * GStreamer supports MIXED caps or another mechanism to
-   * prevent renegotiation all the time when two different caps
-   * are going over the same pad
-   */
-  if (GST_EVENT_TYPE (info->data) == GST_EVENT_CAPS) {
-    GstCaps *caps, *peercaps;
-    GstStructure *s;
-
-    gst_event_parse_caps (GST_EVENT (info->data), &caps);
-    s = gst_caps_get_structure (caps, 0);
-    if (gst_structure_has_name (s, "application/x-rtcp")) {
-      peercaps = gst_pad_query_caps (pad, NULL);
-
-      /* If the peer does not accept RTCP, we are linked to
-       * the RTP sinkpad of rtpbin. In that case we have to
-       * drop the RTCP caps and assume that we sent RTP caps
-       * before here, which is very likely but not guaranteed
-       * if for some reason we receive RTCP before any RTP.
-       * In that unlikely case we will get event misordering
-       * warnings later, instead of getting them always as
-       * happens now.
-       */
-      if (peercaps && !gst_caps_is_subset (caps, peercaps)) {
-        gst_caps_unref (peercaps);
-        return GST_PAD_PROBE_DROP;
-      }
-      gst_caps_replace (&peercaps, NULL);
-    }
-  }
-
-  return GST_PAD_PROBE_OK;
-}
diff --git a/ext/dtls/gstdtlssrtpdec.h b/ext/dtls/gstdtlssrtpdec.h
index d32a44b..3d64c15 100644
--- a/ext/dtls/gstdtlssrtpdec.h
+++ b/ext/dtls/gstdtlssrtpdec.h
@@ -46,7 +46,6 @@
 
     GstElement *dtls_srtp_demux;
     GstElement *srtp_dec;
-    GstElement *funnel;
 };
 
 struct _GstDtlsSrtpDecClass {
diff --git a/ext/dtls/gstdtlssrtpenc.c b/ext/dtls/gstdtlssrtpenc.c
index 35bf707..d7055b8 100644
--- a/ext/dtls/gstdtlssrtpenc.c
+++ b/ext/dtls/gstdtlssrtpenc.c
@@ -99,7 +99,7 @@
 static void on_key_received (GObject * encoder, GstDtlsSrtpEnc *);
 
 static void gst_dtls_srtp_enc_remove_dtls_element (GstDtlsSrtpBin *);
-static GstPadProbeReturn remove_dtls_encodgst_probe_callback (GstPad *,
+static GstPadProbeReturn remove_dtls_encoder_probe_callback (GstPad *,
     GstPadProbeInfo *, GstElement *);
 
 static void
@@ -410,7 +410,7 @@
 gst_dtls_srtp_enc_remove_dtls_element (GstDtlsSrtpBin * bin)
 {
   GstDtlsSrtpEnc *self = GST_DTLS_SRTP_ENC (bin);
-  GstPad *dtls_sink_pad, *pegst_pad;
+  GstPad *dtls_sink_pad, *peer_pad;
   gulong id;
   guint rtp_cipher = 1, rtcp_cipher = 1, rtp_auth = 1, rtcp_auth = 1;
 
@@ -436,26 +436,26 @@
     return;
   }
 
-  pegst_pad = gst_pad_get_peer (dtls_sink_pad);
-  g_return_if_fail (pegst_pad);
+  peer_pad = gst_pad_get_peer (dtls_sink_pad);
+  g_return_if_fail (peer_pad);
   gst_object_unref (dtls_sink_pad);
   dtls_sink_pad = NULL;
 
-  id = gst_pad_add_probe (pegst_pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
-      (GstPadProbeCallback) remove_dtls_encodgst_probe_callback,
+  id = gst_pad_add_probe (peer_pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
+      (GstPadProbeCallback) remove_dtls_encoder_probe_callback,
       bin->dtls_element, NULL);
   g_return_if_fail (id);
   bin->dtls_element = NULL;
 
-  gst_pad_push_event (pegst_pad,
+  gst_pad_push_event (peer_pad,
       gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
           gst_structure_new_empty ("dummy")));
 
-  gst_object_unref (pegst_pad);
+  gst_object_unref (peer_pad);
 }
 
 static GstPadProbeReturn
-remove_dtls_encodgst_probe_callback (GstPad * pad,
+remove_dtls_encoder_probe_callback (GstPad * pad,
     GstPadProbeInfo * info, GstElement * element)
 {
   gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info));
diff --git a/ext/dtls/gstdtlssrtpenc.h b/ext/dtls/gstdtlssrtpenc.h
index 5cc07ee..5dd603d 100644
--- a/ext/dtls/gstdtlssrtpenc.h
+++ b/ext/dtls/gstdtlssrtpenc.h
@@ -56,7 +56,7 @@
 
 gboolean gst_dtls_srtp_enc_plugin_init(GstPlugin *);
 
-guint gst_dtls_srtp_enc_get_ciphgst_value_by_nick(const gchar *ciphgst_nick);
+guint gst_dtls_srtp_enc_get_cipher_value_by_nick(const gchar *cipher_nick);
 guint gst_dtls_srtp_enc_get_auth_value_by_nick(const gchar *auth_nick);
 
 G_END_DECLS
diff --git a/ext/faac/Makefile.am b/ext/faac/Makefile.am
index 8727a21..007c66d 100644
--- a/ext/faac/Makefile.am
+++ b/ext/faac/Makefile.am
@@ -11,18 +11,3 @@
 libgstfaac_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
 
 noinst_HEADERS = gstfaac.h
-
-Android.mk: Makefile.am $(BUILT_SOURCES)
-	androgenizer \
-	-:PROJECT libgstfaac -:SHARED libgstfaac \
-	 -:TAGS eng debug \
-	 -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgstfaac_la_SOURCES) \
-	 -:CPPFLAGS $(CPPFLAGS) \
-	 -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstfaac_la_CFLAGS) \
-	 -:LDFLAGS $(libgstfaac_la_LDFLAGS) \
-	           $(libgstfaac_la_LIBADD) \
-	           -ldl \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-		       LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
-	> $@
diff --git a/ext/faac/Makefile.in b/ext/faac/Makefile.in
index db62636..6e58f22 100644
--- a/ext/faac/Makefile.in
+++ b/ext/faac/Makefile.in
@@ -1073,21 +1073,6 @@
 	uninstall-pluginLTLIBRARIES
 
 
-Android.mk: Makefile.am $(BUILT_SOURCES)
-	androgenizer \
-	-:PROJECT libgstfaac -:SHARED libgstfaac \
-	 -:TAGS eng debug \
-	 -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgstfaac_la_SOURCES) \
-	 -:CPPFLAGS $(CPPFLAGS) \
-	 -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstfaac_la_CFLAGS) \
-	 -:LDFLAGS $(libgstfaac_la_LDFLAGS) \
-	           $(libgstfaac_la_LIBADD) \
-	           -ldl \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-		       LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
-	> $@
-
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
diff --git a/ext/faad/Makefile.am b/ext/faad/Makefile.am
index cf405f4..2aef183 100644
--- a/ext/faad/Makefile.am
+++ b/ext/faad/Makefile.am
@@ -10,18 +10,3 @@
 libgstfaad_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
 
 noinst_HEADERS = gstfaad.h
-
-Android.mk: Makefile.am $(BUILT_SOURCES)
-	androgenizer \
-	-:PROJECT libgstfaad -:SHARED libgstfaad \
-	 -:TAGS eng debug \
-         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgstfaad_la_SOURCES) \
-	 -:CPPFLAGS $(CPPFLAGS) \
-	 -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstfaad_la_CFLAGS) \
-	 -:LDFLAGS $(libgstfaad_la_LDFLAGS) \
-	           $(libgstfaad_la_LIBADD) \
-	           -ldl \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-		       LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
-	> $@
diff --git a/ext/faad/Makefile.in b/ext/faad/Makefile.in
index 59bd578..a3eb642 100644
--- a/ext/faad/Makefile.in
+++ b/ext/faad/Makefile.in
@@ -1073,21 +1073,6 @@
 	uninstall-pluginLTLIBRARIES
 
 
-Android.mk: Makefile.am $(BUILT_SOURCES)
-	androgenizer \
-	-:PROJECT libgstfaad -:SHARED libgstfaad \
-	 -:TAGS eng debug \
-         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgstfaad_la_SOURCES) \
-	 -:CPPFLAGS $(CPPFLAGS) \
-	 -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstfaad_la_CFLAGS) \
-	 -:LDFLAGS $(libgstfaad_la_LDFLAGS) \
-	           $(libgstfaad_la_LIBADD) \
-	           -ldl \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-		       LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
-	> $@
-
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
diff --git a/ext/gl/Makefile.am b/ext/gl/Makefile.am
index 7dc1041..5d02afc 100644
--- a/ext/gl/Makefile.am
+++ b/ext/gl/Makefile.am
@@ -17,6 +17,20 @@
 	effects/gstgleffectidentity.c \
 	effects/gstgleffectmirror.c \
 	effects/gstgleffectsqueeze.c \
+	effects/gstgleffectstretch.c \
+	effects/gstgleffectfisheye.c \
+	effects/gstgleffecttwirl.c \
+	effects/gstgleffectbulge.c \
+	effects/gstgleffecttunnel.c \
+	effects/gstgleffectsquare.c \
+	effects/gstgleffectlumatocurve.c \
+	effects/gstgleffectrgbtocurve.c \
+	effects/gstgleffectsin.c \
+	effects/gstgleffectxray.c \
+	effects/gstgleffectglow.c \
+	effects/gstgleffectblur.c \
+	effects/gstgleffectsobel.c \
+	effects/gstgleffectlaplacian.c \
 	gstglcolorscale.c \
 	gstglmixer.c \
 	gstglvideomixer.c \
@@ -45,30 +59,13 @@
 # full opengl required
 if USE_OPENGL
 libgstopengl_la_SOURCES += \
-	gstglfilterblur.c \
-	gstglfiltersobel.c \
-	gstglfilterlaplacian.c \
 	gstglfilterglass.c \
 	gstgldeinterlace.c \
 	gltestsrc.c \
 	gstgltestsrc.c \
-	gstglmosaic.c \
-	effects/gstgleffectstretch.c \
-	effects/gstgleffecttunnel.c \
-	effects/gstgleffectfisheye.c \
-	effects/gstgleffecttwirl.c \
-	effects/gstgleffectbulge.c \
-	effects/gstgleffectsquare.c \
-	effects/gstgleffectlumatocurve.c \
-	effects/gstgleffectrgbtocurve.c \
-	effects/gstgleffectsin.c \
-	effects/gstgleffectglow.c \
-	effects/gstgleffectxray.c
+	gstglmosaic.c
 
 noinst_HEADERS += \
-	gstglfilterblur.h \
-	gstglfiltersobel.h \
-	gstglfilterlaplacian.h \
 	gstglfilterglass.h \
 	gstgldeinterlace.h \
 	gltestsrc.h \
diff --git a/ext/gl/Makefile.in b/ext/gl/Makefile.in
index 9d79a39..83de156 100644
--- a/ext/gl/Makefile.in
+++ b/ext/gl/Makefile.in
@@ -83,30 +83,13 @@
 
 # full opengl required
 @USE_OPENGL_TRUE@am__append_1 = \
-@USE_OPENGL_TRUE@	gstglfilterblur.c \
-@USE_OPENGL_TRUE@	gstglfiltersobel.c \
-@USE_OPENGL_TRUE@	gstglfilterlaplacian.c \
 @USE_OPENGL_TRUE@	gstglfilterglass.c \
 @USE_OPENGL_TRUE@	gstgldeinterlace.c \
 @USE_OPENGL_TRUE@	gltestsrc.c \
 @USE_OPENGL_TRUE@	gstgltestsrc.c \
-@USE_OPENGL_TRUE@	gstglmosaic.c \
-@USE_OPENGL_TRUE@	effects/gstgleffectstretch.c \
-@USE_OPENGL_TRUE@	effects/gstgleffecttunnel.c \
-@USE_OPENGL_TRUE@	effects/gstgleffectfisheye.c \
-@USE_OPENGL_TRUE@	effects/gstgleffecttwirl.c \
-@USE_OPENGL_TRUE@	effects/gstgleffectbulge.c \
-@USE_OPENGL_TRUE@	effects/gstgleffectsquare.c \
-@USE_OPENGL_TRUE@	effects/gstgleffectlumatocurve.c \
-@USE_OPENGL_TRUE@	effects/gstgleffectrgbtocurve.c \
-@USE_OPENGL_TRUE@	effects/gstgleffectsin.c \
-@USE_OPENGL_TRUE@	effects/gstgleffectglow.c \
-@USE_OPENGL_TRUE@	effects/gstgleffectxray.c
+@USE_OPENGL_TRUE@	gstglmosaic.c
 
 @USE_OPENGL_TRUE@am__append_2 = \
-@USE_OPENGL_TRUE@	gstglfilterblur.h \
-@USE_OPENGL_TRUE@	gstglfiltersobel.h \
-@USE_OPENGL_TRUE@	gstglfilterlaplacian.h \
 @USE_OPENGL_TRUE@	gstglfilterglass.h \
 @USE_OPENGL_TRUE@	gstgldeinterlace.h \
 @USE_OPENGL_TRUE@	gltestsrc.h \
@@ -224,38 +207,25 @@
 	gstglsinkbin.c gstglsrcbin.c gstglimagesink.c \
 	gstglfiltercube.c gstgleffects.c effects/gstgleffectssources.c \
 	effects/gstgleffectidentity.c effects/gstgleffectmirror.c \
-	effects/gstgleffectsqueeze.c gstglcolorscale.c gstglmixer.c \
-	gstglvideomixer.c gstglfiltershader.c gstglfilterapp.c \
-	gstglfilterblur.c gstglfiltersobel.c gstglfilterlaplacian.c \
-	gstglfilterglass.c gstgldeinterlace.c gltestsrc.c \
-	gstgltestsrc.c gstglmosaic.c effects/gstgleffectstretch.c \
-	effects/gstgleffecttunnel.c effects/gstgleffectfisheye.c \
-	effects/gstgleffecttwirl.c effects/gstgleffectbulge.c \
+	effects/gstgleffectsqueeze.c effects/gstgleffectstretch.c \
+	effects/gstgleffectfisheye.c effects/gstgleffecttwirl.c \
+	effects/gstgleffectbulge.c effects/gstgleffecttunnel.c \
 	effects/gstgleffectsquare.c effects/gstgleffectlumatocurve.c \
 	effects/gstgleffectrgbtocurve.c effects/gstgleffectsin.c \
-	effects/gstgleffectglow.c effects/gstgleffectxray.c \
-	gstgldifferencematte.c gstgltransformation.c \
-	gstgltransformation.h gstgloverlay.c caopengllayersink.m
+	effects/gstgleffectxray.c effects/gstgleffectglow.c \
+	effects/gstgleffectblur.c effects/gstgleffectsobel.c \
+	effects/gstgleffectlaplacian.c gstglcolorscale.c gstglmixer.c \
+	gstglvideomixer.c gstglfiltershader.c gstglfilterapp.c \
+	gstglfilterglass.c gstgldeinterlace.c gltestsrc.c \
+	gstgltestsrc.c gstglmosaic.c gstgldifferencematte.c \
+	gstgltransformation.c gstgltransformation.h gstgloverlay.c \
+	caopengllayersink.m
 am__dirstamp = $(am__leading_dot)dirstamp
-@USE_OPENGL_TRUE@am__objects_1 = libgstopengl_la-gstglfilterblur.lo \
-@USE_OPENGL_TRUE@	libgstopengl_la-gstglfiltersobel.lo \
-@USE_OPENGL_TRUE@	libgstopengl_la-gstglfilterlaplacian.lo \
-@USE_OPENGL_TRUE@	libgstopengl_la-gstglfilterglass.lo \
+@USE_OPENGL_TRUE@am__objects_1 = libgstopengl_la-gstglfilterglass.lo \
 @USE_OPENGL_TRUE@	libgstopengl_la-gstgldeinterlace.lo \
 @USE_OPENGL_TRUE@	libgstopengl_la-gltestsrc.lo \
 @USE_OPENGL_TRUE@	libgstopengl_la-gstgltestsrc.lo \
-@USE_OPENGL_TRUE@	libgstopengl_la-gstglmosaic.lo \
-@USE_OPENGL_TRUE@	effects/libgstopengl_la-gstgleffectstretch.lo \
-@USE_OPENGL_TRUE@	effects/libgstopengl_la-gstgleffecttunnel.lo \
-@USE_OPENGL_TRUE@	effects/libgstopengl_la-gstgleffectfisheye.lo \
-@USE_OPENGL_TRUE@	effects/libgstopengl_la-gstgleffecttwirl.lo \
-@USE_OPENGL_TRUE@	effects/libgstopengl_la-gstgleffectbulge.lo \
-@USE_OPENGL_TRUE@	effects/libgstopengl_la-gstgleffectsquare.lo \
-@USE_OPENGL_TRUE@	effects/libgstopengl_la-gstgleffectlumatocurve.lo \
-@USE_OPENGL_TRUE@	effects/libgstopengl_la-gstgleffectrgbtocurve.lo \
-@USE_OPENGL_TRUE@	effects/libgstopengl_la-gstgleffectsin.lo \
-@USE_OPENGL_TRUE@	effects/libgstopengl_la-gstgleffectglow.lo \
-@USE_OPENGL_TRUE@	effects/libgstopengl_la-gstgleffectxray.lo
+@USE_OPENGL_TRUE@	libgstopengl_la-gstglmosaic.lo
 @HAVE_PNG_TRUE@@USE_OPENGL_TRUE@am__objects_2 = libgstopengl_la-gstgldifferencematte.lo
 @HAVE_GRAPHENE_TRUE@am__objects_3 =  \
 @HAVE_GRAPHENE_TRUE@	libgstopengl_la-gstgltransformation.lo
@@ -277,6 +247,20 @@
 	effects/libgstopengl_la-gstgleffectidentity.lo \
 	effects/libgstopengl_la-gstgleffectmirror.lo \
 	effects/libgstopengl_la-gstgleffectsqueeze.lo \
+	effects/libgstopengl_la-gstgleffectstretch.lo \
+	effects/libgstopengl_la-gstgleffectfisheye.lo \
+	effects/libgstopengl_la-gstgleffecttwirl.lo \
+	effects/libgstopengl_la-gstgleffectbulge.lo \
+	effects/libgstopengl_la-gstgleffecttunnel.lo \
+	effects/libgstopengl_la-gstgleffectsquare.lo \
+	effects/libgstopengl_la-gstgleffectlumatocurve.lo \
+	effects/libgstopengl_la-gstgleffectrgbtocurve.lo \
+	effects/libgstopengl_la-gstgleffectsin.lo \
+	effects/libgstopengl_la-gstgleffectxray.lo \
+	effects/libgstopengl_la-gstgleffectglow.lo \
+	effects/libgstopengl_la-gstgleffectblur.lo \
+	effects/libgstopengl_la-gstgleffectsobel.lo \
+	effects/libgstopengl_la-gstgleffectlaplacian.lo \
 	libgstopengl_la-gstglcolorscale.lo \
 	libgstopengl_la-gstglmixer.lo \
 	libgstopengl_la-gstglvideomixer.lo \
@@ -358,7 +342,6 @@
 	gstglimagesink.h gstglfiltercube.h gstgleffects.h \
 	effects/gstgleffectssources.h gstglcolorscale.h gstglmixer.h \
 	gstglvideomixer.h gstglfiltershader.h gstglfilterapp.h \
-	gstglfilterblur.h gstglfiltersobel.h gstglfilterlaplacian.h \
 	gstglfilterglass.h gstgldeinterlace.h gltestsrc.h \
 	gstgltestsrc.h gstglmosaic.h effects/gstgleffectscurves.h \
 	effects/gstgleffectlumatocurve.h gstgldifferencematte.h \
@@ -897,7 +880,14 @@
 	gstglsinkbin.c gstglsrcbin.c gstglimagesink.c \
 	gstglfiltercube.c gstgleffects.c effects/gstgleffectssources.c \
 	effects/gstgleffectidentity.c effects/gstgleffectmirror.c \
-	effects/gstgleffectsqueeze.c gstglcolorscale.c gstglmixer.c \
+	effects/gstgleffectsqueeze.c effects/gstgleffectstretch.c \
+	effects/gstgleffectfisheye.c effects/gstgleffecttwirl.c \
+	effects/gstgleffectbulge.c effects/gstgleffecttunnel.c \
+	effects/gstgleffectsquare.c effects/gstgleffectlumatocurve.c \
+	effects/gstgleffectrgbtocurve.c effects/gstgleffectsin.c \
+	effects/gstgleffectxray.c effects/gstgleffectglow.c \
+	effects/gstgleffectblur.c effects/gstgleffectsobel.c \
+	effects/gstgleffectlaplacian.c gstglcolorscale.c gstglmixer.c \
 	gstglvideomixer.c gstglfiltershader.c gstglfilterapp.c \
 	$(am__append_1) $(am__append_3) $(am__append_5) \
 	$(am__append_6) $(am__append_8)
@@ -1030,14 +1020,14 @@
 	effects/$(am__dirstamp) effects/$(DEPDIR)/$(am__dirstamp)
 effects/libgstopengl_la-gstgleffectstretch.lo:  \
 	effects/$(am__dirstamp) effects/$(DEPDIR)/$(am__dirstamp)
-effects/libgstopengl_la-gstgleffecttunnel.lo: effects/$(am__dirstamp) \
-	effects/$(DEPDIR)/$(am__dirstamp)
 effects/libgstopengl_la-gstgleffectfisheye.lo:  \
 	effects/$(am__dirstamp) effects/$(DEPDIR)/$(am__dirstamp)
 effects/libgstopengl_la-gstgleffecttwirl.lo: effects/$(am__dirstamp) \
 	effects/$(DEPDIR)/$(am__dirstamp)
 effects/libgstopengl_la-gstgleffectbulge.lo: effects/$(am__dirstamp) \
 	effects/$(DEPDIR)/$(am__dirstamp)
+effects/libgstopengl_la-gstgleffecttunnel.lo: effects/$(am__dirstamp) \
+	effects/$(DEPDIR)/$(am__dirstamp)
 effects/libgstopengl_la-gstgleffectsquare.lo: effects/$(am__dirstamp) \
 	effects/$(DEPDIR)/$(am__dirstamp)
 effects/libgstopengl_la-gstgleffectlumatocurve.lo:  \
@@ -1046,10 +1036,16 @@
 	effects/$(am__dirstamp) effects/$(DEPDIR)/$(am__dirstamp)
 effects/libgstopengl_la-gstgleffectsin.lo: effects/$(am__dirstamp) \
 	effects/$(DEPDIR)/$(am__dirstamp)
-effects/libgstopengl_la-gstgleffectglow.lo: effects/$(am__dirstamp) \
-	effects/$(DEPDIR)/$(am__dirstamp)
 effects/libgstopengl_la-gstgleffectxray.lo: effects/$(am__dirstamp) \
 	effects/$(DEPDIR)/$(am__dirstamp)
+effects/libgstopengl_la-gstgleffectglow.lo: effects/$(am__dirstamp) \
+	effects/$(DEPDIR)/$(am__dirstamp)
+effects/libgstopengl_la-gstgleffectblur.lo: effects/$(am__dirstamp) \
+	effects/$(DEPDIR)/$(am__dirstamp)
+effects/libgstopengl_la-gstgleffectsobel.lo: effects/$(am__dirstamp) \
+	effects/$(DEPDIR)/$(am__dirstamp)
+effects/libgstopengl_la-gstgleffectlaplacian.lo:  \
+	effects/$(am__dirstamp) effects/$(DEPDIR)/$(am__dirstamp)
 
 libgstopengl.la: $(libgstopengl_la_OBJECTS) $(libgstopengl_la_DEPENDENCIES) $(EXTRA_libgstopengl_la_DEPENDENCIES) 
 	$(AM_V_OBJCLD)$(libgstopengl_la_LINK) -rpath $(plugindir) $(libgstopengl_la_OBJECTS) $(libgstopengl_la_LIBADD) $(LIBS)
@@ -1073,12 +1069,9 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstopengl_la-gstgleffects.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstopengl_la-gstglfilterapp.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstopengl_la-gstglfilterbin.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstopengl_la-gstglfilterblur.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstopengl_la-gstglfiltercube.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstopengl_la-gstglfilterglass.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstopengl_la-gstglfilterlaplacian.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstopengl_la-gstglfiltershader.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstopengl_la-gstglfiltersobel.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstopengl_la-gstglimagesink.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstopengl_la-gstglmixer.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstopengl_la-gstglmixerbin.Plo@am__quote@
@@ -1091,14 +1084,17 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstopengl_la-gstgluploadelement.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstopengl_la-gstglvideomixer.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstopengl_la-gstopengl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/libgstopengl_la-gstgleffectblur.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/libgstopengl_la-gstgleffectbulge.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/libgstopengl_la-gstgleffectfisheye.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/libgstopengl_la-gstgleffectglow.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/libgstopengl_la-gstgleffectidentity.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/libgstopengl_la-gstgleffectlaplacian.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/libgstopengl_la-gstgleffectlumatocurve.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/libgstopengl_la-gstgleffectmirror.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/libgstopengl_la-gstgleffectrgbtocurve.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/libgstopengl_la-gstgleffectsin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/libgstopengl_la-gstgleffectsobel.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/libgstopengl_la-gstgleffectsquare.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/libgstopengl_la-gstgleffectsqueeze.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/libgstopengl_la-gstgleffectssources.Plo@am__quote@
@@ -1243,6 +1239,104 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectsqueeze.lo `test -f 'effects/gstgleffectsqueeze.c' || echo '$(srcdir)/'`effects/gstgleffectsqueeze.c
 
+effects/libgstopengl_la-gstgleffectstretch.lo: effects/gstgleffectstretch.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectstretch.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectstretch.Tpo -c -o effects/libgstopengl_la-gstgleffectstretch.lo `test -f 'effects/gstgleffectstretch.c' || echo '$(srcdir)/'`effects/gstgleffectstretch.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectstretch.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectstretch.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectstretch.c' object='effects/libgstopengl_la-gstgleffectstretch.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectstretch.lo `test -f 'effects/gstgleffectstretch.c' || echo '$(srcdir)/'`effects/gstgleffectstretch.c
+
+effects/libgstopengl_la-gstgleffectfisheye.lo: effects/gstgleffectfisheye.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectfisheye.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectfisheye.Tpo -c -o effects/libgstopengl_la-gstgleffectfisheye.lo `test -f 'effects/gstgleffectfisheye.c' || echo '$(srcdir)/'`effects/gstgleffectfisheye.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectfisheye.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectfisheye.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectfisheye.c' object='effects/libgstopengl_la-gstgleffectfisheye.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectfisheye.lo `test -f 'effects/gstgleffectfisheye.c' || echo '$(srcdir)/'`effects/gstgleffectfisheye.c
+
+effects/libgstopengl_la-gstgleffecttwirl.lo: effects/gstgleffecttwirl.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffecttwirl.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffecttwirl.Tpo -c -o effects/libgstopengl_la-gstgleffecttwirl.lo `test -f 'effects/gstgleffecttwirl.c' || echo '$(srcdir)/'`effects/gstgleffecttwirl.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffecttwirl.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffecttwirl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffecttwirl.c' object='effects/libgstopengl_la-gstgleffecttwirl.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffecttwirl.lo `test -f 'effects/gstgleffecttwirl.c' || echo '$(srcdir)/'`effects/gstgleffecttwirl.c
+
+effects/libgstopengl_la-gstgleffectbulge.lo: effects/gstgleffectbulge.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectbulge.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectbulge.Tpo -c -o effects/libgstopengl_la-gstgleffectbulge.lo `test -f 'effects/gstgleffectbulge.c' || echo '$(srcdir)/'`effects/gstgleffectbulge.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectbulge.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectbulge.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectbulge.c' object='effects/libgstopengl_la-gstgleffectbulge.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectbulge.lo `test -f 'effects/gstgleffectbulge.c' || echo '$(srcdir)/'`effects/gstgleffectbulge.c
+
+effects/libgstopengl_la-gstgleffecttunnel.lo: effects/gstgleffecttunnel.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffecttunnel.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffecttunnel.Tpo -c -o effects/libgstopengl_la-gstgleffecttunnel.lo `test -f 'effects/gstgleffecttunnel.c' || echo '$(srcdir)/'`effects/gstgleffecttunnel.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffecttunnel.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffecttunnel.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffecttunnel.c' object='effects/libgstopengl_la-gstgleffecttunnel.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffecttunnel.lo `test -f 'effects/gstgleffecttunnel.c' || echo '$(srcdir)/'`effects/gstgleffecttunnel.c
+
+effects/libgstopengl_la-gstgleffectsquare.lo: effects/gstgleffectsquare.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectsquare.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectsquare.Tpo -c -o effects/libgstopengl_la-gstgleffectsquare.lo `test -f 'effects/gstgleffectsquare.c' || echo '$(srcdir)/'`effects/gstgleffectsquare.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectsquare.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectsquare.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectsquare.c' object='effects/libgstopengl_la-gstgleffectsquare.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectsquare.lo `test -f 'effects/gstgleffectsquare.c' || echo '$(srcdir)/'`effects/gstgleffectsquare.c
+
+effects/libgstopengl_la-gstgleffectlumatocurve.lo: effects/gstgleffectlumatocurve.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectlumatocurve.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectlumatocurve.Tpo -c -o effects/libgstopengl_la-gstgleffectlumatocurve.lo `test -f 'effects/gstgleffectlumatocurve.c' || echo '$(srcdir)/'`effects/gstgleffectlumatocurve.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectlumatocurve.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectlumatocurve.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectlumatocurve.c' object='effects/libgstopengl_la-gstgleffectlumatocurve.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectlumatocurve.lo `test -f 'effects/gstgleffectlumatocurve.c' || echo '$(srcdir)/'`effects/gstgleffectlumatocurve.c
+
+effects/libgstopengl_la-gstgleffectrgbtocurve.lo: effects/gstgleffectrgbtocurve.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectrgbtocurve.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectrgbtocurve.Tpo -c -o effects/libgstopengl_la-gstgleffectrgbtocurve.lo `test -f 'effects/gstgleffectrgbtocurve.c' || echo '$(srcdir)/'`effects/gstgleffectrgbtocurve.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectrgbtocurve.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectrgbtocurve.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectrgbtocurve.c' object='effects/libgstopengl_la-gstgleffectrgbtocurve.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectrgbtocurve.lo `test -f 'effects/gstgleffectrgbtocurve.c' || echo '$(srcdir)/'`effects/gstgleffectrgbtocurve.c
+
+effects/libgstopengl_la-gstgleffectsin.lo: effects/gstgleffectsin.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectsin.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectsin.Tpo -c -o effects/libgstopengl_la-gstgleffectsin.lo `test -f 'effects/gstgleffectsin.c' || echo '$(srcdir)/'`effects/gstgleffectsin.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectsin.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectsin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectsin.c' object='effects/libgstopengl_la-gstgleffectsin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectsin.lo `test -f 'effects/gstgleffectsin.c' || echo '$(srcdir)/'`effects/gstgleffectsin.c
+
+effects/libgstopengl_la-gstgleffectxray.lo: effects/gstgleffectxray.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectxray.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectxray.Tpo -c -o effects/libgstopengl_la-gstgleffectxray.lo `test -f 'effects/gstgleffectxray.c' || echo '$(srcdir)/'`effects/gstgleffectxray.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectxray.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectxray.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectxray.c' object='effects/libgstopengl_la-gstgleffectxray.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectxray.lo `test -f 'effects/gstgleffectxray.c' || echo '$(srcdir)/'`effects/gstgleffectxray.c
+
+effects/libgstopengl_la-gstgleffectglow.lo: effects/gstgleffectglow.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectglow.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectglow.Tpo -c -o effects/libgstopengl_la-gstgleffectglow.lo `test -f 'effects/gstgleffectglow.c' || echo '$(srcdir)/'`effects/gstgleffectglow.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectglow.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectglow.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectglow.c' object='effects/libgstopengl_la-gstgleffectglow.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectglow.lo `test -f 'effects/gstgleffectglow.c' || echo '$(srcdir)/'`effects/gstgleffectglow.c
+
+effects/libgstopengl_la-gstgleffectblur.lo: effects/gstgleffectblur.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectblur.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectblur.Tpo -c -o effects/libgstopengl_la-gstgleffectblur.lo `test -f 'effects/gstgleffectblur.c' || echo '$(srcdir)/'`effects/gstgleffectblur.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectblur.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectblur.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectblur.c' object='effects/libgstopengl_la-gstgleffectblur.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectblur.lo `test -f 'effects/gstgleffectblur.c' || echo '$(srcdir)/'`effects/gstgleffectblur.c
+
+effects/libgstopengl_la-gstgleffectsobel.lo: effects/gstgleffectsobel.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectsobel.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectsobel.Tpo -c -o effects/libgstopengl_la-gstgleffectsobel.lo `test -f 'effects/gstgleffectsobel.c' || echo '$(srcdir)/'`effects/gstgleffectsobel.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectsobel.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectsobel.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectsobel.c' object='effects/libgstopengl_la-gstgleffectsobel.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectsobel.lo `test -f 'effects/gstgleffectsobel.c' || echo '$(srcdir)/'`effects/gstgleffectsobel.c
+
+effects/libgstopengl_la-gstgleffectlaplacian.lo: effects/gstgleffectlaplacian.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectlaplacian.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectlaplacian.Tpo -c -o effects/libgstopengl_la-gstgleffectlaplacian.lo `test -f 'effects/gstgleffectlaplacian.c' || echo '$(srcdir)/'`effects/gstgleffectlaplacian.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectlaplacian.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectlaplacian.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectlaplacian.c' object='effects/libgstopengl_la-gstgleffectlaplacian.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectlaplacian.lo `test -f 'effects/gstgleffectlaplacian.c' || echo '$(srcdir)/'`effects/gstgleffectlaplacian.c
+
 libgstopengl_la-gstglcolorscale.lo: gstglcolorscale.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT libgstopengl_la-gstglcolorscale.lo -MD -MP -MF $(DEPDIR)/libgstopengl_la-gstglcolorscale.Tpo -c -o libgstopengl_la-gstglcolorscale.lo `test -f 'gstglcolorscale.c' || echo '$(srcdir)/'`gstglcolorscale.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libgstopengl_la-gstglcolorscale.Tpo $(DEPDIR)/libgstopengl_la-gstglcolorscale.Plo
@@ -1278,27 +1372,6 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o libgstopengl_la-gstglfilterapp.lo `test -f 'gstglfilterapp.c' || echo '$(srcdir)/'`gstglfilterapp.c
 
-libgstopengl_la-gstglfilterblur.lo: gstglfilterblur.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT libgstopengl_la-gstglfilterblur.lo -MD -MP -MF $(DEPDIR)/libgstopengl_la-gstglfilterblur.Tpo -c -o libgstopengl_la-gstglfilterblur.lo `test -f 'gstglfilterblur.c' || echo '$(srcdir)/'`gstglfilterblur.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libgstopengl_la-gstglfilterblur.Tpo $(DEPDIR)/libgstopengl_la-gstglfilterblur.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='gstglfilterblur.c' object='libgstopengl_la-gstglfilterblur.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o libgstopengl_la-gstglfilterblur.lo `test -f 'gstglfilterblur.c' || echo '$(srcdir)/'`gstglfilterblur.c
-
-libgstopengl_la-gstglfiltersobel.lo: gstglfiltersobel.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT libgstopengl_la-gstglfiltersobel.lo -MD -MP -MF $(DEPDIR)/libgstopengl_la-gstglfiltersobel.Tpo -c -o libgstopengl_la-gstglfiltersobel.lo `test -f 'gstglfiltersobel.c' || echo '$(srcdir)/'`gstglfiltersobel.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libgstopengl_la-gstglfiltersobel.Tpo $(DEPDIR)/libgstopengl_la-gstglfiltersobel.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='gstglfiltersobel.c' object='libgstopengl_la-gstglfiltersobel.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o libgstopengl_la-gstglfiltersobel.lo `test -f 'gstglfiltersobel.c' || echo '$(srcdir)/'`gstglfiltersobel.c
-
-libgstopengl_la-gstglfilterlaplacian.lo: gstglfilterlaplacian.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT libgstopengl_la-gstglfilterlaplacian.lo -MD -MP -MF $(DEPDIR)/libgstopengl_la-gstglfilterlaplacian.Tpo -c -o libgstopengl_la-gstglfilterlaplacian.lo `test -f 'gstglfilterlaplacian.c' || echo '$(srcdir)/'`gstglfilterlaplacian.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libgstopengl_la-gstglfilterlaplacian.Tpo $(DEPDIR)/libgstopengl_la-gstglfilterlaplacian.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='gstglfilterlaplacian.c' object='libgstopengl_la-gstglfilterlaplacian.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o libgstopengl_la-gstglfilterlaplacian.lo `test -f 'gstglfilterlaplacian.c' || echo '$(srcdir)/'`gstglfilterlaplacian.c
-
 libgstopengl_la-gstglfilterglass.lo: gstglfilterglass.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT libgstopengl_la-gstglfilterglass.lo -MD -MP -MF $(DEPDIR)/libgstopengl_la-gstglfilterglass.Tpo -c -o libgstopengl_la-gstglfilterglass.lo `test -f 'gstglfilterglass.c' || echo '$(srcdir)/'`gstglfilterglass.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libgstopengl_la-gstglfilterglass.Tpo $(DEPDIR)/libgstopengl_la-gstglfilterglass.Plo
@@ -1334,83 +1407,6 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o libgstopengl_la-gstglmosaic.lo `test -f 'gstglmosaic.c' || echo '$(srcdir)/'`gstglmosaic.c
 
-effects/libgstopengl_la-gstgleffectstretch.lo: effects/gstgleffectstretch.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectstretch.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectstretch.Tpo -c -o effects/libgstopengl_la-gstgleffectstretch.lo `test -f 'effects/gstgleffectstretch.c' || echo '$(srcdir)/'`effects/gstgleffectstretch.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectstretch.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectstretch.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectstretch.c' object='effects/libgstopengl_la-gstgleffectstretch.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectstretch.lo `test -f 'effects/gstgleffectstretch.c' || echo '$(srcdir)/'`effects/gstgleffectstretch.c
-
-effects/libgstopengl_la-gstgleffecttunnel.lo: effects/gstgleffecttunnel.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffecttunnel.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffecttunnel.Tpo -c -o effects/libgstopengl_la-gstgleffecttunnel.lo `test -f 'effects/gstgleffecttunnel.c' || echo '$(srcdir)/'`effects/gstgleffecttunnel.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffecttunnel.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffecttunnel.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffecttunnel.c' object='effects/libgstopengl_la-gstgleffecttunnel.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffecttunnel.lo `test -f 'effects/gstgleffecttunnel.c' || echo '$(srcdir)/'`effects/gstgleffecttunnel.c
-
-effects/libgstopengl_la-gstgleffectfisheye.lo: effects/gstgleffectfisheye.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectfisheye.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectfisheye.Tpo -c -o effects/libgstopengl_la-gstgleffectfisheye.lo `test -f 'effects/gstgleffectfisheye.c' || echo '$(srcdir)/'`effects/gstgleffectfisheye.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectfisheye.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectfisheye.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectfisheye.c' object='effects/libgstopengl_la-gstgleffectfisheye.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectfisheye.lo `test -f 'effects/gstgleffectfisheye.c' || echo '$(srcdir)/'`effects/gstgleffectfisheye.c
-
-effects/libgstopengl_la-gstgleffecttwirl.lo: effects/gstgleffecttwirl.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffecttwirl.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffecttwirl.Tpo -c -o effects/libgstopengl_la-gstgleffecttwirl.lo `test -f 'effects/gstgleffecttwirl.c' || echo '$(srcdir)/'`effects/gstgleffecttwirl.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffecttwirl.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffecttwirl.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffecttwirl.c' object='effects/libgstopengl_la-gstgleffecttwirl.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffecttwirl.lo `test -f 'effects/gstgleffecttwirl.c' || echo '$(srcdir)/'`effects/gstgleffecttwirl.c
-
-effects/libgstopengl_la-gstgleffectbulge.lo: effects/gstgleffectbulge.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectbulge.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectbulge.Tpo -c -o effects/libgstopengl_la-gstgleffectbulge.lo `test -f 'effects/gstgleffectbulge.c' || echo '$(srcdir)/'`effects/gstgleffectbulge.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectbulge.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectbulge.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectbulge.c' object='effects/libgstopengl_la-gstgleffectbulge.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectbulge.lo `test -f 'effects/gstgleffectbulge.c' || echo '$(srcdir)/'`effects/gstgleffectbulge.c
-
-effects/libgstopengl_la-gstgleffectsquare.lo: effects/gstgleffectsquare.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectsquare.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectsquare.Tpo -c -o effects/libgstopengl_la-gstgleffectsquare.lo `test -f 'effects/gstgleffectsquare.c' || echo '$(srcdir)/'`effects/gstgleffectsquare.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectsquare.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectsquare.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectsquare.c' object='effects/libgstopengl_la-gstgleffectsquare.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectsquare.lo `test -f 'effects/gstgleffectsquare.c' || echo '$(srcdir)/'`effects/gstgleffectsquare.c
-
-effects/libgstopengl_la-gstgleffectlumatocurve.lo: effects/gstgleffectlumatocurve.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectlumatocurve.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectlumatocurve.Tpo -c -o effects/libgstopengl_la-gstgleffectlumatocurve.lo `test -f 'effects/gstgleffectlumatocurve.c' || echo '$(srcdir)/'`effects/gstgleffectlumatocurve.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectlumatocurve.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectlumatocurve.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectlumatocurve.c' object='effects/libgstopengl_la-gstgleffectlumatocurve.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectlumatocurve.lo `test -f 'effects/gstgleffectlumatocurve.c' || echo '$(srcdir)/'`effects/gstgleffectlumatocurve.c
-
-effects/libgstopengl_la-gstgleffectrgbtocurve.lo: effects/gstgleffectrgbtocurve.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectrgbtocurve.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectrgbtocurve.Tpo -c -o effects/libgstopengl_la-gstgleffectrgbtocurve.lo `test -f 'effects/gstgleffectrgbtocurve.c' || echo '$(srcdir)/'`effects/gstgleffectrgbtocurve.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectrgbtocurve.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectrgbtocurve.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectrgbtocurve.c' object='effects/libgstopengl_la-gstgleffectrgbtocurve.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectrgbtocurve.lo `test -f 'effects/gstgleffectrgbtocurve.c' || echo '$(srcdir)/'`effects/gstgleffectrgbtocurve.c
-
-effects/libgstopengl_la-gstgleffectsin.lo: effects/gstgleffectsin.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectsin.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectsin.Tpo -c -o effects/libgstopengl_la-gstgleffectsin.lo `test -f 'effects/gstgleffectsin.c' || echo '$(srcdir)/'`effects/gstgleffectsin.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectsin.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectsin.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectsin.c' object='effects/libgstopengl_la-gstgleffectsin.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectsin.lo `test -f 'effects/gstgleffectsin.c' || echo '$(srcdir)/'`effects/gstgleffectsin.c
-
-effects/libgstopengl_la-gstgleffectglow.lo: effects/gstgleffectglow.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectglow.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectglow.Tpo -c -o effects/libgstopengl_la-gstgleffectglow.lo `test -f 'effects/gstgleffectglow.c' || echo '$(srcdir)/'`effects/gstgleffectglow.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectglow.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectglow.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectglow.c' object='effects/libgstopengl_la-gstgleffectglow.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectglow.lo `test -f 'effects/gstgleffectglow.c' || echo '$(srcdir)/'`effects/gstgleffectglow.c
-
-effects/libgstopengl_la-gstgleffectxray.lo: effects/gstgleffectxray.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT effects/libgstopengl_la-gstgleffectxray.lo -MD -MP -MF effects/$(DEPDIR)/libgstopengl_la-gstgleffectxray.Tpo -c -o effects/libgstopengl_la-gstgleffectxray.lo `test -f 'effects/gstgleffectxray.c' || echo '$(srcdir)/'`effects/gstgleffectxray.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) effects/$(DEPDIR)/libgstopengl_la-gstgleffectxray.Tpo effects/$(DEPDIR)/libgstopengl_la-gstgleffectxray.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='effects/gstgleffectxray.c' object='effects/libgstopengl_la-gstgleffectxray.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -c -o effects/libgstopengl_la-gstgleffectxray.lo `test -f 'effects/gstgleffectxray.c' || echo '$(srcdir)/'`effects/gstgleffectxray.c
-
 libgstopengl_la-gstgldifferencematte.lo: gstgldifferencematte.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstopengl_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstopengl_la_CFLAGS) $(CFLAGS) -MT libgstopengl_la-gstgldifferencematte.lo -MD -MP -MF $(DEPDIR)/libgstopengl_la-gstgldifferencematte.Tpo -c -o libgstopengl_la-gstgldifferencematte.lo `test -f 'gstgldifferencematte.c' || echo '$(srcdir)/'`gstgldifferencematte.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libgstopengl_la-gstgldifferencematte.Tpo $(DEPDIR)/libgstopengl_la-gstgldifferencematte.Plo
diff --git a/ext/gl/effects/gstgleffectblur.c b/ext/gl/effects/gstgleffectblur.c
new file mode 100644
index 0000000..07eb38d
--- /dev/null
+++ b/ext/gl/effects/gstgleffectblur.c
@@ -0,0 +1,122 @@
+/*
+ * GStreamer
+ * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com>
+ * Copyright (C) 2015 Michał Dębski <debski.mi.zd@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "../gstgleffects.h"
+
+static float *
+gst_gl_effects_blur_kernel (void)
+{
+  /* gaussian kernel (well, actually vector), size 9, standard
+   * deviation 3.0 */
+  /* FIXME: make this a runtime property */
+  static gfloat *kernel = NULL;
+  if (G_UNLIKELY (NULL == kernel)) {
+    /* 3x3 matrix */
+    kernel = g_malloc (sizeof (gfloat) * 9);
+    fill_gaussian_kernel (kernel, 7, 3.f);
+  }
+  return kernel;
+}
+
+static void
+gst_gl_effects_blur_callback_hconv (gint width, gint height, guint texture,
+    gpointer data)
+{
+  GstGLShader *shader = NULL;
+  GstGLEffects *effects = GST_GL_EFFECTS (data);
+
+  if (NULL != (shader = gst_gl_effects_get_fragment_shader (effects, "hconv0",
+              hconv7_fragment_source_gles2, hconv7_fragment_source_opengl))) {
+    GstGLFilter *filter = GST_GL_FILTER (effects);
+    GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
+
+#if GST_GL_HAVE_OPENGL
+    if (USING_OPENGL (GST_GL_BASE_FILTER (filter)->context)) {
+      gl->MatrixMode (GL_PROJECTION);
+      gl->LoadIdentity ();
+    }
+#endif
+
+    gst_gl_shader_use (shader);
+
+    gl->ActiveTexture (GL_TEXTURE0);
+    gl->Enable (GL_TEXTURE_2D);
+    gl->BindTexture (GL_TEXTURE_2D, texture);
+    gl->Disable (GL_TEXTURE_2D);
+
+    gst_gl_shader_set_uniform_1i (shader, "tex", 0);
+    gst_gl_shader_set_uniform_1f (shader, "gauss_width", width);
+    gst_gl_shader_set_uniform_1fv (shader, "kernel", 7,
+        gst_gl_effects_blur_kernel ());
+
+    gst_gl_filter_draw_texture (filter, texture, width, height);
+  }
+}
+
+static void
+gst_gl_effects_blur_callback_vconv (gint width, gint height, guint texture,
+    gpointer data)
+{
+  GstGLShader *shader = NULL;
+  GstGLEffects *effects = GST_GL_EFFECTS (data);
+  GstGLFilter *filter = GST_GL_FILTER (effects);
+
+  if (NULL != (shader = gst_gl_effects_get_fragment_shader (effects, "vconv0",
+              vconv7_fragment_source_gles2, vconv7_fragment_source_opengl))) {
+    GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
+
+#if GST_GL_HAVE_OPENGL
+    if (USING_OPENGL (GST_GL_BASE_FILTER (filter)->context)) {
+      gl->MatrixMode (GL_PROJECTION);
+      gl->LoadIdentity ();
+    }
+#endif
+
+    gst_gl_shader_use (shader);
+
+    gl->ActiveTexture (GL_TEXTURE0);
+    gl->Enable (GL_TEXTURE_2D);
+    gl->BindTexture (GL_TEXTURE_2D, texture);
+    gl->Disable (GL_TEXTURE_2D);
+
+    gst_gl_shader_set_uniform_1i (shader, "tex", 0);
+    gst_gl_shader_set_uniform_1f (shader, "gauss_height", height);
+    gst_gl_shader_set_uniform_1fv (shader, "kernel", 7,
+        gst_gl_effects_blur_kernel ());
+
+    gst_gl_filter_draw_texture (filter, texture, width, height);
+  }
+}
+
+void
+gst_gl_effects_blur (GstGLEffects * effects)
+{
+  GstGLFilter *filter = GST_GL_FILTER (effects);
+
+  gst_gl_filter_render_to_target (filter, TRUE, effects->intexture,
+      effects->midtexture[0], gst_gl_effects_blur_callback_hconv, effects);
+  gst_gl_filter_render_to_target (filter, FALSE, effects->midtexture[0],
+      effects->outtexture, gst_gl_effects_blur_callback_vconv, effects);
+}
diff --git a/ext/gl/effects/gstgleffectbulge.c b/ext/gl/effects/gstgleffectbulge.c
index 75b9e2f..2e21025 100644
--- a/ext/gl/effects/gstgleffectbulge.c
+++ b/ext/gl/effects/gstgleffectbulge.c
@@ -33,23 +33,18 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "bulge0");
+  shader = gst_gl_effects_get_fragment_shader (effects, "bulge",
+      bulge_fragment_source_gles2, bulge_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "bulge0", shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          bulge_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context, "Failed to initialize bulge shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
@@ -59,9 +54,6 @@
 
   gst_gl_shader_set_uniform_1i (shader, "tex", 0);
 
-  gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f);
-  gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f);
-
   gst_gl_filter_draw_texture (filter, texture, width, height);
 }
 
diff --git a/ext/gl/effects/gstgleffectfisheye.c b/ext/gl/effects/gstgleffectfisheye.c
index 524b659..c94cd42 100644
--- a/ext/gl/effects/gstgleffectfisheye.c
+++ b/ext/gl/effects/gstgleffectfisheye.c
@@ -33,23 +33,18 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "fisheye0");
+  shader = gst_gl_effects_get_fragment_shader (effects, "fisheye",
+      fisheye_fragment_source_gles2, fisheye_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "fisheye0", shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          fisheye_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context, "Failed to initialize fisheye shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
@@ -59,9 +54,6 @@
 
   gst_gl_shader_set_uniform_1i (shader, "tex", 0);
 
-  gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f);
-  gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f);
-
   gst_gl_filter_draw_texture (filter, texture, width, height);
 }
 
diff --git a/ext/gl/effects/gstgleffectglow.c b/ext/gl/effects/gstgleffectglow.c
index 4853fd9..b387715 100644
--- a/ext/gl/effects/gstgleffectglow.c
+++ b/ext/gl/effects/gstgleffectglow.c
@@ -36,24 +36,19 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "glow0");
+  shader = gst_gl_effects_get_fragment_shader (effects, "luma_threshold",
+      luma_threshold_fragment_source_gles2,
+      luma_threshold_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "glow0", shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          luma_threshold_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context,
-        "Failed to initialize luma threshold shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
@@ -76,28 +71,22 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "glow1");
+  shader = gst_gl_effects_get_fragment_shader (effects, "hconv7",
+      hconv7_fragment_source_gles2, hconv7_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "glow1", shader);
-  }
+  if (!shader)
+    return;
 
   if (!kernel_ready) {
     fill_gaussian_kernel (gauss_kernel, 7, 10.0);
     kernel_ready = TRUE;
   }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          hconv7_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context, "Failed to initialize hconv7 shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
-    return;
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
   }
-
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#endif
 
   gst_gl_shader_use (shader);
 
@@ -108,7 +97,7 @@
 
   gst_gl_shader_set_uniform_1i (shader, "tex", 1);
   gst_gl_shader_set_uniform_1fv (shader, "kernel", 7, gauss_kernel);
-  gst_gl_shader_set_uniform_1f (shader, "height", height);
+  gst_gl_shader_set_uniform_1f (shader, "gauss_width", width);
 
   gst_gl_filter_draw_texture (filter, texture, width, height);
 }
@@ -123,23 +112,18 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "glow2");
+  shader = gst_gl_effects_get_fragment_shader (effects, "vconv7",
+      vconv7_fragment_source_gles2, vconv7_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "glow2", shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          vconv7_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context, "Failed to initialize vcon7 shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
@@ -150,7 +134,7 @@
 
   gst_gl_shader_set_uniform_1i (shader, "tex", 1);
   gst_gl_shader_set_uniform_1fv (shader, "kernel", 7, gauss_kernel);
-  gst_gl_shader_set_uniform_1f (shader, "width", width);
+  gst_gl_shader_set_uniform_1f (shader, "gauss_height", height);
 
   gst_gl_filter_draw_texture (filter, texture, width, height);
 }
@@ -165,23 +149,18 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "glow3");
+  shader = gst_gl_effects_get_fragment_shader (effects, "sum",
+      sum_fragment_source_gles2, sum_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "glow3", shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          sum_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context, "Failed to initialize sum shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
@@ -190,7 +169,7 @@
   gl->BindTexture (GL_TEXTURE_2D, effects->intexture);
   gl->Disable (GL_TEXTURE_2D);
 
-  gst_gl_shader_set_uniform_1f (shader, "alpha", 1.0);
+  gst_gl_shader_set_uniform_1f (shader, "alpha", 1.0f);
   gst_gl_shader_set_uniform_1i (shader, "base", 2);
 
   gl->ActiveTexture (GL_TEXTURE1);
@@ -212,11 +191,14 @@
   /* threshold */
   gst_gl_filter_render_to_target (filter, TRUE, effects->intexture,
       effects->midtexture[0], gst_gl_effects_glow_step_one, effects);
+
   /* blur */
   gst_gl_filter_render_to_target (filter, FALSE, effects->midtexture[0],
       effects->midtexture[1], gst_gl_effects_glow_step_two, effects);
+
   gst_gl_filter_render_to_target (filter, FALSE, effects->midtexture[1],
       effects->midtexture[2], gst_gl_effects_glow_step_three, effects);
+
   /* add blurred luma to intexture */
   gst_gl_filter_render_to_target (filter, FALSE, effects->midtexture[2],
       effects->outtexture, gst_gl_effects_glow_step_four, effects);
diff --git a/ext/gl/effects/gstgleffectidentity.c b/ext/gl/effects/gstgleffectidentity.c
index eec357e..58d0055 100644
--- a/ext/gl/effects/gstgleffectidentity.c
+++ b/ext/gl/effects/gstgleffectidentity.c
@@ -23,12 +23,6 @@
 
 #include "../gstgleffects.h"
 
-#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
-#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1))
-#define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0))
-#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
-#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
-
 static void
 gst_gl_effects_identity_callback (gint width, gint height, guint texture,
     gpointer data)
diff --git a/ext/gl/effects/gstgleffectlaplacian.c b/ext/gl/effects/gstgleffectlaplacian.c
new file mode 100644
index 0000000..b9dabcb
--- /dev/null
+++ b/ext/gl/effects/gstgleffectlaplacian.c
@@ -0,0 +1,74 @@
+/*
+ * GStreamer
+ * Copyright (C) 2008-2010 Filippo Argiolas <filippo.argiolas@gmail.com>
+ * Copyright (C) 2015 Michał Dębski <debski.mi.zd@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "../gstgleffects.h"
+
+static void
+gst_gl_effects_laplacian_callback (gint width, gint height, guint texture,
+    gpointer data)
+{
+  GstGLShader *shader = NULL;
+  GstGLEffects *effects = GST_GL_EFFECTS (data);
+  GstGLFilter *filter = GST_GL_FILTER (effects);
+
+  if (NULL != (shader = gst_gl_effects_get_fragment_shader (effects, "conv0",
+              conv9_fragment_source_gles2, conv9_fragment_source_opengl))) {
+    GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
+    static gfloat kernel[9] = { 0.0, -1.0, 0.0,
+      -1.0, 4.0, -1.0,
+      0.0, -1.0, 0.0
+    };
+
+#if GST_GL_HAVE_OPENGL
+    if (USING_OPENGL (GST_GL_BASE_FILTER (filter)->context)) {
+      gl->MatrixMode (GL_PROJECTION);
+      gl->LoadIdentity ();
+    }
+#endif
+
+    gst_gl_shader_use (shader);
+
+    gl->ActiveTexture (GL_TEXTURE0);
+    gl->Enable (GL_TEXTURE_2D);
+    gl->BindTexture (GL_TEXTURE_2D, texture);
+    gl->Disable (GL_TEXTURE_2D);
+
+    gst_gl_shader_set_uniform_1i (shader, "tex", 0);
+    gst_gl_shader_set_uniform_1f (shader, "height", height);
+    gst_gl_shader_set_uniform_1f (shader, "width", width);
+    gst_gl_shader_set_uniform_1fv (shader, "kernel", 9, kernel);
+    gst_gl_shader_set_uniform_1i (shader, "invert", effects->invert);
+
+    gst_gl_filter_draw_texture (filter, texture, width, height);
+  }
+}
+
+void
+gst_gl_effects_laplacian (GstGLEffects * effects)
+{
+  gst_gl_filter_render_to_target (GST_GL_FILTER (effects), TRUE,
+      effects->intexture, effects->outtexture,
+      gst_gl_effects_laplacian_callback, effects);
+}
diff --git a/ext/gl/effects/gstgleffectlumatocurve.c b/ext/gl/effects/gstgleffectlumatocurve.c
index 2ce1de3..0a925fe 100644
--- a/ext/gl/effects/gstgleffectlumatocurve.c
+++ b/ext/gl/effects/gstgleffectlumatocurve.c
@@ -34,41 +34,53 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "lumamap0");
+  shader = gst_gl_effects_get_fragment_shader (effects, "luma_to_curve",
+      luma_to_curve_fragment_source_gles2,
+      luma_to_curve_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "lumamap0", shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          luma_to_curve_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context,
-        "Failed to initialize luma to curve shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
   if (effects->curve[curve_index] == 0) {
     /* this parameters are needed to have a right, predictable, mapping */
     gl->GenTextures (1, &effects->curve[curve_index]);
-    gl->Enable (GL_TEXTURE_1D);
-    gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]);
-    gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
-    gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 
-    gl->TexImage1D (GL_TEXTURE_1D, 0, curve->bytes_per_pixel,
-        curve->width, 0, GL_RGB, GL_UNSIGNED_BYTE, curve->pixel_data);
+#if GST_GL_HAVE_OPENGL
+    if (USING_OPENGL (context)) {
+      gl->Enable (GL_TEXTURE_1D);
+      gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]);
+      gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+      gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+      gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+      gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 
-    gl->Disable (GL_TEXTURE_1D);
+      gl->TexImage1D (GL_TEXTURE_1D, 0, curve->bytes_per_pixel,
+          curve->width, 0, GL_RGB, GL_UNSIGNED_BYTE, curve->pixel_data);
+
+      gl->Disable (GL_TEXTURE_1D);
+    }
+#endif
+    if (USING_GLES2 (context) || USING_OPENGL3 (context)) {
+      gl->Enable (GL_TEXTURE_2D);
+      gl->BindTexture (GL_TEXTURE_2D, effects->curve[curve_index]);
+      gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+      gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+      gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+      gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+      gl->TexImage2D (GL_TEXTURE_2D, 0, GL_RGB,
+          curve->width, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, curve->pixel_data);
+      gl->Disable (GL_TEXTURE_2D);
+    }
   }
 
   gl->ActiveTexture (GL_TEXTURE2);
@@ -79,13 +91,26 @@
 
   gl->Disable (GL_TEXTURE_2D);
 
-  gl->ActiveTexture (GL_TEXTURE1);
-  gl->Enable (GL_TEXTURE_1D);
-  gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]);
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->ActiveTexture (GL_TEXTURE1);
+    gl->Enable (GL_TEXTURE_1D);
+    gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]);
 
-  gst_gl_shader_set_uniform_1i (shader, "curve", 1);
+    gst_gl_shader_set_uniform_1i (shader, "curve", 1);
 
-  gl->Disable (GL_TEXTURE_1D);
+    gl->Disable (GL_TEXTURE_1D);
+  }
+#endif
+  if (USING_GLES2 (context) || USING_OPENGL3 (context)) {
+    gl->ActiveTexture (GL_TEXTURE1);
+    gl->Enable (GL_TEXTURE_2D);
+    gl->BindTexture (GL_TEXTURE_2D, effects->curve[curve_index]);
+
+    gst_gl_shader_set_uniform_1i (shader, "curve", 1);
+
+    gl->Disable (GL_TEXTURE_2D);
+  }
 
   gst_gl_filter_draw_texture (filter, texture, width, height);
 }
diff --git a/ext/gl/effects/gstgleffectmirror.c b/ext/gl/effects/gstgleffectmirror.c
index 1713d54..7a88f07 100644
--- a/ext/gl/effects/gstgleffectmirror.c
+++ b/ext/gl/effects/gstgleffectmirror.c
@@ -23,12 +23,6 @@
 
 #include "../gstgleffects.h"
 
-#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
-#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1))
-#define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0))
-#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
-#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
-
 static void
 gst_gl_effects_mirror_callback (gint width, gint height, guint texture,
     gpointer data)
@@ -39,37 +33,12 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "mirror0");
+  shader = gst_gl_effects_get_fragment_shader (effects, "mirror",
+      mirror_fragment_source_gles2, mirror_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "mirror0", shader);
+  if (!shader)
+    return;
 
-    if (USING_GLES2 (context) || USING_OPENGL3 (context)) {
-      if (!gst_gl_shader_compile_with_default_v_and_check (shader,
-              mirror_fragment_source_gles2, &filter->draw_attr_position_loc,
-              &filter->draw_attr_texture_loc)) {
-        /* gst gl context error is already set */
-        GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-            ("Failed to initialize squeeze shader, %s",
-                gst_gl_context_get_error ()), (NULL));
-        return;
-      }
-    }
-#if GST_GL_HAVE_OPENGL
-    if (USING_OPENGL (context)) {
-      if (!gst_gl_shader_compile_and_check (shader,
-              mirror_fragment_source_opengl, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-        gst_gl_context_set_error (context,
-            "Failed to initialize mirror shader");
-        GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-            ("%s", gst_gl_context_get_error ()), (NULL));
-        return;
-      }
-
-    }
-#endif
-  }
 #if GST_GL_HAVE_OPENGL
   if (USING_OPENGL (context)) {
     gl->MatrixMode (GL_PROJECTION);
diff --git a/ext/gl/effects/gstgleffectrgbtocurve.c b/ext/gl/effects/gstgleffectrgbtocurve.c
index 18b0905..b34a3f3 100644
--- a/ext/gl/effects/gstgleffectrgbtocurve.c
+++ b/ext/gl/effects/gstgleffectrgbtocurve.c
@@ -34,41 +34,51 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "rgbmap0");
+  shader = gst_gl_effects_get_fragment_shader (effects, "rgb_to_curve",
+      rgb_to_curve_fragment_source_gles2, rgb_to_curve_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "rgbmap0", shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          rgb_to_curve_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context,
-        "Failed to initialize rgb to curve shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
   if (effects->curve[curve_index] == 0) {
     /* this parameters are needed to have a right, predictable, mapping */
     gl->GenTextures (1, &effects->curve[curve_index]);
-    gl->Enable (GL_TEXTURE_1D);
-    gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]);
-    gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
-    gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+#if GST_GL_HAVE_OPENGL
+    if (USING_OPENGL (context)) {
+      gl->Enable (GL_TEXTURE_1D);
+      gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]);
+      gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+      gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+      gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+      gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 
-    gl->TexImage1D (GL_TEXTURE_1D, 0, curve->bytes_per_pixel,
-        curve->width, 0, GL_RGB, GL_UNSIGNED_BYTE, curve->pixel_data);
+      gl->TexImage1D (GL_TEXTURE_1D, 0, GL_RGB,
+          curve->width, 0, GL_RGB, GL_UNSIGNED_BYTE, curve->pixel_data);
 
-    gl->Disable (GL_TEXTURE_1D);
+      gl->Disable (GL_TEXTURE_1D);
+    }
+#endif
+    if (USING_GLES2 (context) || USING_OPENGL3 (context)) {
+      gl->Enable (GL_TEXTURE_2D);
+      gl->BindTexture (GL_TEXTURE_2D, effects->curve[curve_index]);
+      gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+      gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+      gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+      gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+      gl->TexImage2D (GL_TEXTURE_2D, 0, GL_RGB,
+          curve->width, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, curve->pixel_data);
+      gl->Disable (GL_TEXTURE_2D);
+    }
   }
 
   gl->ActiveTexture (GL_TEXTURE0);
@@ -79,13 +89,26 @@
 
   gl->Disable (GL_TEXTURE_2D);
 
-  gl->ActiveTexture (GL_TEXTURE1);
-  gl->Enable (GL_TEXTURE_1D);
-  gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]);
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->ActiveTexture (GL_TEXTURE1);
+    gl->Enable (GL_TEXTURE_1D);
+    gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]);
 
-  gst_gl_shader_set_uniform_1i (shader, "curve", 1);
+    gst_gl_shader_set_uniform_1i (shader, "curve", 1);
 
-  gl->Disable (GL_TEXTURE_1D);
+    gl->Disable (GL_TEXTURE_1D);
+  }
+#endif
+  if (USING_GLES2 (context) || USING_OPENGL3 (context)) {
+    gl->ActiveTexture (GL_TEXTURE1);
+    gl->Enable (GL_TEXTURE_2D);
+    gl->BindTexture (GL_TEXTURE_2D, effects->curve[curve_index]);
+
+    gst_gl_shader_set_uniform_1i (shader, "curve", 1);
+
+    gl->Disable (GL_TEXTURE_2D);
+  }
 
   gst_gl_filter_draw_texture (filter, texture, width, height);
 }
diff --git a/ext/gl/effects/gstgleffectsin.c b/ext/gl/effects/gstgleffectsin.c
index 8d6be54..a28414d 100644
--- a/ext/gl/effects/gstgleffectsin.c
+++ b/ext/gl/effects/gstgleffectsin.c
@@ -33,23 +33,18 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "sin0");
+  shader = gst_gl_effects_get_fragment_shader (effects, "sin",
+      sin_fragment_source_gles2, sin_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "sin0", shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          sin_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context, "Failed to initialize sin shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
diff --git a/ext/gl/effects/gstgleffectsobel.c b/ext/gl/effects/gstgleffectsobel.c
new file mode 100644
index 0000000..fcb7847
--- /dev/null
+++ b/ext/gl/effects/gstgleffectsobel.c
@@ -0,0 +1,180 @@
+/*
+ * GStreamer
+ * Copyright (C) 2008-2010 Filippo Argiolas <filippo.argiolas@gmail.com>
+ * Copyright (C) 2015 Michał Dębski <debski.mi.zd@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "../gstgleffects.h"
+
+static void
+gst_gl_effects_sobel_callback_desaturate (gint width, gint height,
+    guint texture, gpointer data)
+{
+  GstGLShader *shader = NULL;
+  GstGLEffects *effects = GST_GL_EFFECTS (data);
+  GstGLFilter *filter = GST_GL_FILTER (effects);
+
+  if (NULL != (shader = gst_gl_effects_get_fragment_shader (effects, "desat0",
+              desaturate_fragment_source_gles2,
+              desaturate_fragment_source_opengl))) {
+    GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
+
+#if GST_GL_HAVE_OPENGL
+    if (USING_OPENGL (GST_GL_BASE_FILTER (filter)->context)) {
+      gl->MatrixMode (GL_PROJECTION);
+      gl->LoadIdentity ();
+    }
+#endif
+
+    gst_gl_shader_use (shader);
+
+    gl->ActiveTexture (GL_TEXTURE0);
+    gl->Enable (GL_TEXTURE_2D);
+    gl->BindTexture (GL_TEXTURE_2D, texture);
+    gl->Disable (GL_TEXTURE_2D);
+
+    gst_gl_shader_set_uniform_1i (shader, "tex", 0);
+
+    gst_gl_filter_draw_texture (filter, texture, width, height);
+  }
+}
+
+static void
+gst_gl_effects_sobel_callback_hconv (gint width, gint height, guint texture,
+    gpointer data)
+{
+  GstGLShader *shader = NULL;
+  GstGLEffects *effects = GST_GL_EFFECTS (data);
+  GstGLFilter *filter = GST_GL_FILTER (effects);
+
+  if (NULL != (shader = gst_gl_effects_get_fragment_shader (effects, "hconv0",
+              sep_sobel_hconv3_fragment_source_gles2,
+              sep_sobel_hconv3_fragment_source_opengl))) {
+    GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
+
+#if GST_GL_HAVE_OPENGL
+    if (USING_OPENGL (GST_GL_BASE_FILTER (filter)->context)) {
+      gl->MatrixMode (GL_PROJECTION);
+      gl->LoadIdentity ();
+    }
+#endif
+
+    gst_gl_shader_use (shader);
+
+    gl->ActiveTexture (GL_TEXTURE0);
+    gl->Enable (GL_TEXTURE_2D);
+    gl->BindTexture (GL_TEXTURE_2D, texture);
+    gl->Disable (GL_TEXTURE_2D);
+
+    gst_gl_shader_set_uniform_1i (shader, "tex", 0);
+    gst_gl_shader_set_uniform_1f (shader, "width", width);
+
+    gst_gl_filter_draw_texture (filter, texture, width, height);
+  }
+}
+
+static void
+gst_gl_effects_sobel_callback_vconv (gint width, gint height, guint texture,
+    gpointer data)
+{
+  GstGLShader *shader = NULL;
+  GstGLEffects *effects = GST_GL_EFFECTS (data);
+  GstGLFilter *filter = GST_GL_FILTER (effects);
+
+  if (NULL != (shader = gst_gl_effects_get_fragment_shader (effects, "vconv0",
+              sep_sobel_vconv3_fragment_source_gles2,
+              sep_sobel_vconv3_fragment_source_opengl))) {
+    GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
+
+#if GST_GL_HAVE_OPENGL
+    if (USING_OPENGL (GST_GL_BASE_FILTER (filter)->context)) {
+      gl->MatrixMode (GL_PROJECTION);
+      gl->LoadIdentity ();
+    }
+#endif
+
+    gst_gl_shader_use (shader);
+
+    gl->ActiveTexture (GL_TEXTURE0);
+    gl->Enable (GL_TEXTURE_2D);
+    gl->BindTexture (GL_TEXTURE_2D, texture);
+    gl->Disable (GL_TEXTURE_2D);
+
+    gst_gl_shader_set_uniform_1i (shader, "tex", 0);
+    gst_gl_shader_set_uniform_1f (shader, "height", height);
+
+    gst_gl_filter_draw_texture (filter, texture, width, height);
+  }
+}
+
+static void
+gst_gl_effects_sobel_callback_length (gint width, gint height, guint texture,
+    gpointer data)
+{
+  GstGLShader *shader = NULL;
+  GstGLEffects *effects = GST_GL_EFFECTS (data);
+  GstGLFilter *filter = GST_GL_FILTER (effects);
+
+  if (NULL != (shader = gst_gl_effects_get_fragment_shader (effects, "len0",
+              sep_sobel_length_fragment_source_gles2,
+              sep_sobel_length_fragment_source_opengl))) {
+    GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
+
+#if GST_GL_HAVE_OPENGL
+    if (USING_OPENGL (GST_GL_BASE_FILTER (filter)->context)) {
+      gl->MatrixMode (GL_PROJECTION);
+      gl->LoadIdentity ();
+    }
+#endif
+
+    gst_gl_shader_use (shader);
+
+    gl->ActiveTexture (GL_TEXTURE0);
+    gl->Enable (GL_TEXTURE_2D);
+    gl->BindTexture (GL_TEXTURE_2D, texture);
+    gl->Disable (GL_TEXTURE_2D);
+
+    gst_gl_shader_set_uniform_1i (shader, "tex", 0);
+    gst_gl_shader_set_uniform_1i (shader, "invert", effects->invert);
+
+    gst_gl_filter_draw_texture (filter, texture, width, height);
+  }
+}
+
+void
+gst_gl_effects_sobel (GstGLEffects * effects)
+{
+  GstGLFilter *filter = GST_GL_FILTER (effects);
+
+  gst_gl_filter_render_to_target (filter, TRUE,
+      effects->intexture, effects->midtexture[0],
+      gst_gl_effects_sobel_callback_desaturate, effects);
+  gst_gl_filter_render_to_target (filter, FALSE,
+      effects->midtexture[0], effects->midtexture[1],
+      gst_gl_effects_sobel_callback_hconv, effects);
+  gst_gl_filter_render_to_target (filter, FALSE,
+      effects->midtexture[1], effects->midtexture[0],
+      gst_gl_effects_sobel_callback_vconv, effects);
+  gst_gl_filter_render_to_target (filter, FALSE,
+      effects->midtexture[0], effects->outtexture,
+      gst_gl_effects_sobel_callback_length, effects);
+}
diff --git a/ext/gl/effects/gstgleffectsquare.c b/ext/gl/effects/gstgleffectsquare.c
index b1619c0..40dd313 100644
--- a/ext/gl/effects/gstgleffectsquare.c
+++ b/ext/gl/effects/gstgleffectsquare.c
@@ -33,23 +33,18 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "square0");
+  shader = gst_gl_effects_get_fragment_shader (effects, "square",
+      square_fragment_source_gles2, square_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "square0", shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          square_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context, "Failed to initialize square shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
@@ -59,9 +54,6 @@
 
   gst_gl_shader_set_uniform_1i (shader, "tex", 0);
 
-  gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f);
-  gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f);
-
   gst_gl_filter_draw_texture (filter, texture, width, height);
 }
 
diff --git a/ext/gl/effects/gstgleffectsqueeze.c b/ext/gl/effects/gstgleffectsqueeze.c
index 863157a..7ba5e52 100644
--- a/ext/gl/effects/gstgleffectsqueeze.c
+++ b/ext/gl/effects/gstgleffectsqueeze.c
@@ -23,12 +23,6 @@
 
 #include "../gstgleffects.h"
 
-#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
-#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1))
-#define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0))
-#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
-#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
-
 static void
 gst_gl_effects_squeeze_callback (gint width, gint height, guint texture,
     gpointer data)
@@ -39,36 +33,12 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "squeeze0");
+  shader = gst_gl_effects_get_fragment_shader (effects, "squeeze",
+      squeeze_fragment_source_gles2, squeeze_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "squeeze0", shader);
+  if (!shader)
+    return;
 
-    if (USING_GLES2 (context) || USING_OPENGL3 (context)) {
-      if (!gst_gl_shader_compile_with_default_v_and_check (shader,
-              squeeze_fragment_source_gles2, &filter->draw_attr_position_loc,
-              &filter->draw_attr_texture_loc)) {
-        /* gst gl context error is already set */
-        GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-            ("Failed to initialize squeeze shader, %s",
-                gst_gl_context_get_error ()), (NULL));
-        return;
-      }
-    }
-#if GST_GL_HAVE_OPENGL
-    if (USING_OPENGL (context)) {
-      if (!gst_gl_shader_compile_and_check (shader,
-              squeeze_fragment_source_opengl, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-        gst_gl_context_set_error (context,
-            "Failed to initialize squeeze shader");
-        GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-            ("%s", gst_gl_context_get_error ()), (NULL));
-        return;
-      }
-    }
-#endif
-  }
 #if GST_GL_HAVE_OPENGL
   if (USING_OPENGL (context)) {
     gl->MatrixMode (GL_PROJECTION);
@@ -79,8 +49,7 @@
   gst_gl_shader_use (shader);
 
   gl->ActiveTexture (GL_TEXTURE0);
-  if (USING_OPENGL (context))
-    gl->Enable (GL_TEXTURE_2D);
+  gl->Enable (GL_TEXTURE_2D);
   gl->BindTexture (GL_TEXTURE_2D, texture);
 
   gst_gl_shader_set_uniform_1i (shader, "tex", 0);
diff --git a/ext/gl/effects/gstgleffectssources.c b/ext/gl/effects/gstgleffectssources.c
index 3786503..0060ff0 100644
--- a/ext/gl/effects/gstgleffectssources.c
+++ b/ext/gl/effects/gstgleffectssources.c
@@ -65,7 +65,6 @@
 /* *INDENT-OFF* */
 
 /* Mirror effect */
-#if GST_GL_HAVE_OPENGL
 const gchar *mirror_fragment_source_opengl =
   "uniform sampler2D tex;"
   "void main () {"
@@ -77,7 +76,7 @@
   "  vec4 color = texture2D (tex, texturecoord);"
   "  gl_FragColor = color * gl_Color;"
   "}";
-#endif
+
 const gchar *mirror_fragment_source_gles2 =
   "#ifdef GL_ES\n"
   "precision mediump float;\n"
@@ -93,7 +92,6 @@
   "}";
 
 /* Squeeze effect */
-#if GST_GL_HAVE_OPENGL
 const gchar *squeeze_fragment_source_opengl =
   "uniform sampler2D tex;"
   "void main () {"
@@ -105,7 +103,7 @@
   "  texturecoord = (normcoord + 0.5);"
   "  gl_FragColor = texture2D (tex, texturecoord);"
   "}";
-#endif
+
 const gchar *squeeze_fragment_source_gles2 =
   "#ifdef GL_ES\n"
   "precision mediump float;\n"
@@ -123,7 +121,7 @@
   "}";
 
 /* Stretch Effect */
-const gchar *stretch_fragment_source =
+const gchar *stretch_fragment_source_opengl =
   "uniform sampler2D tex;"
   "void main () {"
   "  vec2 texturecoord = gl_TexCoord[0].xy;"
@@ -136,8 +134,24 @@
   "  gl_FragColor = color * gl_Color;"
   "}";
 
+const gchar *stretch_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D tex;"
+  "void main () {"
+	"  vec2 texturecoord = v_texcoord.xy;"
+  "  vec2 normcoord;"
+  "  normcoord = texturecoord - 0.5;"
+  "  float r = length (normcoord);"
+  "  normcoord *= 2.0 - smoothstep(0.0, 0.35, r);"
+  "  texturecoord = normcoord + 0.5;"
+  "  gl_FragColor = texture2D (tex, texturecoord);"
+  "}";
+
 /* Light Tunnel effect */
-const gchar *tunnel_fragment_source =
+const gchar *tunnel_fragment_source_opengl =
   "uniform sampler2D tex;"
   "void main () {"
   "  vec2 texturecoord = gl_TexCoord[0].xy;"
@@ -152,23 +166,56 @@
   "  gl_FragColor = color;"
   "}";
 
+const gchar *tunnel_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D tex;"
+  "void main () {"
+  "  vec2 texturecoord = v_texcoord.xy;"
+  "  vec2 normcoord;"
+  /* little trick with normalized coords to obtain a circle with
+   * rect textures */
+  "  normcoord = (texturecoord - 0.5);"
+  "  float r = length(normcoord);"
+  "  normcoord *= clamp (r, 0.0, 0.275) / r;"
+  "  texturecoord = normcoord + 0.5;"
+  "  gl_FragColor = texture2D (tex, texturecoord);"
+  "}";
+
 /* FishEye effect */
-const gchar *fisheye_fragment_source =
+const gchar *fisheye_fragment_source_opengl =
   "uniform sampler2D tex;"
   "void main () {"
   "  vec2 texturecoord = gl_TexCoord[0].xy;"
   "  vec2 normcoord;"
   "  normcoord = texturecoord - 0.5;"
   "  float r = length (normcoord);"
-  "  normcoord *= r * sqrt(2);"
+  "  normcoord *= r * sqrt(2.0);"
   "  texturecoord = normcoord + 0.5;"
   "  vec4 color = texture2D (tex, texturecoord);"
   "  gl_FragColor = color;"
   "}";
 
+const gchar *fisheye_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D tex;"
+  "void main () {"
+  "  vec2 texturecoord = v_texcoord.xy;"
+  "  vec2 normcoord;"
+  "  normcoord = texturecoord - 0.5;"
+  "  float r = length (normcoord);"
+  "  normcoord *= r * sqrt(2);"
+  "  texturecoord = normcoord + 0.5;"
+  "  gl_FragColor = texture2D (tex, texturecoord);"
+  "}";
 
 /* Twirl effect */
-const gchar *twirl_fragment_source =
+const gchar *twirl_fragment_source_opengl =
   "uniform sampler2D tex;"
   "void main () {"
   "  vec2 texturecoord = gl_TexCoord[0].xy;"
@@ -188,9 +235,31 @@
   "  gl_FragColor = color;"
   "}";
 
+const gchar *twirl_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+	"uniform sampler2D tex;"
+  "void main () {"
+  "  vec2 texturecoord = v_texcoord.xy;"
+  "  vec2 normcoord;"
+  "  normcoord = texturecoord - 0.5;"
+  "  float r = length (normcoord);"
+  /* calculate rotation angle: maximum (about pi/2) at the origin and
+   * gradually decrease it up to 0.6 of each quadrant */
+  "  float phi = (1.0 - smoothstep (0.0, 0.3, r)) * 1.6;"
+  /* precalculate sin phi and cos phi, save some alu */
+  "  float s = sin(phi);"
+  "  float c = cos(phi);"
+  /* rotate */
+  "  normcoord *= mat2(c, s, -s, c);"
+  "  texturecoord = normcoord + 0.5;"
+  "  gl_FragColor = texture2D (tex, texturecoord);"
+  "}";
 
 /* Bulge effect */
-const gchar *bulge_fragment_source =
+const gchar *bulge_fragment_source_opengl =
   "uniform sampler2D tex;"
   "void main () {"
   "  vec2 texturecoord = gl_TexCoord[0].xy;"
@@ -203,9 +272,24 @@
   "  gl_FragColor = color;"
   "}";
 
+const gchar *bulge_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D tex;"
+  "void main () {"
+  "  vec2 texturecoord = v_texcoord.xy;"
+  "  vec2 normcoord;"
+  "  normcoord = texturecoord - 0.5;"
+  "  float r =  length (normcoord);"
+  "  normcoord *= smoothstep (-0.05, 0.25, r);"
+  "  texturecoord = normcoord + 0.5;"
+  "  gl_FragColor = texture2D (tex, texturecoord);"
+  "}";
 
 /* Square Effect */
-const gchar *square_fragment_source =
+const gchar *square_fragment_source_opengl =
   "uniform sampler2D tex;"
   "void main () {"
   "  vec2 texturecoord = gl_TexCoord[0].xy;"
@@ -219,8 +303,24 @@
   "  gl_FragColor = color * gl_Color;"
   "}";
 
+const gchar *square_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D tex;"
+  "void main () {"
+  "  vec2 texturecoord = v_texcoord.xy;"
+  "  vec2 normcoord;"
+  "  normcoord = texturecoord - 0.5;"
+  "  float r = length (normcoord);"
+  "  normcoord *= 1.0 + smoothstep(0.125, 0.25, abs(normcoord));"
+  "  normcoord /= 2.0; /* zoom amount */"
+  "  texturecoord = normcoord + 0.5;"
+  "  gl_FragColor = texture2D (tex, texturecoord);"
+  "}";
 
-const gchar *luma_threshold_fragment_source =
+const gchar *luma_threshold_fragment_source_opengl =
   "uniform sampler2D tex;"
   "void main () {"
   "  vec2 texturecoord = gl_TexCoord[0].st;"
@@ -229,7 +329,20 @@
   "  gl_FragColor = vec4 (vec3 (smoothstep (0.30, 0.50, luma)), color.a);"
   "}";
 
-const gchar *sep_sobel_length_fragment_source =
+const gchar *luma_threshold_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D tex;"
+  "void main () {"
+  "  vec2 texturecoord = v_texcoord.xy;"
+  "  vec4 color = texture2D(tex, texturecoord);"
+  "  float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));"    /* BT.709 (from orange book) */
+  "  gl_FragColor = vec4 (vec3 (smoothstep (0.30, 0.50, luma)), color.a);"
+  "}";
+
+const gchar *sep_sobel_length_fragment_source_opengl =
   "uniform sampler2D tex;"
   "uniform bool invert;"
   "void main () {"
@@ -242,7 +355,24 @@
   "  gl_FragColor = abs(vec4(vec3(float(invert) - len), 1.0));"
   "}";
 
-const gchar *desaturate_fragment_source =
+const gchar *sep_sobel_length_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D tex;"
+  "uniform bool invert;"
+  "void main () {"
+  "  vec4 g = texture2D (tex, v_texcoord.xy);"
+  /* restore black background with grey edges */
+  "  g -= vec4(0.5, 0.5, 0.0, 0.0);"
+  "  float len = length (g);"
+  /* little trick to avoid IF operator */
+  /* TODO: test if a standalone inverting pass is worth */
+  "  gl_FragColor = abs(vec4(vec3(float(invert) - len), 1.0));"
+  "}";
+
+const gchar *desaturate_fragment_source_opengl =
   "uniform sampler2D tex;"
   "void main () {"
   "  vec4 color = texture2D (tex, gl_TexCoord[0].st);"
@@ -250,7 +380,19 @@
   "  gl_FragColor = vec4(vec3(luma), color.a);"
   "}";
 
-const gchar *sep_sobel_hconv3_fragment_source =
+const gchar *desaturate_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D tex;"
+  "void main () {"
+  "  vec4 color = texture2D (tex, v_texcoord.xy);"
+  "  float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));"
+  "  gl_FragColor = vec4(vec3(luma), color.a);"
+  "}";
+
+const gchar *sep_sobel_hconv3_fragment_source_opengl =
   "uniform sampler2D tex;"
   "uniform float width;"
   "void main () {"
@@ -277,7 +419,38 @@
   "  gl_FragColor = sum + vec4(0.0, 0.5, 0.0, 0.0);"
   "}";
 
-const gchar *sep_sobel_vconv3_fragment_source =
+const gchar *sep_sobel_hconv3_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D tex;"
+  "uniform float width;"
+  "void main () {"
+  "  float w = 1.0 / width;"
+  "  vec2 texturecoord[3];"
+  "  texturecoord[1] = v_texcoord.xy;"
+  "  texturecoord[0] = texturecoord[1] - vec2(w, 0.0);"
+  "  texturecoord[2] = texturecoord[1] + vec2(w, 0.0);"
+  "  float grad_kern[3];"
+  "  grad_kern[0] = 1.0;"
+  "  grad_kern[1] = 0.0;"
+  "  grad_kern[2] = -1.0;"
+  "  float blur_kern[3];"
+  "  blur_kern[0] = 0.25;"
+  "  blur_kern[1] = 0.5;"
+  "  blur_kern[2] = 0.25;"
+  "  int i;"
+  "  vec4 sum = vec4 (0.0);"
+  "  for (i = 0; i < 3; i++) { "
+  "    vec4 neighbor = texture2D(tex, texturecoord[i]); "
+  "    sum.r = neighbor.r * blur_kern[i] + sum.r;"
+  "    sum.g = neighbor.g * grad_kern[i] + sum.g;"
+  "  }"
+  "  gl_FragColor = sum + vec4(0.0, 0.5, 0.0, 0.0);"
+  "}";
+
+const gchar *sep_sobel_vconv3_fragment_source_opengl =
   "uniform sampler2D tex;"
   "uniform float height;"
   "void main () {"
@@ -304,13 +477,44 @@
   "  gl_FragColor = sum + vec4(0.5, 0.0, 0.0, 0.0);"
   "}";
 
+const gchar *sep_sobel_vconv3_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D tex;"
+  "uniform float height;"
+  "void main () {"
+  "  float h = 1.0 / height;"
+  "  vec2 texturecoord[3];"
+  "  texturecoord[1] = v_texcoord.xy;"
+  "  texturecoord[0] = texturecoord[1] - vec2(0.0, h);"
+  "  texturecoord[2] = texturecoord[1] + vec2(0.0, h);"
+  "  float grad_kern[3];"
+  "  grad_kern[0] = 1.0;"
+  "  grad_kern[1] = 0.0;"
+  "  grad_kern[2] = -1.0;"
+  "  float blur_kern[3];"
+  "  blur_kern[0] = 0.25;"
+  "  blur_kern[1] = 0.5;"
+  "  blur_kern[2] = 0.25;"
+  "  int i;"
+  "  vec4 sum = vec4 (0.0);"
+  "  for (i = 0; i < 3; i++) { "
+  "    vec4 neighbor = texture2D(tex, texturecoord[i]); "
+  "    sum.r = neighbor.r * grad_kern[i] + sum.r;"
+  "    sum.g = neighbor.g * blur_kern[i] + sum.g;"
+  "  }"
+  "  gl_FragColor = sum + vec4(0.5, 0.0, 0.0, 0.0);"
+  "}";
+
 /* horizontal convolution 7x7 */
-const gchar *hconv7_fragment_source =
+const gchar *hconv7_fragment_source_opengl =
   "uniform sampler2D tex;"
   "uniform float kernel[7];"
-  "uniform float width;"
+  "uniform float gauss_width;"
   "void main () {"
-  "  float w = 1.0 / width;"
+  "  float w = 1.0 / gauss_width;"
   "  vec2 texturecoord[7];"
   "  texturecoord[3] = gl_TexCoord[0].st;"
   "  texturecoord[2] = texturecoord[3] - vec2(w, 0.0);"
@@ -328,13 +532,40 @@
   "  gl_FragColor = sum;"
   "}";
 
-/* vertical convolution 7x7 */
-const gchar *vconv7_fragment_source =
+const gchar *hconv7_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "uniform float kernel[7];"
-  "uniform float height;"
+  "uniform float gauss_width;"
   "void main () {"
-  "  float h = 1.0 / height;"
+  "  float w = 1.0 / gauss_width;"
+  "  vec2 texturecoord[7];"
+  "  texturecoord[3] = v_texcoord.xy;"
+  "  texturecoord[2] = texturecoord[3] - vec2(w, 0.0);"
+  "  texturecoord[1] = texturecoord[2] - vec2(w, 0.0);"
+  "  texturecoord[0] = texturecoord[1] - vec2(w, 0.0);"
+  "  texturecoord[4] = texturecoord[3] + vec2(w, 0.0);"
+  "  texturecoord[5] = texturecoord[4] + vec2(w, 0.0);"
+  "  texturecoord[6] = texturecoord[5] + vec2(w, 0.0);"
+  "  int i;"
+  "  vec4 sum = vec4 (0.0);"
+  "  for (i = 0; i < 7; i++) { "
+  "    vec4 neighbor = texture2D(tex, texturecoord[i]); "
+  "    sum += neighbor * kernel[i];"
+  "  }"
+  "  gl_FragColor = sum;"
+  "}";
+
+/* vertical convolution 7x7 */
+const gchar *vconv7_fragment_source_opengl =
+  "uniform sampler2D tex;"
+  "uniform float kernel[7];"
+  "uniform float gauss_height;"
+  "void main () {"
+  "  float h = 1.0 / gauss_height;"
   "  vec2 texturecoord[7];"
   "  texturecoord[3] = gl_TexCoord[0].st;"
   "  texturecoord[2] = texturecoord[3] - vec2(0.0, h);"
@@ -352,9 +583,35 @@
   "  gl_FragColor = sum;"
   "}";
 
+const gchar *vconv7_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D tex;"
+  "uniform float kernel[7];"
+  "uniform float gauss_height;"
+  "void main () {"
+  "  float h = 1.0 / gauss_height;"
+  "  vec2 texturecoord[7];"
+  "  texturecoord[3] = v_texcoord.xy;"
+  "  texturecoord[2] = texturecoord[3] - vec2(0.0, h);"
+  "  texturecoord[1] = texturecoord[2] - vec2(0.0, h);"
+  "  texturecoord[0] = texturecoord[1] - vec2(0.0, h);"
+  "  texturecoord[4] = texturecoord[3] + vec2(0.0, h);"
+  "  texturecoord[5] = texturecoord[4] + vec2(0.0, h);"
+  "  texturecoord[6] = texturecoord[5] + vec2(0.0, h);"
+  "  int i;"
+  "  vec4 sum = vec4 (0.0);"
+  "  for (i = 0; i < 7; i++) { "
+  "    vec4 neighbor = texture2D(tex, texturecoord[i]);"
+  "    sum += neighbor * kernel[i];"
+  "  }"
+  "  gl_FragColor = sum;"
+  "}";
 
 /* TODO: support several blend modes */
-const gchar *sum_fragment_source =
+const gchar *sum_fragment_source_opengl =
   "uniform sampler2D base;"
   "uniform sampler2D blend;"
   "uniform float alpha;"
@@ -365,7 +622,22 @@
   "  gl_FragColor = alpha * basecolor + beta * blendcolor;"
   "}";
 
-const gchar *multiply_fragment_source =
+const gchar *sum_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D base;"
+  "uniform sampler2D blend;"
+  "uniform float alpha;"
+  "uniform float beta;"
+  "void main () {"
+  "  vec4 basecolor = texture2D (base, v_texcoord.xy);"
+  "  vec4 blendcolor = texture2D (blend, v_texcoord.xy);"
+  "  gl_FragColor = alpha * basecolor + beta * blendcolor;"
+  "}";
+
+const gchar *multiply_fragment_source_opengl =
   "uniform sampler2D base;"
   "uniform sampler2D blend;"
   "uniform float alpha;"
@@ -375,8 +647,22 @@
   "  gl_FragColor = (1.0 - alpha) * basecolor + alpha * basecolor * blendcolor;"
   "}";
 
+const gchar *multiply_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D base;"
+  "uniform sampler2D blend;"
+  "uniform float alpha;"
+  "void main () {"
+  "  vec4 basecolor = texture2D (base, v_texcoord.xy);"
+  "  vec4 blendcolor = texture2D (blend, v_texcoord.xy);"
+  "  gl_FragColor = (1.0 - alpha) * basecolor + alpha * basecolor * blendcolor;"
+  "}";
+
 /* lut operations, map luma to tex1d, see orange book (chapter 19) */
-const gchar *luma_to_curve_fragment_source =
+const gchar *luma_to_curve_fragment_source_opengl =
   "uniform sampler2D tex;"
   "uniform sampler1D curve;"
   "void main () {"
@@ -387,9 +673,23 @@
   "  gl_FragColor = color;"
   "}";
 
+const gchar *luma_to_curve_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D tex;"
+  "uniform sampler2D curve;"
+  "void main () {"
+  "  vec2 texturecoord = v_texcoord.xy;"
+  "  vec4 color = texture2D (tex, texturecoord);"
+  "  float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));"
+  "  color = texture2D (curve, vec2(luma, 0.0));"
+  "  gl_FragColor = color;"
+  "}";
 
 /* lut operations, map rgb to tex1d, see orange book (chapter 19) */
-const gchar *rgb_to_curve_fragment_source =
+const gchar *rgb_to_curve_fragment_source_opengl =
   "uniform sampler2D tex;"
   "uniform sampler1D curve;"
   "void main () {"
@@ -402,7 +702,24 @@
   "  gl_FragColor = outcolor;"
   "}";
 
-const gchar *sin_fragment_source =
+const gchar *rgb_to_curve_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D tex;"
+  "uniform sampler2D curve;"
+  "void main () {"
+  "  vec4 color = texture2D (tex, v_texcoord.xy);"
+  "  vec4 outcolor;"
+  "  outcolor.r = texture2D (curve, vec2(color.r, 0.0)).r;"
+  "  outcolor.g = texture2D (curve, vec2(color.g, 0.0)).g;"
+  "  outcolor.b = texture2D (curve, vec2(color.b, 0.0)).b;"
+  "  outcolor.a = color.a;"
+  "  gl_FragColor = outcolor;"
+  "}";
+
+const gchar *sin_fragment_source_opengl =
   "uniform sampler2D tex;"
   "void main () {"
   "  vec4 color = texture2D (tex, vec2(gl_TexCoord[0].st));"
@@ -427,6 +744,35 @@
   "  gl_FragColor = color * mix + luma * (1.0 - mix);"
   "}";
 
+const gchar *sin_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D tex;"
+  "void main () {"
+  "  vec4 color = texture2D (tex, vec2(v_texcoord.xy));"
+  "  float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));"
+/* calculate hue with the Preucil formula */
+  "  float cosh = color.r - 0.5*(color.g + color.b);"
+/* sqrt(3)/2 = 0.866 */
+  "  float sinh = 0.866*(color.g - color.b);"
+/* hue = atan2 h */
+  "  float sch = (1.0-sinh)*cosh;"
+/* ok this is a little trick I came up because I didn't find any
+ * detailed proof of the Preucil formula. The issue is that tan(h) is
+ * pi-periodic so the smoothstep thing gives both reds (h = 0) and
+ * cyans (h = 180). I don't want to use atan since it requires
+ * branching and doesn't work on i915. So take only the right half of
+ * the circle where cosine is positive */
+/* take a slightly purple color trying to get rid of human skin reds */
+/* tanh = +-1.0 for h = +-45, where yellow=60, magenta=-60 */
+  "  float a = smoothstep (0.3, 1.0, sch);"
+  "  float b = smoothstep (-0.4, -0.1, sinh);"
+  "  float mix = a * b;"
+  "  gl_FragColor = color * mix + luma * (1.0 - mix);"
+  "}";
+
 const gchar *interpolate_fragment_source =
   "uniform sampler2D base;"
   "uniform sampler2D blend;"
@@ -457,4 +803,66 @@
   "gl_FragColor = vec4 (step (0.12, length (savedcolor - currentcolor)));"
   "}";
 
+/* This filter is meant as a demo of gst-plugins-gl + glsl
+   capabilities. So I'm keeping this shader readable enough. If and
+   when this shader will be used in production be careful to hard code
+   kernel into the shader and remove unneeded zero multiplications in
+   the convolution */
+const gchar *conv9_fragment_source_opengl =
+  "uniform sampler2D tex;"
+  "uniform float kernel[9];"
+  "uniform float width, height;"
+  "uniform bool invert;"
+  "void main () {"
+  "  float w = 1.0 / width;"
+  "  float h = 1.0 / height;"
+  "  vec2 texturecoord[9];"
+  "  texturecoord[4] = gl_TexCoord[0].st;"                /*  0  0 */
+  "  texturecoord[5] = texturecoord[4] + vec2(w,   0.0);" /*  1  0 */
+  "  texturecoord[2] = texturecoord[5] - vec2(0.0, h);"   /*  1 -1 */
+  "  texturecoord[1] = texturecoord[2] - vec2(w,   0.0);" /*  0 -1 */
+  "  texturecoord[0] = texturecoord[1] - vec2(w,   0.0);" /* -1 -1 */
+  "  texturecoord[3] = texturecoord[0] + vec2(0.0, h);"   /* -1  0 */
+  "  texturecoord[6] = texturecoord[3] + vec2(0.0, h);"   /* -1  1 */
+  "  texturecoord[7] = texturecoord[6] + vec2(w,   0.0);" /*  0  1 */
+  "  texturecoord[8] = texturecoord[7] + vec2(w,   0.0);" /*  1  1 */
+  "  int i;"
+  "  vec3 sum = vec3 (0.0);"
+  "  for (i = 0; i < 9; i++) { "
+  "    vec4 neighbor = texture2D (tex, texturecoord[i]);"
+  "    sum += neighbor.xyz * kernel[i];"
+  "  }"
+  "  gl_FragColor = vec4 (abs(sum - vec3(float(invert))), 1.0);"
+  "}";
+
+const gchar *conv9_fragment_source_gles2 =
+  "#ifdef GL_ES\n"
+  "precision mediump float;\n"
+  "#endif\n"
+  "varying vec2 v_texcoord;"
+  "uniform sampler2D tex;"
+  "uniform float kernel[9];"
+  "uniform float width, height;"
+  "void main () {"
+  "  float w = 1.0 / width;"
+  "  float h = 1.0 / height;"
+  "  vec2 texturecoord[9];"
+  "  texturecoord[4] = v_texcoord.xy;"                    /*  0  0 */
+  "  texturecoord[5] = texturecoord[4] + vec2(w,   0.0);" /*  1  0 */
+  "  texturecoord[2] = texturecoord[5] - vec2(0.0, h);"   /*  1 -1 */
+  "  texturecoord[1] = texturecoord[2] - vec2(w,   0.0);" /*  0 -1 */
+  "  texturecoord[0] = texturecoord[1] - vec2(w,   0.0);" /* -1 -1 */
+  "  texturecoord[3] = texturecoord[0] + vec2(0.0, h);"   /* -1  0 */
+  "  texturecoord[6] = texturecoord[3] + vec2(0.0, h);"   /* -1  1 */
+  "  texturecoord[7] = texturecoord[6] + vec2(w,   0.0);" /*  0  1 */
+  "  texturecoord[8] = texturecoord[7] + vec2(w,   0.0);" /*  1  1 */
+  "  int i;"
+  "  vec3 sum = vec3 (0.0);"
+  "  for (i = 0; i < 9; i++) { "
+  "    vec4 neighbor = texture2D (tex, texturecoord[i]);"
+  "    sum += neighbor.xyz * kernel[i];"
+  "  }"
+  "  gl_FragColor = vec4 (abs(sum - vec3(float(invert))), 1.0);"
+  "}";
+
 /* *INDENT-ON* */
diff --git a/ext/gl/effects/gstgleffectssources.h b/ext/gl/effects/gstgleffectssources.h
index 76f0b5e..6e41c72 100644
--- a/ext/gl/effects/gstgleffectssources.h
+++ b/ext/gl/effects/gstgleffectssources.h
@@ -21,35 +21,53 @@
 #ifndef __GST_GL_EFFECTS_SOURCES_H__
 #define __GST_GL_EFFECTS_SOURCES_H__
 
-#if GST_GL_HAVE_OPENGL
 extern const gchar *mirror_fragment_source_opengl;
 extern const gchar *squeeze_fragment_source_opengl;
-#endif
+extern const gchar *stretch_fragment_source_opengl;
+extern const gchar *fisheye_fragment_source_opengl;
+extern const gchar *twirl_fragment_source_opengl;
+extern const gchar *bulge_fragment_source_opengl;
+extern const gchar *tunnel_fragment_source_opengl;
+extern const gchar *square_fragment_source_opengl;
+extern const gchar *luma_threshold_fragment_source_opengl;
+extern const gchar *hconv7_fragment_source_opengl;
+extern const gchar *vconv7_fragment_source_opengl;
+extern const gchar *sum_fragment_source_opengl;
+extern const gchar *luma_to_curve_fragment_source_opengl;
+extern const gchar *rgb_to_curve_fragment_source_opengl;
+extern const gchar *sin_fragment_source_opengl;
+extern const gchar *desaturate_fragment_source_opengl;
+extern const gchar *sep_sobel_hconv3_fragment_source_opengl;
+extern const gchar *sep_sobel_vconv3_fragment_source_opengl;
+extern const gchar *sep_sobel_length_fragment_source_opengl;
+extern const gchar *multiply_fragment_source_opengl;
+extern const gchar *conv9_fragment_source_opengl;
 
 extern const gchar *mirror_fragment_source_gles2;
 extern const gchar *squeeze_fragment_source_gles2;
+extern const gchar *stretch_fragment_source_gles2;
+extern const gchar *fisheye_fragment_source_gles2;
+extern const gchar *twirl_fragment_source_gles2;
+extern const gchar *bulge_fragment_source_gles2;
+extern const gchar *tunnel_fragment_source_gles2;
+extern const gchar *square_fragment_source_gles2;
+extern const gchar *luma_threshold_fragment_source_gles2;
+extern const gchar *hconv7_fragment_source_gles2;
+extern const gchar *vconv7_fragment_source_gles2;
+extern const gchar *sum_fragment_source_gles2;
+extern const gchar *luma_to_curve_fragment_source_gles2;
+extern const gchar *rgb_to_curve_fragment_source_gles2;
+extern const gchar *sin_fragment_source_gles2;
+extern const gchar *desaturate_fragment_source_gles2;
+extern const gchar *sep_sobel_hconv3_fragment_source_gles2;
+extern const gchar *sep_sobel_vconv3_fragment_source_gles2;
+extern const gchar *sep_sobel_length_fragment_source_gles2;
+extern const gchar *multiply_fragment_source_gles2;
+extern const gchar *conv9_fragment_source_gles2;
 
-extern const gchar *stretch_fragment_source;
-extern const gchar *tunnel_fragment_source;
-extern const gchar *fisheye_fragment_source;
-extern const gchar *twirl_fragment_source;
-extern const gchar *bulge_fragment_source;
-extern const gchar *square_fragment_source;
-extern const gchar *luma_threshold_fragment_source;
-extern const gchar *sep_sobel_length_fragment_source;
-extern const gchar *desaturate_fragment_source;
-extern const gchar *sep_sobel_hconv3_fragment_source;
-extern const gchar *sep_sobel_vconv3_fragment_source;
-extern const gchar *hconv7_fragment_source;
-extern const gchar *vconv7_fragment_source;
-extern const gchar *sum_fragment_source;
-extern const gchar *luma_to_curve_fragment_source;
-extern const gchar *rgb_to_curve_fragment_source;
-extern const gchar *sin_fragment_source;
 extern const gchar *interpolate_fragment_source;
 extern const gchar *texture_interp_fragment_source;
 extern const gchar *difference_fragment_source;
-extern const gchar *multiply_fragment_source;
 
 void fill_gaussian_kernel (float *kernel, int size, float sigma);
 
diff --git a/ext/gl/effects/gstgleffectstretch.c b/ext/gl/effects/gstgleffectstretch.c
index 206a097..0c645f9 100644
--- a/ext/gl/effects/gstgleffectstretch.c
+++ b/ext/gl/effects/gstgleffectstretch.c
@@ -33,24 +33,18 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "stretch0");
+  shader = gst_gl_effects_get_fragment_shader (effects, "stretch",
+      stretch_fragment_source_gles2, stretch_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "stretch0", shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          stretch_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context, "Failed to initialize stretch shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
+
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
   }
-
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
-
+#endif
   gst_gl_shader_use (shader);
 
   gl->ActiveTexture (GL_TEXTURE0);
@@ -59,9 +53,6 @@
 
   gst_gl_shader_set_uniform_1i (shader, "tex", 0);
 
-  gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f);
-  gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f);
-
   gst_gl_filter_draw_texture (filter, texture, width, height);
 }
 
diff --git a/ext/gl/effects/gstgleffecttunnel.c b/ext/gl/effects/gstgleffecttunnel.c
index b547436..3bacdae 100644
--- a/ext/gl/effects/gstgleffecttunnel.c
+++ b/ext/gl/effects/gstgleffecttunnel.c
@@ -33,23 +33,18 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "tunnel0");
+  shader = gst_gl_effects_get_fragment_shader (effects, "tunnel",
+      tunnel_fragment_source_gles2, tunnel_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "tunnel0", shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          tunnel_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context, "Failed to initialize tunnel shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
@@ -59,9 +54,6 @@
 
   gst_gl_shader_set_uniform_1i (shader, "tex", 0);
 
-  gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f);
-  gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f);
-
   gst_gl_filter_draw_texture (filter, texture, width, height);
 }
 
diff --git a/ext/gl/effects/gstgleffecttwirl.c b/ext/gl/effects/gstgleffecttwirl.c
index 3a9b374..2061c87 100644
--- a/ext/gl/effects/gstgleffecttwirl.c
+++ b/ext/gl/effects/gstgleffecttwirl.c
@@ -33,23 +33,18 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "twirl0");
+  shader = gst_gl_effects_get_fragment_shader (effects, "twirl",
+      twirl_fragment_source_gles2, twirl_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "twirl0", shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          twirl_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context, "Failed to initialize twirl shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
@@ -59,9 +54,6 @@
 
   gst_gl_shader_set_uniform_1i (shader, "tex", 0);
 
-  gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f);
-  gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f);
-
   gst_gl_filter_draw_texture (filter, texture, width, height);
 }
 
diff --git a/ext/gl/effects/gstgleffectxray.c b/ext/gl/effects/gstgleffectxray.c
index 79aeca1..5f104df 100644
--- a/ext/gl/effects/gstgleffectxray.c
+++ b/ext/gl/effects/gstgleffectxray.c
@@ -48,28 +48,22 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "xray1");
+  shader = gst_gl_effects_get_fragment_shader (effects, "hconv7",
+      hconv7_fragment_source_gles2, hconv7_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "xray1", shader);
-  }
+  if (!shader)
+    return;
 
   if (!kernel_ready) {
     fill_gaussian_kernel (gauss_kernel, 7, 1.5);
     kernel_ready = TRUE;
   }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          hconv7_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context, "Failed to initialize hconv7 shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
-    return;
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
   }
-
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#endif
 
   gst_gl_shader_use (shader);
 
@@ -80,7 +74,7 @@
 
   gst_gl_shader_set_uniform_1i (shader, "tex", 1);
   gst_gl_shader_set_uniform_1fv (shader, "kernel", 9, gauss_kernel);
-  gst_gl_shader_set_uniform_1f (shader, "width", width);
+  gst_gl_shader_set_uniform_1f (shader, "gauss_width", width);
 
   gst_gl_filter_draw_texture (filter, texture, width, height);
 }
@@ -95,23 +89,18 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "xray2");
+  shader = gst_gl_effects_get_fragment_shader (effects, "vconv7",
+      vconv7_fragment_source_gles2, vconv7_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "xray2", shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          vconv7_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context, "Failed to initialize vconv7 shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
@@ -122,7 +111,7 @@
 
   gst_gl_shader_set_uniform_1i (shader, "tex", 1);
   gst_gl_shader_set_uniform_1fv (shader, "kernel", 9, gauss_kernel);
-  gst_gl_shader_set_uniform_1f (shader, "height", height);
+  gst_gl_shader_set_uniform_1f (shader, "gauss_height", height);
 
   gst_gl_filter_draw_texture (filter, texture, width, height);
 }
@@ -138,24 +127,18 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "xray_desat");
+  shader = gst_gl_effects_get_fragment_shader (effects, "desaturate",
+      desaturate_fragment_source_gles2, desaturate_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "xray_desat", shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          desaturate_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context,
-        "Failed to initialize desaturate shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
@@ -178,25 +161,19 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "xray_sob_hconv");
+  shader = gst_gl_effects_get_fragment_shader (effects, "sobel_hconv3",
+      sep_sobel_hconv3_fragment_source_gles2,
+      sep_sobel_hconv3_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "xray_sob_hconv",
-        shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          sep_sobel_hconv3_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context,
-        "Failed to initialize sobel hvonc3 shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
@@ -221,25 +198,19 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "xray_sob_vconv");
+  shader = gst_gl_effects_get_fragment_shader (effects, "sobel_vconv3",
+      sep_sobel_vconv3_fragment_source_gles2,
+      sep_sobel_vconv3_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "xray_sob_vconv",
-        shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          sep_sobel_vconv3_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context,
-        "Failed to initialize sobel vconv3 shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
@@ -264,25 +235,19 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "xray_sob_len");
+  shader = gst_gl_effects_get_fragment_shader (effects, "sobel_length",
+      sep_sobel_length_fragment_source_gles2,
+      sep_sobel_length_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "xray_sob_len",
-        shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          sep_sobel_length_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context,
-        "Failed to initialize seobel length shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
@@ -308,23 +273,18 @@
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
   GstGLFuncs *gl = context->gl_vtable;
 
-  shader = g_hash_table_lookup (effects->shaderstable, "xray4");
+  shader = gst_gl_effects_get_fragment_shader (effects, "multiply",
+      multiply_fragment_source_gles2, multiply_fragment_source_opengl);
 
-  if (!shader) {
-    shader = gst_gl_shader_new (context);
-    g_hash_table_insert (effects->shaderstable, (gchar *) "xray4", shader);
-  }
-
-  if (!gst_gl_shader_compile_and_check (shader,
-          multiply_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-    gst_gl_context_set_error (context, "Failed to initialize multiply shader");
-    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
-        ("%s", gst_gl_context_get_error ()), (NULL));
+  if (!shader)
     return;
-  }
 
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
+#if GST_GL_HAVE_OPENGL
+  if (USING_OPENGL (context)) {
+    gl->MatrixMode (GL_PROJECTION);
+    gl->LoadIdentity ();
+  }
+#endif
 
   gst_gl_shader_use (shader);
 
diff --git a/ext/gl/gstglbasemixer.c b/ext/gl/gstglbasemixer.c
index f2eaa2f..0e670e0 100644
--- a/ext/gl/gstglbasemixer.c
+++ b/ext/gl/gstglbasemixer.c
@@ -41,7 +41,6 @@
     GValue * value, GParamSpec * pspec);
 static void gst_gl_base_mixer_pad_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
-static void gst_gl_base_mixer_pad_finalize (GObject * object);
 
 static void gst_gl_base_mixer_set_context (GstElement * element,
     GstContext * context);
@@ -81,20 +80,12 @@
   gobject_class->set_property = gst_gl_base_mixer_pad_set_property;
   gobject_class->get_property = gst_gl_base_mixer_pad_get_property;
 
-  gobject_class->finalize = gst_gl_base_mixer_pad_finalize;
-
   vaggpad_class->set_info = NULL;
   vaggpad_class->prepare_frame = NULL;
   vaggpad_class->clean_frame = NULL;
 }
 
 static void
-gst_gl_base_mixer_pad_finalize (GObject * object)
-{
-  G_OBJECT_CLASS (gst_gl_base_mixer_pad_parent_class)->finalize (object);
-}
-
-static void
 gst_gl_base_mixer_pad_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec)
 {
@@ -256,8 +247,6 @@
     GstBufferPool * pool, GstAllocator * allocator,
     GstAllocationParams * params, GstQuery * query);
 
-static void gst_gl_base_mixer_finalize (GObject * object);
-
 static void
 gst_gl_base_mixer_class_init (GstGLBaseMixerClass * klass)
 {
@@ -275,8 +264,6 @@
 
   g_type_class_add_private (klass, sizeof (GstGLBaseMixerPrivate));
 
-  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_gl_base_mixer_finalize);
-
   gobject_class->get_property = gst_gl_base_mixer_get_property;
   gobject_class->set_property = gst_gl_base_mixer_set_property;
 
@@ -323,19 +310,6 @@
 }
 
 static void
-gst_gl_base_mixer_finalize (GObject * object)
-{
-  GstGLBaseMixer *mix = GST_GL_BASE_MIXER (object);
-
-  if (mix->priv->other_context) {
-    gst_object_unref (mix->priv->other_context);
-    mix->priv->other_context = NULL;
-  }
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
 gst_gl_base_mixer_set_context (GstElement * element, GstContext * context)
 {
   GstGLBaseMixer *mix = GST_GL_BASE_MIXER (element);
@@ -493,6 +467,7 @@
   _find_local_gl_context (mix);
 
   if (!mix->context) {
+    GST_OBJECT_LOCK (mix->display);
     do {
       if (mix->context)
         gst_object_unref (mix->context);
@@ -506,6 +481,7 @@
           goto context_error;
       }
     } while (!gst_gl_display_add_context (mix->display, mix->context));
+    GST_OBJECT_UNLOCK (mix->display);
   }
 
   if (mix_class->decide_allocation)
@@ -681,11 +657,6 @@
     mix->priv->pool = NULL;
   }
 
-  if (mix->display) {
-    gst_object_unref (mix->display);
-    mix->display = NULL;
-  }
-
   if (mix->context) {
     gst_object_unref (mix->context);
     mix->context = NULL;
@@ -724,6 +695,17 @@
     return ret;
 
   switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      if (mix->priv->other_context) {
+        gst_object_unref (mix->priv->other_context);
+        mix->priv->other_context = NULL;
+      }
+
+      if (mix->display) {
+        gst_object_unref (mix->display);
+        mix->display = NULL;
+      }
+      break;
     default:
       break;
   }
diff --git a/ext/gl/gstglcolorconvertelement.c b/ext/gl/gstglcolorconvertelement.c
index a3118f8..833d07e 100644
--- a/ext/gl/gstglcolorconvertelement.c
+++ b/ext/gl/gstglcolorconvertelement.c
@@ -35,7 +35,6 @@
         "glconvertelement", 0, "convert");
     );
 
-static void gst_gl_color_convert_element_finalize (GObject * object);
 static gboolean gst_gl_color_convert_element_set_caps (GstBaseTransform * bt,
     GstCaps * in_caps, GstCaps * out_caps);
 static GstCaps *gst_gl_color_convert_element_transform_caps (GstBaseTransform *
@@ -49,6 +48,8 @@
     GstBuffer * inbuf, GstBuffer ** outbuf);
 static GstFlowReturn gst_gl_color_convert_element_transform (GstBaseTransform *
     bt, GstBuffer * inbuf, GstBuffer * outbuf);
+static GstCaps *gst_gl_color_convert_element_fixate_caps (GstBaseTransform *
+    bt, GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
 
 static GstStaticPadTemplate gst_gl_color_convert_element_src_pad_template =
 GST_STATIC_PAD_TEMPLATE ("src",
@@ -62,6 +63,24 @@
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS (GST_GL_COLOR_CONVERT_VIDEO_CAPS));
 
+static gboolean
+gst_gl_color_convert_element_stop (GstBaseTransform * bt)
+{
+  GstGLColorConvertElement *convert = GST_GL_COLOR_CONVERT_ELEMENT (bt);
+
+  if (convert->convert) {
+    gst_object_unref (convert->convert);
+    convert->convert = NULL;
+  }
+
+  gst_caps_replace (&convert->in_caps, NULL);
+  gst_caps_replace (&convert->out_caps, NULL);
+
+  return
+      GST_BASE_TRANSFORM_CLASS (gst_gl_color_convert_element_parent_class)->stop
+      (bt);
+}
+
 static void
 gst_gl_color_convert_element_class_init (GstGLColorConvertElementClass * klass)
 {
@@ -75,6 +94,8 @@
   bt_class->prepare_output_buffer =
       gst_gl_color_convert_element_prepare_output_buffer;
   bt_class->transform = gst_gl_color_convert_element_transform;
+  bt_class->stop = gst_gl_color_convert_element_stop;
+  bt_class->fixate_caps = gst_gl_color_convert_element_fixate_caps;
 
   bt_class->passthrough_on_same_caps = TRUE;
 
@@ -89,8 +110,6 @@
       "OpenGL color converter", "Filter/Converter/Video",
       "Converts between color spaces using OpenGL shaders",
       "Matthew Waters <matthew@centricular.com>");
-
-  G_OBJECT_CLASS (klass)->finalize = gst_gl_color_convert_element_finalize;
 }
 
 static void
@@ -100,17 +119,6 @@
       TRUE);
 }
 
-static void
-gst_gl_color_convert_element_finalize (GObject * object)
-{
-  GstGLColorConvertElement *convert = GST_GL_COLOR_CONVERT_ELEMENT (object);
-
-  gst_caps_replace (&convert->in_caps, NULL);
-  gst_caps_replace (&convert->out_caps, NULL);
-
-  G_OBJECT_CLASS (gst_gl_color_convert_element_parent_class)->finalize (object);
-}
-
 static gboolean
 gst_gl_color_convert_element_set_caps (GstBaseTransform * bt,
     GstCaps * in_caps, GstCaps * out_caps)
@@ -206,3 +214,23 @@
 {
   return GST_FLOW_OK;
 }
+
+static GstCaps *
+gst_gl_color_convert_element_fixate_caps (GstBaseTransform *
+    bt, GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
+{
+  GstCaps *ret;
+
+  ret =
+      GST_BASE_TRANSFORM_CLASS
+      (gst_gl_color_convert_element_parent_class)->fixate_caps (bt, direction,
+      caps, othercaps);
+
+  if (direction == GST_PAD_SINK) {
+    if (gst_caps_is_subset (caps, ret)) {
+      gst_caps_replace (&ret, caps);
+    }
+  }
+
+  return ret;
+}
diff --git a/ext/gl/gstglcolorscale.c b/ext/gl/gstglcolorscale.c
index fa22bf9..a79e524 100644
--- a/ext/gl/gstglcolorscale.c
+++ b/ext/gl/gstglcolorscale.c
@@ -61,7 +61,7 @@
 
 #define DEBUG_INIT \
   GST_DEBUG_CATEGORY_INIT (gst_gl_colorscale_debug, "glcolorscale", 0, "glcolorscale element");
-
+#define gst_gl_colorscale_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstGLColorscale, gst_gl_colorscale,
     GST_TYPE_GL_FILTER, DEBUG_INIT);
 
@@ -71,7 +71,7 @@
     GValue * value, GParamSpec * pspec);
 
 static gboolean gst_gl_colorscale_gen_gl_resources (GstGLFilter * filter);
-static void gst_gl_colorscale_del_gl_resources (GstGLFilter * filter);
+static gboolean gst_gl_colorscale_del_gl_resources (GstBaseTransform * trans);
 
 static gboolean gst_gl_colorscale_filter_texture (GstGLFilter * filter,
     guint in_tex, guint out_tex);
@@ -97,12 +97,13 @@
       "Filter/Effect/Video", "Colorspace converter and video scaler",
       "Julien Isorce <julien.isorce@gmail.com>");
 
-  filter_class->onInitFBO =
+  filter_class->init_fbo =
       GST_DEBUG_FUNCPTR (gst_gl_colorscale_gen_gl_resources);
-  filter_class->onStop = GST_DEBUG_FUNCPTR (gst_gl_colorscale_del_gl_resources);
 
   filter_class->filter_texture = gst_gl_colorscale_filter_texture;
 
+  basetransform_class->stop =
+      GST_DEBUG_FUNCPTR (gst_gl_colorscale_del_gl_resources);
   basetransform_class->passthrough_on_same_caps = TRUE;
   GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api =
       GST_GL_API_OPENGL | GST_GL_API_OPENGL3 | GST_GL_API_GLES2;
@@ -173,16 +174,18 @@
   return TRUE;
 }
 
-static void
-gst_gl_colorscale_del_gl_resources (GstGLFilter * filter)
+static gboolean
+gst_gl_colorscale_del_gl_resources (GstBaseTransform * trans)
 {
-  GstGLColorscale *colorscale = GST_GL_COLORSCALE (filter);
+  GstGLColorscale *colorscale = GST_GL_COLORSCALE (trans);
 
   if (colorscale->shader) {
-    gst_gl_context_del_shader (GST_GL_BASE_FILTER (filter)->context,
+    gst_gl_context_del_shader (GST_GL_BASE_FILTER (trans)->context,
         colorscale->shader);
     colorscale->shader = NULL;
   }
+
+  return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (trans);
 }
 
 static gboolean
diff --git a/ext/gl/gstgldeinterlace.c b/ext/gl/gstgldeinterlace.c
index bf969f2..ce66666 100644
--- a/ext/gl/gstgldeinterlace.c
+++ b/ext/gl/gstgldeinterlace.c
@@ -48,7 +48,7 @@
 
 #define DEBUG_INIT \
   GST_DEBUG_CATEGORY_INIT (gst_gl_deinterlace_debug, "gldeinterlace", 0, "gldeinterlace element");
-
+#define gst_gl_deinterlace_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstGLDeinterlace, gst_gl_deinterlace,
     GST_TYPE_GL_FILTER, DEBUG_INIT);
 
@@ -57,7 +57,7 @@
 static void gst_gl_deinterlace_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
 
-static void gst_gl_deinterlace_reset (GstGLFilter * filter);
+static gboolean gst_gl_deinterlace_reset (GstBaseTransform * trans);
 static gboolean gst_gl_deinterlace_init_shader (GstGLFilter * filter);
 static gboolean gst_gl_deinterlace_filter (GstGLFilter * filter,
     GstBuffer * inbuf, GstBuffer * outbuf);
@@ -163,11 +163,12 @@
       "Deinterlacing based on fragment shaders",
       "Julien Isorce <julien.isorce@mail.com>");
 
+  GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_deinterlace_reset;
+
   GST_GL_FILTER_CLASS (klass)->filter = gst_gl_deinterlace_filter;
   GST_GL_FILTER_CLASS (klass)->filter_texture =
       gst_gl_deinterlace_filter_texture;
-  GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_deinterlace_init_shader;
-  GST_GL_FILTER_CLASS (klass)->onReset = gst_gl_deinterlace_reset;
+  GST_GL_FILTER_CLASS (klass)->init_fbo = gst_gl_deinterlace_init_shader;
 
   GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api = GST_GL_API_OPENGL;
 }
@@ -180,18 +181,20 @@
   filter->prev_tex = 0;
 }
 
-static void
-gst_gl_deinterlace_reset (GstGLFilter * filter)
+static gboolean
+gst_gl_deinterlace_reset (GstBaseTransform * trans)
 {
-  GstGLDeinterlace *deinterlace_filter = GST_GL_DEINTERLACE (filter);
+  GstGLDeinterlace *deinterlace_filter = GST_GL_DEINTERLACE (trans);
 
   gst_buffer_replace (&deinterlace_filter->prev_buffer, NULL);
 
   //blocking call, wait the opengl thread has destroyed the shader
   if (deinterlace_filter->shader)
-    gst_gl_context_del_shader (GST_GL_BASE_FILTER (filter)->context,
+    gst_gl_context_del_shader (GST_GL_BASE_FILTER (trans)->context,
         deinterlace_filter->shader);
   deinterlace_filter->shader = NULL;
+
+  return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (trans);
 }
 
 static void
diff --git a/ext/gl/gstgldifferencematte.c b/ext/gl/gstgldifferencematte.c
index ce1b513..4f0a8f6 100644
--- a/ext/gl/gstgldifferencematte.c
+++ b/ext/gl/gstgldifferencematte.c
@@ -61,9 +61,6 @@
 static void gst_gl_differencematte_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
 
-static void gst_gl_differencematte_init_resources (GstGLFilter * filter);
-static void gst_gl_differencematte_reset_resources (GstGLFilter * filter);
-
 static gboolean gst_gl_differencematte_filter_texture (GstGLFilter * filter,
     guint in_tex, guint out_tex);
 
@@ -109,7 +106,7 @@
   }
 
   if (!gst_gl_shader_compile_and_check (differencematte->shader[1],
-          hconv7_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
+          hconv7_fragment_source_opengl, GST_GL_SHADER_FRAGMENT_SOURCE)) {
     gst_gl_context_set_error (GST_GL_BASE_FILTER (differencematte)->context,
         "Failed to initialize hconv7 shader");
     GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND,
@@ -118,7 +115,7 @@
   }
 
   if (!gst_gl_shader_compile_and_check (differencematte->shader[2],
-          vconv7_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
+          vconv7_fragment_source_opengl, GST_GL_SHADER_FRAGMENT_SOURCE)) {
     gst_gl_context_set_error (GST_GL_BASE_FILTER (differencematte)->context,
         "Failed to initialize vconv7 shader");
     GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND,
@@ -180,8 +177,6 @@
       gst_gl_differencematte_init_gl_resources;
   GST_GL_FILTER_CLASS (klass)->display_reset_cb =
       gst_gl_differencematte_reset_gl_resources;
-  GST_GL_FILTER_CLASS (klass)->onStart = gst_gl_differencematte_init_resources;
-  GST_GL_FILTER_CLASS (klass)->onStop = gst_gl_differencematte_reset_resources;
 
   g_object_class_install_property (gobject_class,
       PROP_LOCATION,
@@ -215,12 +210,6 @@
 }
 
 static void
-gst_gl_differencematte_reset_resources (GstGLFilter * filter)
-{
-//  GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE(filter);
-}
-
-static void
 gst_gl_differencematte_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
@@ -256,12 +245,6 @@
 }
 
 static void
-gst_gl_differencematte_init_resources (GstGLFilter * filter)
-{
-//  GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter);
-}
-
-static void
 gst_gl_differencematte_save_texture (gint width, gint height, guint texture,
     gpointer stuff)
 {
diff --git a/ext/gl/gstgldownloadelement.c b/ext/gl/gstgldownloadelement.c
index dfe0856..78afff5 100644
--- a/ext/gl/gstgldownloadelement.c
+++ b/ext/gl/gstgldownloadelement.c
@@ -34,7 +34,6 @@
     GST_DEBUG_CATEGORY_INIT (gst_gl_download_element_debug, "gldownloadelement",
         0, "download element");
     );
-static void gst_gl_download_element_finalize (GObject * object);
 
 static gboolean gst_gl_download_element_get_unit_size (GstBaseTransform * trans,
     GstCaps * caps, gsize * size);
@@ -82,9 +81,7 @@
 
   gst_element_class_set_metadata (element_class,
       "OpenGL uploader", "Filter/Video",
-      "Uploads data into OpenGL", "Matthew Waters <matthew@centricular.com>");
-
-  G_OBJECT_CLASS (klass)->finalize = gst_gl_download_element_finalize;
+      "Downloads data from OpenGL", "Matthew Waters <matthew@centricular.com>");
 }
 
 static void
@@ -94,12 +91,6 @@
       TRUE);
 }
 
-static void
-gst_gl_download_element_finalize (GObject * object)
-{
-  G_OBJECT_CLASS (gst_gl_download_element_parent_class)->finalize (object);
-}
-
 static gboolean
 gst_gl_download_element_set_caps (GstBaseTransform * bt, GstCaps * in_caps,
     GstCaps * out_caps)
diff --git a/ext/gl/gstgleffects.c b/ext/gl/gstgleffects.c
index a85e624..02878d2 100644
--- a/ext/gl/gstgleffects.c
+++ b/ext/gl/gstgleffects.c
@@ -39,19 +39,21 @@
 #include <gst/gl/gstglconfig.h>
 #include "gstgleffects.h"
 
-#define GST_TYPE_GL_EFFECTS            (gst_gl_effects_get_type())
-#define GST_GL_EFFECTS(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_GL_EFFECTS,GstGLEffects))
-#define GST_IS_GL_EFFECTS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_GL_EFFECTS))
-#define GST_GL_EFFECTS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass) , GST_TYPE_GL_EFFECTS,GstGLEffectsClass))
-#define GST_IS_GL_EFFECTS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) , GST_TYPE_GL_EFFECTS))
-#define GST_GL_EFFECTS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) , GST_TYPE_GL_EFFECTS,GstGLEffectsClass))
-
 #define GST_CAT_DEFAULT gst_gl_effects_debug
 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
 
+enum
+{
+  PROP_0 = 0x0,
+  PROP_EFFECT = 0x1 << 1,
+  PROP_HSWAP = 0x1 << 2,
+  PROP_INVERT = 0x1 << 3
+};
+
 #define DEBUG_INIT \
   GST_DEBUG_CATEGORY_INIT (gst_gl_effects_debug, "gleffects", 0, "gleffects element");
 
+#define gst_gl_effects_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstGLEffects, gst_gl_effects, GST_TYPE_GL_FILTER,
     DEBUG_INIT);
 
@@ -60,8 +62,8 @@
 static void gst_gl_effects_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
-static void gst_gl_effects_init_resources (GstGLFilter * filter);
-static void gst_gl_effects_reset_resources (GstGLFilter * filter);
+static gboolean gst_gl_effects_init_resources (GstBaseTransform * trans);
+static gboolean gst_gl_effects_reset_resources (GstBaseTransform * trans);
 
 static gboolean gst_gl_effects_on_init_gl_context (GstGLFilter * filter);
 
@@ -70,6 +72,8 @@
 
 static gboolean gst_gl_effects_filter_texture (GstGLFilter * filter,
     guint in_tex, guint out_tex);
+static gboolean gst_gl_effects_filters_is_property_supported (const
+    GstGLEffectsFilterDescriptor *, gint property);
 
 /* dont' forget to edit the following when a new effect is added */
 typedef enum
@@ -90,24 +94,24 @@
   GST_GL_EFFECT_XRAY,
   GST_GL_EFFECT_SIN,
   GST_GL_EFFECT_GLOW,
+  GST_GL_EFFECT_SOBEL,
+  GST_GL_EFFECT_BLUR,
+  GST_GL_EFFECT_LAPLACIAN,
   GST_GL_N_EFFECTS
 } GstGLEffectsEffect;
 
-#define GST_TYPE_GL_EFFECTS_EFFECT (gst_gl_effects_effect_get_type ())
-static GType
-gst_gl_effects_effect_get_type (void)
+static const GEnumValue *
+gst_gl_effects_get_effects (void)
 {
-  static GType gl_effects_effect_type = 0;
   static const GEnumValue effect_types[] = {
     {GST_GL_EFFECT_IDENTITY, "Do nothing Effect", "identity"},
     {GST_GL_EFFECT_MIRROR, "Mirror Effect", "mirror"},
     {GST_GL_EFFECT_SQUEEZE, "Squeeze Effect", "squeeze"},
-#if GST_GL_HAVE_OPENGL
     {GST_GL_EFFECT_STRETCH, "Stretch Effect", "stretch"},
+    {GST_GL_EFFECT_TUNNEL, "Light Tunnel Effect", "tunnel"},
     {GST_GL_EFFECT_FISHEYE, "FishEye Effect", "fisheye"},
     {GST_GL_EFFECT_TWIRL, "Twirl Effect", "twirl"},
     {GST_GL_EFFECT_BULGE, "Bulge Effect", "bulge"},
-    {GST_GL_EFFECT_TUNNEL, "Light Tunnel Effect", "tunnel"},
     {GST_GL_EFFECT_SQUARE, "Square Effect", "square"},
     {GST_GL_EFFECT_HEAT, "Heat Signature Effect", "heat"},
     {GST_GL_EFFECT_SEPIA, "Sepia Toning Effect", "sepia"},
@@ -116,13 +120,23 @@
     {GST_GL_EFFECT_XRAY, "Glowing negative effect", "xray"},
     {GST_GL_EFFECT_SIN, "All Grey but Red Effect", "sin"},
     {GST_GL_EFFECT_GLOW, "Glow Lighting Effect", "glow"},
-#endif
+    {GST_GL_EFFECT_SOBEL, "Sobel edge detection Effect", "sobel"},
+    {GST_GL_EFFECT_BLUR, "Blur with 9x9 separable convolution Effect", "blur"},
+    {GST_GL_EFFECT_LAPLACIAN, "Laplacian Convolution Demo Effect", "laplacian"},
     {0, NULL, NULL}
   };
+  return effect_types;
+}
 
+#define GST_TYPE_GL_EFFECTS_EFFECT (gst_gl_effects_effect_get_type ())
+static GType
+gst_gl_effects_effect_get_type (void)
+{
+  static GType gl_effects_effect_type = 0;
   if (!gl_effects_effect_type) {
     gl_effects_effect_type =
-        g_enum_register_static ("GstGLEffectsEffect", effect_types);
+        g_enum_register_static ("GstGLEffectsEffect",
+        gst_gl_effects_get_effects ());
   }
   return gl_effects_effect_type;
 }
@@ -131,7 +145,6 @@
 gst_gl_effects_set_effect (GstGLEffects * effects, gint effect_type)
 {
   GstGLBaseFilterClass *filter_class = GST_GL_BASE_FILTER_GET_CLASS (effects);
-  GstGLContext *context = GST_GL_BASE_FILTER (effects)->context;
 
   switch (effect_type) {
     case GST_GL_EFFECT_IDENTITY:
@@ -152,78 +165,106 @@
           GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
       effects->current_effect = effect_type;
       break;
-  }
-
-  if (context
-      && (gst_gl_context_get_gl_api (context) & GST_GL_API_OPENGL) ==
-      GST_GL_API_NONE) {
-    GST_ELEMENT_WARNING (effects, RESOURCE, SETTINGS, ("%s",
-            "cannot change effect type"), ("%s",
-            "the current OpenGL context does not support the GL API required"));
-    return;
-  }
-#if GST_GL_HAVE_OPENGL
-  switch (effect_type) {
-    case GST_GL_EFFECT_IDENTITY:
-    case GST_GL_EFFECT_MIRROR:
-    case GST_GL_EFFECT_SQUEEZE:
-      break;
     case GST_GL_EFFECT_STRETCH:
       effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_stretch;
-      filter_class->supported_gl_api = GST_GL_API_OPENGL;
+      filter_class->supported_gl_api =
+          GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+      effects->current_effect = effect_type;
       break;
     case GST_GL_EFFECT_TUNNEL:
       effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_tunnel;
-      filter_class->supported_gl_api = GST_GL_API_OPENGL;
+      filter_class->supported_gl_api =
+          GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+      effects->current_effect = effect_type;
       break;
     case GST_GL_EFFECT_FISHEYE:
       effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_fisheye;
-      filter_class->supported_gl_api = GST_GL_API_OPENGL;
+      filter_class->supported_gl_api =
+          GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+      effects->current_effect = effect_type;
       break;
     case GST_GL_EFFECT_TWIRL:
       effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_twirl;
-      filter_class->supported_gl_api = GST_GL_API_OPENGL;
+      filter_class->supported_gl_api =
+          GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+      effects->current_effect = effect_type;
       break;
     case GST_GL_EFFECT_BULGE:
       effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_bulge;
-      filter_class->supported_gl_api = GST_GL_API_OPENGL;
+      filter_class->supported_gl_api =
+          GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+      effects->current_effect = effect_type;
       break;
     case GST_GL_EFFECT_SQUARE:
       effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_square;
-      filter_class->supported_gl_api = GST_GL_API_OPENGL;
+      filter_class->supported_gl_api =
+          GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+      effects->current_effect = effect_type;
       break;
     case GST_GL_EFFECT_HEAT:
       effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_heat;
-      filter_class->supported_gl_api = GST_GL_API_OPENGL;
+      filter_class->supported_gl_api =
+          GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+      effects->current_effect = effect_type;
       break;
     case GST_GL_EFFECT_SEPIA:
       effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_sepia;
-      filter_class->supported_gl_api = GST_GL_API_OPENGL;
+      filter_class->supported_gl_api =
+          GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+      effects->current_effect = effect_type;
       break;
     case GST_GL_EFFECT_XPRO:
       effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_xpro;
-      filter_class->supported_gl_api = GST_GL_API_OPENGL;
+      filter_class->supported_gl_api =
+          GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+      effects->current_effect = effect_type;
       break;
     case GST_GL_EFFECT_LUMA_XPRO:
       effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_luma_xpro;
-      filter_class->supported_gl_api = GST_GL_API_OPENGL;
-      break;
-    case GST_GL_EFFECT_XRAY:
-      effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_xray;
-      filter_class->supported_gl_api = GST_GL_API_OPENGL;
+      filter_class->supported_gl_api =
+          GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+      effects->current_effect = effect_type;
       break;
     case GST_GL_EFFECT_SIN:
       effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_sin;
-      filter_class->supported_gl_api = GST_GL_API_OPENGL;
+      filter_class->supported_gl_api =
+          GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+      effects->current_effect = effect_type;
+      break;
+    case GST_GL_EFFECT_XRAY:
+      effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_sin;
+      filter_class->supported_gl_api =
+          GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+      effects->current_effect = effect_type;
       break;
     case GST_GL_EFFECT_GLOW:
       effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_glow;
-      filter_class->supported_gl_api = GST_GL_API_OPENGL;
+      filter_class->supported_gl_api =
+          GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+      effects->current_effect = effect_type;
+      break;
+    case GST_GL_EFFECT_SOBEL:
+      effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_sobel;
+      filter_class->supported_gl_api =
+          GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+      effects->current_effect = effect_type;
+      break;
+    case GST_GL_EFFECT_BLUR:
+      effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_blur;
+      filter_class->supported_gl_api =
+          GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+      effects->current_effect = effect_type;
+      break;
+    case GST_GL_EFFECT_LAPLACIAN:
+      effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_laplacian;
+      filter_class->supported_gl_api =
+          GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+      effects->current_effect = effect_type;
       break;
     default:
       g_assert_not_reached ();
   }
-#endif
+
   effects->current_effect = effect_type;
 }
 
@@ -276,37 +317,19 @@
 static void
 gst_gl_effects_class_init (GstGLEffectsClass * klass)
 {
-  GObjectClass *gobject_class;
-  GstElementClass *element_class;
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
 
-  gobject_class = (GObjectClass *) klass;
-  element_class = GST_ELEMENT_CLASS (klass);
-
-  gobject_class->set_property = gst_gl_effects_set_property;
-  gobject_class->get_property = gst_gl_effects_get_property;
+  GST_BASE_TRANSFORM_CLASS (klass)->start = gst_gl_effects_init_resources;
+  GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_effects_reset_resources;
 
   GST_GL_FILTER_CLASS (klass)->filter_texture = gst_gl_effects_filter_texture;
   GST_GL_FILTER_CLASS (klass)->display_init_cb =
       gst_gl_effects_init_gl_resources;
   GST_GL_FILTER_CLASS (klass)->display_reset_cb =
       gst_gl_effects_reset_gl_resources;
-  GST_GL_FILTER_CLASS (klass)->onStart = gst_gl_effects_init_resources;
-  GST_GL_FILTER_CLASS (klass)->onStop = gst_gl_effects_reset_resources;
-  GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_effects_on_init_gl_context;
+  GST_GL_FILTER_CLASS (klass)->init_fbo = gst_gl_effects_on_init_gl_context;
 
-  g_object_class_install_property (gobject_class,
-      PROP_EFFECT,
-      g_param_spec_enum ("effect",
-          "Effect",
-          "Select which effect apply to GL video texture",
-          GST_TYPE_GL_EFFECTS_EFFECT,
-          GST_GL_EFFECT_IDENTITY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class,
-      PROP_HSWAP,
-      g_param_spec_boolean ("hswap",
-          "Horizontal Swap",
-          "Switch video texture left to right, useful with webcams",
-          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  klass->filter_descriptor = NULL;
 
   gst_element_class_set_metadata (element_class,
       "Gstreamer OpenGL Effects", "Filter/Effect/Video",
@@ -318,6 +341,46 @@
 }
 
 static void
+gst_gl_effects_filter_class_init (GstGLEffectsClass * klass,
+    const GstGLEffectsFilterDescriptor * filter_descriptor)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  klass->filter_descriptor = filter_descriptor;
+
+  gobject_class->set_property = gst_gl_effects_set_property;
+  gobject_class->get_property = gst_gl_effects_get_property;
+
+  /* if filterDescriptor is null it's a generic gleffects */
+  if (!filter_descriptor) {
+    g_object_class_install_property (gobject_class,
+        PROP_EFFECT,
+        g_param_spec_enum ("effect",
+            "Effect",
+            "Select which effect apply to GL video texture",
+            GST_TYPE_GL_EFFECTS_EFFECT,
+            GST_GL_EFFECT_IDENTITY,
+            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  }
+
+  g_object_class_install_property (gobject_class,
+      PROP_HSWAP,
+      g_param_spec_boolean ("hswap",
+          "Horizontal Swap",
+          "Switch video texture left to right, useful with webcams",
+          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /* FIXME: make it work on every effect */
+  if (gst_gl_effects_filters_is_property_supported (filter_descriptor,
+          PROP_INVERT)) {
+    g_object_class_install_property (gobject_class, PROP_INVERT,
+        g_param_spec_boolean ("invert", "Invert the colors for sobel effect",
+            "Invert colors to get dark edges on bright background when using sobel effect",
+            FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  }
+}
+
+static void
 set_horizontal_swap (GstGLContext * context, gpointer data)
 {
 #if GST_GL_HAVE_OPENGL
@@ -338,8 +401,16 @@
 static void
 gst_gl_effects_init (GstGLEffects * effects)
 {
-  effects->effect = gst_gl_effects_identity;
   effects->horizontal_swap = FALSE;
+  effects->invert = FALSE;
+  effects->effect = gst_gl_effects_identity;
+}
+
+static void
+gst_gl_effects_filter_init (GstGLEffects * effects)
+{
+  gst_gl_effects_set_effect (effects,
+      GST_GL_EFFECTS_GET_CLASS (effects)->filter_descriptor->effect);
 }
 
 static void
@@ -354,20 +425,22 @@
   value = NULL;
 }
 
-static void
-gst_gl_effects_reset_resources (GstGLFilter * filter)
+static gboolean
+gst_gl_effects_reset_resources (GstBaseTransform * trans)
 {
-  GstGLEffects *effects = GST_GL_EFFECTS (filter);
+  GstGLEffects *effects = GST_GL_EFFECTS (trans);
 
   /* release shaders in the gl thread */
   g_hash_table_foreach (effects->shaderstable, gst_gl_effects_ghash_func_clean,
-      filter);
+      effects);
 
   /* clean the htable without calling values destructors
    * because shaders have been released in the glthread
    * through the foreach func */
   g_hash_table_unref (effects->shaderstable);
   effects->shaderstable = NULL;
+
+  return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (trans);
 }
 
 static void
@@ -383,6 +456,9 @@
     case PROP_HSWAP:
       effects->horizontal_swap = g_value_get_boolean (value);
       break;
+    case PROP_INVERT:
+      effects->invert = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -402,16 +478,19 @@
     case PROP_HSWAP:
       g_value_set_boolean (value, effects->horizontal_swap);
       break;
+    case PROP_INVERT:
+      g_value_set_boolean (value, effects->invert);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 }
 
-static void
-gst_gl_effects_init_resources (GstGLFilter * filter)
+static gboolean
+gst_gl_effects_init_resources (GstBaseTransform * trans)
 {
-  GstGLEffects *effects = GST_GL_EFFECTS (filter);
+  GstGLEffects *effects = GST_GL_EFFECTS (trans);
   gint i;
 
   effects->shaderstable = g_hash_table_new (g_str_hash, g_str_equal);
@@ -422,6 +501,8 @@
   for (i = 0; i < GST_GL_EFFECTS_N_CURVES; i++) {
     effects->curve[i] = 0;
   }
+
+  return GST_BASE_TRANSFORM_CLASS (parent_class)->start (trans);
 }
 
 static gboolean
@@ -447,3 +528,150 @@
 
   return TRUE;
 }
+
+GstGLShader *
+gst_gl_effects_get_fragment_shader (GstGLEffects * effects,
+    const gchar * shader_name, const gchar * shader_source_gles2,
+    const gchar * shader_source_opengl)
+{
+  GstGLShader *shader;
+  GstGLFilter *filter = GST_GL_FILTER (effects);
+  GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
+
+  shader = g_hash_table_lookup (effects->shaderstable, shader_name);
+
+  if (!shader) {
+    shader = gst_gl_shader_new (context);
+    g_hash_table_insert (effects->shaderstable, (gchar *) shader_name, shader);
+
+    if (USING_GLES2 (context) || USING_OPENGL3 (context)) {
+      if (!gst_gl_shader_compile_with_default_v_and_check (shader,
+              shader_source_gles2, &filter->draw_attr_position_loc,
+              &filter->draw_attr_texture_loc)) {
+        /* gst gl context error is already set */
+        GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
+            ("Failed to initialize %s shader, %s",
+                shader_name, gst_gl_context_get_error ()), (NULL));
+        return NULL;
+      }
+    }
+#if GST_GL_HAVE_OPENGL
+    if (!gst_gl_shader_compile_and_check (shader,
+            shader_source_opengl, GST_GL_SHADER_FRAGMENT_SOURCE)) {
+      gst_gl_context_set_error (context, "Failed to initialize %s shader",
+          shader_name);
+      GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, ("%s",
+              gst_gl_context_get_error ()), (NULL));
+      return NULL;
+    }
+#endif
+  }
+
+  return shader;
+}
+
+static const GstGLEffectsFilterDescriptor *
+gst_gl_effects_filters_supported_properties (void)
+{
+  /* Horizontal swap property is supported by all filters */
+  static const GstGLEffectsFilterDescriptor effects[] = {
+    {GST_GL_EFFECT_SOBEL, PROP_INVERT, NULL},
+    {GST_GL_EFFECT_LAPLACIAN, PROP_INVERT, NULL},
+    {0, 0, NULL}
+  };
+  return effects;
+}
+
+static inline gboolean
+gst_gl_effects_filters_is_property_supported (const GstGLEffectsFilterDescriptor
+    * descriptor, gint property)
+{
+  /* generic filter (NULL descriptor) supports all properties */
+  return !descriptor || (descriptor->supported_properties & property);
+}
+
+static const GstGLEffectsFilterDescriptor *
+gst_gl_effects_filters_descriptors (void)
+{
+  static GstGLEffectsFilterDescriptor *descriptors = NULL;
+  if (!descriptors) {
+    const GEnumValue *effect = gst_gl_effects_get_effects ();
+    guint n_filters = 0;
+    for (const GEnumValue * e = effect; NULL != e->value_nick; ++e, ++n_filters) {
+    }
+
+    descriptors = g_new0 (GstGLEffectsFilterDescriptor, n_filters + 1);
+    for (guint i = 0; i < n_filters; ++i, ++effect) {
+      descriptors[i].effect = effect->value;
+      descriptors[i].filter_name = effect->value_nick;
+    }
+
+    for (const GstGLEffectsFilterDescriptor * defined =
+        gst_gl_effects_filters_supported_properties ();
+        0 != defined->supported_properties; ++defined) {
+
+      guint i = 0;
+      for (; i < n_filters; ++i) {
+        if (descriptors[i].effect == defined->effect) {
+          descriptors[i].supported_properties = defined->supported_properties;
+          break;
+        }
+      }
+      if (i >= n_filters) {
+        GST_WARNING ("Could not match gstgleffects-%s descriptor",
+            defined->filter_name);
+      }
+    }
+  }
+  return descriptors;
+}
+
+gboolean
+gst_gl_effects_register_filters (GstPlugin * plugin, GstRank rank)
+{
+  static volatile gsize registered = 0;
+
+  if (g_once_init_enter (&registered)) {
+    GTypeInfo info = {
+      sizeof (GstGLEffectsClass),
+      NULL,
+      NULL,
+      (GClassInitFunc) gst_gl_effects_filter_class_init,
+      NULL,
+      NULL,
+      sizeof (GstGLEffects),
+      0,
+      NULL
+    };
+    GType generic_type =
+        g_type_register_static (GST_TYPE_GL_EFFECTS, "GstGLEffectsGeneric",
+        &info, 0);
+
+    if (gst_element_register (plugin, "gleffects", rank, generic_type)) {
+      for (const GstGLEffectsFilterDescriptor * filters =
+          gst_gl_effects_filters_descriptors (); NULL != filters->filter_name;
+          ++filters) {
+        gchar *name = g_strdup_printf ("gleffects_%s", filters->filter_name);
+        GTypeInfo info = {
+          sizeof (GstGLEffectsClass),
+          NULL,
+          NULL,
+          (GClassInitFunc) gst_gl_effects_filter_class_init,
+          NULL,
+          filters,
+          sizeof (GstGLEffects),
+          0,
+          (GInstanceInitFunc) gst_gl_effects_filter_init
+        };
+        GType type =
+            g_type_register_static (GST_TYPE_GL_EFFECTS, name, &info, 0);
+        if (!gst_element_register (plugin, name, rank, type)) {
+          GST_WARNING ("Could not register %s", name);
+        }
+        g_free (name);
+      }
+    }
+    g_once_init_leave (&registered, generic_type);
+  }
+  return registered;
+}
diff --git a/ext/gl/gstgleffects.h b/ext/gl/gstgleffects.h
index 71bec25..3d30067 100644
--- a/ext/gl/gstgleffects.h
+++ b/ext/gl/gstgleffects.h
@@ -26,7 +26,6 @@
 
 G_BEGIN_DECLS
 
-
 #define GST_TYPE_GL_EFFECTS            (gst_gl_effects_get_type())
 #define GST_GL_EFFECTS(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_GL_EFFECTS,GstGLEffects))
 #define GST_IS_GL_EFFECTS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_GL_EFFECTS))
@@ -34,9 +33,21 @@
 #define GST_IS_GL_EFFECTS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) , GST_TYPE_GL_EFFECTS))
 #define GST_GL_EFFECTS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) , GST_TYPE_GL_EFFECTS,GstGLEffectsClass))
 
+#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
+#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1))
+#define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0))
+#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
+#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
+
 typedef struct _GstGLEffects GstGLEffects;
 typedef struct _GstGLEffectsClass GstGLEffectsClass;
 
+typedef struct {
+  gint effect;
+  guint supported_properties;
+  const gchar *filter_name;
+} GstGLEffectsFilterDescriptor;
+
 typedef void (* GstGLEffectProcessFunc) (GstGLEffects *effects);
 
 #define NEEDED_TEXTURES 5
@@ -66,22 +77,19 @@
   GHashTable *shaderstable;
 
   gboolean horizontal_swap; /* switch left to right */
+  gboolean invert; /* colours */
 };
 
 struct _GstGLEffectsClass
 {
   GstGLFilterClass filter_class;
+  const GstGLEffectsFilterDescriptor *filter_descriptor;
 };
 
-enum
-{
-  PROP_0,
-  PROP_EFFECT,
-  PROP_HSWAP
-};
-
-
 GType gst_gl_effects_get_type (void);
+gboolean gst_gl_effects_register_filters (GstPlugin *, GstRank);
+GstGLShader* gst_gl_effects_get_fragment_shader (GstGLEffects *effects,
+    const gchar * shader_name, const gchar * shader_source_gles2, const gchar * shader_source_opengl);
 
 void gst_gl_effects_identity (GstGLEffects *effects);
 void gst_gl_effects_mirror (GstGLEffects *effects);
@@ -99,6 +107,9 @@
 void gst_gl_effects_luma_xpro (GstGLEffects *effects);
 void gst_gl_effects_sin (GstGLEffects *effects);
 void gst_gl_effects_glow (GstGLEffects *effects);
+void gst_gl_effects_sobel (GstGLEffects *effects);
+void gst_gl_effects_blur (GstGLEffects *effects);
+void gst_gl_effects_laplacian (GstGLEffects *effects);
 
 G_END_DECLS
 
diff --git a/ext/gl/gstglfilterbin.c b/ext/gl/gstglfilterbin.c
index 9bab3d3..a8e703e 100644
--- a/ext/gl/gstglfilterbin.c
+++ b/ext/gl/gstglfilterbin.c
@@ -48,7 +48,6 @@
     GST_TYPE_BIN, GST_DEBUG_CATEGORY_INIT (gst_gl_filter_bin_debug,
         "glfilterbin", 0, "glfilterbin element"););
 
-static void gst_gl_filter_bin_finalize (GObject * object);
 static void gst_gl_filter_bin_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 static void gst_gl_filter_bin_set_property (GObject * object, guint prop_id,
@@ -62,28 +61,25 @@
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS ("video/x-raw(ANY)"));
 
-static GstStaticPadTemplate _sink_pad_template =
-GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-raw(ANY)"));
-
 static void
 gst_gl_filter_bin_class_init (GstGLFilterBinClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstCaps *upload_caps;
 
   element_class->change_state = gst_gl_filter_bin_change_state;
 
   gobject_class->set_property = gst_gl_filter_bin_set_property;
   gobject_class->get_property = gst_gl_filter_bin_get_property;
-  gobject_class->finalize = gst_gl_filter_bin_finalize;
 
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&_src_pad_template));
+
+  upload_caps = gst_gl_upload_get_input_template_caps ();
   gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&_sink_pad_template));
+      gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, upload_caps));
+  gst_caps_unref (upload_caps);
 
   g_object_class_install_property (gobject_class, PROP_FILTER,
       g_param_spec_object ("filter",
@@ -236,12 +232,6 @@
   }
 }
 
-static void
-gst_gl_filter_bin_finalize (GObject * object)
-{
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
 static GstStateChangeReturn
 gst_gl_filter_bin_change_state (GstElement * element, GstStateChange transition)
 {
diff --git a/ext/gl/gstglfilterblur.c b/ext/gl/gstglfilterblur.c
deleted file mode 100644
index 842a014..0000000
--- a/ext/gl/gstglfilterblur.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:element-glfilterblur
- *
- * Blur with 9x9 separable convolution.
- *
- * <refsect2>
- * <title>Examples</title>
- * |[
- * gst-launch videotestsrc ! glupload ! glfilterblur ! glimagesink
- * ]|
- * FBO (Frame Buffer Object) and GLSL (OpenGL Shading Language) are required.
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstglfilterblur.h"
-#include "effects/gstgleffectssources.h"
-
-#define GST_CAT_DEFAULT gst_gl_filterblur_debug
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
-
-#define DEBUG_INIT \
-  GST_DEBUG_CATEGORY_INIT (gst_gl_filterblur_debug, "glfilterblur", 0, "glfilterblur element");
-
-G_DEFINE_TYPE_WITH_CODE (GstGLFilterBlur, gst_gl_filterblur,
-    GST_TYPE_GL_FILTER, DEBUG_INIT);
-
-static void gst_gl_filterblur_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void gst_gl_filterblur_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-static void gst_gl_filter_filterblur_reset (GstGLFilter * filter);
-
-static gboolean gst_gl_filterblur_init_shader (GstGLFilter * filter);
-static gboolean gst_gl_filterblur_filter_texture (GstGLFilter * filter,
-    guint in_tex, guint out_tex);
-static void gst_gl_filterblur_hcallback (gint width, gint height, guint texture,
-    gpointer stuff);
-static void gst_gl_filterblur_vcallback (gint width, gint height, guint texture,
-    gpointer stuff);
-
-
-static void
-gst_gl_filterblur_init_resources (GstGLFilter * filter)
-{
-  GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (filter);
-  GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
-
-  gl->GenTextures (1, &filterblur->midtexture);
-  gl->BindTexture (GL_TEXTURE_2D, filterblur->midtexture);
-  gl->TexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8,
-      GST_VIDEO_INFO_WIDTH (&filter->out_info),
-      GST_VIDEO_INFO_HEIGHT (&filter->out_info),
-      0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-}
-
-static void
-gst_gl_filterblur_reset_resources (GstGLFilter * filter)
-{
-  GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (filter);
-  GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
-
-  gl->DeleteTextures (1, &filterblur->midtexture);
-}
-
-static void
-gst_gl_filterblur_class_init (GstGLFilterBlurClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *element_class;
-
-  gobject_class = (GObjectClass *) klass;
-  element_class = GST_ELEMENT_CLASS (klass);
-
-  gobject_class->set_property = gst_gl_filterblur_set_property;
-  gobject_class->get_property = gst_gl_filterblur_get_property;
-
-  gst_element_class_set_metadata (element_class, "Gstreamer OpenGL Blur",
-      "Filter/Effect/Video", "Blur with 9x9 separable convolution",
-      "Filippo Argiolas <filippo.argiolas@gmail.com>");
-
-  GST_GL_FILTER_CLASS (klass)->filter_texture =
-      gst_gl_filterblur_filter_texture;
-  GST_GL_FILTER_CLASS (klass)->display_init_cb =
-      gst_gl_filterblur_init_resources;
-  GST_GL_FILTER_CLASS (klass)->display_reset_cb =
-      gst_gl_filterblur_reset_resources;
-  GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_filterblur_init_shader;
-  GST_GL_FILTER_CLASS (klass)->onReset = gst_gl_filter_filterblur_reset;
-
-  GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api = GST_GL_API_OPENGL;
-}
-
-static void
-gst_gl_filterblur_init (GstGLFilterBlur * filterblur)
-{
-  filterblur->shader0 = NULL;
-  filterblur->shader1 = NULL;
-  filterblur->midtexture = 0;
-  /* gaussian kernel (well, actually vector), size 9, standard
-   * deviation 3.0 */
-  /* FIXME: eventually make this a runtime property */
-  fill_gaussian_kernel (filterblur->gauss_kernel, 7, 3.0);
-}
-
-static void
-gst_gl_filter_filterblur_reset (GstGLFilter * filter)
-{
-  GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (filter);
-
-  //blocking call, wait the opengl thread has destroyed the shader
-  if (filterblur->shader0)
-    gst_gl_context_del_shader (GST_GL_BASE_FILTER (filter)->context,
-        filterblur->shader0);
-  filterblur->shader0 = NULL;
-
-  //blocking call, wait the opengl thread has destroyed the shader
-  if (filterblur->shader1)
-    gst_gl_context_del_shader (GST_GL_BASE_FILTER (filter)->context,
-        filterblur->shader1);
-  filterblur->shader1 = NULL;
-}
-
-static void
-gst_gl_filterblur_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  /* GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (object); */
-
-  switch (prop_id) {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_gl_filterblur_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  /* GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (object); */
-
-  switch (prop_id) {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static gboolean
-gst_gl_filterblur_init_shader (GstGLFilter * filter)
-{
-  GstGLFilterBlur *blur_filter = GST_GL_FILTERBLUR (filter);
-
-  //blocking call, wait the opengl thread has compiled the shader
-  if (!gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, 0,
-          hconv7_fragment_source, &blur_filter->shader0))
-    return FALSE;
-
-  //blocking call, wait the opengl thread has compiled the shader
-  if (!gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, 0,
-          vconv7_fragment_source, &blur_filter->shader1))
-    return FALSE;
-
-  return TRUE;
-}
-
-static gboolean
-gst_gl_filterblur_filter_texture (GstGLFilter * filter, guint in_tex,
-    guint out_tex)
-{
-  GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (filter);
-
-  gst_gl_filter_render_to_target (filter, TRUE, in_tex,
-      filterblur->midtexture, gst_gl_filterblur_hcallback, filterblur);
-
-  gst_gl_filter_render_to_target (filter, FALSE, filterblur->midtexture,
-      out_tex, gst_gl_filterblur_vcallback, filterblur);
-
-  return TRUE;
-}
-
-static void
-gst_gl_filterblur_hcallback (gint width, gint height, guint texture,
-    gpointer stuff)
-{
-  GstGLFilter *filter = GST_GL_FILTER (stuff);
-  GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (filter);
-  GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
-
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
-
-  gst_gl_shader_use (filterblur->shader0);
-
-  gl->ActiveTexture (GL_TEXTURE1);
-  gl->Enable (GL_TEXTURE_2D);
-  gl->BindTexture (GL_TEXTURE_2D, texture);
-  gl->Disable (GL_TEXTURE_2D);
-
-  gst_gl_shader_set_uniform_1i (filterblur->shader0, "tex", 1);
-  gst_gl_shader_set_uniform_1fv (filterblur->shader0, "kernel", 7,
-      filterblur->gauss_kernel);
-  gst_gl_shader_set_uniform_1f (filterblur->shader0, "width", width);
-
-  gst_gl_filter_draw_texture (filter, texture, width, height);
-}
-
-
-static void
-gst_gl_filterblur_vcallback (gint width, gint height, guint texture,
-    gpointer stuff)
-{
-  GstGLFilter *filter = GST_GL_FILTER (stuff);
-  GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (filter);
-  GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
-
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
-
-  gst_gl_shader_use (filterblur->shader1);
-
-  gl->ActiveTexture (GL_TEXTURE1);
-  gl->Enable (GL_TEXTURE_2D);
-  gl->BindTexture (GL_TEXTURE_2D, texture);
-  gl->Disable (GL_TEXTURE_2D);
-
-  gst_gl_shader_set_uniform_1i (filterblur->shader1, "tex", 1);
-  gst_gl_shader_set_uniform_1fv (filterblur->shader1, "kernel", 7,
-      filterblur->gauss_kernel);
-  gst_gl_shader_set_uniform_1f (filterblur->shader1, "height", height);
-
-  gst_gl_filter_draw_texture (filter, texture, width, height);
-}
diff --git a/ext/gl/gstglfilterblur.h b/ext/gl/gstglfilterblur.h
deleted file mode 100644
index 9604d05..0000000
--- a/ext/gl/gstglfilterblur.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef _GST_GL_FILTERBLUR_H_
-#define _GST_GL_FILTERBLUR_H_
-
-#include <gst/gl/gstglfilter.h>
-
-#define GST_TYPE_GL_FILTERBLUR            (gst_gl_filterblur_get_type())
-#define GST_GL_FILTERBLUR(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_FILTERBLUR,GstGLFilterBlur))
-#define GST_IS_GL_FILTERBLUR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_FILTERBLUR))
-#define GST_GL_FILTERBLUR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_FILTERBLUR,GstGLFilterBlurClass))
-#define GST_IS_GL_FILTERBLUR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_FILTERBLUR))
-#define GST_GL_FILTERBLUR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_FILTERBLUR,GstGLFilterBlurClass))
-
-typedef struct _GstGLFilterBlur GstGLFilterBlur;
-typedef struct _GstGLFilterBlurClass GstGLFilterBlurClass;
-
-struct _GstGLFilterBlur
-{
-  GstGLFilter filter;
-  GstGLShader *shader0;
-  GstGLShader *shader1;
-
-  GLuint midtexture;
-  float gauss_kernel[7];
-};
-
-struct _GstGLFilterBlurClass
-{
-  GstGLFilterClass filter_class;
-};
-
-GType gst_gl_filterblur_get_type (void);
-
-#endif /* _GST_GL_FILTERBLUR_H_ */
diff --git a/ext/gl/gstglfiltercube.c b/ext/gl/gstglfiltercube.c
index 518b295..ad529b3 100644
--- a/ext/gl/gstglfiltercube.c
+++ b/ext/gl/gstglfiltercube.c
@@ -64,7 +64,7 @@
 
 #define DEBUG_INIT \
     GST_DEBUG_CATEGORY_INIT (gst_gl_filter_cube_debug, "glfiltercube", 0, "glfiltercube element");
-
+#define gst_gl_filter_cube_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstGLFilterCube, gst_gl_filter_cube,
     GST_TYPE_GL_FILTER, DEBUG_INIT);
 
@@ -73,9 +73,10 @@
 static void gst_gl_filter_cube_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
+static gboolean gst_gl_filter_cube_stop (GstBaseTransform * trans);
+
 static gboolean gst_gl_filter_cube_set_caps (GstGLFilter * filter,
     GstCaps * incaps, GstCaps * outcaps);
-static void gst_gl_filter_cube_reset (GstGLFilter * filter);
 static void gst_gl_filter_cube_reset_gl (GstGLFilter * filter);
 static gboolean gst_gl_filter_cube_init_shader (GstGLFilter * filter);
 static void _callback (gpointer stuff);
@@ -138,8 +139,9 @@
   gobject_class->set_property = gst_gl_filter_cube_set_property;
   gobject_class->get_property = gst_gl_filter_cube_get_property;
 
-  GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_filter_cube_init_shader;
-  GST_GL_FILTER_CLASS (klass)->onReset = gst_gl_filter_cube_reset;
+  GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_filter_cube_stop;
+
+  GST_GL_FILTER_CLASS (klass)->init_fbo = gst_gl_filter_cube_init_shader;
   GST_GL_FILTER_CLASS (klass)->display_reset_cb = gst_gl_filter_cube_reset_gl;
   GST_GL_FILTER_CLASS (klass)->set_caps = gst_gl_filter_cube_set_caps;
   GST_GL_FILTER_CLASS (klass)->filter_texture =
@@ -290,18 +292,26 @@
     gl->DeleteBuffers (1, &cube_filter->vertex_buffer);
     cube_filter->vertex_buffer = 0;
   }
+
+  if (cube_filter->shader) {
+    gst_gl_context_del_shader (GST_GL_BASE_FILTER (filter)->context,
+        cube_filter->shader);
+    cube_filter->shader = NULL;
+  }
 }
 
-static void
-gst_gl_filter_cube_reset (GstGLFilter * filter)
+static gboolean
+gst_gl_filter_cube_stop (GstBaseTransform * trans)
 {
-  GstGLFilterCube *cube_filter = GST_GL_FILTER_CUBE (filter);
+  GstGLFilterCube *cube_filter = GST_GL_FILTER_CUBE (trans);
 
   /* blocking call, wait the opengl thread has destroyed the shader */
   if (cube_filter->shader)
-    gst_gl_context_del_shader (GST_GL_BASE_FILTER (filter)->context,
+    gst_gl_context_del_shader (GST_GL_BASE_FILTER (trans)->context,
         cube_filter->shader);
   cube_filter->shader = NULL;
+
+  return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (trans);
 }
 
 static gboolean
@@ -309,6 +319,11 @@
 {
   GstGLFilterCube *cube_filter = GST_GL_FILTER_CUBE (filter);
 
+  if (cube_filter->shader) {
+    gst_object_unref (cube_filter->shader);
+    cube_filter->shader = NULL;
+  }
+
   /* blocking call, wait the opengl thread has compiled the shader */
   return gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context,
       cube_v_src, cube_f_src, &cube_filter->shader);
diff --git a/ext/gl/gstglfilterglass.c b/ext/gl/gstglfilterglass.c
index 0fe109a..0709954 100644
--- a/ext/gl/gstglfilterglass.c
+++ b/ext/gl/gstglfilterglass.c
@@ -53,7 +53,7 @@
 
 #define DEBUG_INIT \
   GST_DEBUG_CATEGORY_INIT (gst_gl_filter_glass_debug, "glfilterglass", 0, "glfilterglass element");
-
+#define gst_gl_filter_glass_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstGLFilterGlass, gst_gl_filter_glass,
     GST_TYPE_GL_FILTER, DEBUG_INIT);
 
@@ -62,7 +62,8 @@
 static void gst_gl_filter_glass_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
-static void gst_gl_filter_glass_reset (GstGLFilter * filter);
+static gboolean gst_gl_filter_glass_reset (GstBaseTransform * trans);
+
 static gboolean gst_gl_filter_glass_init_shader (GstGLFilter * filter);
 static gboolean gst_gl_filter_glass_filter_texture (GstGLFilter * filter,
     guint in_tex, guint out_tex);
@@ -160,8 +161,8 @@
 
   GST_GL_FILTER_CLASS (klass)->filter_texture =
       gst_gl_filter_glass_filter_texture;
-  GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_filter_glass_init_shader;
-  GST_GL_FILTER_CLASS (klass)->onReset = gst_gl_filter_glass_reset;
+  GST_GL_FILTER_CLASS (klass)->init_fbo = gst_gl_filter_glass_init_shader;
+  GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_filter_glass_reset;
 
   GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api = GST_GL_API_OPENGL;
 }
@@ -173,20 +174,22 @@
   filter->timestamp = 0;
 }
 
-static void
-gst_gl_filter_glass_reset (GstGLFilter * filter)
+static gboolean
+gst_gl_filter_glass_reset (GstBaseTransform * trans)
 {
-  GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter);
+  GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (trans);
 
   //blocking call, wait the opengl thread has destroyed the shader
   if (glass_filter->shader)
-    gst_gl_context_del_shader (GST_GL_BASE_FILTER (filter)->context,
+    gst_gl_context_del_shader (GST_GL_BASE_FILTER (trans)->context,
         glass_filter->shader);
   glass_filter->shader = NULL;
   if (glass_filter->passthrough_shader)
-    gst_gl_context_del_shader (GST_GL_BASE_FILTER (filter)->context,
+    gst_gl_context_del_shader (GST_GL_BASE_FILTER (trans)->context,
         glass_filter->passthrough_shader);
   glass_filter->passthrough_shader = NULL;
+
+  return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (trans);
 }
 
 static void
diff --git a/ext/gl/gstglfilterlaplacian.c b/ext/gl/gstglfilterlaplacian.c
deleted file mode 100644
index da656bc..0000000
--- a/ext/gl/gstglfilterlaplacian.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008-2010 Filippo Argiolas <filippo.argiolas@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:element-glfilterlaplacian
- *
- * Laplacian Convolution Demo Filter.
- *
- * <refsect2>
- * <title>Examples</title>
- * |[
- * gst-launch videotestsrc ! glupload ! glfilterlaplacian ! glimagesink
- * ]|
- * FBO (Frame Buffer Object) and GLSL (OpenGL Shading Language) are required.
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstglfilterlaplacian.h"
-
-#define GST_CAT_DEFAULT gst_gl_filter_laplacian_debug
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
-
-enum
-{
-  PROP_0
-};
-
-#define DEBUG_INIT \
-  GST_DEBUG_CATEGORY_INIT (gst_gl_filter_laplacian_debug, "glfilterlaplacian", 0, "glfilterlaplacian element");
-
-G_DEFINE_TYPE_WITH_CODE (GstGLFilterLaplacian, gst_gl_filter_laplacian,
-    GST_TYPE_GL_FILTER, DEBUG_INIT);
-
-static void gst_gl_filter_laplacian_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_gl_filter_laplacian_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec);
-
-static void gst_gl_filter_laplacian_reset (GstGLFilter * filter);
-static gboolean gst_gl_filter_laplacian_init_shader (GstGLFilter * filter);
-static gboolean gst_gl_filter_laplacian_filter_texture (GstGLFilter * filter,
-    guint in_tex, guint out_tex);
-static void gst_gl_filter_laplacian_callback (gint width, gint height,
-    guint texture, gpointer stuff);
-
-/* *INDENT-OFF* */
-
-/* This filter is meant as a demo of gst-plugins-gl + glsl
-   capabilities. So I'm keeping this shader readable enough. If and
-   when this shader will be used in production be careful to hard code
-   kernel into the shader and remove unneeded zero multiplications in
-   the convolution */
-static const gchar *convolution_fragment_source =
-  "uniform sampler2D tex;"
-  "uniform float kernel[9];"
-  "uniform float width, height;"
-  "void main () {"
-  "  float w = 1.0 / width;"
-  "  float h = 1.0 / height;"
-  "  vec2 texturecoord[9];"
-  "  texturecoord[4] = gl_TexCoord[0].st;"                /*  0  0 */
-  "  texturecoord[5] = texturecoord[4] + vec2(w,   0.0);" /*  1  0 */
-  "  texturecoord[2] = texturecoord[5] - vec2(0.0, h);" /*  1 -1 */
-  "  texturecoord[1] = texturecoord[2] - vec2(w,   0.0);" /*  0 -1 */
-  "  texturecoord[0] = texturecoord[1] - vec2(w,   0.0);" /* -1 -1 */
-  "  texturecoord[3] = texturecoord[0] + vec2(0.0, h);" /* -1  0 */
-  "  texturecoord[6] = texturecoord[3] + vec2(0.0, h);" /* -1  1 */
-  "  texturecoord[7] = texturecoord[6] + vec2(w,   0.0);" /*  0  1 */
-  "  texturecoord[8] = texturecoord[7] + vec2(w,   0.0);" /*  1  1 */
-  "  int i;"
-  "  vec4 sum = vec4 (0.0);"
-  "  for (i = 0; i < 9; i++) { "
-  "    vec4 neighbor = texture2D(tex, texturecoord[i]);"
-  "    sum += neighbor * kernel[i];"
-  "  }"
-  "  gl_FragColor = sum;"
-  "}";
-/* *INDENT-ON* */
-
-static void
-gst_gl_filter_laplacian_class_init (GstGLFilterLaplacianClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *element_class;
-
-  gobject_class = (GObjectClass *) klass;
-  element_class = GST_ELEMENT_CLASS (klass);
-
-  gobject_class->set_property = gst_gl_filter_laplacian_set_property;
-  gobject_class->get_property = gst_gl_filter_laplacian_get_property;
-
-  gst_element_class_set_metadata (element_class,
-      "OpenGL laplacian filter", "Filter/Effect/Video",
-      "Laplacian Convolution Demo Filter",
-      "Filippo Argiolas <filippo.argiolas@gmail.com>");
-
-  GST_GL_FILTER_CLASS (klass)->filter_texture =
-      gst_gl_filter_laplacian_filter_texture;
-  GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_filter_laplacian_init_shader;
-  GST_GL_FILTER_CLASS (klass)->onReset = gst_gl_filter_laplacian_reset;
-
-  GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api = GST_GL_API_OPENGL;
-}
-
-static void
-gst_gl_filter_laplacian_init (GstGLFilterLaplacian * filter)
-{
-  filter->shader = NULL;
-}
-
-static void
-gst_gl_filter_laplacian_reset (GstGLFilter * filter)
-{
-  GstGLFilterLaplacian *laplacian_filter = GST_GL_FILTER_LAPLACIAN (filter);
-
-  //blocking call, wait the opengl thread has destroyed the shader
-  if (laplacian_filter->shader)
-    gst_gl_context_del_shader (GST_GL_BASE_FILTER (filter)->context,
-        laplacian_filter->shader);
-  laplacian_filter->shader = NULL;
-}
-
-static void
-gst_gl_filter_laplacian_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  //GstGLFilterLaplacian *filter = GST_GL_FILTER_LAPLACIAN (object);
-
-  switch (prop_id) {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_gl_filter_laplacian_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  //GstGLFilterLaplacian *filter = GST_GL_FILTER_LAPLACIAN (object);
-
-  switch (prop_id) {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static gboolean
-gst_gl_filter_laplacian_init_shader (GstGLFilter * filter)
-{
-  GstGLFilterLaplacian *laplacian_filter = GST_GL_FILTER_LAPLACIAN (filter);
-
-  //blocking call, wait the opengl thread has compiled the shader
-  return gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, 0,
-      convolution_fragment_source, &laplacian_filter->shader);
-}
-
-static gboolean
-gst_gl_filter_laplacian_filter_texture (GstGLFilter * filter, guint in_tex,
-    guint out_tex)
-{
-  gpointer laplacian_filter = GST_GL_FILTER_LAPLACIAN (filter);
-
-
-  //blocking call, use a FBO
-  gst_gl_filter_render_to_target (filter, TRUE, in_tex, out_tex,
-      gst_gl_filter_laplacian_callback, laplacian_filter);
-
-  return TRUE;
-}
-
-//opengl scene, params: input texture (not the output filter->texture)
-static void
-gst_gl_filter_laplacian_callback (gint width, gint height, guint texture,
-    gpointer stuff)
-{
-  GstGLFilter *filter = GST_GL_FILTER (stuff);
-  GstGLFilterLaplacian *laplacian_filter = GST_GL_FILTER_LAPLACIAN (filter);
-  GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
-
-  gfloat kernel[9] = { 0.0, -1.0, 0.0,
-    -1.0, 4.0, -1.0,
-    0.0, -1.0, 0.0
-  };
-
-  gl->MatrixMode (GL_PROJECTION);
-  gl->LoadIdentity ();
-
-  gst_gl_shader_use (laplacian_filter->shader);
-
-  gl->ActiveTexture (GL_TEXTURE0);
-  gl->Enable (GL_TEXTURE_2D);
-  gl->BindTexture (GL_TEXTURE_2D, texture);
-
-  gst_gl_shader_set_uniform_1i (laplacian_filter->shader, "tex", 0);
-  gst_gl_shader_set_uniform_1fv (laplacian_filter->shader, "kernel", 9, kernel);
-  gst_gl_shader_set_uniform_1f (laplacian_filter->shader, "width",
-      (gfloat) width);
-  gst_gl_shader_set_uniform_1f (laplacian_filter->shader, "height",
-      (gfloat) height);
-
-  gst_gl_filter_draw_texture (filter, texture, width, height);
-}
diff --git a/ext/gl/gstglfilterlaplacian.h b/ext/gl/gstglfilterlaplacian.h
deleted file mode 100644
index 90a54e3..0000000
--- a/ext/gl/gstglfilterlaplacian.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* 
- * GStreamer
- * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef _GST_GL_FILTERLAPLACIAN_H_
-#define _GST_GL_FILTERLAPLACIAN_H_
-
-#include <gst/gl/gstglfilter.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GL_FILTER_LAPLACIAN            (gst_gl_filter_laplacian_get_type())
-#define GST_GL_FILTER_LAPLACIAN(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_FILTER_LAPLACIAN,GstGLFilterLaplacian))
-#define GST_IS_GL_FILTER_LAPLACIAN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_FILTER_LAPLACIAN))
-#define GST_GL_FILTER_LAPLACIAN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_FILTER_LAPLACIAN,GstGLFilterLaplacianClass))
-#define GST_IS_GL_FILTER_LAPLACIAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_FILTER_LAPLACIAN))
-#define GST_GL_FILTER_LAPLACIAN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_FILTER_LAPLACIAN,GstGLFilterLaplacianClass))
-
-typedef struct _GstGLFilterLaplacian GstGLFilterLaplacian;
-typedef struct _GstGLFilterLaplacianClass GstGLFilterLaplacianClass;
-
-struct _GstGLFilterLaplacian
-{
-  GstGLFilter filter;
-  GstGLShader *shader;
-};
-
-struct _GstGLFilterLaplacianClass
-{
-  GstGLFilterClass filter_class;
-};
-
-GType gst_gl_filter_laplacian_get_type (void);
-
-G_END_DECLS
-
-#endif /* _GST_GLFILTERLAPLACIAN_H_ */
diff --git a/ext/gl/gstglfiltershader.c b/ext/gl/gstglfiltershader.c
index 91c4cfb..0b96ebb 100644
--- a/ext/gl/gstglfiltershader.c
+++ b/ext/gl/gstglfiltershader.c
@@ -67,7 +67,7 @@
 
 #define DEBUG_INIT \
   GST_DEBUG_CATEGORY_INIT (gst_gl_filtershader_debug, "glshader", 0, "glshader element");
-
+#define gst_gl_filtershader_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstGLFilterShader, gst_gl_filtershader,
     GST_TYPE_GL_FILTER, DEBUG_INIT);
 
@@ -75,7 +75,7 @@
     const GValue * value, GParamSpec * pspec);
 static void gst_gl_filtershader_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
-static void gst_gl_filter_filtershader_reset (GstGLFilter * filter);
+static gboolean gst_gl_filter_filtershader_reset (GstBaseTransform * trans);
 
 static gboolean gst_gl_filtershader_load_shader (GstGLFilterShader *
     filter_shader, char *filename, char **storage);
@@ -140,6 +140,8 @@
       "OpenGL fragment shader filter", "Filter/Effect",
       "Load GLSL fragment shader from file", "<luc.deschenaux@freesurf.ch>");
 
+  GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_filter_filtershader_reset;
+
   GST_GL_FILTER_CLASS (klass)->filter = gst_gl_filtershader_filter;
   GST_GL_FILTER_CLASS (klass)->filter_texture =
       gst_gl_filtershader_filter_texture;
@@ -147,8 +149,7 @@
       gst_gl_filtershader_init_resources;
   GST_GL_FILTER_CLASS (klass)->display_reset_cb =
       gst_gl_filtershader_reset_resources;
-  GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_filtershader_init_shader;
-  GST_GL_FILTER_CLASS (klass)->onReset = gst_gl_filter_filtershader_reset;
+  GST_GL_FILTER_CLASS (klass)->init_fbo = gst_gl_filtershader_init_shader;
 
   GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api =
       GST_GL_API_OPENGL | GST_GL_API_GLES2 | GST_GL_API_OPENGL3;
@@ -160,16 +161,18 @@
   filtershader->shader0 = NULL;
 }
 
-static void
-gst_gl_filter_filtershader_reset (GstGLFilter * filter)
+static gboolean
+gst_gl_filter_filtershader_reset (GstBaseTransform * trans)
 {
-  GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (filter);
+  GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (trans);
 
   //blocking call, wait the opengl thread has destroyed the shader
   if (filtershader->shader0)
-    gst_gl_context_del_shader (GST_GL_BASE_FILTER (filter)->context,
+    gst_gl_context_del_shader (GST_GL_BASE_FILTER (trans)->context,
         filtershader->shader0);
   filtershader->shader0 = NULL;
+
+  return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (trans);
 }
 
 static void
@@ -186,8 +189,9 @@
         g_free (filtershader->filename);
       }
       if (filtershader->compiled) {
-        //gst_gl_context_del_shader (filtershader->filter.context, filtershader->shader0);
-        gst_gl_filter_filtershader_reset (&filtershader->filter);
+        if (filtershader->shader0)
+          gst_gl_context_del_shader (GST_GL_BASE_FILTER (filtershader)->context,
+              filtershader->shader0);
         filtershader->shader0 = 0;
       }
       filtershader->filename = g_strdup (g_value_get_string (value));
diff --git a/ext/gl/gstglfiltersobel.c b/ext/gl/gstglfiltersobel.c
deleted file mode 100644
index f70b6d2..0000000
--- a/ext/gl/gstglfiltersobel.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008-2010 Filippo Argiolas <filippo.argiolas@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/**
- * SECTION:element-glfiltersobel.
- *
- * Sobel Edge Detection.
- *
- * <refsect2>
- * <title>Examples</title>
- * |[
- * gst-launch videotestsrc ! glupload ! glfiltersobel ! glimagesink
- * ]|
- * FBO (Frame Buffer Object) and GLSL (OpenGL Shading Language) are required.
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstglfiltersobel.h"
-#include "effects/gstgleffectssources.h"
-
-enum
-{
-  PROP_0,
-  PROP_INVERT
-};
-
-#define GST_CAT_DEFAULT gst_gl_filtersobel_debug
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
-
-#define DEBUG_INIT \
-  GST_DEBUG_CATEGORY_INIT (gst_gl_filtersobel_debug, "glfiltersobel", 0, "glfiltersobel element");
-
-G_DEFINE_TYPE_WITH_CODE (GstGLFilterSobel, gst_gl_filtersobel,
-    GST_TYPE_GL_FILTER, DEBUG_INIT);
-
-static void gst_gl_filtersobel_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void gst_gl_filtersobel_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-static void gst_gl_filter_filtersobel_reset (GstGLFilter * filter);
-
-static gboolean gst_gl_filtersobel_init_shader (GstGLFilter * filter);
-static gboolean gst_gl_filtersobel_filter_texture (GstGLFilter * filter,
-    guint in_tex, guint out_tex);
-
-static void gst_gl_filtersobel_length (gint width, gint height, guint texture,
-    gpointer stuff);
-
-static void
-gst_gl_filtersobel_init_resources (GstGLFilter * filter)
-{
-  GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (filter);
-  GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
-  int i;
-
-  for (i = 0; i < 2; i++) {
-    gl->GenTextures (1, &filtersobel->midtexture[i]);
-    gl->BindTexture (GL_TEXTURE_2D, filtersobel->midtexture[i]);
-    gl->TexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8,
-        GST_VIDEO_INFO_WIDTH (&filter->out_info),
-        GST_VIDEO_INFO_HEIGHT (&filter->out_info),
-        0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-    gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-  }
-}
-
-static void
-gst_gl_filtersobel_reset_resources (GstGLFilter * filter)
-{
-  GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (filter);
-  GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
-  int i;
-
-  for (i = 0; i < 2; i++) {
-    gl->DeleteTextures (1, &filtersobel->midtexture[i]);
-  }
-}
-
-static void
-gst_gl_filtersobel_class_init (GstGLFilterSobelClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *element_class;
-
-  gobject_class = (GObjectClass *) klass;
-  element_class = GST_ELEMENT_CLASS (klass);
-
-  gobject_class->set_property = gst_gl_filtersobel_set_property;
-  gobject_class->get_property = gst_gl_filtersobel_get_property;
-
-  GST_GL_FILTER_CLASS (klass)->filter_texture =
-      gst_gl_filtersobel_filter_texture;
-  GST_GL_FILTER_CLASS (klass)->display_init_cb =
-      gst_gl_filtersobel_init_resources;
-  GST_GL_FILTER_CLASS (klass)->display_reset_cb =
-      gst_gl_filtersobel_reset_resources;
-  GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_filtersobel_init_shader;
-  GST_GL_FILTER_CLASS (klass)->onReset = gst_gl_filter_filtersobel_reset;
-
-  g_object_class_install_property (gobject_class,
-      PROP_INVERT,
-      g_param_spec_boolean ("invert",
-          "Invert the colors",
-          "Invert colors to get dark edges on bright background",
-          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-  gst_element_class_set_metadata (element_class,
-      "Gstreamer OpenGL Sobel", "Filter/Effect/Video", "Sobel edge detection",
-      "Filippo Argiolas <filippo.argiolas@gmail.com>");
-
-  GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api = GST_GL_API_OPENGL;
-}
-
-static void
-gst_gl_filtersobel_init (GstGLFilterSobel * filtersobel)
-{
-  int i;
-  filtersobel->hconv = NULL;
-  filtersobel->vconv = NULL;
-  filtersobel->invert = FALSE;
-  for (i = 0; i < 2; i++) {
-    filtersobel->midtexture[i] = 0;
-  }
-}
-
-static void
-gst_gl_filter_filtersobel_reset (GstGLFilter * filter)
-{
-  GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (filter);
-
-  //blocking call, wait the opengl thread has destroyed the shader
-  if (filtersobel->desat)
-    gst_gl_context_del_shader (GST_GL_BASE_FILTER (filter)->context,
-        filtersobel->desat);
-  filtersobel->desat = NULL;
-
-  if (filtersobel->hconv)
-    gst_gl_context_del_shader (GST_GL_BASE_FILTER (filter)->context,
-        filtersobel->hconv);
-  filtersobel->hconv = NULL;
-
-  if (filtersobel->vconv)
-    gst_gl_context_del_shader (GST_GL_BASE_FILTER (filter)->context,
-        filtersobel->vconv);
-  filtersobel->vconv = NULL;
-
-  if (filtersobel->len)
-    gst_gl_context_del_shader (GST_GL_BASE_FILTER (filter)->context,
-        filtersobel->len);
-  filtersobel->len = NULL;
-}
-
-static void
-gst_gl_filtersobel_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (object);
-
-  switch (prop_id) {
-    case PROP_INVERT:
-      filtersobel->invert = g_value_get_boolean (value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_gl_filtersobel_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (object);
-
-  switch (prop_id) {
-    case PROP_INVERT:
-      g_value_set_boolean (value, filtersobel->invert);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static gboolean
-gst_gl_filtersobel_init_shader (GstGLFilter * filter)
-{
-  GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (filter);
-  gboolean ret = TRUE;
-
-  //blocking call, wait the opengl thread has compiled the shader
-  ret =
-      gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, 0,
-      desaturate_fragment_source, &filtersobel->desat);
-  ret &=
-      gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, 0,
-      sep_sobel_hconv3_fragment_source, &filtersobel->hconv);
-  ret &=
-      gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, 0,
-      sep_sobel_vconv3_fragment_source, &filtersobel->vconv);
-  ret &=
-      gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, 0,
-      sep_sobel_length_fragment_source, &filtersobel->len);
-
-  return ret;
-}
-
-static gboolean
-gst_gl_filtersobel_filter_texture (GstGLFilter * filter, guint in_tex,
-    guint out_tex)
-{
-  GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (filter);
-
-  gst_gl_filter_render_to_target_with_shader (filter, TRUE, in_tex,
-      filtersobel->midtexture[0], filtersobel->desat);
-  gst_gl_filter_render_to_target_with_shader (filter, FALSE,
-      filtersobel->midtexture[0], filtersobel->midtexture[1],
-      filtersobel->hconv);
-  gst_gl_filter_render_to_target_with_shader (filter, FALSE,
-      filtersobel->midtexture[1], filtersobel->midtexture[0],
-      filtersobel->vconv);
-  gst_gl_filter_render_to_target (filter, FALSE, filtersobel->midtexture[0],
-      out_tex, gst_gl_filtersobel_length, filtersobel);
-
-  return TRUE;
-}
-
-static void
-gst_gl_filtersobel_length (gint width, gint height, guint texture,
-    gpointer stuff)
-{
-  GstGLFilter *filter = GST_GL_FILTER (stuff);
-  GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
-  GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (filter);
-
-  glMatrixMode (GL_PROJECTION);
-  glLoadIdentity ();
-
-  gst_gl_shader_use (filtersobel->len);
-
-  gl->ActiveTexture (GL_TEXTURE1);
-  gl->Enable (GL_TEXTURE_2D);
-  gl->BindTexture (GL_TEXTURE_2D, texture);
-  gl->Disable (GL_TEXTURE_2D);
-
-  gst_gl_shader_set_uniform_1i (filtersobel->len, "tex", 1);
-  gst_gl_shader_set_uniform_1i (filtersobel->len, "invert",
-      filtersobel->invert);
-
-  gst_gl_filter_draw_texture (filter, texture, width, height);
-}
diff --git a/ext/gl/gstglfiltersobel.h b/ext/gl/gstglfiltersobel.h
deleted file mode 100644
index 3b88baf..0000000
--- a/ext/gl/gstglfiltersobel.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef _GST_GL_FILTERSOBEL_H_
-#define _GST_GL_FILTERSOBEL_H_
-
-#include <gst/gl/gstglfilter.h>
-
-#define GST_TYPE_GL_FILTERSOBEL            (gst_gl_filtersobel_get_type())
-#define GST_GL_FILTERSOBEL(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_FILTERSOBEL,GstGLFilterSobel))
-#define GST_IS_GL_FILTERSOBEL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_FILTERSOBEL))
-#define GST_GL_FILTERSOBEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_FILTERSOBEL,GstGLFilterSobelClass))
-#define GST_IS_GL_FILTERSOBEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_FILTERSOBEL))
-#define GST_GL_FILTERSOBEL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_FILTERSOBEL,GstGLFilterSobelClass))
-
-typedef struct _GstGLFilterSobel GstGLFilterSobel;
-typedef struct _GstGLFilterSobelClass GstGLFilterSobelClass;
-
-struct _GstGLFilterSobel
-{
-  GstGLFilter filter;
-  GstGLShader *hconv;
-  GstGLShader *vconv;
-  GstGLShader *len;
-  GstGLShader *desat;
-
-  GLuint midtexture[5];
-
-  gboolean invert;
-};
-
-struct _GstGLFilterSobelClass
-{
-  GstGLFilterClass filter_class;
-};
-
-GType gst_gl_filtersobel_get_type (void);
-
-#endif /* _GST_GL_FILTERSOBEL_H_ */
diff --git a/ext/gl/gstglimagesink.c b/ext/gl/gstglimagesink.c
index ae3f3df..15aebe2 100644
--- a/ext/gl/gstglimagesink.c
+++ b/ext/gl/gstglimagesink.c
@@ -325,8 +325,6 @@
 static void gst_glimage_sink_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * param_spec);
 
-static gboolean gst_glimage_sink_stop (GstBaseSink * bsink);
-
 static gboolean gst_glimage_sink_query (GstBaseSink * bsink, GstQuery * query);
 static void gst_glimage_sink_set_context (GstElement * element,
     GstContext * context);
@@ -547,7 +545,6 @@
   gstbasesink_class->get_times = gst_glimage_sink_get_times;
   gstbasesink_class->prepare = gst_glimage_sink_prepare;
   gstbasesink_class->propose_allocation = gst_glimage_sink_propose_allocation;
-  gstbasesink_class->stop = gst_glimage_sink_stop;
 
   gstvideosink_class->show_frame =
       GST_DEBUG_FUNCPTR (gst_glimage_sink_show_frame);
@@ -624,11 +621,6 @@
 
   g_mutex_clear (&glimage_sink->drawing_lock);
 
-  if (glimage_sink->other_context) {
-    gst_object_unref (glimage_sink->other_context);
-    glimage_sink->other_context = NULL;
-  }
-
   g_free (glimage_sink->display_name);
 
   GST_DEBUG ("finalized");
@@ -698,6 +690,7 @@
   GST_DEBUG_OBJECT (gl_sink, "Ensuring setup");
 
   if (!gl_sink->context) {
+    GST_OBJECT_LOCK (gl_sink->display);
     do {
       GstGLContext *other_context;
       GstGLWindow *window;
@@ -770,6 +763,7 @@
         gst_object_unref (other_context);
       gst_object_unref (window);
     } while (!gst_gl_display_add_context (gl_sink->display, gl_sink->context));
+    GST_OBJECT_UNLOCK (gl_sink->display);
   } else
     GST_DEBUG_OBJECT (gl_sink, "Already have a context");
 
@@ -803,10 +797,8 @@
     {
       const gchar *context_type;
       GstContext *context, *old_context;
-      gboolean ret;
 
-      ret =
-          gst_gl_handle_context_query ((GstElement *) glimage_sink, query,
+      res = gst_gl_handle_context_query ((GstElement *) glimage_sink, query,
           &glimage_sink->display, &glimage_sink->other_context);
       if (glimage_sink->display)
         gst_gl_display_filter_gl_api (glimage_sink->display, SUPPORTED_GL_APIS);
@@ -829,12 +821,14 @@
         gst_query_set_context (query, context);
         gst_context_unref (context);
 
-        ret = glimage_sink->context != NULL;
+        res = glimage_sink->context != NULL;
       }
-      GST_DEBUG_OBJECT (glimage_sink, "context query of type %s %i",
-          context_type, ret);
+      GST_LOG_OBJECT (glimage_sink, "context query of type %s %i", context_type,
+          res);
 
-      return ret;
+      if (res)
+        return res;
+      break;
     }
     case GST_QUERY_DRAIN:
     {
@@ -862,19 +856,6 @@
   return res;
 }
 
-static gboolean
-gst_glimage_sink_stop (GstBaseSink * bsink)
-{
-  GstGLImageSink *glimage_sink = GST_GLIMAGE_SINK (bsink);
-
-  if (glimage_sink->pool) {
-    gst_object_unref (glimage_sink->pool);
-    glimage_sink->pool = NULL;
-  }
-
-  return TRUE;
-}
-
 static void
 gst_glimage_sink_set_context (GstElement * element, GstContext * context)
 {
@@ -908,6 +889,9 @@
       gst_gl_display_filter_gl_api (glimage_sink->display, SUPPORTED_GL_APIS);
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
+      if (!_ensure_gl_setup (glimage_sink))
+        return GST_STATE_CHANGE_FAILURE;
+
       g_atomic_int_set (&glimage_sink->to_quit, 0);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
@@ -942,6 +926,18 @@
 
       GST_VIDEO_SINK_WIDTH (glimage_sink) = 1;
       GST_VIDEO_SINK_HEIGHT (glimage_sink) = 1;
+      /* Clear cached caps */
+      if (glimage_sink->caps) {
+        gst_caps_unref (glimage_sink->caps);
+        glimage_sink->caps = NULL;
+      }
+
+      /* we're losing the context, this pool is no use anymore */
+      if (glimage_sink->pool) {
+        gst_object_unref (glimage_sink->pool);
+        glimage_sink->pool = NULL;
+      }
+
       if (glimage_sink->context) {
         GstGLWindow *window = gst_gl_context_get_window (glimage_sink->context);
 
@@ -952,19 +948,30 @@
         gst_gl_window_set_draw_callback (window, NULL, NULL, NULL);
         gst_gl_window_set_close_callback (window, NULL, NULL, NULL);
 
+        if (glimage_sink->key_sig_id)
+          g_signal_handler_disconnect (window, glimage_sink->key_sig_id);
+        glimage_sink->key_sig_id = 0;
+        if (glimage_sink->mouse_sig_id)
+          g_signal_handler_disconnect (window, glimage_sink->mouse_sig_id);
+        glimage_sink->mouse_sig_id = 0;
+
         gst_object_unref (window);
         gst_object_unref (glimage_sink->context);
         glimage_sink->context = NULL;
       }
+      break;
+    }
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      if (glimage_sink->other_context) {
+        gst_object_unref (glimage_sink->other_context);
+        glimage_sink->other_context = NULL;
+      }
 
       if (glimage_sink->display) {
         gst_object_unref (glimage_sink->display);
         glimage_sink->display = NULL;
       }
       break;
-    }
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      break;
     default:
       break;
   }
@@ -1001,7 +1008,7 @@
   GstCaps *tmp = NULL;
   GstCaps *result = NULL;
 
-  tmp = gst_caps_from_string ("video/x-raw(memory:GLMemory),format=RGBA");
+  tmp = gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD (bsink));
 
   if (filter) {
     result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
@@ -1085,6 +1092,8 @@
       GST_VIDEO_SINK_HEIGHT (glimage_sink));
 
   glimage_sink->info = vinfo;
+  glimage_sink->caps = gst_caps_ref (caps);
+
   if (!_ensure_gl_setup (glimage_sink))
     return FALSE;
 
@@ -1516,8 +1525,7 @@
   gl->BindTexture (GL_TEXTURE_2D, 0);
 
   sample = gst_sample_new (gl_sink->stored_buffer,
-      gst_video_info_to_caps (&gl_sink->info),
-      &GST_BASE_SINK (gl_sink)->segment, NULL);
+      gl_sink->caps, &GST_BASE_SINK (gl_sink)->segment, NULL);
 
   g_signal_emit (gl_sink, gst_glimage_sink_signals[CLIENT_DRAW_SIGNAL], 0,
       gl_sink->context, sample, &do_redisplay);
@@ -1577,8 +1585,12 @@
 
   window = gst_gl_context_get_window (gl_sink->context);
 
-  g_signal_handler_disconnect (window, gl_sink->key_sig_id);
-  g_signal_handler_disconnect (window, gl_sink->mouse_sig_id);
+  if (gl_sink->key_sig_id)
+    g_signal_handler_disconnect (window, gl_sink->key_sig_id);
+  gl_sink->key_sig_id = 0;
+  if (gl_sink->mouse_sig_id)
+    g_signal_handler_disconnect (window, gl_sink->mouse_sig_id);
+  gl_sink->mouse_sig_id = 0;
 
   g_atomic_int_set (&gl_sink->to_quit, 1);
 
diff --git a/ext/gl/gstglimagesink.h b/ext/gl/gstglimagesink.h
index 1eed7b3..ce93ba7 100644
--- a/ext/gl/gstglimagesink.h
+++ b/ext/gl/gstglimagesink.h
@@ -61,6 +61,7 @@
 
     //caps
     GstVideoInfo info;
+    GstCaps *caps;
 
     GstGLDisplay *display;
     GstGLContext *context;
diff --git a/ext/gl/gstglmixer.c b/ext/gl/gstglmixer.c
index 51bd517..119ab5a 100644
--- a/ext/gl/gstglmixer.c
+++ b/ext/gl/gstglmixer.c
@@ -42,7 +42,6 @@
     GValue * value, GParamSpec * pspec);
 static void gst_gl_mixer_pad_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
-static void gst_gl_mixer_pad_finalize (GObject * object);
 
 enum
 {
@@ -73,20 +72,12 @@
   gobject_class->set_property = gst_gl_mixer_pad_set_property;
   gobject_class->get_property = gst_gl_mixer_pad_get_property;
 
-  gobject_class->finalize = gst_gl_mixer_pad_finalize;
-
   vaggpad_class->set_info = NULL;
   vaggpad_class->prepare_frame = NULL;
   vaggpad_class->clean_frame = NULL;
 }
 
 static void
-gst_gl_mixer_pad_finalize (GObject * object)
-{
-  G_OBJECT_CLASS (gst_gl_mixer_pad_parent_class)->finalize (object);
-}
-
-static void
 gst_gl_mixer_pad_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec)
 {
@@ -123,6 +114,26 @@
   return ret;
 }
 
+static void
+_find_best_format (GstVideoAggregator * vagg, GstCaps * downstream_caps,
+    GstVideoInfo * best_info, gboolean * at_least_one_alpha)
+{
+  GstVideoInfo tmp_info;
+
+  GST_VIDEO_AGGREGATOR_CLASS (parent_class)->find_best_format (vagg,
+      downstream_caps, best_info, at_least_one_alpha);
+
+  gst_video_info_set_format (&tmp_info, GST_VIDEO_FORMAT_RGBA,
+      best_info->width, best_info->height);
+  tmp_info.par_n = best_info->par_n;
+  tmp_info.par_d = best_info->par_d;
+  tmp_info.fps_n = best_info->fps_n;
+  tmp_info.fps_d = best_info->fps_d;
+  tmp_info.flags = best_info->flags;
+  tmp_info.interlace_mode = best_info->interlace_mode;
+  *best_info = tmp_info;
+}
+
 static gboolean
 gst_gl_mixer_propose_allocation (GstGLBaseMixer * base_mix,
     GstGLBaseMixerPad * base_pad, GstQuery * decide_query, GstQuery * query)
@@ -222,27 +233,27 @@
   GstCaps *template_caps;
   GstCaps *filtered_caps;
   GstCaps *returned_caps;
-  gboolean had_current_caps = TRUE;
 
   template_caps = gst_pad_get_pad_template_caps (pad);
 
   sinkcaps = gst_pad_get_current_caps (pad);
   if (sinkcaps == NULL) {
-    had_current_caps = FALSE;
-    sinkcaps = template_caps;
+    sinkcaps = gst_caps_ref (template_caps);
   } else {
-    sinkcaps = gst_caps_merge (sinkcaps, template_caps);
+    sinkcaps = gst_caps_merge (sinkcaps, gst_caps_ref (template_caps));
   }
 
-  filtered_caps = sinkcaps;
-  if (filter)
+  if (filter) {
     filtered_caps = gst_caps_intersect (sinkcaps, filter);
+    gst_caps_unref (sinkcaps);
+  } else {
+    filtered_caps = sinkcaps;   /* pass ownership */
+  }
+
   returned_caps = gst_caps_intersect (filtered_caps, template_caps);
 
-  if (filter)
-    gst_caps_unref (filtered_caps);
-  if (had_current_caps)
-    gst_caps_unref (template_caps);
+  gst_caps_unref (template_caps);
+  gst_caps_unref (filtered_caps);
 
   GST_DEBUG_OBJECT (pad, "returning %" GST_PTR_FORMAT, returned_caps);
 
@@ -375,7 +386,7 @@
   videoaggregator_class->get_output_buffer = gst_gl_mixer_get_output_buffer;
   videoaggregator_class->negotiated_caps = _negotiated_caps;
   videoaggregator_class->update_caps = _update_caps;
-  videoaggregator_class->find_best_format = NULL;
+  videoaggregator_class->find_best_format = _find_best_format;
 
   mix_class->propose_allocation = gst_gl_mixer_propose_allocation;
   mix_class->decide_allocation = gst_gl_mixer_decide_allocation;
@@ -413,6 +424,9 @@
   GstGLMixer *mix = GST_GL_MIXER (object);
   GstGLMixerPrivate *priv = mix->priv;
 
+  if (mix->out_caps)
+    gst_caps_unref (mix->out_caps);
+
   g_mutex_clear (&priv->gl_resource_lock);
   g_cond_clear (&priv->gl_resource_cond);
   G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -508,7 +522,6 @@
   GstCaps *caps;
   guint min, max, size;
   gboolean update_pool;
-  GError *error = NULL;
   guint out_width, out_height;
 
   out_width = GST_VIDEO_INFO_WIDTH (&vagg->info);
@@ -572,8 +585,7 @@
 
 context_error:
   {
-    GST_ELEMENT_ERROR (mix, RESOURCE, NOT_FOUND, ("%s", error->message),
-        (NULL));
+    GST_ELEMENT_ERROR (mix, RESOURCE, NOT_FOUND, ("Context error"), (NULL));
     return FALSE;
   }
 }
@@ -754,9 +766,9 @@
   GstElement *element = GST_ELEMENT (agg);
 
   GST_OBJECT_LOCK (mix);
-  mix->array_buffers = g_ptr_array_new_full (element->numsinkpads,
+  mix->array_buffers = g_ptr_array_new_full (element->numsinkpads, NULL);
+  mix->frames = g_ptr_array_new_full (element->numsinkpads,
       (GDestroyNotify) _free_glmixer_frame_data);
-  mix->frames = g_ptr_array_new_full (element->numsinkpads, NULL);
 
   g_ptr_array_set_size (mix->array_buffers, element->numsinkpads);
   g_ptr_array_set_size (mix->frames, element->numsinkpads);
diff --git a/ext/gl/gstglmixerbin.c b/ext/gl/gstglmixerbin.c
index 2dada97..ae8abef 100644
--- a/ext/gl/gstglmixerbin.c
+++ b/ext/gl/gstglmixerbin.c
@@ -110,12 +110,6 @@
     GST_STATIC_CAPS ("video/x-raw(ANY)")
     );
 
-static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink_%u",
-    GST_PAD_SINK,
-    GST_PAD_REQUEST,
-    GST_STATIC_CAPS ("video/x-raw(ANY)")
-    );
-
 static void gst_gl_mixer_bin_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_gl_mixer_bin_get_property (GObject * object, guint prop_id,
@@ -133,6 +127,7 @@
 {
   GObjectClass *gobject_class = (GObjectClass *) klass;
   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstCaps *upload_caps;
 
   g_type_class_add_private (klass, sizeof (GstGLMixerBinPrivate));
 
@@ -178,8 +173,12 @@
 
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&src_factory));
+
+  upload_caps = gst_gl_upload_get_input_template_caps ();
   gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&sink_factory));
+      gst_pad_template_new ("sink_%u", GST_PAD_SINK, GST_PAD_REQUEST,
+          upload_caps));
+  gst_caps_unref (upload_caps);
 }
 
 static void
@@ -425,7 +424,6 @@
 
   mixer_pad =
       gst_element_request_pad (self->mixer, mixer_templ, req_name, NULL);
-  gst_object_unref (mixer_templ);
   g_return_val_if_fail (mixer_pad, NULL);
 
   if (!_create_input_chain (self, chain, mixer_pad)) {
diff --git a/ext/gl/gstgloverlay.c b/ext/gl/gstgloverlay.c
index 2dd5326..916389b 100644
--- a/ext/gl/gstgloverlay.c
+++ b/ext/gl/gstgloverlay.c
@@ -68,8 +68,6 @@
 static void gst_gl_overlay_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
-static void gst_gl_overlay_reset_resources (GstGLFilter * filter);
-
 static void gst_gl_overlay_before_transform (GstBaseTransform * trans,
     GstBuffer * outbuf);
 static gboolean gst_gl_overlay_filter_texture (GstGLFilter * filter,
@@ -187,8 +185,7 @@
   GST_GL_FILTER_CLASS (klass)->filter_texture = gst_gl_overlay_filter_texture;
   GST_GL_FILTER_CLASS (klass)->display_reset_cb =
       gst_gl_overlay_reset_gl_resources;
-  GST_GL_FILTER_CLASS (klass)->onStop = gst_gl_overlay_reset_resources;
-  GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_overlay_init_gl_resources;
+  GST_GL_FILTER_CLASS (klass)->init_fbo = gst_gl_overlay_init_gl_resources;
 
   GST_BASE_TRANSFORM_CLASS (klass)->before_transform =
       GST_DEBUG_FUNCPTR (gst_gl_overlay_before_transform);
@@ -267,11 +264,6 @@
 }
 
 static void
-gst_gl_overlay_reset_resources (GstGLFilter * filter)
-{
-}
-
-static void
 gst_gl_overlay_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
diff --git a/ext/gl/gstglsinkbin.c b/ext/gl/gstglsinkbin.c
index ec6a1e2..1f4bd53 100644
--- a/ext/gl/gstglsinkbin.c
+++ b/ext/gl/gstglsinkbin.c
@@ -30,7 +30,6 @@
 GST_DEBUG_CATEGORY (gst_debug_gl_sink_bin);
 #define GST_CAT_DEFAULT gst_debug_gl_sink_bin
 
-static void gst_gl_sink_bin_finalize (GObject * object);
 static void gst_gl_sink_bin_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * param_spec);
 static void gst_gl_sink_bin_get_property (GObject * object, guint prop_id,
@@ -44,12 +43,6 @@
 static void gst_gl_sink_bin_navigation_interface_init (gpointer g_iface,
     gpointer g_iface_data);
 
-static GstStaticPadTemplate gst_gl_sink_bin_template =
-GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-raw(ANY)"));
-
 enum
 {
   PROP_0,
@@ -80,6 +73,7 @@
 {
   GObjectClass *gobject_class;
   GstElementClass *element_class;
+  GstCaps *upload_caps;
 
   gobject_class = (GObjectClass *) klass;
   element_class = GST_ELEMENT_CLASS (klass);
@@ -88,7 +82,6 @@
 
   gobject_class->set_property = gst_gl_sink_bin_set_property;
   gobject_class->get_property = gst_gl_sink_bin_get_property;
-  gobject_class->finalize = gst_gl_sink_bin_finalize;
 
   g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
       g_param_spec_boolean ("force-aspect-ratio",
@@ -121,14 +114,10 @@
       "Infrastructure to process GL textures",
       "Matthew Waters <matthew@centricular.com>");
 
+  upload_caps = gst_gl_upload_get_input_template_caps ();
   gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_gl_sink_bin_template));
-}
-
-static void
-gst_gl_sink_bin_finalize (GObject * object)
-{
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+      gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, upload_caps));
+  gst_caps_unref (upload_caps);
 }
 
 static void
diff --git a/ext/gl/gstglsrcbin.c b/ext/gl/gstglsrcbin.c
index 58d34c6..76510a0 100644
--- a/ext/gl/gstglsrcbin.c
+++ b/ext/gl/gstglsrcbin.c
@@ -27,7 +27,6 @@
 GST_DEBUG_CATEGORY (gst_debug_gl_src_bin);
 #define GST_CAT_DEFAULT gst_debug_gl_src_bin
 
-static void gst_gl_src_bin_finalize (GObject * object);
 static void gst_gl_src_bin_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * param_spec);
 static void gst_gl_src_bin_get_property (GObject * object, guint prop_id,
@@ -76,7 +75,6 @@
 
   gobject_class->set_property = gst_gl_src_bin_set_property;
   gobject_class->get_property = gst_gl_src_bin_get_property;
-  gobject_class->finalize = gst_gl_src_bin_finalize;
 
   g_object_class_install_property (gobject_class, PROP_SRC,
       g_param_spec_object ("src",
@@ -109,12 +107,6 @@
 }
 
 static void
-gst_gl_src_bin_finalize (GObject * object)
-{
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
 gst_gl_src_bin_init (GstGLSrcBin * self)
 {
   gboolean res = TRUE;
diff --git a/ext/gl/gstgltestsrc.c b/ext/gl/gstgltestsrc.c
index dbd5610..eba66b0 100644
--- a/ext/gl/gstgltestsrc.c
+++ b/ext/gl/gstgltestsrc.c
@@ -80,10 +80,8 @@
     const GValue * value, GParamSpec * pspec);
 static void gst_gl_test_src_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
-static void gst_gl_test_src_dispose (GObject * object);
 
 static gboolean gst_gl_test_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps);
-static GstCaps *gst_gl_test_src_getcaps (GstBaseSrc * bsrc, GstCaps * filter);
 static GstCaps *gst_gl_test_src_fixate (GstBaseSrc * bsrc, GstCaps * caps);
 
 static gboolean gst_gl_test_src_is_seekable (GstBaseSrc * psrc);
@@ -156,7 +154,6 @@
 
   gobject_class->set_property = gst_gl_test_src_set_property;
   gobject_class->get_property = gst_gl_test_src_get_property;
-  gobject_class->dispose = gst_gl_test_src_dispose;
 
   g_object_class_install_property (gobject_class, PROP_PATTERN,
       g_param_spec_enum ("pattern", "Pattern",
@@ -183,7 +180,6 @@
   element_class->change_state = gst_gl_test_src_change_state;
 
   gstbasesrc_class->set_caps = gst_gl_test_src_setcaps;
-  gstbasesrc_class->get_caps = gst_gl_test_src_getcaps;
   gstbasesrc_class->is_seekable = gst_gl_test_src_is_seekable;
   gstbasesrc_class->do_seek = gst_gl_test_src_do_seek;
   gstbasesrc_class->query = gst_gl_test_src_query;
@@ -387,18 +383,6 @@
 }
 
 static void
-gst_gl_test_src_dispose (GObject * object)
-{
-  GstGLTestSrc *src = GST_GL_TEST_SRC (object);
-
-  if (src->other_context)
-    gst_object_unref (src->other_context);
-  src->other_context = NULL;
-
-  G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
 gst_gl_test_src_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
@@ -465,24 +449,6 @@
   }
 }
 
-static GstCaps *
-gst_gl_test_src_getcaps (GstBaseSrc * bsrc, GstCaps * filter)
-{
-  GstCaps *tmp = NULL;
-  GstCaps *result =
-      gst_caps_from_string ("video/x-raw(memory:GLMemory),format=RGBA");
-
-  if (filter) {
-    tmp = gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
-    gst_caps_unref (result);
-    result = tmp;
-  }
-
-  GST_DEBUG_OBJECT (bsrc, "returning caps: %" GST_PTR_FORMAT, result);
-
-  return result;
-}
-
 static void
 gst_gl_test_src_set_context (GstElement * element, GstContext * context)
 {
@@ -749,11 +715,6 @@
     src->context = NULL;
   }
 
-  if (src->display) {
-    gst_object_unref (src->display);
-    src->display = NULL;
-  }
-
   return TRUE;
 }
 
@@ -816,6 +777,7 @@
   _find_local_gl_context (src);
 
   if (!src->context) {
+    GST_OBJECT_LOCK (src->display);
     do {
       if (src->context)
         gst_object_unref (src->context);
@@ -828,6 +790,7 @@
           goto context_error;
       }
     } while (!gst_gl_display_add_context (src->display, src->context));
+    GST_OBJECT_UNLOCK (src->display);
   }
 
   out_width = GST_VIDEO_INFO_WIDTH (&src->out_info);
@@ -932,6 +895,17 @@
     return ret;
 
   switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      if (src->other_context) {
+        gst_object_unref (src->other_context);
+        src->other_context = NULL;
+      }
+
+      if (src->display) {
+        gst_object_unref (src->display);
+        src->display = NULL;
+      }
+      break;
     default:
       break;
   }
diff --git a/ext/gl/gstgltransformation.c b/ext/gl/gstgltransformation.c
index f9273c7..4bd022e 100644
--- a/ext/gl/gstgltransformation.c
+++ b/ext/gl/gstgltransformation.c
@@ -52,6 +52,8 @@
 #define GST_CAT_DEFAULT gst_gl_transformation_debug
 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
 
+#define gst_gl_transformation_parent_class parent_class
+
 enum
 {
   PROP_0,
@@ -83,7 +85,7 @@
     GstCaps * incaps, GstCaps * outcaps);
 
 static void gst_gl_transformation_reset_gl (GstGLFilter * filter);
-static void gst_gl_transformation_reset (GstGLFilter * filter);
+static gboolean gst_gl_transformation_stop (GstBaseTransform * trans);
 static gboolean gst_gl_transformation_init_shader (GstGLFilter * filter);
 static void gst_gl_transformation_callback (gpointer stuff);
 static void gst_gl_transformation_build_mvp (GstGLTransformation *
@@ -128,13 +130,13 @@
   gobject_class->set_property = gst_gl_transformation_set_property;
   gobject_class->get_property = gst_gl_transformation_get_property;
 
-  GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_transformation_init_shader;
+  GST_GL_FILTER_CLASS (klass)->init_fbo = gst_gl_transformation_init_shader;
   GST_GL_FILTER_CLASS (klass)->display_reset_cb =
       gst_gl_transformation_reset_gl;
-  GST_GL_FILTER_CLASS (klass)->onReset = gst_gl_transformation_reset;
   GST_GL_FILTER_CLASS (klass)->set_caps = gst_gl_transformation_set_caps;
   GST_GL_FILTER_CLASS (klass)->filter_texture =
       gst_gl_transformation_filter_texture;
+  GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_transformation_stop;
 
   g_object_class_install_property (gobject_class, PROP_FOV,
       g_param_spec_float ("fov", "Fov", "Field of view angle in degrees",
@@ -404,18 +406,26 @@
     gl->DeleteBuffers (1, &transformation->vertex_buffer);
     transformation->vertex_buffer = 0;
   }
+
+  if (transformation->shader) {
+    gst_object_unref (transformation->shader);
+    transformation->shader = NULL;
+  }
 }
 
-static void
-gst_gl_transformation_reset (GstGLFilter * filter)
+static gboolean
+gst_gl_transformation_stop (GstBaseTransform * trans)
 {
-  GstGLTransformation *transformation = GST_GL_TRANSFORMATION (filter);
+  GstGLBaseFilter *basefilter = GST_GL_BASE_FILTER (trans);
+  GstGLTransformation *transformation = GST_GL_TRANSFORMATION (trans);
 
   /* blocking call, wait until the opengl thread has destroyed the shader */
-  if (transformation->shader)
-    gst_gl_context_del_shader (GST_GL_BASE_FILTER (filter)->context,
-        transformation->shader);
-  transformation->shader = NULL;
+  if (basefilter->context && transformation->shader) {
+    gst_gl_context_del_shader (basefilter->context, transformation->shader);
+    transformation->shader = NULL;
+  }
+
+  return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (trans);
 }
 
 static gboolean
@@ -423,6 +433,11 @@
 {
   GstGLTransformation *transformation = GST_GL_TRANSFORMATION (filter);
 
+  if (transformation->shader) {
+    gst_object_unref (transformation->shader);
+    transformation->shader = NULL;
+  }
+
   if (gst_gl_context_get_gl_api (GST_GL_BASE_FILTER (filter)->context)) {
     /* blocking call, wait until the opengl thread has compiled the shader */
     return gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context,
diff --git a/ext/gl/gstgluploadelement.c b/ext/gl/gstgluploadelement.c
index a8971d8..be01143 100644
--- a/ext/gl/gstgluploadelement.c
+++ b/ext/gl/gstgluploadelement.c
@@ -27,16 +27,6 @@
 #include <gst/gl/gl.h>
 #include "gstgluploadelement.h"
 
-#if GST_GL_HAVE_PLATFORM_EGL
-#include <gst/gl/egl/gsteglimagememory.h>
-#endif
-
-#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
-#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1))
-#define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0))
-#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
-#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
-
 GST_DEBUG_CATEGORY_STATIC (gst_gl_upload_element_debug);
 #define GST_CAT_DEFAULT gst_gl_upload_element_debug
 
@@ -46,7 +36,6 @@
     GST_DEBUG_CATEGORY_INIT (gst_gl_upload_element_debug, "gluploadelement", 0,
         "glupload Element");
     );
-static void gst_gl_upload_element_finalize (GObject * object);
 
 static gboolean gst_gl_upload_element_get_unit_size (GstBaseTransform * trans,
     GstCaps * caps, gsize * size);
@@ -65,6 +54,7 @@
     GstBuffer * buffer, GstBuffer ** outbuf);
 static GstFlowReturn gst_gl_upload_element_transform (GstBaseTransform * bt,
     GstBuffer * buffer, GstBuffer * outbuf);
+static gboolean gst_gl_upload_element_stop (GstBaseTransform * bt);
 
 static GstStaticPadTemplate gst_gl_upload_element_src_pad_template =
 GST_STATIC_PAD_TEMPLATE ("src",
@@ -72,17 +62,12 @@
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS ("video/x-raw(ANY)"));
 
-static GstStaticPadTemplate gst_gl_upload_element_sink_pad_template =
-GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-raw(ANY)"));
-
 static void
 gst_gl_upload_element_class_init (GstGLUploadElementClass * klass)
 {
   GstBaseTransformClass *bt_class = GST_BASE_TRANSFORM_CLASS (klass);
   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstCaps *upload_caps;
 
   bt_class->query = gst_gl_upload_element_query;
   bt_class->transform_caps = _gst_gl_upload_element_transform_caps;
@@ -92,19 +77,21 @@
   bt_class->get_unit_size = gst_gl_upload_element_get_unit_size;
   bt_class->prepare_output_buffer = gst_gl_upload_element_prepare_output_buffer;
   bt_class->transform = gst_gl_upload_element_transform;
+  bt_class->stop = gst_gl_upload_element_stop;
 
   bt_class->passthrough_on_same_caps = TRUE;
 
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&gst_gl_upload_element_src_pad_template));
+
+  upload_caps = gst_gl_upload_get_input_template_caps ();
   gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_gl_upload_element_sink_pad_template));
+      gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, upload_caps));
+  gst_caps_unref (upload_caps);
 
   gst_element_class_set_metadata (element_class,
       "OpenGL uploader", "Filter/Video",
       "Uploads data into OpenGL", "Matthew Waters <matthew@centricular.com>");
-
-  G_OBJECT_CLASS (klass)->finalize = gst_gl_upload_element_finalize;
 }
 
 static void
@@ -113,10 +100,10 @@
   gst_base_transform_set_prefer_passthrough (GST_BASE_TRANSFORM (upload), TRUE);
 }
 
-static void
-gst_gl_upload_element_finalize (GObject * object)
+static gboolean
+gst_gl_upload_element_stop (GstBaseTransform * bt)
 {
-  GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (object);
+  GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (bt);
 
   if (upload->upload) {
     gst_object_unref (upload->upload);
@@ -126,7 +113,7 @@
   gst_caps_replace (&upload->in_caps, NULL);
   gst_caps_replace (&upload->out_caps, NULL);
 
-  G_OBJECT_CLASS (gst_gl_upload_element_parent_class)->finalize (object);
+  return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (bt);
 }
 
 static gboolean
@@ -195,8 +182,10 @@
   gst_caps_replace (&upload->in_caps, in_caps);
   gst_caps_replace (&upload->out_caps, out_caps);
 
-  if (upload->upload)
+  if (upload->upload) {
+    gst_gl_upload_release_buffer (upload->upload);
     return gst_gl_upload_set_caps (upload->upload, in_caps, out_caps);
+  }
 
   return TRUE;
 }
diff --git a/ext/gl/gstglvideomixer.c b/ext/gl/gstglvideomixer.c
index c399e92..f7a3eb1 100644
--- a/ext/gl/gstglvideomixer.c
+++ b/ext/gl/gstglvideomixer.c
@@ -621,9 +621,49 @@
   }
 }
 
+static void
+_mixer_pad_get_output_size (GstGLVideoMixer * mix,
+    GstGLVideoMixerPad * mix_pad, gint * width, gint * height)
+{
+  GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (mix);
+  GstVideoAggregatorPad *vagg_pad = GST_VIDEO_AGGREGATOR_PAD (mix_pad);
+  gint pad_width, pad_height;
+  gint dar_n, dar_d;
+
+  pad_width =
+      mix_pad->width <=
+      0 ? GST_VIDEO_INFO_WIDTH (&vagg_pad->info) : mix_pad->width;
+  pad_height =
+      mix_pad->height <=
+      0 ? GST_VIDEO_INFO_HEIGHT (&vagg_pad->info) : mix_pad->height;
+
+  gst_util_fraction_multiply (GST_VIDEO_INFO_PAR_N (&vagg_pad->info),
+      GST_VIDEO_INFO_PAR_D (&vagg_pad->info),
+      GST_VIDEO_INFO_PAR_D (&vagg->info), GST_VIDEO_INFO_PAR_N (&vagg->info),
+      &dar_n, &dar_d);
+  GST_LOG_OBJECT (mix_pad, "scaling %ux%u by %u/%u (%u/%u / %u/%u)", pad_width,
+      pad_height, dar_n, dar_d, GST_VIDEO_INFO_PAR_N (&vagg_pad->info),
+      GST_VIDEO_INFO_PAR_D (&vagg_pad->info),
+      GST_VIDEO_INFO_PAR_N (&vagg->info), GST_VIDEO_INFO_PAR_D (&vagg->info));
+
+  if (pad_height % dar_n == 0) {
+    pad_height = gst_util_uint64_scale_int (pad_width, dar_n, dar_d);
+  } else if (pad_width % dar_d == 0) {
+    pad_width = gst_util_uint64_scale_int (pad_height, dar_d, dar_n);
+  } else {
+    pad_height = gst_util_uint64_scale_int (pad_width, dar_n, dar_d);
+  }
+
+  if (width)
+    *width = pad_width;
+  if (height)
+    *height = pad_height;
+}
+
 static GstCaps *
 _update_caps (GstVideoAggregator * vagg, GstCaps * caps)
 {
+  GstGLVideoMixer *mix = GST_GL_VIDEO_MIXER (vagg);
   GList *l;
   gint best_width = -1, best_height = -1;
   GstVideoInfo info;
@@ -640,15 +680,7 @@
     gint this_width, this_height;
     gint width, height;
 
-    if (mixer_pad->width > 0)
-      width = mixer_pad->width;
-    else
-      width = GST_VIDEO_INFO_WIDTH (&vaggpad->info);
-
-    if (mixer_pad->height > 0)
-      height = mixer_pad->height;
-    else
-      height = GST_VIDEO_INFO_HEIGHT (&vaggpad->info);
+    _mixer_pad_get_output_size (mix, mixer_pad, &width, &height);
 
     if (width == 0 || height == 0)
       continue;
@@ -709,21 +741,23 @@
 gst_gl_video_mixer_reset (GstGLMixer * mixer)
 {
   GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (mixer);
+  GstGLContext *context = GST_GL_BASE_MIXER (mixer)->context;
 
   video_mixer->input_frames = NULL;
 
+  GST_DEBUG_OBJECT (mixer, "context:%p", context);
+
   if (video_mixer->shader)
-    gst_gl_context_del_shader (GST_GL_BASE_MIXER (mixer)->context,
-        video_mixer->shader);
+    gst_gl_context_del_shader (context, video_mixer->shader);
   video_mixer->shader = NULL;
 
   if (video_mixer->checker)
-    gst_gl_context_del_shader (GST_GL_BASE_MIXER (mixer)->context,
-        video_mixer->checker);
+    gst_gl_context_del_shader (context, video_mixer->checker);
   video_mixer->checker = NULL;
 
-  gst_gl_context_thread_add (GST_GL_BASE_MIXER (mixer)->context,
-      (GstGLContextThreadFunc) _reset_gl, mixer);
+  if (GST_GL_BASE_MIXER (mixer)->context)
+    gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _reset_gl,
+        mixer);
 }
 
 static gboolean
@@ -842,6 +876,7 @@
 gst_gl_video_mixer_callback (gpointer stuff)
 {
   GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (stuff);
+  GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (stuff);
   GstGLMixer *mixer = GST_GL_MIXER (video_mixer);
   GstGLFuncs *gl = GST_GL_BASE_MIXER (mixer)->context->gl_vtable;
 
@@ -856,8 +891,8 @@
 
   guint count = 0;
 
-  out_width = GST_VIDEO_INFO_WIDTH (&GST_VIDEO_AGGREGATOR (stuff)->info);
-  out_height = GST_VIDEO_INFO_HEIGHT (&GST_VIDEO_AGGREGATOR (stuff)->info);
+  out_width = GST_VIDEO_INFO_WIDTH (&vagg->info);
+  out_height = GST_VIDEO_INFO_HEIGHT (&vagg->info);
 
   gst_gl_context_clear_shader (GST_GL_BASE_MIXER (mixer)->context);
   gl->BindTexture (GL_TEXTURE_2D, 0);
@@ -889,6 +924,7 @@
   while (count < video_mixer->input_frames->len) {
     GstGLMixerFrameData *frame;
     GstGLVideoMixerPad *pad;
+    GstVideoInfo *v_info;
     guint in_tex;
     guint in_width, in_height;
 
@@ -908,8 +944,9 @@
       continue;
     }
     pad = (GstGLVideoMixerPad *) frame->pad;
-    in_width = GST_VIDEO_INFO_WIDTH (&GST_VIDEO_AGGREGATOR_PAD (pad)->info);
-    in_height = GST_VIDEO_INFO_HEIGHT (&GST_VIDEO_AGGREGATOR_PAD (pad)->info);
+    v_info = &GST_VIDEO_AGGREGATOR_PAD (pad)->info;
+    in_width = GST_VIDEO_INFO_WIDTH (v_info);
+    in_height = GST_VIDEO_INFO_HEIGHT (v_info);
 
     if (!frame->texture || in_width <= 0 || in_height <= 0
         || pad->alpha == 0.0f) {
@@ -922,11 +959,10 @@
     in_tex = frame->texture;
 
     if (pad->geometry_change || !pad->vertex_buffer) {
-      guint pad_width, pad_height;
+      gint pad_width, pad_height;
       gfloat w, h;
 
-      pad_width = pad->width <= 0 ? in_width : pad->width;
-      pad_height = pad->height <= 0 ? in_height : pad->height;
+      _mixer_pad_get_output_size (video_mixer, pad, &pad_width, &pad_height);
 
       w = ((gfloat) pad_width / (gfloat) out_width);
       h = ((gfloat) pad_height / (gfloat) out_height);
@@ -952,6 +988,8 @@
 
       gl->BufferData (GL_ARRAY_BUFFER, 4 * 5 * sizeof (GLfloat), v_vertices,
           GL_STATIC_DRAW);
+
+      pad->geometry_change = FALSE;
     } else {
       gl->BindBuffer (GL_ARRAY_BUFFER, pad->vertex_buffer);
     }
diff --git a/ext/gl/gstopengl.c b/ext/gl/gstopengl.c
index 452efdd..308c65c 100644
--- a/ext/gl/gstopengl.c
+++ b/ext/gl/gstopengl.c
@@ -69,11 +69,8 @@
 
 #if GST_GL_HAVE_OPENGL
 #include "gstgltestsrc.h"
-#include "gstglfilterlaplacian.h"
 #include "gstglfilterglass.h"
-#include "gstglfilterblur.h"
 /* #include "gstglfilterreflectedscreen.h" */
-#include "gstglfiltersobel.h"
 #include "gstgldeinterlace.h"
 #include "gstglmosaic.h"
 #if HAVE_PNG
@@ -119,18 +116,23 @@
     return FALSE;
   }
 
+  if (!gst_element_register (plugin, "glimagesinkelement",
+          GST_RANK_NONE, gst_glimage_sink_get_type ())) {
+    return FALSE;
+  }
+
   if (!gst_element_register (plugin, "glupload",
-          GST_RANK_SECONDARY, GST_TYPE_GL_UPLOAD_ELEMENT)) {
+          GST_RANK_NONE, GST_TYPE_GL_UPLOAD_ELEMENT)) {
     return FALSE;
   }
 
   if (!gst_element_register (plugin, "gldownload",
-          GST_RANK_SECONDARY, GST_TYPE_GL_DOWNLOAD_ELEMENT)) {
+          GST_RANK_NONE, GST_TYPE_GL_DOWNLOAD_ELEMENT)) {
     return FALSE;
   }
 
   if (!gst_element_register (plugin, "glcolorconvert",
-          GST_RANK_SECONDARY, GST_TYPE_GL_COLOR_CONVERT_ELEMENT)) {
+          GST_RANK_NONE, GST_TYPE_GL_COLOR_CONVERT_ELEMENT)) {
     return FALSE;
   }
 
@@ -164,10 +166,10 @@
     return FALSE;
   }
 #endif
-  if (!gst_element_register (plugin, "gleffects",
-          GST_RANK_NONE, gst_gl_effects_get_type ())) {
+
+  if (!gst_gl_effects_register_filters (plugin, GST_RANK_NONE)) {
     return FALSE;
-  }
+  };
 
   if (!gst_element_register (plugin, "glcolorscale",
           GST_RANK_NONE, GST_TYPE_GL_COLORSCALE)) {
@@ -179,6 +181,11 @@
     return FALSE;
   }
 
+  if (!gst_element_register (plugin, "glvideomixerelement",
+          GST_RANK_NONE, gst_gl_video_mixer_get_type ())) {
+    return FALSE;
+  }
+
   if (!gst_element_register (plugin, "glshader",
           GST_RANK_NONE, gst_gl_filtershader_get_type ())) {
     return FALSE;
@@ -202,21 +209,6 @@
     return FALSE;
   }
 
-  if (!gst_element_register (plugin, "glfilterblur",
-          GST_RANK_NONE, gst_gl_filterblur_get_type ())) {
-    return FALSE;
-  }
-
-  if (!gst_element_register (plugin, "glfiltersobel",
-          GST_RANK_NONE, gst_gl_filtersobel_get_type ())) {
-    return FALSE;
-  }
-
-  if (!gst_element_register (plugin, "glfilterlaplacian",
-          GST_RANK_NONE, GST_TYPE_GL_FILTER_LAPLACIAN)) {
-    return FALSE;
-  }
-
   if (!gst_element_register (plugin, "glfilterglass",
           GST_RANK_NONE, GST_TYPE_GL_FILTER_GLASS)) {
     return FALSE;
diff --git a/ext/hls/Makefile.am b/ext/hls/Makefile.am
index 6ef163b..f66880f 100644
--- a/ext/hls/Makefile.am
+++ b/ext/hls/Makefile.am
@@ -24,17 +24,3 @@
 	gsthlssink.h			\
 	gstm3u8playlist.h		\
 	m3u8.h
-
-Android.mk: Makefile.am $(BUILT_SOURCES)
-	androgenizer \
-	-:PROJECT libgsthls -:SHARED libgsthls \
-	 -:TAGS eng debug \
-         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgsthls_la_SOURCES) \
-	 -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgsthls_la_CFLAGS) \
-	 -:LDFLAGS $(libgsthls_la_LDFLAGS) \
-	           $(libgsthls_la_LIBADD) \
-	           -ldl \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-		       LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
-	> $@
diff --git a/ext/hls/Makefile.in b/ext/hls/Makefile.in
index 140ce07..bb91c7a 100644
--- a/ext/hls/Makefile.in
+++ b/ext/hls/Makefile.in
@@ -1126,20 +1126,6 @@
 	uninstall-pluginLTLIBRARIES
 
 
-Android.mk: Makefile.am $(BUILT_SOURCES)
-	androgenizer \
-	-:PROJECT libgsthls -:SHARED libgsthls \
-	 -:TAGS eng debug \
-         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgsthls_la_SOURCES) \
-	 -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgsthls_la_CFLAGS) \
-	 -:LDFLAGS $(libgsthls_la_LDFLAGS) \
-	           $(libgsthls_la_LIBADD) \
-	           -ldl \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-		       LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
-	> $@
-
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
diff --git a/ext/hls/gsthlsdemux.c b/ext/hls/gsthlsdemux.c
index fad5a7b..5513815 100644
--- a/ext/hls/gsthlsdemux.c
+++ b/ext/hls/gsthlsdemux.c
@@ -100,8 +100,7 @@
     demux);
 static gboolean gst_hls_demux_process_manifest (GstAdaptiveDemux * demux,
     GstBuffer * buf);
-static GstFlowReturn gst_hls_demux_update_manifest (GstAdaptiveDemux * demux,
-    GstBuffer * buf);
+static GstFlowReturn gst_hls_demux_update_manifest (GstAdaptiveDemux * demux);
 static gboolean gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek);
 static gboolean
 gst_hls_demux_start_fragment (GstAdaptiveDemux * demux,
@@ -130,11 +129,6 @@
 {
   GstHLSDemux *demux = GST_HLS_DEMUX (obj);
 
-  if (demux->downloader != NULL) {
-    g_object_unref (demux->downloader);
-    demux->downloader = NULL;
-  }
-
   gst_hls_demux_reset (GST_ADAPTIVE_DEMUX_CAST (demux));
   gst_m3u8_client_free (demux->client);
 
@@ -207,11 +201,7 @@
 static void
 gst_hls_demux_init (GstHLSDemux * demux)
 {
-  /* Downloader */
-  demux->downloader = gst_uri_downloader_new ();
-
   demux->do_typefind = TRUE;
-
 }
 
 static void
@@ -250,7 +240,6 @@
   switch (transition) {
     case GST_STATE_CHANGE_READY_TO_PAUSED:
       gst_hls_demux_reset (GST_ADAPTIVE_DEMUX_CAST (demux));
-      gst_uri_downloader_reset (demux->downloader);
       break;
     default:
       break;
@@ -307,7 +296,7 @@
   GstSeekType start_type, stop_type;
   gint64 start, stop;
   gdouble rate;
-  GList *walk;
+  GList *walk, *current_file = NULL;
   GstClockTime current_pos, target_pos;
   gint64 current_sequence;
   GstM3U8MediaFile *file;
@@ -335,7 +324,7 @@
     GST_M3U8_CLIENT_UNLOCK (hlsdemux->client);
     gst_m3u8_client_set_current (hlsdemux->client,
         hlsdemux->client->main->iframe_lists->data);
-    gst_uri_downloader_reset (hlsdemux->downloader);
+    gst_uri_downloader_reset (demux->downloader);
     if (!gst_hls_demux_update_playlist (hlsdemux, FALSE, &err)) {
       GST_ELEMENT_ERROR_FROM_ERROR (hlsdemux, "Could not switch playlist", err);
       return FALSE;
@@ -354,7 +343,7 @@
     GST_M3U8_CLIENT_UNLOCK (hlsdemux->client);
     gst_m3u8_client_set_current (hlsdemux->client,
         hlsdemux->client->main->lists->data);
-    gst_uri_downloader_reset (hlsdemux->downloader);
+    gst_uri_downloader_reset (demux->downloader);
     if (!gst_hls_demux_update_playlist (hlsdemux, FALSE, &err)) {
       GST_ELEMENT_ERROR_FROM_ERROR (hlsdemux, "Could not switch playlist", err);
       return FALSE;
@@ -376,22 +365,23 @@
     file = walk->data;
 
     current_sequence = file->sequence;
+    current_file = walk;
     if (current_pos <= target_pos && target_pos < current_pos + file->duration) {
       break;
     }
     current_pos += file->duration;
   }
-  GST_M3U8_CLIENT_UNLOCK (hlsdemux->client);
 
   if (walk == NULL) {
     GST_DEBUG_OBJECT (demux, "seeking further than track duration");
     current_sequence++;
   }
 
-  GST_M3U8_CLIENT_LOCK (hlsdemux->client);
   GST_DEBUG_OBJECT (demux, "seeking to sequence %u", (guint) current_sequence);
   hlsdemux->reset_pts = TRUE;
   hlsdemux->client->sequence = current_sequence;
+  hlsdemux->client->current_file =
+      current_file ? current_file : hlsdemux->client->current->files;
   hlsdemux->client->sequence_position = current_pos;
   GST_M3U8_CLIENT_UNLOCK (hlsdemux->client);
 
@@ -399,7 +389,7 @@
 }
 
 static GstFlowReturn
-gst_hls_demux_update_manifest (GstAdaptiveDemux * demux, GstBuffer * buf)
+gst_hls_demux_update_manifest (GstAdaptiveDemux * demux)
 {
   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
   if (!gst_hls_demux_update_playlist (hlsdemux, TRUE, NULL))
@@ -514,7 +504,7 @@
 
       GST_INFO_OBJECT (demux, "Fetching key %s", hlsdemux->current_key);
       key_fragment =
-          gst_uri_downloader_fetch_uri (hlsdemux->downloader,
+          gst_uri_downloader_fetch_uri (demux->downloader,
           hlsdemux->current_key, hlsdemux->client->main ?
           hlsdemux->client->main->uri : NULL, FALSE, FALSE,
           hlsdemux->client->current ? hlsdemux->client->current->
@@ -544,10 +534,71 @@
 }
 
 static GstFlowReturn
+gst_hls_demux_handle_buffer (GstAdaptiveDemux * demux,
+    GstAdaptiveDemuxStream * stream, GstBuffer * buffer, gboolean force)
+{
+  GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
+
+  if (G_UNLIKELY (hlsdemux->do_typefind && buffer != NULL)) {
+    GstCaps *caps = NULL;
+    GstMapInfo info;
+    guint buffer_size;
+    GstTypeFindProbability prob = GST_TYPE_FIND_NONE;
+
+    gst_buffer_map (buffer, &info, GST_MAP_READ);
+    buffer_size = info.size;
+
+    /* Typefind could miss if buffer is too small. In this case we
+     * will retry later */
+    if (buffer_size >= (2 * 1024)) {
+      caps =
+          gst_type_find_helper_for_data (GST_OBJECT_CAST (hlsdemux), info.data,
+          info.size, &prob);
+    }
+    gst_buffer_unmap (buffer, &info);
+
+    if (G_UNLIKELY (!caps)) {
+      /* Only fail typefinding if we already a good amount of data
+       * and we still don't know the type */
+      if (buffer_size > (2 * 1024 * 1024) || force) {
+        GST_ELEMENT_ERROR (hlsdemux, STREAM, TYPE_NOT_FOUND,
+            ("Could not determine type of stream"), (NULL));
+        gst_buffer_unref (buffer);
+        return GST_FLOW_NOT_NEGOTIATED;
+      } else {
+        if (hlsdemux->pending_buffer)
+          hlsdemux->pending_buffer =
+              gst_buffer_append (buffer, hlsdemux->pending_buffer);
+        else
+          hlsdemux->pending_buffer = buffer;
+        return GST_FLOW_OK;
+      }
+    }
+
+    GST_DEBUG_OBJECT (hlsdemux, "Typefind result: %" GST_PTR_FORMAT " prob:%d",
+        caps, prob);
+
+    if (!hlsdemux->input_caps
+        || !gst_caps_is_equal (caps, hlsdemux->input_caps)) {
+      gst_caps_replace (&hlsdemux->input_caps, caps);
+      GST_INFO_OBJECT (demux, "Input source caps: %" GST_PTR_FORMAT,
+          hlsdemux->input_caps);
+    }
+    gst_adaptive_demux_stream_set_caps (stream, caps);
+    hlsdemux->do_typefind = FALSE;
+  }
+
+  if (buffer)
+    return gst_adaptive_demux_stream_push_buffer (stream, buffer);
+  return GST_FLOW_OK;
+}
+
+static GstFlowReturn
 gst_hls_demux_finish_fragment (GstAdaptiveDemux * demux,
     GstAdaptiveDemuxStream * stream)
 {
   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
+  GstFlowReturn ret = GST_FLOW_OK;
 
   if (hlsdemux->current_key)
     gst_hls_demux_decrypt_end (hlsdemux);
@@ -558,20 +609,24 @@
       ": %" G_GSIZE_FORMAT, gst_adapter_available (stream->adapter));
   gst_adapter_clear (stream->adapter);
 
-  /* pending buffer is only used for encrypted streams */
   if (stream->last_ret == GST_FLOW_OK) {
     if (hlsdemux->pending_buffer) {
-      GstMapInfo info;
-      gsize unpadded_size;
+      if (hlsdemux->current_key) {
+        GstMapInfo info;
+        gssize unpadded_size;
 
-      /* Handle pkcs7 unpadding here */
-      gst_buffer_map (hlsdemux->pending_buffer, &info, GST_MAP_READ);
-      unpadded_size = info.size - info.data[info.size - 1];
-      gst_buffer_unmap (hlsdemux->pending_buffer, &info);
+        /* Handle pkcs7 unpadding here */
+        gst_buffer_map (hlsdemux->pending_buffer, &info, GST_MAP_READ);
+        unpadded_size = info.size - info.data[info.size - 1];
+        gst_buffer_unmap (hlsdemux->pending_buffer, &info);
 
-      gst_buffer_resize (hlsdemux->pending_buffer, 0, unpadded_size);
+        gst_buffer_resize (hlsdemux->pending_buffer, 0, unpadded_size);
+      }
 
-      gst_adaptive_demux_stream_push_buffer (stream, hlsdemux->pending_buffer);
+      ret =
+          gst_hls_demux_handle_buffer (demux, stream, hlsdemux->pending_buffer,
+          TRUE);
+      hlsdemux->pending_buffer = NULL;
     }
   } else {
     if (hlsdemux->pending_buffer)
@@ -579,8 +634,10 @@
     hlsdemux->pending_buffer = NULL;
   }
 
-  return gst_adaptive_demux_stream_advance_fragment (demux, stream,
-      stream->fragment.duration);
+  if (ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED)
+    return gst_adaptive_demux_stream_advance_fragment (demux, stream,
+        stream->fragment.duration);
+  return ret;
 }
 
 static GstFlowReturn
@@ -625,59 +682,7 @@
     }
   }
 
-  if (G_UNLIKELY (hlsdemux->do_typefind && buffer != NULL)) {
-    GstCaps *caps = NULL;
-    GstMapInfo info;
-    guint buffer_size;
-    GstTypeFindProbability prob = GST_TYPE_FIND_NONE;
-
-    gst_buffer_map (buffer, &info, GST_MAP_READ);
-    buffer_size = info.size;
-
-    /* Typefind could miss if buffer is too small. In this case we
-     * will retry later */
-    if (buffer_size >= (2 * 1024)) {
-      caps =
-          gst_type_find_helper_for_data (GST_OBJECT_CAST (hlsdemux), info.data,
-          info.size, &prob);
-    }
-    gst_buffer_unmap (buffer, &info);
-
-    if (G_UNLIKELY (!caps)) {
-      /* Only fail typefinding if we already a good amount of data
-       * and we still don't know the type */
-      if (buffer_size > (2 * 1024 * 1024)) {
-        GST_ELEMENT_ERROR (hlsdemux, STREAM, TYPE_NOT_FOUND,
-            ("Could not determine type of stream"), (NULL));
-        gst_buffer_unref (buffer);
-        return GST_FLOW_NOT_NEGOTIATED;
-      } else {
-        if (hlsdemux->pending_buffer)
-          hlsdemux->pending_buffer =
-              gst_buffer_append (buffer, hlsdemux->pending_buffer);
-        else
-          hlsdemux->pending_buffer = buffer;
-        return GST_FLOW_OK;
-      }
-    }
-
-    GST_DEBUG_OBJECT (hlsdemux, "Typefind result: %" GST_PTR_FORMAT " prob:%d",
-        caps, prob);
-
-    if (!hlsdemux->input_caps
-        || !gst_caps_is_equal (caps, hlsdemux->input_caps)) {
-      gst_caps_replace (&hlsdemux->input_caps, caps);
-      GST_INFO_OBJECT (demux, "Input source caps: %" GST_PTR_FORMAT,
-          hlsdemux->input_caps);
-    }
-    gst_adaptive_demux_stream_set_caps (stream, caps);
-    hlsdemux->do_typefind = FALSE;
-  }
-
-  if (buffer) {
-    return gst_adaptive_demux_stream_push_buffer (stream, buffer);
-  }
-  return GST_FLOW_OK;
+  return gst_hls_demux_handle_buffer (demux, stream, buffer, FALSE);
 }
 
 static gboolean
@@ -852,6 +857,7 @@
 gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update,
     GError ** err)
 {
+  GstAdaptiveDemux *adaptive_demux = GST_ADAPTIVE_DEMUX (demux);
   GstFragment *download;
   GstBuffer *buf;
   gchar *playlist;
@@ -862,7 +868,7 @@
   uri = gst_m3u8_client_get_current_uri (demux->client);
   main_uri = gst_m3u8_client_get_uri (demux->client);
   download =
-      gst_uri_downloader_fetch_uri (demux->downloader, uri, main_uri,
+      gst_uri_downloader_fetch_uri (adaptive_demux->downloader, uri, main_uri,
       TRUE, TRUE, TRUE, err);
   g_free (main_uri);
   if (download == NULL) {
@@ -875,7 +881,7 @@
           "Updating playlist %s failed, attempt to refresh variant playlist %s",
           uri, main_uri);
       download =
-          gst_uri_downloader_fetch_uri (demux->downloader,
+          gst_uri_downloader_fetch_uri (adaptive_demux->downloader,
           main_uri, NULL, TRUE, TRUE, TRUE, &err2);
       g_free (main_uri);
       g_clear_error (&err2);
diff --git a/ext/hls/gsthlsdemux.h b/ext/hls/gsthlsdemux.h
index 77f7414..7acfead 100644
--- a/ext/hls/gsthlsdemux.h
+++ b/ext/hls/gsthlsdemux.h
@@ -27,7 +27,6 @@
 #include <gst/gst.h>
 #include "m3u8.h"
 #include "gstfragmented.h"
-#include <gst/uridownloader/gsturidownloader.h>
 #include <gst/adaptivedemux/gstadaptivedemux.h>
 #if defined(HAVE_OPENSSL)
 #include <openssl/evp.h>
@@ -68,7 +67,6 @@
   gint srcpad_counter;
 
   GstCaps *input_caps;
-  GstUriDownloader *downloader;
   gchar *uri;                   /* Original playlist URI */
   GstM3U8Client *client;        /* M3U8 client */
   gboolean do_typefind;         /* Whether we need to typefind the next buffer */
diff --git a/ext/hls/gsthlssink.c b/ext/hls/gsthlssink.c
index ea337ea..de5e84c 100644
--- a/ext/hls/gsthlssink.c
+++ b/ext/hls/gsthlssink.c
@@ -85,6 +85,8 @@
 static GstStateChangeReturn
 gst_hls_sink_change_state (GstElement * element, GstStateChange trans);
 static gboolean schedule_next_key_unit (GstHlsSink * sink);
+static GstFlowReturn gst_hls_sink_chain_list (GstPad * pad, GstObject * parent,
+    GstBufferList * list);
 
 static void
 gst_hls_sink_dispose (GObject * object)
@@ -180,6 +182,7 @@
       gst_hls_sink_ghost_event_probe, sink, NULL);
   gst_pad_add_probe (sink->ghostpad, GST_PAD_PROBE_TYPE_BUFFER,
       gst_hls_sink_ghost_buffer_probe, sink, NULL);
+  gst_pad_set_chain_list_function (sink->ghostpad, gst_hls_sink_chain_list);
 
   sink->location = g_strdup (DEFAULT_LOCATION);
   sink->playlist_location = g_strdup (DEFAULT_PLAYLIST_LOCATION);
@@ -250,6 +253,25 @@
 }
 
 static void
+gst_hls_sink_write_playlist (GstHlsSink * sink)
+{
+  char *playlist_content;
+  GError *error = NULL;
+
+  playlist_content = gst_m3u8_playlist_render (sink->playlist);
+  if (!g_file_set_contents (sink->playlist_location,
+          playlist_content, -1, &error)) {
+    GST_ERROR ("Failed to write playlist: %s", error->message);
+    GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE,
+        (("Failed to write playlist '%s'."), error->message), (NULL));
+    g_error_free (error);
+    error = NULL;
+  }
+  g_free (playlist_content);
+
+}
+
+static void
 gst_hls_sink_handle_message (GstBin * bin, GstMessage * message)
 {
   GstHlsSink *sink = GST_HLS_SINK_CAST (bin);
@@ -258,10 +280,8 @@
     case GST_MESSAGE_ELEMENT:
     {
       const char *filename;
-      char *playlist_content;
       GstClockTime running_time, duration;
       gboolean discont = FALSE;
-      GError *error = NULL;
       gchar *entry_location;
       const GstStructure *structure;
 
@@ -286,16 +306,8 @@
       gst_m3u8_playlist_add_entry (sink->playlist, entry_location,
           NULL, duration, sink->index, discont);
       g_free (entry_location);
-      playlist_content = gst_m3u8_playlist_render (sink->playlist);
-      if (!g_file_set_contents (sink->playlist_location,
-              playlist_content, -1, &error)) {
-        GST_ERROR ("Failed to write playlist: %s", error->message);
-        GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE,
-            (("Failed to write playlist '%s'."), error->message), (NULL));
-        g_error_free (error);
-        error = NULL;
-      }
-      g_free (playlist_content);
+
+      gst_hls_sink_write_playlist (sink);
 
       /* multifilesink is starting a new file. It means that upstream sent a key
        * unit and we can schedule the next key unit now.
@@ -310,6 +322,11 @@
       message = NULL;
       break;
     }
+    case GST_MESSAGE_EOS:{
+      sink->playlist->end_list = TRUE;
+      gst_hls_sink_write_playlist (sink);
+      break;
+    }
     default:
       break;
   }
@@ -499,6 +516,19 @@
   return res;
 }
 
+static void
+gst_hls_sink_check_schedule_next_key_unit (GstHlsSink * sink, GstBuffer * buf)
+{
+  GstClockTime timestamp;
+
+  timestamp = GST_BUFFER_TIMESTAMP (buf);
+  if (!GST_CLOCK_TIME_IS_VALID (timestamp))
+    return;
+
+  sink->last_running_time = gst_segment_to_running_time (&sink->segment,
+      GST_FORMAT_TIME, timestamp);
+  schedule_next_key_unit (sink);
+}
 
 static GstPadProbeReturn
 gst_hls_sink_ghost_buffer_probe (GstPad * pad, GstPadProbeInfo * info,
@@ -506,19 +536,45 @@
 {
   GstHlsSink *sink = GST_HLS_SINK_CAST (data);
   GstBuffer *buffer = gst_pad_probe_info_get_buffer (info);
-  GstClockTime timestamp;
 
-  timestamp = GST_BUFFER_TIMESTAMP (buffer);
-  if (sink->target_duration == 0 || !GST_CLOCK_TIME_IS_VALID (timestamp)
-      || sink->waiting_fku)
+  if (sink->target_duration == 0 || sink->waiting_fku)
     return GST_PAD_PROBE_OK;
 
-  sink->last_running_time = gst_segment_to_running_time (&sink->segment,
-      GST_FORMAT_TIME, timestamp);
-  schedule_next_key_unit (sink);
+  gst_hls_sink_check_schedule_next_key_unit (sink, buffer);
   return GST_PAD_PROBE_OK;
 }
 
+static GstFlowReturn
+gst_hls_sink_chain_list (GstPad * pad, GstObject * parent, GstBufferList * list)
+{
+  guint i, len;
+  GstBuffer *buffer;
+  GstFlowReturn ret;
+  GstHlsSink *sink = GST_HLS_SINK_CAST (parent);
+
+  if (sink->target_duration == 0 || sink->waiting_fku)
+    return gst_proxy_pad_chain_list_default (pad, parent, list);
+
+  GST_DEBUG_OBJECT (pad, "chaining each group in list as a merged buffer");
+
+  len = gst_buffer_list_length (list);
+
+  ret = GST_FLOW_OK;
+  for (i = 0; i < len; i++) {
+    buffer = gst_buffer_list_get (list, i);
+
+    if (!sink->waiting_fku)
+      gst_hls_sink_check_schedule_next_key_unit (sink, buffer);
+
+    ret = gst_pad_chain (pad, gst_buffer_ref (buffer));
+    if (ret != GST_FLOW_OK)
+      break;
+  }
+  gst_buffer_list_unref (list);
+
+  return ret;
+}
+
 gboolean
 gst_hls_sink_plugin_init (GstPlugin * plugin)
 {
diff --git a/ext/hls/m3u8.c b/ext/hls/m3u8.c
index 9645256..0d1f892 100755
--- a/ext/hls/m3u8.c
+++ b/ext/hls/m3u8.c
@@ -925,15 +925,16 @@
     }
 
     if (unmatched_lists != NULL) {
-      g_list_free (unmatched_lists);
+      GST_WARNING ("Unable to match all playlists");
 
-      /* We should attempt to handle the case where playlists are dropped/replaced,
-       * and possibly switch over to a comparable (not neccessarily identical)
-       * playlist.
-       */
-      GST_FIXME
-          ("Cannot update variant playlist, unable to match all playlists");
-      goto out;
+      for (list_entry = unmatched_lists; list_entry;
+          list_entry = list_entry->next) {
+        if (list_entry->data == self->current) {
+          GST_WARNING ("Unable to match current playlist");
+        }
+      }
+
+      g_list_free (unmatched_lists);
     }
 
     /* Switch out the variant playlist */
diff --git a/ext/libde265/libde265-dec.c b/ext/libde265/libde265-dec.c
index 0c530ae..a57bd5b 100644
--- a/ext/libde265/libde265-dec.c
+++ b/ext/libde265/libde265-dec.c
@@ -36,14 +36,62 @@
 #include "config.h"
 #endif
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+
+#include "libde265-dec.h"
+
+#if !GLIB_CHECK_VERSION(2, 36, 0)
+#include <stdio.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
+#ifdef G_OS_WIN32
+#include <windows.h>
+#endif
+#define g_get_num_processors gst_g_get_num_processors
+static guint
+gst_g_get_num_processors (void)
+{
+  guint threads = 0;
 
-#include "libde265-dec.h"
+#if defined(_SC_NPROC_ONLN)
+  threads = sysconf (_SC_NPROC_ONLN);
+#elif defined(_SC_NPROCESSORS_ONLN)
+  threads = sysconf (_SC_NPROCESSORS_ONLN);
+#elif defined(G_OS_WIN32)
+  {
+    SYSTEM_INFO sysinfo;
+    DWORD_PTR process_cpus;
+    DWORD_PTR system_cpus;
+
+    /* This *never* fails, but doesn't take CPU affinity into account */
+    GetSystemInfo (&sysinfo);
+    threads = (int) sysinfo.dwNumberOfProcessors;
+
+    /* This *can* fail, but produces correct results if affinity mask is used,
+     * unlike the simpler code above.
+     */
+    if (GetProcessAffinityMask (GetCurrentProcess (),
+            &process_cpus, &system_cpus)) {
+      unsigned int count;
+
+      for (count = 0; process_cpus != 0; process_cpus >>= 1)
+        if (process_cpus & 1)
+          count++;
+    }
+  }
+#else
+#warning "Don't know how to get number of CPU cores, will use the default thread count"
+  threads = DEFAULT_THREAD_COUNT;
+#endif
+
+  if (threads > 0)
+    return threads;
+
+  return 1;
+}
+#endif /* !GLIB_CHECK_VERSION(2, 36, 0) */
 
 /* use two decoder threads if no information about
  * available CPU cores can be retrieved */
@@ -374,17 +422,8 @@
     return FALSE;
   }
   if (threads == 0) {
-#if defined(_SC_NPROC_ONLN)
-    threads = sysconf (_SC_NPROC_ONLN);
-#elif defined(_SC_NPROCESSORS_ONLN)
-    threads = sysconf (_SC_NPROCESSORS_ONLN);
-#else
-#warning "Don't know how to get number of CPU cores, will use the default thread count"
-    threads = DEFAULT_THREAD_COUNT;
-#endif
-    if (threads <= 0) {
-      threads = DEFAULT_THREAD_COUNT;
-    }
+    threads = g_get_num_processors ();
+
     /* NOTE: We start more threads than cores for now, as some threads
      * might get blocked while waiting for dependent data. Having more
      * threads increases decoding speed by about 10% */
@@ -601,8 +640,8 @@
             int nal_count;
             if (pos + 3 > size) {
               GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
-                  ("Buffer underrun in extra header (%d >= %ld)", pos + 3,
-                      size), (NULL));
+                  ("Buffer underrun in extra header (%d >= %" G_GSIZE_FORMAT
+                      ")", pos + 3, size), (NULL));
               return FALSE;
             }
             /* ignore flags + NAL type (1 byte) */
@@ -612,14 +651,14 @@
               int nal_size;
               if (pos + 2 > size) {
                 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
-                    ("Buffer underrun in extra nal header (%d >= %ld)", pos + 2,
-                        size), (NULL));
+                    ("Buffer underrun in extra nal header (%d >= %"
+                        G_GSIZE_FORMAT ")", pos + 2, size), (NULL));
                 return FALSE;
               }
               nal_size = data[pos] << 8 | data[pos + 1];
               if (pos + 2 + nal_size > size) {
                 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
-                    ("Buffer underrun in extra nal (%d >= %ld)",
+                    ("Buffer underrun in extra nal (%d >= %" G_GSIZE_FORMAT ")",
                         pos + 2 + nal_size, size), (NULL));
                 return FALSE;
               }
diff --git a/ext/mpg123/Makefile.am b/ext/mpg123/Makefile.am
index 3acdfa4..6c96207 100644
--- a/ext/mpg123/Makefile.am
+++ b/ext/mpg123/Makefile.am
@@ -10,18 +10,3 @@
 libgstmpg123_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
 
 noinst_HEADERS = gstmpg123audiodec.h
-
-Android.mk: Makefile.am $(BUILT_SOURCES)
-	androgenizer \
-	-:PROJECT libgstmpg123 -:SHARED libgstmpg123 \
-	 -:TAGS eng debug \
-         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgstmpg123_la_SOURCES) \
-	 -:CPPFLAGS $(CPPFLAGS) \
-	 -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstmpg123_la_CFLAGS) \
-	 -:LDFLAGS $(libgstmpg123_la_LDFLAGS) \
-	           $(libgstmpg123_la_LIBADD) \
-	           -ldl \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-		       LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-@GST_API_VERSION@' \
-	> $@
diff --git a/ext/mpg123/Makefile.in b/ext/mpg123/Makefile.in
index 8f13897..7d53fb9 100644
--- a/ext/mpg123/Makefile.in
+++ b/ext/mpg123/Makefile.in
@@ -1073,21 +1073,6 @@
 	uninstall-pluginLTLIBRARIES
 
 
-Android.mk: Makefile.am $(BUILT_SOURCES)
-	androgenizer \
-	-:PROJECT libgstmpg123 -:SHARED libgstmpg123 \
-	 -:TAGS eng debug \
-         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgstmpg123_la_SOURCES) \
-	 -:CPPFLAGS $(CPPFLAGS) \
-	 -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstmpg123_la_CFLAGS) \
-	 -:LDFLAGS $(libgstmpg123_la_LDFLAGS) \
-	           $(libgstmpg123_la_LIBADD) \
-	           -ldl \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-		       LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-@GST_API_VERSION@' \
-	> $@
-
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
diff --git a/ext/opencv/MotionCells.cpp b/ext/opencv/MotionCells.cpp
index 449fe24..eaa013f 100644
--- a/ext/opencv/MotionCells.cpp
+++ b/ext/opencv/MotionCells.cpp
@@ -54,6 +54,7 @@
 #include <math.h>
 #include <gst/gst.h>
 #include "MotionCells.h"
+#include <opencv2/imgproc/imgproc_c.h>
 
 MotionCells::MotionCells ()
 {
diff --git a/ext/opencv/MotionCells.h b/ext/opencv/MotionCells.h
index 5c6d131..41bb9c7 100644
--- a/ext/opencv/MotionCells.h
+++ b/ext/opencv/MotionCells.h
@@ -45,7 +45,7 @@
 #ifndef MOTIONCELLS_H_
 #define MOTIONCELLS_H_
 
-#include <cv.h>                 // includes OpenCV definitions
+#include <opencv2/core/core_c.h>
 #ifdef HAVE_HIGHGUI_H
 #include <highgui.h>            // includes highGUI definitions
 #endif
diff --git a/ext/opencv/gstcvdilate.c b/ext/opencv/gstcvdilate.c
index 3b55f45..da0713d 100644
--- a/ext/opencv/gstcvdilate.c
+++ b/ext/opencv/gstcvdilate.c
@@ -48,6 +48,7 @@
 #include <gst/gst.h>
 
 #include "gstcvdilate.h"
+#include <opencv2/imgproc/imgproc_c.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_cv_dilate_debug);
 #define GST_CAT_DEFAULT gst_cv_dilate_debug
diff --git a/ext/opencv/gstcvdilate.h b/ext/opencv/gstcvdilate.h
index 21c3fbf..fdacdd8 100644
--- a/ext/opencv/gstcvdilate.h
+++ b/ext/opencv/gstcvdilate.h
@@ -45,7 +45,7 @@
 #define __GST_CV_DILATE_H__
 
 #include <gst/gst.h>
-#include <cv.h>
+
 #include "gstcvdilateerode.h"
 
 G_BEGIN_DECLS
diff --git a/ext/opencv/gstcvdilateerode.h b/ext/opencv/gstcvdilateerode.h
index 20b55a6..94425f5 100644
--- a/ext/opencv/gstcvdilateerode.h
+++ b/ext/opencv/gstcvdilateerode.h
@@ -45,7 +45,7 @@
 #define __GST_CV_DILATE_ERODE_H__
 
 #include <gst/gst.h>
-#include <cv.h>
+
 #include <gstopencvvideofilter.h>
 
 G_BEGIN_DECLS
diff --git a/ext/opencv/gstcvequalizehist.c b/ext/opencv/gstcvequalizehist.c
index 5c6526a..7384df1 100644
--- a/ext/opencv/gstcvequalizehist.c
+++ b/ext/opencv/gstcvequalizehist.c
@@ -49,6 +49,7 @@
 
 #include "gstopencvutils.h"
 #include "gstcvequalizehist.h"
+#include <opencv2/imgproc/imgproc_c.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_cv_equalize_hist_debug);
 #define GST_CAT_DEFAULT gst_cv_equalize_hist_debug
diff --git a/ext/opencv/gstcvequalizehist.h b/ext/opencv/gstcvequalizehist.h
index 0be379d..d1d600d 100644
--- a/ext/opencv/gstcvequalizehist.h
+++ b/ext/opencv/gstcvequalizehist.h
@@ -45,7 +45,7 @@
 #define __GST_CV_EQUALIZE_HIST_H__
 
 #include <gst/gst.h>
-#include <cv.h>
+
 #include <gstopencvvideofilter.h>
 
 G_BEGIN_DECLS
diff --git a/ext/opencv/gstcverode.c b/ext/opencv/gstcverode.c
index a869a84..4c62624 100644
--- a/ext/opencv/gstcverode.c
+++ b/ext/opencv/gstcverode.c
@@ -48,6 +48,7 @@
 #include <gst/gst.h>
 
 #include "gstcverode.h"
+#include <opencv2/imgproc/imgproc_c.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_cv_erode_debug);
 #define GST_CAT_DEFAULT gst_cv_erode_debug
diff --git a/ext/opencv/gstcverode.h b/ext/opencv/gstcverode.h
index bc474f3..3f2944a 100644
--- a/ext/opencv/gstcverode.h
+++ b/ext/opencv/gstcverode.h
@@ -45,7 +45,7 @@
 #define __GST_CV_ERODE_H__
 
 #include <gst/gst.h>
-#include <cv.h>
+
 #include "gstcvdilateerode.h"
 
 G_BEGIN_DECLS
diff --git a/ext/opencv/gstcvlaplace.c b/ext/opencv/gstcvlaplace.c
index bd71ae6..5b95618 100644
--- a/ext/opencv/gstcvlaplace.c
+++ b/ext/opencv/gstcvlaplace.c
@@ -49,6 +49,7 @@
 
 #include "gstopencvutils.h"
 #include "gstcvlaplace.h"
+#include <opencv2/imgproc/imgproc_c.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_cv_laplace_debug);
 #define GST_CAT_DEFAULT gst_cv_laplace_debug
diff --git a/ext/opencv/gstcvlaplace.h b/ext/opencv/gstcvlaplace.h
index 93201e4..098b347 100644
--- a/ext/opencv/gstcvlaplace.h
+++ b/ext/opencv/gstcvlaplace.h
@@ -45,7 +45,7 @@
 #define __GST_CV_LAPLACE_H__
 
 #include <gst/gst.h>
-#include <cv.h>
+
 #include <gstopencvvideofilter.h>
 
 G_BEGIN_DECLS
diff --git a/ext/opencv/gstcvsmooth.c b/ext/opencv/gstcvsmooth.c
index ec36173..67f403e 100644
--- a/ext/opencv/gstcvsmooth.c
+++ b/ext/opencv/gstcvsmooth.c
@@ -49,6 +49,7 @@
 
 #include "gstopencvutils.h"
 #include "gstcvsmooth.h"
+#include <opencv2/imgproc/imgproc_c.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_cv_smooth_debug);
 #define GST_CAT_DEFAULT gst_cv_smooth_debug
diff --git a/ext/opencv/gstcvsmooth.h b/ext/opencv/gstcvsmooth.h
index 16521d9..9a62e91 100644
--- a/ext/opencv/gstcvsmooth.h
+++ b/ext/opencv/gstcvsmooth.h
@@ -45,7 +45,7 @@
 #define __GST_CV_SMOOTH_H__
 
 #include <gst/gst.h>
-#include <cv.h>
+
 #include <gstopencvvideofilter.h>
 
 G_BEGIN_DECLS
diff --git a/ext/opencv/gstcvsobel.c b/ext/opencv/gstcvsobel.c
index cd21189..1d9b151 100644
--- a/ext/opencv/gstcvsobel.c
+++ b/ext/opencv/gstcvsobel.c
@@ -49,6 +49,7 @@
 
 #include "gstopencvutils.h"
 #include "gstcvsobel.h"
+#include <opencv2/imgproc/imgproc_c.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_cv_sobel_debug);
 #define GST_CAT_DEFAULT gst_cv_sobel_debug
diff --git a/ext/opencv/gstcvsobel.h b/ext/opencv/gstcvsobel.h
index 55885d3..c6719a0 100644
--- a/ext/opencv/gstcvsobel.h
+++ b/ext/opencv/gstcvsobel.h
@@ -45,7 +45,7 @@
 #define __GST_CV_SOBEL_H__
 
 #include <gst/gst.h>
-#include <cv.h>
+
 #include <gstopencvvideofilter.h>
 
 G_BEGIN_DECLS
diff --git a/ext/opencv/gstdisparity.h b/ext/opencv/gstdisparity.h
index a1e0bdc..adbb9ae 100644
--- a/ext/opencv/gstdisparity.h
+++ b/ext/opencv/gstdisparity.h
@@ -45,7 +45,7 @@
 #define __GST_DISPARITY_H__
 
 #include <gst/gst.h>
-#include <cv.h>
+
 #include <opencv2/legacy/legacy.hpp>
 
 G_BEGIN_DECLS
diff --git a/ext/opencv/gstedgedetect.c b/ext/opencv/gstedgedetect.c
index bb85de4..14781bd 100644
--- a/ext/opencv/gstedgedetect.c
+++ b/ext/opencv/gstedgedetect.c
@@ -64,6 +64,7 @@
 
 #include "gstopencvutils.h"
 #include "gstedgedetect.h"
+#include <opencv2/imgproc/imgproc_c.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_edge_detect_debug);
 #define GST_CAT_DEFAULT gst_edge_detect_debug
diff --git a/ext/opencv/gstedgedetect.h b/ext/opencv/gstedgedetect.h
index 065dccf..23c95e6 100644
--- a/ext/opencv/gstedgedetect.h
+++ b/ext/opencv/gstedgedetect.h
@@ -47,7 +47,7 @@
 #define __GST_EDGE_DETECT_H__
 
 #include <gst/gst.h>
-#include <cv.h>
+#include <opencv2/core/core_c.h>
 
 G_BEGIN_DECLS
 /* #defines don't like whitespacey bits */
diff --git a/ext/opencv/gstfaceblur.c b/ext/opencv/gstfaceblur.c
index cadeaed..11d9145 100644
--- a/ext/opencv/gstfaceblur.c
+++ b/ext/opencv/gstfaceblur.c
@@ -65,6 +65,7 @@
 
 #include "gstopencvutils.h"
 #include "gstfaceblur.h"
+#include <opencv2/imgproc/imgproc_c.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_face_blur_debug);
 #define GST_CAT_DEFAULT gst_face_blur_debug
diff --git a/ext/opencv/gstfaceblur.h b/ext/opencv/gstfaceblur.h
index a6ee28e..23fa7fc 100644
--- a/ext/opencv/gstfaceblur.h
+++ b/ext/opencv/gstfaceblur.h
@@ -48,7 +48,7 @@
 #define __GST_FACE_BLUR_H__
 
 #include <gst/gst.h>
-#include <cv.h>
+#include <opencv2/core/version.hpp>
 
 #include "gstopencvvideofilter.h"
 
diff --git a/ext/opencv/gstfacedetect.c b/ext/opencv/gstfacedetect.c
index fa01268..0f9425b 100644
--- a/ext/opencv/gstfacedetect.c
+++ b/ext/opencv/gstfacedetect.c
@@ -81,6 +81,7 @@
 
 #include "gstopencvutils.h"
 #include "gstfacedetect.h"
+#include <opencv2/imgproc/imgproc_c.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_face_detect_debug);
 #define GST_CAT_DEFAULT gst_face_detect_debug
diff --git a/ext/opencv/gstfacedetect.h b/ext/opencv/gstfacedetect.h
index 090fb79..6db7033 100644
--- a/ext/opencv/gstfacedetect.h
+++ b/ext/opencv/gstfacedetect.h
@@ -49,7 +49,7 @@
 #define __GST_FACE_DETECT_H__
 
 #include <gst/gst.h>
-#include <cv.h>
+#include <opencv2/core/version.hpp>
 #include "gstopencvvideofilter.h"
 
 #if (CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >= 2)
diff --git a/ext/opencv/gstgrabcut.cpp b/ext/opencv/gstgrabcut.cpp
index 8b57306..c9ff4f9 100644
--- a/ext/opencv/gstgrabcut.cpp
+++ b/ext/opencv/gstgrabcut.cpp
@@ -89,7 +89,9 @@
 extern "C"
 {
 #include <gst/video/gstvideometa.h>
+#include <opencv2/imgproc/imgproc_c.h>
 }
+#include <opencv2/imgproc/imgproc.hpp>
 GST_DEBUG_CATEGORY_STATIC (gst_grabcut_debug);
 #define GST_CAT_DEFAULT gst_grabcut_debug
 
diff --git a/ext/opencv/gstgrabcut.h b/ext/opencv/gstgrabcut.h
index ec7dc96..de988bb 100644
--- a/ext/opencv/gstgrabcut.h
+++ b/ext/opencv/gstgrabcut.h
@@ -47,8 +47,9 @@
 #include <gst/gst.h>
 #include <gst/video/video.h>
 #include <gst/video/gstvideofilter.h>
+#include <opencv2/core/core_c.h>
 
-#include <cv.h>
+
 
 G_BEGIN_DECLS
 /* #defines don't like whitespacey bits */
diff --git a/ext/opencv/gsthanddetect.c b/ext/opencv/gsthanddetect.c
index d01a42e..8c72b72 100644
--- a/ext/opencv/gsthanddetect.c
+++ b/ext/opencv/gsthanddetect.c
@@ -63,6 +63,7 @@
 /* element header */
 #include "gsthanddetect.h"
 #include "gstopencvutils.h"
+#include <opencv2/imgproc/imgproc_c.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_handdetect_debug);
 #define GST_CAT_DEFAULT gst_handdetect_debug
@@ -429,7 +430,7 @@
     if (filter->prev_r == NULL)
       filter->prev_r = &temp_r;
     /* Get the best FIST gesture */
-    for (i = 0; i < (hands ? hands->total : 0); i++) {
+    for (i = 0; i < hands->total; i++) {
       r = (CvRect *) cvGetSeqElem (hands, i);
       distance = (int) sqrt (pow ((r->x - filter->prev_r->x),
               2) + pow ((r->y - filter->prev_r->y), 2));
diff --git a/ext/opencv/gsthanddetect.h b/ext/opencv/gsthanddetect.h
index 129784f..e57f567 100644
--- a/ext/opencv/gsthanddetect.h
+++ b/ext/opencv/gsthanddetect.h
@@ -51,9 +51,13 @@
 
 #include "gstopencvvideofilter.h"
 /* opencv */
-#include <cv.h>
-#include <cxcore.h>
-#include <highgui.h>
+#include <opencv2/core/version.hpp>
+#ifdef HAVE_HIGHGUI_H
+#include <highgui.h>            // includes highGUI definitions
+#endif
+#ifdef HAVE_OPENCV2_HIGHGUI_HIGHGUI_C_H
+#include <opencv2/highgui/highgui_c.h>            // includes highGUI definitions
+#endif
 #if (CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >= 2)
 #include <opencv2/objdetect/objdetect.hpp>
 #endif
diff --git a/ext/opencv/gstmotioncells.h b/ext/opencv/gstmotioncells.h
index 6d4b123..08eed3e 100644
--- a/ext/opencv/gstmotioncells.h
+++ b/ext/opencv/gstmotioncells.h
@@ -46,7 +46,7 @@
 #define __GST_MOTIONCELLS_H__
 
 #include <gst/gst.h>
-#include <cv.h>
+#include <opencv2/core/core_c.h>
 
 G_BEGIN_DECLS
 /* #defines don't like whitespacey bits */
diff --git a/ext/opencv/gstopencvutils.c b/ext/opencv/gstopencvutils.c
index 6655b07..89901bf 100644
--- a/ext/opencv/gstopencvutils.c
+++ b/ext/opencv/gstopencvutils.c
@@ -24,6 +24,7 @@
 #endif
 
 #include "gstopencvutils.h"
+#include <opencv2/core/types_c.h>
 
 static gboolean
 gst_opencv_get_ipl_depth_and_channels (GstStructure * structure,
diff --git a/ext/opencv/gstopencvutils.h b/ext/opencv/gstopencvutils.h
index 82a2795..84123f1 100644
--- a/ext/opencv/gstopencvutils.h
+++ b/ext/opencv/gstopencvutils.h
@@ -29,7 +29,7 @@
 #include <gst/gst.h>
 #include <gst/video/video.h>
 
-#include <cv.h>
+
 
 gboolean
 gst_opencv_get_ipldepth (gint depth, gint bpp, gint * ipldepth);
diff --git a/ext/opencv/gstopencvvideofilter.h b/ext/opencv/gstopencvvideofilter.h
index fce3b32..7fbafe9 100644
--- a/ext/opencv/gstopencvvideofilter.h
+++ b/ext/opencv/gstopencvvideofilter.h
@@ -46,7 +46,7 @@
 
 #include <gst/gst.h>
 #include <gst/video/gstvideofilter.h>
-#include <cv.h>
+#include <opencv2/core/core_c.h>
 
 G_BEGIN_DECLS
 /* #defines don't like whitespacey bits */
diff --git a/ext/opencv/gstpyramidsegment.h b/ext/opencv/gstpyramidsegment.h
index 7d7bcf5..586ef2c 100644
--- a/ext/opencv/gstpyramidsegment.h
+++ b/ext/opencv/gstpyramidsegment.h
@@ -47,7 +47,7 @@
 #define __GST_PYRAMID_SEGMENT_H__
 
 #include <gst/gst.h>
-#include <cv.h>
+#include <opencv2/core/version.hpp>
 
 #if CV_MAJOR_VERSION * 100 + CV_MINOR_VERSION >= 204
 #include <opencv2/legacy/legacy.hpp>
diff --git a/ext/opencv/gstretinex.c b/ext/opencv/gstretinex.c
index 8c64b80..5bc112a 100644
--- a/ext/opencv/gstretinex.c
+++ b/ext/opencv/gstretinex.c
@@ -64,6 +64,7 @@
 
 #include <gst/gst.h>
 #include "gstretinex.h"
+#include <opencv2/imgproc/imgproc_c.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_retinex_debug);
 #define GST_CAT_DEFAULT gst_retinex_debug
diff --git a/ext/opencv/gstretinex.h b/ext/opencv/gstretinex.h
index 24a7c5e..c53d230 100644
--- a/ext/opencv/gstretinex.h
+++ b/ext/opencv/gstretinex.h
@@ -47,8 +47,8 @@
 #include <gst/gst.h>
 #include <gst/video/video.h>
 #include <gst/video/gstvideofilter.h>
+#include <opencv2/core/core_c.h>
 
-#include <cv.h>
 
 G_BEGIN_DECLS
 /* #defines don't like whitespacey bits */
diff --git a/ext/opencv/gstsegmentation.cpp b/ext/opencv/gstsegmentation.cpp
index ec03b80..79cbb49 100644
--- a/ext/opencv/gstsegmentation.cpp
+++ b/ext/opencv/gstsegmentation.cpp
@@ -94,6 +94,7 @@
 
 #include "gstsegmentation.h"
 #include <opencv2/video/background_segm.hpp>
+#include <opencv2/imgproc/imgproc_c.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_segmentation_debug);
 #define GST_CAT_DEFAULT gst_segmentation_debug
diff --git a/ext/opencv/gstsegmentation.h b/ext/opencv/gstsegmentation.h
index 0357770..9400853 100644
--- a/ext/opencv/gstsegmentation.h
+++ b/ext/opencv/gstsegmentation.h
@@ -46,8 +46,9 @@
 
 #include <gst/gst.h>
 #include <gst/video/gstvideofilter.h>
+#include <opencv2/core/core_c.h>
 
-#include <cv.h>
+
 
 G_BEGIN_DECLS
 /* #defines don't like whitespacey bits */
diff --git a/ext/opencv/gstskindetect.c b/ext/opencv/gstskindetect.c
index 9cd5633..caf38ec 100644
--- a/ext/opencv/gstskindetect.c
+++ b/ext/opencv/gstskindetect.c
@@ -62,6 +62,8 @@
 
 #include "gstopencvutils.h"
 #include "gstskindetect.h"
+#include <opencv2/imgproc/imgproc_c.h>
+#include <opencv2/legacy/compat.hpp>
 
 GST_DEBUG_CATEGORY_STATIC (gst_skin_detect_debug);
 #define GST_CAT_DEFAULT gst_skin_detect_debug
diff --git a/ext/opencv/gstskindetect.h b/ext/opencv/gstskindetect.h
index 9789834..910d22e 100644
--- a/ext/opencv/gstskindetect.h
+++ b/ext/opencv/gstskindetect.h
@@ -47,7 +47,7 @@
 #define __GST_SKIN_DETECT_H__
 
 #include <gst/gst.h>
-#include <cv.h>
+
 #include <gstopencvvideofilter.h>
 
 G_BEGIN_DECLS
diff --git a/ext/opencv/gsttemplatematch.c b/ext/opencv/gsttemplatematch.c
index 602dd8e..3c97841 100644
--- a/ext/opencv/gsttemplatematch.c
+++ b/ext/opencv/gsttemplatematch.c
@@ -66,6 +66,7 @@
 #include "../../gst-libs/gst/gst-i18n-plugin.h"
 #include "gstopencvutils.h"
 #include "gsttemplatematch.h"
+#include <opencv2/imgproc/imgproc_c.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_template_match_debug);
 #define GST_CAT_DEFAULT gst_template_match_debug
diff --git a/ext/opencv/gsttemplatematch.h b/ext/opencv/gsttemplatematch.h
index 6b67000..44d3d9c 100644
--- a/ext/opencv/gsttemplatematch.h
+++ b/ext/opencv/gsttemplatematch.h
@@ -47,7 +47,7 @@
 #define __GST_TEMPLATE_MATCH_H__
 
 #include <gst/gst.h>
-#include <cv.h>
+
 #ifdef HAVE_HIGHGUI_H
 #include <highgui.h>            // includes highGUI definitions
 #endif
diff --git a/ext/opencv/gsttextoverlay.h b/ext/opencv/gsttextoverlay.h
index cf59b35..1fe8d22 100644
--- a/ext/opencv/gsttextoverlay.h
+++ b/ext/opencv/gsttextoverlay.h
@@ -48,6 +48,7 @@
 
 #include <gst/gst.h>
 #include "gstopencvutils.h"
+#include <opencv2/core/core_c.h>
 G_BEGIN_DECLS
 
 /* #defines don't like whitespacey bits */
diff --git a/ext/openh264/gstopenh264enc.cpp b/ext/openh264/gstopenh264enc.cpp
index ebbe9b4..4461ae2 100644
--- a/ext/openh264/gstopenh264enc.cpp
+++ b/ext/openh264/gstopenh264enc.cpp
@@ -38,6 +38,7 @@
 #include <wels/codec_api.h>
 #include <wels/codec_app_def.h>
 #include <wels/codec_def.h>
+#include <wels/codec_ver.h>
 
 #define GST_OPENH264ENC_GET_PRIVATE(obj) \
     (G_TYPE_INSTANCE_GET_PRIVATE((obj), GST_TYPE_OPENH264ENC, GstOpenh264EncPrivate))
@@ -103,14 +104,14 @@
         "Deblocking on, except for slice boundaries", "not-slice-boundaries"},
     {0, NULL, NULL},
   };
-  static volatile GType id = 0;
+  static gsize id = 0;
 
-  if (g_once_init_enter ((gsize *) & id)) {
+  if (g_once_init_enter (& id)) {
     GType _id = g_enum_register_static ("GstOpenh264encDeblockingModes", types);
-    g_once_init_leave ((gsize *) & id, _id);
+    g_once_init_leave (& id, _id);
   }
 
-  return id;
+  return (GType) id;
 }
 
 #define GST_TYPE_OPENH264ENC_SLICE_MODE (gst_openh264enc_slice_mode_get_type ())
@@ -122,14 +123,34 @@
     {SM_AUTO_SLICE, "Number of slices equal to number of threads", "auto"},
     {0, NULL, NULL},
   };
-  static volatile GType id = 0;
+  static gsize id = 0;
 
-  if (g_once_init_enter ((gsize *) & id)) {
+  if (g_once_init_enter (& id)) {
     GType _id = g_enum_register_static ("GstOpenh264encSliceModes", types);
-    g_once_init_leave ((gsize *) & id, _id);
+    g_once_init_leave (& id, _id);
   }
 
-  return id;
+  return (GType) id;
+}
+
+#define GST_TYPE_OPENH264ENC_COMPLEXITY (gst_openh264enc_complexity_get_type ())
+static GType
+gst_openh264enc_complexity_get_type (void)
+{
+  static const GEnumValue types[] = {
+    {LOW_COMPLEXITY, "Low complexity / high speed encoding", "low"},
+    {MEDIUM_COMPLEXITY, "Medium complexity / medium speed encoding", "medium"},
+    {HIGH_COMPLEXITY, "High complexity / low speed encoding", "high"},
+    {0, NULL, NULL},
+  };
+  static gsize id = 0;
+
+  if (g_once_init_enter (& id)) {
+    GType _id = g_enum_register_static ("GstOpenh264encComplexity", types);
+    g_once_init_leave (& id, _id);
+  }
+
+  return (GType) id;
 }
 
 /* prototypes */
@@ -170,6 +191,7 @@
 #define DEFAULT_SCENE_CHANGE_DETECTION TRUE
 #define DEFAULT_SLICE_MODE      SM_FIXEDSLCNUM_SLICE
 #define DEFAULT_NUM_SLICES      1
+#define DEFAULT_COMPLEXITY      MEDIUM_COMPLEXITY
 
 enum
 {
@@ -188,6 +210,7 @@
   PROP_SCENE_CHANGE_DETECTION,
   PROP_SLICE_MODE,
   PROP_NUM_SLICES,
+  PROP_COMPLEXITY,
   N_PROPERTIES
 };
 
@@ -214,6 +237,7 @@
   gboolean scene_change_detection;
   SliceModeEnum slice_mode;
   guint num_slices;
+  ECOMPLEXITY_MODE complexity;
 };
 
 /* pad templates */
@@ -352,6 +376,11 @@
           "The number of slices (needs slice-mode=n-slices)",
           0, G_MAXUINT, DEFAULT_NUM_SLICES,
           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COMPLEXITY,
+      g_param_spec_enum ("complexity", "Complexity / quality / speed tradeoff", "Complexity",
+          GST_TYPE_OPENH264ENC_COMPLEXITY, DEFAULT_COMPLEXITY,
+          (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
 }
 
 static void
@@ -379,6 +408,7 @@
   openh264enc->priv->slice_mode = DEFAULT_SLICE_MODE;
   openh264enc->priv->num_slices = DEFAULT_NUM_SLICES;
   openh264enc->priv->encoder = NULL;
+  openh264enc->priv->complexity = DEFAULT_COMPLEXITY;
   gst_openh264enc_set_usage_type (openh264enc, CAMERA_VIDEO_REAL_TIME);
   gst_openh264enc_set_rate_control (openh264enc, RC_QUALITY_MODE);
 }
@@ -485,6 +515,10 @@
       openh264enc->priv->num_slices = g_value_get_uint (value);
       break;
 
+    case PROP_COMPLEXITY:
+      openh264enc->priv->complexity = (ECOMPLEXITY_MODE) g_value_get_enum (value);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -556,6 +590,10 @@
       g_value_set_uint (value, openh264enc->priv->num_slices);
       break;
 
+    case PROP_COMPLEXITY:
+      g_value_set_enum (value, openh264enc->priv->complexity);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -674,6 +712,7 @@
   enc_params.iLtrMarkPeriod = 30;
   enc_params.iMultipleThreadIdc = openh264enc->priv->multi_thread;
   enc_params.bEnableDenoise = openh264enc->priv->enable_denoise;
+  enc_params.iComplexityMode = priv->complexity;
   enc_params.uiIntraPeriod = priv->gop_size;
   enc_params.bEnableBackgroundDetection =
       openh264enc->priv->background_detection;
@@ -682,7 +721,11 @@
       openh264enc->priv->scene_change_detection;
   enc_params.bEnableFrameSkip = openh264enc->priv->enable_frame_skip;
   enc_params.bEnableLongTermReference = 0;
+#if OPENH264_MINOR >= 4
+  enc_params.eSpsPpsIdStrategy = CONSTANT_ID;
+#else
   enc_params.bEnableSpsPpsIdAddition = 1;
+#endif
   enc_params.bPrefixNalAddingCtrl = 0;
   enc_params.fMaxFrameRate = fps_n * 1.0 / fps_d;
   enc_params.iLoopFilterDisableIdc = openh264enc->priv->deblocking_mode;
diff --git a/ext/opus/gstopusdec.c b/ext/opus/gstopusdec.c
index cfa711a..a634787 100644
--- a/ext/opus/gstopusdec.c
+++ b/ext/opus/gstopusdec.c
@@ -224,13 +224,11 @@
     caps = gst_caps_truncate (caps);
     caps = gst_caps_make_writable (caps);
     s = gst_caps_get_structure (caps, 0);
-    gst_structure_fixate_field_nearest_int (s, "rate", 48000);
+    gst_structure_fixate_field_nearest_int (s, "rate", dec->sample_rate);
     gst_structure_get_int (s, "rate", &dec->sample_rate);
     gst_structure_fixate_field_nearest_int (s, "channels", dec->n_channels);
     gst_structure_get_int (s, "channels", &dec->n_channels);
     gst_caps_unref (caps);
-  } else {
-    dec->sample_rate = 48000;
   }
 
   GST_INFO_OBJECT (dec, "Negotiated %d channels, %d Hz", dec->n_channels,
@@ -282,6 +280,7 @@
   }
 
   dec->n_channels = data[9];
+  dec->sample_rate = GST_READ_UINT32_LE (data + 12);
   dec->pre_skip = GST_READ_UINT16_LE (data + 10);
   dec->r128_gain = GST_READ_UINT16_LE (data + 16);
   dec->r128_gain_volume = gst_opus_dec_get_r128_volume (dec->r128_gain);
@@ -432,7 +431,9 @@
   samples = 120 * dec->sample_rate / 1000;
   packet_size = samples * dec->n_channels * 2;
 
-  outbuf = gst_buffer_new_and_alloc (packet_size);
+  outbuf =
+      gst_audio_decoder_allocate_output_buffer (GST_AUDIO_DECODER (dec),
+      packet_size);
   if (!outbuf) {
     goto buffer_failed;
   }
@@ -542,9 +543,22 @@
   gboolean ret = TRUE;
   GstStructure *s;
   const GValue *streamheader;
+  GstCaps *old_caps;
 
   GST_DEBUG_OBJECT (dec, "set_format: %" GST_PTR_FORMAT, caps);
 
+  if ((old_caps = gst_pad_get_current_caps (GST_AUDIO_DECODER_SINK_PAD (bdec)))) {
+    if (gst_caps_is_equal (caps, old_caps)) {
+      gst_caps_unref (old_caps);
+      GST_DEBUG_OBJECT (dec, "caps didn't change");
+      goto done;
+    }
+
+    GST_DEBUG_OBJECT (dec, "caps have changed, resetting decoder");
+    gst_opus_dec_reset (dec);
+    gst_caps_unref (old_caps);
+  }
+
   s = gst_caps_get_structure (caps, 0);
   if ((streamheader = gst_structure_get_value (s, "streamheader")) &&
       G_VALUE_HOLDS (streamheader, GST_TYPE_ARRAY) &&
@@ -570,6 +584,22 @@
         goto done;
       gst_buffer_replace (&dec->vorbiscomment, buf);
     }
+  } else {
+    /* defaults if not in the caps */
+    dec->n_channels = 2;
+    dec->sample_rate = 48000;
+
+    gst_structure_get_int (s, "channels", &dec->n_channels);
+    gst_structure_get_int (s, "rate", &dec->sample_rate);
+
+    /* default stereo mapping */
+    dec->channel_mapping_family = 0;
+    dec->channel_mapping[0] = 0;
+    dec->channel_mapping[1] = 1;
+    dec->n_streams = 1;
+    dec->n_stereo_streams = 1;
+
+    gst_opus_dec_negotiate (dec, NULL);
   }
 
 done:
diff --git a/ext/opus/gstopusdec.h b/ext/opus/gstopusdec.h
index 7248778..4a270fe 100644
--- a/ext/opus/gstopusdec.h
+++ b/ext/opus/gstopusdec.h
@@ -24,7 +24,7 @@
 
 #include <gst/gst.h>
 #include <gst/audio/gstaudiodecoder.h>
-#include <opus/opus_multistream.h>
+#include <opus_multistream.h>
 
 G_BEGIN_DECLS
 
diff --git a/ext/opus/gstopusenc.c b/ext/opus/gstopusenc.c
index cb3f276..4bac854 100644
--- a/ext/opus/gstopusenc.c
+++ b/ext/opus/gstopusenc.c
@@ -44,7 +44,7 @@
 #include <string.h>
 #include <time.h>
 #include <math.h>
-#include <opus/opus.h>
+#include <opus.h>
 
 #include <gst/gsttagsetter.h>
 #include <gst/audio/audio.h>
@@ -387,8 +387,6 @@
   GstOpusEnc *enc = GST_OPUS_ENC (benc);
 
   GST_DEBUG_OBJECT (enc, "start");
-  enc->tags = gst_tag_list_new_empty ();
-  enc->header_sent = FALSE;
   enc->encoded_samples = 0;
 
   return TRUE;
@@ -400,16 +398,10 @@
   GstOpusEnc *enc = GST_OPUS_ENC (benc);
 
   GST_DEBUG_OBJECT (enc, "stop");
-  enc->header_sent = FALSE;
   if (enc->state) {
     opus_multistream_encoder_destroy (enc->state);
     enc->state = NULL;
   }
-  gst_tag_list_unref (enc->tags);
-  enc->tags = NULL;
-  g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL);
-  g_slist_free (enc->headers);
-  enc->headers = NULL;
   gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));
 
   return TRUE;
@@ -701,6 +693,8 @@
 gst_opus_enc_setup (GstOpusEnc * enc)
 {
   int error = OPUS_OK;
+  GstCaps *caps;
+  gboolean ret;
 
 #ifndef GST_DISABLE_GST_DEBUG
   GST_DEBUG_OBJECT (enc,
@@ -740,7 +734,18 @@
 
   GST_LOG_OBJECT (enc, "we have frame size %d", enc->frame_size);
 
-  return TRUE;
+  gst_opus_header_create_caps (&caps, NULL, enc->n_channels,
+      enc->n_stereo_streams, enc->sample_rate, enc->channel_mapping_family,
+      enc->decoding_channel_mapping,
+      gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc)));
+
+  /* negotiate with these caps */
+  GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);
+
+  ret = gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (enc), caps);
+  gst_caps_unref (caps);
+
+  return ret;
 
 encoder_creation_failed:
   GST_ERROR_OBJECT (enc, "Encoder creation failed");
@@ -913,7 +918,9 @@
 
   g_assert (size == bytes);
 
-  outbuf = gst_buffer_new_and_alloc (max_payload_size * enc->n_channels);
+  outbuf =
+      gst_audio_encoder_allocate_output_buffer (GST_AUDIO_ENCODER (enc),
+      max_payload_size * enc->n_channels);
   if (!outbuf)
     goto done;
 
@@ -970,29 +977,6 @@
 
   enc = GST_OPUS_ENC (benc);
   GST_DEBUG_OBJECT (enc, "handle_frame");
-
-  if (!enc->header_sent) {
-    GstCaps *caps;
-
-    g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL);
-    g_slist_free (enc->headers);
-    enc->headers = NULL;
-
-    gst_opus_header_create_caps (&caps, &enc->headers, enc->n_channels,
-        enc->n_stereo_streams, enc->sample_rate, enc->channel_mapping_family,
-        enc->decoding_channel_mapping,
-        gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc)));
-
-
-    /* negotiate with these caps */
-    GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);
-
-    gst_audio_encoder_set_output_format (benc, caps);
-    gst_caps_unref (caps);
-
-    enc->header_sent = TRUE;
-  }
-
   GST_DEBUG_OBJECT (enc, "received buffer %p of %" G_GSIZE_FORMAT " bytes", buf,
       buf ? gst_buffer_get_size (buf) : 0);
 
@@ -1037,6 +1021,7 @@
           ("constrained-vbr property is deprecated; use bitrate-type instead");
       g_value_set_boolean (value,
           enc->bitrate_type == BITRATE_TYPE_CONSTRAINED_VBR);
+      break;
     case PROP_BITRATE_TYPE:
       g_value_set_enum (value, enc->bitrate_type);
       break;
diff --git a/ext/opus/gstopusenc.h b/ext/opus/gstopusenc.h
index 4ff9610..43eaac8 100644
--- a/ext/opus/gstopusenc.h
+++ b/ext/opus/gstopusenc.h
@@ -27,7 +27,7 @@
 #include <gst/gst.h>
 #include <gst/audio/gstaudioencoder.h>
 
-#include <opus/opus_multistream.h>
+#include <opus_multistream.h>
 
 G_BEGIN_DECLS
 
@@ -79,13 +79,8 @@
   gint                  n_channels;
   gint                  sample_rate;
 
-  gboolean              header_sent;
   guint64               encoded_samples;
 
-  GSList                *headers;
-
-  GstTagList            *tags;
-
   guint8                channel_mapping_family;
   guint8                encoding_channel_mapping[256];
   guint8                decoding_channel_mapping[256];
diff --git a/ext/opus/gstopusheader.c b/ext/opus/gstopusheader.c
index d190cc2..1521c1c 100644
--- a/ext/opus/gstopusheader.c
+++ b/ext/opus/gstopusheader.c
@@ -157,17 +157,21 @@
     GstBuffer * buf1, GstBuffer * buf2)
 {
   int n_streams, family;
+  gint channels, rate;
   gboolean multistream;
   GstMapInfo map;
   guint8 *data;
 
   g_return_if_fail (caps);
-  g_return_if_fail (headers && !*headers);
+  g_return_if_fail (!headers || !*headers);
   g_return_if_fail (gst_buffer_get_size (buf1) >= 19);
 
   gst_buffer_map (buf1, &map, GST_MAP_READ);
   data = map.data;
 
+  channels = data[9];
+  rate = GST_READ_UINT32_LE (data + 12);
+
   /* work out the number of streams */
   family = data[18];
   if (family == 0) {
@@ -183,16 +187,27 @@
     }
   }
 
+  /* TODO: should probably also put the channel mapping into the caps too once
+   * we actually support multi channel, and pre-skip and other fields */
+
   gst_buffer_unmap (buf1, &map);
 
   /* mark and put on caps */
   multistream = n_streams > 1;
   *caps = gst_caps_new_simple ("audio/x-opus",
-      "multistream", G_TYPE_BOOLEAN, multistream, NULL);
+      "multistream", G_TYPE_BOOLEAN, multistream,
+      "channels", G_TYPE_INT, channels, NULL);
+
+  if (rate > 0) {
+    gst_caps_set_simple (*caps, "rate", G_TYPE_INT, rate, NULL);
+  }
+
   *caps = _gst_caps_set_buffer_array (*caps, "streamheader", buf1, buf2, NULL);
 
-  *headers = g_slist_prepend (*headers, gst_buffer_ref (buf2));
-  *headers = g_slist_prepend (*headers, gst_buffer_ref (buf1));
+  if (headers) {
+    *headers = g_slist_prepend (*headers, gst_buffer_ref (buf2));
+    *headers = g_slist_prepend (*headers, gst_buffer_ref (buf1));
+  }
 }
 
 void
@@ -203,7 +218,7 @@
   GstBuffer *buf1, *buf2;
 
   g_return_if_fail (caps);
-  g_return_if_fail (headers && !*headers);
+  g_return_if_fail (!headers || !*headers);
   g_return_if_fail (nchannels > 0);
   g_return_if_fail (sample_rate >= 0);  /* 0 -> unset */
   g_return_if_fail (channel_mapping_family == 0 || channel_mapping);
diff --git a/ext/opus/gstopusparse.c b/ext/opus/gstopusparse.c
index 8ede3a3..c8aba11 100644
--- a/ext/opus/gstopusparse.c
+++ b/ext/opus/gstopusparse.c
@@ -39,7 +39,7 @@
 #endif
 
 #include <string.h>
-#include <opus/opus.h>
+#include <opus.h>
 #include "gstopusheader.h"
 #include "gstopusparse.h"
 
diff --git a/ext/opus/gstrtpopusdepay.c b/ext/opus/gstrtpopusdepay.c
index 6bcdd12..af3237b 100644
--- a/ext/opus/gstrtpopusdepay.c
+++ b/ext/opus/gstrtpopusdepay.c
@@ -46,7 +46,7 @@
 GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("audio/x-opus")
+    GST_STATIC_CAPS ("audio/x-opus, multistream = (boolean) FALSE")
     );
 
 static GstBuffer *gst_rtp_opus_depay_process (GstRTPBaseDepayload * depayload,
@@ -92,9 +92,40 @@
 gst_rtp_opus_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
 {
   GstCaps *srccaps;
+  GstStructure *s;
   gboolean ret;
+  const gchar *sprop_stereo, *sprop_maxcapturerate;
 
-  srccaps = gst_caps_new_empty_simple ("audio/x-opus");
+  srccaps =
+      gst_caps_new_simple ("audio/x-opus", "multistream", G_TYPE_BOOLEAN, FALSE,
+      NULL);
+
+  s = gst_caps_get_structure (caps, 0);
+  if ((sprop_stereo = gst_structure_get_string (s, "sprop-stereo"))) {
+    if (strcmp (sprop_stereo, "0") == 0)
+      gst_caps_set_simple (srccaps, "channels", G_TYPE_INT, 1, NULL);
+    else if (strcmp (sprop_stereo, "1") == 0)
+      gst_caps_set_simple (srccaps, "channels", G_TYPE_INT, 2, NULL);
+    else
+      GST_WARNING_OBJECT (depayload, "Unknown sprop-stereo value '%s'",
+          sprop_stereo);
+  }
+
+  if ((sprop_maxcapturerate =
+          gst_structure_get_string (s, "sprop-maxcapturerate"))) {
+    gulong rate;
+    gchar *tailptr;
+
+    rate = strtoul (sprop_maxcapturerate, &tailptr, 10);
+    if (rate > INT_MAX || *tailptr != '\0') {
+      GST_WARNING_OBJECT (depayload,
+          "Failed to parse sprop-maxcapturerate value '%s'",
+          sprop_maxcapturerate);
+    } else {
+      gst_caps_set_simple (srccaps, "rate", G_TYPE_INT, rate, NULL);
+    }
+  }
+
   ret = gst_pad_set_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (depayload), srccaps);
 
   GST_DEBUG_OBJECT (depayload,
diff --git a/ext/opus/gstrtpopuspay.c b/ext/opus/gstrtpopuspay.c
index d0f7b10..057c8d0 100644
--- a/ext/opus/gstrtpopuspay.c
+++ b/ext/opus/gstrtpopuspay.c
@@ -48,11 +48,14 @@
         "media = (string) \"audio\", "
         "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
         "clock-rate = (int) 48000, "
+        "encoding-params = (string) \"2\", "
         "encoding-name = (string) { \"OPUS\", \"X-GST-OPUS-DRAFT-SPITTKA-00\" }")
     );
 
 static gboolean gst_rtp_opus_pay_setcaps (GstRTPBasePayload * payload,
     GstCaps * caps);
+static GstCaps *gst_rtp_opus_pay_getcaps (GstRTPBasePayload * payload,
+    GstPad * pad, GstCaps * filter);
 static GstFlowReturn gst_rtp_opus_pay_handle_buffer (GstRTPBasePayload *
     payload, GstBuffer * buffer);
 
@@ -68,6 +71,7 @@
   element_class = GST_ELEMENT_CLASS (klass);
 
   gstbasertppayload_class->set_caps = gst_rtp_opus_pay_setcaps;
+  gstbasertppayload_class->get_caps = gst_rtp_opus_pay_getcaps;
   gstbasertppayload_class->handle_buffer = gst_rtp_opus_pay_handle_buffer;
 
   gst_element_class_add_pad_template (element_class,
@@ -97,6 +101,9 @@
   GstCaps *src_caps;
   GstStructure *s;
   char *encoding_name;
+  gint channels, rate;
+  const char *sprop_stereo = NULL;
+  char *sprop_maxcapturerate = NULL;
 
   src_caps = gst_pad_get_allowed_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload));
   if (src_caps) {
@@ -110,10 +117,45 @@
     encoding_name = g_strdup ("X-GST-OPUS-DRAFT-SPITTKA-00");
   }
 
+  s = gst_caps_get_structure (caps, 0);
+  if (gst_structure_get_int (s, "channels", &channels)) {
+    if (channels > 2) {
+      GST_ERROR_OBJECT (payload,
+          "More than 2 channels with multistream=FALSE is invalid");
+      return FALSE;
+    } else if (channels == 2) {
+      sprop_stereo = "1";
+    } else {
+      sprop_stereo = "0";
+    }
+  }
+
+  if (gst_structure_get_int (s, "rate", &rate)) {
+    sprop_maxcapturerate = g_strdup_printf ("%d", rate);
+  }
+
   gst_rtp_base_payload_set_options (payload, "audio", FALSE,
       encoding_name, 48000);
   g_free (encoding_name);
-  res = gst_rtp_base_payload_set_outcaps (payload, NULL);
+
+  if (sprop_maxcapturerate && sprop_stereo) {
+    res =
+        gst_rtp_base_payload_set_outcaps (payload, "sprop-maxcapturerate",
+        G_TYPE_STRING, sprop_maxcapturerate, "sprop-stereo", G_TYPE_STRING,
+        sprop_stereo, NULL);
+  } else if (sprop_maxcapturerate) {
+    res =
+        gst_rtp_base_payload_set_outcaps (payload, "sprop-maxcapturerate",
+        G_TYPE_STRING, sprop_maxcapturerate, NULL);
+  } else if (sprop_stereo) {
+    res =
+        gst_rtp_base_payload_set_outcaps (payload, "sprop-stereo",
+        G_TYPE_STRING, sprop_stereo, NULL);
+  } else {
+    res = gst_rtp_base_payload_set_outcaps (payload, NULL);
+  }
+
+  g_free (sprop_maxcapturerate);
 
   return res;
 }
@@ -139,3 +181,62 @@
   /* Push out */
   return gst_rtp_base_payload_push (basepayload, outbuf);
 }
+
+static GstCaps *
+gst_rtp_opus_pay_getcaps (GstRTPBasePayload * payload,
+    GstPad * pad, GstCaps * filter)
+{
+  GstCaps *caps, *peercaps, *tcaps;
+  GstStructure *s;
+  const gchar *stereo;
+
+  if (pad == GST_RTP_BASE_PAYLOAD_SRCPAD (payload))
+    return
+        GST_RTP_BASE_PAYLOAD_CLASS (gst_rtp_opus_pay_parent_class)->get_caps
+        (payload, pad, filter);
+
+  tcaps = gst_pad_get_pad_template_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload));
+  peercaps = gst_pad_peer_query_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload),
+      tcaps);
+  gst_caps_unref (tcaps);
+  if (!peercaps)
+    return
+        GST_RTP_BASE_PAYLOAD_CLASS (gst_rtp_opus_pay_parent_class)->get_caps
+        (payload, pad, filter);
+
+  if (gst_caps_is_empty (peercaps))
+    return peercaps;
+
+  caps = gst_pad_get_pad_template_caps (GST_RTP_BASE_PAYLOAD_SINKPAD (payload));
+
+  s = gst_caps_get_structure (peercaps, 0);
+  stereo = gst_structure_get_string (s, "stereo");
+  if (stereo != NULL) {
+    caps = gst_caps_make_writable (caps);
+
+    if (!strcmp (stereo, "1")) {
+      GstCaps *caps2 = gst_caps_copy (caps);
+
+      gst_caps_set_simple (caps, "channels", G_TYPE_INT, 2, NULL);
+      gst_caps_set_simple (caps2, "channels", G_TYPE_INT, 1, NULL);
+      caps = gst_caps_merge (caps, caps2);
+    } else if (!strcmp (stereo, "0")) {
+      GstCaps *caps2 = gst_caps_copy (caps);
+
+      gst_caps_set_simple (caps, "channels", G_TYPE_INT, 1, NULL);
+      gst_caps_set_simple (caps2, "channels", G_TYPE_INT, 2, NULL);
+      caps = gst_caps_merge (caps, caps2);
+    }
+  }
+  gst_caps_unref (peercaps);
+
+  if (filter) {
+    GstCaps *tmp = gst_caps_intersect_full (caps, filter,
+        GST_CAPS_INTERSECT_FIRST);
+    gst_caps_unref (caps);
+    caps = tmp;
+  }
+
+  GST_DEBUG_OBJECT (payload, "Returning caps: %" GST_PTR_FORMAT, caps);
+  return caps;
+}
diff --git a/ext/smoothstreaming/Makefile.am b/ext/smoothstreaming/Makefile.am
index 06c6796..5f331f3 100644
--- a/ext/smoothstreaming/Makefile.am
+++ b/ext/smoothstreaming/Makefile.am
@@ -19,18 +19,3 @@
 
 noinst_HEADERS = gstmssdemux.h \
 	gstmssmanifest.h
-
-Android.mk: Makefile.am $(BUILT_SOURCES)
-	androgenizer \
-	-:PROJECT libgstsmoothstreaming -:SHARED libgstsmoothstreaming \
-	 -:TAGS eng debug \
-         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgstsmoothstreaming_la_SOURCES) \
-	 -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(CPPFLAGS) $(libgstsmoothstreaming_la_CFLAGS) \
-	 -:LDFLAGS $(libgstsmoothstreaming_la_LDFLAGS) \
-	           $(libgstsmoothstreaming_la_LIBADD) \
-	           -ldl \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-		       LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
-	> $@
-
diff --git a/ext/smoothstreaming/Makefile.in b/ext/smoothstreaming/Makefile.in
index 1bf70fe..8a34871 100644
--- a/ext/smoothstreaming/Makefile.in
+++ b/ext/smoothstreaming/Makefile.in
@@ -1105,20 +1105,6 @@
 	uninstall-pluginLTLIBRARIES
 
 
-Android.mk: Makefile.am $(BUILT_SOURCES)
-	androgenizer \
-	-:PROJECT libgstsmoothstreaming -:SHARED libgstsmoothstreaming \
-	 -:TAGS eng debug \
-         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgstsmoothstreaming_la_SOURCES) \
-	 -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(CPPFLAGS) $(libgstsmoothstreaming_la_CFLAGS) \
-	 -:LDFLAGS $(libgstsmoothstreaming_la_LDFLAGS) \
-	           $(libgstsmoothstreaming_la_LIBADD) \
-	           -ldl \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-		       LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
-	> $@
-
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
diff --git a/ext/smoothstreaming/gstmssdemux.c b/ext/smoothstreaming/gstmssdemux.c
index 90cfac1..8f10d7d 100644
--- a/ext/smoothstreaming/gstmssdemux.c
+++ b/ext/smoothstreaming/gstmssdemux.c
@@ -135,7 +135,8 @@
 static gint64
 gst_mss_demux_get_manifest_update_interval (GstAdaptiveDemux * demux);
 static GstFlowReturn
-gst_mss_demux_update_manifest (GstAdaptiveDemux * demux, GstBuffer * buffer);
+gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,
+    GstBuffer * buffer);
 
 static void
 gst_mss_demux_class_init (GstMssDemuxClass * klass)
@@ -188,7 +189,8 @@
       gst_mss_demux_stream_select_bitrate;
   gstadaptivedemux_class->stream_update_fragment_info =
       gst_mss_demux_stream_update_fragment_info;
-  gstadaptivedemux_class->update_manifest = gst_mss_demux_update_manifest;
+  gstadaptivedemux_class->update_manifest_data =
+      gst_mss_demux_update_manifest_data;
 
   GST_DEBUG_CATEGORY_INIT (mssdemux_debug, "mssdemux", 0, "mssdemux plugin");
 }
@@ -546,7 +548,8 @@
 }
 
 static GstFlowReturn
-gst_mss_demux_update_manifest (GstAdaptiveDemux * demux, GstBuffer * buffer)
+gst_mss_demux_update_manifest_data (GstAdaptiveDemux * demux,
+    GstBuffer * buffer)
 {
   GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);
 
diff --git a/ext/smoothstreaming/gstmssmanifest.c b/ext/smoothstreaming/gstmssmanifest.c
index 7254e4d..e92e3da 100644
--- a/ext/smoothstreaming/gstmssmanifest.c
+++ b/ext/smoothstreaming/gstmssmanifest.c
@@ -724,7 +724,8 @@
     gst_structure_set (structure, "rate", G_TYPE_INT, rate, NULL);
 
   if (q->bitrate)
-    gst_structure_set (structure, "bitrate", G_TYPE_INT, (int) q->bitrate, NULL);
+    gst_structure_set (structure, "bitrate", G_TYPE_INT, (int) q->bitrate,
+        NULL);
 
   if (codec_data)
     gst_structure_set (structure, "codec_data", GST_TYPE_BUFFER, codec_data,
diff --git a/ext/spandsp/gstspanplc.c b/ext/spandsp/gstspanplc.c
index c30c0d7..d3ff53f 100644
--- a/ext/spandsp/gstspanplc.c
+++ b/ext/spandsp/gstspanplc.c
@@ -188,8 +188,7 @@
   GstSpanPlc *plc = GST_SPAN_PLC (parent);
   GstMapInfo map;
 
-  if (plc->plc_state->missing_samples != 0)
-    buffer = gst_buffer_make_writable (buffer);
+  buffer = gst_buffer_make_writable (buffer);
   gst_buffer_map (buffer, &map, GST_MAP_READWRITE);
   plc_rx (plc->plc_state, (int16_t *) map.data, map.size / 2);
   gst_buffer_unmap (buffer, &map);
diff --git a/ext/srtp/gstsrtpdec.c b/ext/srtp/gstsrtpdec.c
index debff15..31999cb 100644
--- a/ext/srtp/gstsrtpdec.c
+++ b/ext/srtp/gstsrtpdec.c
@@ -142,6 +142,22 @@
   PROP_0
 };
 
+typedef struct _ValidateBufferItData
+{
+  GstSrtpDecSsrcStream **stream;
+  GstSrtpDec *filter;
+  guint32 *ssrc;
+  gboolean *is_rtcp;
+} ValidateBufferItData;
+
+typedef struct _DecodeBufferItData
+{
+  GstSrtpDec *filter;
+  GstPad *pad;
+  guint32 ssrc;
+  gboolean is_rtcp;
+} DecodeBufferItData;
+
 /* the capabilities of the inputs and outputs.
  *
  * describe the real formats here.
@@ -202,6 +218,11 @@
 static GstFlowReturn gst_srtp_dec_chain_rtcp (GstPad * pad,
     GstObject * parent, GstBuffer * buf);
 
+static GstFlowReturn gst_srtp_dec_chain_list_rtp (GstPad * pad,
+    GstObject * parent, GstBufferList * buf_list);
+static GstFlowReturn gst_srtp_dec_chain_list_rtcp (GstPad * pad,
+    GstObject * parent, GstBufferList * buf_list);
+
 static GstStateChangeReturn gst_srtp_dec_change_state (GstElement * element,
     GstStateChange transition);
 
@@ -347,6 +368,8 @@
       GST_DEBUG_FUNCPTR (gst_srtp_dec_iterate_internal_links_rtp));
   gst_pad_set_chain_function (filter->rtp_sinkpad,
       GST_DEBUG_FUNCPTR (gst_srtp_dec_chain_rtp));
+  gst_pad_set_chain_list_function (filter->rtp_sinkpad,
+      GST_DEBUG_FUNCPTR (gst_srtp_dec_chain_list_rtp));
 
   filter->rtp_srcpad =
       gst_pad_new_from_static_template (&rtp_src_template, "rtp_src");
@@ -370,6 +393,8 @@
       GST_DEBUG_FUNCPTR (gst_srtp_dec_iterate_internal_links_rtcp));
   gst_pad_set_chain_function (filter->rtcp_sinkpad,
       GST_DEBUG_FUNCPTR (gst_srtp_dec_chain_rtcp));
+  gst_pad_set_chain_list_function (filter->rtcp_sinkpad,
+      GST_DEBUG_FUNCPTR (gst_srtp_dec_chain_list_rtcp));
 
   filter->rtcp_srcpad =
       gst_pad_new_from_static_template (&rtcp_src_template, "rtcp_src");
@@ -701,6 +726,9 @@
     else
       GST_WARNING_OBJECT (filter, "Could not set stream with SSRC %u", ssrc);
     gst_caps_unref (caps);
+  } else {
+    GST_WARNING_OBJECT (filter, "Could not get caps for stream with SSRC %u",
+        ssrc);
   }
 
   return stream;
@@ -768,6 +796,14 @@
       gst_event_unref (event);
       return ret;
     case GST_EVENT_SEGMENT:
+      /* Make sure to send a caps event downstream before the segment event,
+       * even if upstream didn't */
+      if (!gst_pad_has_current_caps (filter->rtp_srcpad)) {
+        GstCaps *caps = gst_caps_new_empty_simple ("application/x-rtp");
+
+        gst_pad_set_caps (filter->rtp_srcpad, caps);
+        gst_caps_unref (caps);
+      }
       filter->rtp_has_segment = TRUE;
       break;
     case GST_EVENT_FLUSH_STOP:
@@ -795,6 +831,14 @@
       gst_event_unref (event);
       return ret;
     case GST_EVENT_SEGMENT:
+      /* Make sure to send a caps event downstream before the segment event,
+       * even if upstream didn't */
+      if (!gst_pad_has_current_caps (filter->rtcp_srcpad)) {
+        GstCaps *caps = gst_caps_new_empty_simple ("application/x-rtcp");
+
+        gst_pad_set_caps (filter->rtcp_srcpad, caps);
+        gst_caps_unref (caps);
+      }
       filter->rtcp_has_segment = TRUE;
       break;
     case GST_EVENT_FLUSH_STOP:
@@ -1003,33 +1047,16 @@
 
 }
 
-static GstFlowReturn
-gst_srtp_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf,
-    gboolean is_rtcp)
+/*
+ * This function should be called while holding the filter lock
+ */
+static gboolean
+gst_srtp_dec_decode_buffer (GstSrtpDec * filter, GstPad * pad, GstBuffer * buf,
+    gboolean is_rtcp, guint32 ssrc)
 {
-  GstSrtpDec *filter = GST_SRTP_DEC (parent);
-  GstPad *otherpad;
-  err_status_t err = err_status_ok;
-  GstSrtpDecSsrcStream *stream = NULL;
-  GstFlowReturn ret = GST_FLOW_OK;
-  gint size;
-  guint32 ssrc = 0;
   GstMapInfo map;
-
-  GST_OBJECT_LOCK (filter);
-
-  /* Check if this stream exists, if not create a new stream */
-
-  if (!(stream = validate_buffer (filter, buf, &ssrc, &is_rtcp))) {
-    GST_OBJECT_UNLOCK (filter);
-    GST_WARNING_OBJECT (filter, "Invalid buffer, dropping");
-    goto drop_buffer;
-  }
-
-  if (!STREAM_HAS_CRYPTO (stream)) {
-    GST_OBJECT_UNLOCK (filter);
-    goto push_out;
-  }
+  err_status_t err;
+  gint size;
 
   GST_LOG_OBJECT (pad, "Received %s buffer of size %" G_GSIZE_FORMAT
       " with SSRC = %u", is_rtcp ? "RTCP" : "RTP", gst_buffer_get_size (buf),
@@ -1038,11 +1065,11 @@
   /* Change buffer to remove protection */
   buf = gst_buffer_make_writable (buf);
 
-unprotect:
-
   gst_buffer_map (buf, &map, GST_MAP_READWRITE);
   size = map.size;
 
+unprotect:
+
   gst_srtp_init_event_reporter ();
 
   if (is_rtcp)
@@ -1074,8 +1101,6 @@
     err = srtp_unprotect (filter->session, map.data, &size);
   }
 
-  gst_buffer_unmap (buf, &map);
-
   GST_OBJECT_UNLOCK (filter);
 
   if (err != err_status_ok) {
@@ -1113,10 +1138,50 @@
         break;
     }
 
+    gst_buffer_unmap (buf, &map);
+
+    GST_OBJECT_LOCK (filter);
+    return FALSE;
+  }
+
+  gst_buffer_unmap (buf, &map);
+
+  gst_buffer_set_size (buf, size);
+
+  GST_OBJECT_LOCK (filter);
+  return TRUE;
+}
+
+static GstFlowReturn
+gst_srtp_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf,
+    gboolean is_rtcp)
+{
+  GstSrtpDec *filter = GST_SRTP_DEC (parent);
+  GstPad *otherpad;
+  GstSrtpDecSsrcStream *stream = NULL;
+  GstFlowReturn ret = GST_FLOW_OK;
+  guint32 ssrc = 0;
+
+  GST_OBJECT_LOCK (filter);
+
+  /* Check if this stream exists, if not create a new stream */
+  if (!(stream = validate_buffer (filter, buf, &ssrc, &is_rtcp))) {
+    GST_OBJECT_UNLOCK (filter);
+    GST_WARNING_OBJECT (filter, "Invalid buffer, dropping");
     goto drop_buffer;
   }
 
-  gst_buffer_set_size (buf, size);
+  if (!STREAM_HAS_CRYPTO (stream)) {
+    GST_OBJECT_UNLOCK (filter);
+    goto push_out;
+  }
+
+  if (!gst_srtp_dec_decode_buffer (filter, pad, buf, is_rtcp, ssrc)) {
+    GST_OBJECT_UNLOCK (filter);
+    goto drop_buffer;
+  }
+
+  GST_OBJECT_UNLOCK (filter);
 
   /* If all is well, we may have reached soft limit */
   if (gst_srtp_get_soft_limit_reached ())
@@ -1147,6 +1212,107 @@
   return ret;
 }
 
+static gboolean
+validate_buffer_it (GstBuffer ** buffer, guint index, gpointer user_data)
+{
+  ValidateBufferItData *data = user_data;
+
+  if (!(*data->stream =
+          validate_buffer (data->filter, *buffer, data->ssrc, data->is_rtcp))) {
+    GST_WARNING_OBJECT (data->filter, "Invalid buffer, dropping");
+    gst_buffer_replace (buffer, NULL);
+  }
+
+  return TRUE;
+}
+
+static gboolean
+decode_buffer_it (GstBuffer ** buffer, guint index, gpointer user_data)
+{
+  DecodeBufferItData *data = user_data;
+
+  if (!gst_srtp_dec_decode_buffer (data->filter, data->pad, *buffer,
+          data->is_rtcp, data->ssrc)) {
+    GST_WARNING_OBJECT (data->filter, "Error decoding buffer, dropping");
+    gst_buffer_replace (buffer, NULL);
+  }
+
+  return TRUE;
+}
+
+static GstFlowReturn
+gst_srtp_dec_chain_list (GstPad * pad, GstObject * parent,
+    GstBufferList * buf_list, gboolean is_rtcp)
+{
+  GstSrtpDec *filter = GST_SRTP_DEC (parent);
+  GstPad *otherpad;
+  GstSrtpDecSsrcStream *stream = NULL;
+  GstFlowReturn ret = GST_FLOW_OK;
+  guint32 ssrc = 0;
+  ValidateBufferItData validate_data;
+  DecodeBufferItData decode_data;
+
+  validate_data.stream = &stream;
+  validate_data.filter = filter;
+  validate_data.ssrc = &ssrc;
+  validate_data.is_rtcp = &is_rtcp;
+
+  decode_data.filter = filter;
+  decode_data.pad = pad;
+
+  GST_OBJECT_LOCK (filter);
+
+  /* Check if this stream exists, if not create a new stream */
+  gst_buffer_list_foreach (buf_list, validate_buffer_it, &validate_data);
+
+  if (!gst_buffer_list_length (buf_list)) {
+    GST_OBJECT_LOCK (filter);
+    gst_buffer_list_unref (buf_list);
+    return GST_FLOW_OK;
+  }
+
+  if (!STREAM_HAS_CRYPTO (stream)) {
+    GST_OBJECT_UNLOCK (filter);
+    goto push_out;
+  }
+
+  decode_data.ssrc = ssrc;
+  decode_data.is_rtcp = is_rtcp;
+
+  gst_buffer_list_foreach (buf_list, decode_buffer_it, &decode_data);
+
+  GST_OBJECT_UNLOCK (filter);
+
+  if (!gst_buffer_list_length (buf_list)) {
+    gst_buffer_list_unref (buf_list);
+    return GST_FLOW_OK;
+  }
+
+  /* If all is well, we may have reached soft limit */
+  if (gst_srtp_get_soft_limit_reached ())
+    request_key_with_signal (filter, ssrc, SIGNAL_SOFT_LIMIT);
+
+push_out:
+  /* Push buffer list to source pad */
+  if (is_rtcp) {
+    otherpad = filter->rtcp_srcpad;
+    if (!filter->rtcp_has_segment)
+      gst_srtp_dec_push_early_events (filter, filter->rtcp_srcpad,
+          filter->rtp_srcpad, TRUE);
+  } else {
+    otherpad = filter->rtp_srcpad;
+    if (!filter->rtp_has_segment)
+      gst_srtp_dec_push_early_events (filter, filter->rtp_srcpad,
+          filter->rtcp_srcpad, FALSE);
+  }
+
+  GST_LOG_OBJECT (pad, "Pushing buffer chain of %d",
+      gst_buffer_list_length (buf_list));
+  ret = gst_pad_push_list (otherpad, buf_list);
+
+  return ret;
+}
+
 static GstFlowReturn
 gst_srtp_dec_chain_rtp (GstPad * pad, GstObject * parent, GstBuffer * buf)
 {
@@ -1159,6 +1325,21 @@
   return gst_srtp_dec_chain (pad, parent, buf, TRUE);
 }
 
+static GstFlowReturn
+gst_srtp_dec_chain_list_rtp (GstPad * pad, GstObject * parent,
+    GstBufferList * buf_list)
+{
+  return gst_srtp_dec_chain_list (pad, parent, buf_list, FALSE);
+}
+
+static GstFlowReturn
+gst_srtp_dec_chain_list_rtcp (GstPad * pad, GstObject * parent,
+    GstBufferList * buf_list)
+{
+  return gst_srtp_dec_chain_list (pad, parent, buf_list, TRUE);
+}
+
+
 static GstStateChangeReturn
 gst_srtp_dec_change_state (GstElement * element, GstStateChange transition)
 {
diff --git a/ext/srtp/gstsrtpenc.c b/ext/srtp/gstsrtpenc.c
index 20d3e36..8489da4 100644
--- a/ext/srtp/gstsrtpenc.c
+++ b/ext/srtp/gstsrtpenc.c
@@ -162,6 +162,20 @@
   PROP_ALLOW_REPEAT_TX
 };
 
+typedef struct ValidateBufferItData
+{
+  GstSrtpEnc *filter;
+  gboolean is_rtcp;
+} ValidateBufferItData;
+
+typedef struct ProcessBufferItData
+{
+  GstSrtpEnc *filter;
+  GstPad *pad;
+  GstBufferList *out_list;
+  gboolean is_rtcp;
+} ProcessBufferItData;
+
 /* the capabilities of the inputs and outputs.
  *
  * describe the real formats here.
@@ -219,6 +233,10 @@
     GstBuffer * buf);
 static GstFlowReturn gst_srtp_enc_chain_rtcp (GstPad * pad, GstObject * parent,
     GstBuffer * buf);
+static GstFlowReturn gst_srtp_enc_chain_list_rtp (GstPad * pad,
+    GstObject * parent, GstBufferList * buf);
+static GstFlowReturn gst_srtp_enc_chain_list_rtcp (GstPad * pad,
+    GstObject * parent, GstBufferList * buf);
 
 static gboolean gst_srtp_enc_sink_event_rtp (GstPad * pad, GstObject * parent,
     GstEvent * event);
@@ -389,6 +407,8 @@
 }
 
 /* Create stream
+ *
+ * Should be called with the filter locked
  */
 static err_status_t
 gst_srtp_enc_create_session (GstSrtpEnc * filter)
@@ -400,30 +420,26 @@
 
   memset (&policy, 0, sizeof (srtp_policy_t));
 
-  GST_OBJECT_LOCK (filter);
-
   if (HAS_CRYPTO (filter)) {
     guint expected;
     gsize keysize;
 
     if (filter->key == NULL) {
-      GST_OBJECT_UNLOCK (filter);
       GST_ELEMENT_ERROR (filter, LIBRARY, SETTINGS,
           ("Cipher is not NULL, key must be set"),
           ("Cipher is not NULL, key must be set"));
-      return FALSE;
+      return err_status_fail;
     }
 
     expected = max_cipher_key_size (filter);
     keysize = gst_buffer_get_size (filter->key);
 
     if (expected != keysize) {
-      GST_OBJECT_UNLOCK (filter);
       GST_ELEMENT_ERROR (filter, LIBRARY, SETTINGS,
           ("Master key size is wrong"),
           ("Expected master key of %d bytes, but received %" G_GSIZE_FORMAT
               " bytes", expected, keysize));
-      return FALSE;
+      return err_status_fail;
     }
   }
 
@@ -457,24 +473,26 @@
   if (HAS_CRYPTO (filter))
     gst_buffer_unmap (filter->key, &map);
 
-  GST_OBJECT_UNLOCK (filter);
-
   return ret;
 }
 
 /* Release ressources and set default values
  */
 static void
-gst_srtp_enc_reset (GstSrtpEnc * filter)
+gst_srtp_enc_reset_no_lock (GstSrtpEnc * filter)
 {
-  GST_OBJECT_LOCK (filter);
-
   if (!filter->first_session)
     srtp_dealloc (filter->session);
 
   filter->first_session = TRUE;
   filter->key_changed = FALSE;
+}
 
+static void
+gst_srtp_enc_reset (GstSrtpEnc * filter)
+{
+  GST_OBJECT_LOCK (filter);
+  gst_srtp_enc_reset_no_lock (filter);
   GST_OBJECT_UNLOCK (filter);
 }
 
@@ -509,6 +527,8 @@
       GST_DEBUG_FUNCPTR (gst_srtp_enc_iterate_internal_links_rtp));
   gst_pad_set_chain_function (sinkpad,
       GST_DEBUG_FUNCPTR (gst_srtp_enc_chain_rtp));
+  gst_pad_set_chain_list_function (sinkpad,
+      GST_DEBUG_FUNCPTR (gst_srtp_enc_chain_list_rtp));
   gst_pad_set_event_function (sinkpad,
       GST_DEBUG_FUNCPTR (gst_srtp_enc_sink_event_rtp));
   gst_pad_set_active (sinkpad, TRUE);
@@ -553,6 +573,8 @@
       GST_DEBUG_FUNCPTR (gst_srtp_enc_iterate_internal_links_rtcp));
   gst_pad_set_chain_function (sinkpad,
       GST_DEBUG_FUNCPTR (gst_srtp_enc_chain_rtcp));
+  gst_pad_set_chain_list_function (sinkpad,
+      GST_DEBUG_FUNCPTR (gst_srtp_enc_chain_list_rtcp));
   gst_pad_set_event_function (sinkpad,
       GST_DEBUG_FUNCPTR (gst_srtp_enc_sink_event_rtcp));
   gst_pad_set_active (sinkpad, TRUE);
@@ -948,27 +970,17 @@
   filter->key_changed = TRUE;
 }
 
-static GstFlowReturn
-gst_srtp_enc_chain (GstPad * pad, GstObject * parent, GstBuffer * buf,
+static gboolean
+gst_srtp_enc_check_buffer (GstSrtpEnc * filter, GstBuffer * buf,
     gboolean is_rtcp)
 {
-  GstSrtpEnc *filter = GST_SRTP_ENC (parent);
-  GstFlowReturn ret = GST_FLOW_OK;
-  GstPad *otherpad = NULL;
-  err_status_t err = err_status_ok;
-  gint size_max, size;
-  GstBuffer *bufout = NULL;
-  gboolean do_setcaps = FALSE;
-  GstMapInfo mapin, mapout;
-
   if (!is_rtcp) {
     GstRTPBuffer rtpbuf = GST_RTP_BUFFER_INIT;
 
     if (!gst_rtp_buffer_map (buf, GST_MAP_READ, &rtpbuf)) {
       GST_ELEMENT_ERROR (filter, STREAM, WRONG_TYPE, (NULL),
           ("Could not map RTP buffer"));
-      ret = GST_FLOW_ERROR;
-      goto out;
+      return FALSE;
     }
 
     gst_rtp_buffer_unmap (&rtpbuf);
@@ -978,61 +990,75 @@
     if (!gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcpbuf)) {
       GST_ELEMENT_ERROR (filter, STREAM, WRONG_TYPE, (NULL),
           ("Could not map RTCP buffer"));
-      ret = GST_FLOW_ERROR;
-      goto out;
+      return FALSE;
     }
     gst_rtcp_buffer_unmap (&rtcpbuf);
   }
 
-  do_setcaps = filter->key_changed;
-  if (filter->key_changed)
-    gst_srtp_enc_reset (filter);
+  return TRUE;
+}
+
+static GstFlowReturn
+gst_srtp_enc_check_set_caps (GstSrtpEnc * filter, GstPad * pad,
+    gboolean is_rtcp)
+{
+  gboolean do_setcaps = FALSE;
+
+  GST_OBJECT_LOCK (filter);
+
+  if (filter->key_changed) {
+    gst_srtp_enc_reset_no_lock (filter);
+    do_setcaps = TRUE;
+  }
+
   if (filter->first_session) {
     err_status_t status = gst_srtp_enc_create_session (filter);
+
     if (status != err_status_ok) {
+      GST_OBJECT_UNLOCK (filter);
       GST_ELEMENT_ERROR (filter, LIBRARY, INIT,
           ("Could not initialize SRTP encoder"),
           ("Failed to add stream to SRTP encoder (err: %d)", status));
-      ret = GST_FLOW_ERROR;
-      goto out;
+      return GST_FLOW_ERROR;
     }
   }
-  GST_OBJECT_LOCK (filter);
+
+  GST_OBJECT_UNLOCK (filter);
 
   /* Update source caps if asked */
   if (do_setcaps) {
     GstCaps *caps;
-    GST_OBJECT_UNLOCK (filter);
 
     caps = gst_pad_get_current_caps (pad);
     if (!gst_srtp_enc_sink_setcaps (pad, filter, caps, is_rtcp)) {
       gst_caps_unref (caps);
-      ret = GST_FLOW_NOT_NEGOTIATED;
-      goto out;
+      return GST_FLOW_NOT_NEGOTIATED;
     }
     gst_caps_unref (caps);
-
-    GST_OBJECT_LOCK (filter);
   }
 
-  if (!HAS_CRYPTO (filter)) {
-    GST_OBJECT_UNLOCK (filter);
-    otherpad = get_rtp_other_pad (pad);
-    return gst_pad_push (otherpad, buf);
-  }
+  return GST_FLOW_OK;
+}
 
+static GstBuffer *
+gst_srtp_enc_process_buffer (GstSrtpEnc * filter, GstPad * pad,
+    GstBuffer * buf, gboolean is_rtcp)
+{
+  gint size_max, size;
+  GstBuffer *bufout = NULL;
+  GstMapInfo mapout;
+  err_status_t err;
 
   /* Create a bigger buffer to add protection */
-  size_max = gst_buffer_get_size (buf) + SRTP_MAX_TRAILER_LEN + 10;
+  size = gst_buffer_get_size (buf);
+  size_max = size + SRTP_MAX_TRAILER_LEN + 10;
   bufout = gst_buffer_new_allocate (NULL, size_max, NULL);
 
-  gst_buffer_map (buf, &mapin, GST_MAP_READ);
   gst_buffer_map (bufout, &mapout, GST_MAP_READWRITE);
 
-  size = mapin.size;
-  memcpy (mapout.data, mapin.data, mapin.size);
+  gst_buffer_extract (buf, 0, mapout.data, size);
 
-  gst_buffer_unmap (buf, &mapin);
+  GST_OBJECT_LOCK (filter);
 
   gst_srtp_init_event_reporter ();
 
@@ -1041,18 +1067,67 @@
   else
     err = srtp_protect (filter->session, mapout.data, &size);
 
-  gst_buffer_unmap (bufout, &mapout);
-
   GST_OBJECT_UNLOCK (filter);
 
+  gst_buffer_unmap (bufout, &mapout);
+
   if (err == err_status_ok) {
     /* Buffer protected */
     gst_buffer_set_size (bufout, size);
     gst_buffer_copy_into (bufout, buf, GST_BUFFER_COPY_METADATA, 0, -1);
 
-    GST_LOG_OBJECT (pad, "Encing %s buffer of size %d",
+    GST_LOG_OBJECT (pad, "Encoding %s buffer of size %d",
         is_rtcp ? "RTCP" : "RTP", size);
 
+  } else if (err == err_status_key_expired) {
+
+    GST_ELEMENT_ERROR (GST_ELEMENT_CAST (filter), STREAM, ENCODE,
+        ("Key usage limit has been reached"),
+        ("Unable to protect buffer (hard key usage limit reached)"));
+    goto fail;
+
+  } else {
+    /* srtp_protect failed */
+    GST_ELEMENT_ERROR (filter, LIBRARY, FAILED, (NULL),
+        ("Unable to protect buffer (protect failed) code %d", err));
+    goto fail;
+  }
+
+  return bufout;
+
+fail:
+  gst_buffer_unref (bufout);
+  return NULL;
+}
+
+static GstFlowReturn
+gst_srtp_enc_chain (GstPad * pad, GstObject * parent, GstBuffer * buf,
+    gboolean is_rtcp)
+{
+  GstSrtpEnc *filter = GST_SRTP_ENC (parent);
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstPad *otherpad;
+  GstBuffer *bufout = NULL;
+
+  if (!gst_srtp_enc_check_buffer (filter, buf, is_rtcp)) {
+    goto fail;
+  }
+
+  if ((ret = gst_srtp_enc_check_set_caps (filter, pad, is_rtcp)) != GST_FLOW_OK) {
+    goto out;
+  }
+
+  GST_OBJECT_LOCK (filter);
+
+  if (!HAS_CRYPTO (filter)) {
+    GST_OBJECT_UNLOCK (filter);
+    otherpad = get_rtp_other_pad (pad);
+    return gst_pad_push (otherpad, buf);
+  }
+
+  GST_OBJECT_UNLOCK (filter);
+
+  if ((bufout = gst_srtp_enc_process_buffer (filter, pad, buf, is_rtcp))) {
     /* Push buffer to source pad */
     otherpad = get_rtp_other_pad (pad);
     ret = gst_pad_push (otherpad, bufout);
@@ -1060,29 +1135,22 @@
 
     if (ret != GST_FLOW_OK)
       goto out;
-
-  } else if (err == err_status_key_expired) {
-
-    GST_ELEMENT_ERROR (GST_ELEMENT_CAST (filter), STREAM, ENCODE,
-        ("Key usage limit has been reached"),
-        ("Unable to protect buffer (hard key usage limit reached)"));
-    gst_buffer_unref (bufout);
-    goto fail;
-
   } else {
-    /* srtp_protect failed */
-    GST_ELEMENT_ERROR (filter, LIBRARY, FAILED, (NULL),
-        ("Unable to protect buffer (protect failed) code %d", err));
-    gst_buffer_unref (bufout);
     goto fail;
   }
 
+  GST_OBJECT_LOCK (filter);
+
   if (gst_srtp_get_soft_limit_reached ()) {
+    GST_OBJECT_UNLOCK (filter);
     g_signal_emit (filter, gst_srtp_enc_signals[SIGNAL_SOFT_LIMIT], 0);
+    GST_OBJECT_LOCK (filter);
     if (filter->random_key && !filter->key_changed)
       gst_srtp_enc_replace_random_key (filter);
   }
 
+  GST_OBJECT_UNLOCK (filter);
+
 out:
 
   gst_buffer_unref (buf);
@@ -1094,6 +1162,115 @@
   goto out;
 }
 
+static gboolean
+validate_buffer_it (GstBuffer ** buffer, guint index, gpointer user_data)
+{
+  ValidateBufferItData *data = user_data;
+
+  if (!gst_srtp_enc_check_buffer (data->filter, *buffer, data->is_rtcp)) {
+    GST_WARNING_OBJECT (data->filter, "Invalid buffer, dropping");
+    gst_buffer_replace (buffer, NULL);
+  }
+
+  return TRUE;
+}
+
+static gboolean
+process_buffer_it (GstBuffer ** buffer, guint index, gpointer user_data)
+{
+  ProcessBufferItData *data = user_data;
+  GstBuffer *bufout;
+
+  if ((bufout =
+          gst_srtp_enc_process_buffer (data->filter, data->pad, *buffer,
+              data->is_rtcp))) {
+    gst_buffer_list_add (data->out_list, bufout);
+  } else {
+    GST_WARNING_OBJECT (data->filter, "Error encoding buffer, dropping");
+  }
+
+  return TRUE;
+}
+
+static GstFlowReturn
+gst_srtp_enc_chain_list (GstPad * pad, GstObject * parent,
+    GstBufferList * buf_list, gboolean is_rtcp)
+{
+  GstSrtpEnc *filter = GST_SRTP_ENC (parent);
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstPad *otherpad;
+  GstBufferList *out_list = NULL;
+  ValidateBufferItData validate_data;
+  ProcessBufferItData process_data;
+
+  validate_data.filter = filter;
+  validate_data.is_rtcp = is_rtcp;
+
+  GST_LOG_OBJECT (pad, "Buffer chain with list of %d",
+      gst_buffer_list_length (buf_list));
+
+  gst_buffer_list_foreach (buf_list, validate_buffer_it, &validate_data);
+
+  if (!gst_buffer_list_length (buf_list))
+    goto out;
+
+  if ((ret = gst_srtp_enc_check_set_caps (filter, pad, is_rtcp)) != GST_FLOW_OK)
+    goto out;
+
+  GST_OBJECT_LOCK (filter);
+
+  if (!HAS_CRYPTO (filter)) {
+    GST_OBJECT_UNLOCK (filter);
+    otherpad = get_rtp_other_pad (pad);
+    return gst_pad_push_list (otherpad, buf_list);
+  }
+
+  GST_OBJECT_UNLOCK (filter);
+
+  out_list = gst_buffer_list_new ();
+
+  process_data.filter = filter;
+  process_data.pad = pad;
+  process_data.is_rtcp = is_rtcp;
+  process_data.out_list = out_list;
+
+  gst_buffer_list_foreach (buf_list, process_buffer_it, &process_data);
+
+  if (!gst_buffer_list_length (out_list)) {
+    gst_buffer_list_unref (out_list);
+    ret = GST_FLOW_OK;
+    goto out;
+  }
+
+  /* Push buffer to source pad */
+  otherpad = get_rtp_other_pad (pad);
+  GST_LOG_OBJECT (pad, "Pushing buffer chain of %d",
+      gst_buffer_list_length (buf_list));
+  ret = gst_pad_push_list (otherpad, out_list);
+
+  if (ret != GST_FLOW_OK) {
+    goto out;
+  }
+
+  GST_OBJECT_LOCK (filter);
+
+  if (gst_srtp_get_soft_limit_reached ()) {
+    GST_OBJECT_UNLOCK (filter);
+    g_signal_emit (filter, gst_srtp_enc_signals[SIGNAL_SOFT_LIMIT], 0);
+    GST_OBJECT_LOCK (filter);
+    if (filter->random_key && !filter->key_changed)
+      gst_srtp_enc_replace_random_key (filter);
+  }
+
+  GST_OBJECT_UNLOCK (filter);
+
+out:
+
+  gst_buffer_list_unref (buf_list);
+
+  return ret;
+}
+
 static GstFlowReturn
 gst_srtp_enc_chain_rtp (GstPad * pad, GstObject * parent, GstBuffer * buf)
 {
@@ -1106,6 +1283,20 @@
   return gst_srtp_enc_chain (pad, parent, buf, TRUE);
 }
 
+static GstFlowReturn
+gst_srtp_enc_chain_list_rtp (GstPad * pad, GstObject * parent,
+    GstBufferList * buf_list)
+{
+  return gst_srtp_enc_chain_list (pad, parent, buf_list, FALSE);
+}
+
+static GstFlowReturn
+gst_srtp_enc_chain_list_rtcp (GstPad * pad, GstObject * parent,
+    GstBufferList * buf_list)
+{
+  return gst_srtp_enc_chain_list (pad, parent, buf_list, TRUE);
+}
+
 
 /* Change state
  */
@@ -1138,8 +1329,10 @@
             "RTCP authentication can't be NULL if encryption is not NULL.");
         return GST_STATE_CHANGE_FAILURE;
       }
+      GST_OBJECT_LOCK (filter);
       if (!filter->first_session)
-        gst_srtp_enc_reset (filter);
+        gst_srtp_enc_reset_no_lock (filter);
+      GST_OBJECT_UNLOCK (filter);
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
       break;
diff --git a/ext/x265/Makefile.am b/ext/x265/Makefile.am
index d2a8102..0f1e7f5 100644
--- a/ext/x265/Makefile.am
+++ b/ext/x265/Makefile.am
@@ -15,18 +15,3 @@
 libgstx265_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
 
 noinst_HEADERS = gstx265enc.h
-
-Android.mk: Makefile.am $(BUILT_SOURCES)
-	androgenizer \
-	-:PROJECT libgstx265 -:SHARED libgstx265 \
-	 -:TAGS eng debug \
-         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgstx265_la_SOURCES) \
-	 -:CPPFLAGS $(CPPFLAGS) \
-	 -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstx265_la_CFLAGS) -I'$$(GSTREAMER_AGGREGATE_TOP)/x265' \
-	 -:LDFLAGS $(libgstx265_la_LDFLAGS) \
-	           $(libgstx265_la_LIBADD) \
-	           -ldl \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-		       LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
-	> $@
diff --git a/ext/x265/Makefile.in b/ext/x265/Makefile.in
index 712244b..0fadad9 100644
--- a/ext/x265/Makefile.in
+++ b/ext/x265/Makefile.in
@@ -1077,21 +1077,6 @@
 	uninstall-pluginLTLIBRARIES
 
 
-Android.mk: Makefile.am $(BUILT_SOURCES)
-	androgenizer \
-	-:PROJECT libgstx265 -:SHARED libgstx265 \
-	 -:TAGS eng debug \
-         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgstx265_la_SOURCES) \
-	 -:CPPFLAGS $(CPPFLAGS) \
-	 -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstx265_la_CFLAGS) -I'$$(GSTREAMER_AGGREGATE_TOP)/x265' \
-	 -:LDFLAGS $(libgstx265_la_LDFLAGS) \
-	           $(libgstx265_la_LIBADD) \
-	           -ldl \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-		       LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
-	> $@
-
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
diff --git a/gst-libs/gst/adaptivedemux/Makefile.am b/gst-libs/gst/adaptivedemux/Makefile.am
index 7ef8990..be4baac 100644
--- a/gst-libs/gst/adaptivedemux/Makefile.am
+++ b/gst-libs/gst/adaptivedemux/Makefile.am
@@ -20,17 +20,3 @@
 	-lgstapp-$(GST_API_VERSION) $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_LIBS)
 
 libgstadaptivedemux_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
-
-Android.mk: Makefile.am
-	androgenizer -:PROJECT libgstadaptivedemux -:STATIC libgstadaptivedemux-@GST_API_VERSION@ \
-	 -:TAGS eng debug \
-         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgstadaptivedemux_@GST_API_VERSION@_la_SOURCES) \
-	 -:CFLAGS $(DEFS) $(libgstadaptivedemux_@GST_API_VERSION@_la_CFLAGS) \
-	 -:LDFLAGS $(libgstadaptivedemux_@GST_API_VERSION@_la_LDFLAGS) \
-	           $(libgstadaptivedemux_@GST_API_VERSION@_la_LIBADD) \
-	           -ldl \
-	 -:HEADER_TARGET gstreamer-@GST_API_VERSION@/gst/adaptivedemux \
-	 -:HEADERS $(libgstadaptivedemuxinclude_HEADERS) \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-	> $@
diff --git a/gst-libs/gst/adaptivedemux/Makefile.in b/gst-libs/gst/adaptivedemux/Makefile.in
index b6ef985..9949cfa 100644
--- a/gst-libs/gst/adaptivedemux/Makefile.in
+++ b/gst-libs/gst/adaptivedemux/Makefile.in
@@ -1082,20 +1082,6 @@
 	tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES
 
 
-Android.mk: Makefile.am
-	androgenizer -:PROJECT libgstadaptivedemux -:STATIC libgstadaptivedemux-@GST_API_VERSION@ \
-	 -:TAGS eng debug \
-         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgstadaptivedemux_@GST_API_VERSION@_la_SOURCES) \
-	 -:CFLAGS $(DEFS) $(libgstadaptivedemux_@GST_API_VERSION@_la_CFLAGS) \
-	 -:LDFLAGS $(libgstadaptivedemux_@GST_API_VERSION@_la_LDFLAGS) \
-	           $(libgstadaptivedemux_@GST_API_VERSION@_la_LIBADD) \
-	           -ldl \
-	 -:HEADER_TARGET gstreamer-@GST_API_VERSION@/gst/adaptivedemux \
-	 -:HEADERS $(libgstadaptivedemuxinclude_HEADERS) \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-	> $@
-
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c
index cf4a317..655e03e 100644
--- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c
+++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c
@@ -75,7 +75,6 @@
 #include "gstadaptivedemux.h"
 #include "gst/gst-i18n-plugin.h"
 #include <gst/base/gstadapter.h>
-#include <gst/uridownloader/gsturidownloader.h>
 
 GST_DEBUG_CATEGORY (adaptivedemux_debug);
 #define GST_CAT_DEFAULT adaptivedemux_debug
@@ -107,7 +106,7 @@
 struct _GstAdaptiveDemuxPrivate
 {
   GstAdapter *input_adapter;
-  GstBuffer *manifest_buffer;
+  gboolean have_manifest;
 
   GstUriDownloader *downloader;
 
@@ -168,6 +167,8 @@
     GstAdaptiveDemuxStream * stream);
 static GstFlowReturn gst_adaptive_demux_update_manifest (GstAdaptiveDemux *
     demux);
+static GstFlowReturn
+gst_adaptive_demux_update_manifest_default (GstAdaptiveDemux * demux);
 static gboolean gst_adaptive_demux_has_next_period (GstAdaptiveDemux * demux);
 static void gst_adaptive_demux_advance_period (GstAdaptiveDemux * demux);
 
@@ -315,6 +316,7 @@
 
   klass->data_received = gst_adaptive_demux_stream_data_received_default;
   klass->finish_fragment = gst_adaptive_demux_stream_finish_fragment_default;
+  klass->update_manifest = gst_adaptive_demux_update_manifest_default;
 }
 
 static void
@@ -328,7 +330,7 @@
 
   demux->priv = GST_ADAPTIVE_DEMUX_GET_PRIVATE (demux);
   demux->priv->input_adapter = gst_adapter_new ();
-  demux->priv->downloader = gst_uri_downloader_new ();
+  demux->downloader = gst_uri_downloader_new ();
   demux->stream_struct_size = sizeof (GstAdaptiveDemuxStream);
 
   gst_segment_init (&demux->segment, GST_FORMAT_TIME);
@@ -372,7 +374,7 @@
   GST_DEBUG_OBJECT (object, "finalize");
 
   g_object_unref (priv->input_adapter);
-  g_object_unref (priv->downloader);
+  g_object_unref (demux->downloader);
 
   g_mutex_clear (&priv->updates_timed_lock);
   g_cond_clear (&priv->updates_timed_cond);
@@ -420,6 +422,7 @@
       gboolean query_res;
       gboolean ret = TRUE;
       gsize available;
+      GstBuffer *manifest_buffer;
 
       demux_class = GST_ADAPTIVE_DEMUX_GET_CLASS (demux);
       available = gst_adapter_available (demux->priv->input_adapter);
@@ -461,16 +464,19 @@
       gst_query_unref (query);
 
       /* Let the subclass parse the manifest */
-      demux->priv->manifest_buffer =
+      manifest_buffer =
           gst_adapter_take_buffer (demux->priv->input_adapter, available);
-      if (!demux_class->process_manifest (demux, demux->priv->manifest_buffer)) {
+      if (!demux_class->process_manifest (demux, manifest_buffer)) {
         /* In most cases, this will happen if we set a wrong url in the
          * source element and we have received the 404 HTML response instead of
          * the manifest */
         GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid manifest."),
             (NULL));
         ret = FALSE;
+      } else {
+        demux->priv->have_manifest = TRUE;
       }
+      gst_buffer_unref (manifest_buffer);
 
       gst_element_post_message (GST_ELEMENT_CAST (demux),
           gst_message_new_element (GST_OBJECT_CAST (demux),
@@ -553,7 +559,7 @@
   GList *iter;
 
   gst_adaptive_demux_stop_tasks (demux);
-  gst_uri_downloader_reset (demux->priv->downloader);
+  gst_uri_downloader_reset (demux->downloader);
 
   if (klass->reset)
     klass->reset (demux);
@@ -579,10 +585,7 @@
   demux->manifest_base_uri = NULL;
 
   gst_adapter_clear (demux->priv->input_adapter);
-  if (demux->priv->manifest_buffer) {
-    gst_buffer_unref (demux->priv->manifest_buffer);
-    demux->priv->manifest_buffer = NULL;
-  }
+  demux->priv->have_manifest = FALSE;
 
   gst_segment_init (&demux->segment, GST_FORMAT_TIME);
 
@@ -1102,7 +1105,8 @@
 
       GST_MANIFEST_LOCK (demux);
       gst_query_parse_duration (query, &fmt, NULL);
-      if (fmt == GST_FORMAT_TIME && demux->priv->manifest_buffer != NULL) {
+      if (fmt == GST_FORMAT_TIME && demux->priv->have_manifest
+          && !gst_adaptive_demux_is_live (demux)) {
         duration = demux_class->get_duration (demux);
 
         if (GST_CLOCK_TIME_IS_VALID (duration) && duration > 0) {
@@ -1116,13 +1120,7 @@
       break;
     }
     case GST_QUERY_LATENCY:{
-      gboolean live = FALSE;
-
-      GST_MANIFEST_LOCK (demux);
-      live = demux->priv->manifest_buffer && gst_adaptive_demux_is_live (demux);
-      GST_MANIFEST_UNLOCK (demux);
-
-      gst_query_set_latency (query, live, 0, -1);
+      gst_query_set_latency (query, FALSE, 0, -1);
       ret = TRUE;
       break;
     }
@@ -1132,8 +1130,10 @@
       gint64 start = 0;
 
       GST_MANIFEST_LOCK (demux);
-      if (demux->priv->manifest_buffer == NULL) {
+      if (!demux->priv->have_manifest) {
         GST_MANIFEST_UNLOCK (demux);
+        GST_INFO_OBJECT (demux,
+            "Don't have manifest yet, can't answer seeking query");
         return FALSE;           /* can't answer without manifest */
       }
 
@@ -1212,7 +1212,7 @@
   g_cond_broadcast (&demux->manifest_cond);
   GST_MANIFEST_UNLOCK (demux);
 
-  gst_uri_downloader_cancel (demux->priv->downloader);
+  gst_uri_downloader_cancel (demux->downloader);
   for (iter = demux->streams; iter; iter = g_list_next (iter)) {
     GstAdaptiveDemuxStream *stream = iter->data;
 
@@ -1974,38 +1974,27 @@
     GST_DEBUG_OBJECT (stream->pad,
         "Activating stream due to reconfigure event");
 
-    cur = stream->segment.position;
+    cur = ts = stream->segment.position;
 
     if (gst_pad_peer_query_position (stream->pad, GST_FORMAT_TIME, &pos)) {
       ts = (GstClockTime) pos;
       GST_DEBUG_OBJECT (demux, "Downstream position: %"
           GST_TIME_FORMAT, GST_TIME_ARGS (ts));
     } else {
-      gboolean have_pos = FALSE;
-
       /* query other pads as some faulty element in the pad's branch might
        * reject position queries. This should be better than using the
        * demux segment position that can be much ahead */
       for (GList * iter = demux->streams; iter != NULL;
           iter = g_list_next (iter)) {
-        GstAdaptiveDemuxStream *cur_stream = iter->data;
+        GstAdaptiveDemuxStream *cur_stream = (GstAdaptiveDemuxStream *)iter->data;
 
-        have_pos =
-            gst_pad_peer_query_position (cur_stream->pad, GST_FORMAT_TIME,
-            &pos);
-        if (have_pos) {
+        if (gst_pad_peer_query_position (cur_stream->pad, GST_FORMAT_TIME, &pos)) {
           ts = (GstClockTime) pos;
           GST_DEBUG_OBJECT (stream->pad, "Downstream position: %"
               GST_TIME_FORMAT, GST_TIME_ARGS (ts));
           break;
         }
       }
-
-      if (!have_pos) {
-        ts = stream->segment.position;
-        GST_DEBUG_OBJECT (stream->pad, "Downstream position query failed, "
-            "failling back to looking at other pads");
-      }
     }
 
     /* we might have already pushed this data */
@@ -2267,7 +2256,8 @@
             g_get_monotonic_time () +
             klass->get_manifest_update_interval (demux);
       } else {
-        GST_ERROR_OBJECT (demux, "Could not update playlist");
+        GST_ELEMENT_ERROR (demux, STREAM, FAILED,
+            (_("Internal data stream error.")), ("Could not update playlist"));
         goto error;
       }
     } else {
@@ -2291,7 +2281,7 @@
 error:
   {
     GST_DEBUG_OBJECT (demux, "Stopped updates task because of error");
-    gst_adaptive_demux_stop_tasks (demux);
+    gst_task_stop (demux->priv->updates_task);
   }
 }
 
@@ -2395,7 +2385,13 @@
 
   if (GST_CLOCK_TIME_IS_VALID (duration))
     stream->segment.position += duration;
-  ret = klass->stream_advance_fragment (stream);
+
+  if (gst_adaptive_demux_is_live (demux)
+      || gst_adaptive_demux_stream_has_next_fragment (demux, stream)) {
+    ret = klass->stream_advance_fragment (stream);
+  } else {
+    ret = GST_FLOW_EOS;
+  }
 
   stream->download_start_time = stream->download_chunk_start_time =
       g_get_monotonic_time ();
@@ -2464,17 +2460,16 @@
 }
 
 static GstFlowReturn
-gst_adaptive_demux_update_manifest (GstAdaptiveDemux * demux)
+gst_adaptive_demux_update_manifest_default (GstAdaptiveDemux * demux)
 {
   GstAdaptiveDemuxClass *klass = GST_ADAPTIVE_DEMUX_GET_CLASS (demux);
   GstFragment *download;
   GstBuffer *buffer;
   GstFlowReturn ret;
 
-  download = gst_uri_downloader_fetch_uri (demux->priv->downloader,
+  download = gst_uri_downloader_fetch_uri (demux->downloader,
       demux->manifest_uri, NULL, TRUE, TRUE, TRUE, NULL);
   if (download) {
-
     GST_MANIFEST_LOCK (demux);
     g_free (demux->manifest_uri);
     g_free (demux->manifest_base_uri);
@@ -2488,31 +2483,11 @@
 
     buffer = gst_fragment_get_buffer (download);
     g_object_unref (download);
-    ret = klass->update_manifest (demux, buffer);
-    if (ret == GST_FLOW_OK) {
-      GstClockTime duration;
-      gst_buffer_unref (demux->priv->manifest_buffer);
-      demux->priv->manifest_buffer = buffer;
-
-      /* Send an updated duration message */
-      duration = klass->get_duration (demux);
-
-      GST_MANIFEST_UNLOCK (demux);
-      if (duration != GST_CLOCK_TIME_NONE) {
-        GST_DEBUG_OBJECT (demux,
-            "Sending duration message : %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (duration));
-        gst_element_post_message (GST_ELEMENT (demux),
-            gst_message_new_duration_changed (GST_OBJECT (demux)));
-      } else {
-        GST_DEBUG_OBJECT (demux,
-            "Duration unknown, can not send the duration message");
-      }
-    } else {
-      GST_MANIFEST_UNLOCK (demux);
-      gst_buffer_unref (buffer);
-      /* Should the manifest uri vars be reverted to original values? */
-    }
+    ret = klass->update_manifest_data (demux, buffer);
+    gst_buffer_unref (buffer);
+    GST_MANIFEST_UNLOCK (demux);
+    /* FIXME: Should the manifest uri vars be reverted to original
+     * values if updating fails? */
   } else {
     ret = GST_FLOW_NOT_LINKED;
   }
@@ -2520,6 +2495,35 @@
   return ret;
 }
 
+static GstFlowReturn
+gst_adaptive_demux_update_manifest (GstAdaptiveDemux * demux)
+{
+  GstAdaptiveDemuxClass *klass = GST_ADAPTIVE_DEMUX_GET_CLASS (demux);
+  GstFlowReturn ret;
+
+  ret = klass->update_manifest (demux);
+
+  if (ret == GST_FLOW_OK) {
+    GstClockTime duration;
+    GST_MANIFEST_LOCK (demux);
+    /* Send an updated duration message */
+    duration = klass->get_duration (demux);
+    GST_MANIFEST_UNLOCK (demux);
+    if (duration != GST_CLOCK_TIME_NONE) {
+      GST_DEBUG_OBJECT (demux,
+          "Sending duration message : %" GST_TIME_FORMAT,
+          GST_TIME_ARGS (duration));
+      gst_element_post_message (GST_ELEMENT (demux),
+          gst_message_new_duration_changed (GST_OBJECT (demux)));
+    } else {
+      GST_DEBUG_OBJECT (demux,
+          "Duration unknown, can not send the duration message");
+    }
+  }
+
+  return ret;
+}
+
 void
 gst_adaptive_demux_stream_fragment_clear (GstAdaptiveDemuxStreamFragment * f)
 {
diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.h b/gst-libs/gst/adaptivedemux/gstadaptivedemux.h
index 36e20ef..9303a84 100644
--- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.h
+++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.h
@@ -24,6 +24,7 @@
 
 #include <gst/gst.h>
 #include <gst/base/gstadapter.h>
+#include <gst/uridownloader/gsturidownloader.h>
 
 G_BEGIN_DECLS
 
@@ -176,7 +177,7 @@
   /*< protected >*/
   GstPad         *sinkpad;
 
-  GstAdaptiveDemuxPrivate *priv;
+  GstUriDownloader *downloader;
 
   GList *streams;
   GList *next_streams;
@@ -198,6 +199,9 @@
 
   gboolean have_group_id;
   guint group_id;
+
+  /* < private > */
+  GstAdaptiveDemuxPrivate *priv;
 };
 
 /**
@@ -233,9 +237,23 @@
    * Returns: the update interval in microseconds
    */
   gint64        (*get_manifest_update_interval) (GstAdaptiveDemux * demux);
+
   /**
    * update_manifest:
    * @demux: #GstAdaptiveDemux
+   *
+   * During live streaming, this will be called for the subclass to update its
+   * manifest with the new version. By default it fetches the manifest URI
+   * and passes it to GstAdaptiveDemux::update_manifest_data().
+   *
+   * Returns: #GST_FLOW_OK is all succeeded, #GST_FLOW_EOS if the stream ended
+   *          or #GST_FLOW_ERROR if an error happened
+   */
+  GstFlowReturn (*update_manifest) (GstAdaptiveDemux * demux);
+
+  /**
+   * update_manifest_data:
+   * @demux: #GstAdaptiveDemux
    * @buf: Downloaded manifest data
    *
    * During live streaming, this will be called for the subclass to update its
@@ -244,7 +262,7 @@
    * Returns: #GST_FLOW_OK is all succeeded, #GST_FLOW_EOS if the stream ended
    *          or #GST_FLOW_ERROR if an error happened
    */
-  GstFlowReturn (*update_manifest) (GstAdaptiveDemux * demux, GstBuffer * buf);
+  GstFlowReturn (*update_manifest_data) (GstAdaptiveDemux * demux, GstBuffer * buf);
 
   gboolean      (*is_live)          (GstAdaptiveDemux * demux);
   GstClockTime  (*get_duration)     (GstAdaptiveDemux * demux);
diff --git a/gst-libs/gst/base/gstaggregator.c b/gst-libs/gst/base/gstaggregator.c
index 788c84a..4370ac2 100644
--- a/gst-libs/gst/base/gstaggregator.c
+++ b/gst-libs/gst/base/gstaggregator.c
@@ -54,6 +54,12 @@
  *    subclass, it should instead return GST_FLOW_EOS in its aggregate
  *    implementation.
  *  </para></listitem>
+ *  <listitem><para>
+ *    Note that the aggregator logic regarding gap event handling is to turn
+ *    these into gap buffers with matching PTS and duration. It will also
+ *    flag these buffers with GST_BUFFER_FLAG_GAP and GST_BUFFER_FLAG_DROPPABLE
+ *    to ease their identification and subsequent processing.
+ *  </para></listitem>
  * </itemizedlist>
  */
 
@@ -87,6 +93,8 @@
  */
 
 
+static GstClockTime gst_aggregator_get_latency_unlocked (GstAggregator * self);
+
 GST_DEBUG_CATEGORY_STATIC (aggregator_debug);
 #define GST_CAT_DEFAULT aggregator_debug
 
@@ -109,16 +117,16 @@
 
 
 #define PAD_WAIT_EVENT(pad)   G_STMT_START {                            \
-  GST_LOG_OBJECT (pad, "Waiting for EVENT on thread %p",                \
+  GST_LOG_OBJECT (pad, "Waiting for buffer to be consumed thread %p",   \
         g_thread_self());                                               \
   g_cond_wait(&(((GstAggregatorPad* )pad)->priv->event_cond),           \
       (&((GstAggregatorPad*)pad)->priv->lock));                         \
-  GST_LOG_OBJECT (pad, "DONE Waiting for EVENT on thread %p",           \
+  GST_LOG_OBJECT (pad, "DONE Waiting for buffer to be consumed on thread %p", \
         g_thread_self());                                               \
   } G_STMT_END
 
 #define PAD_BROADCAST_EVENT(pad) G_STMT_START {                        \
-  GST_LOG_OBJECT (pad, "Signaling EVENT from thread %p",               \
+  GST_LOG_OBJECT (pad, "Signaling buffer consumed from thread %p",     \
         g_thread_self());                                              \
   g_cond_broadcast(&(((GstAggregatorPad* )pad)->priv->event_cond));    \
   } G_STMT_END
@@ -174,10 +182,8 @@
 
 struct _GstAggregatorPadPrivate
 {
-  /* To always be used atomically */
-  gboolean flushing;
-
   /* Following fields are protected by the PAD_LOCK */
+  GstFlowReturn flow_return;
   gboolean pending_flush_start;
   gboolean pending_flush_stop;
   gboolean pending_eos;
@@ -199,8 +205,9 @@
   GstAggregatorPadClass *klass = GST_AGGREGATOR_PAD_GET_CLASS (aggpad);
 
   PAD_LOCK (aggpad);
+  aggpad->priv->pending_eos = FALSE;
   aggpad->priv->eos = FALSE;
-  aggpad->priv->flushing = FALSE;
+  aggpad->priv->flow_return = GST_FLOW_OK;
   PAD_UNLOCK (aggpad);
 
   if (klass->flush)
@@ -229,16 +236,16 @@
   gboolean flush_seeking;
   gboolean pending_flush_start;
   gboolean send_eos;            /* protected by srcpad stream lock */
-  GstFlowReturn flow_return;
 
   GstCaps *srccaps;             /* protected by the srcpad stream lock */
 
   GstTagList *tags;
   gboolean tags_changed;
 
-  gboolean latency_live;        /* protected by src_lock */
-  GstClockTime latency_min;     /* protected by src_lock */
-  GstClockTime latency_max;     /* protected by src_lock */
+  gboolean peer_latency_live;   /* protected by src_lock */
+  GstClockTime peer_latency_min;        /* protected by src_lock */
+  GstClockTime peer_latency_max;        /* protected by src_lock */
+  gboolean has_peer_latency;
 
   GstClockTime sub_latency_min; /* protected by src_lock */
   GstClockTime sub_latency_max; /* protected by src_lock */
@@ -397,7 +404,6 @@
 gst_aggregator_reset_flow_values (GstAggregator * self)
 {
   GST_OBJECT_LOCK (self);
-  self->priv->flow_return = GST_FLOW_FLUSHING;
   self->priv->send_stream_start = TRUE;
   self->priv->send_segment = TRUE;
   gst_segment_init (&self->segment, GST_FORMAT_TIME);
@@ -535,15 +541,15 @@
 static gboolean
 gst_aggregator_wait_and_check (GstAggregator * self, gboolean * timeout)
 {
-  GstClockTime latency_max, latency_min;
+  GstClockTime latency;
   GstClockTime start;
-  gboolean live, res;
+  gboolean res;
 
   *timeout = FALSE;
 
   SRC_LOCK (self);
 
-  gst_aggregator_get_latency_unlocked (self, &live, &latency_min, &latency_max);
+  latency = gst_aggregator_get_latency_unlocked (self);
 
   if (gst_aggregator_check_pads_ready (self)) {
     GST_DEBUG_OBJECT (self, "all pads have data");
@@ -561,8 +567,9 @@
 
   start = gst_aggregator_get_next_time (self);
 
-  if (!live || !GST_IS_CLOCK (GST_ELEMENT_CLOCK (self))
-      || !GST_CLOCK_TIME_IS_VALID (start)) {
+  if (!GST_CLOCK_TIME_IS_VALID (latency) ||
+      !GST_IS_CLOCK (GST_ELEMENT_CLOCK (self)) ||
+      !GST_CLOCK_TIME_IS_VALID (start)) {
     /* We wake up here when something happened, and below
      * then check if we're ready now. If we return FALSE,
      * we will be directly called again.
@@ -585,15 +592,14 @@
     GST_OBJECT_UNLOCK (self);
 
     time = base_time + start;
-    time += latency_min;
+    time += latency;
 
     GST_DEBUG_OBJECT (self, "possibly waiting for clock to reach %"
         GST_TIME_FORMAT " (base %" GST_TIME_FORMAT " start %" GST_TIME_FORMAT
-        " latency max %" GST_TIME_FORMAT " latency min %" GST_TIME_FORMAT
-        " current %" GST_TIME_FORMAT ")", GST_TIME_ARGS (time),
+        " latency %" GST_TIME_FORMAT " current %" GST_TIME_FORMAT ")",
+        GST_TIME_ARGS (time),
         GST_TIME_ARGS (GST_ELEMENT_CAST (self)->base_time),
-        GST_TIME_ARGS (start), GST_TIME_ARGS (latency_max),
-        GST_TIME_ARGS (latency_min),
+        GST_TIME_ARGS (start), GST_TIME_ARGS (latency),
         GST_TIME_ARGS (gst_clock_get_time (clock)));
 
 
@@ -630,6 +636,20 @@
 }
 
 static void
+gst_aggregator_pad_set_flushing (GstAggregatorPad * aggpad,
+    GstFlowReturn flow_return)
+{
+  PAD_LOCK (aggpad);
+  if (flow_return == GST_FLOW_NOT_LINKED)
+    aggpad->priv->flow_return = MIN (flow_return, aggpad->priv->flow_return);
+  else
+    aggpad->priv->flow_return = flow_return;
+  gst_buffer_replace (&aggpad->priv->buffer, NULL);
+  PAD_BROADCAST_EVENT (aggpad);
+  PAD_UNLOCK (aggpad);
+}
+
+static void
 gst_aggregator_aggregate_func (GstAggregator * self)
 {
   GstAggregatorPrivate *priv = self->priv;
@@ -653,10 +673,12 @@
     flow_return = klass->aggregate (self, timeout);
 
     GST_OBJECT_LOCK (self);
-    if (flow_return == GST_FLOW_FLUSHING && priv->flush_seeking)
-      priv->flow_return = GST_FLOW_OK;
-    else
-      priv->flow_return = flow_return;
+    if (flow_return == GST_FLOW_FLUSHING && priv->flush_seeking) {
+      /* We don't want to set the pads to flushing, but we want to
+       * stop the thread, so just break here */
+      GST_OBJECT_UNLOCK (self);
+      break;
+    }
     GST_OBJECT_UNLOCK (self);
 
     if (flow_return == GST_FLOW_EOS) {
@@ -665,8 +687,18 @@
 
     GST_LOG_OBJECT (self, "flow return is %s", gst_flow_get_name (flow_return));
 
-    if (flow_return != GST_FLOW_OK)
+    if (flow_return != GST_FLOW_OK) {
+      GList *item;
+
+      GST_OBJECT_LOCK (self);
+      for (item = GST_ELEMENT (self)->sinkpads; item; item = item->next) {
+        GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (item->data);
+
+        gst_aggregator_pad_set_flushing (aggpad, flow_return);
+      }
+      GST_OBJECT_UNLOCK (self);
       break;
+    }
   }
 
   /* Pause the task here, the only ways to get here are:
@@ -690,7 +722,6 @@
   self->priv->send_segment = TRUE;
   self->priv->send_eos = TRUE;
   self->priv->srccaps = NULL;
-  self->priv->flow_return = GST_FLOW_OK;
 
   klass = GST_AGGREGATOR_GET_CLASS (self);
 
@@ -794,10 +825,7 @@
   GstAggregatorPrivate *priv = self->priv;
   GstAggregatorPadPrivate *padpriv = aggpad->priv;
 
-  g_atomic_int_set (&aggpad->priv->flushing, TRUE);
-
-  /*  Remove pad buffer and wake up the streaming thread */
-  gst_aggregator_pad_drop_buffer (aggpad);
+  gst_aggregator_pad_set_flushing (aggpad, GST_FLOW_FLUSHING);
 
   PAD_FLUSH_LOCK (aggpad);
   PAD_LOCK (aggpad);
@@ -818,7 +846,6 @@
 
       GST_INFO_OBJECT (self, "Flushing, pausing srcpad task");
       gst_aggregator_stop_srcpad_task (self, event);
-      priv->flow_return = GST_FLOW_OK;
 
       GST_INFO_OBJECT (self, "Getting STREAM_LOCK while seeking");
       GST_PAD_STREAM_LOCK (self->srcpad);
@@ -925,9 +952,23 @@
     }
     case GST_EVENT_GAP:
     {
-      /* FIXME: need API to handle GAP events properly */
-      GST_FIXME_OBJECT (self, "implement support for GAP events");
-      /* don't forward GAP events downstream */
+      GstClockTime pts;
+      GstClockTime duration;
+      GstBuffer *gapbuf;
+
+      gst_event_parse_gap (event, &pts, &duration);
+      gapbuf = gst_buffer_new ();
+
+      GST_BUFFER_PTS (gapbuf) = pts;
+      GST_BUFFER_DURATION (gapbuf) = duration;
+      GST_BUFFER_FLAG_SET (gapbuf, GST_BUFFER_FLAG_GAP);
+      GST_BUFFER_FLAG_SET (gapbuf, GST_BUFFER_FLAG_DROPPABLE);
+
+      if (gst_pad_chain (pad, gapbuf) != GST_FLOW_OK) {
+        GST_WARNING_OBJECT (self, "Failed to chain gap buffer");
+        res = FALSE;
+      }
+
       goto eat;
     }
     case GST_EVENT_TAG:
@@ -987,6 +1028,10 @@
   else
     result = TRUE;
 
+  agg->priv->has_peer_latency = FALSE;
+  agg->priv->peer_latency_live = FALSE;
+  agg->priv->peer_latency_min = agg->priv->peer_latency_max = FALSE;
+
   if (agg->priv->tags)
     gst_tag_list_unref (agg->priv->tags);
   agg->priv->tags = NULL;
@@ -1046,14 +1091,12 @@
 gst_aggregator_release_pad (GstElement * element, GstPad * pad)
 {
   GstAggregator *self = GST_AGGREGATOR (element);
-
   GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
 
   GST_INFO_OBJECT (pad, "Removing pad");
 
   SRC_LOCK (self);
-  g_atomic_int_set (&aggpad->priv->flushing, TRUE);
-  gst_aggregator_pad_drop_buffer (aggpad);
+  gst_aggregator_pad_set_flushing (aggpad, GST_FLOW_FLUSHING);
   gst_element_remove_pad (element, pad);
 
   SRC_BROADCAST (self);
@@ -1110,8 +1153,10 @@
   return GST_PAD (agg_pad);
 }
 
+/* Must be called with SRC_LOCK held */
+
 static gboolean
-gst_aggregator_query_latency (GstAggregator * self, GstQuery * query)
+gst_aggregator_query_latency_unlocked (GstAggregator * self, GstQuery * query)
 {
   gboolean query_ret, live;
   GstClockTime our_latency, min, max;
@@ -1125,13 +1170,11 @@
 
   gst_query_parse_latency (query, &live, &min, &max);
 
-  SRC_LOCK (self);
   our_latency = self->priv->latency;
 
   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (min))) {
     GST_ERROR_OBJECT (self, "Invalid minimum latency %" GST_TIME_FORMAT
         ". Please file a bug at " PACKAGE_BUGREPORT ".", GST_TIME_ARGS (min));
-    SRC_UNLOCK (self);
     return FALSE;
   }
 
@@ -1140,13 +1183,13 @@
         ("Impossible to configure latency: max %" GST_TIME_FORMAT " < min %"
             GST_TIME_FORMAT ". Add queues or other buffering elements.",
             GST_TIME_ARGS (max), GST_TIME_ARGS (min)));
-    SRC_UNLOCK (self);
     return FALSE;
   }
 
-  self->priv->latency_live = live;
-  self->priv->latency_min = min;
-  self->priv->latency_max = max;
+  self->priv->peer_latency_live = live;
+  self->priv->peer_latency_min = min;
+  self->priv->peer_latency_max = max;
+  self->priv->has_peer_latency = TRUE;
 
   /* add our own */
   min += our_latency;
@@ -1160,7 +1203,7 @@
   if (live && min > max) {
     GST_ELEMENT_WARNING (self, CORE, NEGOTIATION,
         ("%s", "Latency too big"),
-        ("The requested latency value is too big for the current pipeline.  "
+        ("The requested latency value is too big for the current pipeline. "
             "Limiting to %" G_GINT64_FORMAT, max));
     min = max;
     /* FIXME: This could in theory become negative, but in
@@ -1170,7 +1213,6 @@
   }
 
   SRC_BROADCAST (self);
-  SRC_UNLOCK (self);
 
   GST_DEBUG_OBJECT (self, "configured latency live:%s min:%" G_GINT64_FORMAT
       " max:%" G_GINT64_FORMAT, live ? "true" : "false", min, max);
@@ -1180,47 +1222,63 @@
   return query_ret;
 }
 
-/**
- * gst_aggregator_get_latency_unlocked:
- * @self: a #GstAggregator
- * @live: (out) (allow-none): whether @self is live
- * @min_latency: (out) (allow-none): the configured minimum latency of @self
- * @max_latency: (out) (allow-none): the configured maximum latency of @self
+/*
+ * MUST be called with the src_lock held.
  *
- * Retreives the latency values reported by @self in response to the latency
- * query.
+ * See  gst_aggregator_get_latency() for doc
+ */
+static GstClockTime
+gst_aggregator_get_latency_unlocked (GstAggregator * self)
+{
+  GstClockTime latency;
+
+  g_return_val_if_fail (GST_IS_AGGREGATOR (self), 0);
+
+  if (!self->priv->has_peer_latency) {
+    GstQuery *query = gst_query_new_latency ();
+    gboolean ret;
+
+    ret = gst_aggregator_query_latency_unlocked (self, query);
+    gst_query_unref (query);
+    if (!ret)
+      return GST_CLOCK_TIME_NONE;
+  }
+
+  if (!self->priv->has_peer_latency || !self->priv->peer_latency_live)
+    return GST_CLOCK_TIME_NONE;
+
+  /* latency_min is never GST_CLOCK_TIME_NONE by construction */
+  latency = self->priv->peer_latency_min;
+
+  /* add our own */
+  latency += self->priv->latency;
+  latency += self->priv->sub_latency_min;
+
+  return latency;
+}
+
+/**
+ * gst_aggregator_get_latency:
+ * @self: a #GstAggregator
+ *
+ * Retrieves the latency values reported by @self in response to the latency
+ * query, or %GST_CLOCK_TIME_NONE if there is not live source connected and the element
+ * will not wait for the clock.
  *
  * Typically only called by subclasses.
  *
- * MUST be called with the src_lock held.
+ * Returns: The latency or %GST_CLOCK_TIME_NONE if the element does not sync
  */
-void
-gst_aggregator_get_latency_unlocked (GstAggregator * self, gboolean * live,
-    GstClockTime * min_latency, GstClockTime * max_latency)
+GstClockTime
+gst_aggregator_get_latency (GstAggregator * self)
 {
-  GstClockTime min, max;
+  GstClockTime ret;
 
-  g_return_if_fail (GST_IS_AGGREGATOR (self));
+  SRC_LOCK (self);
+  ret = gst_aggregator_get_latency_unlocked (self);
+  SRC_UNLOCK (self);
 
-  /* latency_min is never GST_CLOCK_TIME_NONE by construction */
-  min = self->priv->latency_min;
-  max = self->priv->latency_max;
-
-  /* add our own */
-  min += self->priv->latency;
-  min += self->priv->sub_latency_min;
-  if (GST_CLOCK_TIME_IS_VALID (max)
-      && GST_CLOCK_TIME_IS_VALID (self->priv->sub_latency_max))
-    max += self->priv->sub_latency_max;
-  else
-    max = GST_CLOCK_TIME_NONE;
-
-  if (live)
-    *live = self->priv->latency_live;
-  if (min_latency)
-    *min_latency = min;
-  if (max_latency)
-    *max_latency = max;
+  return ret;
 }
 
 static gboolean
@@ -1271,17 +1329,17 @@
       gst_query_set_seeking (query, format, FALSE, 0, -1);
       res = TRUE;
 
-      goto discard;
+      break;
     }
     case GST_QUERY_LATENCY:
-      return gst_aggregator_query_latency (self, query);
-    default:
+      SRC_LOCK (self);
+      res = gst_aggregator_query_latency_unlocked (self, query);
+      SRC_UNLOCK (self);
       break;
+    default:
+      return gst_pad_query_default (self->srcpad, GST_OBJECT (self), query);
   }
 
-  return gst_pad_query_default (self->srcpad, GST_OBJECT (self), query);
-
-discard:
   return res;
 }
 
@@ -1549,9 +1607,9 @@
   g_return_if_fail (GST_CLOCK_TIME_IS_VALID (latency));
 
   SRC_LOCK (self);
-  if (self->priv->latency_live) {
-    min = self->priv->latency_min;
-    max = self->priv->latency_max;
+  if (self->priv->peer_latency_live) {
+    min = self->priv->peer_latency_min;
+    max = self->priv->peer_latency_max;
     /* add our own */
     min += latency;
     min += self->priv->sub_latency_min;
@@ -1707,9 +1765,10 @@
   priv->padcount = -1;
   priv->tags_changed = FALSE;
 
-  self->priv->latency_live = FALSE;
-  self->priv->latency_min = self->priv->sub_latency_min = 0;
-  self->priv->latency_max = self->priv->sub_latency_max = 0;
+  self->priv->peer_latency_live = FALSE;
+  self->priv->peer_latency_min = self->priv->sub_latency_min = 0;
+  self->priv->peer_latency_max = self->priv->sub_latency_max = 0;
+  self->priv->has_peer_latency = FALSE;
   gst_aggregator_reset_flow_values (self);
 
   self->srcpad = gst_pad_new_from_template (pad_template, "src");
@@ -1762,7 +1821,6 @@
 {
   GstBuffer *actual_buf = buffer;
   GstAggregator *self = GST_AGGREGATOR (object);
-  GstAggregatorPrivate *priv = self->priv;
   GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
   GstAggregatorClass *aggclass = GST_AGGREGATOR_GET_CLASS (object);
   GstFlowReturn flow_return;
@@ -1771,23 +1829,23 @@
 
   PAD_FLUSH_LOCK (aggpad);
 
-  if (g_atomic_int_get (&aggpad->priv->flushing) == TRUE)
+  PAD_LOCK (aggpad);
+  flow_return = aggpad->priv->flow_return;
+  if (flow_return != GST_FLOW_OK)
     goto flushing;
 
-  PAD_LOCK (aggpad);
   if (aggpad->priv->pending_eos == TRUE)
     goto eos;
 
-  while (aggpad->priv->buffer
-      && g_atomic_int_get (&aggpad->priv->flushing) == FALSE) {
-    GST_DEBUG_OBJECT (aggpad, "Waiting for buffer to be consumed");
+  while (aggpad->priv->buffer && aggpad->priv->flow_return == GST_FLOW_OK)
     PAD_WAIT_EVENT (aggpad);
-  }
-  PAD_UNLOCK (aggpad);
 
-  if (g_atomic_int_get (&aggpad->priv->flushing) == TRUE)
+  flow_return = aggpad->priv->flow_return;
+  if (flow_return != GST_FLOW_OK)
     goto flushing;
 
+  PAD_UNLOCK (aggpad);
+
   if (aggclass->clip) {
     aggclass->clip (self, aggpad, buffer, &actual_buf);
   }
@@ -1797,6 +1855,9 @@
   if (aggpad->priv->buffer)
     gst_buffer_unref (aggpad->priv->buffer);
   aggpad->priv->buffer = actual_buf;
+
+  flow_return = aggpad->priv->flow_return;
+
   PAD_UNLOCK (aggpad);
   PAD_FLUSH_UNLOCK (aggpad);
 
@@ -1805,19 +1866,17 @@
 
   GST_DEBUG_OBJECT (aggpad, "Done chaining");
 
-  GST_OBJECT_LOCK (self);
-  flow_return = priv->flow_return;
-  GST_OBJECT_UNLOCK (self);
-
   return flow_return;
 
 flushing:
+  PAD_UNLOCK (aggpad);
   PAD_FLUSH_UNLOCK (aggpad);
 
   gst_buffer_unref (buffer);
-  GST_DEBUG_OBJECT (aggpad, "We are flushing");
+  GST_DEBUG_OBJECT (aggpad, "Pad is %s, dropping buffer",
+      gst_flow_get_name (flow_return));
 
-  return GST_FLOW_FLUSHING;
+  return flow_return;
 
 eos:
   PAD_UNLOCK (aggpad);
@@ -1839,27 +1898,22 @@
   if (GST_QUERY_IS_SERIALIZED (query)) {
     PAD_LOCK (aggpad);
 
-    if (g_atomic_int_get (&aggpad->priv->flushing) == TRUE) {
-      PAD_UNLOCK (aggpad);
-      goto flushing;
-    }
-
-    while (aggpad->priv->buffer
-        && g_atomic_int_get (&aggpad->priv->flushing) == FALSE) {
-      GST_DEBUG_OBJECT (aggpad, "Waiting for buffer to be consumed");
+    while (aggpad->priv->buffer && aggpad->priv->flow_return == GST_FLOW_OK)
       PAD_WAIT_EVENT (aggpad);
-    }
-    PAD_UNLOCK (aggpad);
 
-    if (g_atomic_int_get (&aggpad->priv->flushing) == TRUE)
+    if (aggpad->priv->flow_return != GST_FLOW_OK)
       goto flushing;
+
+    PAD_UNLOCK (aggpad);
   }
 
   return klass->sink_query (GST_AGGREGATOR (parent),
       GST_AGGREGATOR_PAD (pad), query);
 
 flushing:
-  GST_DEBUG_OBJECT (aggpad, "Pad is flushing, dropping query");
+  GST_DEBUG_OBJECT (aggpad, "Pad is %s, dropping query",
+      gst_flow_get_name (aggpad->priv->flow_return));
+  PAD_UNLOCK (aggpad);
   return FALSE;
 }
 
@@ -1874,29 +1928,24 @@
       && GST_EVENT_TYPE (event) != GST_EVENT_SEGMENT_DONE) {
     PAD_LOCK (aggpad);
 
-    if (g_atomic_int_get (&aggpad->priv->flushing) == TRUE
-        && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP) {
-      PAD_UNLOCK (aggpad);
-      goto flushing;
-    }
 
-    while (aggpad->priv->buffer
-        && g_atomic_int_get (&aggpad->priv->flushing) == FALSE) {
-      GST_DEBUG_OBJECT (aggpad, "Waiting for buffer to be consumed");
+    while (aggpad->priv->buffer && aggpad->priv->flow_return == GST_FLOW_OK)
       PAD_WAIT_EVENT (aggpad);
-    }
-    PAD_UNLOCK (aggpad);
 
-    if (g_atomic_int_get (&aggpad->priv->flushing) == TRUE
+    if (aggpad->priv->flow_return != GST_FLOW_OK
         && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP)
       goto flushing;
+
+    PAD_UNLOCK (aggpad);
   }
 
   return klass->sink_event (GST_AGGREGATOR (parent),
       GST_AGGREGATOR_PAD (pad), event);
 
 flushing:
-  GST_DEBUG_OBJECT (aggpad, "Pad is flushing, dropping event");
+  GST_DEBUG_OBJECT (aggpad, "Pad is %s, dropping event",
+      gst_flow_get_name (aggpad->priv->flow_return));
+  PAD_UNLOCK (aggpad);
   if (GST_EVENT_IS_STICKY (event))
     gst_pad_store_sticky_event (pad, event);
   gst_event_unref (event);
@@ -1910,14 +1959,10 @@
   GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
 
   if (active == FALSE) {
-    PAD_LOCK (aggpad);
-    g_atomic_int_set (&aggpad->priv->flushing, TRUE);
-    gst_buffer_replace (&aggpad->priv->buffer, NULL);
-    PAD_BROADCAST_EVENT (aggpad);
-    PAD_UNLOCK (aggpad);
+    gst_aggregator_pad_set_flushing (aggpad, GST_FLOW_FLUSHING);
   } else {
     PAD_LOCK (aggpad);
-    g_atomic_int_set (&aggpad->priv->flushing, FALSE);
+    aggpad->priv->flow_return = GST_FLOW_OK;
     PAD_BROADCAST_EVENT (aggpad);
     PAD_UNLOCK (aggpad);
   }
diff --git a/gst-libs/gst/base/gstaggregator.h b/gst-libs/gst/base/gstaggregator.h
index a4ebdd7..dce567b 100644
--- a/gst-libs/gst/base/gstaggregator.h
+++ b/gst-libs/gst/base/gstaggregator.h
@@ -271,10 +271,7 @@
                                                     GstAggregatorPadForeachFunc      func,
                                                     gpointer                         user_data);
 
-void     gst_aggregator_get_latency_unlocked       (GstAggregator                 *  self,
-                                                    gboolean                      *  live,
-                                                    GstClockTime                  *  min,
-                                                    GstClockTime                  *  max);
+GstClockTime  gst_aggregator_get_latency           (GstAggregator                 *  self);
 
 G_END_DECLS
 
diff --git a/gst-libs/gst/basecamerabinsrc/Makefile.am b/gst-libs/gst/basecamerabinsrc/Makefile.am
index 51f10ba..64126e3 100644
--- a/gst-libs/gst/basecamerabinsrc/Makefile.am
+++ b/gst-libs/gst/basecamerabinsrc/Makefile.am
@@ -23,17 +23,3 @@
 	-lgstapp-$(GST_API_VERSION) $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_LIBS)
 
 libgstbasecamerabinsrc_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
-
-Android.mk: Makefile.am
-	androgenizer -:PROJECT libgstbasecamerabinsrc -:STATIC libgstbasecamerabinsrc-@GST_API_VERSION@ \
-	 -:TAGS eng debug \
-         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgstbasecamerabinsrc_@GST_API_VERSION@_la_SOURCES) \
-	 -:CFLAGS $(DEFS) $(libgstbasecamerabinsrc_@GST_API_VERSION@_la_CFLAGS) \
-	 -:LDFLAGS $(libgstbasecamerabinsrc_@GST_API_VERSION@_la_LDFLAGS) \
-	           $(libgstbasecamerabinsrc_@GST_API_VERSION@_la_LIBADD) \
-	           -ldl \
-	 -:HEADER_TARGET gstreamer-@GST_API_VERSION@/gst/basecamerabinsrc \
-	 -:HEADERS $(libgstbasecamerabinsrcinclude_HEADERS) \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-	> $@
diff --git a/gst-libs/gst/basecamerabinsrc/Makefile.in b/gst-libs/gst/basecamerabinsrc/Makefile.in
index 5c32e65..d9c75c2 100644
--- a/gst-libs/gst/basecamerabinsrc/Makefile.in
+++ b/gst-libs/gst/basecamerabinsrc/Makefile.in
@@ -1068,20 +1068,6 @@
 	uninstall-libgstbasecamerabinsrc_@GST_API_VERSION@includeHEADERS
 
 
-Android.mk: Makefile.am
-	androgenizer -:PROJECT libgstbasecamerabinsrc -:STATIC libgstbasecamerabinsrc-@GST_API_VERSION@ \
-	 -:TAGS eng debug \
-         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgstbasecamerabinsrc_@GST_API_VERSION@_la_SOURCES) \
-	 -:CFLAGS $(DEFS) $(libgstbasecamerabinsrc_@GST_API_VERSION@_la_CFLAGS) \
-	 -:LDFLAGS $(libgstbasecamerabinsrc_@GST_API_VERSION@_la_LDFLAGS) \
-	           $(libgstbasecamerabinsrc_@GST_API_VERSION@_la_LIBADD) \
-	           -ldl \
-	 -:HEADER_TARGET gstreamer-@GST_API_VERSION@/gst/basecamerabinsrc \
-	 -:HEADERS $(libgstbasecamerabinsrcinclude_HEADERS) \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-	> $@
-
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
diff --git a/gst-libs/gst/codecparsers/Makefile.am b/gst-libs/gst/codecparsers/Makefile.am
index eff6e83..8f2abb9 100644
--- a/gst-libs/gst/codecparsers/Makefile.am
+++ b/gst-libs/gst/codecparsers/Makefile.am
@@ -35,19 +35,3 @@
 	$(GST_LT_LDFLAGS)
 
 EXTRA_DIST = dboolhuff.LICENSE dboolhuff.PATENTS dboolhuff.AUTHORS
-
-Android.mk:  $(BUILT_SOURCES) Makefile.am
-	androgenizer -:PROJECT libgstcodecparsers -:STATIC libgstcodecparsers-@GST_API_VERSION@ \
-	 -:TAGS eng debug \
-         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgstcodecparsers_@GST_API_VERSION@_la_SOURCES) \
-         $(built_sources) \
-	 -:CFLAGS $(DEFS) $(libgstcodecparsers_@GST_API_VERSION@_la_CFLAGS) \
-	 -:LDFLAGS $(libgstcodecparsers_@GST_API_VERSION@_la_LDFLAGS) \
-	           $(libgstcodecparsers@GST_API_VERSION@_la_LIBADD) \
-	           -ldl \
-	 -:HEADER_TARGET gstreamer-@GST_API_VERSION@/gst/codecparsers \
-	 -:HEADERS $(libgstcodecparsersinclude_HEADERS) \
-         $(built_headers) \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-	> $@
diff --git a/gst-libs/gst/codecparsers/Makefile.in b/gst-libs/gst/codecparsers/Makefile.in
index 738a4f8..aa9d1e8 100644
--- a/gst-libs/gst/codecparsers/Makefile.in
+++ b/gst-libs/gst/codecparsers/Makefile.in
@@ -1227,22 +1227,6 @@
 	uninstall-libgstcodecparsers_@GST_API_VERSION@includeHEADERS
 
 
-Android.mk:  $(BUILT_SOURCES) Makefile.am
-	androgenizer -:PROJECT libgstcodecparsers -:STATIC libgstcodecparsers-@GST_API_VERSION@ \
-	 -:TAGS eng debug \
-         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-	 -:SOURCES $(libgstcodecparsers_@GST_API_VERSION@_la_SOURCES) \
-         $(built_sources) \
-	 -:CFLAGS $(DEFS) $(libgstcodecparsers_@GST_API_VERSION@_la_CFLAGS) \
-	 -:LDFLAGS $(libgstcodecparsers_@GST_API_VERSION@_la_LDFLAGS) \
-	           $(libgstcodecparsers@GST_API_VERSION@_la_LIBADD) \
-	           -ldl \
-	 -:HEADER_TARGET gstreamer-@GST_API_VERSION@/gst/codecparsers \
-	 -:HEADERS $(libgstcodecparsersinclude_HEADERS) \
-         $(built_headers) \
-	 -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-	> $@
-
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
diff --git a/gst-libs/gst/codecparsers/gsth265parser.c b/gst-libs/gst/codecparsers/gsth265parser.c
index 083b278..563fedf 100644
--- a/gst-libs/gst/codecparsers/gsth265parser.c
+++ b/gst-libs/gst/codecparsers/gsth265parser.c
@@ -131,6 +131,24 @@
   54, 71, 71, 91
 };
 
+static const guint8 zigzag_4x4[16] = {
+  0, 1, 4, 8,
+  5, 2, 3, 6,
+  9, 12, 13, 10,
+  7, 11, 14, 15,
+};
+
+static const guint8 zigzag_8x8[64] = {
+  0, 1, 8, 16, 9, 2, 3, 10,
+  17, 24, 32, 25, 18, 11, 4, 5,
+  12, 19, 26, 33, 40, 48, 41, 34,
+  27, 20, 13, 6, 7, 14, 21, 28,
+  35, 42, 49, 56, 57, 50, 43, 36,
+  29, 22, 15, 23, 30, 37, 44, 51,
+  58, 59, 52, 45, 38, 31, 39, 46,
+  53, 60, 61, 54, 47, 55, 62, 63
+};
+
 typedef struct
 {
   guint par_n, par_d;
@@ -747,9 +765,6 @@
       READ_UINT8 (nr, used_by_curr_pic_flag[j], 1);
       if (!used_by_curr_pic_flag[j])
         READ_UINT8 (nr, use_delta_flag[j], 1);
-
-      if (used_by_curr_pic_flag[j] || use_delta_flag[j])
-        stRPS->NumDeltaPocs++;
     }
 
     /* 7-47: calcuate NumNegativePics, DeltaPocS0 and UsedByCurrPicS0 */
@@ -839,9 +854,11 @@
       }
     }
 
-    /* 7-57 */
-    stRPS->NumDeltaPocs = stRPS->NumPositivePics + stRPS->NumNegativePics;
   }
+
+  /* 7-57 */
+  stRPS->NumDeltaPocs = stRPS->NumPositivePics + stRPS->NumNegativePics;
+
   return TRUE;
 
 error:
@@ -1222,7 +1239,7 @@
 
   if (nalu->type == GST_H265_NAL_EOS || nalu->type == GST_H265_NAL_EOB) {
     GST_DEBUG ("end-of-seq or end-of-stream nal found");
-    nalu->size = 0;
+    nalu->size = 2;
     return GST_H265_PARSER_OK;
   }
 
@@ -1252,7 +1269,7 @@
       gst_h265_parser_identify_nalu_unchecked (parser, data, offset, size,
       nalu);
 
-  if (res != GST_H265_PARSER_OK || nalu->size == 0)
+  if (res != GST_H265_PARSER_OK || nalu->size == 2)
     goto beach;
 
   off2 = scan_for_start_codes (data + nalu->offset, size - nalu->offset);
@@ -1269,7 +1286,7 @@
     off2--;
 
   nalu->size = off2;
-  if (nalu->size < 2)
+  if (nalu->size < 3)
     return GST_H265_PARSER_BROKEN_DATA;
 
   GST_DEBUG ("Complete nal found. Off: %d, Size: %d", nalu->offset, nalu->size);
@@ -1547,6 +1564,8 @@
   GstH265VPS *vps;
   guint8 vps_id;
   guint i;
+  guint subwc[] = { 1, 2, 2, 1, 1 };
+  guint subhc[] = { 1, 2, 1, 1, 1 };
   GstH265VUIParams *vui = NULL;
 
   INITIALIZE_DEBUG_CATEGORY;
@@ -1696,7 +1715,20 @@
     goto error;
   }
 
-  /* ToDo: Add crop_rectangle dimensions */
+  if (sps->conformance_window_flag) {
+    const guint crop_unit_x = subwc[sps->chroma_format_idc];
+    const guint crop_unit_y = subhc[sps->chroma_format_idc];
+
+    sps->crop_rect_width = sps->width -
+        (sps->conf_win_left_offset + sps->conf_win_right_offset) * crop_unit_x;
+    sps->crop_rect_height = sps->height -
+        (sps->conf_win_top_offset + sps->conf_win_bottom_offset) * crop_unit_y;
+    sps->crop_rect_x = sps->conf_win_left_offset * crop_unit_x;
+    sps->crop_rect_y = sps->conf_win_top_offset * crop_unit_y;
+
+    GST_LOG ("crop_rectangle x=%u y=%u width=%u, height=%u", sps->crop_rect_x,
+        sps->crop_rect_y, sps->crop_rect_width, sps->crop_rect_height);
+  }
 
   sps->fps_num = 0;
   sps->fps_den = 1;
@@ -1804,8 +1836,8 @@
   READ_UINT8 (&nr, pps->entropy_coding_sync_enabled_flag, 1);
 
   if (pps->tiles_enabled_flag) {
-    READ_UE_ALLOWED (&nr, pps->num_tile_columns_minus1, 1, 19);
-    READ_UE_ALLOWED (&nr, pps->num_tile_rows_minus1, 1, 21);
+    READ_UE_ALLOWED (&nr, pps->num_tile_columns_minus1, 0, 19);
+    READ_UE_ALLOWED (&nr, pps->num_tile_rows_minus1, 0, 21);
 
     READ_UINT8 (&nr, pps->uniform_spacing_flag, 1);
     if (!pps->uniform_spacing_flag) {
@@ -2075,24 +2107,25 @@
             pps->num_ref_idx_l1_default_active_minus1;
       }
 
+      /* calculate NumPocTotalCurr */
+      if (slice->short_term_ref_pic_set_sps_flag)
+        CurrRpsIdx = slice->short_term_ref_pic_set_idx;
+      else
+        CurrRpsIdx = sps->num_short_term_ref_pic_sets;
+      stRPS = &sps->short_term_ref_pic_set[CurrRpsIdx];
+      for (i = 0; i < stRPS->NumNegativePics; i++)
+        if (stRPS->UsedByCurrPicS0[i])
+          NumPocTotalCurr++;
+      for (i = 0; i < stRPS->NumPositivePics; i++)
+        if (stRPS->UsedByCurrPicS1[i])
+          NumPocTotalCurr++;
+      for (i = 0;
+          i < (slice->num_long_term_sps + slice->num_long_term_pics); i++)
+        if (UsedByCurrPicLt[i])
+          NumPocTotalCurr++;
+      slice->NumPocTotalCurr = NumPocTotalCurr;
+
       if (pps->lists_modification_present_flag) {
-        /* calculate NumPocTotalCurr */
-        if (slice->short_term_ref_pic_set_sps_flag)
-          CurrRpsIdx = slice->short_term_ref_pic_set_idx;
-        else
-          CurrRpsIdx = sps->num_short_term_ref_pic_sets;
-        stRPS = &sps->short_term_ref_pic_set[CurrRpsIdx];
-        for (i = 0; i < stRPS->NumNegativePics; i++)
-          if (stRPS->UsedByCurrPicS0[i])
-            NumPocTotalCurr++;
-        for (i = 0; i < stRPS->NumPositivePics; i++)
-          if (stRPS->UsedByCurrPicS1[i])
-            NumPocTotalCurr++;
-        for (i = 0;
-            i < (slice->num_long_term_sps + slice->num_long_term_pics); i++)
-          if (UsedByCurrPicLt[i])
-            NumPocTotalCurr++;
-        slice->NumPocTotalCurr = NumPocTotalCurr;
         if (NumPocTotalCurr > 1)
           if (!gst_h265_slice_parse_ref_pic_list_modification (slice, &nr,
                   NumPocTotalCurr))
@@ -2185,6 +2218,14 @@
         goto error;
   }
 
+  /* Skip the byte alignment bits */
+  if (!nal_reader_skip (&nr, 1))
+    goto error;
+  while (!nal_reader_is_byte_aligned (&nr)) {
+    if (!nal_reader_skip (&nr, 1))
+      goto error;
+  }
+
   slice->header_size = nal_reader_get_pos (&nr);
   slice->n_emulation_prevention_bytes = nal_reader_get_epb_count (&nr);
 
@@ -2198,68 +2239,106 @@
   return GST_H265_PARSER_ERROR;
 }
 
-/**
- * gst_h265_parser_parse_sei:
- * @parser: a #GstH265Parser
- * @nalu: The #GST_H265_NAL_SEI #GstH265NalUnit to parse
- * @sei: The #GstH265SEIMessage to fill.
- *
- * Parses @data, and fills the @sei structures.
- * The resulting @sei  structure shall be deallocated with
- * gst_h265_sei_free() when it is no longer needed
- *
- * Returns: a #GstH265ParserResult
- */
-GstH265ParserResult
-gst_h265_parser_parse_sei (GstH265Parser * parser,
-    GstH265NalUnit * nalu, GstH265SEIMessage * sei)
+static gboolean
+nal_reader_has_more_data_in_payload (NalReader * nr,
+    guint32 payload_start_pos_bit, guint32 payloadSize)
 {
-  NalReader nr;
+  if (nal_reader_is_byte_aligned (nr) &&
+      (nal_reader_get_pos (nr) == (payload_start_pos_bit + 8 * payloadSize)))
+    return FALSE;
+
+  return TRUE;
+}
+
+static GstH265ParserResult
+gst_h265_parser_parse_sei_message (GstH265Parser * parser,
+    guint8 nal_type, NalReader * nr, GstH265SEIMessage * sei)
+{
   guint32 payloadSize;
   guint8 payload_type_byte, payload_size_byte;
-#ifndef GST_DISABLE_GST_DEBUG
   guint remaining, payload_size;
-#endif
-  GstH265ParserResult res;
+  guint32 payload_start_pos_bit;
+  GstH265ParserResult res = GST_H265_PARSER_OK;
+
   GST_DEBUG ("parsing \"Sei message\"");
-  nal_reader_init (&nr, nalu->data + nalu->offset + 1, nalu->size - 1);
-  /* init */
-  memset (sei, 0, sizeof (*sei));
+
   sei->payloadType = 0;
   do {
-    READ_UINT8 (&nr, payload_type_byte, 8);
+    READ_UINT8 (nr, payload_type_byte, 8);
     sei->payloadType += payload_type_byte;
   } while (payload_type_byte == 0xff);
   payloadSize = 0;
   do {
-    READ_UINT8 (&nr, payload_size_byte, 8);
+    READ_UINT8 (nr, payload_size_byte, 8);
     payloadSize += payload_size_byte;
   }
   while (payload_size_byte == 0xff);
-#ifndef GST_DISABLE_GST_DEBUG
-  remaining = nal_reader_get_remaining (&nr) * 8;
-  payload_size = payloadSize < remaining ? payloadSize : remaining;
+
+  remaining = nal_reader_get_remaining (nr);
+  payload_size = payloadSize * 8 < remaining ? payloadSize * 8 : remaining;
+
+  payload_start_pos_bit = nal_reader_get_pos (nr);
   GST_DEBUG
       ("SEI message received: payloadType  %u, payloadSize = %u bytes",
       sei->payloadType, payload_size);
-#endif
-  if (sei->payloadType == GST_H265_SEI_BUF_PERIOD) {
-    /* size not set; might depend on emulation_prevention_three_byte */
-    res = gst_h265_parser_parse_buffering_period (parser,
-        &sei->payload.buffering_period, &nr);
-  } else if (sei->payloadType == GST_H265_SEI_PIC_TIMING) {
-    /* size not set; might depend on emulation_prevention_three_byte */
-    res = gst_h265_parser_parse_pic_timing (parser,
-        &sei->payload.pic_timing, &nr);
-  } else
-    res = GST_H265_PARSER_OK;
+
+  if (nal_type == GST_H265_NAL_PREFIX_SEI) {
+    switch (sei->payloadType) {
+      case GST_H265_SEI_BUF_PERIOD:
+        /* size not set; might depend on emulation_prevention_three_byte */
+        res = gst_h265_parser_parse_buffering_period (parser,
+            &sei->payload.buffering_period, nr);
+        break;
+      case GST_H265_SEI_PIC_TIMING:
+        /* size not set; might depend on emulation_prevention_three_byte */
+        res = gst_h265_parser_parse_pic_timing (parser,
+            &sei->payload.pic_timing, nr);
+        break;
+      default:
+        /* Just consume payloadSize bytes, which does not account for
+           emulation prevention bytes */
+        if (!nal_reader_skip_long (nr, payload_size))
+          goto error;
+        res = GST_H265_PARSER_OK;
+        break;
+    }
+  } else if (nal_type == GST_H265_NAL_SUFFIX_SEI) {
+    switch (sei->payloadType) {
+      default:
+        /* Just consume payloadSize bytes, which does not account for
+           emulation prevention bytes */
+        if (!nal_reader_skip_long (nr, payload_size))
+          goto error;
+        res = GST_H265_PARSER_OK;
+        break;
+    }
+  }
+
+  /* Not parsing the reserved_payload_extension, but it shouldn't be
+   * an issue because of 1: There shall not be any reserved_payload_extension
+   * present in bitstreams conforming to the specification.2. Even though
+   * it is present, the size will be less than total PayloadSize since the
+   * size of reserved_payload_extension is supposed to be
+   * 8 * payloadSize - nEarlierBits - nPayloadZeroBits -1 which means the
+   * the current implementation will still skip all unnecessary bits correctly.
+   * In theory, we can have a more optimized implementation by skipping the
+   * data left in PayLoadSize without out individually checking for each bits,
+   * since the totoal size will be always less than payloadSize*/
+  if (nal_reader_has_more_data_in_payload (nr, payload_start_pos_bit,
+          payloadSize)) {
+    /* Skip the byte alignment bits */
+    if (!nal_reader_skip (nr, 1))
+      goto error;
+    while (!nal_reader_is_byte_aligned (nr)) {
+      if (!nal_reader_skip (nr, 1))
+        goto error;
+    }
+  }
 
   return res;
 
 error:
   GST_WARNING ("error parsing \"Sei message\"");
-  gst_h265_sei_free (sei);
-
   return GST_H265_PARSER_ERROR;
 }
 
@@ -2377,3 +2456,139 @@
     pic_timing->du_cpb_removal_delay_increment_minus1 = 0;
   }
 }
+
+/**
+ * gst_h265_parser_parse_sei:
+ * @nalparser: a #GstH265Parser
+ * @nalu: The #GST_H265_NAL_SEI #GstH265NalUnit to parse
+ * @messages: The GArray of #GstH265SEIMessage to fill. The caller must free it when done.
+ *
+ * Parses @data, create and fills the @messages array.
+ *
+ * Returns: a #GstH265ParserResult
+ */
+GstH265ParserResult
+gst_h265_parser_parse_sei (GstH265Parser * nalparser, GstH265NalUnit * nalu,
+    GArray ** messages)
+{
+  NalReader nr;
+  GstH265SEIMessage sei;
+  GstH265ParserResult res;
+
+  GST_DEBUG ("parsing SEI nal");
+  nal_reader_init (&nr, nalu->data + nalu->offset + nalu->header_bytes,
+      nalu->size - nalu->header_bytes);
+  *messages = g_array_new (FALSE, FALSE, sizeof (GstH265SEIMessage));
+  g_array_set_clear_func (*messages, (GDestroyNotify) gst_h265_sei_free);
+
+  do {
+    res = gst_h265_parser_parse_sei_message (nalparser, nalu->type, &nr, &sei);
+    if (res == GST_H265_PARSER_OK)
+      g_array_append_val (*messages, sei);
+    else
+      break;
+  } while (nal_reader_has_more_data (&nr));
+
+  return res;
+}
+
+
+/**
+ * gst_h265_quant_matrix_4x4_get_zigzag_from_raster:
+ * @out_quant: (out): The resulting quantization matrix
+ * @quant: The source quantization matrix
+ *
+ * Converts quantization matrix @quant from raster scan order to
+ * zigzag scan order and store the resulting factors into @out_quant.
+ *
+ * Note: it is an error to pass the same table in both @quant and
+ * @out_quant arguments.
+ *
+ * Since: 1.6
+ */
+void
+gst_h265_quant_matrix_4x4_get_zigzag_from_raster (guint8 out_quant[16],
+    const guint8 quant[16])
+{
+  guint i;
+
+  g_return_if_fail (out_quant != quant);
+
+  for (i = 0; i < 16; i++)
+    out_quant[i] = quant[zigzag_4x4[i]];
+}
+
+/**
+ * gst_h265_quant_matrix_4x4_get_raster_from_zigzag:
+ * @out_quant: (out): The resulting quantization matrix
+ * @quant: The source quantization matrix
+ *
+ * Converts quantization matrix @quant from zigzag scan order to
+ * raster scan order and store the resulting factors into @out_quant.
+ *
+ * Note: it is an error to pass the same table in both @quant and
+ * @out_quant arguments.
+ *
+ * Since: 1.6
+ */
+void
+gst_h265_quant_matrix_4x4_get_raster_from_zigzag (guint8 out_quant[16],
+    const guint8 quant[16])
+{
+  guint i;
+
+  g_return_if_fail (out_quant != quant);
+
+  for (i = 0; i < 16; i++)
+    out_quant[zigzag_4x4[i]] = quant[i];
+}
+
+/**
+ * gst_h265_quant_matrix_8x8_get_zigzag_from_raster:
+ * @out_quant: (out): The resulting quantization matrix
+ * @quant: The source quantization matrix
+ *
+ * Converts quantization matrix @quant from raster scan order to
+ * zigzag scan order and store the resulting factors into @out_quant.
+ *
+ * Note: it is an error to pass the same table in both @quant and
+ * @out_quant arguments.
+ *
+ * Since: 1.6
+ */
+void
+gst_h265_quant_matrix_8x8_get_zigzag_from_raster (guint8 out_quant[64],
+    const guint8 quant[64])
+{
+  guint i;
+
+  g_return_if_fail (out_quant != quant);
+
+  for (i = 0; i < 64; i++)
+    out_quant[i] = quant[zigzag_8x8[i]];
+}
+
+/**
+ * gst_h265_quant_matrix_8x8_get_raster_from_zigzag:
+ * @out_quant: (out): The resulting quantization matrix
+ * @quant: The source quantization matrix
+ *
+ * Converts quantization matrix @quant from zigzag scan order to
+ * raster scan order and store the resulting factors into @out_quant.
+ *
+ * Note: it is an error to pass the same table in both @quant and
+ * @out_quant arguments.
+ *
+ * Since: 1.6
+ */
+void
+gst_h265_quant_matrix_8x8_get_raster_from_zigzag (guint8 out_quant[64],
+    const guint8 quant[64])
+{
+  guint i;
+
+  g_return_if_fail (out_quant != quant);
+
+  for (i = 0; i < 64; i++)
+    out_quant[zigzag_8x8[i]] = quant[i];
+}
diff --git a/gst-libs/gst/codecparsers/gsth265parser.h b/gst-libs/gst/codecparsers/gsth265parser.h
index 883b7b2..9f42625 100644
--- a/gst-libs/gst/codecparsers/gsth265parser.h
+++ b/gst-libs/gst/codecparsers/gsth265parser.h
@@ -763,6 +763,8 @@
   /* calculated values */
   guint8 chroma_array_type;
   gint width, height;
+  gint crop_rect_width, crop_rect_height;
+  gint crop_rect_x, crop_rect_y;
   gint fps_num, fps_den;
   gboolean valid;
 };
@@ -1035,7 +1037,7 @@
 
 GstH265ParserResult gst_h265_parser_parse_sei       (GstH265Parser   * parser,
                                                      GstH265NalUnit  * nalu,
-                                                     GstH265SEIMessage * sei);
+                                                     GArray **messages);
 
 void                gst_h265_parser_free            (GstH265Parser  * parser);
 
@@ -1061,5 +1063,26 @@
 
 void                gst_h265_sei_free       (GstH265SEIMessage * sei);
 
+void    gst_h265_quant_matrix_4x4_get_zigzag_from_raster (guint8 out_quant[16],
+                                                          const guint8 quant[16]);
+
+void    gst_h265_quant_matrix_4x4_get_raster_from_zigzag (guint8 out_quant[16],
+                                                          const guint8 quant[16]);
+
+void    gst_h265_quant_matrix_8x8_get_zigzag_from_raster (guint8 out_quant[64],
+                                                          const guint8 quant[64]);
+
+void    gst_h265_quant_matrix_8x8_get_raster_from_zigzag (guint8 out_quant[64],
+                                                          const guint8 quant[64]);
+
+#define gst_h265_quant_matrix_16x16_get_zigzag_from_raster \
+        gst_h265_quant_matrix_8x8_get_zigzag_from_raster
+#define gst_h265_quant_matrix_16x16_get_raster_from_zigzag \
+        gst_h265_quant_matrix_8x8_get_raster_from_zigzag
+#define gst_h265_quant_matrix_32x32_get_zigzag_from_raster \
+        gst_h265_quant_matrix_8x8_get_zigzag_from_raster
+#define gst_h265_quant_matrix_32x32_get_raster_from_zigzag \
+        gst_h265_quant_matrix_8x8_get_raster_from_zigzag
+
 G_END_DECLS
 #endif
diff --git a/gst-libs/gst/gl/Makefile.am b/gst-libs/gst/gl/Makefile.am
index fcf318d..8f5f115 100644
--- a/gst-libs/gst/gl/Makefile.am
+++ b/gst-libs/gst/gl/Makefile.am
@@ -126,7 +126,7 @@
 gir_sources=$(patsubst %,$(srcdir)/%, $(libgstgl_@GST_API_VERSION@_la_SOURCES))
 
 GstGL-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstgl-@GST_API_VERSION@.la
-	$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
+	$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" GI_SCANNER_DISABLE_CACHE=yes\
 		GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_UPDATE=no \
 		$(INTROSPECTION_SCANNER) -v --namespace GstGL \
 		--nsversion=@GST_API_VERSION@ \
diff --git a/gst-libs/gst/gl/Makefile.in b/gst-libs/gst/gl/Makefile.in
index 4200a7a..3ce5d1b 100644
--- a/gst-libs/gst/gl/Makefile.in
+++ b/gst-libs/gst/gl/Makefile.in
@@ -1541,7 +1541,7 @@
 
 
 @HAVE_INTROSPECTION_TRUE@GstGL-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstgl-@GST_API_VERSION@.la
-@HAVE_INTROSPECTION_TRUE@	$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
+@HAVE_INTROSPECTION_TRUE@	$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" GI_SCANNER_DISABLE_CACHE=yes\
 @HAVE_INTROSPECTION_TRUE@		GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_UPDATE=no \
 @HAVE_INTROSPECTION_TRUE@		$(INTROSPECTION_SCANNER) -v --namespace GstGL \
 @HAVE_INTROSPECTION_TRUE@		--nsversion=@GST_API_VERSION@ \
diff --git a/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c b/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c
index ca5411a..0adbfb6 100644
--- a/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c
+++ b/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c
@@ -29,18 +29,31 @@
 
 #include "gstglwindow_dispmanx_egl.h"
 
+
+#ifndef ELEMENT_CHANGE_LAYER
+/* copied from interface/vmcs_host/vc_vchi_dispmanx.h of userland.git */
+#define ELEMENT_CHANGE_LAYER          (1<<0)
+#define ELEMENT_CHANGE_OPACITY        (1<<1)
+#define ELEMENT_CHANGE_DEST_RECT      (1<<2)
+#define ELEMENT_CHANGE_SRC_RECT       (1<<3)
+#define ELEMENT_CHANGE_MASK_RESOURCE  (1<<4)
+#define ELEMENT_CHANGE_TRANSFORM      (1<<5)
+#endif
+
 #define GST_CAT_DEFAULT gst_gl_window_debug
 
 #define gst_gl_window_dispmanx_egl_parent_class parent_class
 G_DEFINE_TYPE (GstGLWindowDispmanxEGL, gst_gl_window_dispmanx_egl,
     GST_GL_TYPE_WINDOW);
 
+static void gst_gl_window_dispmanx_egl_finalize (GObject * object);
 static guintptr gst_gl_window_dispmanx_egl_get_window_handle (GstGLWindow *
     window);
 static void gst_gl_window_dispmanx_egl_set_window_handle (GstGLWindow * window,
     guintptr handle);
 static void gst_gl_window_dispmanx_egl_set_preferred_size (GstGLWindow * window,
     gint width, gint height);
+static void gst_gl_window_dispmanx_egl_show (GstGLWindow * window);
 static void gst_gl_window_dispmanx_egl_draw (GstGLWindow * window);
 static void gst_gl_window_dispmanx_egl_run (GstGLWindow * window);
 static void gst_gl_window_dispmanx_egl_quit (GstGLWindow * window);
@@ -53,17 +66,19 @@
 
 
 static void window_resize (GstGLWindowDispmanxEGL * window_egl, guint width,
-    guint height);
+    guint height, gboolean visible);
 
 static void
 gst_gl_window_dispmanx_egl_class_init (GstGLWindowDispmanxEGLClass * klass)
 {
   GstGLWindowClass *window_class = (GstGLWindowClass *) klass;
+  GObjectClass *gobject_class = (GObjectClass *) klass;
 
   window_class->get_window_handle =
       GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_get_window_handle);
   window_class->set_window_handle =
       GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_set_window_handle);
+  window_class->show = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_show);
   window_class->draw_unlocked =
       GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_draw);
   window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_draw);
@@ -77,11 +92,26 @@
       GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_get_display);
   window_class->set_preferred_size =
       GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_set_preferred_size);
+
+  gobject_class->finalize = gst_gl_window_dispmanx_egl_finalize;
 }
 
 static void
-gst_gl_window_dispmanx_egl_init (GstGLWindowDispmanxEGL * window)
+gst_gl_window_dispmanx_egl_init (GstGLWindowDispmanxEGL * window_egl)
 {
+  window_egl->main_context = g_main_context_new ();
+  window_egl->loop = g_main_loop_new (window_egl->main_context, FALSE);