Merge branch 'master' into 0.11

unport gdkpixbuf
not merged: https://bugzilla.gnome.org/show_bug.cgi?id=654850

Conflicts:
	docs/plugins/Makefile.am
	docs/plugins/gst-plugins-good-plugins-docs.sgml
	docs/plugins/gst-plugins-good-plugins-sections.txt
	docs/plugins/gst-plugins-good-plugins.hierarchy
	docs/plugins/inspect/plugin-avi.xml
	docs/plugins/inspect/plugin-png.xml
	ext/flac/gstflacdec.c
	ext/flac/gstflacdec.h
	ext/libpng/gstpngdec.c
	ext/libpng/gstpngenc.c
	ext/speex/gstspeexdec.c
	gst/audioparsers/gstflacparse.c
	gst/flv/gstflvmux.c
	gst/rtp/gstrtpdvdepay.c
	gst/rtp/gstrtph264depay.c
diff --git a/configure.ac b/configure.ac
index 0d31edf..943b2a9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -314,7 +314,7 @@
 GST_PLUGINS_NONPORTED="deinterlace interleave flx \
  smpte \
  videobox \
- cairo cairo_gobject dv1394 \
+ cairo cairo_gobject dv1394 gdk_pixbuf \
  oss oss4 \
  osx_video osx_audio "
 AC_SUBST(GST_PLUGINS_NONPORTED)
@@ -386,18 +386,14 @@
   LDFLAGS="$LDFLAGS $DIRECTSOUND_LDFLAGS"
   LIBS="$LIBS -ldsound -ldxerr9 -luser32"
   AC_MSG_CHECKING(for DirectSound LDFLAGS)
-  AC_LINK_IFELSE([
+  AC_LINK_IFELSE([AC_LANG_PROGRAM([[
 #include <windows.h>
 #include <dxerr9.h>
 #include <dsound.h>
-
-int main ()
-{
+]], [[
   DXGetErrorString9 (0);
   DirectSoundCreate(NULL, NULL, NULL);
-
-  return 0;
-}
+]])
 ],
     [HAVE_DIRECTSOUND="yes"],
     [HAVE_DIRECTSOUND="no"])
diff --git a/docs/plugins/gst-plugins-good-plugins.args b/docs/plugins/gst-plugins-good-plugins.args
index b9afcdf..b4ce267 100644
--- a/docs/plugins/gst-plugins-good-plugins.args
+++ b/docs/plugins/gst-plugins-good-plugins.args
@@ -869,6 +869,16 @@
 </ARG>
 
 <ARG>
+<NAME>GstRTSPSrc::do-rtsp-keep-alive</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Do RTSP Keep Alive</NICK>
+<BLURB>Send RTSP keep alive packets, disable for old incompatible server.</BLURB>
+<DEFAULT>TRUE</DEFAULT>
+</ARG>
+
+<ARG>
 <NAME>GstRTPDec::skip</NAME>
 <TYPE>gint</TYPE>
 <RANGE></RANGE>
@@ -1925,7 +1935,7 @@
 <FLAGS>rwx</FLAGS>
 <NICK>Seekpoints</NICK>
 <BLURB>Add SEEKTABLE metadata (if > 0, number of entries, if < 0, interval in sec).</BLURB>
-<DEFAULT>0</DEFAULT>
+<DEFAULT>-10</DEFAULT>
 </ARG>
 
 <ARG>
@@ -21525,7 +21535,7 @@
 <FLAGS>rw</FLAGS>
 <NICK>Transport mode</NICK>
 <BLURB>Jack transport behaviour of the client.</BLURB>
-<DEFAULT>No transport support</DEFAULT>
+<DEFAULT></DEFAULT>
 </ARG>
 
 <ARG>
@@ -21575,7 +21585,7 @@
 <FLAGS>rw</FLAGS>
 <NICK>Transport mode</NICK>
 <BLURB>Jack transport behaviour of the client.</BLURB>
-<DEFAULT>No transport support</DEFAULT>
+<DEFAULT></DEFAULT>
 </ARG>
 
 <ARG>
@@ -22578,3 +22588,73 @@
 <DEFAULT>FALSE</DEFAULT>
 </ARG>
 
+<ARG>
+<NAME>GstGdkPixbufOverlay::location</NAME>
+<TYPE>gchar*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>location</NICK>
+<BLURB>Location of image file to overlay.</BLURB>
+<DEFAULT>NULL</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstGdkPixbufOverlay::offset-x</NAME>
+<TYPE>gint</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>X Offset</NICK>
+<BLURB>Horizontal offset of overlay image in pixels from top-left corner of video image.</BLURB>
+<DEFAULT>0</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstGdkPixbufOverlay::offset-y</NAME>
+<TYPE>gint</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Y Offset</NICK>
+<BLURB>Vertical offset of overlay image in pixels from top-left corner of video image.</BLURB>
+<DEFAULT>0</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstGdkPixbufOverlay::overlay-height</NAME>
+<TYPE>gint</TYPE>
+<RANGE>>= 0</RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Overlay Height</NICK>
+<BLURB>Height of overlay image in pixels (0 = same as overlay image).</BLURB>
+<DEFAULT>0</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstGdkPixbufOverlay::overlay-width</NAME>
+<TYPE>gint</TYPE>
+<RANGE>>= 0</RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Overlay Width</NICK>
+<BLURB>Width of overlay image in pixels (0 = same as overlay image).</BLURB>
+<DEFAULT>0</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstGdkPixbufOverlay::relative-x</NAME>
+<TYPE>gdouble</TYPE>
+<RANGE>[0,1]</RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Relative X Offset</NICK>
+<BLURB>Horizontal offset of overlay image in fractions of video image width, from top-left corner of video image.</BLURB>
+<DEFAULT>0</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstGdkPixbufOverlay::relative-y</NAME>
+<TYPE>gdouble</TYPE>
+<RANGE>[0,1]</RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Relative Y Offset</NICK>
+<BLURB>Vertical offset of overlay image in fractions of video image height, from top-left corner of video image.</BLURB>
+<DEFAULT>0</DEFAULT>
+</ARG>
+
diff --git a/docs/plugins/inspect/plugin-audioparsers.xml b/docs/plugins/inspect/plugin-audioparsers.xml
index c58dc60..c26f2eb 100644
--- a/docs/plugins/inspect/plugin-audioparsers.xml
+++ b/docs/plugins/inspect/plugin-audioparsers.xml
@@ -135,5 +135,26 @@
         </caps>
       </pads>
     </element>
+    <element>
+      <name>wavpackparse2</name>
+      <longname>Wavpack audio stream parser</longname>
+      <class>Codec/Parser/Audio</class>
+      <description>Wavpack parser</description>
+      <author>Mark Nauwelaerts &lt;mark.nauwelaerts@collabora.co.uk&gt;</author>
+      <pads>
+        <caps>
+          <name>sink</name>
+          <direction>sink</direction>
+          <presence>always</presence>
+          <details>audio/x-wavpack</details>
+        </caps>
+        <caps>
+          <name>src</name>
+          <direction>source</direction>
+          <presence>always</presence>
+          <details>audio/x-wavpack, width=(int)[ 1, 32 ], channels=(int)[ 1, 8 ], rate=(int)[ 6000, 192000 ], framed=(boolean)true; audio/x-wavpack-correction, framed=(boolean)true</details>
+        </caps>
+      </pads>
+    </element>
   </elements>
 </plugin>
\ No newline at end of file
diff --git a/docs/plugins/inspect/plugin-avi.xml b/docs/plugins/inspect/plugin-avi.xml
index 5b6cbe5..fdae4f6 100644
--- a/docs/plugins/inspect/plugin-avi.xml
+++ b/docs/plugins/inspect/plugin-avi.xml
@@ -91,4 +91,4 @@
       </pads>
     </element>
   </elements>
-</plugin>
\ No newline at end of file
+</plugin>
diff --git a/docs/plugins/inspect/plugin-gdkpixbuf.xml b/docs/plugins/inspect/plugin-gdkpixbuf.xml
index 8b27462..72211c3 100644
--- a/docs/plugins/inspect/plugin-gdkpixbuf.xml
+++ b/docs/plugins/inspect/plugin-gdkpixbuf.xml
@@ -31,6 +31,27 @@
       </pads>
     </element>
     <element>
+      <name>gdkpixbufoverlay</name>
+      <longname>GdkPixbuf Overlay</longname>
+      <class>Filter/Effect/Video</class>
+      <description>Overlay an image onto a video stream</description>
+      <author>Tim-Philipp Müller &lt;tim centricular net&gt;</author>
+      <pads>
+        <caps>
+          <name>sink</name>
+          <direction>sink</direction>
+          <presence>always</presence>
+          <details>video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc){ I420, YV12, AYUV, YUY2, UYVY, v308, v210, v216, Y41B, Y42B, Y444, Y800, Y16 , NV12, NV21, UYVP, A420, YUV9, IYU1 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
+        </caps>
+        <caps>
+          <name>src</name>
+          <direction>source</direction>
+          <presence>always</presence>
+          <details>video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc){ I420, YV12, AYUV, YUY2, UYVY, v308, v210, v216, Y41B, Y42B, Y444, Y800, Y16 , NV12, NV21, UYVP, A420, YUV9, IYU1 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
+        </caps>
+      </pads>
+    </element>
+    <element>
       <name>gdkpixbufscale</name>
       <longname>GdkPixbuf image scaler</longname>
       <class>Filter/Effect/Video</class>
diff --git a/docs/plugins/inspect/plugin-png.xml b/docs/plugins/inspect/plugin-png.xml
index 7cc2823..9561c4f 100644
--- a/docs/plugins/inspect/plugin-png.xml
+++ b/docs/plugins/inspect/plugin-png.xml
@@ -52,4 +52,4 @@
       </pads>
     </element>
   </elements>
-</plugin>
\ No newline at end of file
+</plugin>
diff --git a/docs/plugins/inspect/plugin-wavpack.xml b/docs/plugins/inspect/plugin-wavpack.xml
index d5b7cbd..88ba068 100644
--- a/docs/plugins/inspect/plugin-wavpack.xml
+++ b/docs/plugins/inspect/plugin-wavpack.xml
@@ -26,7 +26,7 @@
           <name>src</name>
           <direction>source</direction>
           <presence>always</presence>
-          <details>audio/x-raw-int, width=(int)32, depth=(int)[ 1, 32 ], channels=(int)[ 1, 8 ], rate=(int)[ 6000, 192000 ], endianness=(int)1234, signed=(boolean)true</details>
+          <details>audio/x-raw-int, width=(int)8, depth=(int)8, channels=(int)[ 1, 8 ], rate=(int)[ 6000, 192000 ], endianness=(int)1234, signed=(boolean)true; audio/x-raw-int, width=(int)16, depth=(int)16, channels=(int)[ 1, 8 ], rate=(int)[ 6000, 192000 ], endianness=(int)1234, signed=(boolean)true; audio/x-raw-int, width=(int)32, depth=(int)32, channels=(int)[ 1, 8 ], rate=(int)[ 6000, 192000 ], endianness=(int)1234, signed=(boolean)true</details>
         </caps>
       </pads>
     </element>
@@ -41,13 +41,13 @@
           <name>sink</name>
           <direction>sink</direction>
           <presence>always</presence>
-          <details>audio/x-raw-int, width=(int)32, depth=(int)[ 1, 32 ], endianness=(int)1234, channels=(int)[ 1, 8 ], rate=(int)[ 6000, 192000 ], signed=(boolean)true</details>
+          <details>audio/x-raw-int, width=(int)32, depth=(int){ 24, 32 }, endianness=(int)1234, channels=(int)[ 1, 8 ], rate=(int)[ 6000, 192000 ], signed=(boolean)true</details>
         </caps>
         <caps>
           <name>src</name>
           <direction>source</direction>
           <presence>always</presence>
-          <details>audio/x-wavpack, width=(int)[ 1, 32 ], channels=(int)[ 1, 2 ], rate=(int)[ 6000, 192000 ], framed=(boolean)true</details>
+          <details>audio/x-wavpack, width=(int)[ 1, 32 ], channels=(int)[ 1, 8 ], rate=(int)[ 6000, 192000 ], framed=(boolean)true</details>
         </caps>
         <caps>
           <name>wvcsrc</name>
diff --git a/ext/flac/gstflacdec.c b/ext/flac/gstflacdec.c
index f553f64..37f697d 100644
--- a/ext/flac/gstflacdec.c
+++ b/ext/flac/gstflacdec.c
@@ -415,6 +415,26 @@
   return TRUE;
 }
 
+static gboolean
+gst_flac_dec_handle_decoder_error (GstFlacDec * dec, gboolean msg)
+{
+  gboolean ret;
+
+  dec->error_count++;
+  if (dec->error_count > 10) {
+    if (msg)
+      GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), (NULL));
+    dec->last_flow = GST_FLOW_ERROR;
+    ret = TRUE;
+  } else {
+    GST_DEBUG_OBJECT (dec, "ignoring error for now at count %d",
+        dec->error_count);
+    ret = FALSE;
+  }
+
+  return ret;
+}
+
 static void
 gst_flac_dec_metadata_cb (const FLAC__StreamDecoder * decoder,
     const FLAC__StreamMetadata * metadata, void *client_data)
