diff --git a/configure.ac b/configure.ac
index ef62ea7..fc68976 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3211,6 +3211,26 @@ AC_CHECK_HEADERS(png.h, [
 fi
 AM_CONDITIONAL(BUILD_OSDMENU, [test "${enable_png}" != "no"])
 
+
+dnl
+dnl  VDPAU decoder module
+dnl
+AC_ARG_ENABLE(vdpau,
+  [  --enable-vdpau            VDPAU support (default enabled)])
+if test "${enable_vdpau}" != "no"; then
+AC_CHECK_HEADERS(vdpau/vdpau.h vdpau/vdpau_x11.h, [
+dnl  LDFLAGS="${LDFLAGS_save}"
+  AC_CHECK_LIB(vdpau, vdp_device_create_x11, [
+    VLC_ADD_LIBS([vdpau],[-lvdpau -lavcodec -lX11 -lvdpau_nvidia])
+    VLC_ADD_PLUGIN([vdpau])
+    AC_DEFINE(HAVE_LIBVDPAU, 1, [Define if you have the VDPAU library: libvdpau])
+    ],
+    [],[])
+dnl    LDFLAGS="${LDFLAGS_save}"
+  ])
+fi
+
+
 dnl
 dnl H264 encoder plugin (using libx264)
 dnl
@@ -5230,6 +5250,7 @@ AC_CONFIG_FILES([
   modules/codec/shine/Makefile
   modules/codec/subtitles/Makefile
   modules/codec/spudec/Makefile
+  modules/codec/vdpau/Makefile
   modules/codec/wmafixed/Makefile
   modules/codec/xvmc/Makefile
   modules/control/Makefile
diff --git a/modules/codec/Modules.am b/modules/codec/Modules.am
index 1ad8002..dad999a 100644
--- a/modules/codec/Modules.am
+++ b/modules/codec/Modules.am
@@ -1,4 +1,4 @@
-SUBDIRS = cmml dmo avcodec shine subtitles spudec wmafixed xvmc
+SUBDIRS = cmml dmo avcodec shine subtitles spudec vdpau wmafixed xvmc
 SOURCES_a52 = a52.c a52.h
 SOURCES_dts = dts.c
 SOURCES_flac = flac.c
diff --git a/modules/codec/vdpau/Modules.am b/modules/codec/vdpau/Modules.am
new file mode 100644
index 0000000..fd28c71
--- /dev/null
+++ b/modules/codec/vdpau/Modules.am
@@ -0,0 +1,18 @@
+SOURCES_vdpau = \
+	avcodec.c \
+	avcodec.h \
+	video.c \
+	deinterlace.c \
+	avutil.h \
+	fourcc.c \
+	chroma.c \
+	$(NULL)
+
+#EXTRA_vdpau_plugin_la_SOURCES = \
+#	$(NULL)
+
+libvlc_LTLIBRARIES += \
+	$(LTLIBvdpau)
+
+EXTRA_LTLIBRARIES += \
+	libvdpau_plugin.la
diff --git a/modules/codec/vdpau/avcodec.c b/modules/codec/vdpau/avcodec.c
new file mode 100644
index 0000000..844ba55
--- /dev/null
+++ b/modules/codec/vdpau/avcodec.c
@@ -0,0 +1,251 @@
+/*****************************************************************************
+ * avcodec.c: video and audio decoder and encoder using libavcodec
+ *****************************************************************************
+ * Copyright (C) 1999-2009 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *          Gildas Bazin <gbazin@videolan.org>
+ *          Kevin Keraudren <kevin.keraudren@student.ecp.fr>
+ *          Etienne Membrives <etienne@membrives.fr>
+ *          Tilo Van Ekeris <tilo.van-ekeris@student.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_codec.h>
+#include <vlc_avcodec.h>
+
+/* ffmpeg header */
+#define HAVE_MMX 1
+
+#include <libavcodec/avcodec.h>
+
+
+#if LIBAVCODEC_BUILD < 5000
+#   error You must have a libavcodec >= 5000 (get svn)
+#endif
+
+#include "avcodec.h"
+#include "avutil.h"
+
+/*****************************************************************************
+ * decoder_sys_t: decoder descriptor
+ *****************************************************************************/
+struct decoder_sys_t
+{
+    /* Common part between video and audio decoder */
+    FFMPEG_COMMON_MEMBERS
+};
+
+/****************************************************************************
+ * Local prototypes
+ ****************************************************************************/
+static int OpenDecoder( vlc_object_t * );
+static void CloseDecoder( vlc_object_t * );
+
+static const int  nloopf_list[] = { 0, 1, 2, 3, 4 };
+static const char *const nloopf_list_text[] =
+  { N_("None"), N_("Non-ref"), N_("Bidir"), N_("Non-key"), N_("All") };
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define MODULE_DESCRIPTION N_( "VDPAU hardware acc. h264 video decoder") 
+
+vlc_module_begin ()
+    set_shortname( "VDPAU")
+    add_shortcut( "vdpau" )
+    set_category( CAT_INPUT )
+    set_subcategory( SUBCAT_INPUT_VCODEC )
+    /* decoder main module */
+    set_description( N_("VDPAU hardware acc. h264 video decoder") )
+    set_help( MODULE_DESCRIPTION )
+    set_capability( "decoder", 2000 ) // 1000
+    set_section( N_("Decoding") , NULL )
+    set_callbacks( OpenDecoder, CloseDecoder )
+
+
+/*    add_bool( "ffmpeg-dr", 1, NULL, DR_TEXT, DR_TEXT, true )
+    add_integer ( "ffmpeg-error-resilience", 1, NULL, ERROR_TEXT,
+        ERROR_LONGTEXT, true )
+    add_integer ( "ffmpeg-workaround-bugs", 1, NULL, BUGS_TEXT, BUGS_LONGTEXT,
+        false )
+    add_bool( "ffmpeg-hurry-up", 1, NULL, HURRYUP_TEXT, HURRYUP_LONGTEXT,
+        false )
+    add_integer( "ffmpeg-skip-frame", 0, NULL, SKIP_FRAME_TEXT,
+        SKIP_FRAME_LONGTEXT, true )
+        change_integer_range( -1, 4 )
+    add_integer( "ffmpeg-skip-idct", 0, NULL, SKIP_IDCT_TEXT,
+        SKIP_IDCT_LONGTEXT, true )
+        change_integer_range( -1, 4 )
+    add_integer ( "ffmpeg-vismv", 0, NULL, VISMV_TEXT, VISMV_LONGTEXT,
+        true )
+    add_integer ( "ffmpeg-lowres", 0, NULL, LOWRES_TEXT, LOWRES_LONGTEXT,
+        true )
+        change_integer_range( 0, 2 )
+    add_bool( "ffmpeg-fast", 0, NULL, FAST_TEXT, FAST_LONGTEXT, true )
+    add_integer ( "ffmpeg-skiploopfilter", 0, NULL, SKIPLOOPF_TEXT,
+                  SKIPLOOPF_LONGTEXT, true )
+        change_safe ()
+        change_integer_list( nloopf_list, nloopf_list_text, NULL )
+
+    add_integer( "ffmpeg-debug", 0, NULL, DEBUG_TEXT, DEBUG_LONGTEXT,
+                 true )
+*/
+
+vlc_module_end ()
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************/
+static int OpenDecoder( vlc_object_t *p_this )
+{
+    decoder_t *p_dec = (decoder_t*) p_this;
+    int i_cat, i_codec_id, i_result;
+    const char *psz_namecodec;
+
+    AVCodecContext *p_context = NULL;
+    AVCodec        *p_codec = NULL;
+
+    /* *** determine codec type *** */
+    if( !GetFfmpegCodec( p_dec->fmt_in.i_codec, &i_cat, &i_codec_id,
+                             &psz_namecodec ) )
+    {
+        return VLC_EGENERIC;
+    }
+
+    /* Initialization must be done before avcodec_find_decoder() */
+    InitLibavcodec(p_this);
+
+    /* *** ask ffmpeg for a decoder *** */
+    //p_codec = avcodec_find_decoder( i_codec_id );
+    p_codec = avcodec_find_decoder_by_name("h264_vdpau");
+
+    if( !p_codec )
+    {
+        msg_Dbg( p_dec, "codec not found (%s)", psz_namecodec );
+        return VLC_EGENERIC;
+    }
+
+    /* *** get a p_context *** */
+    p_context = avcodec_alloc_context();
+    if( !p_context )
+        return VLC_ENOMEM;
+    p_context->debug = config_GetInt( p_dec, "ffmpeg-debug" );
+    p_context->opaque = (void *)p_this;
+
+    /* Set CPU capabilities */
+    unsigned i_cpu = vlc_CPU();
+    p_context->dsp_mask = 0;
+    if( !(i_cpu & CPU_CAPABILITY_MMX) )
+    {
+        p_context->dsp_mask |= FF_MM_MMX;
+    }
+    if( !(i_cpu & CPU_CAPABILITY_MMXEXT) )
+    {
+        p_context->dsp_mask |= FF_MM_MMXEXT;
+    }
+    if( !(i_cpu & CPU_CAPABILITY_3DNOW) )
+    {
+        p_context->dsp_mask |= FF_MM_3DNOW;
+    }
+    if( !(i_cpu & CPU_CAPABILITY_SSE) )
+    {
+        p_context->dsp_mask |= FF_MM_SSE;
+    }
+    if( !(i_cpu & CPU_CAPABILITY_SSE2) )
+    {
+        p_context->dsp_mask |= FF_MM_SSE2;
+    }
+
+    p_dec->b_need_packetized = true;
+    if( i_cat == VIDEO_ES )
+    {
+        p_dec->pf_decode_video = DecodeVideo;
+        i_result =  InitVideoDec ( p_dec, p_context, p_codec,
+                                       i_codec_id, psz_namecodec );
+    }
+    else
+    {
+        i_result = VLC_EGENERIC;
+    }
+
+    if( i_result == VLC_SUCCESS ) p_dec->p_sys->i_cat = i_cat;
+
+    return i_result;
+}
+
+/*****************************************************************************
+ * CloseDecoder: decoder destruction
+ *****************************************************************************/
+static void CloseDecoder( vlc_object_t *p_this )
+{
+    decoder_t *p_dec = (decoder_t *)p_this;
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    EndVideoDec ( p_dec );
+
+    if( p_sys->p_context )
+    {
+        free( p_sys->p_context->extradata );
+        p_sys->p_context->extradata = NULL;
+
+        if( !p_sys->b_delayed_open )
+        {
+            vlc_avcodec_lock();
+            avcodec_close( p_sys->p_context );
+            vlc_avcodec_unlock();
+        }
+        msg_Dbg( p_dec, "ffmpeg codec (%s) stopped", p_sys->psz_namecodec );
+        av_free( p_sys->p_context );
+    }
+
+    free( p_sys );
+}
+
+void InitLibavcodec( vlc_object_t *p_object )
+{
+    static bool b_ffmpeginit = false;
+
+    vlc_avcodec_lock();
+
+    /* *** init ffmpeg library (libavcodec) *** */
+    if( !b_ffmpeginit )
+    {
+        avcodec_init();
+        avcodec_register_all();
+        av_log_set_callback( LibavutilCallback );
+        b_ffmpeginit = true;
+
+        msg_Dbg( p_object, "libavcodec initialized (interface 0x%x)",
+                 LIBAVCODEC_VERSION_INT );
+    }
+    else
+    {
+        msg_Dbg( p_object, "libavcodec already initialized" );
+    }
+
+    vlc_avcodec_unlock();
+}
diff --git a/modules/codec/vdpau/avcodec.h b/modules/codec/vdpau/avcodec.h
new file mode 100644
index 0000000..1d79f89
--- /dev/null
+++ b/modules/codec/vdpau/avcodec.h
@@ -0,0 +1,249 @@
+/*****************************************************************************
+ * avcodec.h: decoder and encoder using libavcodec
+ *****************************************************************************
+ * Copyright (C) 2001-2009 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/* VLC <-> avcodec tables */
+int GetFfmpegCodec( vlc_fourcc_t i_fourcc, int *pi_cat,
+                    int *pi_ffmpeg_codec, const char **ppsz_name );
+int GetVlcFourcc( int i_ffmpeg_codec, int *pi_cat,
+                  vlc_fourcc_t *pi_fourcc, const char **ppsz_name );
+int TestFfmpegChroma( const int i_ffmpeg_id, const vlc_fourcc_t i_vlc_fourcc );
+int GetFfmpegChroma( int *i_ffmpeg_chroma, const video_format_t fmt );
+int GetVlcChroma( video_format_t *fmt, const int i_ffmpeg_chroma );
+
+
+picture_t * DecodeVideo    ( decoder_t *, block_t ** );
+
+/* Video encoder module */
+int  OpenEncoder ( vlc_object_t * );
+void CloseEncoder( vlc_object_t * );
+
+/* Deinterlace video filter module */
+int  OpenDeinterlace( vlc_object_t * );
+void CloseDeinterlace( vlc_object_t * );
+
+void InitLibavcodec( vlc_object_t *p_object );
+
+/* Video Decoder */
+int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
+                  AVCodec *p_codec, int i_codec_id, const char *psz_namecodec );
+void EndVideoDec( decoder_t *p_dec );
+
+/*****************************************************************************
+ * Module descriptor help strings
+ *****************************************************************************/
+#define DR_TEXT N_("Direct rendering")
+/* FIXME Does somebody who knows what it does, explain */
+#define DR_LONGTEXT N_("Direct rendering")
+
+#define ERROR_TEXT N_("Error resilience")
+#define ERROR_LONGTEXT N_( \
+    "Ffmpeg can do error resilience.\n" \
+    "However, with a buggy encoder (such as the ISO MPEG-4 encoder from M$) " \
+    "this can produce a lot of errors.\n" \
+    "Valid values range from 0 to 4 (0 disables all errors resilience).")
+
+#define BUGS_TEXT N_("Workaround bugs")
+#define BUGS_LONGTEXT N_( \
+    "Try to fix some bugs:\n" \
+    "1  autodetect\n" \
+    "2  old msmpeg4\n" \
+    "4  xvid interlaced\n" \
+    "8  ump4 \n" \
+    "16 no padding\n" \
+    "32 ac vlc\n" \
+    "64 Qpel chroma.\n" \
+    "This must be the sum of the values. For example, to fix \"ac vlc\" and " \
+    "\"ump4\", enter 40.")
+
+#define HURRYUP_TEXT N_("Hurry up")
+#define HURRYUP_LONGTEXT N_( \
+    "The decoder can partially decode or skip frame(s) " \
+    "when there is not enough time. It's useful with low CPU power " \
+    "but it can produce distorted pictures.")
+
+#define FAST_TEXT N_("Allow speed tricks")
+#define FAST_LONGTEXT N_( \
+    "Allow non specification compliant speedup tricks. Faster but error-prone.")
+
+#define SKIP_FRAME_TEXT N_("Skip frame (default=0)")
+#define SKIP_FRAME_LONGTEXT N_( \
+    "Force skipping of frames to speed up decoding " \
+    "(-1=None, 0=Default, 1=B-frames, 2=P-frames, 3=B+P frames, 4=all frames)." )
+
+#define SKIP_IDCT_TEXT N_("Skip idct (default=0)")
+#define SKIP_IDCT_LONGTEXT N_( \
+    "Force skipping of idct to speed up decoding for frame types" \
+    "(-1=None, 0=Default, 1=B-frames, 2=P-frames, 3=B+P frames, 4=all frames)." )
+
+#define DEBUG_TEXT N_( "Debug mask" )
+#define DEBUG_LONGTEXT N_( "Set ffmpeg debug mask" )
+
+/* TODO: Use a predefined list, with 0,1,2,4,7 */
+#define VISMV_TEXT N_( "Visualize motion vectors" )
+#define VISMV_LONGTEXT N_( \
+    "You can overlay the motion vectors (arrows showing how the images move) "\
+    "on the image. This value is a mask, based on these values:\n"\
+    "1 - visualize forward predicted MVs of P frames\n" \
+    "2 - visualize forward predicted MVs of B frames\n" \
+    "4 - visualize backward predicted MVs of B frames\n" \
+    "To visualize all vectors, the value should be 7." )
+
+#define LOWRES_TEXT N_( "Low resolution decoding" )
+#define LOWRES_LONGTEXT N_( "Only decode a low resolution version of " \
+    "the video. This requires less processing power" )
+
+#define SKIPLOOPF_TEXT N_( "Skip the loop filter for H.264 decoding" )
+#define SKIPLOOPF_LONGTEXT N_( "Skipping the loop filter (aka deblocking) " \
+    "usually has a detrimental effect on quality. However it provides a big " \
+    "speedup for high definition streams." )
+
+/*
+ * Encoder options
+ */
+#define ENC_CFG_PREFIX "sout-ffmpeg-"
+
+#define ENC_KEYINT_TEXT N_( "Ratio of key frames" )
+#define ENC_KEYINT_LONGTEXT N_( "Number of frames " \
+  "that will be coded for one key frame." )
+
+#define ENC_BFRAMES_TEXT N_( "Ratio of B frames" )
+#define ENC_BFRAMES_LONGTEXT N_( "Number of " \
+  "B frames that will be coded between two reference frames." )
+
+#define ENC_VT_TEXT N_( "Video bitrate tolerance" )
+#define ENC_VT_LONGTEXT N_( "Video bitrate tolerance in kbit/s." )
+
+#define ENC_INTERLACE_TEXT N_( "Interlaced encoding" )
+#define ENC_INTERLACE_LONGTEXT N_( "Enable dedicated " \
+  "algorithms for interlaced frames." )
+
+#define ENC_INTERLACE_ME_TEXT N_( "Interlaced motion estimation" )
+#define ENC_INTERLACE_ME_LONGTEXT N_( "Enable interlaced " \
+  "motion estimation algorithms. This requires more CPU." )
+
+#define ENC_PRE_ME_TEXT N_( "Pre-motion estimation" )
+#define ENC_PRE_ME_LONGTEXT N_( "Enable the pre-motion " \
+  "estimation algorithm.")
+
+#define ENC_RC_BUF_TEXT N_( "Rate control buffer size" )
+#define ENC_RC_BUF_LONGTEXT N_( "Rate control " \
+  "buffer size (in kbytes). A bigger buffer will allow for better rate " \
+  "control, but will cause a delay in the stream." )
+
+#define ENC_RC_BUF_AGGR_TEXT N_( "Rate control buffer aggressiveness" )
+#define ENC_RC_BUF_AGGR_LONGTEXT N_( "Rate control "\
+  "buffer aggressiveness." )
+
+#define ENC_IQUANT_FACTOR_TEXT N_( "I quantization factor" )
+#define ENC_IQUANT_FACTOR_LONGTEXT N_(  \
+  "Quantization factor of I frames, compared with P frames (for instance " \
+  "1.0 => same qscale for I and P frames)." )
+
+#define ENC_NOISE_RED_TEXT N_( "Noise reduction" )
+#define ENC_NOISE_RED_LONGTEXT N_( "Enable a simple noise " \
+  "reduction algorithm to lower the encoding length and bitrate, at the " \
+  "expense of lower quality frames." )
+
+#define ENC_MPEG4_MATRIX_TEXT N_( "MPEG4 quantization matrix" )
+#define ENC_MPEG4_MATRIX_LONGTEXT N_( "Use the MPEG4 " \
+  "quantization matrix for MPEG2 encoding. This generally yields a " \
+  "better looking picture, while still retaining the compatibility with " \
+  "standard MPEG2 decoders.")
+
+#define ENC_HQ_TEXT N_( "Quality level" )
+#define ENC_HQ_LONGTEXT N_( "Quality level " \
+  "for the encoding of motions vectors (this can slow down the encoding " \
+  "very much)." )
+
+#define ENC_HURRYUP_TEXT N_( "Hurry up" )
+#define ENC_HURRYUP_LONGTEXT N_( "The encoder " \
+  "can make on-the-fly quality tradeoffs if your CPU can't keep up with " \
+  "the encoding rate. It will disable trellis quantization, then the rate " \
+  "distortion of motion vectors (hq), and raise the noise reduction " \
+  "threshold to ease the encoder's task." )
+
+#define ENC_QMIN_TEXT N_( "Minimum video quantizer scale" )
+#define ENC_QMIN_LONGTEXT N_( "Minimum video " \
+  "quantizer scale." )
+
+#define ENC_QMAX_TEXT N_( "Maximum video quantizer scale" )
+#define ENC_QMAX_LONGTEXT N_( "Maximum video " \
+  "quantizer scale." )
+
+#define ENC_TRELLIS_TEXT N_( "Trellis quantization" )
+#define ENC_TRELLIS_LONGTEXT N_( "Enable trellis " \
+  "quantization (rate distortion for block coefficients)." )
+
+#define ENC_QSCALE_TEXT N_( "Fixed quantizer scale" )
+#define ENC_QSCALE_LONGTEXT N_( "A fixed video " \
+  "quantizer scale for VBR encoding (accepted values: 0.01 to 255.0)." )
+
+#define ENC_STRICT_TEXT N_( "Strict standard compliance" )
+#define ENC_STRICT_LONGTEXT N_( "Force a strict standard " \
+  "compliance when encoding (accepted values: -1, 0, 1)." )
+
+#define ENC_LUMI_MASKING_TEXT N_( "Luminance masking" )
+#define ENC_LUMI_MASKING_LONGTEXT N_( "Raise the quantizer for " \
+  "very bright macroblocks (default: 0.0)." )
+
+#define ENC_DARK_MASKING_TEXT N_( "Darkness masking" )
+#define ENC_DARK_MASKING_LONGTEXT N_( "Raise the quantizer for " \
+  "very dark macroblocks (default: 0.0)." )
+
+#define ENC_P_MASKING_TEXT N_( "Motion masking" )
+#define ENC_P_MASKING_LONGTEXT N_( "Raise the quantizer for " \
+  "macroblocks with a high temporal complexity (default: 0.0)." )
+
+#define ENC_BORDER_MASKING_TEXT N_( "Border masking" )
+#define ENC_BORDER_MASKING_LONGTEXT N_( "Raise the quantizer " \
+  "for macroblocks at the border of the frame (default: 0.0)." )
+
+#define ENC_LUMA_ELIM_TEXT N_( "Luminance elimination" )
+#define ENC_LUMA_ELIM_LONGTEXT N_( "Eliminates luminance blocks when " \
+  "the PSNR isn't much changed (default: 0.0). The H264 specification " \
+  "recommends -4." )
+
+#define ENC_CHROMA_ELIM_TEXT N_( "Chrominance elimination" )
+#define ENC_CHROMA_ELIM_LONGTEXT N_( "Eliminates chrominance blocks when " \
+  "the PSNR isn't much changed (default: 0.0). The H264 specification " \
+  "recommends 7." )
+
+#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(40<<8)+4)
+#define ENC_PROFILE_TEXT N_( "Specify AAC audio profile to use" )
+#define ENC_PROFILE_LONGTEXT N_( "Specify the AAC audio profile to use " \
+   "for encoding the audio bitstream. It takes the following options: " \
+   "main, low, ssr (not supported) and ltp (default: main)" )
+#endif
+
+#define FFMPEG_COMMON_MEMBERS   \
+    int i_cat;                  \
+    int i_codec_id;             \
+    const char *psz_namecodec;  \
+    AVCodecContext *p_context;  \
+    AVCodec        *p_codec;    \
+    bool b_delayed_open;
+
+#ifndef AV_VERSION_INT
+#   define AV_VERSION_INT(a, b, c) ((a)<<16 | (b)<<8 | (c))
+#endif
+
diff --git a/modules/codec/vdpau/avutil.h b/modules/codec/vdpau/avutil.h
new file mode 100644
index 0000000..48a5222
--- /dev/null
+++ b/modules/codec/vdpau/avutil.h
@@ -0,0 +1,60 @@
+/*****************************************************************************
+ * avutil.h: avutil helper functions
+ *****************************************************************************
+ * Copyright (C) 1999-2009 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *          Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Export libavutil messages to the VLC message system
+ *****************************************************************************/
+static inline void LibavutilCallback( void *p_opaque, int i_level,
+                        const char *psz_format, va_list va )
+{
+    AVCodecContext *p_avctx = (AVCodecContext *)p_opaque;
+    const AVClass *p_avc;
+
+    p_avc = p_avctx ? p_avctx->av_class : 0;
+
+#define cln p_avc->class_name
+    /* Make sure we can get p_this back */
+    if( !p_avctx || !p_avc || !cln ||
+        cln[0]!='A' || cln[1]!='V' || cln[2]!='C' || cln[3]!='o' ||
+        cln[4]!='d' || cln[5]!='e' || cln[6]!='c' )
+    {
+        if( i_level == AV_LOG_ERROR ) vfprintf( stderr, psz_format, va );
+        return;
+    }
+#undef cln
+
+    switch( i_level )
+    {
+    case AV_LOG_DEBUG:
+    case AV_LOG_INFO:
+        /* Print debug messages if they were requested */
+        if( !p_avctx->debug )
+            break;
+
+    case AV_LOG_ERROR:
+    case AV_LOG_QUIET:
+        vfprintf( stderr, psz_format, va );
+        break;
+    }
+}
diff --git a/modules/codec/vdpau/chroma.c b/modules/codec/vdpau/chroma.c
new file mode 100644
index 0000000..0192a5e
--- /dev/null
+++ b/modules/codec/vdpau/chroma.c
@@ -0,0 +1,158 @@
+/*****************************************************************************
+ * chroma.c: libavutil <-> libvlc conversion routines
+ *****************************************************************************
+ * Copyright (C) 1999-2009 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *          Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 021100301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <vlc_common.h>
+#include <vlc_codec.h>
+
+#include <libavcodec/avcodec.h>
+#include "avcodec.h"
+
+/*****************************************************************************
+ * Chroma fourcc -> ffmpeg_id mapping
+ *****************************************************************************/
+#if defined(WORDS_BIGENDIAN)
+#   define VLC_RGB_ES( fcc, leid, beid ) \
+    { fcc, beid, 0, 0, 0 },
+#else
+#   define VLC_RGB_ES( fcc, leid, beid ) \
+    { fcc, leid, 0, 0, 0 },
+#endif
+
+#define VLC_RGB( fcc, leid, beid, rmask, gmask, bmask ) \
+    { fcc, leid, rmask, gmask, bmask }, \
+    { fcc, beid, bmask, gmask, rmask }, \
+    VLC_RGB_ES( fcc, leid, beid )
+
+
+static const struct
+{
+    vlc_fourcc_t  i_chroma;
+    int           i_chroma_id;
+    uint32_t      i_rmask;
+    uint32_t      i_gmask;
+    uint32_t      i_bmask;
+
+} chroma_table[] =
+{
+    /* Planar YUV formats */
+    {VLC_FOURCC('I','4','4','4'), PIX_FMT_YUV444P, 0, 0, 0 },
+    {VLC_FOURCC('J','4','4','4'), PIX_FMT_YUVJ444P, 0, 0, 0 },
+
+#if LIBAVUTIL_VERSION_INT >= ((49<<16)+(5<<8)+0)
+    {VLC_FOURCC('I','4','4','0'), PIX_FMT_YUV440P, 0, 0, 0 },
+    {VLC_FOURCC('J','4','4','0'), PIX_FMT_YUVJ440P, 0, 0, 0 },
+#endif
+
+    {VLC_FOURCC('I','4','2','2'), PIX_FMT_YUV422P, 0, 0, 0 },
+    {VLC_FOURCC('J','4','2','2'), PIX_FMT_YUVJ422P, 0, 0, 0 },
+
+    {VLC_FOURCC('I','4','2','0'), PIX_FMT_YUV420P, 0, 0, 0 },
+    {VLC_FOURCC('Y','V','1','2'), PIX_FMT_YUV420P, 0, 0, 0 },
+    {VLC_FOURCC('I','Y','U','V'), PIX_FMT_YUV420P, 0, 0, 0 },
+    {VLC_FOURCC('J','4','2','0'), PIX_FMT_YUVJ420P, 0, 0, 0 },
+    {VLC_FOURCC('I','4','1','1'), PIX_FMT_YUV411P, 0, 0, 0 },
+    {VLC_FOURCC('I','4','1','0'), PIX_FMT_YUV410P, 0, 0, 0 },
+    {VLC_FOURCC('Y','V','U','9'), PIX_FMT_YUV410P, 0, 0, 0 },
+
+    {VLC_FOURCC('N','V','1','2'), PIX_FMT_NV12, 0, 0, 0 },
+    {VLC_FOURCC('N','V','2','1'), PIX_FMT_NV21, 0, 0, 0 },
+
+    /* Packed YUV formats */
+    {VLC_FOURCC('Y','U','Y','2'), PIX_FMT_YUYV422, 0, 0, 0 },
+    {VLC_FOURCC('Y','U','Y','V'), PIX_FMT_YUYV422, 0, 0, 0 },
+    {VLC_FOURCC('U','Y','V','Y'), PIX_FMT_UYVY422, 0, 0, 0 },
+    {VLC_FOURCC('Y','4','1','1'), PIX_FMT_UYYVYY411, 0, 0, 0 },
+
+    /* Packed RGB formats */
+    VLC_RGB( VLC_FOURCC('R','G','B','4'), PIX_FMT_RGB4, PIX_FMT_BGR4, 0x10, 0x06, 0x01 )
+    VLC_RGB( VLC_FOURCC('R','G','B','8'), PIX_FMT_RGB8, PIX_FMT_BGR8, 0xC0, 0x38, 0x07 )
+
+    VLC_RGB( VLC_FOURCC('R','V','1','5'), PIX_FMT_BGR555, PIX_FMT_RGB555, 0x7c00, 0x03e0, 0x001f )
+    VLC_RGB( VLC_FOURCC('R','V','1','6'), PIX_FMT_BGR565, PIX_FMT_RGB565, 0xf800, 0x07e0, 0x001f )
+    VLC_RGB( VLC_FOURCC('R','V','2','4'), PIX_FMT_BGR24, PIX_FMT_RGB24, 0xff0000, 0x00ff00, 0x0000ff )
+
+    VLC_RGB( VLC_FOURCC('R','V','3','2'), PIX_FMT_RGB32, PIX_FMT_BGR32, 0x00ff0000, 0x0000ff00, 0x000000ff )
+    VLC_RGB( VLC_FOURCC('R','V','3','2'), PIX_FMT_RGB32_1, PIX_FMT_BGR32_1, 0xff000000, 0x00ff0000, 0x0000ff00 )
+
+#if defined(PIX_FMT_RGBA)
+    {VLC_FOURCC('R','G','B','A'), PIX_FMT_RGBA, 0xff000000, 0x00ff0000, 0x0000ff00},
+#endif
+    {VLC_FOURCC('G','R','E','Y'), PIX_FMT_GRAY8, 0, 0, 0},
+
+     /* Paletized RGB */
+    {VLC_FOURCC('R','G','B','P'), PIX_FMT_PAL8, 0, 0, 0},
+
+
+    { 0, 0, 0, 0, 0 }
+};
+
+int TestFfmpegChroma( const int i_ffmpeg_id, const vlc_fourcc_t i_vlc_fourcc )
+{
+    for( int i = 0; chroma_table[i].i_chroma != 0; i++ )
+    {
+        if( chroma_table[i].i_chroma == i_vlc_fourcc || chroma_table[i].i_chroma_id == i_ffmpeg_id )
+            return VLC_SUCCESS;
+    }
+    return VLC_EGENERIC;
+}
+
+/* FIXME special case the RGB formats */
+int GetFfmpegChroma( int *i_ffmpeg_chroma, const video_format_t fmt )
+{
+    for( int i = 0; chroma_table[i].i_chroma != 0; i++ )
+    {
+        if( chroma_table[i].i_chroma == fmt.i_chroma )
+        {
+            if( chroma_table[i].i_rmask == fmt.i_rmask &&
+                chroma_table[i].i_gmask == fmt.i_gmask &&
+                chroma_table[i].i_bmask == fmt.i_bmask )
+            {
+                *i_ffmpeg_chroma = chroma_table[i].i_chroma_id;
+                return VLC_SUCCESS;
+            }
+        }
+    }
+    return VLC_EGENERIC;
+}
+
+int GetVlcChroma( video_format_t *fmt, const int i_ffmpeg_chroma )
+{
+    /* TODO FIXME for rgb format we HAVE to set rgb mask/shift */
+    for( int i = 0; chroma_table[i].i_chroma != 0; i++ )
+    {
+        if( chroma_table[i].i_chroma_id == i_ffmpeg_chroma )
+        {
+            fmt->i_rmask = chroma_table[i].i_rmask;
+            fmt->i_gmask = chroma_table[i].i_gmask;
+            fmt->i_bmask = chroma_table[i].i_bmask;
+            fmt->i_chroma = chroma_table[i].i_chroma;
+            return VLC_SUCCESS;
+        }
+    }
+    return VLC_EGENERIC;
+}
diff --git a/modules/codec/vdpau/deinterlace.c b/modules/codec/vdpau/deinterlace.c
new file mode 100644
index 0000000..94a1bab
--- /dev/null
+++ b/modules/codec/vdpau/deinterlace.c
@@ -0,0 +1,157 @@
+/*****************************************************************************
+ * video filter: video filter doing chroma conversion and resizing
+ *               using the ffmpeg library
+ *****************************************************************************
+ * Copyright (C) 1999-2009 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_codec.h>
+#include <vlc_vout.h>
+#include <vlc_filter.h>
+
+/* ffmpeg header */
+#include <libavcodec/avcodec.h>
+
+#include "avcodec.h"
+
+static picture_t *Deinterlace( filter_t *p_filter, picture_t *p_pic );
+
+/*****************************************************************************
+ * filter_sys_t : filter descriptor
+ *****************************************************************************/
+struct filter_sys_t
+{
+    bool b_resize;
+    bool b_convert;
+    bool b_resize_first;
+    bool b_enable_croppadd;
+
+    es_format_t fmt_in;
+    int i_src_ffmpeg_chroma;
+    es_format_t fmt_out;
+    int i_dst_ffmpeg_chroma;
+
+    AVPicture tmp_pic;
+};
+
+/*****************************************************************************
+ * OpenDeinterlace: probe the filter and return score
+ *****************************************************************************/
+int OpenDeinterlace( vlc_object_t *p_this )
+{
+    filter_t *p_filter = (filter_t*)p_this;
+    filter_sys_t *p_sys;
+
+    /* Check if we can handle that formats */
+    if( TestFfmpegChroma( -1, p_filter->fmt_in.i_codec  ) != VLC_SUCCESS )
+    {
+        msg_Err( p_filter, "Failed to match chroma type" );
+        return VLC_EGENERIC;
+    }
+
+    /* Allocate the memory needed to store the decoder's structure */
+    if( ( p_filter->p_sys = p_sys =
+          (filter_sys_t *)malloc(sizeof(filter_sys_t)) ) == NULL )
+    {
+        return VLC_EGENERIC;
+    }
+
+    /* Misc init */
+    p_filter->fmt_in.video.i_chroma = p_filter->fmt_in.i_codec;
+    if( GetFfmpegChroma( &p_sys->i_src_ffmpeg_chroma, p_filter->fmt_in.video ) != VLC_SUCCESS )
+    {
+        msg_Err( p_filter, "Failed to match chroma type" );
+        return VLC_EGENERIC;
+    }
+    p_filter->pf_video_filter = Deinterlace;
+
+    msg_Dbg( p_filter, "deinterlacing" );
+
+    /* libavcodec needs to be initialized for some chroma conversions */
+    InitLibavcodec(p_this);
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * CloseDeinterlace: clean up the filter
+ *****************************************************************************/
+void CloseDeinterlace( vlc_object_t *p_this )
+{
+    filter_t *p_filter = (filter_t*)p_this;
+    filter_sys_t *p_sys = p_filter->p_sys;
+
+    free( p_sys );
+}
+
+/*****************************************************************************
+ * Do the processing here
+ *****************************************************************************/
+static picture_t *Deinterlace( filter_t *p_filter, picture_t *p_pic )
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+    AVPicture src_pic, dest_pic;
+    picture_t *p_pic_dst;
+    int i, i_res = -1;
+
+    /* Request output picture */
+    p_pic_dst = filter_NewPicture( p_filter );
+    if( !p_pic_dst )
+    {
+        picture_Release( p_pic );
+        return NULL;
+    }
+
+    /* Prepare the AVPictures for the conversion */
+    for( i = 0; i < p_pic->i_planes; i++ )
+    {
+        src_pic.data[i] = p_pic->p[i].p_pixels;
+        src_pic.linesize[i] = p_pic->p[i].i_pitch;
+    }
+    for( i = 0; i < p_pic_dst->i_planes; i++ )
+    {
+        dest_pic.data[i] = p_pic_dst->p[i].p_pixels;
+        dest_pic.linesize[i] = p_pic_dst->p[i].i_pitch;
+    }
+
+    i_res = avpicture_deinterlace( &dest_pic, &src_pic, p_sys->i_src_ffmpeg_chroma,
+                                   p_filter->fmt_in.video.i_width,
+                                   p_filter->fmt_in.video.i_height );
+    if( i_res == -1 )
+    {
+        msg_Err( p_filter, "deinterlacing picture failed" );
+        filter_DeletePicture( p_filter, p_pic_dst );
+        picture_Release( p_pic );
+        return NULL;
+    }
+
+    picture_CopyProperties( p_pic_dst, p_pic );
+    p_pic_dst->b_progressive = true;
+    picture_Release( p_pic );
+    return p_pic_dst;
+}
diff --git a/modules/codec/vdpau/fourcc.c b/modules/codec/vdpau/fourcc.c
new file mode 100644
index 0000000..b27ea99
--- /dev/null
+++ b/modules/codec/vdpau/fourcc.c
@@ -0,0 +1,177 @@
+/*****************************************************************************
+ * fourcc.c: libavcodec <-> libvlc conversion routines
+ *****************************************************************************
+ * Copyright (C) 1999-2009 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *          Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <vlc_common.h>
+#include <vlc_codec.h>
+
+#include <libavcodec/avcodec.h>
+#include "avcodec.h"
+
+/*****************************************************************************
+ * Codec fourcc -> ffmpeg_id mapping
+ *****************************************************************************/
+static const struct
+{
+    vlc_fourcc_t  i_fourcc;
+    int  i_codec;
+    int  i_cat;
+    const char psz_name[36];
+} codecs_table[] =
+{
+    /*
+     * Video Codecs
+     */
+
+    /* MPEG-1 Video */
+    { VLC_FOURCC('m','p','1','v'), CODEC_ID_MPEG1VIDEO,
+      VIDEO_ES, "MPEG-1 Video" },
+    { VLC_FOURCC('m','p','e','g'), CODEC_ID_MPEG1VIDEO,
+      VIDEO_ES, "MPEG-1 Video" },
+    { VLC_FOURCC('m','p','g','1'), CODEC_ID_MPEG1VIDEO,
+      VIDEO_ES, "MPEG-1 Video" },
+    { VLC_FOURCC('P','I','M','1'), CODEC_ID_MPEG1VIDEO,
+      VIDEO_ES, "Pinnacle DC1000 (MPEG-1 Video)" },
+
+    /* MPEG-2 Video */
+    { VLC_FOURCC('m','p','2','v'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "MPEG-2 Video" },
+    { VLC_FOURCC('M','P','E','G'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "MPEG-2 Video" },
+    { VLC_FOURCC('m','p','g','v'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "MPEG-2 Video" },
+    { VLC_FOURCC('m','p','g','2'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "MPEG-2 Video" },
+    { VLC_FOURCC('h','d','v','1'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "HDV 720p30 (MPEG-2 Video)" },
+    { VLC_FOURCC('h','d','v','2'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "Sony HDV (MPEG-2 Video)" },
+    { VLC_FOURCC('h','d','v','3'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "FCP HDV (MPEG-2 Video)" },
+    { VLC_FOURCC('h','d','v','5'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "HDV 720p25 (MPEG-2 Video)" },
+    { VLC_FOURCC('m','x','5','n'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "MPEG2 IMX NTSC 525/60 50mb/s (FCP)" },
+    { VLC_FOURCC('m','x','5','p'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "MPEG2 IMX PAL 625/60 50mb/s (FCP)" },
+    { VLC_FOURCC('m','x','4','n'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "MPEG2 IMX NTSC 525/60 40mb/s (FCP)" },
+    { VLC_FOURCC('m','x','4','p'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "MPEG2 IMX PAL 625/50 40mb/s (FCP)" },
+    { VLC_FOURCC('m','x','3','n'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "MPEG2 IMX NTSC 525/60 30mb/s (FCP)" },
+    { VLC_FOURCC('m','x','3','p'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "MPEG2 IMX NTSC 625/50 30mb/s (FCP)" },
+    { VLC_FOURCC('x','d','v','2'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "XDCAM HD 1080i60" },
+    { VLC_FOURCC('A','V','m','p'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "AVID IMX PAL" },
+    /* ATI VCR2 */
+    { VLC_FOURCC('V','C','R','2'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "ATI VCR2 Video" },
+    { VLC_FOURCC('M','M','E','S'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "Matrox MPEG-2" },
+    { VLC_FOURCC('m','m','e','s'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "Matrox MPEG-2" },
+    { VLC_FOURCC('P','I','M','2'), CODEC_ID_MPEG2VIDEO,
+      VIDEO_ES, "Pinnacle DC1000 (MPEG-2 Video)" },
+
+
+    /* h264 */
+    { VLC_FOURCC('h','2','6','4'), CODEC_ID_H264,
+      VIDEO_ES, "H264 - MPEG-4 AVC (part 10)" },
+    { VLC_FOURCC('H','2','6','4'), CODEC_ID_H264,
+      VIDEO_ES, "H264 - MPEG-4 AVC (part 10)" },
+    { VLC_FOURCC('x','2','6','4'), CODEC_ID_H264,
+      VIDEO_ES, "H264 - MPEG-4 AVC (part 10)" },
+    { VLC_FOURCC('X','2','6','4'), CODEC_ID_H264,
+      VIDEO_ES, "H264 - MPEG-4 AVC (part 10)" },
+    /* avc1: special case h264 */
+    { VLC_FOURCC('a','v','c','1'), CODEC_ID_H264,
+      VIDEO_ES, "H264 - MPEG-4 AVC (part 10)" },
+    { VLC_FOURCC('A','V','C','1'), CODEC_ID_H264,
+      VIDEO_ES, "H264 - MPEG-4 AVC (part 10)" },
+    { VLC_FOURCC('V','S','S','H'), CODEC_ID_H264,
+      VIDEO_ES, "Vanguard VSS H264" },
+    { VLC_FOURCC('V','S','S','W'), CODEC_ID_H264,
+      VIDEO_ES, "Vanguard VSS H264" },
+    { VLC_FOURCC('v','s','s','h'), CODEC_ID_H264,
+      VIDEO_ES, "Vanguard VSS H264" },
+    { VLC_FOURCC('D','A','V','C'), CODEC_ID_H264,
+      VIDEO_ES, "Dicas MPEGable H.264/MPEG-4 AVC" },
+    { VLC_FOURCC('d','a','v','c'), CODEC_ID_H264,
+      VIDEO_ES, "Dicas MPEGable H.264/MPEG-4 AVC" },
+
+    /* VC-1 */
+    { VLC_FOURCC('W','V','C','1'), CODEC_ID_VC1,
+      VIDEO_ES, "Windows Media Video VC1" },
+    { VLC_FOURCC('w','v','c','1'), CODEC_ID_VC1,
+      VIDEO_ES, "Windows Media Video VC1" },
+    { VLC_FOURCC('v','c','-','1'), CODEC_ID_VC1,
+      VIDEO_ES, "Windows Media Video VC1" },
+    { VLC_FOURCC('V','C','-','1'), CODEC_ID_VC1,
+      VIDEO_ES, "Windows Media Video VC1" },
+    /* WMVA is the VC-1 codec before the standardization proces,
+       it is not bitstream compatible and deprecated  */
+    { VLC_FOURCC('W','M','V','A'), CODEC_ID_VC1,
+      VIDEO_ES, "Windows Media Video Advanced Profile" },
+    { 0, 0, 0, "" }
+};
+
+int GetFfmpegCodec( vlc_fourcc_t i_fourcc, int *pi_cat,
+                    int *pi_ffmpeg_codec, const char **ppsz_name )
+{
+    for( unsigned i = 0; codecs_table[i].i_fourcc != 0; i++ )
+    {
+        if( codecs_table[i].i_fourcc == i_fourcc )
+        {
+            if( pi_cat ) *pi_cat = codecs_table[i].i_cat;
+            if( pi_ffmpeg_codec ) *pi_ffmpeg_codec = codecs_table[i].i_codec;
+            if( ppsz_name ) *ppsz_name = (char *)codecs_table[i].psz_name;
+
+            return true;
+        }
+    }
+    return false;
+}
+
+int GetVlcFourcc( int i_ffmpeg_codec, int *pi_cat,
+                  vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
+{
+    for( unsigned i = 0; codecs_table[i].i_codec != 0; i++ )
+    {
+        if( codecs_table[i].i_codec == i_ffmpeg_codec )
+        {
+            if( pi_cat ) *pi_cat = codecs_table[i].i_cat;
+            if( pi_fourcc ) *pi_fourcc = codecs_table[i].i_fourcc;
+            if( ppsz_name ) *ppsz_name = codecs_table[i].psz_name;
+
+            return true;
+        }
+    }
+    return false;
+}
diff --git a/modules/codec/vdpau/video.c b/modules/codec/vdpau/video.c
new file mode 100644
index 0000000..3bc8fc8
--- /dev/null
+++ b/modules/codec/vdpau/video.c
@@ -0,0 +1,1446 @@
+/*****************************************************************************
+ * video.c: video decoder using the ffmpeg library
+ *****************************************************************************
+ * Copyright (C) 1999-2009 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *          Gildas Bazin <gbazin@videolan.org>
+ *          Kevin Keraudren <kevin.keraudren@student.ecp.fr>
+ *          Etienne Membrives <etienne@membrives.fr>
+ *          Tilo Van Ekeris <tilo.van-ekeris@student.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_codec.h>
+#include <vlc_vout.h>
+#include <vlc_codecs.h>                               /* BITMAPINFOHEADER */
+#include <vlc_avcodec.h>
+#include <src/video_output/vout_pictures.h>
+
+/* VDPAU libraries */
+#include <vdpau/vdpau.h>
+#include <vdpau/vdpau_x11.h>
+
+/* X11 libraries */
+#include <X11/Xlib.h>
+
+/* To load vdpau functions (dlopen) */
+#include <dlfcn.h>
+
+/* ffmpeg header */
+#include <libavcodec/avcodec.h>
+#include <libavcodec/vdpau.h>
+
+#include "avcodec.h"
+
+/*****************************************************************************
+ * decoder_sys_t : decoder descriptor
+ *****************************************************************************/
+struct decoder_sys_t
+{
+    FFMPEG_COMMON_MEMBERS
+
+    /* Video decoder specific part */
+    mtime_t input_pts;
+    mtime_t input_dts;
+    mtime_t i_pts;
+
+    AVFrame          *p_ff_pic;
+
+    /* for frame skipping algo */
+    bool b_hurry_up;
+    enum AVDiscard i_skip_frame;
+    enum AVDiscard i_skip_idct;
+
+    /* how many decoded frames are late */
+    int     i_late_frames;
+    mtime_t i_late_frames_start;
+
+    /* for direct rendering */
+    bool b_direct_rendering;
+
+    bool b_has_b_frames;
+
+    /* Hack to force display of still pictures */
+    bool b_first_frame;
+
+    int i_buffer_orig, i_buffer;
+    char *p_buffer_orig, *p_buffer;
+
+    /* */
+    AVPaletteControl palette;
+
+    /* */
+    bool b_flush;
+
+    /* VDPAU device and init functions */
+    VdpDevice vdp_device;
+    VdpDeviceCreateX11 *pf_vdp_device_create;
+    VdpGetProcAddress * pf_vdp_get_proc_address;
+    VdpPreemptionCallbackRegister * pf_vdp_preemption_callback_register;
+
+    /* VDPAU decoding functions*/
+    VdpDeviceDestroy *pf_vdp_device_destroy;
+
+    VdpVideoSurfaceCreate *pf_vdp_video_surface_create;
+    VdpVideoSurfaceDestroy *pf_vdp_video_surface_destroy;
+
+    VdpDecoderCreate *pf_vdp_decoder_create;
+    VdpDecoderDestroy *pf_vdp_decoder_destroy;
+    VdpDecoderRender *pf_vdp_decoder_render;
+
+    VdpVideoSurfacePutBitsYCbCr *pf_vdp_video_surface_get_bits_y_cb_cr;
+
+    /* VDPAU objects and variables */
+    VdpChromaType vdp_chroma_type;
+    VdpDecoderProfile vdp_decoder_profile;
+
+    VdpDecoder vdp_decoder;
+    //VdpVideoSurface vdp_video_surface;
+
+    int i_max_refs;
+
+    struct vdpau_render_state p_render_surfaces[17];
+    
+    //struct Display *p_display;
+    Display *p_display;
+    int i_screen;
+
+    int i_used_surfaces;
+
+    /* VDPAU error handling function */
+    VdpGetErrorString *pf_vdp_get_error_string; 
+    bool reinit_needed;
+
+};
+
+/* FIXME (dummy palette for now) */
+static const AVPaletteControl palette_control;
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static void ffmpeg_InitCodec      ( decoder_t * );
+static int  ffmpeg_OpenCodec      ( decoder_t * );
+static int  ffmpeg_OpenVDPAU      ( decoder_t * );
+static void ffmpeg_CopyPicture    ( decoder_t *, picture_t *, AVFrame * );
+static int  ffmpeg_GetFrameBuf    ( struct AVCodecContext *, AVFrame * );
+static int  ffmpeg_ReGetFrameBuf  ( struct AVCodecContext *, AVFrame * );
+static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *, AVFrame * );
+static void ffmpeg_SetFrameBufferPts( decoder_t *p_dec, AVFrame *p_ff_pic );
+static void ffmpeg_NextPts        ( decoder_t * );
+
+static int  InitVDPAUFunction     (decoder_t *p_dec, int i_func, void *pf_func);
+static int  LibraryLink           (decoder_t *p_dec);
+
+static struct vdpau_render_state *vdpau_GetFreeSurface(decoder_t *p_dec);
+
+static uint32_t ffmpeg_CodecTag( vlc_fourcc_t fcc )
+{
+    uint8_t *p = (uint8_t*)&fcc;
+    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+}
+
+static void  ffmpeg_PreemptionCallback      ( VdpDevice,  decoder_t * );
+static void  ffmpeg_reinitialize_decoder ( decoder_t * ); 
+
+/*****************************************************************************
+ * Local Functions
+ *****************************************************************************/
+
+/* Returns a new picture buffer */
+static inline picture_t *ffmpeg_NewPictBuf( decoder_t *p_dec,
+                                            AVCodecContext *p_context )
+{
+    msg_Dbg( p_dec, "Function NewPictBuf called" );
+    picture_t *p_pic;
+
+    p_dec->fmt_out.video.i_width = p_context->width;
+    p_dec->fmt_out.video.i_height = p_context->height;
+
+    if( !p_context->width || !p_context->height )
+    {
+        return NULL; /* invalid display size */
+    }
+
+    if( GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt ) != VLC_SUCCESS )
+    {
+        /* we are doomed, but not really, because most codecs set their pix_fmt much later */
+        p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
+    }
+    p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma;
+
+    /* If an aspect-ratio was specified in the input format then force it */
+    if( p_dec->fmt_in.video.i_aspect )
+    {
+        p_dec->fmt_out.video.i_aspect = p_dec->fmt_in.video.i_aspect;
+    }
+    else
+    {
+        p_dec->fmt_out.video.i_aspect =
+            VOUT_ASPECT_FACTOR * ( av_q2d(p_context->sample_aspect_ratio) *
+                p_context->width / p_context->height );
+        p_dec->fmt_out.video.i_sar_num = p_context->sample_aspect_ratio.num;
+        p_dec->fmt_out.video.i_sar_den = p_context->sample_aspect_ratio.den;
+
+        if( p_dec->fmt_out.video.i_aspect == 0 )
+        {
+            p_dec->fmt_out.video.i_aspect =
+                VOUT_ASPECT_FACTOR * p_context->width / p_context->height;
+        }
+    }
+
+    if( p_dec->fmt_in.video.i_frame_rate > 0 &&
+        p_dec->fmt_in.video.i_frame_rate_base > 0 )
+    {
+        p_dec->fmt_out.video.i_frame_rate =
+            p_dec->fmt_in.video.i_frame_rate;
+        p_dec->fmt_out.video.i_frame_rate_base =
+            p_dec->fmt_in.video.i_frame_rate_base;
+    }
+    else if( p_context->time_base.num > 0 && p_context->time_base.den > 0 )
+    {
+        p_dec->fmt_out.video.i_frame_rate = p_context->time_base.den;
+        p_dec->fmt_out.video.i_frame_rate_base = p_context->time_base.num;
+    }
+
+    p_pic = decoder_NewPicture( p_dec );
+
+    return p_pic;
+}
+
+void debug_vdp_status(char * function_name, char * msg, int vdp_status, decoder_t *p_dec) 
+/* This prints out information about the return value of vdpau functions as a debug message */
+{
+   if (vdp_status != VDP_STATUS_OK)
+   {
+       msg_Dbg( p_dec, "%s : %s - %s", function_name, msg, ( p_dec->p_sys->pf_vdp_get_error_string(vdp_status) ) );
+   }
+}
+
+void error_vdp_status(char * function_name, char * msg, int vdp_status, decoder_t *p_dec) 
+/* This prints out information about the return value of vdpau functions as an error message */
+{
+   if (vdp_status != VDP_STATUS_OK)
+   {
+       msg_Err( p_dec, "%s : %s - %s", function_name, msg, ( p_dec->p_sys->pf_vdp_get_error_string(vdp_status) ) );
+   }
+} 
+
+
+static void  ffmpeg_PreemptionCallback ( VdpDevice device, decoder_t * p_dec ) 
+/* This function is called by VDPAU when the display is pre-empted
+ * It should recreate all the objects that have automatically been
+ * destroyed by VDPAU at pre-emption */
+{
+
+    msg_Err( p_dec, "ffmpeg_PreemptionCallback called" );
+
+    p_dec->p_sys->reinit_needed = true;
+}
+
+
+static void  ffmpeg_reinitialize_decoder ( decoder_t * p_dec ) 
+{
+    decoder_sys_t *p_sys;
+    p_sys = p_dec->p_sys;
+
+  
+    /* Create display for VDPAU surfaces */
+    //p_sys->p_display = XOpenDisplay( NULL );
+    p_sys->i_screen = DefaultScreen( p_sys->p_display );
+
+    VdpStatus vdp_status = p_sys->pf_vdp_device_create(p_sys->p_display, p_sys->i_screen,
+					     &(p_sys->vdp_device), &(p_sys->pf_vdp_get_proc_address));
+    error_vdp_status("ffmpeg_reinitialize_decoder", "vdp_device_create", vdp_status, p_dec);
+
+    if ( p_sys->vdp_decoder != VDP_INVALID_HANDLE ) {
+	// p_sys->pf_vdp_decoder_destroy(p_sys->vdp_decoder);
+      p_sys->vdp_decoder = VDP_INVALID_HANDLE;
+    }
+
+    for ( int i=0; i<17; i++ )
+    {
+        if(p_sys->p_render_surfaces[i].surface!=VDP_INVALID_HANDLE) {
+	    // p_sys->pf_vdp_video_surface_destroy(p_sys->p_render_surfaces[i].surface);
+	    p_sys->p_render_surfaces[i].surface=VDP_INVALID_HANDLE;
+	}
+    }
+
+     vdp_status = p_sys->pf_vdp_preemption_callback_register( p_sys->vdp_device, &ffmpeg_PreemptionCallback, p_dec);
+     error_vdp_status("ffmpeg_reinitialize_decoder", "vdp_preemption_callback_register", vdp_status, p_dec);   
+
+     p_sys->reinit_needed = false;
+     
+}
+
+/*****************************************************************************
+ * InitVideo: initialize the video decoder
+ *****************************************************************************
+ * the ffmpeg codec will be opened, some memory allocated. The vout is not yet
+ * opened (done after the first decoded frame).
+ *****************************************************************************/
+int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
+                      AVCodec *p_codec, int i_codec_id, const char *psz_namecodec )
+{
+    msg_Dbg( p_dec, "Function InitVideoDec called" );
+
+    decoder_sys_t *p_sys;
+    vlc_value_t val;
+
+    /* Allocate the memory needed to store the decoder's structure */
+    if( ( p_dec->p_sys = p_sys = calloc( 1, sizeof(decoder_sys_t) ) ) == NULL )
+        return VLC_ENOMEM;
+
+    p_sys->p_context = p_context;
+    p_sys->p_codec = p_codec;
+    p_sys->i_codec_id = i_codec_id;
+    p_sys->psz_namecodec = psz_namecodec;
+    p_sys->p_ff_pic = avcodec_alloc_frame();
+    p_sys->b_delayed_open = true;
+
+    msg_Dbg(p_dec,"Chosen codec : %s", p_codec->name);
+
+    p_dec->p_sys->i_used_surfaces = 0;
+
+    /* ***** Fill p_context with init values ***** */
+    p_sys->p_context->codec_tag = ffmpeg_CodecTag( p_dec->fmt_in.i_codec );
+
+    /*  ***** Get configuration of ffmpeg plugin ***** */
+    p_sys->p_context->workaround_bugs =
+        config_GetInt( p_dec, "ffmpeg-workaround-bugs" );
+#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
+    p_sys->p_context->error_resilience =
+        config_GetInt( p_dec, "ffmpeg-error-resilience" );
+#else
+    p_sys->p_context->error_recognition =
+        config_GetInt( p_dec, "ffmpeg-error-resilience" );
+#endif
+
+    var_Create( p_dec, "grayscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+    var_Get( p_dec, "grayscale", &val );
+    if( val.b_bool ) p_sys->p_context->flags |= CODEC_FLAG_GRAY;
+
+    var_Create( p_dec, "ffmpeg-vismv", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
+    var_Get( p_dec, "ffmpeg-vismv", &val );
+    if( val.i_int ) p_sys->p_context->debug_mv = val.i_int;
+
+    var_Create( p_dec, "ffmpeg-lowres", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
+    var_Get( p_dec, "ffmpeg-lowres", &val );
+    if( val.i_int > 0 && val.i_int <= 2 ) p_sys->p_context->lowres = val.i_int;
+
+    var_Create( p_dec, "ffmpeg-skiploopfilter",
+                VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
+    var_Get( p_dec, "ffmpeg-skiploopfilter", &val );
+    if( val.i_int > 0 ) p_sys->p_context->skip_loop_filter = AVDISCARD_NONREF;
+    if( val.i_int > 1 ) p_sys->p_context->skip_loop_filter = AVDISCARD_BIDIR;
+    if( val.i_int > 2 ) p_sys->p_context->skip_loop_filter = AVDISCARD_NONKEY;
+    if( val.i_int > 3 ) p_sys->p_context->skip_loop_filter = AVDISCARD_ALL;
+
+    bool b_fast = var_CreateGetBool( p_dec, "ffmpeg-fast" );
+    if( b_fast ) p_sys->p_context->flags2 |= CODEC_FLAG2_FAST;
+
+    /* ***** ffmpeg frame skipping ***** */
+    var_Create( p_dec, "ffmpeg-hurry-up", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+    var_Get( p_dec, "ffmpeg-hurry-up", &val );
+    p_sys->b_hurry_up = val.b_bool;
+
+    var_Create( p_dec, "ffmpeg-skip-frame", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
+    var_Get( p_dec, "ffmpeg-skip-frame", &val );
+    switch( val.i_int )
+    {
+        case -1:
+            p_sys->p_context->skip_frame = AVDISCARD_NONE;
+            break;
+        case 0:
+            p_sys->p_context->skip_frame = AVDISCARD_DEFAULT;
+            break;
+        case 1:
+            p_sys->p_context->skip_frame = AVDISCARD_BIDIR;
+            break;
+        case 2:
+            p_sys->p_context->skip_frame = AVDISCARD_NONKEY;
+            break;
+        case 3:
+            p_sys->p_context->skip_frame = AVDISCARD_ALL;
+            break;
+        default:
+            p_sys->p_context->skip_frame = AVDISCARD_NONE;
+            break;
+    }
+    p_sys->i_skip_frame = p_sys->p_context->skip_frame;
+
+    var_Create( p_dec, "ffmpeg-skip-idct",  VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
+    var_Get( p_dec, "ffmpeg-skip-idct", &val );
+    switch( val.i_int )
+    {
+        case -1:
+            p_sys->p_context->skip_idct = AVDISCARD_NONE;
+            break;
+        case 0:
+            p_sys->p_context->skip_idct = AVDISCARD_DEFAULT;
+            break;
+        case 1:
+            p_sys->p_context->skip_idct = AVDISCARD_BIDIR;
+            break;
+        case 2:
+            p_sys->p_context->skip_idct = AVDISCARD_NONKEY;
+            break;
+        case 3:
+            p_sys->p_context->skip_idct = AVDISCARD_ALL;
+            break;
+        default:
+            p_sys->p_context->skip_idct = AVDISCARD_NONE;
+            break;
+    }
+    p_sys->i_skip_idct = p_sys->p_context->skip_idct;
+
+    /* ***** ffmpeg direct rendering ***** */
+    p_sys->b_direct_rendering = false;
+    var_Create( p_dec, "ffmpeg-dr", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+    var_Get( p_dec, "ffmpeg-dr", &val );
+    if( val.b_bool && (p_sys->p_codec->capabilities & CODEC_CAP_DR1) &&
+        /* Apparently direct rendering doesn't work with YUV422P */
+        p_sys->p_context->pix_fmt != PIX_FMT_YUV422P &&
+        /* H264 uses too many reference frames */
+        p_sys->i_codec_id != CODEC_ID_H264 &&
+        /* No idea why ... but this fixes flickering on some TSCC streams */
+        p_sys->i_codec_id != CODEC_ID_TSCC &&
+        !p_sys->p_context->debug_mv )
+    {
+        /* Some codecs set pix_fmt only after the 1st frame has been decoded,
+         * so we need to do another check in ffmpeg_GetFrameBuf() */
+        p_sys->b_direct_rendering = true;
+    }
+
+    /* ffmpeg doesn't properly release old pictures when frames are skipped */
+    //if( p_sys->b_hurry_up ) p_sys->b_direct_rendering = false;
+    if( p_sys->b_direct_rendering )
+    {
+        msg_Dbg( p_dec, "using direct rendering" );
+        p_sys->p_context->flags |= CODEC_FLAG_EMU_EDGE;
+    }
+
+    /* Always use our get_buffer wrapper so we can calculate the
+     * PTS correctly */
+    p_sys->p_context->get_buffer = ffmpeg_GetFrameBuf;
+    p_sys->p_context->reget_buffer = ffmpeg_ReGetFrameBuf;
+    p_sys->p_context->release_buffer = ffmpeg_ReleaseFrameBuf;
+    p_sys->p_context->opaque = p_dec;
+
+    /* ***** misc init ***** */
+    p_sys->input_pts = p_sys->input_dts = 0;
+    p_sys->i_pts = 0;
+    p_sys->b_has_b_frames = false;
+    p_sys->b_first_frame = true;
+    p_sys->b_flush = false;
+    p_sys->i_late_frames = 0;
+    p_sys->i_buffer = 0;
+    p_sys->i_buffer_orig = 1;
+    p_sys->p_buffer_orig = p_sys->p_buffer = malloc( p_sys->i_buffer_orig );
+    if( !p_sys->p_buffer_orig )
+    {
+        free( p_sys );
+        return VLC_ENOMEM;
+    }
+
+    /* Set output properties */
+    p_dec->fmt_out.i_cat = VIDEO_ES;
+    if( GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt ) != VLC_SUCCESS )
+    {
+        /* we are doomed. but not really, because most codecs set their pix_fmt later on */
+        p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
+    }
+    p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma;
+
+    /* Setup palette */
+    memset( &p_sys->palette, 0, sizeof(p_sys->palette) );
+    if( p_dec->fmt_in.video.p_palette )
+    {
+        p_sys->palette.palette_changed = 1;
+
+        for( int i = 0; i < __MIN( AVPALETTE_COUNT, p_dec->fmt_in.video.p_palette->i_entries ); i++ )
+        {
+            union {
+                uint32_t u;
+                uint8_t a[4];
+            } c;
+            c.a[0] = p_dec->fmt_in.video.p_palette->palette[i][0];
+            c.a[1] = p_dec->fmt_in.video.p_palette->palette[i][1];
+            c.a[2] = p_dec->fmt_in.video.p_palette->palette[i][2];
+            c.a[3] = p_dec->fmt_in.video.p_palette->palette[i][3];
+
+            p_sys->palette.palette[i] = c.u;
+        }
+        p_sys->p_context->palctrl = &p_sys->palette;
+
+        p_dec->fmt_out.video.p_palette = malloc( sizeof(video_palette_t) );
+        if( p_dec->fmt_out.video.p_palette )
+            *p_dec->fmt_out.video.p_palette = *p_dec->fmt_in.video.p_palette;
+    }
+    else if( p_sys->i_codec_id != CODEC_ID_MSVIDEO1 && p_sys->i_codec_id != CODEC_ID_CINEPAK )
+    {
+        p_sys->p_context->palctrl = &p_sys->palette;
+    }
+
+    /* ***** init this codec with special data ***** */
+    ffmpeg_InitCodec( p_dec );
+
+    /* ***** Open the codec ***** */
+    if( ffmpeg_OpenCodec( p_dec ) < 0 || ffmpeg_OpenVDPAU( p_dec ) < 0)
+    {
+        msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
+        free( p_sys->p_buffer_orig );
+        free( p_sys );
+        return VLC_EGENERIC;
+    }
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * DecodeVideo: Called to decode one or more frames
+ *****************************************************************************/
+picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
+{
+
+    msg_Dbg( p_dec, "Function DecodeVideo called" );
+
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    int b_drawpicture;
+    int b_null_size = false;
+    block_t *p_block;
+
+    if( !pp_block || !*pp_block )
+        return NULL;
+
+    if( !p_sys->p_context->extradata_size && p_dec->fmt_in.i_extra )
+    {
+        ffmpeg_InitCodec( p_dec );
+        if( p_sys->b_delayed_open )
+        {
+            if( ffmpeg_OpenCodec( p_dec ) )
+                msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
+        }
+    }
+
+    p_block = *pp_block;
+    if( p_sys->b_delayed_open )
+    {
+        block_Release( p_block );
+        return NULL;
+    }
+
+    if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
+    {
+        p_sys->i_buffer = 0;
+        p_sys->i_pts = 0; /* To make sure we recover properly */
+
+        p_sys->input_pts = p_sys->input_dts = 0;
+        p_sys->i_late_frames = 0;
+
+        block_Release( p_block );
+
+        //if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
+            //avcodec_flush_buffers( p_sys->p_context );
+        return NULL;
+    }
+
+    if( p_block->i_flags & BLOCK_FLAG_PREROLL )
+    {
+        /* Do not care about late frames when prerolling
+         * TODO avoid decoding of non reference frame
+         * (ie all B except for H264 where it depends only on nal_ref_idc) */
+        p_sys->i_late_frames = 0;
+    }
+
+    if( !p_dec->b_pace_control && (p_sys->i_late_frames > 0) &&
+        (mdate() - p_sys->i_late_frames_start > INT64_C(5000000)) )
+    {
+        if( p_sys->i_pts )
+        {
+            msg_Err( p_dec, "more than 5 seconds of late video -> "
+                     "dropping frame (computer too slow ?)" );
+            p_sys->i_pts = 0; /* To make sure we recover properly */
+        }
+        block_Release( p_block );
+        p_sys->i_late_frames--;
+        return NULL;
+    }
+
+    if( p_block->i_pts > 0 || p_block->i_dts > 0 )
+    {
+        p_sys->input_pts = p_block->i_pts;
+        p_sys->input_dts = p_block->i_dts;
+
+        /* Make sure we don't reuse the same timestamps twice */
+        p_block->i_pts = p_block->i_dts = 0;
+    }
+
+    /* A good idea could be to decode all I pictures and see for the other */
+    if( !p_dec->b_pace_control &&
+        p_sys->b_hurry_up &&
+        (p_sys->i_late_frames > 4) )
+    {
+        b_drawpicture = 0;
+        if( p_sys->i_late_frames < 12 )
+        {
+            p_sys->p_context->skip_frame =
+                    (p_sys->i_skip_frame <= AVDISCARD_BIDIR) ?
+                    AVDISCARD_BIDIR : p_sys->i_skip_frame;
+        }
+        else
+        {
+            /* picture too late, won't decode
+             * but break picture until a new I, and for mpeg4 ...*/
+            p_sys->i_late_frames--; /* needed else it will never be decrease */
+            block_Release( p_block );
+            p_sys->i_buffer = 0;
+            return NULL;
+        }
+    }
+    else
+    {
+        if( p_sys->b_hurry_up )
+            p_sys->p_context->skip_frame = p_sys->i_skip_frame;
+        if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
+            b_drawpicture = 1;
+        else
+            b_drawpicture = 0;
+    }
+
+    if( p_sys->p_context->width <= 0 || p_sys->p_context->height <= 0 )
+    {
+        if( p_sys->b_hurry_up )
+            p_sys->p_context->skip_frame = p_sys->i_skip_frame;
+        b_null_size = true;
+    }
+    else if( !b_drawpicture )
+    {
+        /* It creates broken picture
+         * FIXME either our parser or ffmpeg is broken */
+#if 0
+        if( p_sys->b_hurry_up )
+            p_sys->p_context->skip_frame = __MAX( p_sys->p_context->skip_frame,
+                                                  AVDISCARD_NONREF );
+#endif
+    }
+
+    /*
+     * Do the actual decoding now
+     */
+
+    /* Don't forget that ffmpeg requires a little more bytes
+     * that the real frame size */
+    if( p_block->i_buffer > 0 )
+    {
+        p_sys->b_flush = ( p_block->i_flags & BLOCK_FLAG_END_OF_SEQUENCE ) != 0;
+
+        p_sys->i_buffer = p_block->i_buffer;
+        if( p_sys->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE >
+            p_sys->i_buffer_orig )
+        {
+            free( p_sys->p_buffer_orig );
+            p_sys->i_buffer_orig =
+                p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE;
+            p_sys->p_buffer_orig = malloc( p_sys->i_buffer_orig );
+        }
+        p_sys->p_buffer = p_sys->p_buffer_orig;
+        p_sys->i_buffer = p_block->i_buffer;
+        if( !p_sys->p_buffer )
+        {
+            block_Release( p_block );
+            return NULL;
+        }
+        vlc_memcpy( p_sys->p_buffer, p_block->p_buffer, p_block->i_buffer );
+        memset( p_sys->p_buffer + p_block->i_buffer, 0,
+                FF_INPUT_BUFFER_PADDING_SIZE );
+
+        p_block->i_buffer = 0;
+    }
+
+    if (p_sys->reinit_needed) {
+	ffmpeg_reinitialize_decoder(p_dec); 
+    }
+
+    while( p_sys->i_buffer > 0 || p_sys->b_flush )
+    {
+        msg_Dbg( p_dec, "DecodeVideo: New while step" );
+        int i_used, b_gotpicture;
+        picture_t *p_pic;
+
+        /* This fills in p_sys->p_context which gives us header information
+         * and does NOT decode the frame when using vdpau */
+        i_used = avcodec_decode_video( p_sys->p_context, p_sys->p_ff_pic,
+                                       &b_gotpicture,
+                                       p_sys->i_buffer <= 0 && p_sys->b_flush ? NULL : (uint8_t*)p_sys->p_buffer, p_sys->i_buffer );
+
+        if( b_null_size && p_sys->p_context->width > 0 &&
+            p_sys->p_context->height > 0 &&
+            !p_sys->b_flush )
+        {
+            /* Reparse it to not drop the I frame */ 
+            b_null_size = false;
+            if( p_sys->b_hurry_up )
+                p_sys->p_context->skip_frame = p_sys->i_skip_frame;
+            i_used = avcodec_decode_video( p_sys->p_context, p_sys->p_ff_pic,
+                                           &b_gotpicture,
+                                           (uint8_t*)p_sys->p_buffer, p_sys->i_buffer );
+        }
+
+        if( p_sys->b_flush )
+            p_sys->b_first_frame = true;
+
+        if( p_sys->i_buffer <= 0 )
+            p_sys->b_flush = false;
+
+        if( i_used < 0 )
+        {
+            if( b_drawpicture )
+                msg_Warn( p_dec, "cannot decode one frame (%d bytes)",
+                          p_sys->i_buffer );
+            block_Release( p_block );
+            return NULL;
+        }
+        else if( i_used > p_sys->i_buffer )
+        {
+            i_used = p_sys->i_buffer;
+        }
+
+        /* Consumed bytes */
+        p_sys->i_buffer -= i_used;
+        p_sys->p_buffer += i_used;
+
+        /* Nothing to display */
+        if( !b_gotpicture )
+        {
+            msg_Dbg( p_dec, "DecodeVideo: Nothing to display" );
+            if( i_used == 0 ) break;
+            continue;
+        }
+
+        /* Set the PTS */
+        if( p_sys->p_ff_pic->pts )
+            p_sys->i_pts = p_sys->p_ff_pic->pts;
+
+        /* Update frame late count (except when doing preroll) */
+        mtime_t i_display_date = 0;
+        if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
+            i_display_date = decoder_GetDisplayDate( p_dec, p_sys->i_pts );
+
+        if( i_display_date > 0 && i_display_date <= mdate() )
+        {
+            p_sys->i_late_frames++;
+            if( p_sys->i_late_frames == 1 )
+                p_sys->i_late_frames_start = mdate();
+        }
+        else
+        {
+            p_sys->i_late_frames = 0;
+        }
+
+        // Changed: FFMpeg does not decode so does not fill in the linesize
+        //if( !b_drawpicture || !p_sys->p_ff_pic->linesize[0] )
+        if( !b_drawpicture )
+        {
+            /* Do not display the picture */
+            msg_Dbg( p_dec, "DecodeVideo: Do not display the picture, b_drawpicture: %d, linesize[0]: %d", b_drawpicture, p_sys->p_ff_pic->linesize[0] );
+
+            p_pic = (picture_t *)p_sys->p_ff_pic->opaque;
+            if( !b_drawpicture && p_pic )
+                decoder_DeletePicture( p_dec, p_pic );
+
+            ffmpeg_NextPts( p_dec );
+            continue;
+        }
+
+        if( !p_sys->p_ff_pic->opaque )
+        {
+
+            msg_Dbg( p_dec, "DecodeVideo: No opaque picture found" );
+
+            /* Get a new picture */
+
+            /* Attention: This will create a new picture with the chroma given in
+             * p_context. Set YV12 chroma, because this will be the format
+             * given by VDPAU GetBits function...  */
+            p_sys->p_context->pix_fmt = PIX_FMT_YUV420P;
+
+            p_pic = ffmpeg_NewPictBuf( p_dec, p_sys->p_context );
+            if( !p_pic )
+            {
+                msg_Dbg( p_dec, "DecodeVideo: No picture found" );
+                block_Release( p_block );
+                return NULL;
+            }
+
+            /* This will pass the still encoded data to vdpau and read back
+             * the decoded data to put it in p_pic */
+            ffmpeg_CopyPicture( p_dec, p_pic, p_sys->p_ff_pic );
+        }
+        else
+        {
+
+            msg_Dbg( p_dec, "DecodeVideo: Opaque picture found" );
+
+            /* We will never have opaque pictures when using vdpau,
+             * because with this command it will never be decoded...!?  */
+            p_pic = (picture_t *)p_sys->p_ff_pic->opaque;
+        }
+
+        /* Sanity check (seems to be needed for some streams) */
+        if( p_sys->p_ff_pic->pict_type == FF_B_TYPE )
+        {
+            p_sys->b_has_b_frames = true;
+        }
+
+        if( !p_dec->fmt_in.video.i_aspect )
+        {
+            /* Fetch again the aspect ratio in case it changed */
+            p_dec->fmt_out.video.i_aspect =
+                VOUT_ASPECT_FACTOR
+                    * ( av_q2d(p_sys->p_context->sample_aspect_ratio)
+                    * p_sys->p_context->width / p_sys->p_context->height );
+            p_dec->fmt_out.video.i_sar_num
+                = p_sys->p_context->sample_aspect_ratio.num;
+            p_dec->fmt_out.video.i_sar_den
+                = p_sys->p_context->sample_aspect_ratio.den;
+
+            if( p_dec->fmt_out.video.i_aspect == 0 )
+            {
+                p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR
+                    * p_sys->p_context->width / p_sys->p_context->height;
+            }
+        }
+
+        /* Send decoded frame to vout */
+        if( p_sys->i_pts )
+        {
+            p_pic->date = p_sys->i_pts;
+
+            ffmpeg_NextPts( p_dec );
+
+            if( p_sys->b_first_frame )
+            {
+                /* Hack to force display of still pictures */
+                p_sys->b_first_frame = false;
+                p_pic->b_force = true;
+            }
+
+            p_pic->i_nb_fields = 2 + p_sys->p_ff_pic->repeat_pict;
+            p_pic->b_progressive = !p_sys->p_ff_pic->interlaced_frame;
+            p_pic->b_top_field_first = p_sys->p_ff_pic->top_field_first;
+
+            p_pic->i_qstride = p_sys->p_ff_pic->qstride;
+            int i_mb_h = ( p_pic->format.i_height + 15 ) / 16;
+            p_pic->p_q = malloc( p_pic->i_qstride * i_mb_h );
+            memcpy( p_pic->p_q, p_sys->p_ff_pic->qscale_table,
+                    p_pic->i_qstride * i_mb_h );
+            switch( p_sys->p_ff_pic->qscale_type )
+            {
+                case FF_QSCALE_TYPE_MPEG1:
+                    p_pic->i_qtype = QTYPE_MPEG1;
+                    break;
+                case FF_QSCALE_TYPE_MPEG2:
+                    p_pic->i_qtype = QTYPE_MPEG2;
+                    break;
+                case FF_QSCALE_TYPE_H264:
+                    p_pic->i_qtype = QTYPE_H264;
+                    break;
+            }
+
+            return p_pic;
+        }
+        else
+        {
+            decoder_DeletePicture( p_dec, p_pic );
+        }
+    }
+
+    block_Release( p_block );
+    return NULL;
+}
+
+/*****************************************************************************
+ * EndVideo: decoder destruction
+ *****************************************************************************
+ * This function is called when the thread ends after a successful
+ * initialization.
+ *****************************************************************************/
+void EndVideoDec( decoder_t *p_dec )
+{
+    msg_Dbg( p_dec, "Function EndVideoDec called" );
+
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    if( p_sys->p_ff_pic ) av_free( p_sys->p_ff_pic );
+    free( p_sys->p_buffer_orig );
+}
+
+/*****************************************************************************
+ * ffmpeg_InitCodec: setup codec extra initialization data for ffmpeg
+ *****************************************************************************/
+static void ffmpeg_InitCodec( decoder_t *p_dec )
+{
+    msg_Dbg( p_dec, "Function ffmpeg_InitCodec called" );
+
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    int i_size = p_dec->fmt_in.i_extra;
+    
+    if( !i_size ) return;
+    
+    p_sys->p_context->extradata_size = i_size;
+    p_sys->p_context->extradata =
+        malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );
+    if( p_sys->p_context->extradata )
+    {
+        memcpy( p_sys->p_context->extradata,
+                p_dec->fmt_in.p_extra, i_size );
+        memset( &((uint8_t*)p_sys->p_context->extradata)[i_size],
+                0, FF_INPUT_BUFFER_PADDING_SIZE );
+    }
+}
+
+/*****************************************************************************
+ * ffmpeg_OpenCodec:
+ *****************************************************************************/
+static int ffmpeg_OpenCodec( decoder_t *p_dec )
+{
+    msg_Dbg( p_dec, "Function ffmpeg_OpenCodec called" );
+
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    if( p_sys->p_context->extradata_size <= 0 )
+    {
+        if( p_sys->i_codec_id == CODEC_ID_VC1 ||
+            p_sys->i_codec_id == CODEC_ID_VORBIS ||
+            p_sys->i_codec_id == CODEC_ID_THEORA )
+        {
+            msg_Warn( p_dec, "waiting for extra data for codec %s",
+                      p_sys->psz_namecodec );
+            return 1;
+        }
+    }
+    p_sys->p_context->width  = p_dec->fmt_in.video.i_width;
+    p_sys->p_context->height = p_dec->fmt_in.video.i_height;
+#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
+    p_sys->p_context->bits_per_sample = p_dec->fmt_in.video.i_bits_per_pixel;
+#else
+    p_sys->p_context->bits_per_coded_sample = p_dec->fmt_in.video.i_bits_per_pixel;
+#endif
+
+    int ret;
+    vlc_avcodec_lock();
+    ret = avcodec_open( p_sys->p_context, p_sys->p_codec );
+    vlc_avcodec_unlock();
+    if( ret < 0 )
+        return VLC_EGENERIC;
+    msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec );
+
+    p_sys->b_delayed_open = false;
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * ffmpeg_OpenVDPAU: initialize VDPAU variables and functions used to decode
+ *                   ffmpeg's VDPAU output
+ *****************************************************************************/
+static int ffmpeg_OpenVDPAU ( decoder_t * p_this)
+{
+
+    msg_Dbg( p_this, "Function ffmpeg_OpenVDPAU called" );
+
+    VdpStatus vdp_status;
+    decoder_t *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys=p_dec->p_sys;
+
+    if (LibraryLink(p_dec)!=VLC_SUCCESS)
+    {
+        return VLC_EGENERIC;
+    }
+
+    /* This defines Chroma Type
+     * And H264 profile. This depends on the video and could be automatically
+     * filled!? */
+    p_sys->vdp_chroma_type= VDP_CHROMA_TYPE_420;
+    p_sys->vdp_decoder_profile = VDP_DECODER_PROFILE_H264_MAIN;
+
+    /* Create display for VDPAU surfaces */
+    //char *psz_display = var_CreateGetNonEmptyString( p_dec, "x11-display" );
+    //p_sys->p_display = XOpenDisplay( psz_display );
+    p_sys->p_display = XOpenDisplay( NULL );
+    //free( psz_display );
+    p_sys->i_screen = DefaultScreen( p_sys->p_display );
+
+    /* Create VDPAU device which will allow to call all the other functions */
+    vdp_status = p_sys->pf_vdp_device_create(p_sys->p_display, p_sys->i_screen,
+					     &(p_sys->vdp_device), &(p_sys->pf_vdp_get_proc_address));
+
+    /* Initialize all the VDPAU functions */
+    int i_errors=0;
+    i_errors += InitVDPAUFunction( p_dec,VDP_FUNC_ID_DEVICE_DESTROY,&(p_sys->pf_vdp_device_destroy ) );
+
+    i_errors += InitVDPAUFunction( p_dec,VDP_FUNC_ID_VIDEO_SURFACE_CREATE,&(p_sys->pf_vdp_video_surface_create ) );
+    i_errors += InitVDPAUFunction( p_dec,VDP_FUNC_ID_VIDEO_SURFACE_DESTROY,&(p_sys->pf_vdp_video_surface_destroy ) );
+
+    i_errors += InitVDPAUFunction( p_dec,VDP_FUNC_ID_DECODER_CREATE,&(p_sys->pf_vdp_decoder_create ) );
+    i_errors += InitVDPAUFunction( p_dec,VDP_FUNC_ID_DECODER_DESTROY,&(p_sys->pf_vdp_decoder_destroy ) );
+    i_errors += InitVDPAUFunction( p_dec,VDP_FUNC_ID_DECODER_RENDER,&(p_sys->pf_vdp_decoder_render ) );
+
+    i_errors += InitVDPAUFunction( p_dec,VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR,&(p_sys->pf_vdp_video_surface_get_bits_y_cb_cr) );
+    i_errors += InitVDPAUFunction( p_dec,VDP_FUNC_ID_GET_ERROR_STRING,&(p_sys->pf_vdp_get_error_string) );
+    i_errors += InitVDPAUFunction( p_dec,VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER,&(p_sys->pf_vdp_preemption_callback_register) );
+
+    if ( i_errors!=VLC_SUCCESS )
+        return VLC_EGENERIC;
+
+    
+    /* Lets prepare surfaces */
+    for ( int i=0; i<17; i++ )
+    {
+        p_sys->p_render_surfaces[i].surface=VDP_INVALID_HANDLE;
+    }
+
+    /* Register display pre-emption callback function */
+    p_sys->pf_vdp_preemption_callback_register( p_sys->vdp_device, &ffmpeg_PreemptionCallback, p_dec);
+
+
+    p_sys->reinit_needed = false;
+    error_vdp_status("ffmpeg_OpenVDPAU", "vdp_preemption_callback_register", vdp_status, p_dec);
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * ffmpeg_CopyPicture: Do VDPAU video decoding, obtain decoded data from VDPAU
+ *                     data structures and put the frames into VLC's
+ *                     picture_t structure (when not in direct rendering mode).
+ *****************************************************************************/
+static void ffmpeg_CopyPicture( decoder_t *p_dec,
+                                picture_t *p_pic, AVFrame *p_ff_pic )
+{
+
+
+    msg_Dbg( p_dec, "Function CopyPicture called" );
+
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    #define VDPAU_PLANE_NUMBER 3
+    VdpStatus vdp_status;
+
+    uint32_t i_vdp_pitches[VDPAU_PLANE_NUMBER];
+    uint8_t *p_vdp_picture_data[VDPAU_PLANE_NUMBER];
+    void *p_vdp_picture_data_orig[VDPAU_PLANE_NUMBER];
+    
+    int i_plane, i_line, i_dst_stride, i_src_stride;
+    uint8_t *p_dst, *p_src;
+    
+    int i_width = p_dec->fmt_in.video.i_width;
+    int i_height = p_dec->fmt_in.video.i_height;
+
+    /* Read still encoded data from ffmpeg structure and interpret as vdpau_render_state */
+    struct vdpau_render_state *rndr = (struct vdpau_render_state *)p_ff_pic->data[0];
+
+    /* We created video surfaces in here before
+    if (rndr->surface == VDP_INVALID_HANDLE) {
+
+      msg_Dbg( p_dec, "ffmpeg_CopyPicture: Creation of new video surface" );
+
+      vdp_status = p_sys->pf_vdp_video_surface_create(p_sys->vdp_device, p_sys->vdp_chroma_type,
+                                                      i_width, i_height,
+                                                      //&(p_sys->vdp_video_surface));
+							&(rndr->surface));
+      
+      if (vdp_status != VDP_STATUS_OK)
+        {
+          msg_Err( p_dec, "ffmpeg_CopyPicture: could not create vdpau video surface (%d)", vdp_status );
+          //return;
+        }
+    }
+    */
+
+    if ( p_sys->vdp_decoder == NULL || p_sys->vdp_decoder == VDP_INVALID_HANDLE )
+    /* Create a new decoder if none is present */
+    {
+        msg_Dbg(p_dec, "ffmpeg_CopyPicture: creation of first decoder");
+        //p_sys->vdp_decoder = malloc( sizeof(VdpDecoder) ); // Memory does not have to be allocated
+        vdp_status = p_sys->pf_vdp_decoder_create( p_sys->vdp_device, p_sys->vdp_decoder_profile,
+                                                   i_width, i_height, rndr->info.h264.num_ref_frames,
+                                                   &(p_sys->vdp_decoder) );
+
+        error_vdp_status("ffmpeg_CopyPicture", "vdp_decoder_create NULL decoder", vdp_status, p_dec);
+	p_sys->i_max_refs=rndr->info.h264.num_ref_frames;
+	msg_Dbg(p_dec, "ffmpeg_CopyPicture: p_sys->i_max_refs %d",p_sys->i_max_refs);
+
+    }
+    else if ( p_sys->i_max_refs < rndr->info.h264.num_ref_frames )
+    /* If a decoder is present but without enough reference frames to accomodate
+     * the video stream, destroy existing decoder and create a new one */
+    {
+	msg_Dbg(p_dec, "ffmpeg_CopyPicture: creation of a new decoder");
+
+        p_sys->pf_vdp_decoder_destroy(p_sys->vdp_decoder);
+        vdp_status = p_sys->pf_vdp_decoder_create( p_sys->vdp_device, p_sys->vdp_decoder_profile,
+                                                   i_width, i_height, rndr->info.h264.num_ref_frames,
+                                                   &(p_sys->vdp_decoder) );
+        p_sys->i_max_refs = rndr->info.h264.num_ref_frames;
+
+        error_vdp_status("ffmpeg_CopyPicture", "vdp_decoder_create not enough reference frames", vdp_status, p_dec);
+    }
+    
+    //msg_Dbg( p_dec, "ffmpeg_CopyPicture: bitstream before decoding: %d", rndr->bitstream_buffers[1].bitstream_bytes);
+
+    msg_Dbg(p_dec,"ffmpeg_CopyPicture :  rndr->bitstream_buffers_used : %d", rndr->bitstream_buffers_used);
+    msg_Dbg(p_dec,"ffmpeg_CopyPicture :  rndr->bitstream_buffers : %d",rndr->bitstream_buffers);
+    msg_Dbg(p_dec,"ffmpeg_CopyPicture :  rndr->bitstream_buffers_allocated : %d", rndr->bitstream_buffers_allocated);
+
+    /* Do VDPAU decoding
+     * It is not clear how to determine the number of used bistream buffers
+     * This is a dirty hack */ 
+    vdp_status = p_sys->pf_vdp_decoder_render( p_sys->vdp_decoder, rndr->surface,
+                                               (void *)&rndr->info,
+					       rndr->bitstream_buffers_used==0?2:rndr->bitstream_buffers_used,
+                                               rndr->bitstream_buffers );
+    error_vdp_status("ffmpeg_CopyPicture", "vdp_decoder_render", vdp_status, p_dec);
+
+    msg_Dbg(p_dec,"ffmpeg_CopyPicture :  rndr->info.h264.is_reference : %d",rndr->info.h264.is_reference);
+    msg_Dbg(p_dec,"ffmpeg_CopyPicture : *(p_sys->p_vdp_decoder) : %d",p_sys->vdp_decoder);
+
+    /* Now load the decoded data from VDPAU structures to VLC structures
+     * Attention: For the following part we have to be sure that the p_pic is of chroma YV12.
+     * Look into the calling function whether this is correctly created ... */
+    
+    /* It is not clear here whether memory has to be allocated for the picture data or not
+     * but in every case we will have three planes and the pitch information for every plane
+     * We use vlc_memalign to get an aligned block of memory, perhaps this is important!? */
+    
+    for ( i_plane = 0; i_plane < VDPAU_PLANE_NUMBER; i_plane++ )
+    {
+	i_vdp_pitches[i_plane] = p_pic->p[i_plane].i_pitch;
+        msg_Dbg( p_dec, "ffmpeg_CopyPicture: i_pitch: %d, i_lines: %d", p_pic->p[i_plane].i_pitch, p_pic->p[i_plane].i_lines);
+        // p_vdp_picture_data[i_plane] = malloc( p_pic->p[i_plane].i_pitch * p_pic->p[i_plane].i_lines * 100 * sizeof(uint8_t));
+        p_vdp_picture_data[i_plane] = vlc_memalign( &p_vdp_picture_data_orig[i_plane], 16, p_pic->p[i_plane].i_pitch * p_pic->p[i_plane].i_lines );
+    }
+
+    /* Obtain decompressed video data. Put it into the given structure and
+     * deliver us also pitches information */    
+    vdp_status = p_sys->pf_vdp_video_surface_get_bits_y_cb_cr ( rndr->surface,
+                                                                VDP_YCBCR_FORMAT_YV12,
+                                                                p_vdp_picture_data,
+                                                                i_vdp_pitches );
+    
+    error_vdp_status("ffmpeg_CopyPicture", "vdp_video_surface_get_bits_y_cb_cr", vdp_status, p_dec);
+    
+    msg_Dbg( p_dec, "ffmpeg_CopyPicture: rndr->surface : %d", rndr->surface);
+    
+    
+    /* Copy data from VDPAU structures into VLC structures
+     * In other codecs this is quite complicated, because the strides can
+     * be different. It is not sure whether it has to be done so complicated in
+     * here */
+    for( i_plane = 0; i_plane < VDPAU_PLANE_NUMBER; i_plane++ )
+    {
+        p_dst = p_pic->p[i_plane].p_pixels;
+        /* Which is the order of the YUV planes? For another codec the following was proposed */
+        //p_src = i_plane ? (i_plane - 1 ? p_vdp_picture_data[2] : p_vdp_picture_data[1] ) : p_vdp_picture_data[0];
+        p_src = p_vdp_picture_data[i_plane];
+        i_dst_stride  = p_pic->p[i_plane].i_pitch;
+        i_src_stride  = i_vdp_pitches[i_plane]; // Stride of the source
+
+        for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
+        {
+            vlc_memcpy( p_dst, p_src, p_pic->p[i_plane].i_pitch ); // Width of the source
+            p_src += i_src_stride;
+            p_dst += i_dst_stride;
+        }
+    }
+
+    
+    /* Free memory */
+    for ( i_plane = 0; i_plane < VDPAU_PLANE_NUMBER; i_plane++ )
+    {
+        free( p_vdp_picture_data_orig[i_plane] );
+    }
+
+}
+
+/*****************************************************************************
+ * ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer.
+ *****************************************************************************
+ * It is used for direct rendering as well as to get the right PTS for each
+ * decoded picture (even in indirect rendering mode).
+ *****************************************************************************/
+static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
+                               AVFrame *p_ff_pic )
+{
+
+    decoder_t *p_dec = (decoder_t *)p_context->opaque;
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    struct vdpau_render_state* rndr;
+
+    /* Set picture PTS */
+    ffmpeg_SetFrameBufferPts( p_dec, p_ff_pic );
+
+    /* */
+    p_ff_pic->opaque = 0;
+
+    /* Some codecs set pix_fmt only after the 1st frame has been decoded,
+     * so we need to check for direct rendering again. */
+    int i_width = p_sys->p_context->width;
+    int i_height = p_sys->p_context->height;
+    avcodec_align_dimensions( p_sys->p_context, &i_width, &i_height );
+
+    /* We do not need this a priori because we always know our chroma!?
+
+    msg_Dbg( p_dec, "p_context->pix_fmt: %d", p_context->pix_fmt);
+
+    int GetVlcChromaResult = GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt );
+
+    msg_Dbg( p_dec, "GetVlcChroma Result: %d", GetVlcChromaResult );
+
+    if( GetVlcChromaResult != VLC_SUCCESS ||  
+        p_sys->p_context->width % 16 || p_sys->p_context->height % 16 ||
+        // We only pad picture up to 16
+        PAD(p_sys->p_context->width,16) < i_width || PAD(p_sys->p_context->height,16) < i_height ||
+        p_context->pix_fmt == PIX_FMT_PAL8 )
+    {
+        // If it occurs, it's going to be difficult
+        //   TODO: Verify if it can occur ; error handling
+        msg_Dbg( p_dec, "disabling direct rendering" );
+        p_sys->b_direct_rendering = false;
+        return avcodec_default_get_buffer( p_context, p_ff_pic );
+    }
+    */
+
+    p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma;
+
+    /* Get a new render state */
+    rndr = vdpau_GetFreeSurface(p_dec);
+
+    msg_Dbg( p_dec, "Function ffmpeg_GetFrameBuf called : surface number %d", rndr - p_sys->p_render_surfaces );
+
+    rndr->state |= FF_VDPAU_STATE_USED_FOR_REFERENCE;
+    
+    p_sys->p_context->draw_horiz_band = NULL;
+
+    p_ff_pic->type = FF_BUFFER_TYPE_USER;
+    p_ff_pic->data[0] = (void*)rndr;
+    msg_Dbg(p_dec,"Function ffmpeg_GetFrameBuf : bitstreams used %d", rndr->bitstream_buffers_used);
+
+    /* FIXME what is that, should give good value */
+    p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg
+
+    return 0;
+}
+
+static int  ffmpeg_ReGetFrameBuf( struct AVCodecContext *p_context, AVFrame *p_ff_pic )
+/* TODO: Find something useful to do with this function */
+{
+
+    decoder_t *p_dec = (decoder_t *)p_context->opaque;
+    int i_ret;
+
+    msg_Dbg( p_dec, "Function ffmpeg_ReGetFrameBuf called" );
+
+    /* */
+    p_ff_pic->pts = AV_NOPTS_VALUE;
+
+    /* We always use default reget function, it works perfectly fine */
+    i_ret = avcodec_default_reget_buffer( p_context, p_ff_pic );
+
+    /* Set picture PTS if avcodec_default_reget_buffer didn't set it (through a
+     * ffmpeg_GetFrameBuf call) */
+    if( !i_ret && p_ff_pic->pts == AV_NOPTS_VALUE )
+        ffmpeg_SetFrameBufferPts( p_dec, p_ff_pic );
+
+    return i_ret;
+}
+
+static void ffmpeg_SetFrameBufferPts( decoder_t *p_dec, AVFrame *p_ff_pic )
+{
+    msg_Dbg( p_dec, "Function ffmpeg_SetFrameBufferPts called" );
+
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    /* Set picture PTS */
+    if( p_sys->input_pts )
+    {
+        p_ff_pic->pts = p_sys->input_pts;
+    }
+    else if( p_sys->input_dts )
+    {
+        /* Some demuxers only set the dts so let's try to find a useful
+         * timestamp from this */
+        if( !p_sys->p_context->has_b_frames || !p_sys->b_has_b_frames ||
+            !p_ff_pic->reference || !p_sys->i_pts )
+        {
+            p_ff_pic->pts = p_sys->input_dts;
+        }
+        else
+        {
+            p_ff_pic->pts = 0;
+        }
+    }
+    else
+    {
+        p_ff_pic->pts = 0;
+    }
+
+    if( p_sys->i_pts ) /* make sure 1st frame has a pts > 0 */
+    {
+        p_sys->input_pts = p_sys->input_dts = 0;
+    }
+}
+
+static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
+                                    AVFrame *p_ff_pic )
+/* This should free a certain video surface so that it can be reused */
+{
+
+    decoder_t *p_dec = (decoder_t *)p_context->opaque;
+    msg_Dbg( p_dec, "Function ReleaseFrameBuf called" );
+
+    struct vdpau_render_state *render = (struct vdpau_render_state*) p_ff_pic->data[0];
+    render->state &= ~FF_VDPAU_STATE_USED_FOR_REFERENCE;
+
+    //VdpStatus vdp_status = p_dec->p_sys->pf_vdp_video_surface_destroy(render->surface);
+    //error_vdp_status("ffmpeg_ReleaseFrameBuf", "", vdp_status, p_dec);
+    //render->surface = VDP_INVALID_HANDLE;
+
+    p_ff_pic->data[0] = NULL;
+    p_ff_pic->data[1] = NULL;
+    p_ff_pic->data[2] = NULL;
+    p_ff_pic->data[3] = NULL;
+
+    p_dec->p_sys->i_used_surfaces--;
+    msg_Dbg( p_dec, "ffmpeg_ReleaseFrameBuf: i_used_surfaces = %d", p_dec->p_sys->i_used_surfaces );
+}
+
+static void ffmpeg_NextPts( decoder_t *p_dec )
+{
+    msg_Dbg( p_dec, "Function ffmpeg_NextPts called" );
+
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    if( p_sys->i_pts <= 0 )
+        return;
+
+    /* interpolate the next PTS */
+    if( p_dec->fmt_in.video.i_frame_rate > 0 &&
+        p_dec->fmt_in.video.i_frame_rate_base > 0 )
+    {
+        p_sys->i_pts += INT64_C(1000000) *
+            (2 + p_sys->p_ff_pic->repeat_pict) *
+            p_dec->fmt_in.video.i_frame_rate_base /
+            (2 * p_dec->fmt_in.video.i_frame_rate);
+    }
+    else if( p_sys->p_context->time_base.den > 0 )
+    {
+        p_sys->i_pts += INT64_C(1000000) *
+            (2 + p_sys->p_ff_pic->repeat_pict) *
+            p_sys->p_context->time_base.num /
+            (2 * p_sys->p_context->time_base.den);
+    }
+}
+
+/*****************************************************************************
+ * Init VDPAU decoder
+ *****************************************************************************/
+static int LibraryLink(decoder_t *p_dec)
+/* Construct link to VDPAU library so that the first hook vdp_device_create
+   can be used. All the other VDPAU functions are defined afterwards */
+{
+    msg_Dbg( p_dec, "Function LibraryLink called" );
+
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    static const char *psz_vdpaulibrary = "libvdpau.so.1";
+    static const char *psz_vdpau_device_create = "vdp_device_create_x11";
+
+    void * vdpau_lib_handle = dlopen(psz_vdpaulibrary, RTLD_LAZY);
+    if (!vdpau_lib_handle) {
+        return VLC_EGENERIC;
+    }
+
+    p_sys->pf_vdp_device_create = dlsym(vdpau_lib_handle, psz_vdpau_device_create);
+
+    if (!p_sys->pf_vdp_device_create) {
+        return VLC_EGENERIC;
+    }
+    
+    // Why have we put this here ? I don't remember ...
+    /*if (!vo_init() || win_x11_init_vdpau_procs())
+      return VLC_EGENERIC;*/
+
+    return VLC_SUCCESS;
+}
+
+static int InitVDPAUFunction(decoder_t *p_dec, int i_func, void *pf_func)
+{
+    msg_Dbg( p_dec, "Function InitVDPAUFunction called" );
+    VdpStatus vdp_status;
+    vdp_status=p_dec->p_sys->pf_vdp_get_proc_address(p_dec->p_sys->vdp_device,i_func,pf_func);
+    if( vdp_status != VDP_STATUS_OK)
+        return VLC_EGENERIC;
+    return VLC_SUCCESS;
+}
+
+static struct vdpau_render_state *vdpau_GetFreeSurface(decoder_t *p_dec)
+{
+    msg_Dbg( p_dec, "Function vdpau_GetFreeSurface called" );
+    decoder_sys_t* p_sys=p_dec->p_sys;
+    p_dec->p_sys->i_used_surfaces++;
+
+    msg_Dbg( p_dec, "vdpau_GetFreeSurface: i_used_surfaces = %d",  p_dec->p_sys->i_used_surfaces );
+
+    for (int i=0; i<17; i++)
+    {
+	if ( p_sys->p_render_surfaces[i].surface == VDP_INVALID_HANDLE || !(p_sys->p_render_surfaces[i].state & FF_VDPAU_STATE_USED_FOR_REFERENCE)) {
+
+            int i_width = p_dec->fmt_in.video.i_width;
+            int i_height = p_dec->fmt_in.video.i_height;
+            
+            struct vdpau_render_state *rndr = &(p_dec->p_sys->p_render_surfaces[i]);
+            
+            if (rndr->surface == VDP_INVALID_HANDLE)
+	    {
+                VdpStatus vdp_status = p_sys->pf_vdp_video_surface_create
+                    (p_sys->vdp_device, p_sys->vdp_chroma_type,
+                     i_width, i_height,
+                     //&(p_sys->vdp_video_surface));
+                     &(rndr->surface));
+                
+                msg_Dbg( p_dec, "vdpau_GetFreeSurface: Creation of new video surface i=%d, rndr->surface= %d", i, rndr->surface );
+                error_vdp_status("vdpau_GetFreeSurface", "could not create vdpau video surface", vdp_status, p_dec);
+                
+            }    
+            return &(p_sys->p_render_surfaces[i]);
+        }
+    }
+    
+    msg_Dbg( p_dec, "vdpau_GetFreeSurface: No free surface available" );
+    
+    return NULL;
+}