@@ -495,8 +515,8 @@
       break;
   }
 
-  GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("%s (%d)", error, status));
-  dec->last_flow = GST_FLOW_ERROR;
+  if (gst_flac_dec_handle_decoder_error (dec, FALSE))
+    GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("%s (%d)", error, status));
 }
 
 static FLAC__StreamDecoderReadStatus
@@ -674,6 +694,8 @@
   gst_buffer_unmap (outbuf, &map);
 
   GST_DEBUG_OBJECT (flacdec, "pushing %d samples", samples);
+  if (flacdec->error_count)
+    flacdec->error_count--;
 
   ret = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (flacdec), outbuf, 1);
 
diff --git a/ext/flac/gstflacdec.h b/ext/flac/gstflacdec.h
index 2386a12..12447f8 100644
--- a/ext/flac/gstflacdec.h
+++ b/ext/flac/gstflacdec.h
@@ -58,6 +58,8 @@
   /* from the stream info, needed for scanning */
   guint16        min_blocksize;
   guint16        max_blocksize;
+
+  gint           error_count;
 };
 
 struct _GstFlacDecClass {
diff --git a/ext/flac/gstflacenc.c b/ext/flac/gstflacenc.c
index 9c7a3ee..f39b98f 100644
--- a/ext/flac/gstflacenc.c
+++ b/ext/flac/gstflacenc.c
@@ -203,7 +203,7 @@
 
 #define DEFAULT_QUALITY 5
 #define DEFAULT_PADDING 0
-#define DEFAULT_SEEKPOINTS 0
+#define DEFAULT_SEEKPOINTS -10
 
 #define GST_TYPE_FLAC_ENC_QUALITY (gst_flac_enc_quality_get_type ())
 static GType
diff --git a/ext/gdk_pixbuf/Makefile.am b/ext/gdk_pixbuf/Makefile.am
index cf5265c..32a82ef 100644
--- a/ext/gdk_pixbuf/Makefile.am
+++ b/ext/gdk_pixbuf/Makefile.am
@@ -1,12 +1,15 @@
 plugin_LTLIBRARIES = libgstgdkpixbuf.la
 
-libgstgdkpixbuf_la_SOURCES = gstgdkpixbuf.c gstgdkpixbufsink.c pixbufscale.c
+libgstgdkpixbuf_la_SOURCES = gstgdkpixbuf.c gstgdkpixbufsink.c pixbufscale.c \
+	gstgdkpixbufoverlay.c
 libgstgdkpixbuf_la_CFLAGS = \
 	$(GST_PLUGINS_BASE_CFLAGS) \
+	$(GST_CONTROLLER_CFLAGS) \
 	$(GST_BASE_CFLAGS) \
 	$(GST_CFLAGS) $(GDK_PIXBUF_CFLAGS)
 libgstgdkpixbuf_la_LIBADD = \
 	$(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) \
+	$(GST_CONTROLLER_LIBS) \
 	$(GST_BASE_LIBS) \
 	$(GST_LIBS) $(GDK_PIXBUF_LIBS)
 libgstgdkpixbuf_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
@@ -14,6 +17,7 @@
 
 noinst_HEADERS = \
 	gstgdkpixbuf.h \
+	gstgdkpixbufoverlay.h \
 	gstgdkpixbufsink.h \
 	pixbufscale.h \
 	gstgdkanimation.h
diff --git a/ext/gdk_pixbuf/gstgdkpixbuf.c b/ext/gdk_pixbuf/gstgdkpixbuf.c
index 588e165..1f51a24 100644
--- a/ext/gdk_pixbuf/gstgdkpixbuf.c
+++ b/ext/gdk_pixbuf/gstgdkpixbuf.c
@@ -27,6 +27,7 @@
 #include <string.h>
 
 #include "gstgdkpixbuf.h"
+#include "gstgdkpixbufoverlay.h"
 #include "gstgdkpixbufsink.h"
 #include "pixbufscale.h"
 
@@ -589,6 +590,10 @@
       gst_gdk_pixbuf_type_find, NULL, GST_CAPS_ANY, NULL);
 #endif
 
+  if (!gst_element_register (plugin, "gdkpixbufoverlay", GST_RANK_NONE,
+          GST_TYPE_GDK_PIXBUF_OVERLAY))
+    return FALSE;
+
   if (!gst_element_register (plugin, "gdkpixbufsink", GST_RANK_NONE,
           GST_TYPE_GDK_PIXBUF_SINK))
     return FALSE;
diff --git a/ext/gdk_pixbuf/gstgdkpixbufoverlay.c b/ext/gdk_pixbuf/gstgdkpixbufoverlay.c
new file mode 100644
index 0000000..6ea95c7
--- /dev/null
+++ b/ext/gdk_pixbuf/gstgdkpixbufoverlay.c
@@ -0,0 +1,508 @@
+/* GStreamer GdkPixbuf overlay
+ * Copyright (C) 2012 Tim-Philipp Müller <tim centricular net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
+ * Boston, MA 02110-1335, USA.
+ */
+
+/**
+ * SECTION:element-gdkpixbufoverlay
+ * @see_also:
+ *
+ * The gdkpixbufoverlay element overlays an image loaded from file onto
+ * a video stream.
+ *
+ * Changing the positioning or overlay width and height properties at runtime
+ * is supported, but it might be prudent to to protect the property setting
+ * code with GST_BASE_TRANSFORM_LOCK and GST_BASE_TRANSFORM_UNLOCK, as
+ * g_object_set() is not atomic for multiple properties passed in one go.
+ *
+ * Changing the image at runtime is currently not supported.
+ *
+ * Negative offsets are also not yet supported.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch -v videotestsrc ! gdkpixbufoverlay location=image.png ! autovideosink
+ * ]|
+ * Overlays the image in image.png onto the test video picture produced by
+ * videotestsrc.
+ * </refsect2>
+ *
+ * Since: 0.10.33
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstgdkpixbufoverlay.h"
+
+GST_DEBUG_CATEGORY_STATIC (gdkpixbufoverlay_debug);
+#define GST_CAT_DEFAULT gdkpixbufoverlay_debug
+
+static void gst_gdk_pixbuf_overlay_set_property (GObject * object,
+    guint property_id, const GValue * value, GParamSpec * pspec);
+static void gst_gdk_pixbuf_overlay_get_property (GObject * object,
+    guint property_id, GValue * value, GParamSpec * pspec);
+static void gst_gdk_pixbuf_overlay_finalize (GObject * object);
+
+static gboolean gst_gdk_pixbuf_overlay_start (GstBaseTransform * trans);
+static gboolean gst_gdk_pixbuf_overlay_stop (GstBaseTransform * trans);
+static GstFlowReturn
+gst_gdk_pixbuf_overlay_transform_ip (GstBaseTransform * trans, GstBuffer * buf);
+static void gst_gdk_pixbuf_overlay_before_transform (GstBaseTransform * trans,
+    GstBuffer * outbuf);
+static gboolean
+gst_gdk_pixbuf_overlay_set_caps (GstBaseTransform * trans, GstCaps * incaps,
+    GstCaps * outcaps);
+
+enum
+{
+  PROP_0,
+  PROP_LOCATION,
+  PROP_OFFSET_X,
+  PROP_OFFSET_Y,
+  PROP_RELATIVE_X,
+  PROP_RELATIVE_Y,
+  PROP_OVERLAY_WIDTH,
+  PROP_OVERLAY_HEIGHT
+};
+
+#define VIDEO_CAPS \
+    GST_VIDEO_CAPS_BGRx ";" \
+    GST_VIDEO_CAPS_RGB ";" \
+    GST_VIDEO_CAPS_BGR ";" \
+    GST_VIDEO_CAPS_RGBx ";" \
+    GST_VIDEO_CAPS_xRGB ";" \
+    GST_VIDEO_CAPS_xBGR ";" \
+    GST_VIDEO_CAPS_RGBA ";" \
+    GST_VIDEO_CAPS_BGRA ";" \
+    GST_VIDEO_CAPS_ARGB ";" \
+    GST_VIDEO_CAPS_ABGR ";" \
+    GST_VIDEO_CAPS_YUV ("{I420, YV12, AYUV, YUY2, UYVY, v308, v210," \
+        " v216, Y41B, Y42B, Y444, Y800, Y16, NV12, NV21, UYVP, A420," \
+        " YUV9, IYU1}")
+
+static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (VIDEO_CAPS)
+    );
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (VIDEO_CAPS)
+    );
+
+GST_BOILERPLATE (GstGdkPixbufOverlay, gst_gdk_pixbuf_overlay,
+    GstVideoFilter, GST_TYPE_VIDEO_FILTER);
+
+static void
+gst_gdk_pixbuf_overlay_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_static_pad_template (element_class, &sink_template);
+  gst_element_class_add_static_pad_template (element_class, &src_template);
+
+  gst_element_class_set_details_simple (element_class,
+      "GdkPixbuf Overlay", "Filter/Effect/Video",
+      "Overlay an image onto a video stream",
+      "Tim-Philipp Müller <tim centricular net>");
+}
+
+static void
+gst_gdk_pixbuf_overlay_class_init (GstGdkPixbufOverlayClass * klass)
+{
+  GstBaseTransformClass *basetrans_class = GST_BASE_TRANSFORM_CLASS (klass);
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->set_property = gst_gdk_pixbuf_overlay_set_property;
+  gobject_class->get_property = gst_gdk_pixbuf_overlay_get_property;
+  gobject_class->finalize = gst_gdk_pixbuf_overlay_finalize;
+
+  basetrans_class->start = GST_DEBUG_FUNCPTR (gst_gdk_pixbuf_overlay_start);
+  basetrans_class->stop = GST_DEBUG_FUNCPTR (gst_gdk_pixbuf_overlay_stop);
+  basetrans_class->set_caps =
+      GST_DEBUG_FUNCPTR (gst_gdk_pixbuf_overlay_set_caps);
+  basetrans_class->transform_ip =
+      GST_DEBUG_FUNCPTR (gst_gdk_pixbuf_overlay_transform_ip);
+  basetrans_class->before_transform =
+      GST_DEBUG_FUNCPTR (gst_gdk_pixbuf_overlay_before_transform);
+
+  g_object_class_install_property (gobject_class, PROP_LOCATION,
+      g_param_spec_string ("location", "location",
+          "Location of image file to overlay", NULL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_OFFSET_X,
+      g_param_spec_int ("offset-x", "X Offset",
+          "Horizontal offset of overlay image in pixels from top-left corner "
+          "of video image", G_MININT, G_MAXINT, 0,
+          GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE
+          | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_OFFSET_Y,
+      g_param_spec_int ("offset-y", "Y Offset",
+          "Vertical offset of overlay image in pixels from top-left corner "
+          "of video image", G_MININT, G_MAXINT, 0,
+          GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE
+          | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_RELATIVE_X,
+      g_param_spec_double ("relative-x", "Relative X Offset",
+          "Horizontal offset of overlay image in fractions of video image "
+          "width, from top-left corner of video image", 0.0, 1.0, 0.0,
+          GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE
+          | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_RELATIVE_Y,
+      g_param_spec_double ("relative-y", "Relative Y Offset",
+          "Vertical offset of overlay image in fractions of video image "
+          "height, from top-left corner of video image", 0.0, 1.0, 0.0,
+          GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE
+          | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_OVERLAY_WIDTH,
+      g_param_spec_int ("overlay-width", "Overlay Width",
+          "Width of overlay image in pixels (0 = same as overlay image)", 0,
+          G_MAXINT, 0,
+          GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE
+          | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_OVERLAY_HEIGHT,
+      g_param_spec_int ("overlay-height", "Overlay Height",
+          "Height of overlay image in pixels (0 = same as overlay image)", 0,
+          G_MAXINT, 0,
+          GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE
+          | G_PARAM_STATIC_STRINGS));
+
+  GST_DEBUG_CATEGORY_INIT (gdkpixbufoverlay_debug, "gdkpixbufoverlay", 0,
+      "debug category for gdkpixbufoverlay element");
+}
+
+static void
+gst_gdk_pixbuf_overlay_init (GstGdkPixbufOverlay * overlay,
+    GstGdkPixbufOverlayClass * overlay_class)
+{
+  overlay->offset_x = 0;
+  overlay->offset_y = 0;
+
+  overlay->relative_x = 0.0;
+  overlay->relative_y = 0.0;
+
+  overlay->overlay_width = 0;
+  overlay->overlay_height = 0;
+}
+
+void
+gst_gdk_pixbuf_overlay_set_property (GObject * object, guint property_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstGdkPixbufOverlay *overlay = GST_GDK_PIXBUF_OVERLAY (object);
+
+  GST_OBJECT_LOCK (overlay);
+
+  switch (property_id) {
+    case PROP_LOCATION:
+      g_free (overlay->location);
+      overlay->location = g_value_dup_string (value);
+      break;
+    case PROP_OFFSET_X:
+      overlay->offset_x = g_value_get_int (value);
+      overlay->update_composition = TRUE;
+      break;
+    case PROP_OFFSET_Y:
+      overlay->offset_y = g_value_get_int (value);
+      overlay->update_composition = TRUE;
+      break;
+    case PROP_RELATIVE_X:
+      overlay->relative_x = g_value_get_double (value);
+      overlay->update_composition = TRUE;
+      break;
+    case PROP_RELATIVE_Y:
+      overlay->relative_y = g_value_get_double (value);
+      overlay->update_composition = TRUE;
+      break;
+    case PROP_OVERLAY_WIDTH:
+      overlay->overlay_width = g_value_get_int (value);
+      overlay->update_composition = TRUE;
+      break;
+    case PROP_OVERLAY_HEIGHT:
+      overlay->overlay_height = g_value_get_int (value);
+      overlay->update_composition = TRUE;
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+
+  GST_OBJECT_UNLOCK (overlay);
+}
+
+void
+gst_gdk_pixbuf_overlay_get_property (GObject * object, guint property_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstGdkPixbufOverlay *overlay = GST_GDK_PIXBUF_OVERLAY (object);
+
+  GST_OBJECT_LOCK (overlay);
+
+  switch (property_id) {
+    case PROP_LOCATION:
+      g_value_set_string (value, overlay->location);
+      break;
+    case PROP_OFFSET_X:
+      g_value_set_int (value, overlay->offset_x);
+      break;
+    case PROP_OFFSET_Y:
+      g_value_set_int (value, overlay->offset_y);
+      break;
+    case PROP_RELATIVE_X:
+      g_value_set_double (value, overlay->relative_x);
+      break;
+    case PROP_RELATIVE_Y:
+      g_value_set_double (value, overlay->relative_y);
+      break;
+    case PROP_OVERLAY_WIDTH:
+      g_value_set_int (value, overlay->overlay_width);
+      break;
+    case PROP_OVERLAY_HEIGHT:
+      g_value_set_int (value, overlay->overlay_height);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+
+  GST_OBJECT_UNLOCK (overlay);
+}
+
+void
+gst_gdk_pixbuf_overlay_finalize (GObject * object)
+{
+  GstGdkPixbufOverlay *overlay = GST_GDK_PIXBUF_OVERLAY (object);
+
+  g_free (overlay->location);
+  overlay->location = NULL;
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+gst_gdk_pixbuf_overlay_load_image (GstGdkPixbufOverlay * overlay, GError ** err)
+{
+  GdkPixbuf *pixbuf;
+  guint8 *pixels, *p;
+  gint width, height, stride, w, h;
+
+  pixbuf = gdk_pixbuf_new_from_file (overlay->location, err);
+
+  if (pixbuf == NULL)
+    return FALSE;
+
+  if (!gdk_pixbuf_get_has_alpha (pixbuf)) {
+    GdkPixbuf *alpha_pixbuf;
+
+    /* FIXME: we could do this much more efficiently ourselves below, but
+     * we're lazy for now */
+    /* FIXME: perhaps expose substitute_color via properties */
+    alpha_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
+    g_object_unref (pixbuf);
+    pixbuf = alpha_pixbuf;
+  }
+
+  width = gdk_pixbuf_get_width (pixbuf);
+  height = gdk_pixbuf_get_height (pixbuf);
+  stride = gdk_pixbuf_get_rowstride (pixbuf);
+  pixels = gdk_pixbuf_get_pixels (pixbuf);
+
+  /* the memory layout in GdkPixbuf is R-G-B-A, we want:
+   *  - B-G-R-A on little-endian platforms
+   *  - A-R-G-B on big-endian platforms
+   */
+  for (h = 0; h < height; ++h) {
+    p = pixels + (h * stride);
+    for (w = 0; w < width; ++w) {
+      guint8 tmp;
+
+      /* R-G-B-A ==> B-G-R-A */
+      tmp = p[0];
+      p[0] = p[2];
+      p[2] = tmp;
+
+      if (G_BYTE_ORDER == G_BIG_ENDIAN) {
+        /* B-G-R-A ==> A-R-G-B */
+        /* we can probably assume sane alignment */
+        *((guint32 *) p) = GUINT32_SWAP_LE_BE (*((guint32 *) p));
+      }
+
+      p += 4;
+    }
+  }
+
+  overlay->pixels = gst_buffer_new ();
+  GST_BUFFER_DATA (overlay->pixels) = pixels;
+  /* assume we have row padding even for the last row */
+  GST_BUFFER_SIZE (overlay->pixels) = height * stride;
+  /* transfer ownership of pixbuf to buffer */
+  GST_BUFFER_MALLOCDATA (overlay->pixels) = (guint8 *) pixbuf;
+  GST_BUFFER_FREE_FUNC (overlay->pixels) = (GFreeFunc) g_object_unref;
+
+  overlay->pixels_width = width;
+  overlay->pixels_height = height;
+  overlay->pixels_stride = stride;
+
+  overlay->update_composition = TRUE;
+
+  GST_INFO_OBJECT (overlay, "Loaded image, %d x %d", width, height);
+  return TRUE;
+}
+
+static gboolean
+gst_gdk_pixbuf_overlay_start (GstBaseTransform * trans)
+{
+  GstGdkPixbufOverlay *overlay = GST_GDK_PIXBUF_OVERLAY (trans);
+  GError *err = NULL;
+
+  if (overlay->location != NULL) {
+    if (!gst_gdk_pixbuf_overlay_load_image (overlay, &err))
+      goto error_loading_image;
+
+    gst_base_transform_set_passthrough (trans, FALSE);
+  } else {
+    GST_WARNING_OBJECT (overlay, "no image location set, doing nothing");
+    gst_base_transform_set_passthrough (trans, TRUE);
+  }
+
+  return TRUE;
+
+/* ERRORS */
+error_loading_image:
+  {
+    GST_ELEMENT_ERROR (overlay, RESOURCE, OPEN_READ,
+        ("Could not load overlay image."), ("%s", err->message));
+    g_error_free (err);
+    return FALSE;
+  }
+}
+
+static gboolean
+gst_gdk_pixbuf_overlay_stop (GstBaseTransform * trans)
+{
+  GstGdkPixbufOverlay *overlay = GST_GDK_PIXBUF_OVERLAY (trans);
+
+  if (overlay->comp) {
+    gst_video_overlay_composition_unref (overlay->comp);
+    overlay->comp = NULL;
+  }
+
+  gst_buffer_replace (&overlay->pixels, NULL);
+
+  return TRUE;
+}
+
+static gboolean
+gst_gdk_pixbuf_overlay_set_caps (GstBaseTransform * trans, GstCaps * incaps,
+    GstCaps * outcaps)
+{
+  GstGdkPixbufOverlay *overlay = GST_GDK_PIXBUF_OVERLAY (trans);
+  GstVideoFormat video_format;
+  int w, h;
+
+  if (!gst_video_format_parse_caps (incaps, &video_format, &w, &h))
+    return FALSE;
+
+  overlay->format = video_format;
+  overlay->width = w;
+  overlay->height = h;
+  return TRUE;
+}
+
+static void
+gst_gdk_pixbuf_overlay_update_composition (GstGdkPixbufOverlay * overlay)
+{
+  GstVideoOverlayComposition *comp;
+  GstVideoOverlayRectangle *rect;
+  gint x, y, width, height;
+
+  x = overlay->offset_x + (overlay->relative_x * overlay->pixels_width);
+  y = overlay->offset_y + (overlay->relative_y * overlay->pixels_height);
+
+  /* FIXME: this should work, but seems to crash */
+  if (x < 0)
+    x = 0;
+  if (y < 0)
+    y = 0;
+
+  width = overlay->overlay_width;
+  if (width == 0)
+    width = overlay->pixels_width;
+
+  height = overlay->overlay_height;
+  if (height == 0)
+    height = overlay->pixels_height;
+
+  GST_DEBUG_OBJECT (overlay, "overlay image dimensions: %d x %d",
+      overlay->pixels_width, overlay->pixels_height);
+  GST_DEBUG_OBJECT (overlay, "properties: x,y: %d,%d (%g%%,%g%%) - WxH: %dx%d",
+      overlay->offset_x, overlay->offset_y,
+      overlay->relative_x * 100.0, overlay->relative_y * 100.0,
+      overlay->overlay_height, overlay->overlay_width);
+  GST_DEBUG_OBJECT (overlay, "overlay rendered: %d x %d @ %d,%d (onto %d x %d)",
+      width, height, x, y, overlay->width, overlay->height);
+
+  rect = gst_video_overlay_rectangle_new_argb (overlay->pixels,
+      overlay->pixels_width, overlay->pixels_height, overlay->pixels_stride,
+      x, y, width, height, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
+
+  comp = gst_video_overlay_composition_new (rect);
+  gst_video_overlay_rectangle_unref (rect);
+
+  if (overlay->comp)
+    gst_video_overlay_composition_unref (overlay->comp);
+  overlay->comp = comp;
+}
+
+static void
+gst_gdk_pixbuf_overlay_before_transform (GstBaseTransform * trans,
+    GstBuffer * outbuf)
+{
+  GstClockTime stream_time;
+
+  stream_time = gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME,
+      GST_BUFFER_TIMESTAMP (outbuf));
+
+  if (GST_CLOCK_TIME_IS_VALID (stream_time))
+    gst_object_sync_values (G_OBJECT (trans), stream_time);
+}
+
+static GstFlowReturn
+gst_gdk_pixbuf_overlay_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
+{
+  GstGdkPixbufOverlay *overlay = GST_GDK_PIXBUF_OVERLAY (trans);
+
+  GST_OBJECT_LOCK (overlay);
+
+  if (G_UNLIKELY (overlay->update_composition)) {
+    gst_gdk_pixbuf_overlay_update_composition (overlay);
+    overlay->update_composition = FALSE;
+  }
+
+  GST_OBJECT_UNLOCK (overlay);
+
+  gst_video_overlay_composition_blend (overlay->comp, buf);
+
+  return GST_FLOW_OK;
+}
diff --git a/ext/gdk_pixbuf/gstgdkpixbufoverlay.h b/ext/gdk_pixbuf/gstgdkpixbufoverlay.h
new file mode 100644
index 0000000..9c94090
--- /dev/null
+++ b/ext/gdk_pixbuf/gstgdkpixbufoverlay.h
@@ -0,0 +1,87 @@
+/* GStreamer GdkPixbuf overlay
+ * Copyright (C) 2012 Tim-Philipp Müller <tim centricular net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _GST_GDK_PIXBUF_OVERLAY_H_
+#define _GST_GDK_PIXBUF_OVERLAY_H_
+
+#include <gst/video/video.h>
+#include <gst/video/gstvideofilter.h>
+#include <gst/video/video-overlay-composition.h>
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_GDK_PIXBUF_OVERLAY   (gst_gdk_pixbuf_overlay_get_type())
+#define GST_GDK_PIXBUF_OVERLAY(obj)   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GDK_PIXBUF_OVERLAY,GstGdkPixbufOverlay))
+#define GST_GDK_PIXBUF_OVERLAY_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GDK_PIXBUF_OVERLAY,GstGdkPixbufOverlayClass))
+#define GST_IS_GDK_PIXBUF_OVERLAY(obj)   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GDK_PIXBUF_OVERLAY))
+#define GST_IS_GDK_PIXBUF_OVERLAY_CLASS(obj)   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GDK_PIXBUF_OVERLAY))
+
+typedef struct _GstGdkPixbufOverlay GstGdkPixbufOverlay;
+typedef struct _GstGdkPixbufOverlayClass GstGdkPixbufOverlayClass;
+
+/**
+ * GstGdkPixbufOverlay:
+ *
+ * The opaque element instance structure.
+ */
+struct _GstGdkPixbufOverlay
+{
+  GstVideoFilter               videofilter;
+
+  /* negotiated format */
+  GstVideoFormat               format;
+  gint                         width;
+  gint                         height;
+
+  /* properties */
+  gchar                      * location;
+
+  gint                         offset_x;
+  gint                         offset_y;
+
+  gdouble                      relative_x;
+  gdouble                      relative_y;
+
+  gint                         overlay_width;
+  gint                         overlay_height;
+
+  /* the loaded image */
+  GstBuffer                  * pixels;
+  guint                        pixels_width;
+  guint                        pixels_height;
+  guint                        pixels_stride;
+
+  GstVideoOverlayComposition * comp;
+
+  /* render position or dimension has changed */
+  gboolean                     update_composition;
+};
+
+struct _GstGdkPixbufOverlayClass
+{
+  GstVideoFilterClass  videofilter_class;
+};
+
+GType gst_gdk_pixbuf_overlay_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/ext/libpng/gstpngdec.c b/ext/libpng/gstpngdec.c
index 0c10b4c..9e0cbe7 100644
--- a/ext/libpng/gstpngdec.c
+++ b/ext/libpng/gstpngdec.c
@@ -61,7 +61,8 @@
 GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ RGBA, RGB }"))
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
+        ("{ RGBA, RGB, ARGB64, GRAY8, GRAY16_BE }"))
     );
 
 static GstStaticPadTemplate gst_pngdec_sink_pad_template =
@@ -406,15 +407,15 @@
 
   /* Get bits per channel */
   bpc = png_get_bit_depth (pngdec->png, pngdec->info);
-  if (bpc > 8) {
-    /* Add alpha channel if 16-bit depth */
-    png_set_add_alpha (pngdec->png, 0xffff, PNG_FILLER_BEFORE);
-    png_set_swap (pngdec->png);
-  }
 
   /* Get Color type */
   color_type = png_get_color_type (pngdec->png, pngdec->info);
 
+  /* Add alpha channel if 16-bit depth, but not for GRAY images */
+  if ((bpc > 8) && (color_type != PNG_COLOR_TYPE_GRAY)) {
+    png_set_add_alpha (pngdec->png, 0xffff, PNG_FILLER_BEFORE);
+    png_set_swap (pngdec->png);
+  }
 #if 0
   /* We used to have this HACK to reverse the outgoing bytes, but the problem
    * that originally required the hack seems to have been in ffmpegcolorspace's
@@ -424,11 +425,16 @@
     png_set_bgr (pngdec->png);
 #endif
 
-  /* Gray scale converted to RGB and upscaled to 8 bits */
+  /* Gray scale with alpha channel converted to RGB */
+  if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
+    GST_LOG_OBJECT (pngdec,
+        "converting grayscale png with alpha channel to RGB");
+    png_set_gray_to_rgb (pngdec->png);
+  }
+
+  /* Gray scale converted to upscaled to 8 bits */
   if ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
       (color_type == PNG_COLOR_TYPE_GRAY)) {
-    GST_LOG_OBJECT (pngdec, "converting grayscale png to RGB");
-    png_set_gray_to_rgb (pngdec->png);
     if (bpc < 8) {              /* Convert to 8 bits */
       GST_LOG_OBJECT (pngdec, "converting grayscale image to 8 bits");
 #if PNG_LIBPNG_VER < 10400
@@ -466,7 +472,18 @@
       break;
     case PNG_COLOR_TYPE_RGB_ALPHA:
       GST_LOG_OBJECT (pngdec, "we have an alpha channel, depth is 32 bits");
-      format = GST_VIDEO_FORMAT_RGBA;
+      if (bpc == 1)
+        format = GST_VIDEO_FORMAT_RGBA;
+      else
+        format = GST_VIDEO_FORMAT_ARGB64;
+      break;
+    case PNG_COLOR_TYPE_GRAY:
+      GST_LOG_OBJECT (pngdec,
+          "We have an gray image, depth is 8 or 16 (be) bits");
+      if (bpc == 1)
+        format = GST_VIDEO_FORMAT_GRAY8;
+      else
+        format = GST_VIDEO_FORMAT_GRAY16_BE;
       break;
     default:
       GST_ELEMENT_ERROR (pngdec, STREAM, NOT_IMPLEMENTED, (NULL),
diff --git a/ext/libpng/gstpngenc.c b/ext/libpng/gstpngenc.c
index ebdc369..963405a 100644
--- a/ext/libpng/gstpngenc.c
+++ b/ext/libpng/gstpngenc.c
@@ -64,7 +64,7 @@
 GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ RGBA, RGB, GRAY8 }"))
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ RGBA, RGB, GRAY8, GRAY16_BE }"))
     );
 
 /* static GstElementClass *parent_class = NULL; */
@@ -153,12 +153,19 @@
   switch (GST_VIDEO_INFO_FORMAT (&info)) {
     case GST_VIDEO_FORMAT_RGBA:
       pngenc->png_color_type = PNG_COLOR_TYPE_RGBA;
+      pngenc->depth = 8;
       break;
     case GST_VIDEO_FORMAT_RGB:
       pngenc->png_color_type = PNG_COLOR_TYPE_RGB;
+      pngenc->depth = 8;
       break;
     case GST_VIDEO_FORMAT_GRAY8:
       pngenc->png_color_type = PNG_COLOR_TYPE_GRAY;
+      pngenc->depth = 8;
+      break;
+    case GST_VIDEO_FORMAT_GRAY16_BE:
+      pngenc->png_color_type = PNG_COLOR_TYPE_GRAY;
+      pngenc->depth = 16;
       break;
     default:
       ret = FALSE;
@@ -314,7 +321,7 @@
       pngenc->png_info_ptr,
       pngenc->width,
       pngenc->height,
-      8,
+      pngenc->depth,
       pngenc->png_color_type,
       PNG_INTERLACE_NONE,
       PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
diff --git a/ext/libpng/gstpngenc.h b/ext/libpng/gstpngenc.h
index ff5b94e..ba306b9 100644
--- a/ext/libpng/gstpngenc.h
+++ b/ext/libpng/gstpngenc.h
@@ -52,6 +52,7 @@
 
   GstVideoInfo info;
   gint png_color_type;
+  gint depth;
   gint width;
   gint height;
   guint compression_level;
diff --git a/ext/speex/gstspeexdec.c b/ext/speex/gstspeexdec.c
index 6032341..7027d20 100644
--- a/ext/speex/gstspeexdec.c
+++ b/ext/speex/gstspeexdec.c
@@ -310,8 +310,9 @@
 
   GST_INFO_OBJECT (dec, "tags: %" GST_PTR_FORMAT, list);
 
-  gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (dec),
-      gst_event_new_tag (list));
+  gst_audio_decoder_merge_tags (GST_AUDIO_DECODER (dec), list,
+      GST_TAG_MERGE_REPLACE);
+  gst_tag_list_free (list);
 
   g_free (encoder);
   g_free (ver);
diff --git a/ext/wavpack/gstwavpackstreamreader.c b/ext/wavpack/gstwavpackstreamreader.c
index 074a2e7..da1fdc2 100644
--- a/ext/wavpack/gstwavpackstreamreader.c
+++ b/ext/wavpack/gstwavpackstreamreader.c
@@ -78,9 +78,10 @@
 
   GST_DEBUG ("Pushing back one byte: 0x%x", c);
 
+  if (rid->position == 0)
+    return rid->position;
+
   rid->position -= 1;
-  if (rid->position < 0)
-    rid->position = 0;
   return rid->position;
 }
 
diff --git a/gst/audioparsers/gstflacparse.c b/gst/audioparsers/gstflacparse.c
index f5ad169..f50a057 100644
--- a/gst/audioparsers/gstflacparse.c
+++ b/gst/audioparsers/gstflacparse.c
@@ -378,7 +378,8 @@
 
 static FrameHeaderCheckReturn
 gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
-    const guint8 * data, guint size, gboolean set, guint16 * block_size_ret)
+    const guint8 * data, guint size, gboolean set, guint16 * block_size_ret,
+    gboolean * suspect)
 {
   GstBitReader reader = GST_BIT_READER_INIT (data, size);
   guint8 blocking_strategy;
@@ -572,6 +573,8 @@
         /* TODO: can we know we're on the last frame, to avoid warning ? */
         GST_WARNING_OBJECT (flacparse, "Block size is not constant");
         block_size = flacparse->block_size;
+        if (suspect)
+          *suspect = TRUE;
       }
     }
   }
@@ -620,6 +623,7 @@
   guint i, search_start, search_end;
   FrameHeaderCheckReturn header_ret;
   guint16 block_size;
+  gboolean suspect_start = FALSE, suspect_end = FALSE;
   gboolean result = FALSE;
 
   buffer = frame->buffer;
@@ -630,7 +634,7 @@
 
   header_ret =
       gst_flac_parse_frame_header_is_valid (flacparse, map.data, map.size, TRUE,
-      &block_size);
+      &block_size, &suspect_start);
   if (header_ret == FRAME_HEADER_INVALID) {
     *ret = 0;
     goto cleanup;
@@ -650,16 +654,23 @@
 
   for (i = search_start; i < search_end; i++, remaining--) {
     if ((GST_READ_UINT16_BE (map.data + i) & 0xfffe) == 0xfff8) {
+      GST_LOG_OBJECT (flacparse, "possible frame end at offset %d", i);
+      suspect_end = FALSE;
       header_ret =
           gst_flac_parse_frame_header_is_valid (flacparse, map.data + i,
-          remaining, FALSE, NULL);
+          remaining, FALSE, NULL, &suspect_end);
       if (header_ret == FRAME_HEADER_VALID) {
         if (flacparse->check_frame_checksums) {
           guint16 actual_crc = gst_flac_calculate_crc16 (map.data, i - 2);
           guint16 expected_crc = GST_READ_UINT16_BE (map.data + i - 2);
 
-          if (actual_crc != expected_crc)
+          GST_LOG_OBJECT (flacparse,
+              "checking checksum, frame suspect (%d, %d)",
+              suspect_start, suspect_end);
+          if (actual_crc != expected_crc) {
+            GST_DEBUG_OBJECT (flacparse, "checksum did not match");
             continue;
+          }
         }
         *ret = i;
         flacparse->block_size = block_size;
@@ -691,6 +702,15 @@
     }
   }
 
+  /* so we searched to expected end and found nothing,
+   * give up on this frame (start) */
+  if (flacparse->max_framesize && i > 2 * flacparse->max_framesize) {
+    GST_LOG_OBJECT (flacparse,
+        "could not determine valid frame end, discarding frame (start)");
+    *ret = 1;
+    return FALSE;
+  }
+
 need_more:
   max = flacparse->max_framesize + 16;
   if (max == 16)
@@ -1397,7 +1417,7 @@
       flacparse->offset = GST_BUFFER_OFFSET (buffer);
       ret =
           gst_flac_parse_frame_header_is_valid (flacparse,
-          map.data, map.size, TRUE, NULL);
+          map.data, map.size, TRUE, NULL, NULL);
       if (ret != FRAME_HEADER_VALID) {
         GST_ERROR_OBJECT (flacparse,
             "Baseclass didn't provide a complete frame");
diff --git a/gst/deinterlace/gstdeinterlace.c b/gst/deinterlace/gstdeinterlace.c
index e5b0878..e29f38b 100644
--- a/gst/deinterlace/gstdeinterlace.c
+++ b/gst/deinterlace/gstdeinterlace.c
@@ -1984,7 +1984,8 @@
       self->fields = self->new_fields;
     if (self->new_mode != -1)
       self->mode = self->new_mode;
-    self->new_mode = self->new_fields = -1;
+    self->new_mode = -1;
+    self->new_fields = -1;
 
     self->reconfigure = FALSE;
     GST_OBJECT_UNLOCK (self);
diff --git a/gst/deinterlace/tvtime/greedyh.asm b/gst/deinterlace/tvtime/greedyh.asm
index d87b9e3..c710b4a 100644
--- a/gst/deinterlace/tvtime/greedyh.asm
+++ b/gst/deinterlace/tvtime/greedyh.asm
@@ -43,7 +43,7 @@
   gint64 MotionSense;
   gint64 i;
   glong LoopCtr;
-  glong oldbx;
+  glong oldbx = 0;
 
   gint64 QW256B;
   gint64 LastAvg = 0;          //interp value from left qword
@@ -262,7 +262,7 @@
   gint64 MotionSense;
   gint64 i;
   glong LoopCtr;
-  glong oldbx;
+  glong oldbx = 0;
 
   gint64 QW256B;
   gint64 LastAvg = 0;          //interp value from left qword
diff --git a/gst/deinterlace/tvtime/tomsmocomp/SearchLoopTop.inc b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopTop.inc
index 9d6a490..275c7dd 100644
--- a/gst/deinterlace/tvtime/tomsmocomp/SearchLoopTop.inc
+++ b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopTop.inc
@@ -92,7 +92,7 @@
           int64_t Max_Vals  = 0x0000000000000000ull;
           int64_t ShiftMask = 0xfefffefffefffeffull;
 
-          long oldbx;
+          long oldbx = 0;
 
 		// pretend it's indented -->>
         __asm__ __volatile__
diff --git a/gst/flv/gstflvmux.c b/gst/flv/gstflvmux.c
index 8119e9d..555e536 100644
--- a/gst/flv/gstflvmux.c
+++ b/gst/flv/gstflvmux.c
@@ -1165,6 +1165,7 @@
           "streamable=false. Will ignore that and create streamable output "
           "instead");
     }
+    gst_query_unref (query);
   }
 
   header = gst_flv_mux_create_header (mux);
diff --git a/gst/isomp4/gstqtmux.c b/gst/isomp4/gstqtmux.c
index e3064e9..531df78 100644
--- a/gst/isomp4/gstqtmux.c
+++ b/gst/isomp4/gstqtmux.c
@@ -1654,6 +1654,7 @@
           "streamable=false. Will ignore that and create streamable output "
           "instead");
     }
+    gst_query_unref (query);
   }
 
   /* let downstream know we think in BYTES and expect to do seeking later on */
diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c
index 08a53fc..33dedd7 100644
--- a/gst/matroska/matroska-demux.c
+++ b/gst/matroska/matroska-demux.c
@@ -1903,6 +1903,7 @@
   GstMatroskaTrackContext *track = NULL;
   GstSegment seeksegment = { 0, };
   gboolean update = TRUE;
+  gboolean pad_locked = FALSE;
 
   if (pad)
     track = gst_pad_get_element_private (pad);
@@ -2001,6 +2002,7 @@
    * forever. */
   GST_DEBUG_OBJECT (demux, "Waiting for streaming to stop");
   GST_PAD_STREAM_LOCK (demux->common.sinkpad);
+  pad_locked = TRUE;
 
   /* pull mode without index can do some scanning */
   if (!demux->streaming && !entry) {
@@ -2069,13 +2071,17 @@
       (GstTaskFunction) gst_matroska_demux_loop, demux->common.sinkpad);
 
   /* streaming can continue now */
-  GST_PAD_STREAM_UNLOCK (demux->common.sinkpad);
+  if (pad_locked) {
+    GST_PAD_STREAM_UNLOCK (demux->common.sinkpad);
+  }
 
   return TRUE;
 
 seek_error:
   {
-    GST_PAD_STREAM_UNLOCK (demux->common.sinkpad);
+    if (pad_locked) {
+      GST_PAD_STREAM_UNLOCK (demux->common.sinkpad);
+    }
     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("Got a seek error"));
     return FALSE;
   }
diff --git a/gst/matroska/matroska-mux.c b/gst/matroska/matroska-mux.c
index 4b5c8f6..850494f 100644
--- a/gst/matroska/matroska-mux.c
+++ b/gst/matroska/matroska-mux.c
@@ -2361,6 +2361,7 @@
           "streamable=false. Will ignore that and create streamable output "
           "instead");
     }
+    gst_query_unref (query);
   }
 
   if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
diff --git a/gst/rtp/gstrtpdvdepay.c b/gst/rtp/gstrtpdvdepay.c
index ab9a83b..7d81a95 100644
--- a/gst/rtp/gstrtpdvdepay.c
+++ b/gst/rtp/gstrtpdvdepay.c
@@ -336,12 +336,14 @@
       GST_LOG_OBJECT (dvdepay, "got block at location %d", location);
     }
 
-    /* get the byte offset of the dif block */
-    offset = location * 80;
+    if (location != -1) {
+      /* get the byte offset of the dif block */
+      offset = location * 80;
 
-    /* And copy it in, provided the location is sane. */
-    if (offset >= 0 && offset <= dvdepay->frame_size - 80)
-      gst_buffer_fill (dvdepay->acc, offset, payload, 80);
+      /* And copy it in, provided the location is sane. */
+      if (offset <= dvdepay->frame_size - 80)
+        gst_buffer_fill (dvdepay->acc, offset, payload, 80);
+    }
 
     payload += 80;
     payload_len -= 80;
diff --git a/gst/rtsp/gstrtspsrc.c b/gst/rtsp/gstrtspsrc.c
index 448af25..e8e5888 100644
--- a/gst/rtsp/gstrtspsrc.c
+++ b/gst/rtsp/gstrtspsrc.c
@@ -170,6 +170,7 @@
 #define DEFAULT_CONNECTION_SPEED 0
 #define DEFAULT_NAT_METHOD       GST_RTSP_NAT_DUMMY
 #define DEFAULT_DO_RTCP          TRUE
+#define DEFAULT_DO_RTSP_KEEP_ALIVE       TRUE
 #define DEFAULT_PROXY            NULL
 #define DEFAULT_RTP_BLOCKSIZE    0
 #define DEFAULT_USER_ID          NULL
@@ -191,6 +192,7 @@
   PROP_CONNECTION_SPEED,
   PROP_NAT_METHOD,
   PROP_DO_RTCP,
+  PROP_DO_RTSP_KEEP_ALIVE,
   PROP_PROXY,
   PROP_RTP_BLOCKSIZE,
   PROP_USER_ID,
@@ -373,6 +375,20 @@
           DEFAULT_DO_RTCP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
+   * GstRTSPSrc::do-rtsp-keep-alive
+   *
+   * Enable RTSP keep laive support. Some old server don't like RTSP
+   * keep alive and then this property needs to be set to FALSE.
+   *
+   * Since: 0.10.32
+   */
+  g_object_class_install_property (gobject_class, PROP_DO_RTSP_KEEP_ALIVE,
+      g_param_spec_boolean ("do-rtsp-keep-alive", "Do RTSP Keep Alive",
+          "Send RTSP keep alive packets, disable for old incompatible server.",
+          DEFAULT_DO_RTSP_KEEP_ALIVE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
    * GstRTSPSrc::proxy
    *
    * Set the proxy parameters. This has to be a string of the format
@@ -492,6 +508,7 @@
   src->connection_speed = DEFAULT_CONNECTION_SPEED;
   src->nat_method = DEFAULT_NAT_METHOD;
   src->do_rtcp = DEFAULT_DO_RTCP;
+  src->do_rtsp_keep_alive = DEFAULT_DO_RTSP_KEEP_ALIVE;
   gst_rtspsrc_set_proxy (src, DEFAULT_PROXY);
   src->rtp_blocksize = DEFAULT_RTP_BLOCKSIZE;
   src->user_id = g_strdup (DEFAULT_USER_ID);
@@ -650,6 +667,9 @@
     case PROP_DO_RTCP:
       rtspsrc->do_rtcp = g_value_get_boolean (value);
       break;
+    case PROP_DO_RTSP_KEEP_ALIVE:
+      rtspsrc->do_rtsp_keep_alive = g_value_get_boolean (value);
+      break;
     case PROP_PROXY:
       gst_rtspsrc_set_proxy (rtspsrc, g_value_get_string (value));
       break;
@@ -740,6 +760,9 @@
     case PROP_DO_RTCP:
       g_value_set_boolean (value, rtspsrc->do_rtcp);
       break;
+    case PROP_DO_RTSP_KEEP_ALIVE:
+      g_value_set_boolean (value, rtspsrc->do_rtsp_keep_alive);
+      break;
     case PROP_PROXY:
     {
       gchar *str;
@@ -3420,6 +3443,12 @@
   GstRTSPMethod method;
   gchar *control;
 
+  if (src->do_rtsp_keep_alive == FALSE) {
+    GST_DEBUG_OBJECT (src, "do-rtsp-keep-alive is FALSE, not sending.");
+    gst_rtsp_connection_reset_timeout (src->conninfo.connection);
+    return GST_RTSP_OK;
+  }
+
   GST_DEBUG_OBJECT (src, "creating server keep-alive");
 
   /* find a method to use for keep-alive */
@@ -3764,7 +3793,11 @@
           goto connect_error;
 
         continue;
+      case GST_RTSP_ENET:
+        GST_DEBUG_OBJECT (src, "An ethernet problem occured.");
       default:
+        GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
+            ("Unhandled return value %d.", res));
         goto receive_error;
     }
 
@@ -3923,17 +3956,17 @@
         ("Could not receive any UDP packets for %.4f seconds, maybe your "
             "firewall is blocking it. No other protocols to try.",
             gst_guint64_to_gdouble (src->udp_timeout / 1000000.0)));
-    return GST_FLOW_ERROR;
+    return GST_RTSP_ERROR;
   }
 open_failed:
   {
     GST_DEBUG_OBJECT (src, "open failed");
-    return GST_FLOW_OK;
+    return GST_RTSP_OK;
   }
 play_failed:
   {
     GST_DEBUG_OBJECT (src, "play failed");
-    return GST_FLOW_OK;
+    return GST_RTSP_OK;
   }
 }
 
diff --git a/gst/rtsp/gstrtspsrc.h b/gst/rtsp/gstrtspsrc.h
index 9e208bf..eb7f8e5 100644
--- a/gst/rtsp/gstrtspsrc.h
+++ b/gst/rtsp/gstrtspsrc.h
@@ -204,6 +204,7 @@
   guint64           connection_speed;
   GstRTSPNatMethod  nat_method;
   gboolean          do_rtcp;
+  gboolean          do_rtsp_keep_alive;
   gchar            *proxy_host;
   guint             proxy_port;
   gchar            *proxy_user;
diff --git a/gst/smpte/gstsmpte.c b/gst/smpte/gstsmpte.c
index beb979f..afd30a2 100644
--- a/gst/smpte/gstsmpte.c
+++ b/gst/smpte/gstsmpte.c
@@ -408,8 +408,7 @@
   gint i, j;
   gint min, max;
   guint8 *in1u, *in1v, *in2u, *in2v, *outu, *outv;
-  gint lumsize = width * height;
-  gint chromsize = lumsize >> 2;
+  gint uoffset, voffset, ystr, ustr, vstr;
 
   if (border == 0)
     border++;
@@ -417,12 +416,19 @@
   min = pos - border;
   max = pos;
 
-  in1u = in1 + lumsize;
-  in1v = in1u + chromsize;
-  in2u = in2 + lumsize;
-  in2v = in2u + chromsize;
-  outu = out + lumsize;
-  outv = outu + chromsize;
+  uoffset = I420_U_OFFSET (width, height);
+  voffset = I420_V_OFFSET (width, height);
+
+  ystr = I420_Y_ROWSTRIDE (width);
+  ustr = I420_U_ROWSTRIDE (width);
+  vstr = I420_V_ROWSTRIDE (width);
+
+  in1u = in1 + uoffset;
+  in1v = in1 + voffset;
+  in2u = in2 + uoffset;
+  in2v = in2 + voffset;
+  outu = out + uoffset;
+  outv = out + voffset;
 
   maskp = mask->data;
 
@@ -431,12 +437,25 @@
       value = *maskp++;
       value = ((CLAMP (value, min, max) - min) << 8) / border;
 
-      *out++ = ((*in1++ * value) + (*in2++ * (256 - value))) >> 8;
+      out[j] = ((in1[j] * value) + (in2[j] * (256 - value))) >> 8;
       if (!(i & 1) && !(j & 1)) {
-        *outu++ = ((*in1u++ * value) + (*in2u++ * (256 - value))) >> 8;
-        *outv++ = ((*in1v++ * value) + (*in2v++ * (256 - value))) >> 8;
+        outu[j / 2] =
+            ((in1u[j / 2] * value) + (in2u[j / 2] * (256 - value))) >> 8;
+        outv[j / 2] =
+            ((in1v[j / 2] * value) + (in2v[j / 2] * (256 - value))) >> 8;
       }
     }
+    out += ystr;
+    in1 += ystr;
+    in2 += ystr;
+    if (!(i & 1)) {
+      outu += ustr;
+      in1u += ustr;
+      in2u += ustr;
+      outv += vstr;
+      in1v += vstr;
+      in2v += vstr;
+    }
   }
 }
 
diff --git a/sys/ximage/gstximagesrc.c b/sys/ximage/gstximagesrc.c
index eee74d4..0ec9688 100644
--- a/sys/ximage/gstximagesrc.c
+++ b/sys/ximage/gstximagesrc.c
@@ -1053,8 +1053,7 @@
   if (s->endx >= s->startx && s->endy >= s->starty) {
     /* this means user has put in values */
     if (s->startx < xcontext->width && s->endx < xcontext->width &&
-        s->starty < xcontext->height && s->endy < xcontext->height &&
-        s->startx >= 0 && s->starty >= 0) {
+        s->starty < xcontext->height && s->endy < xcontext->height) {
       /* values are fine */
       s->width = width = s->endx - s->startx + 1;
       s->height = height = s->endy - s->starty + 1;