VAAPI support for xine

View: New views
4 Messages — Rating Filter:   Alert me  

VAAPI support for xine

by ebsi4711 :: Rate this Message:

| View Threaded | Show Only this Message

Since a while i work on VAAPI support for xine.

The repository moved from Sourceforge to github :


On the decoder side the ffmpeg VAAPI support is used. 
On the output side i wrote a new plugin which is using VAAPI, The plugin
is based on ideas found in mplayer and vdpau output plugin.

cu

Edgar Hucek


------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure contains a
definitive record of customers, application performance, security
threats, fraudulent activity and more. Splunk takes this data and makes
sense of it. Business sense. IT sense. Common sense.
http://p.sf.net/sfu/splunk-d2dcopy1
_______________________________________________
xine-devel mailing list
xine-devel@...
https://lists.sourceforge.net/lists/listinfo/xine-devel

Re: VAAPI support for xine

by Darren Salt :: Rate this Message:

| View Threaded | Show Only this Message

I demand that ebsi4711 may or may not have written...

> Since a while i work on VAAPI support for xine.

> The repository moved from Sourceforge to github :

> https://github.com/huceke/xine-lib-vaapi/commits/vaapi
>  and
> https://github.com/huceke/xine-lib-vaapi/commits/vaapi-testing

Would prefer this as a mercurial-format repository. However, there's
mercurial-git, which should be sufficient to make this a non-problem.

> On the decoder side the ffmpeg VAAPI support is used.
> On the output side i wrote a new plugin which is using VAAPI, The plugin
> is based on ideas found in mplayer and vdpau output plugin.

Interesting.

Any ABI or API changes (which are not merely extensions)? If there are, that
makes this 1.2-only: such changes intended for 1.1 will be rejected outright.


--
| Darren Salt  | linux or ds at  | nr. Ashington, |  _  ASCII ribbon
| using Debian | youmustbejoking | Northumberland | ( ) campaign against
| GNU/Linux    | ,demon,co,uk    |                |  X  HTML e-mail
                                                    / \ www.asciiribbon.org
No sentence fragments.

------------------------------------------------------------------------------
All of the data generated in your IT infrastructure is seriously valuable.
Why? It contains a definitive record of application performance, security
threats, fraudulent activity, and more. Splunk takes this data and makes
sense of it. IT sense. And common sense.
http://p.sf.net/sfu/splunk-d2dcopy2
_______________________________________________
xine-devel mailing list
xine-devel@...
https://lists.sourceforge.net/lists/listinfo/xine-devel

Re: VAAPI support for xine

by ebsi4711 :: Rate this Message:

| View Threaded | Show Only this Message

The VAAPI support is clear for 1.2. For the OSD it uses similiar functionality like VDPAU. ( ARGB Overlays. )
What i can say, there are no ABI changes from my side. Attached you a patch where you can see my changes
and additions. What's not done so far is the autoconf side, to check if libva is installed. There i would need help.
Libva is a must for the support in the ffmpeg decoder. To make the support optinonal would end in an ifdef mess.

cu

Edgar (gimli) Hucek

2011/9/26 Darren Salt <linux@...>
I demand that ebsi4711 may or may not have written...

> Since a while i work on VAAPI support for xine.

> The repository moved from Sourceforge to github :

> https://github.com/huceke/xine-lib-vaapi/commits/vaapi
>  and
> https://github.com/huceke/xine-lib-vaapi/commits/vaapi-testing

Would prefer this as a mercurial-format repository. However, there's
mercurial-git, which should be sufficient to make this a non-problem.

> On the decoder side the ffmpeg VAAPI support is used.
> On the output side i wrote a new plugin which is using VAAPI, The plugin
> is based on ideas found in mplayer and vdpau output plugin.

Interesting.

Any ABI or API changes (which are not merely extensions)? If there are, that
makes this 1.2-only: such changes intended for 1.1 will be rejected outright.


--
| Darren Salt  | linux or ds at  | nr. Ashington, |  _  ASCII ribbon
| using Debian | youmustbejoking | Northumberland | ( ) campaign against
| GNU/Linux    | ,demon,co,uk    |                |  X  HTML e-mail
                                                   / \ www.asciiribbon.org
No sentence fragments.

------------------------------------------------------------------------------
All of the data generated in your IT infrastructure is seriously valuable.
Why? It contains a definitive record of application performance, security
threats, fraudulent activity, and more. Splunk takes this data and makes
sense of it. IT sense. And common sense.
http://p.sf.net/sfu/splunk-d2dcopy2
_______________________________________________
xine-devel mailing list
xine-devel@...
https://lists.sourceforge.net/lists/listinfo/xine-devel


[vaapi.patch]

diff --git a/README.vaapi b/README.vaapi
new file mode 100644
index 0000000..8ba7edc
--- /dev/null
+++ b/README.vaapi
@@ -0,0 +1,97 @@
+Make sure you have the following in your ~/.xine/config.
+
+General ffmpeg settings :
+
+# Priorität für Dekoder ffmpeg-wmv8
+# numeric, default: 0
+engine.decoder_priorities.ffmpeg-wmv8:0
+
+# Priorität für Dekoder ffmpeg-wmv9
+# numeric, default: 0
+engine.decoder_priorities.ffmpeg-wmv9:0
+
+# Priorität für Dekoder ffmpegvideo
+# numeric, default: 0
+engine.decoder_priorities.ffmpegvideo:1
+
+# Priorität für Dekoder mpeg2
+# numeric, default: 0
+#engine.decoder_priorities.mpeg2:0
+
+Video out settings :
+
+#vaapi: set deinterlace to 0 ( none ), 1 ( top field ), 2 ( bob ).
+# numeric, default: 0
+#video.output.vaapi_deinterlace:0
+
+# vaapi: VDR osd height workaround.
+# numeric, default: 0
+#video.output.vaapi_vdr_osd_height:0
+
+# vaapi: VDR osd width workaround.
+# numeric, default: 0
+#video.output.vaapi_vdr_osd_width:0
+
+# VAAPI Mpeg2 softdecoding
+# bool, default: 0
+#video.processing.vaapi_mpeg_softdec:0
+
+# VAAPI Mpeg2 softdecoding deinterlace
+# bool, default: 0
+#video.processing.vaapi_mpeg_softdec_deinterlace:0
+
+# vaapi: opengl output rendering
+# bool, default: 0
+#video.output.vaapi_opengl_render:0
+
+# vaapi: opengl rendering tfp
+# bool, default: 0
+#video.output.vaapi_opengl_use_tfp:0
+
+# vaapi: set vaapi_guarded_render to 0 ( yes ) 1 ( no )
+# numeric, default: 0
+#video.output.vaapi_guarded_render:0
+
+If you see crashes set guarded render mode.
+
+# vaapi: swap UV planes.
+# bool, default: 0
+#video.output.vaapi_swap_uv_planes:0
+
+Swap UV is a workaround for IronLake chipsets where the driver is bugy.
+
+
+Notes on use with VDR. The OSD will have some delay. This is technical and can only be overcome
+writting a complete new decoder which use VAAPI direct and not ffmpeg.
+
+For using unsclaed OSD there you can overwrite the OSD size in the config file.
+
+For xineliboutput use the defaults.
+
+For vdr-xine set in VDR the OSD size to 1920x1080 and use the following in ~/.xine/config :
+
+video.output.vaapi_vdr_osd_height:0
+video.output.vaapi_vdr_osd_width:0
+
+The workaround is needed, because vdr-xine does not report the real unscaled OSD size.
+
+
+When you get GPU hangs on Mpeg2 material set :
+
+video.processing.vaapi_mpeg_softdec:1
+
+This disables VAAPI fpr Mpeg2.
+
+
+You can use example.config.vaapi as an example config for xine.
+
+Call xine like : xine -V vaapi video.mkv
+
+xvba-vaapi hints:
+
+export LIBVA_DRIVER_NAME=xvba
+export LIBVA_DRIVERS_PATH=/usr/lib/dri/
+video.output.vaapi_opengl_render:1
+
+
+Postprocessing does not work. Do not use "--post vdr_video --post vdr-audio --post vdr" in your xine call.
diff --git a/example.config.vaapi b/example.config.vaapi
new file mode 100644
index 0000000..901860b
--- /dev/null
+++ b/example.config.vaapi
@@ -0,0 +1,749 @@
+#
+# xine config file
+#
+.version:2
+
+# Entries which are still set to their default values are commented out.
+# Remove the '#' at the beginning of the line, if you want to change them.
+
+# Deinterlacing automatisch aktivieren
+# bool, default: 0
+#gui.deinterlace_by_default:0
+
+# Erfahrenheit einstellen
+# { Beginner  Advanced  Expert  Master of the known universe }, default: 0
+#gui.experience_level:Beginner
+
+# OSD-Unterstützung aktivieren
+# bool, default: 1
+#gui.osd_enabled:1
+
+# OSD Anzeigezeit [s]
+# numeric, default: 3
+#gui.osd_timeout:3
+
+# Benutzer fragen bei Wiedergabe mit nichtunterstütztem coder
+# bool, default: 0
+#gui.play_anyway:0
+
+# Automatische alte Playliste wiederherstellen
+# bool, default: 0
+#gui.playlist_auto_reload:0
+
+# Audio-Visualisierung
+# { oscope  fftscope  fftgraph  goom }, default: 0
+#gui.post_audio_plugin:oscope
+
+# gui skin Thema
+# { xinetic }, default: 0
+#gui.skin:xinetic
+
+# xine-Verhalten für unerfahrene Benutzer anpassen
+# bool, default: 1
+#gui.smart_mode:1
+
+# Schnappschußverzeichnis
+# string, default: /home/gimli
+#gui.snapshotdir:/home/gimli
+
+# Startbildschirm anzeigen
+# bool, default: 1
+#gui.splash:1
+
+# Untertitel automatisch laden
+# bool, default: 1
+#gui.subtitle_autoload:1
+
+# Stil der Videoanimation
+# { None  Post Plugin  Stream Animation }, default: 1
+#gui.visual_anim:Post Plugin
+
+# Fensterüberlagerung (mehr)
+# bool, default: 0
+#gui.always_layer_above:0
+
+# Audiomischpultmethode
+# { Sound card  Software }, default: 0
+#gui.audio_mixer_method:Sound card
+
+# Anzeigeverhalten von Bedienfeld
+# bool, default: 0
+#gui.auto_panel_visibility:0
+
+# Anzeigeverhalten des Ausgabefensters
+# bool, default: 0
+#gui.auto_video_output_visibility:0
+
+# Deinterlace-Plugin.
+# string, default: tvtime:method=LinearBlend,cheap_mode=1,pulldown=0,use_progressive_frame_flag=1
+#gui.deinterlace_plugin:tvtime:method=LinearBlend,cheap_mode=1,pulldown=0,use_progressive_frame_flag=1
+
+# Verhalten von Ereignissender
+# bool, default: 1
+#gui.eventer_sticky:1
+
+# Fensterüberlagerung
+# bool, default: 0
+#gui.layer_above:0
+
+# Unvergrößertes OSD benutzen
+# bool, default: 1
+#gui.osd_use_unscaled:1
+
+# Bildschirmschoner Resetintervall [s]
+# numeric, default: 10
+#gui.screensaver_timeout:10
+
+# Menu Tastenkürzelstil
+# { Windows style  Emacs style }, default: 0
+#gui.shortcut_style:Windows style
+
+# Datenstrominformationen
+# bool, default: 0
+#gui.sinfo_auto_update:0
+
+# Skin-Server URL
+# string, default: http://xine.sourceforge.net/skins/skins.slx
+#gui.skin_server_url:http://xine.sourceforge.net/skins/skins.slx
+
+# Kapitelspringen
+# bool, default: 1
+#gui.skip_by_chapter:1
+
+# Neue Datemstromgröße verändert Ausgabefenstergröße
+# bool, default: 1
+#gui.stream_resize_window:1
+
+# Hinweiszeit (ms)
+# numeric, default: 5000
+#gui.tips_timeout:5000
+
+# gui Hinweise sichtbar
+# bool, default: 1
+#gui.tips_visible:1
+
+# Name des Video-Bildschirms
+# string, default:
+#gui.video_display:
+
+# Synchrones X-Protokoll (Fehlersuche)
+# bool, default: 0
+#gui.xsynchronize:0
+
+# Doppelte Größe für kleine Datemströme (Erfordert stream_resize_window)
+# bool, default: 0
+#gui.zoom_small_stream:0
+
+# Logo MRL
+# string, default: /usr/share/xine/skins/xine-ui_logo.png
+#gui.logo_mrl:/usr/share/xine/skins/xine-ui_logo.png
+
+# Benutze XVidModeExtension beim Umschalten auf Vollbild
+# bool, default: 0
+#gui.use_xvidext:0
+
+# Höhe für Xinerama-Vollbildmodus (-8192 = automatisch)
+# numeric, default: -8192
+#gui.xinerama_fullscreen_height:-8192
+
+# Breite für Xinerama-Vollbildmodus (-8192 = automatisch)
+# numeric, default: -8192
+#gui.xinerama_fullscreen_width:-8192
+
+# X-Koordinate für Xinerama-Vollbildmodus (-8192 = automatisch)
+# numeric, default: -8192
+#gui.xinerama_fullscreen_x:-8192
+
+# Y-Koordinate für Xinerama-Vollbildmodus (-8192 = automatisch)
+# numeric, default: -8192
+#gui.xinerama_fullscreen_y:-8192
+
+# Zu nutzende Bildschirme im Xinerama Vollbildmodus (z.B. 0 2 3)
+# string, default: 0 1
+#gui.xinerama_use_screens:0 1
+
+# Verstärkungslevel
+# [0..200], default: 100
+#gui.amp_level:100
+
+# gui Fenster sichtbar
+# bool, default: 1
+gui.panel_visible:0
+
+# numeric, default: 200
+#gui.panel_x:200
+
+# numeric, default: 100
+#gui.panel_y:100
+
+gui.setup_x:81
+
+gui.setup_y:104
+
+# color specification yuv-opacity
+# string, default: 8080c0-f
+#gui.osdmenu.color_focused_button:8080c0-f
+
+# color specification yuv-opacity
+# string, default: 808080-f
+#gui.osdmenu.color_focused_slider:808080-f
+
+# color specification yuv-opacity
+# string, default: ff8080-f
+#gui.osdmenu.color_focused_slider_knob:ff8080-f
+
+# color specification yuv-opacity
+# string, default: 808080-f
+#gui.osdmenu.color_focused_text_border:808080-f
+
+# color specification yuv-opacity
+# string, default: ff8080-f
+#gui.osdmenu.color_focused_text_foreground:ff8080-f
+
+# color specification yuv-opacity
+# string, default: 0080c0-f
+#gui.osdmenu.color_label_border:0080c0-f
+
+# color specification yuv-opacity
+# string, default: c08080-f
+#gui.osdmenu.color_label_foreground:c08080-f
+
+# color specification yuv-opacity
+# string, default: 0080c0-f
+#gui.osdmenu.color_label_window:0080c0-f
+
+# color specification yuv-opacity
+# string, default: 008000-f
+#gui.osdmenu.color_slider:008000-f
+
+# color specification yuv-opacity
+# string, default: ffff00-f
+#gui.osdmenu.color_slider_knob:ffff00-f
+
+# color specification yuv-opacity
+# string, default: 008000-f
+#gui.osdmenu.color_text_border:008000-f
+
+# color specification yuv-opacity
+# string, default: ffff00-f
+#gui.osdmenu.color_text_foreground:ffff00-f
+
+# color specification yuv-opacity
+# string, default: 0080c0-f
+#gui.osdmenu.color_text_window:0080c0-f
+
+# directory a media in dvd device will be mounted
+# string, default: /dvd
+#gui.osdmenu.dvd_mountpoint:/dvd
+
+# Farbpalette (Vordergrund-Rand-Hintergrund) für Untertitel und OSD
+# { white-black-transparent  white-none-transparent  white-none-translucid  yellow-black-transparent }, default: 0
+#ui.osd.text_palette:white-black-transparent
+
+# Änderungen an Hardwaremixer melden
+# bool, default: 1
+#audio.alsa_hw_mixer:1
+
+# Zu benutzender Audiotreiber
+# { auto  null  alsa  oss  file  none }, default: 0
+#audio.driver:auto
+
+# Benutze dynamische A/52 Bereichskomprimierung
+# bool, default: 0
+#audio.a52.dynamic_range:0
+
+# Heruntermischen zu Zweikanal Stereo Raumklang
+# bool, default: 0
+#audio.a52.surround_downmix:0
+
+# A/52 Lautstärke
+# [0..200], default: 100
+#audio.a52.level:100
+
+# Gerät für Monoausgabe
+# string, default: default
+#audio.device.alsa_default_device:default
+
+# Gerät für Stereoausgabe
+# string, default: plug:front:default
+audio.device.alsa_front_device:default
+
+# ALSA Mixergerät
+# string, default: PCM
+#audio.device.alsa_mixer_name:PCM
+
+# Soundkarte unterstützt mmap
+# bool, default: 0
+#audio.device.alsa_mmap_enable:0
+
+# Gerät für 5.1-Kanalausgabe
+# string, default: iec958:AES0=0x6,AES1=0x82,AES2=0x0,AES3=0x2
+#audio.device.alsa_passthrough_device:iec958:AES0=0x6,AES1=0x82,AES2=0x0,AES3=0x2
+
+# Gerät für 4-Kanalausgabe
+# string, default: plug:surround40:0
+#audio.device.alsa_surround40_device:plug:surround40:0
+
+# Gerät für 5.1-Kanalausgabe
+# string, default: plug:surround51:0
+#audio.device.alsa_surround51_device:plug:surround51:0
+
+# Lautsprecherplazierung
+# { Mono 1.0  Stereo 2.0  Headphones 2.0  Stereo 2.1  Surround 3.0  Surround 4.0  Surround 4.1  Surround 5.0  Surround 5.1  Surround 6.0  Surround 6.1  Surround 7.1  Pass Through }, default: 1
+#audio.output.speaker_arrangement:Stereo 2.0
+
+# Versatz für digitales Passthrough
+# numeric, default: 0
+#audio.synchronization.passthrough_offset:0
+
+# Audiowiedergabe während langsamer/schneller Geschwindigkeit
+# bool, default: 0
+#audio.synchronization.slow_fast_audio:0
+
+# Methode für Audio/Videosynchronisation
+# { metronom feedback  resample }, default: 0
+#audio.synchronization.av_sync_method:metronom feedback
+
+# Wenn !=0, immer auf diese Rate anpassen
+# numeric, default: 0
+#audio.synchronization.force_rate:0
+
+# Resampling benutzen
+# { auto  off  on }, default: 0
+#audio.synchronization.resample_mode:auto
+
+# Startlautstärke
+# [0..100], default: 50
+#audio.volume.mixer_volume:50
+
+# Lautstärke beim Starten wiederherstellen
+# bool, default: 0
+#audio.volume.remember_volume:0
+
+# Zu benutzender Videotreiber
+# { auto  vdpau  xv  vaapi  opengl  raw  xshm  none  fb }, default: 0
+video.driver:vaapi
+
+# Alle Videoskalierungen deaktivieren
+# bool, default: 0
+#video.output.disable_scaling:0
+
+# Horizontale Bildposition im Ausgabefenster
+# [0..100], default: 50
+#video.output.horizontal_position:50
+
+# vaapi: set deinterlace to 0 ( none ), 1 ( top field ), 2 ( bob ).
+# numeric, default: 0
+#video.output.vaapi_deinterlace:0
+
+# vaapi: indirect output rendering
+# bool, default: 0
+#video.output.vaapi_indirect_render:0
+
+# vaapi: VDR osd height workaround.
+# numeric, default: 0
+#video.output.vaapi_vdr_osd_height:0
+
+# vaapi: VDR osd width workaround.
+# numeric, default: 0
+#video.output.vaapi_vdr_osd_width:0
+
+# Vertikale Bildposition im Ausgabefenster
+# [0..100], default: 50
+#video.output.vertical_position:50
+
+# Choose speed over specification compliance
+# bool, default: 0
+#video.processing.ffmpeg_choose_speed_over_accuracy:0
+
+# Enable usage of VAAPI
+# bool, default: 1
+#video.processing.ffmpeg_enable_vaapi:1
+
+# Qualität der MPEG-4 Nachbearbeitungsstufe
+# [0..6], default: 3
+#video.processing.ffmpeg_pp_quality:3
+
+# Skip loop filter
+# { default  none  nonref  bidir  nonkey  all }, default: 0
+#video.processing.ffmpeg_skip_loop_filter:default
+
+# FFmpeg video decoding thread count
+# numeric, default: 1
+#video.processing.ffmpeg_thread_count:1
+
+# VAAPI Mpeg2 softdecoding
+# bool, default: 0
+#video.processing.vaapi_mpeg_sofdec:0
+
+# VAAPI Mpeg2 softdecoding deinterlace
+# bool, default: 0
+#video.processing.vaapi_mpeg_sofdec_deinterlace:0
+
+# Gerät für CD-Audio
+# string, default: /dev/cdrom
+#media.audio_cd.device:/dev/cdrom
+
+# Laufwerk auf diesen Faktor verlangsamen
+# numeric, default: 4
+#media.audio_cd.drive_slowdown:4
+
+# CDDB abfragen
+# bool, default: 1
+#media.audio_cd.use_cddb:1
+
+# CDDB Serverport
+# numeric, default: 8880
+#media.audio_cd.cddb_port:8880
+
+# CDDB Servername
+# string, default: freedb.freedb.org
+#media.audio_cd.cddb_server:freedb.freedb.org
+
+# BluRay player country code
+# string, default: en
+#media.bluray.country:en
+
+# device used for BluRay playback
+# string, default: /dev/dvd
+#media.bluray.device:/dev/dvd
+
+# default language for BluRay playback
+# string, default: eng
+#media.bluray.language:eng
+
+# BluRay mount point
+# string, default: /mnt/bluray
+#media.bluray.mountpoint:/mnt/bluray
+
+# parental control age limit (1-99)
+# numeric, default: 99
+#media.bluray.parental:99
+
+# BluRay player region code (1=A, 2=B, 4=C)
+# numeric, default: 7
+#media.bluray.region:7
+
+# Pfad zum Sichen von Datenströmen
+# string, default:
+#media.capture.save_dir:
+
+# Nummer der zu benutzenden DVB-Karte.
+# numeric, default: 0
+#media.dvb.adapter:0
+
+# Zuletzt gesehenen DVB-Kanal vermerken
+# bool, default: 1
+#media.dvb.remember_channel:1
+
+# Number of seconds until tuning times out.
+# numeric, default: 0
+#media.dvb.tuning_timeout:0
+
+# Enable the DVB GUI
+# bool, default: 1
+#media.dvb.gui_enabled:1
+
+# Zuletzt gesehener DVB-Kanal
+# numeric, default: -1
+#media.dvb.last_channel:-1
+
+# Standardsprache für die DVD-Wiedergabe
+# string, default: en
+#media.dvd.language:en
+
+# Region (1-8), aus der der DVD Player zu kommen scheint
+# numeric, default: 1
+#media.dvd.region:1
+
+# Gerät für DVD Wiedergabe
+# string, default: /dev/dvd
+#media.dvd.device:/dev/dvd
+
+# Pfad zum RAW-Device des DVD-Laufwerks
+# string, default: /dev/rdvd
+#media.dvd.raw_device:/dev/rdvd
+
+# Vorauseilendes Caching benutzen
+# bool, default: 1
+#media.dvd.readahead:1
+
+# CSS Entschlüsselungsmethode
+# { key  disc  title }, default: 0
+#media.dvd.css_decryption_method:key
+
+# Wiedergabemodus falls Titel/Kapitel angegeben
+# { entire dvd  one chapter }, default: 0
+#media.dvd.play_single_chapter:entire dvd
+
+# Einheit beim Suchen
+# { seek in program chain  seek in program }, default: 0
+#media.dvd.seek_behaviour:seek in program chain
+
+# Einheit für die Überspringen-Aktion
+# { skip program  skip part  skip title }, default: 0
+#media.dvd.skip_behaviour:skip program
+
+# Startverzeichnis für Dateisuche
+# string, default: /home/gimli
+#media.files.origin_path:/home/gimli
+
+# Versteckte Dateien anzeigen
+# bool, default: 0
+#media.files.show_hidden_files:0
+
+# Netzwerkbandbreite
+# { 14.4 Kbps (Modem)  19.2 Kbps (Modem)  28.8 Kbps (Modem)  33.6 Kbps (Modem)  34.4 Kbps (Modem)  57.6 Kbps (Modem)  115.2 Kbps (ISDN)  262.2 Kbps (Cable/DSL)  393.2 Kbps (Cable/DSL)  524.3 Kbps (Cable/DSL) }, default: 10
+
+# Zeitüberschreitung für Netzwerkdatenströme (in Sekunden)
+# numeric, default: 30
+#media.network.timeout:30
+
+# Domains, die den HTTP Proxy umgehen
+# string, default:
+#media.network.http_no_proxy:
+
+# HTTP Proxy Rechnername
+# string, default:
+#media.network.http_proxy_host:
+
+# HTTP Proxy Passwort
+# string, default:
+#media.network.http_proxy_password:
+
+# HTTP Proxy Portnummer
+# numeric, default: 80
+#media.network.http_proxy_port:80
+
+# HTTP Proxy Benutzername
+# string, default:
+#media.network.http_proxy_user:
+
+# MMS-Protokoll
+# { auto  TCP  HTTP }, default: 0
+#media.network.mms_protocol:auto
+
+# default VDR host
+# string, default: xvdr://127.0.0.1#nocache;demux:mpeg_block
+#media.xvdr.default_mrl:xvdr://127.0.0.1#nocache;demux:mpeg_block
+
+# Fast (low-quality) OSD scaling
+# bool, default: 0
+#media.xvdr.fast_osd_scaling:0
+
+# number of buffers for HD content
+# numeric, default: 2500
+#media.xvdr.num_buffers_hd:2500
+
+# SCR-Treshold for HD-Playback (%)
+# numeric, default: 40
+#media.xvdr.scr_treshold_hd:40
+
+# SCR-Treshold for SD-Playback (%)
+# numeric, default: 50
+#media.xvdr.scr_treshold_sd:50
+
+# SRC tuning step
+# numeric, default: 5000
+#media.xvdr.scr_tuning_step:5000
+
+# Smoother SRC tuning
+# bool, default: 0
+#media.xvdr.smooth_scr_tuning:0
+
+# opacity for the black parts of bitmapped subtitles
+# [0..100], default: 67
+#subtitles.bitmap.black_opacity:67
+
+# opacity for the colour parts of bitmapped subtitles
+# [0..100], default: 100
+#subtitles.bitmap.colour_opacity:100
+
+# Untertitelgröße
+# { tiny  small  normal  large  very large  huge }, default: 1
+#subtitles.separate.subtitle_size:small
+
+# Vertikaler Versatz für Untertitel
+# numeric, default: 0
+#subtitles.separate.vertical_offset:0
+
+# Zeichensatz für Untertitel
+# string, default: sans
+#subtitles.separate.font:sans
+
+# Zeichenkodierung für Untertitel
+# string, default: iso-8859-1
+#subtitles.separate.src_encoding:iso-8859-1
+
+# Benutze unskaliertes OSD falls möglich
+# bool, default: 1
+#subtitles.separate.use_unscaled_osd:1
+
+# Zu generierende Bilder/Sekunde
+# numeric, default: 14
+#effects.goom.fps:14
+
+# Goom Bildhöhe
+# numeric, default: 240
+#effects.goom.height:240
+
+# Goom Bildbreite
+# numeric, default: 320
+#effects.goom.width:320
+
+# Farbraumkonvertierungsmethode
+# { Fast but not photorealistic  Slow but looks better }, default: 0
+#effects.goom.csc_method:Fast but not photorealistic
+
+# Anzahl der Audiopuffer
+# numeric, default: 230
+#engine.buffers.audio_num_buffers:230
+
+# Anzahl der Videopuffer
+# numeric, default: 500
+#engine.buffers.video_num_buffers:500
+
+# Standardanzahl von Videobildern
+# numeric, default: 21
+engine.buffers.video_num_frames:22
+
+# disable decoder flush at discontinuity
+# bool, default: 0
+#engine.decoder.disable_flush_at_discontinuity:0
+
+# disable decoder flush from video out
+# bool, default: 0
+#engine.decoder.disable_flush_from_video_out:0
+
+# Priorität für Dekoder a/52
+# numeric, default: 0
+#engine.decoder_priorities.a/52:0
+
+# Priorität für Dekoder bitplane
+# numeric, default: 0
+#engine.decoder_priorities.bitplane:0
+
+# Priorität für Dekoder dts
+# numeric, default: 0
+#engine.decoder_priorities.dts:0
+
+# Priorität für Dekoder dvaudio
+# numeric, default: 0
+#engine.decoder_priorities.dvaudio:0
+
+# Priorität für Dekoder faad
+# numeric, default: 0
+#engine.decoder_priorities.faad:0
+
+# Priorität für Dekoder ffmpeg-wmv8
+# numeric, default: 0
+#engine.decoder_priorities.ffmpeg-wmv8:0
+
+# Priorität für Dekoder ffmpeg-wmv9
+# numeric, default: 0
+#engine.decoder_priorities.ffmpeg-wmv9:0
+
+# Priorität für Dekoder ffmpegaudio
+# numeric, default: 0
+#engine.decoder_priorities.ffmpegaudio:0
+
+# Priorität für Dekoder ffmpegvideo
+# numeric, default: 0
+engine.decoder_priorities.ffmpegvideo:1
+
+# Priorität für Dekoder flacdec
+# numeric, default: 0
+#engine.decoder_priorities.flacdec:0
+
+# Priorität für Dekoder gsm610
+# numeric, default: 0
+#engine.decoder_priorities.gsm610:0
+
+# Priorität für Dekoder mad
+# numeric, default: 0
+#engine.decoder_priorities.mad:0
+
+# Priorität für Dekoder mpeg2
+# numeric, default: 0
+#engine.decoder_priorities.mpeg2:0
+
+# Priorität für Dekoder pcm
+# numeric, default: 0
+#engine.decoder_priorities.pcm:0
+
+# Priorität für Dekoder rgb
+# numeric, default: 0
+#engine.decoder_priorities.rgb:0
+
+# Priorität für Dekoder spucc
+# numeric, default: 0
+#engine.decoder_priorities.spucc:0
+
+# Priorität für Dekoder spucmml
+# numeric, default: 0
+#engine.decoder_priorities.spucmml:0
+
+# Priorität für Dekoder spudec
+# numeric, default: 0
+#engine.decoder_priorities.spudec:0
+
+# Priorität für Dekoder spudvb
+# numeric, default: 0
+#engine.decoder_priorities.spudvb:0
+
+# Priorität für Dekoder spuhdmv
+# numeric, default: 0
+#engine.decoder_priorities.spuhdmv:0
+
+# Priorität für Dekoder sputext
+# numeric, default: 0
+#engine.decoder_priorities.sputext:0
+
+# Priorität für Dekoder theora
+# numeric, default: 0
+#engine.decoder_priorities.theora:0
+
+# Priorität für Dekoder vdpau_h264
+# numeric, default: 0
+#engine.decoder_priorities.vdpau_h264:0
+
+# Priorität für Dekoder vdpau_mpeg12
+# numeric, default: 0
+#engine.decoder_priorities.vdpau_mpeg12:0
+
+# Priorität für Dekoder vdpau_mpeg4
+# numeric, default: 0
+#engine.decoder_priorities.vdpau_mpeg4:0
+
+# Priorität für Dekoder vdpau_vc1
+# numeric, default: 0
+#engine.decoder_priorities.vdpau_vc1:0
+
+# Priorität für Dekoder vorbis
+# numeric, default: 0
+#engine.decoder_priorities.vorbis:0
+
+# Priorität für Dekoder yuv
+# numeric, default: 0
+#engine.decoder_priorities.yuv:0
+
+# Medienformaterkennungsstrategie
+# { default  reverse  content  extension }, default: 0
+#engine.demux.strategy:default
+
+# xines Methode zum Kopieren von Speicher
+# { probe  libc  kernel  mmx  mmxext  sse }, default: 0
+engine.performance.memcpy_method:libc
+
+# Erlaubter Prozentsatz für verworfene Frames
+# numeric, default: 10
+#engine.performance.warn_discarded_threshold:10
+
+# Erlaubter Prozentsatz für übersprungene Frames
+# numeric, default: 10
+#engine.performance.warn_skipped_threshold:10
+
+# Erlaube implizierte Änderungen an Konfiguration (z.B. durch MRL)
+# bool, default: 0
+#misc.implicit_config:0
+
diff --git a/include/xine.h b/include/xine.h
index d6f54b7..e7a2ee3 100644
--- a/include/xine.h
+++ b/include/xine.h
@@ -452,6 +452,7 @@ int  xine_get_current_frame_data (xine_stream_t *stream,
 #define XINE_IMGFMT_XVMC (('C'<<24)|('M'<<16)|('v'<<8)|'X')
 #define XINE_IMGFMT_XXMC (('C'<<24)|('M'<<16)|('x'<<8)|'X')
 #define XINE_IMGFMT_VDPAU (('A'<<24)|('P'<<16)|('D'<<8)|'V')
+#define XINE_IMGFMT_VAAPI (('P'<<24)|('A'<<16)|('A'<<8)|'V')
 
 /* get current xine's virtual presentation timestamp (1/90000 sec)
  * note: this is mostly internal data.
diff --git a/include/xine/video_out.h b/include/xine/video_out.h
index 5a04011..d648f5d 100644
--- a/include/xine/video_out.h
+++ b/include/xine/video_out.h
@@ -303,6 +303,7 @@ struct xine_video_port_s {
 #define VO_CAP_VDPAU_MPEG12           0x00000100 /* driver can use VDPAU for mpeg1/2 */
 #define VO_CAP_VDPAU_VC1              0x00000200 /* driver can use VDPAU for VC1 */
 #define VO_CAP_VDPAU_MPEG4            0x00000400 /* driver can use VDPAU for mpeg4-part2 */
+#define VO_CAP_VAAPI                  0x00000600 /* driver can use VAAPI */
 #define VO_CAP_HUE                    0x00010000
 #define VO_CAP_SATURATION             0x00020000
 #define VO_CAP_CONTRAST               0x00040000
diff --git a/src/combined/ffmpeg/Makefile.am b/src/combined/ffmpeg/Makefile.am
index c6509ed..dc2622b 100644
--- a/src/combined/ffmpeg/Makefile.am
+++ b/src/combined/ffmpeg/Makefile.am
@@ -18,12 +18,12 @@ DISTCLEANFILES = $(ff_generated)
 EXTRA_DIST = xine_video.list xine_audio.list mkcodeclist.pl
 
 xineplug_decode_ff_la_SOURCES = ffmpeg_decoder.c ff_audio_decoder.c ff_video_decoder.c \
-                                ff_mpeg_parser.c ffmpeg_decoder.h ff_mpeg_parser.h
+ ff_mpeg_parser.c ffmpeg_decoder.h ff_mpeg_parser.h
 
 nodist_xineplug_decode_ff_la_SOURCES = ffmpeg_config.h
 
 xineplug_decode_ff_la_CFLAGS = $(AM_CFLAGS) $(FFMPEG_CFLAGS) $(FFMPEG_POSTPROC_CFLAGS)
-xineplug_decode_ff_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) -lm $(ZLIB_LIBS) \
+xineplug_decode_ff_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(ZLIB_LIBS) \
  $(FFMPEG_LIBS) $(AVUTIL_LIBS) $(FFMPEG_POSTPROC_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL)
 xineplug_decode_ff_la_LDFLAGS = $(AM_LDFLAGS) $(IMPURE_TEXT_LDFLAGS)
 
diff --git a/src/combined/ffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c
index 5e4967f..20af8d1 100644
--- a/src/combined/ffmpeg/ff_video_decoder.c
+++ b/src/combined/ffmpeg/ff_video_decoder.c
@@ -50,6 +50,9 @@
 #  include <libpostproc/postprocess.h>
 #endif
 
+#include <libavcodec/vaapi.h>
+#include "accel_vaapi.h"
+
 #define VIDEOBUFSIZE        (128*1024)
 #define SLICE_BUFFER_SIZE   (1194*1024)
 
@@ -65,6 +68,10 @@
 #  define pp_mode pp_mode_t
 #endif
 
+#if LIBAVCODEC_VERSION_MAJOR >= 53 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 112)
+#  define DEPRECATED_AVCODEC_THREAD_INIT 1
+#endif
+
 typedef struct ff_video_decoder_s ff_video_decoder_t;
 
 typedef struct ff_video_class_s {
@@ -74,6 +81,9 @@ typedef struct ff_video_class_s {
   int                     thread_count;
   int8_t                  skip_loop_filter_enum;
   int8_t                  choose_speed_over_accuracy;
+  int                     enable_vaapi;
+  int                     vaapi_mpeg_softdec;
+  int                     vaapi_mpeg_softdec_deinterlace;
 
   xine_t                 *xine;
 } ff_video_class_t;
@@ -137,8 +147,12 @@ struct ff_video_decoder_s {
 #ifdef LOG
   enum PixelFormat  debug_fmt;
 #endif
-};
 
+  struct vaapi_context  vaapi_context;
+  vaapi_accel_t         *accel;
+  vo_frame_t            *accel_img;
+  uint8_t               set_stream_info;
+};
 
 static void set_stream_info(ff_video_decoder_t *this) {
   _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH,  this->bih.biWidth);
@@ -162,13 +176,72 @@ static int get_buffer(AVCodecContext *context, AVFrame *av_frame){
       this->aspect_ratio = (double)width / (double)height;
       this->aspect_ratio_prio = 1;
       lprintf("default aspect ratio: %f\n", this->aspect_ratio);
-      set_stream_info(this);
+      this->set_stream_info = 1;
     }
   }
 
   avcodec_align_dimensions(context, &width, &height);
 
-  if( this->context->pix_fmt != PIX_FMT_YUV420P && this->context->pix_fmt != PIX_FMT_YUVJ420P ) {
+  if( this->context->pix_fmt == PIX_FMT_VAAPI_VLD) {
+
+    av_frame->opaque  = NULL;
+    av_frame->data[0] = NULL;
+    av_frame->data[1] = NULL;
+    av_frame->data[2] = NULL;
+    av_frame->data[3] = NULL;
+    av_frame->type = FF_BUFFER_TYPE_USER;
+    av_frame->age = 1;
+    av_frame->reordered_opaque = context->reordered_opaque;
+
+    if(!this->accel->guarded_render(this->accel_img)) {
+      img = this->stream->video_out->get_frame (this->stream->video_out,
+                                            width,
+                                            height,
+                                            this->aspect_ratio,
+                                            this->output_format,
+                                            VO_BOTH_FIELDS|this->frame_flags);
+
+      av_frame->opaque = img;
+      xine_list_push_back(this->dr1_frames, av_frame);
+
+      vaapi_accel_t *accel = (vaapi_accel_t*)img->accel_data;
+      ff_vaapi_surface_t *va_surface = accel->get_vaapi_surface(img);
+
+      if(va_surface) {
+        av_frame->data[0] = (void *)va_surface;//(void *)(uintptr_t)va_surface->va_surface_id;
+        av_frame->data[3] = (void *)(uintptr_t)va_surface->va_surface_id;
+      }
+    } else {
+      ff_vaapi_surface_t *va_surface = this->accel->get_vaapi_surface(this->accel_img);
+
+      if(va_surface) {
+        av_frame->data[0] = (void *)va_surface;//(void *)(uintptr_t)va_surface->va_surface_id;
+        av_frame->data[3] = (void *)(uintptr_t)va_surface->va_surface_id;
+      }
+    }
+
+    lprintf("1: 0x%08x\n", av_frame->data[3]);
+
+    av_frame->linesize[0] = 0;
+    av_frame->linesize[1] = 0;
+    av_frame->linesize[2] = 0;
+    av_frame->linesize[3] = 0;
+
+    this->is_direct_rendering_disabled = 1;
+
+    return 0;
+  }
+
+  /* on vaapi out do not use direct rendeing */
+  if(this->class->enable_vaapi) {
+    this->output_format = XINE_IMGFMT_YV12;
+  }
+
+  int guarded_render = 0;
+  if(this->accel)
+    guarded_render = this->accel->guarded_render(this->accel_img);
+
+  if( (this->context->pix_fmt != PIX_FMT_YUV420P && this->context->pix_fmt != PIX_FMT_YUVJ420P) || guarded_render) {
     if (!this->is_direct_rendering_disabled) {
       xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
               _("ffmpeg_video_dec: unsupported frame format, DR1 disabled.\n"));
@@ -235,6 +308,18 @@ static int get_buffer(AVCodecContext *context, AVFrame *av_frame){
 static void release_buffer(struct AVCodecContext *context, AVFrame *av_frame){
   ff_video_decoder_t *this = (ff_video_decoder_t *)context->opaque;
 
+  if( this->context->pix_fmt == PIX_FMT_VAAPI_VLD ) {
+    if(this->accel->guarded_render(this->accel_img)) {
+      ff_vaapi_surface_t *va_surface = (ff_vaapi_surface_t *)av_frame->data[0];
+      if(va_surface != NULL) {
+        this->accel->release_vaapi_surface(this->accel_img, va_surface);
+        lprintf("release_buffer: va_surface_id 0x%08x\n", (unsigned int)av_frame->data[3]);
+      }
+    }
+  }
+
+  lprintf("3: 0x%08x\n", av_frame->data[3]);
+
   if (av_frame->type == FF_BUFFER_TYPE_USER) {
     if ( av_frame->opaque ) {
       vo_frame_t *img = (vo_frame_t *)av_frame->opaque;
@@ -245,7 +330,7 @@ static void release_buffer(struct AVCodecContext *context, AVFrame *av_frame){
     xine_list_iterator_t it;
 
     it = xine_list_find(this->dr1_frames, av_frame);
-    assert(it);
+    //assert(it);
     if( it != NULL )
       xine_list_remove(this->dr1_frames, it);
   } else {
@@ -280,6 +365,51 @@ static const int skip_loop_filter_enum_values[] = {
   AVDISCARD_ALL
 };
 
+static enum PixelFormat get_format(struct AVCodecContext *context, const enum PixelFormat *fmt)
+{
+  int i, profile;
+  ff_video_decoder_t *this = (ff_video_decoder_t *)context->opaque;
+
+  if(!this->class->enable_vaapi || !this->accel_img)
+    return PIX_FMT_YUV420P;
+
+  vaapi_accel_t *accel = (vaapi_accel_t*)this->accel_img->accel_data;
+
+  for (i = 0; fmt[i] != PIX_FMT_NONE; i++) {
+    if (fmt[i] != PIX_FMT_VAAPI_VLD)
+      continue;
+
+    profile = accel->profile_from_imgfmt(this->accel_img, fmt[i], context->codec_id, this->class->vaapi_mpeg_softdec);
+
+    if (profile >= 0) {
+      VAStatus status;
+
+      status = accel->vaapi_init(this->accel_img, profile, context->width, context->height, 0);
+
+      if( status == VA_STATUS_SUCCESS ) {
+        ff_vaapi_context_t *va_context = accel->get_context(this->accel_img);
+
+        if(!va_context)
+          return PIX_FMT_YUV420P;
+
+        context->draw_horiz_band = NULL;
+        context->slice_flags = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
+        context->dsp_mask = 0;
+
+        this->vaapi_context.config_id    = va_context->va_config_id;
+        this->vaapi_context.context_id   = va_context->va_context_id;
+        this->vaapi_context.display      = va_context->va_display;
+
+        context->hwaccel_context     = &this->vaapi_context;
+        this->pts = 0;
+
+        return fmt[i];
+      }
+    }
+  }
+  return PIX_FMT_YUV420P;
+}
+
 static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type) {
   size_t i;
 
@@ -291,6 +421,8 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type)
       pthread_mutex_lock(&ffmpeg_lock);
       this->codec = avcodec_find_decoder(ff_video_lookup[i].id);
       pthread_mutex_unlock(&ffmpeg_lock);
+      xprintf (this->stream->xine, XINE_VERBOSITY_LOG, "ffmpeg_video_dec: video codec %s\n",
+                            ff_video_lookup[i].name);
       _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC,
                             ff_video_lookup[i].name);
       break;
@@ -325,6 +457,47 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type)
   if (this->class->choose_speed_over_accuracy)
     this->context->flags2 |= CODEC_FLAG2_FAST;
 
+  if(this->class->enable_vaapi)
+  {
+    this->class->thread_count = this->context->thread_count = 1;
+
+    this->context->skip_loop_filter = AVDISCARD_DEFAULT;
+    xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+     _("ffmpeg_video_dec: force AVDISCARD_DEFAULT for VAAPI\n"));
+  } else {
+    this->context->skip_loop_filter = skip_loop_filter_enum_values[this->class->skip_loop_filter_enum];
+  }
+
+  if (this->class->thread_count > 1) {
+    if (this->codec->id != CODEC_ID_SVQ3
+#ifndef DEPRECATED_AVCODEC_THREAD_INIT
+        && avcodec_thread_init(this->context, this->class->thread_count) != -1
+#endif
+      )
+      this->context->thread_count = this->class->thread_count;
+  }
+
+  /* enable direct rendering by default */
+  this->output_format = XINE_IMGFMT_YV12;
+#ifdef ENABLE_DIRECT_RENDERING
+  if( this->codec->capabilities & CODEC_CAP_DR1 && this->codec->id != CODEC_ID_H264 ) {
+    this->context->get_buffer = get_buffer;
+    this->context->release_buffer = release_buffer;
+    xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+    _("ffmpeg_video_dec: direct rendering enabled\n"));
+  }
+
+  if( this->class->enable_vaapi ) {
+    this->output_format = XINE_IMGFMT_VAAPI;
+    this->context->get_buffer = get_buffer;
+    this->context->reget_buffer = get_buffer;
+    this->context->release_buffer = release_buffer;
+    this->context->get_format = get_format;
+    xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+    _("ffmpeg_video_dec: direct rendering enabled\n"));
+  }
+#endif
+
   pthread_mutex_lock(&ffmpeg_lock);
   if (avcodec_open (this->context, this->codec) < 0) {
     pthread_mutex_unlock(&ffmpeg_lock);
@@ -351,15 +524,6 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type)
       return;
     }
   }
-
-  if (this->class->thread_count > 1) {
-    if (this->codec->id != CODEC_ID_SVQ3
-        && avcodec_thread_init(this->context, this->class->thread_count) != -1)
-      this->context->thread_count = this->class->thread_count;
-  }
-
-  this->context->skip_loop_filter = skip_loop_filter_enum_values[this->class->skip_loop_filter_enum];
-
   pthread_mutex_unlock(&ffmpeg_lock);
 
   lprintf("lavc decoder opened\n");
@@ -382,41 +546,50 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type)
 
   this->skipframes = 0;
 
-  /* enable direct rendering by default */
-  this->output_format = XINE_IMGFMT_YV12;
-#ifdef ENABLE_DIRECT_RENDERING
-  if( this->codec->capabilities & CODEC_CAP_DR1 && this->codec->id != CODEC_ID_H264 ) {
-    this->context->get_buffer = get_buffer;
-    this->context->release_buffer = release_buffer;
-    xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
-    _("ffmpeg_video_dec: direct rendering enabled\n"));
-  }
-#endif
-
   /* flag for interlaced streams */
   this->frame_flags = 0;
   /* FIXME: which codecs can be interlaced?
       FIXME: check interlaced DCT and other codec specific info. */
-  switch( codec_type ) {
-    case BUF_VIDEO_DV:
-      this->frame_flags |= VO_INTERLACED_FLAG;
-      break;
-    case BUF_VIDEO_MPEG:
-      this->frame_flags |= VO_INTERLACED_FLAG;
-      break;
-    case BUF_VIDEO_MJPEG:
-      this->frame_flags |= VO_INTERLACED_FLAG;
-      break;
-    case BUF_VIDEO_HUFFYUV:
-      this->frame_flags |= VO_INTERLACED_FLAG;
-      break;
-    case BUF_VIDEO_H264:
-      this->frame_flags |= VO_INTERLACED_FLAG;
-      break;
+  if(!this->class->enable_vaapi) {
+    switch( codec_type ) {
+      case BUF_VIDEO_DV:
+        this->frame_flags |= VO_INTERLACED_FLAG;
+        break;
+      case BUF_VIDEO_MPEG:
+        this->frame_flags |= VO_INTERLACED_FLAG;
+        break;
+      case BUF_VIDEO_MJPEG:
+        this->frame_flags |= VO_INTERLACED_FLAG;
+        break;
+      case BUF_VIDEO_HUFFYUV:
+        this->frame_flags |= VO_INTERLACED_FLAG;
+        break;
+      case BUF_VIDEO_H264:
+        this->frame_flags |= VO_INTERLACED_FLAG;
+        break;
+    }
   }
 
 }
 
+static void vaapi_enable_vaapi(void *user_data, xine_cfg_entry_t *entry) {
+  ff_video_class_t   *class = (ff_video_class_t *) user_data;
+
+  class->enable_vaapi = entry->num_value;
+}
+
+static void vaapi_mpeg_softdec_func(void *user_data, xine_cfg_entry_t *entry) {
+  ff_video_class_t   *class = (ff_video_class_t *) user_data;
+
+  class->vaapi_mpeg_softdec = entry->num_value;
+}
+
+static void vaapi_mpeg_softdec_deinterlace(void *user_data, xine_cfg_entry_t *entry) {
+  ff_video_class_t   *class = (ff_video_class_t *) user_data;
+
+  class->vaapi_mpeg_softdec_deinterlace = entry->num_value;
+}
+
 static void choose_speed_over_accuracy_cb(void *user_data, xine_cfg_entry_t *entry) {
   ff_video_class_t   *class = (ff_video_class_t *) user_data;
 
@@ -543,7 +716,7 @@ static int ff_handle_mpeg_sequence(ff_video_decoder_t *this, mpeg_parser_t *pars
   return 1;
 }
 
-static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
+static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img, AVFrame *av_frame) {
   int         y;
   uint8_t    *dy, *du, *dv, *sy, *su, *sv;
 
@@ -555,9 +728,9 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
   dy = img->base[0];
   du = img->base[1];
   dv = img->base[2];
-  sy = this->av_frame->data[0];
-  su = this->av_frame->data[1];
-  sv = this->av_frame->data[2];
+  sy = av_frame->data[0];
+  su = av_frame->data[1];
+  sv = av_frame->data[2];
 
   /* Some segfaults & heap corruption have been observed with img->height,
    * so we use this->bih.biHeight instead (which is the displayed height)
@@ -567,18 +740,18 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
 
     yuv9_to_yv12(
      /* Y */
-      this->av_frame->data[0],
-      this->av_frame->linesize[0],
+      av_frame->data[0],
+      av_frame->linesize[0],
       img->base[0],
       img->pitches[0],
      /* U */
-      this->av_frame->data[1],
-      this->av_frame->linesize[1],
+      av_frame->data[1],
+      av_frame->linesize[1],
       img->base[1],
       img->pitches[1],
      /* V */
-      this->av_frame->data[2],
-      this->av_frame->linesize[2],
+      av_frame->data[2],
+      av_frame->linesize[2],
       img->base[2],
       img->pitches[2],
      /* width x height */
@@ -589,18 +762,18 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
 
     yuv411_to_yv12(
      /* Y */
-      this->av_frame->data[0],
-      this->av_frame->linesize[0],
+      av_frame->data[0],
+      av_frame->linesize[0],
       img->base[0],
       img->pitches[0],
      /* U */
-      this->av_frame->data[1],
-      this->av_frame->linesize[1],
+      av_frame->data[1],
+      av_frame->linesize[1],
       img->base[1],
       img->pitches[1],
      /* V */
-      this->av_frame->data[2],
-      this->av_frame->linesize[2],
+      av_frame->data[2],
+      av_frame->linesize[2],
       img->base[2],
       img->pitches[2],
      /* width x height */
@@ -630,7 +803,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
         this->yuv.v[plane_ptr] = COMPUTE_V(r, g, b);
         plane_ptr++;
       }
-      sy += this->av_frame->linesize[0];
+      sy += av_frame->linesize[0];
     }
 
     yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]);
@@ -659,7 +832,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
         this->yuv.v[plane_ptr] = COMPUTE_V(r, g, b);
         plane_ptr++;
       }
-      sy += this->av_frame->linesize[0];
+      sy += av_frame->linesize[0];
     }
 
     yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]);
@@ -688,7 +861,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
         this->yuv.v[plane_ptr] = COMPUTE_V(r, g, b);
         plane_ptr++;
       }
-      sy += this->av_frame->linesize[0];
+      sy += av_frame->linesize[0];
     }
 
     yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]);
@@ -712,7 +885,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
         this->yuv.v[plane_ptr] = COMPUTE_V(r, g, b);
         plane_ptr++;
       }
-      sy += this->av_frame->linesize[0];
+      sy += av_frame->linesize[0];
     }
 
     yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]);
@@ -736,7 +909,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
         this->yuv.v[plane_ptr] = COMPUTE_V(r, g, b);
         plane_ptr++;
       }
-      sy += this->av_frame->linesize[0];
+      sy += av_frame->linesize[0];
     }
 
     yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]);
@@ -775,7 +948,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
         this->yuv.v[plane_ptr] = v_palette[pixel];
         plane_ptr++;
       }
-      sy += this->av_frame->linesize[0];
+      sy += av_frame->linesize[0];
     }
 
     yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]);
@@ -787,7 +960,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
 
       dy += img->pitches[0];
 
-      sy += this->av_frame->linesize[0];
+      sy += av_frame->linesize[0];
     }
 
     for (y = 0; y < this->bih.biHeight / 2; y++) {
@@ -824,11 +997,11 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
       dv += img->pitches[2];
 
       if (this->context->pix_fmt != PIX_FMT_YUV420P) {
-        su += 2*this->av_frame->linesize[1];
-        sv += 2*this->av_frame->linesize[2];
+        su += 2*av_frame->linesize[1];
+        sv += 2*av_frame->linesize[2];
       } else {
-        su += this->av_frame->linesize[1];
-        sv += this->av_frame->linesize[2];
+        su += av_frame->linesize[1];
+        sv += av_frame->linesize[2];
       }
     }
   }
@@ -1013,6 +1186,52 @@ static void ff_handle_special_buffer (ff_video_decoder_t *this, buf_element_t *b
   }
 }
 
+static uint64_t ff_tag_pts(ff_video_decoder_t *this, uint64_t pts)
+{
+  return pts | this->pts_tag;
+}
+
+static uint64_t ff_untag_pts(ff_video_decoder_t *this, uint64_t pts)
+{
+  if (this->pts_tag_mask == 0)
+    return pts; /* pts tagging inactive */
+
+  if (this->pts_tag != 0 && (pts & this->pts_tag_mask) != this->pts_tag)
+    return 0; /* reset pts if outdated while waiting for first pass (see below) */
+
+  return pts & ~this->pts_tag_mask;
+}
+
+static void ff_check_pts_tagging(ff_video_decoder_t *this, uint64_t pts)
+{
+  if (this->pts_tag_mask == 0)
+    return; /* pts tagging inactive */
+  if ((pts & this->pts_tag_mask) != this->pts_tag) {
+    this->pts_tag_stable_counter = 0;
+    return; /* pts still outdated */
+  }
+
+  /* the tag should be stable for 100 frames */
+  this->pts_tag_stable_counter++;
+
+  if (this->pts_tag != 0) {
+    if (this->pts_tag_stable_counter >= 100) {
+      /* first pass: reset pts_tag */
+      this->pts_tag = 0;
+      this->pts_tag_stable_counter = 0;
+    }
+  } else if (pts == 0)
+    return; /* cannot detect second pass */
+  else {
+    if (this->pts_tag_stable_counter >= 100) {
+      /* second pass: reset pts_tag_mask and pts_tag_counter */
+      this->pts_tag_mask = 0;
+      this->pts_tag_counter = 0;
+      this->pts_tag_stable_counter = 0;
+    }
+  }
+}
+
 static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
 
   vo_frame_t *img;
@@ -1021,9 +1240,22 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu
   int         offset = 0;
   int         flush = 0;
   int         size = buf->size;
+  uint8_t     *buf_deint = 0;
+  AVFrame     *av_framedisp = this->av_frame;
+  AVFrame     *av_framedeint = NULL;
+  int         bDeint = 0;
 
   lprintf("handle_mpeg12_buffer\n");
 
+  /*
+  if(this->mpeg_parser->buffer_size == 0) {
+    this->av_frame->reordered_opaque = ff_tag_pts(this, this->pts);
+    if (this->context)
+      this->context->reordered_opaque = ff_tag_pts(this, this->pts);
+    this->pts = 0;
+  }
+  */
+
   while ((size > 0) || (flush == 1)) {
 
     uint8_t *current;
@@ -1070,12 +1302,23 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu
     avpkt.data = (uint8_t *)this->mpeg_parser->chunk_buffer;
     avpkt.size = this->mpeg_parser->buffer_size;
     avpkt.flags = AV_PKT_FLAG_KEY;
-    len = avcodec_decode_video2 (this->context, this->av_frame,
+    if(this->accel) {
+      len = this->accel->avcodec_decode_video2 ( this->accel_img, this->context, av_framedisp,
+ &got_picture, &avpkt);
+    } else {
+      len = avcodec_decode_video2 ( this->context, av_framedisp,
  &got_picture, &avpkt);
+   }
 #else
-    len = avcodec_decode_video (this->context, this->av_frame,
+    if(this->accel) {
+      len = this->accel->avcodec_decode_video ( this->accel_img, this->context, av_framedisp,
                                 &got_picture, this->mpeg_parser->chunk_buffer,
                                 this->mpeg_parser->buffer_size);
+    } else {
+      len = avcodec_decode_video (this->context, av_framedisp,
+                                &got_picture, this->mpeg_parser->chunk_buffer,
+                                this->mpeg_parser->buffer_size);
+    }
 #endif
     lprintf("avcodec_decode_video: decoded_size=%d, got_picture=%d\n",
             len, got_picture);
@@ -1091,11 +1334,31 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu
     } else {
       size -= len;
       offset += len;
+      /*
+      this->av_frame->reordered_opaque = ff_tag_pts(this, this->pts);
+      this->context->reordered_opaque = ff_tag_pts(this, this->pts);
+      this->pts = 0;
+      */
+    }
+
+    if(got_picture && this->class->enable_vaapi) {
+      int width, height;
+      width  = this->context->width;
+      height = this->context->height;
+      if((this->bih.biWidth != width) || (this->bih.biHeight != height)) {
+        this->bih.biWidth = width;
+        this->bih.biHeight = height;
+      }
     }
 
-    if (got_picture && this->av_frame->data[0]) {
+    if( this->set_stream_info) {
+      set_stream_info(this);
+      this->set_stream_info = 0;
+    }
+
+    if (got_picture && av_framedisp->data[0]) {
       /* got a picture, draw it */
-      if(!this->av_frame->opaque) {
+      if(!av_framedisp->opaque) {
         /* indirect rendering */
         img = this->stream->video_out->get_frame (this->stream->video_out,
                                                   this->bih.biWidth,
@@ -1106,21 +1369,74 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu
         free_img = 1;
       } else {
         /* DR1 */
-        img = (vo_frame_t*) this->av_frame->opaque;
+        img = (vo_frame_t*) av_framedisp->opaque;
         free_img = 0;
       }
 
-      img->pts  = this->pts;
-      this->pts = 0;
+      if( this->context->pix_fmt != PIX_FMT_VAAPI_VLD) {
+        if(av_framedisp->interlaced_frame && this->class->vaapi_mpeg_softdec_deinterlace) {
+          int size;
+          int ret;
+
+          av_framedeint = avcodec_alloc_frame();
+
+          size = avpicture_get_size(this->context->pix_fmt, this->context->width, this->context->height);
+          buf_deint = av_malloc(size);
+
+          if(av_framedeint) {
+            avpicture_fill((AVPicture*)av_framedeint, buf_deint, this->context->pix_fmt, this->context->width, this->context->height);
 
-      if (this->av_frame->repeat_pict)
+            ret = avpicture_deinterlace((AVPicture*)av_framedeint, (AVPicture*) av_framedisp,
+                                         this->context->pix_fmt, this->context->width, this->context->height);
+
+            if(ret) {
+              av_free( buf_deint );
+              av_free( av_framedeint );
+            } else {
+              bDeint = 1;
+              av_framedisp = av_framedeint;
+            }
+          } else {
+            av_free( buf_deint );
+          }
+        }
+
+        if(bDeint) {
+          ff_convert_frame(this, img, av_framedeint);
+        } else {
+          ff_convert_frame(this, img, av_framedisp);
+        }
+      }
+
+      img->progressive_frame = !this->av_frame->interlaced_frame;
+      img->top_field_first   = this->av_frame->top_field_first;
+      img->bad_frame = 0;
+
+      if (av_framedisp->repeat_pict)
         img->duration = this->video_step * 3 / 2;
       else
         img->duration = this->video_step;
 
+      img->pts  = this->pts;
+      this->pts = 0;
+
+      /*
+      img->pts  = ff_untag_pts(this, this->av_frame->reordered_opaque);
+      ff_check_pts_tagging(this, this->av_frame->reordered_opaque);
+      this->av_frame->reordered_opaque = 0;
+      */
+
       img->crop_right  = this->crop_right;
       img->crop_bottom = this->crop_bottom;
 
+      if( this->context->pix_fmt == PIX_FMT_VAAPI_VLD) {
+        if(this->accel->guarded_render(this->accel_img)) {
+          ff_vaapi_surface_t *va_surface = (ff_vaapi_surface_t *)av_framedisp->data[0];
+          this->accel->render_vaapi_surface(img, va_surface);
+          lprintf("handle_mpeg12_buffer: render_vaapi_surface va_surface_id 0x%08x\n", av_framedisp->data[0]);
+        }
+      }
+
       this->skipframes = img->draw(img, this->stream);
 
       if(free_img)
@@ -1142,6 +1458,10 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu
                                                   this->aspect_ratio,
                                                   this->output_format,
                                                   VO_BOTH_FIELDS|this->frame_flags);
+        /*
+        img->pts       = ff_untag_pts(this, this->av_frame->reordered_opaque);
+        this->av_frame->reordered_opaque = 0;
+        */
         img->pts       = 0;
         img->duration  = this->video_step;
         img->bad_frame = 1;
@@ -1149,51 +1469,11 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu
         img->free(img);
       }
     }
-  }
-}
-
-static uint64_t ff_tag_pts(ff_video_decoder_t *this, uint64_t pts)
-{
-  return pts | this->pts_tag;
-}
-
-static uint64_t ff_untag_pts(ff_video_decoder_t *this, uint64_t pts)
-{
-  if (this->pts_tag_mask == 0)
-    return pts; /* pts tagging inactive */
-
-  if (this->pts_tag != 0 && (pts & this->pts_tag_mask) != this->pts_tag)
-    return 0; /* reset pts if outdated while waiting for first pass (see below) */
-
-  return pts & ~this->pts_tag_mask;
-}
-
-static void ff_check_pts_tagging(ff_video_decoder_t *this, uint64_t pts)
-{
-  if (this->pts_tag_mask == 0)
-    return; /* pts tagging inactive */
-  if ((pts & this->pts_tag_mask) != this->pts_tag) {
-    this->pts_tag_stable_counter = 0;
-    return; /* pts still outdated */
-  }
 
-  /* the tag should be stable for 100 frames */
-  this->pts_tag_stable_counter++;
-
-  if (this->pts_tag != 0) {
-    if (this->pts_tag_stable_counter >= 100) {
-      /* first pass: reset pts_tag */
-      this->pts_tag = 0;
-      this->pts_tag_stable_counter = 0;
-    }
-  } else if (pts == 0)
-    return; /* cannot detect second pass */
-  else {
-    if (this->pts_tag_stable_counter >= 100) {
-      /* second pass: reset pts_tag_mask and pts_tag_counter */
-      this->pts_tag_mask = 0;
-      this->pts_tag_counter = 0;
-      this->pts_tag_stable_counter = 0;
+    /* free deinterlace picture */
+    if(bDeint) {
+      av_free( buf_deint );
+      av_free( av_framedeint );
     }
   }
 }
@@ -1334,12 +1614,23 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
  avpkt.data = (uint8_t *)&chunk_buf[offset];
  avpkt.size = this->size;
  avpkt.flags = AV_PKT_FLAG_KEY;
- len = avcodec_decode_video2 (this->context, this->av_frame,
+  if(this->accel) {
+   len = this->accel->avcodec_decode_video2 ( this->accel_img, this->context, this->av_frame,
      &got_picture, &avpkt);
+  } else {
+   len = avcodec_decode_video2 (this->context, this->av_frame,
+     &got_picture, &avpkt);
+  }
 #else
+  if(this->accel) {
+        len = this->accel->avcodec_decode_video ( this->accel_img, this->context, this->av_frame,
+                                    &got_picture, &chunk_buf[offset],
+                                    this->size);
+  } else {
         len = avcodec_decode_video (this->context, this->av_frame,
                                     &got_picture, &chunk_buf[offset],
                                     this->size);
+  }
 #endif
         /* reset consumed pts value */
         this->context->reordered_opaque = ff_tag_pts(this, 0);
@@ -1391,6 +1682,11 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
  set_stream_info(this);
       }
 
+      if( this->set_stream_info) {
+        set_stream_info(this);
+        this->set_stream_info = 0;
+      }
+
       if (got_picture && this->av_frame->data[0]) {
         /* got a picture, draw it */
         got_one_picture = 1;
@@ -1398,7 +1694,7 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
   /* indirect rendering */
 
   /* initialize the colorspace converter */
-  if (!this->cs_convert_init) {
+  if (!this->cs_convert_init && !this->context->pix_fmt != PIX_FMT_VAAPI_VLD) {
     if ((this->context->pix_fmt == PIX_FMT_RGB32) ||
         (this->context->pix_fmt == PIX_FMT_RGB565) ||
         (this->context->pix_fmt == PIX_FMT_RGB555) ||
@@ -1434,10 +1730,10 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
         }
 
         /* post processing */
-        if(this->pp_quality != this->class->pp_quality)
+        if(this->pp_quality != this->class->pp_quality && this->context->pix_fmt != PIX_FMT_VAAPI_VLD)
           pp_change_quality(this);
 
-        if(this->pp_available && this->pp_quality) {
+        if(this->pp_available && this->pp_quality && this->context->pix_fmt != PIX_FMT_VAAPI_VLD) {
 
           if(this->av_frame->opaque) {
             /* DR1 */
@@ -1450,7 +1746,7 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
             free_img = 1;
           }
 
-          pp_postprocess(this->av_frame->data, this->av_frame->linesize,
+          pp_postprocess((const uint8_t **)this->av_frame->data, this->av_frame->linesize,
                         img->base, img->pitches,
                         img->width, img->height,
                         this->av_frame->qscale_table, this->av_frame->qstride,
@@ -1459,7 +1755,8 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
 
         } else if (!this->av_frame->opaque) {
   /* colorspace conversion or copy */
-          ff_convert_frame(this, img);
+          if( this->context->pix_fmt != PIX_FMT_VAAPI_VLD)
+            ff_convert_frame(this, img, this->av_frame);
         }
 
         img->pts  = ff_untag_pts(this, this->av_frame->reordered_opaque);
@@ -1488,6 +1785,15 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
         img->progressive_frame = !this->av_frame->interlaced_frame;
         img->top_field_first   = this->av_frame->top_field_first;
 
+        if( this->context->pix_fmt == PIX_FMT_VAAPI_VLD) {
+          if(this->accel->guarded_render(this->accel_img)) {
+            ff_vaapi_surface_t *va_surface = (ff_vaapi_surface_t *)this->av_frame->data[0];
+            this->accel->render_vaapi_surface(img, va_surface);
+            if(va_surface)
+              lprintf("handle_buffer: render_vaapi_surface va_surface_id 0x%08x\n", this->av_frame->data[0]);
+          }
+        }
+
         this->skipframes = img->draw(img, this->stream);
 
         if(free_img)
@@ -1696,6 +2002,9 @@ static void ff_dispose (video_decoder_t *this_gen) {
 
   xine_list_delete(this->dr1_frames);
 
+  if(this->accel_img)
+    this->accel_img->free(this->accel_img);
+
   free (this_gen);
 }
 
@@ -1737,11 +2046,37 @@ static video_decoder_t *ff_video_open_plugin (video_decoder_class_t *class_gen,
   this->mpeg_parser       = NULL;
 
   this->dr1_frames        = xine_list_new();
+  this->set_stream_info   = 0;
 
 #ifdef LOG
   this->debug_fmt = -1;
 #endif
 
+  memset(&this->vaapi_context, 0x0 ,sizeof(struct vaapi_context));
+
+  this->dr1_frames        = xine_list_new();
+
+  this->accel             = NULL;
+  this->accel_img         = NULL;
+
+
+  if(this->class->enable_vaapi) {
+    this->accel_img  = stream->video_out->get_frame( stream->video_out, 1920, 1080, 1, XINE_IMGFMT_VAAPI, VO_BOTH_FIELDS );
+
+    if( this->accel_img && (stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VAAPI) ) {
+      this->accel = (vaapi_accel_t*)this->accel_img->accel_data;
+      xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: VAAPI Enabled in config.\n"));
+    } else {
+      this->class->enable_vaapi = 0;
+      xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: VAAPI Enabled disabled by driver.\n"));
+    }
+  }
+
+  xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: vaapi_mpeg_softdec %d\n"),
+          this->class->vaapi_mpeg_softdec );
+  xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: vaapi_mpeg_softdec_deinterlace %d\n"),
+          this->class->vaapi_mpeg_softdec_deinterlace );
+
   return &this->video_decoder;
 }
 
@@ -1801,6 +2136,21 @@ void *init_video_plugin (xine_t *xine, void *data) {
       "A change of this setting will take effect with playing the next stream."),
     10, choose_speed_over_accuracy_cb, this);
 
+  this->vaapi_mpeg_softdec = xine->config->register_bool(config, "video.processing.vaapi_mpeg_softdec", 0,
+    _("VAAPI Mpeg2 softdecoding"),
+    _("If the machine freezes on mpeg2 decoding use mpeg2 software decoding."),
+    10, vaapi_mpeg_softdec_func, this);
+
+  this->vaapi_mpeg_softdec_deinterlace = xine->config->register_bool(config, "video.processing.vaapi_mpeg_softdec_deinterlace", 0,
+    _("VAAPI Mpeg2 softdecoding deinterlace"),
+    _("FFMPEGS simple deinterlacer with Mpeg2 software decoding."),
+    10, vaapi_mpeg_softdec_deinterlace, this);
+
+  this->enable_vaapi = xine->config->register_bool(config, "video.processing.ffmpeg_enable_vaapi", 1,
+    _("Enable VAAPI"),
+    _("Enable or disable usage of vaapi"),
+    10, vaapi_enable_vaapi, this);
+
   return this;
 }
 
diff --git a/src/combined/ffmpeg/ffmpeg_decoder.c b/src/combined/ffmpeg/ffmpeg_decoder.c
index 4f9a0f7..a0314c8 100644
--- a/src/combined/ffmpeg/ffmpeg_decoder.c
+++ b/src/combined/ffmpeg/ffmpeg_decoder.c
@@ -39,6 +39,9 @@ void init_once_routine(void) {
   pthread_mutex_init(&ffmpeg_lock, NULL);
   avcodec_init();
   avcodec_register_all();
+
+  av_log_set_level(AV_LOG_QUIET);
+
 }
 
 /*
diff --git a/src/combined/ffmpeg/xine_video.list b/src/combined/ffmpeg/xine_video.list
index 009f4da..6364c45 100644
--- a/src/combined/ffmpeg/xine_video.list
+++ b/src/combined/ffmpeg/xine_video.list
@@ -70,7 +70,7 @@ WNV1 WNV1 Winnow Video
 XL VIXL Miro/Pinnacle VideoXL
 RT21 INDEO2 Indeo/RealTime 2
 FPS1 FRAPS Fraps
-MPEG MPEG1VIDEO MPEG 1/2
+MPEG MPEG2VIDEO MPEG 1/2
 CSCD CSCD CamStudio
 AVS AVS AVS
 ALGMM MMVIDEO American Laser Games MM
diff --git a/src/post/deinterlace/xine_plugin.c b/src/post/deinterlace/xine_plugin.c
index 5615e4b..d96aafb 100644
--- a/src/post/deinterlace/xine_plugin.c
+++ b/src/post/deinterlace/xine_plugin.c
@@ -437,6 +437,8 @@ static void deinterlace_dispose(post_plugin_t *this_gen)
   if (_x_post_dispose(this_gen)) {
     _flush_frames(this);
     pthread_mutex_destroy(&this->lock);
+    if(this->tvtime)
+      free(this->tvtime );
     free(this);
   }
 }
diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am
index 45a6f03..76708e2 100644
--- a/src/video_out/Makefile.am
+++ b/src/video_out/Makefile.am
@@ -43,6 +43,8 @@ if ENABLE_VDPAU
 vdpau_module = xineplug_vo_out_vdpau.la
 endif
 
+vaapi_module = xineplug_vo_out_vaapi.la
+
 if ENABLE_XCB
 XCBOSD = xcbosd.c
 if ENABLE_XCBSHM
@@ -117,6 +119,7 @@ xineplug_LTLIBRARIES = $(xshm_module) $(xv_module) $(xvmc_module) \
   $(xcbshm_module) \
   $(xcbxv_module) \
   $(vdpau_module) \
+  $(vaapi_module) \
                   xineplug_vo_out_raw.la \
                   xineplug_vo_out_none.la
 
@@ -124,6 +127,10 @@ xineplug_vo_out_vdpau_la_SOURCES = video_out_vdpau.c
 xineplug_vo_out_vdpau_la_LIBADD = $(YUV_LIBS) $(PTHREAD_LIBS) $(X_LIBS) $(LTLIBINTL) $(VDPAU_LIBS) -lm
 xineplug_vo_out_vdpau_la_CFLAGS = $(VISIBILITY_FLAG) $(MLIB_CFLAGS) $(X_CFLAGS) $(VDPAU_CFLAGS)
 
+xineplug_vo_out_vaapi_la_SOURCES = $(X11OSD) video_out_vaapi.c
+xineplug_vo_out_vaapi_la_LIBADD = $(YUV_LIBS) $(XINE_LIB) $(OPENGL_LIBS) $(FFMPEG_LIBS) $(AVUTIL_LIBS) $(X_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) -ldl -lGLU -lva-glx -lva-x11 -lva
+xineplug_vo_out_vaapi_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) $(XV_CFLAGS) -fno-strict-aliasing
+
 xineplug_vo_out_xcbshm_la_SOURCES = video_out_xcbshm.c $(XCBOSD)
 xineplug_vo_out_xcbshm_la_LIBADD = $(YUV_LIBS) $(PTHREAD_LIBS) $(XCB_LIBS) $(XCBSHM_LIBS) $(LTLIBINTL)
 xineplug_vo_out_xcbshm_la_CFLAGS = $(AM_CFLAGS) $(XCB_CFLAGS) $(XCBSHM_CFLAGS) $(AVUTIL_CFLAGS)
diff --git a/src/video_out/video_out_vaapi.c b/src/video_out/video_out_vaapi.c
new file mode 100644
index 0000000..42a6360
--- /dev/null
+++ b/src/video_out/video_out_vaapi.c
@@ -0,0 +1,3951 @@
+/*
+ * Copyright (C) 2000-2004, 2008 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine 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.
+ *
+ * xine 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, USA
+ *
+ * video_out_vaapi.c, VAAPI video extension interface for xine
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+
+#include <sys/types.h>
+#if defined(__FreeBSD__)
+#include <machine/param.h>
+#endif
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/time.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/cursorfont.h>
+#include <time.h>
+#include <unistd.h>
+#include "yuv2rgb.h"
+
+#define LOG_MODULE "video_out_vaapi"
+#define LOG_VERBOSE
+/*
+#define LOG
+*/
+/*
+#define DEBUG_SURFACE
+*/
+#include "xine.h"
+#include <xine/video_out.h>
+#include <xine/xine_internal.h>
+#include <xine/xineutils.h>
+#include <xine/vo_scale.h>
+
+#include <GL/glu.h>
+#include <GL/glx.h>
+#include <GL/glext.h>
+#include <GL/gl.h>
+#include <dlfcn.h>
+
+#include <va/va_x11.h>
+#include <va/va_glx.h>
+
+#include "accel_vaapi.h"
+
+#define  RENDER_SURFACES  50
+#define  SOFT_SURFACES    3
+#define  SW_WIDTH         1920
+#define  SW_HEIGHT        1080
+#define  STABLE_FRAME_COUNTER 4
+#define  SW_CONTEXT_INIT_FORMAT -1 //VAProfileH264Main
+
+#if defined VA_SRC_BT601 && defined VA_SRC_BT709
+# define USE_VAAPI_COLORSPACE 1
+#else
+# define USE_VAAPI_COLORSPACE 0
+#endif
+
+#define IMGFMT_VAAPI               0x56410000 /* 'VA'00 */
+#define IMGFMT_VAAPI_MASK          0xFFFF0000
+#define IMGFMT_IS_VAAPI(fmt)       (((fmt) & IMGFMT_VAAPI_MASK) == IMGFMT_VAAPI)
+#define IMGFMT_VAAPI_CODEC_MASK    0x000000F0
+#define IMGFMT_VAAPI_CODEC(fmt)    ((fmt) & IMGFMT_VAAPI_CODEC_MASK)
+#define IMGFMT_VAAPI_CODEC_MPEG2   (0x10)
+#define IMGFMT_VAAPI_CODEC_MPEG4   (0x20)
+#define IMGFMT_VAAPI_CODEC_H264    (0x30)
+#define IMGFMT_VAAPI_CODEC_VC1     (0x40)
+#define IMGFMT_VAAPI_MPEG2         (IMGFMT_VAAPI|IMGFMT_VAAPI_CODEC_MPEG2)
+#define IMGFMT_VAAPI_MPEG2_IDCT    (IMGFMT_VAAPI|IMGFMT_VAAPI_CODEC_MPEG2|1)
+#define IMGFMT_VAAPI_MPEG2_MOCO    (IMGFMT_VAAPI|IMGFMT_VAAPI_CODEC_MPEG2|2)
+#define IMGFMT_VAAPI_MPEG4         (IMGFMT_VAAPI|IMGFMT_VAAPI_CODEC_MPEG4)
+#define IMGFMT_VAAPI_H263          (IMGFMT_VAAPI|IMGFMT_VAAPI_CODEC_MPEG4|1)
+#define IMGFMT_VAAPI_H264          (IMGFMT_VAAPI|IMGFMT_VAAPI_CODEC_H264)
+#define IMGFMT_VAAPI_VC1           (IMGFMT_VAAPI|IMGFMT_VAAPI_CODEC_VC1)
+#define IMGFMT_VAAPI_WMV3          (IMGFMT_VAAPI|IMGFMT_VAAPI_CODEC_VC1|1)
+
+#define FOVY     60.0f
+#define ASPECT   1.0f
+#define Z_NEAR   0.1f
+#define Z_FAR    100.0f
+#define Z_CAMERA 0.869f
+
+#ifndef GLAPIENTRY
+#ifdef APIENTRY
+#define GLAPIENTRY APIENTRY
+#else
+#define GLAPIENTRY
+#endif
+#endif
+
+#if defined(__linux__)
+// Linux select() changes its timeout parameter upon return to contain
+// the remaining time. Most other unixen leave it unchanged or undefined.
+#define SELECT_SETS_REMAINING
+#elif defined(__FreeBSD__) || defined(__sun__) || (defined(__MACH__) && defined(__APPLE__))
+#define USE_NANOSLEEP
+#elif defined(HAVE_PTHREADS) && defined(sgi)
+// SGI pthreads has a bug when using pthreads+signals+nanosleep,
+// so instead of using nanosleep, wait on a CV which is never signalled.
+#include <pthread.h>
+#define USE_COND_TIMEDWAIT
+#endif
+
+#define RECT_IS_EQ(a, b) ((a).x1 == (b).x1 && (a).y1 == (b).y1 && (a).x2 == (b).x2 && (a).y2 == (b).y2)
+
+static const char *const scaling_level_enum_names[] = {
+  "default",  /* VA_FILTER_SCALING_DEFAULT       */
+  "fast",     /* VA_FILTER_SCALING_FAST          */
+  "hq",       /* VA_FILTER_SCALING_HQ            */
+  "nla",      /* VA_FILTER_SCALING_NL_ANAMORPHIC */
+  NULL
+};
+
+static const int scaling_level_enum_values[] = {
+  VA_FILTER_SCALING_DEFAULT,
+  VA_FILTER_SCALING_FAST,
+  VA_FILTER_SCALING_HQ,
+  VA_FILTER_SCALING_NL_ANAMORPHIC
+};
+
+typedef struct vaapi_driver_s vaapi_driver_t;
+
+typedef struct {
+    int x0, y0;
+    int x1, y1, x2, y2;
+} vaapi_rect_t;
+
+typedef struct {
+  vo_frame_t         vo_frame;
+
+  int                width, height, format, flags;
+  double             ratio;
+
+  vaapi_accel_t     vaapi_accel_data;
+} vaapi_frame_t;
+
+typedef struct {
+  VADisplayAttribType type;
+  int                 value;
+  int                 min;
+  int                 max;
+  int                 atom;
+
+  cfg_entry_t        *entry;
+
+  vaapi_driver_t     *this;
+
+} va_property_t;
+
+struct vaapi_driver_s {
+
+  vo_driver_t        vo_driver;
+
+  config_values_t   *config;
+
+  /* X11 related stuff */
+  Display            *display;
+  int                 screen;
+  Drawable            drawable;
+  XColor              black;
+  Window              window;
+
+  uint32_t            capabilities;
+
+  int ovl_changed;
+  vo_overlay_t       *overlays[XINE_VORAW_MAX_OVL];
+  uint32_t           *overlay_bitmap;
+  int                 overlay_bitmap_size;
+  uint32_t            overlay_bitmap_width;
+  uint32_t            overlay_bitmap_height;
+  vaapi_rect_t        overlay_bitmap_src;
+  vaapi_rect_t        overlay_bitmap_dst;
+
+  uint32_t            vdr_osd_width;
+  uint32_t            vdr_osd_height;
+
+  uint32_t            overlay_output_width;
+  uint32_t            overlay_output_height;
+  vaapi_rect_t        overlay_dirty_rect;
+  int                 has_overlay;
+
+  uint32_t            overlay_unscaled_width;
+  uint32_t            overlay_unscaled_height;
+  vaapi_rect_t        overlay_unscaled_dirty_rect;
+
+  yuv2rgb_factory_t  *yuv2rgb_factory;
+  yuv2rgb_t          *ovl_yuv2rgb;
+
+  /* all scaling information goes here */
+  vo_scale_t          sc;
+
+  xine_t             *xine;
+
+  unsigned int        deinterlace;
+  
+  int                 valid_opengl_context;
+  int                 opengl_render;
+  int                 opengl_use_tfp;
+  int                 query_va_status;
+
+  GLuint              gl_texture;
+  GLXContext          gl_context;
+  XVisualInfo         *gl_vinfo;
+  Pixmap              gl_pixmap;
+  Pixmap              gl_image_pixmap;
+
+  ff_vaapi_context_t  *va_context;
+
+  int                  num_frame_buffers;
+  vaapi_frame_t       *frames[RENDER_SURFACES];
+
+  pthread_mutex_t     vaapi_lock;
+
+  unsigned int        init_opengl_render;
+  unsigned int        guarded_render;
+  unsigned int        scaling_level_enum;
+  unsigned int        scaling_level;
+  va_property_t       props[VO_NUM_PROPERTIES];
+  unsigned int        swap_uv_planes;
+};
+
+ff_vaapi_surface_t  *va_render_surfaces   = NULL;
+VASurfaceID         *va_surface_ids       = NULL;
+VASurfaceID         *va_soft_surface_ids  = NULL;
+VAImage             *va_soft_images       = NULL;
+
+static void vaapi_destroy_subpicture(vo_driver_t *this_gen);
+static void vaapi_destroy_image(vo_driver_t *this_gen, VAImage *va_image);
+static int vaapi_ovl_associate(vo_driver_t *this_gen, int format, int bShow);
+static VAStatus vaapi_destroy_soft_surfaces(vo_driver_t *this_gen);
+static VAStatus vaapi_destroy_render_surfaces(vo_driver_t *this_gen);
+static const char *vaapi_profile_to_string(VAProfile profile);
+static int vaapi_set_property (vo_driver_t *this_gen, int property, int value);
+static void vaapi_show_display_props(vo_driver_t *this_gen);
+
+static void nv12_to_yv12(const uint8_t *y_src,  int y_src_pitch,
+                         const uint8_t *uv_src, int uv_src_pitch,
+                         uint8_t *y_dst, int y_dst_pitch,
+                         uint8_t *u_dst, int u_dst_pitch,
+                         uint8_t *v_dst, int v_dst_pitch,
+                         int src_width, int src_height,
+                         int dst_width, int dst_height,
+                         int src_data_size);
+
+static void yv12_to_nv12(const uint8_t *y_src, int y_src_pitch,
+                         const uint8_t *u_src, int u_src_pitch,
+                         const uint8_t *v_src, int v_src_pitch,
+                         uint8_t *y_dst,  int y_dst_pitch,
+                         uint8_t *uv_dst, int uv_dst_pitch,
+                         int src_width, int src_height,
+                         int dst_width, int dst_height,
+                         int dst_data_size);
+
+void (GLAPIENTRY *mpglGenTextures)(GLsizei, GLuint *);
+void (GLAPIENTRY *mpglBindTexture)(GLenum, GLuint);
+void (GLAPIENTRY *mpglXBindTexImage)(Display *, GLXDrawable, int, const int *);
+void (GLAPIENTRY *mpglXReleaseTexImage)(Display *, GLXDrawable, int);
+GLXPixmap (GLAPIENTRY *mpglXCreatePixmap)(Display *, GLXFBConfig, Pixmap, const int *);
+void (GLAPIENTRY *mpglXDestroyPixmap)(Display *, GLXPixmap);
+const GLubyte *(GLAPIENTRY *mpglGetString)(GLenum);
+void (GLAPIENTRY *mpglGenPrograms)(GLsizei, GLuint *);
+
+static const char *string_of_VAImageFormat(VAImageFormat *imgfmt)
+{
+  static char str[5];
+  str[0] = imgfmt->fourcc;
+  str[1] = imgfmt->fourcc >> 8;
+  str[2] = imgfmt->fourcc >> 16;
+  str[3] = imgfmt->fourcc >> 24;
+  str[4] = '\0';
+  return str;
+}
+
+static int vaapi_check_status(vo_driver_t *this_gen, VAStatus vaStatus, const char *msg)
+{
+
+  vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
+
+  if (vaStatus != VA_STATUS_SUCCESS) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " Error : %s: %s\n", msg, vaErrorStr(vaStatus));
+    return 0;
+  }
+  return 1;
+}
+
+/* Wrapper for ffmpeg avcodec_decode_video2 */
+#if AVVIDEO > 1
+static int guarded_avcodec_decode_video2(vo_frame_t *frame_gen, AVCodecContext *avctx, AVFrame *picture,
+                                         int *got_picture_ptr, AVPacket *avpkt) {
+
+  vaapi_driver_t  *this = (vaapi_driver_t *) frame_gen->driver;
+
+  int len = 0;
+
+
+  if(this->guarded_render) {
+    lprintf("guarded_avcodec_decode_video2 enter\n");
+    pthread_mutex_lock(&this->vaapi_lock);
+    //XLockDisplay( this->display );
+  }
+
+  len = avcodec_decode_video2 (avctx, picture, got_picture_ptr, avpkt);
+
+  if(this->guarded_render) {
+    //XUnlockDisplay( this->display );
+    pthread_mutex_unlock(&this->vaapi_lock);
+    lprintf("guarded_avcodec_decode_video2 exit\n");
+  }
+
+
+  return len;
+}
+#else
+static int guarded_avcodec_decode_video(vo_frame_t *frame_gen, AVCodecContext *avctx, AVFrame *picture,
+                                        int *got_picture_ptr, uint8_t *buf, int buf_size) {
+
+  vaapi_driver_t  *this = (vaapi_driver_t *) frame_gen->driver;
+
+  int len = 0;
+
+
+  if(this->guarded_render) {
+    lprintf("guarded_avcodec_decode_video enter\n");
+    pthread_mutex_lock(&this->vaapi_lock);
+    //XLockDisplay( this->display );
+  }
+
+  len = avcodec_decode_video (avctx, picture, got_picture_ptr, buf, buf_size);
+
+  if(this->guarded_render) {
+    //XUnlockDisplay( this->display );
+    pthread_mutex_unlock(&this->vaapi_lock);
+    lprintf("guarded_avcodec_decode_video exit\n");
+  }
+
+
+  return len;
+}
+#endif
+
+static int guarded_render(vo_frame_t *frame_gen) {
+  vaapi_driver_t  *this = (vaapi_driver_t *) frame_gen->driver;
+
+  return this->guarded_render;
+}
+
+static ff_vaapi_surface_t *get_vaapi_surface(vo_frame_t *frame_gen) {
+
+  vaapi_driver_t      *this       = (vaapi_driver_t *) frame_gen->driver;
+  vaapi_frame_t       *frame      = (vaapi_frame_t *) frame_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  ff_vaapi_surface_t  *va_surface = NULL;
+  VAStatus            vaStatus;
+
+  lprintf("get_vaapi_surface\n");
+
+  if(!va_render_surfaces)
+    return NULL;
+
+  if(this->guarded_render) {
+    /* Get next VAAPI surface marked as SURFACE_FREE */
+    for(;;) {
+      int old_head = va_context->va_head;
+      va_context->va_head = (va_context->va_head + 1) % ((RENDER_SURFACES));
+
+      va_surface = &va_render_surfaces[old_head];
+
+      if( va_surface->status == SURFACE_FREE ) {
+
+        VASurfaceStatus surf_status = 0;
+
+        if(this->query_va_status) {
+          vaStatus = vaQuerySurfaceStatus(va_context->va_display, va_surface->va_surface_id, &surf_status);
+          vaapi_check_status(va_context->driver, vaStatus, "vaQuerySurfaceStatus()");
+        } else {
+          surf_status = VASurfaceReady;
+        }
+
+        if(surf_status == VASurfaceReady) {
+
+          va_surface->status = SURFACE_ALOC;
+
+#ifdef DEBUG_SURFACE
+          printf("get_vaapi_surface 0x%08x\n", va_surface->va_surface_id);
+#endif
+
+          return &va_render_surfaces[old_head];
+        } else {
+#ifdef DEBUG_SURFACE
+          printf("get_vaapi_surface busy\n");
+#endif
+        }
+      }
+#ifdef DEBUG_SURFACE
+      printf("get_vaapi_surface miss\n");
+#endif
+    }
+  } else {
+      va_surface = &va_render_surfaces[frame->vaapi_accel_data.index];
+  }
+
+  return va_surface;
+}
+
+/* Set VAAPI surface status to render */
+static void render_vaapi_surface(vo_frame_t *frame_gen, ff_vaapi_surface_t *va_surface) {
+  vaapi_driver_t  *this = (vaapi_driver_t *) frame_gen->driver;
+  vaapi_accel_t *accel = (vaapi_accel_t*)frame_gen->accel_data;
+
+  lprintf("render_vaapi_surface\n");
+
+  if(!this->guarded_render || !accel || !va_surface)
+    return;
+
+  pthread_mutex_lock(&this->vaapi_lock);
+  //XLockDisplay( this->display );
+
+  accel->index = va_surface->index;
+
+  va_surface->status = SURFACE_RENDER;
+#ifdef DEBUG_SURFACE
+  printf("render_vaapi_surface 0x%08x\n", va_surface->va_surface_id);
+#endif
+
+  //XUnlockDisplay( this->display );
+  pthread_mutex_unlock(&this->vaapi_lock);
+}
+
+/* Set VAAPI surface status to free */
+static void release_vaapi_surface(vo_frame_t *frame_gen, ff_vaapi_surface_t *va_surface) {
+  vaapi_driver_t  *this = (vaapi_driver_t *) frame_gen->driver;
+
+  lprintf("release_vaapi_surface\n");
+
+  if(va_surface == NULL || !this->guarded_render) {
+    return;
+  }
+
+  if(va_surface->status == SURFACE_RENDER) {
+    va_surface->status = SURFACE_RENDER_RELEASE;
+  } else if (va_surface->status != SURFACE_RENDER_RELEASE) {
+    va_surface->status = SURFACE_FREE;
+#ifdef DEBUG_SURFACE
+    printf("release_surface 0x%08x\n", va_surface->va_surface_id);
+#endif
+  }
+}
+
+static VADisplay vaapi_get_display(Display *display, int opengl_render)
+{
+  VADisplay ret;
+
+  if(opengl_render) {
+    ret = vaGetDisplayGLX(display);
+  } else {
+    ret = vaGetDisplay(display);
+  }
+
+  if(vaDisplayIsValid(ret))
+    return ret;
+  else
+    return 0;
+}
+
+typedef struct {
+  void *funcptr;
+  const char *extstr;
+  const char *funcnames[7];
+  void *fallback;
+} extfunc_desc_t;
+
+#define DEF_FUNC_DESC(name) {&mpgl##name, NULL, {"gl"#name, NULL}, gl ##name}
+static const extfunc_desc_t extfuncs[] = {
+  DEF_FUNC_DESC(GenTextures),
+
+  {&mpglBindTexture, NULL, {"glBindTexture", "glBindTextureARB", "glBindTextureEXT", NULL}},
+  {&mpglXBindTexImage, "GLX_EXT_texture_from_pixmap", {"glXBindTexImageEXT", NULL}},
+  {&mpglXReleaseTexImage, "GLX_EXT_texture_from_pixmap", {"glXReleaseTexImageEXT", NULL}},
+  {&mpglXCreatePixmap, "GLX_EXT_texture_from_pixmap", {"glXCreatePixmap", NULL}},
+  {&mpglXDestroyPixmap, "GLX_EXT_texture_from_pixmap", {"glXDestroyPixmap", NULL}},
+  {&mpglGenPrograms, "_program", {"glGenProgramsARB", NULL}},
+  {NULL}
+};
+
+typedef struct {
+  video_driver_class_t driver_class;
+
+  config_values_t     *config;
+  xine_t              *xine;
+} vaapi_class_t;
+
+static int gl_visual_attr[] = {
+  GLX_RGBA,
+  GLX_RED_SIZE, 1,
+  GLX_GREEN_SIZE, 1,
+  GLX_BLUE_SIZE, 1,
+  GLX_DOUBLEBUFFER,
+  GL_NONE
+};
+
+static void delay_usec(unsigned int usec)
+{
+    int was_error;
+
+#if defined(USE_NANOSLEEP)
+    struct timespec elapsed, tv;
+#elif defined(USE_COND_TIMEDWAIT)
+    // Use a local mutex and cv, so threads remain independent
+    pthread_cond_t delay_cond = PTHREAD_COND_INITIALIZER;
+    pthread_mutex_t delay_mutex = PTHREAD_MUTEX_INITIALIZER;
+    struct timespec elapsed;
+    uint64_t future;
+#else
+    struct timeval tv;
+#ifndef SELECT_SETS_REMAINING
+    uint64_t then, now, elapsed;
+#endif
+#endif
+
+    // Set the timeout interval - Linux only needs to do this once
+#if defined(SELECT_SETS_REMAINING)
+    tv.tv_sec = 0;
+    tv.tv_usec = usec;
+#elif defined(USE_NANOSLEEP)
+    elapsed.tv_sec = 0;
+    elapsed.tv_nsec = usec * 1000;
+#elif defined(USE_COND_TIMEDWAIT)
+    future = get_ticks_usec() + usec;
+    elapsed.tv_sec = future / 1000000;
+    elapsed.tv_nsec = (future % 1000000) * 1000;
+#else
+    then = get_ticks_usec();
+#endif
+
+    do {
+        errno = 0;
+#if defined(USE_NANOSLEEP)
+        tv.tv_sec = elapsed.tv_sec;
+        tv.tv_nsec = elapsed.tv_nsec;
+        was_error = nanosleep(&tv, &elapsed);
+#elif defined(USE_COND_TIMEDWAIT)
+        was_error = pthread_mutex_lock(&delay_mutex);
+        was_error = pthread_cond_timedwait(&delay_cond, &delay_mutex, &elapsed);
+        was_error = pthread_mutex_unlock(&delay_mutex);
+#else
+#ifndef SELECT_SETS_REMAINING
+        // Calculate the time interval left (in case of interrupt)
+        now = get_ticks_usec();
+        elapsed = now - then;
+        then = now;
+        if (elapsed >= usec)
+            break;
+        usec -= elapsed;
+        tv.tv_sec = 0;
+        tv.tv_usec = usec;
+#endif
+        was_error = select(0, NULL, NULL, NULL, &tv);
+#endif
+    } while (was_error && (errno == EINTR));
+}
+
+static void vaapi_x11_wait_event(Display *dpy, Window w, int type)
+{
+  XEvent e;
+  while (!XCheckTypedWindowEvent(dpy, w, type, &e))
+    delay_usec(10);
+}
+
+/* X11 Error handler and error functions */
+static int vaapi_x11_error_code = 0;
+static int (*vaapi_x11_old_error_handler)(Display *, XErrorEvent *);
+
+static int vaapi_x11_error_handler(Display *dpy, XErrorEvent *error)
+{
+    vaapi_x11_error_code = error->error_code;
+    return 0;
+}
+
+static void vaapi_x11_trap_errors(void)
+{
+    vaapi_x11_error_code    = 0;
+    vaapi_x11_old_error_handler = XSetErrorHandler(vaapi_x11_error_handler);
+}
+
+static int vaapi_x11_untrap_errors(void)
+{
+    XSetErrorHandler(vaapi_x11_old_error_handler);
+    return vaapi_x11_error_code;
+}
+
+static void vaapi_appendstr(char **dst, const char *str)
+{
+    int newsize;
+    char *newstr;
+    if (!str)
+        return;
+    newsize = strlen(*dst) + 1 + strlen(str) + 1;
+    newstr = realloc(*dst, newsize);
+    if (!newstr)
+        return;
+    *dst = newstr;
+    strcat(*dst, " ");
+    strcat(*dst, str);
+}
+
+/* Return the address of a linked function */
+static void *vaapi_getdladdr (const char *s) {
+  void *ret = NULL;
+  void *handle = dlopen(NULL, RTLD_LAZY);
+  if (!handle)
+    return NULL;
+  ret = dlsym(handle, s);
+  dlclose(handle);
+
+  return ret;
+}
+
+/* Resolve opengl functions. */
+static void vaapi_get_functions(vo_driver_t *this_gen, void *(*getProcAddress)(const GLubyte *),
+                         const char *ext2) {
+  const extfunc_desc_t *dsc;
+  const char *extensions;
+  char *allexts;
+
+  if (!getProcAddress)
+    getProcAddress = (void *)vaapi_getdladdr;
+
+  /* special case, we need glGetString before starting to find the other functions */
+  mpglGetString = getProcAddress("glGetString");
+  if (!mpglGetString)
+      mpglGetString = glGetString;
+
+  extensions = (const char *)mpglGetString(GL_EXTENSIONS);
+  if (!extensions) extensions = "";
+  if (!ext2) ext2 = "";
+  allexts = malloc(strlen(extensions) + strlen(ext2) + 2);
+  strcpy(allexts, extensions);
+  strcat(allexts, " ");
+  strcat(allexts, ext2);
+  lprintf("vaapi_get_functions: OpenGL extensions string:\n%s\n", allexts);
+  for (dsc = extfuncs; dsc->funcptr; dsc++) {
+    void *ptr = NULL;
+    int i;
+    if (!dsc->extstr || strstr(allexts, dsc->extstr)) {
+      for (i = 0; !ptr && dsc->funcnames[i]; i++)
+        ptr = getProcAddress((const GLubyte *)dsc->funcnames[i]);
+    }
+    if (!ptr)
+        ptr = dsc->fallback;
+    *(void **)dsc->funcptr = ptr;
+  }
+  lprintf("\n");
+  free(allexts);
+}
+
+/* Check if opengl indirect/software rendering is used */
+static int vaapi_opengl_verify_direct (x11_visual_t *vis) {
+  Window        root, win;
+  XVisualInfo  *visinfo;
+  GLXContext    ctx;
+  XSetWindowAttributes xattr;
+  int           ret = 0;
+
+  if (!vis || !vis->display || ! (root = RootWindow (vis->display, vis->screen))) {
+    lprintf ("vaapi_opengl_verify_direct: Don't have a root window to verify\n");
+    return 0;
+  }
+
+  if (! (visinfo = glXChooseVisual (vis->display, vis->screen, gl_visual_attr)))
+    return 0;
+
+  if (! (ctx = glXCreateContext (vis->display, visinfo, NULL, 1)))
+    return 0;
+
+  memset (&xattr, 0, sizeof (xattr));
+  xattr.colormap = XCreateColormap(vis->display, root, visinfo->visual, AllocNone);
+  xattr.event_mask = StructureNotifyMask | ExposureMask;
+
+  if ( (win = XCreateWindow (vis->display, root, 0, 0, 1, 1, 0, visinfo->depth,
+                       InputOutput, visinfo->visual,
+                       CWBackPixel | CWBorderPixel | CWColormap | CWEventMask,
+                       &xattr))) {
+    if (glXMakeCurrent (vis->display, win, ctx)) {
+    const char *renderer = (const char *) glGetString(GL_RENDERER);
+    if (glXIsDirect (vis->display, ctx) &&
+                ! strstr (renderer, "Software") &&
+                ! strstr (renderer, "Indirect"))
+      ret = 1;
+      glXMakeCurrent (vis->display, None, NULL);
+      }
+      XDestroyWindow (vis->display, win);
+  }
+  glXDestroyContext (vis->display, ctx);
+  XFreeColormap     (vis->display, xattr.colormap);
+
+  return ret;
+}
+
+static int vaapi_glx_bind_texture(vo_driver_t *this_gen)
+{
+  vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
+
+  glEnable(GL_TEXTURE_2D);
+  mpglBindTexture(GL_TEXTURE_2D, this->gl_texture);
+
+  if (this->opengl_use_tfp) {
+    vaapi_x11_trap_errors();
+    mpglXBindTexImage(this->display, this->gl_pixmap, GLX_FRONT_LEFT_EXT, NULL);
+    XSync(this->display, False);
+    if (vaapi_x11_untrap_errors())
+      xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_bind_texture : Update bind_tex_image failed\n");
+  }
+
+  return 0;
+}
+
+static int vaapi_glx_unbind_texture(vo_driver_t *this_gen)
+{
+  vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
+
+  if (this->opengl_use_tfp) {
+    vaapi_x11_trap_errors();
+    mpglXReleaseTexImage(this->display, this->gl_pixmap, GLX_FRONT_LEFT_EXT);
+    if (vaapi_x11_untrap_errors())
+      xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_unbind_texture : Failed to release?\n");
+  }
+
+  mpglBindTexture(GL_TEXTURE_2D, 0);
+  glDisable(GL_TEXTURE_2D);
+  return 0;
+}
+
+static void vaapi_glx_render_frame(vo_frame_t *frame_gen, int left, int top, int right, int bottom)
+{
+  vaapi_driver_t        *this = (vaapi_driver_t *) frame_gen->driver;
+  vaapi_frame_t         *frame = (vaapi_frame_t *) frame_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+  int             x1, x2, y1, y2;
+  float           tx, ty;
+
+  if (vaapi_glx_bind_texture(frame_gen->driver) < 0)
+    return;
+
+  /* Calc texture/rectangle coords */
+  x1 = this->sc.output_xoffset;
+  y1 = this->sc.output_yoffset;
+  x2 = x1 + this->sc.output_width;
+  y2 = y1 + this->sc.output_height;
+  tx = (float) frame->width  / va_context->width;
+  ty = (float) frame->height / va_context->height;
+
+  glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+  /* Draw quad */
+  glBegin (GL_QUADS);
+
+    glTexCoord2f (tx, ty);   glVertex2i (x2, y2);
+    glTexCoord2f (0,  ty);   glVertex2i (x1, y2);
+    glTexCoord2f (0,  0);    glVertex2i (x1, y1);
+    glTexCoord2f (tx, 0);    glVertex2i (x2, y1);
+    lprintf("render_frame left %d top %d right %d bottom %d\n", x1, y1, x2, y2);
+
+  glEnd ();
+
+  if (vaapi_glx_unbind_texture(frame_gen->driver) < 0)
+    return;
+}
+
+static void vaapi_glx_flip_page(vo_frame_t *frame_gen, int left, int top, int right, int bottom)
+{
+  vaapi_driver_t *this = (vaapi_driver_t *) frame_gen->driver;
+
+  glClear(GL_COLOR_BUFFER_BIT);
+
+  vaapi_glx_render_frame(frame_gen, left, top, right, bottom);
+
+  //if (gl_finish)
+  //  glFinish();
+
+  glXSwapBuffers(this->display, this->window);
+
+}
+
+static void destroy_glx(vo_driver_t *this_gen)
+{
+  vaapi_driver_t        *this       = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+
+  if(!this->opengl_render || !va_context->valid_context)
+    return;
+
+  //if (gl_finish)
+  //  glFinish();
+
+  if(va_context->gl_surface) {
+    VAStatus vaStatus = vaDestroySurfaceGLX(va_context->va_display, va_context->gl_surface);
+    vaapi_check_status(this_gen, vaStatus, "vaDestroySurfaceGLX()");
+    va_context->gl_surface = NULL;
+  }
+
+  if(this->gl_context)
+    glXMakeCurrent(this->display, None, NULL);
+
+  if(this->gl_pixmap) {
+    vaapi_x11_trap_errors();
+    mpglXDestroyPixmap(this->display, this->gl_pixmap);
+    XSync(this->display, False);
+    vaapi_x11_untrap_errors();
+    this->gl_pixmap = None;
+  }
+
+  if(this->gl_image_pixmap) {
+    XFreePixmap(this->display, this->gl_image_pixmap);
+    this->gl_image_pixmap = None;
+  }
+
+  if(this->gl_texture) {
+    glDeleteTextures(1, &this->gl_texture);
+    this->gl_texture = GL_NONE;
+  }
+
+  if(this->gl_context) {
+    glXDestroyContext(this->display, this->gl_context);
+    this->gl_context = 0;
+  }
+
+  if(this->gl_vinfo) {
+    XFree(this->gl_vinfo);
+    this->gl_vinfo = NULL;
+  }
+
+  this->valid_opengl_context = 0;
+}
+
+static GLXFBConfig *get_fbconfig_for_depth(vo_driver_t *this_gen, int depth)
+{
+  vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
+
+    GLXFBConfig *fbconfigs, *ret = NULL;
+    int          n_elements, i, found;
+    int          db, stencil, alpha, rgba, value;
+
+    static GLXFBConfig *cached_config = NULL;
+    static int          have_cached_config = 0;
+
+    if (have_cached_config)
+        return cached_config;
+
+    fbconfigs = glXGetFBConfigs(this->display, this->screen, &n_elements);
+
+    db      = SHRT_MAX;
+    stencil = SHRT_MAX;
+    rgba    = 0;
+
+    found = n_elements;
+
+    for (i = 0; i < n_elements; i++) {
+        XVisualInfo *vi;
+        int          visual_depth;
+
+        vi = glXGetVisualFromFBConfig(this->display, fbconfigs[i]);
+        if (!vi)
+            continue;
+
+        visual_depth = vi->depth;
+        XFree(vi);
+
+        if (visual_depth != depth)
+            continue;
+
+        glXGetFBConfigAttrib(this->display, fbconfigs[i], GLX_ALPHA_SIZE, &alpha);
+        glXGetFBConfigAttrib(this->display, fbconfigs[i], GLX_BUFFER_SIZE, &value);
+        if (value != depth && (value - alpha) != depth)
+            continue;
+
+        value = 0;
+        if (depth == 32) {
+            glXGetFBConfigAttrib(this->display, fbconfigs[i],
+                                 GLX_BIND_TO_TEXTURE_RGBA_EXT, &value);
+            if (value)
+                rgba = 1;
+        }
+
+        if (!value) {
+            if (rgba)
+                continue;
+
+            glXGetFBConfigAttrib(this->display, fbconfigs[i],
+                                 GLX_BIND_TO_TEXTURE_RGB_EXT, &value);
+            if (!value)
+                continue;
+        }
+
+        glXGetFBConfigAttrib(this->display, fbconfigs[i], GLX_DOUBLEBUFFER, &value);
+        if (value > db)
+            continue;
+        db = value;
+
+        glXGetFBConfigAttrib(this->display, fbconfigs[i], GLX_STENCIL_SIZE, &value);
+        if (value > stencil)
+            continue;
+        stencil = value;
+
+        found = i;
+    }
+
+    if (found != n_elements) {
+        ret = malloc(sizeof(*ret));
+        *ret = fbconfigs[found];
+    }
+
+    if (n_elements)
+        XFree(fbconfigs);
+
+    have_cached_config = 1;
+    cached_config = ret;
+    return ret;
+}
+
+static int vaapi_glx_config_tfp(vo_driver_t *this_gen, unsigned int width, unsigned int height)
+{
+  vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
+
+  GLXFBConfig *fbconfig;
+  int attribs[7], i = 0;
+  const int depth = 24;
+
+  if (!mpglXBindTexImage || !mpglXReleaseTexImage) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_tfp : No GLX texture-from-pixmap extension available\n");
+    return 0;
+  }
+
+  if (depth != 24 && depth != 32) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_tfp : color depth wrong.\n");
+    return 0;
+  }
+
+  this->gl_image_pixmap = XCreatePixmap(this->display, this->window, width, height, depth);
+  if (!this->gl_image_pixmap) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_tfp : Could not create X11 pixmap\n");
+    return 0;
+  }
+
+  fbconfig = get_fbconfig_for_depth(this_gen, depth);
+  if (!fbconfig) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_tfp : Could not find an FBConfig for 32-bit pixmap\n");
+    return 0;
+  }
+
+  attribs[i++] = GLX_TEXTURE_TARGET_EXT;
+  attribs[i++] = GLX_TEXTURE_2D_EXT;
+  attribs[i++] = GLX_TEXTURE_FORMAT_EXT;
+  if (depth == 24)
+    attribs[i++] = GLX_TEXTURE_FORMAT_RGB_EXT;
+  else if (depth == 32)
+    attribs[i++] = GLX_TEXTURE_FORMAT_RGBA_EXT;
+  attribs[i++] = GLX_MIPMAP_TEXTURE_EXT;
+  attribs[i++] = GL_FALSE;
+  attribs[i++] = None;
+
+  vaapi_x11_trap_errors();
+  this->gl_pixmap = mpglXCreatePixmap(this->display, *fbconfig, this->gl_image_pixmap, attribs);
+  XSync(this->display, False);
+  if (vaapi_x11_untrap_errors()) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_tfp : Could not create GLX pixmap\n");
+    return 0;
+  }
+
+  return 1;
+}
+
+static int vaapi_glx_config_glx(vo_driver_t *this_gen, unsigned int width, unsigned int height)
+{
+  vaapi_driver_t        *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+
+  this->gl_vinfo = glXChooseVisual(this->display, this->screen, gl_visual_attr);
+  if(!this->gl_vinfo) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_glx : error glXChooseVisual\n");
+    this->opengl_render = 0;
+  }
+
+  glXMakeCurrent(this->display, None, NULL);
+  this->gl_context = glXCreateContext (this->display, this->gl_vinfo, NULL, True);
+  if (this->gl_context) {
+    if(!glXMakeCurrent (this->display, this->window, this->gl_context)) {
+      xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_glx : error glXMakeCurrent\n");
+      goto error;
+    }
+  } else {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_glx : error glXCreateContext\n");
+    goto error;
+  }
+
+  void *(*getProcAddress)(const GLubyte *);
+  const char *(*glXExtStr)(Display *, int);
+  char *glxstr = strdup(" ");
+
+  getProcAddress = vaapi_getdladdr("glXGetProcAddress");
+  if (!getProcAddress)
+    getProcAddress = vaapi_getdladdr("glXGetProcAddressARB");
+  glXExtStr = vaapi_getdladdr("glXQueryExtensionsString");
+  if (glXExtStr)
+      vaapi_appendstr(&glxstr, glXExtStr(this->display, this->screen));
+  glXExtStr = vaapi_getdladdr("glXGetClientString");
+  if (glXExtStr)
+      vaapi_appendstr(&glxstr, glXExtStr(this->display, GLX_EXTENSIONS));
+  glXExtStr = vaapi_getdladdr("glXGetServerString");
+  if (glXExtStr)
+      vaapi_appendstr(&glxstr, glXExtStr(this->display, GLX_EXTENSIONS));
+
+  vaapi_get_functions(this_gen, getProcAddress, glxstr);
+  if (!mpglGenPrograms && mpglGetString &&
+      getProcAddress &&
+      strstr(mpglGetString(GL_EXTENSIONS), "GL_ARB_vertex_program")) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_glx : Broken glXGetProcAddress detected, trying workaround\n");
+    vaapi_get_functions(this_gen, NULL, glxstr);
+  }
+  free(glxstr);
+
+  glDisable(GL_DEPTH_TEST);
+  glDepthMask(GL_FALSE);
+  glDisable(GL_CULL_FACE);
+  glEnable(GL_TEXTURE_2D);
+  glDrawBuffer(GL_BACK);
+  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+  /* Create TFP resources */
+  if(this->opengl_use_tfp && vaapi_glx_config_tfp(this_gen, width, height)) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_glx : Using GLX texture-from-pixmap extension\n");
+  } else {
+    this->opengl_use_tfp = 0;
+  }
+
+  /* Create OpenGL texture */
+  /* XXX: assume GL_ARB_texture_non_power_of_two is available */
+  glEnable(GL_TEXTURE_2D);
+  glGenTextures(1, &this->gl_texture);
+  mpglBindTexture(GL_TEXTURE_2D, this->gl_texture);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  if (!this->opengl_use_tfp) {
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
+                 GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+  }
+  mpglBindTexture(GL_TEXTURE_2D, 0);
+  glDisable(GL_TEXTURE_2D);
+
+  glClearColor(0.0, 0.0, 0.0, 1.0);
+  glClear(GL_COLOR_BUFFER_BIT);
+
+  if(!this->gl_texture) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_glx : gl_texture NULL\n");
+    goto error;
+  }
+
+  if(!this->opengl_use_tfp) {
+    VAStatus vaStatus = vaCreateSurfaceGLX(va_context->va_display, GL_TEXTURE_2D, this->gl_texture, &va_context->gl_surface);
+    if(!vaapi_check_status(this_gen, vaStatus, "vaCreateSurfaceGLX()")) {
+      va_context->gl_surface = NULL;
+      goto error;
+    }
+  } else {
+    va_context->gl_surface = NULL;
+  }
+
+  lprintf("vaapi_glx_config_glx : GL setup done\n");
+
+  this->valid_opengl_context = 1;
+  return 1;
+
+error:
+  destroy_glx(this_gen);
+  this->valid_opengl_context = 0;
+  return 0;
+}
+
+static uint32_t vaapi_get_capabilities (vo_driver_t *this_gen) {
+  vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
+
+  return this->capabilities;
+}
+
+static const struct {
+  int fmt;
+  enum PixelFormat pix_fmt;
+  enum CodecID codec_id;
+} conversion_map[] = {
+  {IMGFMT_VAAPI_MPEG2,     PIX_FMT_VAAPI_VLD,  CODEC_ID_MPEG2VIDEO},
+  {IMGFMT_VAAPI_MPEG2_IDCT,PIX_FMT_VAAPI_IDCT, CODEC_ID_MPEG2VIDEO},
+  {IMGFMT_VAAPI_MPEG2_MOCO,PIX_FMT_VAAPI_MOCO, CODEC_ID_MPEG2VIDEO},
+  {IMGFMT_VAAPI_MPEG4,     PIX_FMT_VAAPI_VLD,  CODEC_ID_MPEG4},
+  {IMGFMT_VAAPI_H263,      PIX_FMT_VAAPI_VLD,  CODEC_ID_H263},
+  {IMGFMT_VAAPI_H264,      PIX_FMT_VAAPI_VLD,  CODEC_ID_H264},
+  {IMGFMT_VAAPI_WMV3,      PIX_FMT_VAAPI_VLD,  CODEC_ID_WMV3},
+  {IMGFMT_VAAPI_VC1,       PIX_FMT_VAAPI_VLD,  CODEC_ID_VC1},
+  {0, PIX_FMT_NONE}
+};
+
+static int vaapi_pixfmt2imgfmt(enum PixelFormat pix_fmt, int codec_id)
+{
+  int i;
+  int fmt;
+  for (i = 0; conversion_map[i].pix_fmt != PIX_FMT_NONE; i++) {
+    if (conversion_map[i].pix_fmt == pix_fmt &&
+        (conversion_map[i].codec_id == 0 ||
+        conversion_map[i].codec_id == codec_id)) {
+      break;
+    }
+  }
+  fmt = conversion_map[i].fmt;
+  return fmt;
+}
+
+static int vaapi_has_profile(VAProfile *va_profiles, int va_num_profiles, VAProfile profile)
+{
+  if (va_profiles && va_num_profiles > 0) {
+    int i;
+    for (i = 0; i < va_num_profiles; i++) {
+      if (va_profiles[i] == profile)
+        return 1;
+      }
+  }
+  return 0;
+}
+
+static int profile_from_imgfmt(vo_frame_t *frame_gen, enum PixelFormat pix_fmt, int codec_id, int vaapi_mpeg_sofdec)
+{
+  vo_driver_t         *this_gen   = (vo_driver_t *) frame_gen->driver;
+  vaapi_driver_t      *this       = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  VAStatus            vaStatus;
+  int                 profile     = -1;
+  int                 maj, min;
+  int                 i;
+  int                 va_num_profiles;
+  int                 max_profiles;
+  VAProfile           *va_profiles = NULL;
+  int                 inited = 0;
+
+  if(va_context->va_display == NULL) {
+    lprintf("profile_from_imgfmt vaInitialize\n");
+    inited = 1;
+    va_context->va_display = vaapi_get_display(this->display, this->opengl_render);
+    if(!va_context->va_display)
+      goto out;
+
+    vaStatus = vaInitialize(va_context->va_display, &maj, &min);
+    if(!vaapi_check_status(this_gen, vaStatus, "vaInitialize()"))
+      goto out;
+
+  }
+
+  max_profiles = vaMaxNumProfiles(va_context->va_display);
+  va_profiles = calloc(max_profiles, sizeof(*va_profiles));
+  if (!va_profiles)
+    goto out;
+
+  vaStatus = vaQueryConfigProfiles(va_context->va_display, va_profiles, &va_num_profiles);
+  if(!vaapi_check_status(this_gen, vaStatus, "vaQueryConfigProfiles()"))
+    goto out;
+
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " VAAPI Supported Profiles : ");
+  for (i = 0; i < va_num_profiles; i++) {
+    printf("%s ", vaapi_profile_to_string(va_profiles[i]));
+  }
+  printf("\n");
+
+  uint32_t format = vaapi_pixfmt2imgfmt(pix_fmt, codec_id);
+
+  static const int mpeg2_profiles[] = { VAProfileMPEG2Main, VAProfileMPEG2Simple, -1 };
+  static const int mpeg4_profiles[] = { VAProfileMPEG4Main, VAProfileMPEG4AdvancedSimple, VAProfileMPEG4Simple, -1 };
+  static const int h264_profiles[]  = { VAProfileH264High, VAProfileH264Main, VAProfileH264Baseline, -1 };
+  static const int wmv3_profiles[]  = { VAProfileVC1Main, VAProfileVC1Simple, -1 };
+  static const int vc1_profiles[]   = { VAProfileVC1Advanced, -1 };
+
+  const int *profiles = NULL;
+  switch (IMGFMT_VAAPI_CODEC(format))
+  {
+    case IMGFMT_VAAPI_CODEC_MPEG2:
+      if(!vaapi_mpeg_sofdec) {
+        profiles = mpeg2_profiles;
+      }
+      break;
+    case IMGFMT_VAAPI_CODEC_MPEG4:
+      profiles = mpeg4_profiles;
+      break;
+    case IMGFMT_VAAPI_CODEC_H264:
+      profiles = h264_profiles;
+      break;
+    case IMGFMT_VAAPI_CODEC_VC1:
+      switch (format) {
+        case IMGFMT_VAAPI_WMV3:
+          profiles = wmv3_profiles;
+          break;
+        case IMGFMT_VAAPI_VC1:
+            profiles = vc1_profiles;
+            break;
+      }
+      break;
+  }
+
+  if (profiles) {
+    int i;
+    for (i = 0; profiles[i] != -1; i++) {
+      if (vaapi_has_profile(va_profiles, va_num_profiles, profiles[i])) {
+        profile = profiles[i];
+        xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " VAAPI Profile %s supported by your hardware\n", vaapi_profile_to_string(profiles[i]));
+        break;
+      }
+    }
+  }
+
+out:
+  if(va_profiles)
+    free(va_profiles);
+  if(inited) {
+    vaStatus = vaTerminate(va_context->va_display);
+    vaapi_check_status(this_gen, vaStatus, "vaTerminate()");
+  }
+  return profile;
+}
+
+
+static const char *vaapi_profile_to_string(VAProfile profile)
+{
+  switch(profile) {
+#define PROFILE(profile) \
+    case VAProfile##profile: return "VAProfile" #profile
+      PROFILE(MPEG2Simple);
+      PROFILE(MPEG2Main);
+      PROFILE(MPEG4Simple);
+      PROFILE(MPEG4AdvancedSimple);
+      PROFILE(MPEG4Main);
+      PROFILE(H264Baseline);
+      PROFILE(H264Main);
+      PROFILE(H264High);
+      PROFILE(VC1Simple);
+      PROFILE(VC1Main);
+      PROFILE(VC1Advanced);
+#undef PROFILE
+    default: break;
+  }
+  return "<unknown>";
+}
+
+static const char *vaapi_entrypoint_to_string(VAEntrypoint entrypoint)
+{
+  switch(entrypoint)
+  {
+#define ENTRYPOINT(entrypoint) \
+    case VAEntrypoint##entrypoint: return "VAEntrypoint" #entrypoint
+      ENTRYPOINT(VLD);
+      ENTRYPOINT(IZZ);
+      ENTRYPOINT(IDCT);
+      ENTRYPOINT(MoComp);
+      ENTRYPOINT(Deblocking);
+#undef ENTRYPOINT
+    default: break;
+  }
+  return "<unknown>";
+}
+
+/* Init subpicture */
+static void vaapi_init_subpicture(vaapi_driver_t *this_gen) {
+  vaapi_driver_t        *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+
+  va_context->va_subpic_width               = 0;
+  va_context->va_subpic_height              = 0;
+  va_context->va_subpic_id                  = VA_INVALID_ID;
+  va_context->va_subpic_image.image_id      = VA_INVALID_ID;
+
+  this->overlay_output_width = this->overlay_output_height = 0;
+  this->overlay_unscaled_width = this->overlay_unscaled_height = 0;
+  this->ovl_changed = 0;
+  this->has_overlay = 0;
+  this->overlay_bitmap = NULL;
+  this->overlay_bitmap_size = 0;
+
+}
+
+/* Init vaapi context */
+static void vaapi_init_va_context(vaapi_driver_t *this_gen) {
+  vaapi_driver_t        *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+  int i;
+
+  va_context->va_config_id              = VA_INVALID_ID;
+  va_context->va_context_id             = VA_INVALID_ID;
+  va_context->va_profile                = 0;
+  va_context->va_colorspace             = 1;
+  va_context->is_bound                  = 0;
+  va_context->gl_surface                = NULL;
+  va_context->soft_head                 = 0;
+  va_context->valid_context             = 0;
+  va_context->va_head                   = 0;
+  va_context->va_soft_head              = 0;
+
+  for(i = 0; i < RENDER_SURFACES; i++) {
+    ff_vaapi_surface_t *va_surface      = &va_render_surfaces[i];
+
+    va_surface->index                   = i;
+    va_surface->status                  = SURFACE_FREE;
+    va_surface->va_surface_id           = VA_INVALID_SURFACE;
+
+    va_surface_ids[i]                   = VA_INVALID_SURFACE;
+  }
+
+  for(i = 0; i < SOFT_SURFACES; i++) {
+    va_soft_surface_ids[i]              = VA_INVALID_SURFACE;
+    va_soft_images[i].image_id          = VA_INVALID_ID;
+  }
+
+  va_context->va_image_formats      = NULL;
+  va_context->va_num_image_formats  = 0;
+
+  va_context->va_subpic_formats     = NULL;
+  va_context->va_num_subpic_formats = 0;
+}
+
+/* Close vaapi  */
+static void vaapi_close(vo_driver_t *this_gen) {
+  vaapi_driver_t        *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+  VAStatus              vaStatus;
+
+  if(!va_context || !va_context->va_display || !va_context->valid_context)
+    return;
+
+  vaapi_ovl_associate(this_gen, 0, 0);
+  destroy_glx((vo_driver_t *)this);
+
+  vaapi_destroy_subpicture(this_gen);
+
+  vaapi_destroy_soft_surfaces(this_gen);
+
+  vaapi_destroy_render_surfaces(this_gen);
+
+  if(va_context->va_config_id != VA_INVALID_ID) {
+    vaStatus = vaDestroyConfig(va_context->va_display, va_context->va_config_id);
+    vaapi_check_status(this_gen, vaStatus, "vaDestroyConfig()");
+    va_context->va_config_id = VA_INVALID_ID;
+  }
+
+  if(va_context->va_context_id != VA_INVALID_ID) {
+    vaStatus = vaDestroyContext(va_context->va_display, va_context->va_context_id);
+    vaapi_check_status(this_gen, vaStatus, "vaDestroyContext()");
+    va_context->va_context_id = VA_INVALID_ID;
+  }
+  
+  vaStatus = vaTerminate(va_context->va_display);
+  vaapi_check_status(this_gen, vaStatus, "vaTerminate()");
+  va_context->va_display = NULL;
+
+  if(va_context->va_image_formats) {
+    free(va_context->va_image_formats);
+    va_context->va_image_formats      = NULL;
+    va_context->va_num_image_formats  = 0;
+  }
+  if(va_context->va_subpic_formats) {
+    free(va_context->va_subpic_formats);
+    va_context->va_subpic_formats     = NULL;
+    va_context->va_num_subpic_formats = 0;
+  }
+
+  va_context->valid_context = 0;
+}
+
+/* Returns internal VAAPI context */
+static ff_vaapi_context_t *get_context(vo_frame_t *frame_gen) {
+  vaapi_driver_t        *this = (vaapi_driver_t *) frame_gen->driver;
+
+  return this->va_context;
+}
+
+/* Free allocated VAAPI image */
+static void vaapi_destroy_image(vo_driver_t *this_gen, VAImage *va_image) {
+  vaapi_driver_t        *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+  VAStatus              vaStatus;
+
+  if(va_image->image_id != VA_INVALID_ID) {
+    lprintf("vaapi_destroy_image 0x%08x\n", va_image->image_id);
+    vaStatus = vaDestroyImage(va_context->va_display, va_image->image_id);
+    vaapi_check_status(this_gen, vaStatus, "vaDestroyImage()");
+  }
+  va_image->image_id      = VA_INVALID_ID;
+  va_image->width         = 0;
+  va_image->height        = 0;
+}
+
+/* Allocated VAAPI image */
+static VAStatus vaapi_create_image(vo_driver_t *this_gen, VASurfaceID va_surface_id, VAImage *va_image, int width, int height, int clear) {
+  vaapi_driver_t        *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+
+  int i = 0;
+  VAStatus vaStatus;
+
+  if(!va_context->valid_context || va_context->va_image_formats == NULL || va_context->va_num_image_formats == 0)
+    return VA_STATUS_ERROR_UNKNOWN;
+
+  va_context->is_bound = 0;
+
+  vaStatus = vaDeriveImage(va_context->va_display, va_surface_id, va_image);
+  if(vaStatus == VA_STATUS_SUCCESS) {
+    if (va_image->image_id != VA_INVALID_ID && va_image->buf != VA_INVALID_ID) {
+      va_context->is_bound = 1;
+    }
+  }
+
+  if(!va_context->is_bound) {
+    for (i = 0; i < va_context->va_num_image_formats; i++) {
+      if (va_context->va_image_formats[i].fourcc == VA_FOURCC( 'Y', 'V', '1', '2' ) ||
+          va_context->va_image_formats[i].fourcc == VA_FOURCC( 'I', '4', '2', '0' ) /*||
+          va_context->va_image_formats[i].fourcc == VA_FOURCC( 'N', 'V', '1', '2' ) */) {
+        vaStatus = vaCreateImage( va_context->va_display, &va_context->va_image_formats[i], width, height, va_image );
+        if(!vaapi_check_status(this_gen, vaStatus, "vaCreateImage()"))
+          goto error;
+        break;
+      }
+    }
+  }
+
+  void *p_base = NULL;
+
+  vaStatus = vaMapBuffer( va_context->va_display, va_image->buf, &p_base );
+  if(!vaapi_check_status(this_gen, vaStatus, "vaMapBuffer()"))
+    goto error;
+
+  if(clear) {
+    if(va_image->format.fourcc == VA_FOURCC( 'Y', 'V', '1', '2' ) ||
+       va_image->format.fourcc == VA_FOURCC( 'I', '4', '2', '0' )) {
+      memset((uint8_t*)p_base + va_image->offsets[0],   0, va_image->pitches[0] * va_image->height);
+      memset((uint8_t*)p_base + va_image->offsets[1], 128, va_image->pitches[1] * (va_image->height/2));
+      memset((uint8_t*)p_base + va_image->offsets[2], 128, va_image->pitches[2] * (va_image->height/2));
+    } else if (va_image->format.fourcc == VA_FOURCC( 'N', 'V', '1', '2' ) ) {
+      memset((uint8_t*)p_base + va_image->offsets[0],   0, va_image->pitches[0] * va_image->height);
+      memset((uint8_t*)p_base + va_image->offsets[1], 128, va_image->pitches[1] * (va_image->height/2));
+    }
+  }
+
+  vaStatus = vaUnmapBuffer( va_context->va_display, va_image->buf );
+  vaapi_check_status(this_gen, vaStatus, "vaUnmapBuffer()");
+
+  lprintf("vaapi_create_image 0x%08x width %d height %d format %s\n", va_image->image_id, va_image->width, va_image->height,
+      string_of_VAImageFormat(&va_image->format));
+
+  return VA_STATUS_SUCCESS;
+
+error:
+  /* house keeping */
+  vaapi_destroy_image(this_gen, va_image);
+  return VA_STATUS_ERROR_UNKNOWN;
+}
+
+/* Deassociate and free subpicture */
+static void vaapi_destroy_subpicture(vo_driver_t *this_gen) {
+  vaapi_driver_t        *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+  VAStatus              vaStatus;
+
+  lprintf("destroy sub 0x%08x 0x%08x 0x%08x\n", va_context->va_subpic_id,
+      va_context->va_subpic_image.image_id, va_context->va_subpic_image.buf);
+
+  if(va_context->va_subpic_id != VA_INVALID_ID) {
+    vaStatus = vaDestroySubpicture(va_context->va_display, va_context->va_subpic_id);
+    vaapi_check_status(this_gen, vaStatus, "vaDeassociateSubpicture()");
+  }
+  va_context->va_subpic_id = VA_INVALID_ID;
+
+  vaapi_destroy_image(this_gen, &va_context->va_subpic_image);
+
+}
+
+/* Create VAAPI subpicture */
+static VAStatus vaapi_create_subpicture(vo_driver_t *this_gen, int width, int height) {
+  vaapi_driver_t      *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  VAStatus            vaStatus;
+
+  int i = 0;
+
+  if(!va_context->valid_context || !va_context->va_subpic_formats || va_context->va_num_subpic_formats == 0)
+    return VA_STATUS_ERROR_UNKNOWN;
+
+  for (i = 0; i < va_context->va_num_subpic_formats; i++) {
+    if ( va_context->va_subpic_formats[i].fourcc == VA_FOURCC('B','G','R','A')) {
+
+      vaStatus = vaCreateImage( va_context->va_display, &va_context->va_subpic_formats[i], width, height, &va_context->va_subpic_image );
+      if(!vaapi_check_status(this_gen, vaStatus, "vaCreateImage()"))
+        goto error;
+
+      vaStatus = vaCreateSubpicture(va_context->va_display, va_context->va_subpic_image.image_id, &va_context->va_subpic_id );
+      if(!vaapi_check_status(this_gen, vaStatus, "vaCreateSubpicture()"))
+        goto error;
+    }
+  }
+
+  if(va_context->va_subpic_image.image_id == VA_INVALID_ID || va_context->va_subpic_id == VA_INVALID_ID)
+    goto error;
+
+  void *p_base = NULL;
+
+  lprintf("create sub 0x%08x 0x%08x 0x%08x\n", va_context->va_subpic_id,
+      va_context->va_subpic_image.image_id, va_context->va_subpic_image.buf);
+
+  vaStatus = vaMapBuffer(va_context->va_display, va_context->va_subpic_image.buf, &p_base);
+  if(!vaapi_check_status(this_gen, vaStatus, "vaMapBuffer()"))
+    goto error;
+
+  memset((uint32_t *)p_base, 0x0, va_context->va_subpic_image.data_size);
+  vaStatus = vaUnmapBuffer(va_context->va_display, va_context->va_subpic_image.buf);
+  vaapi_check_status(this_gen, vaStatus, "vaUnmapBuffer()");
+
+  this->overlay_output_width  = width;
+  this->overlay_output_height = height;
+
+  lprintf("vaapi_create_subpicture 0x%08x format %s\n", va_context->va_subpic_image.image_id,
+      string_of_VAImageFormat(&va_context->va_subpic_image.format));
+
+  return VA_STATUS_SUCCESS;
+
+error:
+  /* house keeping */
+  if(va_context->va_subpic_id != VA_INVALID_ID)
+    vaapi_destroy_subpicture(this_gen);
+  va_context->va_subpic_id = VA_INVALID_ID;
+
+  vaapi_destroy_image(this_gen, &va_context->va_subpic_image);
+
+  this->overlay_output_width  = 0;
+  this->overlay_output_height = 0;
+
+  return VA_STATUS_ERROR_UNKNOWN;
+}
+
+static inline int vaapi_get_colorspace_flags(vo_driver_t *this_gen)
+{
+  vaapi_driver_t      *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+
+  if(!va_context)
+    return 0;
+
+  int colorspace = 0;
+#if USE_VAAPI_COLORSPACE
+  switch (va_context->va_colorspace) {
+    case 0:
+      colorspace = ((va_context->sw_width >= 1280 || va_context->sw_height > 576) ?
+               VA_SRC_BT709 : VA_SRC_BT601);
+      break;
+    case 1:
+      colorspace = VA_SRC_BT601;
+      break;
+    case 2:
+      colorspace = VA_SRC_BT709;
+      break;
+    case 3:
+      colorspace = VA_SRC_SMPTE_240;
+      break;
+    default:
+      colorspace = VA_SRC_BT601;
+      break;
+  }
+#endif
+    return colorspace;
+}
+
+static void vaapi_property_callback (void *property_gen, xine_cfg_entry_t *entry) {
+  va_property_t       *property   = (va_property_t *) property_gen;
+  vaapi_driver_t      *this       = property->this;
+  ff_vaapi_context_t  *va_context = this->va_context;
+
+  pthread_mutex_lock(&this->vaapi_lock);
+  XLockDisplay(this->display);
+
+  VADisplayAttribute attr;
+
+  attr.type   = property->type;
+  attr.value  = entry->num_value;
+
+  lprintf("vaapi_property_callback property=%d, value=%d\n", property->type, entry->num_value );
+
+  VAStatus vaStatus = vaSetDisplayAttributes(va_context->va_display, &attr, 1);
+  vaapi_check_status((vo_driver_t *)this, vaStatus, "vaSetDisplayAttributes()");
+
+  vaapi_show_display_props((vo_driver_t*)this);
+
+  XUnlockDisplay(this->display);
+  pthread_mutex_unlock(&this->vaapi_lock);
+}
+
+/* called xlocked */
+static void vaapi_check_capability (vaapi_driver_t *this,
+         int property, VADisplayAttribute attr,
+         const char *config_name,
+         const char *config_desc,
+         const char *config_help) {
+  int int_default = 0;
+  cfg_entry_t *entry;
+
+  this->props[property].type   = attr.type;
+  this->props[property].min    = attr.min_value;
+  this->props[property].max    = attr.max_value;
+  int_default                  = attr.value;
+  this->props[property].atom   = 1;
+
+  if (config_name) {
+    /* is this a boolean property ? */
+    if ((attr.min_value == 0) && (attr.max_value == 1)) {
+      this->config->register_bool (this->config, config_name, int_default,
+           config_desc,
+           config_help, 20, vaapi_property_callback, &this->props[property]);
+
+    } else {
+      this->config->register_range (this->config, config_name, int_default,
+            this->props[property].min, this->props[property].max,
+            config_desc,
+            config_help, 20, vaapi_property_callback, &this->props[property]);
+    }
+
+    entry = this->config->lookup_entry (this->config, config_name);
+    if((entry->num_value < this->props[property].min) ||
+       (entry->num_value > this->props[property].max)) {
+
+      this->config->update_num(this->config, config_name,
+             ((this->props[property].min + this->props[property].max) >> 1));
+
+      entry = this->config->lookup_entry (this->config, config_name);
+    }
+
+    this->props[property].entry = entry;
+
+    vaapi_set_property(&this->vo_driver, property, entry->num_value);
+  } else {
+    this->props[property].value  = int_default;
+  }
+}
+
+static void vaapi_show_display_props(vo_driver_t *this_gen) {
+  /*
+  vaapi_driver_t      *this = (vaapi_driver_t *) this_gen;
+
+  if(this->capabilities & VO_CAP_BRIGHTNESS)
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : brightness     : %d\n", this->props[VO_PROP_BRIGHTNESS].value);
+  if(this->capabilities & VO_CAP_CONTRAST)
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : contrast       : %d\n", this->props[VO_PROP_CONTRAST].value);
+  if(this->capabilities & VO_CAP_HUE)
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : hue            : %d\n", this->props[VO_PROP_HUE].value);
+  if(this->capabilities & VO_CAP_SATURATION)
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : saturation     : %d\n", this->props[VO_PROP_SATURATION].value);
+  */
+}
+
+/* VAAPI display attributes. */
+static void vaapi_display_attribs(vo_driver_t *this_gen) {
+  vaapi_driver_t      *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+
+  int num_display_attrs, max_display_attrs;
+  VAStatus vaStatus;
+  VADisplayAttribute *display_attrs;
+  int i;
+
+  max_display_attrs = vaMaxNumDisplayAttributes(va_context->va_display);
+  display_attrs = calloc(max_display_attrs, sizeof(*display_attrs));
+
+  if (display_attrs) {
+    num_display_attrs = 0;
+    vaStatus = vaQueryDisplayAttributes(va_context->va_display,
+                                        display_attrs, &num_display_attrs);
+    if(vaapi_check_status(this_gen, vaStatus, "vaQueryDisplayAttributes()")) {
+      for (i = 0; i < num_display_attrs; i++) {
+        switch (display_attrs[i].type) {
+          case VADisplayAttribBrightness:
+            if( ( display_attrs[i].flags & VA_DISPLAY_ATTRIB_GETTABLE ) &&
+                ( display_attrs[i].flags & VA_DISPLAY_ATTRIB_SETTABLE ) ) {
+              this->capabilities |= VO_CAP_BRIGHTNESS;
+              vaapi_check_capability(this, VO_PROP_BRIGHTNESS, display_attrs[i], "video.output.vaapi_brightness", "Brightness setting", "Brightness setting");
+            }
+            break;
+          case VADisplayAttribContrast:
+            if( ( display_attrs[i].flags & VA_DISPLAY_ATTRIB_GETTABLE ) &&
+                ( display_attrs[i].flags & VA_DISPLAY_ATTRIB_SETTABLE ) ) {
+              this->capabilities |= VO_CAP_CONTRAST;
+              vaapi_check_capability(this, VO_PROP_CONTRAST, display_attrs[i], "video.output.vaapi_contrast", "Contrast setting", "Contrast setting");
+            }
+            break;
+          case VADisplayAttribHue:
+            if( ( display_attrs[i].flags & VA_DISPLAY_ATTRIB_GETTABLE ) &&
+                ( display_attrs[i].flags & VA_DISPLAY_ATTRIB_SETTABLE ) ) {
+              this->capabilities |= VO_CAP_HUE;
+              vaapi_check_capability(this, VO_PROP_HUE, display_attrs[i], "video.output.vaapi_hue", "Hue setting", "Hue setting");
+            }
+            break;
+          case VADisplayAttribSaturation:
+            if( ( display_attrs[i].flags & VA_DISPLAY_ATTRIB_GETTABLE ) &&
+                ( display_attrs[i].flags & VA_DISPLAY_ATTRIB_SETTABLE ) ) {
+              this->capabilities |= VO_CAP_SATURATION;
+              vaapi_check_capability(this, VO_PROP_SATURATION, display_attrs[i], "video.output.vaapi_saturation", "Saturation setting", "Saturation setting");
+            }
+            break;
+          default:
+            break;
+        }
+      }
+    }
+    free(display_attrs);
+  }
+  vaapi_show_display_props(this_gen);
+}
+
+static void vaapi_set_background_color(vo_driver_t *this_gen) {
+  vaapi_driver_t      *this = (vaapi_driver_t *)this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  VAStatus            vaStatus;
+
+  if(!va_context->valid_context)
+    return;
+
+  VADisplayAttribute attr;
+  memset( &attr, 0, sizeof(attr) );
+
+  attr.type  = VADisplayAttribBackgroundColor;
+  attr.value = 0x000000;
+
+  vaStatus = vaSetDisplayAttributes(va_context->va_display, &attr, 1);
+  vaapi_check_status(this_gen, vaStatus, "vaSetDisplayAttributes()");
+}
+
+static VAStatus vaapi_destroy_render_surfaces(vo_driver_t *this_gen) {
+  vaapi_driver_t      *this = (vaapi_driver_t *)this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  int                 i;
+  VAStatus            vaStatus;
+
+  for(i = 0; i < RENDER_SURFACES; i++) {
+    if(va_surface_ids[i] != VA_INVALID_SURFACE) {
+      vaStatus = vaSyncSurface(va_context->va_display, va_surface_ids[i]);
+      vaapi_check_status(this_gen, vaStatus, "vaSyncSurface()");
+      vaStatus = vaDestroySurfaces(va_context->va_display, &va_surface_ids[i], 1);
+      vaapi_check_status(this_gen, vaStatus, "vaDestroySurfaces()");
+      va_surface_ids[i] = VA_INVALID_SURFACE;
+
+      ff_vaapi_surface_t *va_surface  = &va_render_surfaces[i];
+      va_surface->index               = i;
+      va_surface->status              = SURFACE_FREE;
+      va_surface->va_surface_id       = va_surface_ids[i];
+    }
+  }
+
+  return VA_STATUS_SUCCESS;
+}
+
+static VAStatus vaapi_destroy_soft_surfaces(vo_driver_t *this_gen) {
+  vaapi_driver_t      *this = (vaapi_driver_t *)this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  int                 i;
+  VAStatus            vaStatus;
+
+
+  for(i = 0; i < SOFT_SURFACES; i++) {
+    if(va_soft_images[i].image_id != VA_INVALID_ID)
+      vaapi_destroy_image((vo_driver_t *)this, &va_soft_images[i]);
+    va_soft_images[i].image_id = VA_INVALID_ID;
+
+    if(va_soft_surface_ids[i] != VA_INVALID_SURFACE) {
+#ifdef DEBUG_SURFACE
+      printf("vaapi_close destroy render surface 0x%08x\n", va_soft_surface_ids[i]);
+#endif
+      vaStatus = vaSyncSurface(va_context->va_display, va_soft_surface_ids[i]);
+      vaapi_check_status(this_gen, vaStatus, "vaSyncSurface()");
+      vaStatus = vaDestroySurfaces(va_context->va_display, &va_soft_surface_ids[i], 1);
+      vaapi_check_status(this_gen, vaStatus, "vaDestroySurfaces()");
+      va_soft_surface_ids[i] = VA_INVALID_SURFACE;
+    }
+  }
+
+  va_context->sw_width  = 0;
+  va_context->sw_height = 0;
+  return VA_STATUS_SUCCESS;
+}
+
+static VAStatus vaapi_init_soft_surfaces(vo_driver_t *this_gen, int width, int height) {
+  vaapi_driver_t      *this = (vaapi_driver_t *)this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  VAStatus            vaStatus;
+  int                 i;
+
+  vaapi_destroy_soft_surfaces(this_gen);
+
+  vaStatus = vaCreateSurfaces(va_context->va_display, width, height, VA_RT_FORMAT_YUV420, SOFT_SURFACES, va_soft_surface_ids);
+  if(!vaapi_check_status(this_gen, vaStatus, "vaCreateSurfaces()"))
+    goto error;
+
+  /* allocate software surfaces */
+  for(i = 0; i < SOFT_SURFACES; i++) {
+    ff_vaapi_surface_t *va_surface  = &va_render_surfaces[i];
+
+    vaStatus = vaapi_create_image((vo_driver_t *)this, va_soft_surface_ids[i], &va_soft_images[i], width, height, 1);
+    if(!vaapi_check_status(this_gen, vaStatus, "vaapi_create_image()")) {
+      va_soft_images[i].image_id = VA_INVALID_ID;
+      goto error;
+    }
+
+    va_surface->index = i;
+
+    vaStatus = vaPutImage(va_context->va_display, va_soft_surface_ids[i], va_soft_images[i].image_id,
+               0, 0, va_soft_images[i].width, va_soft_images[i].height,
+               0, 0, va_soft_images[i].width, va_soft_images[i].height);
+    vaapi_check_status(this_gen, vaStatus, "vaPutImage()");
+#ifdef DEBUG_SURFACE
+    printf("vaapi_init_soft_surfaces 0x%08x\n", va_soft_surface_ids[i]);
+#endif
+  }
+
+  va_context->sw_width  = width;
+  va_context->sw_height = height;
+  return VA_STATUS_SUCCESS;
+
+error:
+  va_context->sw_width  = 0;
+  va_context->sw_height = 0;
+  vaapi_destroy_soft_surfaces(this_gen);
+  return VA_STATUS_ERROR_UNKNOWN;
+}
+
+static VAStatus vaapi_init_internal(vo_driver_t *this_gen, int va_profile, int width, int height, int softrender) {
+  vaapi_driver_t      *this = (vaapi_driver_t *)this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  VAConfigAttrib      va_attrib;
+  int                 maj, min, i;
+  VAStatus            vaStatus;
+
+  vaapi_close(this_gen);
+  vaapi_init_va_context(this);
+
+  this->va_context->va_display = vaapi_get_display(this->display, this->opengl_render);
+
+  if(!this->va_context->va_display)
+    goto error;
+
+  vaStatus = vaInitialize(this->va_context->va_display, &maj, &min);
+  if(!vaapi_check_status((vo_driver_t *)this, vaStatus, "vaInitialize()"))
+    goto error;
+
+  lprintf("libva: %d.%d\n", maj, min);
+
+  va_context->valid_context = 1;
+
+  int fmt_count = 0;
+  fmt_count = vaMaxNumImageFormats( va_context->va_display );
+  va_context->va_image_formats = calloc( fmt_count, sizeof(*va_context->va_image_formats) );
+
+  vaStatus = vaQueryImageFormats(va_context->va_display, va_context->va_image_formats, &va_context->va_num_image_formats);
+  if(!vaapi_check_status(this_gen, vaStatus, "vaQueryImageFormats()"))
+    goto error;
+
+  fmt_count = vaMaxNumSubpictureFormats( va_context->va_display );
+  va_context->va_subpic_formats = calloc( fmt_count, sizeof(*va_context->va_subpic_formats) );
+
+  vaStatus = vaQuerySubpictureFormats( va_context->va_display , va_context->va_subpic_formats, 0, &va_context->va_num_subpic_formats );
+  if(!vaapi_check_status(this_gen, vaStatus, "vaQuerySubpictureFormats()"))
+    goto error;
+  
+  const char *vendor = vaQueryVendorString(va_context->va_display);
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_open: Vendor : %s\n", vendor);
+    
+  this->query_va_status = 1;
+  char *p = (char *)vendor;
+  for(i = 0; i < strlen(vendor); i++, p++) {
+    if(strncmp(p, "VDPAU", strlen("VDPAU")) == 0) {
+      xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_open: Enable Splitted-Desktop Systems VDPAU-VIDEO workarounds.\n");
+      this->query_va_status = 0;
+      this->opengl_use_tfp = 0;
+      break;
+    }
+  }
+
+  vaapi_set_background_color(this_gen);
+  vaapi_display_attribs((vo_driver_t *)this);
+
+  va_context->width = width;
+  va_context->height = height;
+  va_context->va_profile = va_profile;
+
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : Context width %d height %d\n", va_context->width, va_context->height);
+
+  /* allocate decoding surfaces */
+  vaStatus = vaCreateSurfaces(va_context->va_display, va_context->width, va_context->height, VA_RT_FORMAT_YUV420, RENDER_SURFACES, va_surface_ids);
+  if(!vaapi_check_status(this_gen, vaStatus, "vaCreateSurfaces()"))
+    goto error;
+
+  /* hardware decoding needs more setup */
+  if(!softrender && va_profile >= 0) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : Profile: %d (%s) Entrypoint %d (%s) Surfaces %d\n", va_context->va_profile, vaapi_profile_to_string(va_context->va_profile), VAEntrypointVLD, vaapi_entrypoint_to_string(VAEntrypointVLD), RENDER_SURFACES);
+
+    memset( &va_attrib, 0, sizeof(va_attrib) );
+    va_attrib.type = VAConfigAttribRTFormat;
+
+    vaStatus = vaGetConfigAttributes(va_context->va_display, va_context->va_profile, VAEntrypointVLD, &va_attrib, 1);
+    if(!vaapi_check_status(this_gen, vaStatus, "vaGetConfigAttributes()"))
+      goto error;
+  
+    if( (va_attrib.value & VA_RT_FORMAT_YUV420) == 0 )
+      goto error;
+
+    vaStatus = vaCreateConfig(va_context->va_display, va_context->va_profile, VAEntrypointVLD, &va_attrib, 1, &va_context->va_config_id);
+    if(!vaapi_check_status(this_gen, vaStatus, "vaCreateConfig()")) {
+      va_context->va_config_id = VA_INVALID_ID;
+      goto error;
+    }
+
+    vaStatus = vaCreateContext(va_context->va_display, va_context->va_config_id, va_context->width, va_context->height,
+                               VA_PROGRESSIVE, va_surface_ids, RENDER_SURFACES, &va_context->va_context_id);
+    if(!vaapi_check_status(this_gen, vaStatus, "vaCreateContext()")) {
+      va_context->va_context_id = VA_INVALID_ID;
+      goto error;
+    }
+  }
+
+  /* xine was told to allocate RENDER_SURFACES frames. assign the frames the rendering surfaces. */
+  for(i = 0; i < RENDER_SURFACES; i++) {
+    ff_vaapi_surface_t *va_surface  = &va_render_surfaces[i];
+    va_surface->index               = i;
+    va_surface->status              = SURFACE_FREE;
+    va_surface->va_surface_id       = va_surface_ids[i];
+
+    if(this->frames[i]) {
+      vaapi_frame_t *frame                  = this->frames[i];
+      frame->vaapi_accel_data.index         = i;
+
+      VAImage va_image;
+      vaStatus = vaapi_create_image(va_context->driver, va_surface_ids[i], &va_image, width, height, 1);
+      if(vaapi_check_status(va_context->driver, vaStatus, "vaapi_create_image()")) {
+        vaStatus = vaPutImage(va_context->va_display, va_surface_ids[i], va_image.image_id,
+                              0, 0, va_image.width, va_image.height,
+                              0, 0, va_image.width, va_image.height);
+        vaapi_destroy_image(va_context->driver, &va_image);
+      }
+    }
+#ifdef DEBUG_SURFACE
+    printf("vaapi_init_internal 0x%08x\n", va_surface_ids[i]);
+#endif
+  }
+
+  vaStatus = vaapi_init_soft_surfaces(this_gen, width, height);
+  if(!vaapi_check_status(this_gen, vaStatus, "vaapi_init_soft_surfaces()")) {
+    vaapi_destroy_soft_surfaces(this_gen);
+    goto error;
+  }
+
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : guarded render : %d\n", this->guarded_render);
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : glxrender      : %d\n", this->opengl_render);
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : glxrender tfp  : %d\n", this->opengl_use_tfp);
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : is_bound       : %d\n", va_context->is_bound);
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : scaling level  : name %s value 0x%08x\n", scaling_level_enum_names[this->scaling_level_enum], this->scaling_level);
+
+  this->init_opengl_render = 1;
+
+  return VA_STATUS_SUCCESS;
+
+error:
+  vaapi_close(this_gen);
+  vaapi_init_va_context(this);
+  va_context->valid_context = 0;
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : error init vaapi\n");
+
+  return VA_STATUS_ERROR_UNKNOWN;
+}
+
+/*
+ * Init VAAPI. This function is called from the decoder side.
+ * When the decoder uses software decoding vaapi_init is not called.
+ * Therefore we do it in vaapi_display_frame to get a valid VAAPI context
+ */
+static VAStatus vaapi_init(vo_frame_t *frame_gen, int va_profile, int width, int height, int softrender) {
+  if(!frame_gen)
+    return VA_STATUS_ERROR_UNKNOWN;
+
+  vo_driver_t         *this_gen   = (vo_driver_t *) frame_gen->driver;
+  vaapi_driver_t      *this       = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+
+  VAStatus vaStatus;
+
+  unsigned int last_sub_img_fmt = va_context->last_sub_image_fmt;
+
+  if(last_sub_img_fmt)
+    vaapi_ovl_associate(this_gen, frame_gen->format, 0);
+
+  if(!this->guarded_render) {
+    pthread_mutex_lock(&this->vaapi_lock);
+    XLockDisplay(this->display);
+  }
+
+  vaStatus = vaapi_init_internal(this_gen, va_profile, width, height, softrender);
+
+  if(!this->guarded_render) {
+    XUnlockDisplay(this->display);
+    pthread_mutex_unlock(&this->vaapi_lock);
+  }
+
+  if(last_sub_img_fmt)
+    vaapi_ovl_associate(this_gen, frame_gen->format, this->has_overlay);
+
+  return vaStatus;
+}
+
+static void vaapi_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src)
+{
+  vo_img->proc_called = 1;
+}
+
+static void vaapi_frame_field (vo_frame_t *vo_img, int which_field)
+{
+}
+
+static void vaapi_frame_dispose (vo_frame_t *vo_img) {
+  vaapi_driver_t *this  = (vaapi_driver_t *) vo_img->driver;
+  vaapi_frame_t  *frame = (vaapi_frame_t *) vo_img ;
+  vaapi_accel_t  *accel = &frame->vaapi_accel_data;
+
+  lprintf("vaapi_frame_dispose\n");
+
+  av_free (frame->vo_frame.base[0]);
+  av_free (frame->vo_frame.base[1]);
+  av_free (frame->vo_frame.base[2]);
+
+  if(this->guarded_render) {
+    ff_vaapi_surface_t *va_surface = &va_render_surfaces[accel->index];
+    va_surface->status = SURFACE_FREE;
+  }
+
+  free (frame);
+}
+
+static vo_frame_t *vaapi_alloc_frame (vo_driver_t *this_gen) {
+  vaapi_driver_t  *this = (vaapi_driver_t *) this_gen;
+  vaapi_frame_t   *frame;
+
+  frame = (vaapi_frame_t *) calloc(1, sizeof(vaapi_frame_t));
+
+  if (!frame)
+    return NULL;
+
+  this->frames[this->num_frame_buffers++] = frame;
+
+  frame->vo_frame.base[0] = frame->vo_frame.base[1] = frame->vo_frame.base[2] = NULL;
+  frame->width = frame->height = frame->format = frame->flags = 0;
+
+  frame->vo_frame.accel_data = &frame->vaapi_accel_data;
+
+  pthread_mutex_init (&frame->vo_frame.mutex, NULL);
+
+  /*
+   * supply required functions
+   */
+  frame->vo_frame.proc_duplicate_frame_data         = NULL;
+  frame->vo_frame.proc_provide_standard_frame_data  = NULL;
+  frame->vo_frame.proc_slice                        = vaapi_frame_proc_slice;
+  frame->vo_frame.proc_frame                        = NULL;
+  frame->vo_frame.field                             = vaapi_frame_field;
+  frame->vo_frame.dispose                           = vaapi_frame_dispose;
+  frame->vo_frame.driver                            = this_gen;
+
+  frame->vaapi_accel_data.vo_frame                  = &frame->vo_frame;
+  frame->vaapi_accel_data.vaapi_init                = &vaapi_init;
+  frame->vaapi_accel_data.profile_from_imgfmt       = &profile_from_imgfmt;
+  frame->vaapi_accel_data.get_context               = &get_context;
+
+#if AVVIDEO > 1
+  frame->vaapi_accel_data.avcodec_decode_video2     = &guarded_avcodec_decode_video2;
+#else
+  frame->vaapi_accel_data.avcodec_decode_video      = &guarded_avcodec_decode_video;
+#endif
+
+  frame->vaapi_accel_data.get_vaapi_surface         = &get_vaapi_surface;
+  frame->vaapi_accel_data.render_vaapi_surface      = &render_vaapi_surface;
+  frame->vaapi_accel_data.release_vaapi_surface     = &release_vaapi_surface;
+  frame->vaapi_accel_data.guarded_render            = &guarded_render;
+
+  lprintf("alloc frame\n");
+
+  return (vo_frame_t *) frame;
+}
+
+
+/* Display OSD */
+static int vaapi_ovl_associate(vo_driver_t *this_gen, int format, int bShow) {
+  vaapi_driver_t      *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  VAStatus vaStatus;
+
+  if(!va_context->valid_context)
+    return 0;
+
+  if(va_context->last_sub_image_fmt && !bShow) {
+    if(va_context->va_subpic_id != VA_INVALID_ID) {
+      if(va_context->last_sub_image_fmt == XINE_IMGFMT_VAAPI) {
+        vaStatus = vaDeassociateSubpicture(va_context->va_display, va_context->va_subpic_id,
+                                va_surface_ids, RENDER_SURFACES);
+        vaapi_check_status(this_gen, vaStatus, "vaDeassociateSubpicture()");
+      } else if(va_context->last_sub_image_fmt == XINE_IMGFMT_YV12 ||
+                va_context->last_sub_image_fmt == XINE_IMGFMT_YUY2) {
+        vaStatus = vaDeassociateSubpicture(va_context->va_display, va_context->va_subpic_id,
+                                va_soft_surface_ids, SOFT_SURFACES);
+        vaapi_check_status(this_gen, vaStatus, "vaDeassociateSubpicture()");
+      }
+    }
+    va_context->last_sub_image_fmt = 0;
+    return 1;
+  }
+  
+  if(!va_context->last_sub_image_fmt && bShow) {
+    unsigned int flags = 0;
+    unsigned int output_width = va_context->width;
+    unsigned int output_height = va_context->height;
+    void *p_base = NULL;
+
+    VAStatus vaStatus;
+
+    vaapi_destroy_subpicture(this_gen);
+    vaStatus = vaapi_create_subpicture(this_gen, this->overlay_bitmap_width, this->overlay_bitmap_height);
+    if(!vaapi_check_status(this_gen, vaStatus, "vaapi_create_subpicture()"))
+      return 0;
+
+    vaStatus = vaMapBuffer(va_context->va_display, va_context->va_subpic_image.buf, &p_base);
+    if(!vaapi_check_status(this_gen, vaStatus, "vaMapBuffer()"))
+      return 0;
+
+    xine_fast_memcpy((uint32_t *)p_base, this->overlay_bitmap, this->overlay_bitmap_width * this->overlay_bitmap_height * sizeof(uint32_t));
+
+    vaStatus = vaUnmapBuffer(va_context->va_display, va_context->va_subpic_image.buf);
+    vaapi_check_status(this_gen, vaStatus, "vaUnmapBuffer()");
+
+    lprintf( "vaapi_ovl_associate: overlay_width=%d overlay_height=%d unscaled %d va_subpic_id 0x%08x ovl_changed %d has_overlay %d bShow %d overlay_bitmap_width %d overlay_bitmap_height %d va_context->width %d va_context->height %d\n",
+           this->overlay_output_width, this->overlay_output_height, this->has_overlay,
+           va_context->va_subpic_id, this->ovl_changed, this->has_overlay, bShow,
+           this->overlay_bitmap_width, this->overlay_bitmap_height,
+           va_context->width, va_context->height);
+
+    if(format == XINE_IMGFMT_VAAPI) {
+      lprintf("vaapi_ovl_associate hw\n");
+      vaStatus = vaAssociateSubpicture(va_context->va_display, va_context->va_subpic_id,
+                              va_surface_ids, RENDER_SURFACES,
+                              0, 0, va_context->va_subpic_image.width, va_context->va_subpic_image.height,
+                              0, 0, output_width, output_height, flags);
+    } else {
+      lprintf("vaapi_ovl_associate sw\n");
+      vaStatus = vaAssociateSubpicture(va_context->va_display, va_context->va_subpic_id,
+                              va_soft_surface_ids, SOFT_SURFACES,
+                              0, 0, va_context->va_subpic_image.width, va_context->va_subpic_image.height,
+                              0, 0, va_soft_images[0].width, va_soft_images[0].height, flags);
+    }
+
+    if(vaapi_check_status(this_gen, vaStatus, "vaAssociateSubpicture()")) {
+      va_context->last_sub_image_fmt = format;
+      return 1;
+    }
+  }
+  return 0;
+}
+
+static void vaapi_overlay_clut_yuv2rgb(vaapi_driver_t  *this, vo_overlay_t *overlay, vaapi_frame_t *frame)
+{
+  int i;
+  clut_t* clut = (clut_t*) overlay->color;
+
+  if (!overlay->rgb_clut) {
+    for ( i=0; i<sizeof(overlay->color)/sizeof(overlay->color[0]); i++ ) {
+      *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(this->ovl_yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr);
+    }
+    overlay->rgb_clut++;
+  }
+  if (!overlay->hili_rgb_clut) {
+    clut = (clut_t*) overlay->hili_color;
+    for ( i=0; i<sizeof(overlay->color)/sizeof(overlay->color[0]); i++) {
+      *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(this->ovl_yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr);
+    }
+    overlay->hili_rgb_clut++;
+  }
+}
+
+static void vaapi_overlay_begin (vo_driver_t *this_gen,
+      vo_frame_t *frame_gen, int changed) {
+  vaapi_driver_t      *this       = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+
+  if ( !changed )
+    return;
+
+  this->has_overlay = 0;
+  ++this->ovl_changed;
+
+  /* Apply OSD layer. */
+  if(va_context->valid_context) {
+    lprintf("vaapi_overlay_begin chaned %d\n", changed);
+
+    pthread_mutex_lock(&this->vaapi_lock);
+    XLockDisplay(this->display);
+
+    vaapi_ovl_associate(this_gen, frame_gen->format, this->has_overlay);
+
+    XUnlockDisplay(this->display);
+    pthread_mutex_unlock(&this->vaapi_lock);
+  }
+}
+
+static void vaapi_overlay_blend (vo_driver_t *this_gen,
+      vo_frame_t *frame_gen, vo_overlay_t *overlay) {
+  vaapi_driver_t  *this = (vaapi_driver_t *) this_gen;
+
+  int i = this->ovl_changed;
+
+  if (!i)
+    return;
+
+  if (--i >= XINE_VORAW_MAX_OVL)
+    return;
+
+  if (overlay->width <= 0 || overlay->height <= 0 || (!overlay->rle && (!overlay->argb_layer || !overlay->argb_layer->buffer)))
+    return;
+
+  if (overlay->rle)
+    lprintf("overlay[%d] rle %s%s %dx%d@%d,%d hili rect %d,%d-%d,%d\n", i,
+            overlay->unscaled ? " unscaled ": " scaled ",
+            (overlay->rgb_clut > 0 || overlay->hili_rgb_clut > 0) ? " rgb ": " ycbcr ",
+            overlay->width, overlay->height, overlay->x, overlay->y,
+            overlay->hili_left, overlay->hili_top,
+            overlay->hili_right, overlay->hili_bottom);
+  if (overlay->argb_layer && overlay->argb_layer->buffer)
+    lprintf("overlay[%d] argb %s %dx%d@%d,%d dirty rect %d,%d-%d,%d\n", i,
+            overlay->unscaled ? " unscaled ": " scaled ",
+            overlay->width, overlay->height, overlay->x, overlay->y,
+            overlay->argb_layer->x1, overlay->argb_layer->y1,
+            overlay->argb_layer->x2, overlay->argb_layer->y2);
+
+
+  this->overlays[i] = overlay;
+
+  ++this->ovl_changed;
+}
+
+static void vaapi_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
+  vaapi_driver_t      *this       = (vaapi_driver_t *) this_gen;
+  vaapi_frame_t       *frame      = (vaapi_frame_t *) frame_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+
+  int novls = this->ovl_changed;
+  if (novls < 2) {
+    this->ovl_changed = 0;
+    return;
+  }
+  --novls;
+
+  uint32_t output_width = frame->width;
+  uint32_t output_height = frame->height;
+  uint32_t unscaled_width = 0, unscaled_height = 0;
+  vo_overlay_t *first_scaled = NULL, *first_unscaled = NULL;
+  vaapi_rect_t dirty_rect, unscaled_dirty_rect;
+  int has_rle = 0;
+
+  int i;
+  for (i = 0; i < novls; ++i) {
+    vo_overlay_t *ovl = this->overlays[i];
+
+    if (ovl->rle)
+      has_rle = 1;
+
+    if (ovl->unscaled) {
+      if (first_unscaled) {
+        if (ovl->x < unscaled_dirty_rect.x1)
+          unscaled_dirty_rect.x1 = ovl->x;
+        if (ovl->y < unscaled_dirty_rect.y1)
+          unscaled_dirty_rect.y1 = ovl->y;
+        if ((ovl->x + ovl->width) > unscaled_dirty_rect.x2)
+          unscaled_dirty_rect.x2 = ovl->x + ovl->width;
+        if ((ovl->y + ovl->height) > unscaled_dirty_rect.y2)
+          unscaled_dirty_rect.y2 = ovl->y + ovl->height;
+      } else {
+        first_unscaled = ovl;
+        unscaled_dirty_rect.x1 = ovl->x;
+        unscaled_dirty_rect.y1 = ovl->y;
+        unscaled_dirty_rect.x2 = ovl->x + ovl->width;
+        unscaled_dirty_rect.y2 = ovl->y + ovl->height;
+      }
+
+      unscaled_width = unscaled_dirty_rect.x2;
+      unscaled_height = unscaled_dirty_rect.y2;
+    } else {
+      if (first_scaled) {
+        if (ovl->x < dirty_rect.x1)
+          dirty_rect.x1 = ovl->x;
+        if (ovl->y < dirty_rect.y1)
+          dirty_rect.y1 = ovl->y;
+        if ((ovl->x + ovl->width) > dirty_rect.x2)
+          dirty_rect.x2 = ovl->x + ovl->width;
+        if ((ovl->y + ovl->height) > dirty_rect.y2)
+          dirty_rect.y2 = ovl->y + ovl->height;
+      } else {
+        first_scaled = ovl;
+        dirty_rect.x1 = ovl->x;
+        dirty_rect.y1 = ovl->y;
+        dirty_rect.x2 = ovl->x + ovl->width;
+        dirty_rect.y2 = ovl->y + ovl->height;
+      }
+
+      if (dirty_rect.x2 > output_width)
+        output_width = dirty_rect.x2;
+      if (dirty_rect.y2 > output_height)
+        output_height = dirty_rect.y2;
+
+    }
+  }
+
+  int need_init = 0;
+
+  lprintf("dirty_rect.x0 %d dirty_rect.y0 %d dirty_rect.x2 %d dirty_rect.y2 %d output_width %d output_height %d\n",
+      dirty_rect.x0, dirty_rect.y0, dirty_rect.x2, dirty_rect.y2, output_width, output_height);
+
+  if (first_scaled) {
+    vaapi_rect_t dest;
+    dest.x1 = first_scaled->x;
+    dest.y1 = first_scaled->y;
+    dest.x2 = first_scaled->x + first_scaled->width;
+    dest.y2 = first_scaled->y + first_scaled->height;
+    if (!RECT_IS_EQ(dest, dirty_rect))
+      need_init = 1;
+  }
+
+  int need_unscaled_init = (first_unscaled &&
+                                  (first_unscaled->x != unscaled_dirty_rect.x1 ||
+                                   first_unscaled->y != unscaled_dirty_rect.y1 ||
+                                   (first_unscaled->x + first_unscaled->width) != unscaled_dirty_rect.x2 ||
+                                   (first_unscaled->y + first_unscaled->height) != unscaled_dirty_rect.y2));
+
+  if (first_scaled) {
+    this->overlay_output_width = output_width;
+    this->overlay_output_height = output_height;
+
+    need_init = 1;
+
+    this->overlay_dirty_rect = dirty_rect;
+  }
+
+  if (first_unscaled) {
+    this->overlay_unscaled_width = unscaled_width;
+    this->overlay_unscaled_height = unscaled_height;
+
+    need_unscaled_init = 1;
+    this->overlay_unscaled_dirty_rect = unscaled_dirty_rect;
+  }
+
+  if (has_rle || need_init || need_unscaled_init) {
+    lprintf("has_rle %d need_init %d need_unscaled_init %d unscaled_width %d unscaled_height %d output_width %d output_height %d\n",
+        has_rle, need_init, need_unscaled_init, unscaled_width, unscaled_height, output_width, output_height);
+    if (need_init) {
+      this->overlay_bitmap_width = output_width;
+      this->overlay_bitmap_height = output_height;
+    }
+    if (need_unscaled_init) {
+
+      if(this->vdr_osd_width)
+        this->overlay_bitmap_width =  (this->vdr_osd_width >  this->sc.gui_width) ? this->vdr_osd_width : this->sc.gui_width;
+      else
+        this->overlay_bitmap_width =  (unscaled_width >  this->sc.gui_width) ? unscaled_width : this->sc.gui_width;
+
+      if(this->vdr_osd_height)
+        this->overlay_bitmap_height = (this->vdr_osd_height > this->sc.gui_height) ? this->vdr_osd_height : this->sc.gui_height;
+      else
+        this->overlay_bitmap_height = (unscaled_height > this->sc.gui_height) ? unscaled_height : this->sc.gui_height;
+
+    } else if (need_init) {
+
+      if(this->vdr_osd_width)
+        this->overlay_bitmap_width =  (this->vdr_osd_width >  this->sc.gui_width) ? this->vdr_osd_width : this->sc.gui_width;
+      else
+        this->overlay_bitmap_width =  (output_width >  this->sc.gui_width) ? output_width : this->sc.gui_width;
+
+      if(this->vdr_osd_height)
+        this->overlay_bitmap_height = (this->vdr_osd_height > this->sc.gui_height) ? this->vdr_osd_height : this->sc.gui_height;
+      else
+        this->overlay_bitmap_height = (output_height > this->sc.gui_height) ? output_height : this->sc.gui_height;
+
+    }
+  }
+
+  if ((this->overlay_bitmap_width * this->overlay_bitmap_height) > this->overlay_bitmap_size) {
+    this->overlay_bitmap_size = this->overlay_bitmap_width * this->overlay_bitmap_height;
+    free(this->overlay_bitmap);
+    this->overlay_bitmap = calloc( this->overlay_bitmap_size, sizeof(uint32_t));
+  } else {
+    memset(this->overlay_bitmap, 0x0, this->overlay_bitmap_size * sizeof(uint32_t));
+  }
+
+  for (i = 0; i < novls; ++i) {
+    vo_overlay_t *ovl = this->overlays[i];
+    uint32_t *bitmap = NULL;
+    uint32_t *rgba = NULL;
+
+    if (ovl->rle) {
+      if(ovl->width<=0 || ovl->height<=0)
+        continue;
+
+      if (!ovl->rgb_clut || !ovl->hili_rgb_clut)
+        vaapi_overlay_clut_yuv2rgb (this, ovl, frame);
+
+      bitmap = rgba = calloc(ovl->width * ovl->height * 4, sizeof(uint32_t));
+
+      int num_rle = ovl->num_rle;
+      rle_elem_t *rle = ovl->rle;
+      uint32_t red, green, blue, alpha;
+      clut_t *low_colors = (clut_t*)ovl->color;
+      clut_t *hili_colors = (clut_t*)ovl->hili_color;
+      uint8_t *low_trans = ovl->trans;
+      uint8_t *hili_trans = ovl->hili_trans;
+      clut_t *colors;
+      uint8_t *trans;
+      int rlelen = 0;
+      uint8_t clr = 0;
+      int i, pos=0, x, y;
+
+      while (num_rle > 0) {
+        x = pos % ovl->width;
+        y = pos / ovl->width;
+
+        if ( (x>=ovl->hili_left && x<=ovl->hili_right) && (y>=ovl->hili_top && y<=ovl->hili_bottom) ) {
+          colors = hili_colors;
+          trans = hili_trans;
+        }
+        else {
+          colors = low_colors;
+          trans = low_trans;
+        }
+        rlelen = rle->len;
+        clr = rle->color;
+        for ( i=0; i<rlelen; ++i ) {
+          if ( trans[clr] == 0 ) {
+            alpha = red = green = blue = 0;
+          }
+          else {
+            red = colors[clr].y; // red
+            green = colors[clr].cr; // green
+            blue = colors[clr].cb; // blue
+            alpha = trans[clr]*255/15;
+          }
+          *rgba = (alpha<<24) | (red<<16) | (green<<8) | blue;
+          rgba++;
+          ++pos;
+        }
+        ++rle;
+        --num_rle;
+      }
+      lprintf("width %d height %d pos %d %d\n", ovl->width, ovl->height, pos, ovl->width * ovl->height);
+    } else {
+      pthread_mutex_lock(&ovl->argb_layer->mutex);
+      bitmap = ovl->argb_layer->buffer;
+    }
+
+    /* Blit overlay to destination */
+    uint32_t pitch = ovl->width * sizeof(uint32_t);
+    uint32_t *copy_dst = this->overlay_bitmap;
+    uint32_t *copy_src = NULL;
+    uint32_t height = 0;
+
+    copy_src = bitmap;
+  
+    copy_dst += ovl->y * this->overlay_bitmap_width;
+
+    lprintf("overlay_bitmap_width %d overlay_bitmap_height %d  ovl->x %d ovl->y %d ovl->width %d ovl->height %d width %d height %d\n",
+      this->overlay_bitmap_width, this->overlay_bitmap_height, ovl->x, ovl->y, ovl->width, ovl->height, this->overlay_bitmap_width, this->overlay_bitmap_height);
+
+    for(height = 0; height < ovl->height; height++) {
+      if((height + ovl->y) >= this->overlay_bitmap_height)
+        break;
+
+      xine_fast_memcpy(copy_dst + ovl->x, copy_src, pitch);
+      copy_dst += this->overlay_bitmap_width;
+      copy_src += ovl->width;
+    }
+
+    if (ovl->rle) {
+      if(bitmap) {
+        free(bitmap);
+        bitmap = NULL;
+      }
+    }
+
+    if (!ovl->rle)
+      pthread_mutex_unlock(&ovl->argb_layer->mutex);
+
+  }
+
+  this->ovl_changed = 0;
+  this->has_overlay = (first_scaled != NULL) | (first_unscaled != NULL);
+
+  lprintf("this->has_overlay %d\n", this->has_overlay);
+  /* Apply OSD layer. */
+  if(va_context->valid_context) {
+    pthread_mutex_lock(&this->vaapi_lock);
+    XLockDisplay(this->display);
+
+    vaapi_ovl_associate(this_gen, frame_gen->format, this->has_overlay);
+
+    XUnlockDisplay(this->display);
+    pthread_mutex_unlock(&this->vaapi_lock);
+  }
+}
+
+static void vaapi_resize_glx_window (vo_driver_t *this_gen, int width, int height) {
+  vaapi_driver_t  *this = (vaapi_driver_t *) this_gen;
+
+  if(this->valid_opengl_context) {
+    glViewport(0, 0, width, height);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    gluPerspective(FOVY, ASPECT, Z_NEAR, Z_FAR);
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+    glTranslatef(-0.5f, -0.5f, -Z_CAMERA);
+    glScalef(1.0f / (GLfloat)width,
+             -1.0f / (GLfloat)height,
+             1.0f / (GLfloat)width);
+    glTranslatef(0.0f, -1.0f * (GLfloat)height, 0.0f);
+  }
+}
+
+static int vaapi_redraw_needed (vo_driver_t *this_gen) {
+  vaapi_driver_t      *this       = (vaapi_driver_t *) this_gen;
+  int                 ret = 0;
+
+  _x_vo_scale_compute_ideal_size( &this->sc );
+
+  if ( _x_vo_scale_redraw_needed( &this->sc ) ) {
+    _x_vo_scale_compute_output_size( &this->sc );
+
+    XMoveResizeWindow(this->display, this->window,
+                      0, 0, this->sc.gui_width, this->sc.gui_height);
+
+    ret = 1;
+  }
+
+  return ret;
+}
+
+static void vaapi_provide_standard_frame_data (vo_frame_t *orig, xine_current_frame_data_t *data)
+{
+  vaapi_driver_t      *driver     = (vaapi_driver_t *) orig->driver;
+  ff_vaapi_context_t  *va_context = driver->va_context;
+
+  vaapi_accel_t       *accel      = (vaapi_accel_t *) orig->accel_data;
+  vo_frame_t          *this       = accel->vo_frame;
+  ff_vaapi_surface_t  *va_surface = &va_render_surfaces[accel->index];
+
+  uint32_t  pitches[3];
+  uint8_t   *base[3];
+
+  if(driver == NULL) {
+    return;
+  }
+
+  if (this->format != XINE_IMGFMT_VAAPI) {
+    xprintf(driver->xine, XINE_VERBOSITY_LOG, LOG_MODULE "vaapi_provide_standard_frame_data: unexpected frame format 0x%08x!\n", this->format);
+    return;
+  }
+
+  if( !accel || va_surface->va_surface_id == VA_INVALID_SURFACE )
+    return;
+
+  lprintf("vaapi_provide_standard_frame_data %s 0x%08x width %d height %d\n",
+      (this->format == XINE_IMGFMT_VAAPI) ? "XINE_IMGFMT_VAAPI" : ((this->format == XINE_IMGFMT_YV12) ? "XINE_IMGFMT_YV12" : "XINE_IMGFMT_YUY2"),
+      va_surface->va_surface_id, this->width, this->height);
+
+  pthread_mutex_lock(&driver->vaapi_lock);
+  XLockDisplay(driver->display);
+
+  int width = va_context->width;
+  int height = va_context->height;
+
+  data->format = XINE_IMGFMT_YV12;
+  data->img_size = width * height
+                   + ((width + 1) / 2) * ((height + 1) / 2)
+                   + ((width + 1) / 2) * ((height + 1) / 2);
+  if (data->img) {
+    pitches[0] = width;
+    pitches[2] = width / 2;
+    pitches[1] = width / 2;
+    base[0] = data->img;
+    base[2] = data->img + width * height;
+    base[1] = data->img + width * height + width * this->height / 4;
+
+    VAImage   va_image;
+    VAStatus  vaStatus;
+    void      *p_base;
+
+    vaStatus = vaSyncSurface(va_context->va_display, va_surface->va_surface_id);
+    vaapi_check_status(va_context->driver, vaStatus, "vaSyncSurface()");
+
+    VASurfaceStatus surf_status = 0;
+
+    if(driver->query_va_status) {
+      vaStatus = vaQuerySurfaceStatus(va_context->va_display, va_surface->va_surface_id, &surf_status);
+      vaapi_check_status(va_context->driver, vaStatus, "vaQuerySurfaceStatus()");
+    } else {
+      surf_status = VASurfaceReady;
+    }
+
+    if(surf_status != VASurfaceReady)
+      goto error;
+
+    vaStatus = vaapi_create_image(va_context->driver, va_surface->va_surface_id, &va_image, width, height, 0);
+    if(!vaapi_check_status(va_context->driver, vaStatus, "vaapi_create_image()"))
+      goto error;
+
+    lprintf("vaapi_provide_standard_frame_data accel->va_surface_id 0x%08x va_image.image_id 0x%08x va_context->width %d va_context->height %d va_image.width %d va_image.height %d width %d height %d size1 %d size2 %d %d %d %d status %d num_planes %d\n",
+       va_surface->va_surface_id, va_image.image_id, va_context->width, va_context->height, va_image.width, va_image.height, width, height, va_image.data_size, data->img_size,
+       va_image.pitches[0], va_image.pitches[1], va_image.pitches[2], surf_status, va_image.num_planes);
+
+    if(va_image.image_id == VA_INVALID_ID)
+      goto error;
+
+    if(!va_context->is_bound) {
+      vaStatus = vaGetImage(va_context->va_display, va_surface->va_surface_id, 0, 0,
+                          va_image.width, va_image.height, va_image.image_id);
+    } else {
+      vaStatus = VA_STATUS_SUCCESS;
+    }
+
+    if(vaapi_check_status(va_context->driver, vaStatus, "vaGetImage()")) {
+      vaStatus = vaMapBuffer( va_context->va_display, va_image.buf, &p_base ) ;
+      if(vaapi_check_status(va_context->driver, vaStatus, "vaMapBuffer()")) {
+
+        /*
+        uint8_t *src[3] = { NULL, };
+        src[0] = (uint8_t *)p_base + va_image.offsets[0];
+        src[1] = (uint8_t *)p_base + va_image.offsets[1];
+        src[2] = (uint8_t *)p_base + va_image.offsets[2];
+        */
+
+        if( va_image.format.fourcc == VA_FOURCC( 'Y', 'V', '1', '2' ) ||
+            va_image.format.fourcc == VA_FOURCC( 'I', '4', '2', '0' ) ) {
+          lprintf("VAAPI YV12 image\n");
+
+          yv12_to_yv12(
+            (uint8_t*)p_base + va_image.offsets[0], va_image.pitches[0],
+            base[0], pitches[0],
+            (uint8_t*)p_base + va_image.offsets[1], va_image.pitches[1],
+            base[1], pitches[1],
+            (uint8_t*)p_base + va_image.offsets[2], va_image.pitches[2],
+            base[2], pitches[2],
+            va_image.width, va_image.height);
+
+        } else if( va_image.format.fourcc == VA_FOURCC( 'N', 'V', '1', '2' ) ) {
+          lprintf("VAAPI NV12 image\n");
+
+          lprintf("va_image.offsets[0] %d va_image.offsets[1] %d va_image.offsets[2] %d size %d size %d size %d width %d height %d width %d height %d\n",
+              va_image.offsets[0], va_image.offsets[1], va_image.offsets[2], va_image.data_size, va_image.width * va_image.height,
+              data->img_size, width, height, va_image.width, va_image.height);
+
+          base[0] = data->img;
+          base[1] = data->img + width * height;
+          base[2] = data->img + width * height + width * height / 4;
+
+          nv12_to_yv12((uint8_t *)p_base + va_image.offsets[0], va_image.pitches[0],
+                       (uint8_t *)p_base + va_image.offsets[1], va_image.pitches[1],
+                       base[0], pitches[0],
+                       base[1], pitches[1],
+                       base[2], pitches[2],
+                       va_image.width,  va_image.height,
+                       width, height,
+                       va_image.data_size);
+
+        } else {
+          printf("vaapi_provide_standard_frame_data unsupported image format\n");
+        }
+
+        vaStatus = vaUnmapBuffer(va_context->va_display, va_image.buf);
+        vaapi_check_status(va_context->driver, vaStatus, "vaUnmapBuffer()");
+        vaapi_destroy_image(va_context->driver, &va_image);
+      }
+    }
+  }
+
+error:
+  XUnlockDisplay(driver->display);
+  pthread_mutex_unlock(&driver->vaapi_lock);
+}
+
+static void vaapi_duplicate_frame_data (vo_frame_t *this_gen, vo_frame_t *original)
+{
+  vaapi_driver_t      *driver     = (vaapi_driver_t *) original->driver;
+  ff_vaapi_context_t  *va_context = driver->va_context;
+
+  vaapi_frame_t *this = (vaapi_frame_t *)this_gen;
+  vaapi_frame_t *orig = (vaapi_frame_t *)original;
+
+  vaapi_accel_t      *accel_this = &this->vaapi_accel_data;
+  vaapi_accel_t      *accel_orig = &orig->vaapi_accel_data;
+
+  ff_vaapi_surface_t *va_surface_this = &va_render_surfaces[accel_this->index];
+  ff_vaapi_surface_t *va_surface_orig = &va_render_surfaces[accel_orig->index];
+
+  lprintf("vaapi_duplicate_frame_data %s %s 0x%08x 0x%08x\n",
+      (this_gen->format == XINE_IMGFMT_VAAPI) ? "XINE_IMGFMT_VAAPI" : ((this_gen->format == XINE_IMGFMT_YV12) ? "XINE_IMGFMT_YV12" : "XINE_IMGFMT_YUY2"),
+      (original->format == XINE_IMGFMT_VAAPI) ? "XINE_IMGFMT_VAAPI" : ((original->format == XINE_IMGFMT_YV12) ? "XINE_IMGFMT_YV12" : "XINE_IMGFMT_YUY2"),
+      va_surface_this->va_surface_id, va_surface_orig->va_surface_id);
+
+  if (orig->vo_frame.format != XINE_IMGFMT_VAAPI) {
+    xprintf(driver->xine, XINE_VERBOSITY_LOG, LOG_MODULE "vaapi_duplicate_frame_data: unexpected frame format 0x%08x!\n", orig->format);
+    return;
+  }
+
+  if (this->vo_frame.format != XINE_IMGFMT_VAAPI) {
+    xprintf(driver->xine, XINE_VERBOSITY_LOG, LOG_MODULE "vaapi_duplicate_frame_data: unexpected frame format 0x%08x!\n", this->format);
+    return;
+  }
+
+  pthread_mutex_lock(&driver->vaapi_lock);
+  XLockDisplay(driver->display);
+
+  VAImage   va_image_orig;
+  VAImage   va_image_this;
+  VAStatus  vaStatus;
+  void      *p_base_orig = NULL;
+  void      *p_base_this = NULL;
+
+  vaStatus = vaSyncSurface(va_context->va_display, va_surface_orig->va_surface_id);
+  vaapi_check_status(va_context->driver, vaStatus, "vaSyncSurface()");
+
+  int this_width = va_context->width;
+  int this_height = va_context->height;
+  int orig_width = va_context->width;
+  int orig_height = va_context->height;
+
+  vaStatus = vaapi_create_image(va_context->driver, va_surface_orig->va_surface_id, &va_image_orig, orig_width, orig_height, 0);
+  if(!vaapi_check_status(va_context->driver, vaStatus, "vaapi_create_image()")) {
+    va_image_orig.image_id = VA_INVALID_ID;
+    goto error;
+  }
+
+  vaStatus = vaapi_create_image(va_context->driver, va_surface_this->va_surface_id, &va_image_this, this_width, this_height, 0);
+  if(!vaapi_check_status(va_context->driver, vaStatus, "vaapi_create_image()")) {
+    va_image_this.image_id = VA_INVALID_ID;
+    goto error;
+  }
+
+  if(va_image_orig.image_id == VA_INVALID_ID || va_image_this.image_id == VA_INVALID_ID) {
+    printf("vaapi_duplicate_frame_data invalid image\n");
+    goto error;
+  }
+
+  lprintf("vaapi_duplicate_frame_data va_image_orig.image_id 0x%08x va_image_orig.width %d va_image_orig.height %d width %d height %d size %d %d %d %d\n",
+       va_image_orig.image_id, va_image_orig.width, va_image_orig.height, this->width, this->height, va_image_orig.data_size,
+       va_image_orig.pitches[0], va_image_orig.pitches[1], va_image_orig.pitches[2]);
+
+  if(!va_context->is_bound) {
+    vaStatus = vaGetImage(va_context->va_display, va_surface_orig->va_surface_id, 0, 0,
+                          va_image_orig.width, va_image_orig.height, va_image_orig.image_id);
+  } else {
+    vaStatus = VA_STATUS_SUCCESS;
+  }
+
+  if(vaapi_check_status(va_context->driver, vaStatus, "vaGetImage()")) {
+    
+    if(!va_context->is_bound) {
+      vaStatus = vaPutImage(va_context->va_display, va_surface_this->va_surface_id, va_image_orig.image_id,
+                            0, 0, va_image_orig.width, va_image_orig.height,
+                            0, 0, va_image_this.width, va_image_this.height);
+      vaapi_check_status(va_context->driver, vaStatus, "vaPutImage()");
+    } else {
+      vaStatus = vaMapBuffer( va_context->va_display, va_image_orig.buf, &p_base_orig ) ;
+      if(!vaapi_check_status(va_context->driver, vaStatus, "vaMapBuffer()"))
+        goto error;
+
+      vaStatus = vaMapBuffer( va_context->va_display, va_image_this.buf, &p_base_this ) ;
+      if(!vaapi_check_status(va_context->driver, vaStatus, "vaMapBuffer()"))
+        goto error;
+
+      int size = (va_image_orig.data_size > va_image_this.data_size) ? va_image_this.data_size : va_image_orig.data_size;
+      xine_fast_memcpy((uint8_t *) p_base_this, (uint8_t *) p_base_orig, size);
+
+    }
+  }
+
+error:
+  if(p_base_orig) {
+    vaStatus = vaUnmapBuffer(va_context->va_display, va_image_orig.buf);
+    vaapi_check_status(va_context->driver, vaStatus, "vaUnmapBuffer()");
+  }
+  if(p_base_this) {
+    vaStatus = vaUnmapBuffer(va_context->va_display, va_image_this.buf);
+    vaapi_check_status(va_context->driver, vaStatus, "vaUnmapBuffer()");
+  }
+
+  vaapi_destroy_image(va_context->driver, &va_image_orig);
+  vaapi_destroy_image(va_context->driver, &va_image_this);
+
+  XUnlockDisplay(driver->display);
+  pthread_mutex_unlock(&driver->vaapi_lock);
+}
+
+static void vaapi_update_frame_format (vo_driver_t *this_gen,
+    vo_frame_t *frame_gen,
+    uint32_t width, uint32_t height,
+    double ratio, int format, int flags) {
+  vaapi_driver_t      *this       = (vaapi_driver_t *) this_gen;
+  vaapi_frame_t       *frame      = (vaapi_frame_t*)frame_gen;
+  vaapi_accel_t       *accel      = &frame->vaapi_accel_data;
+
+  lprintf("vaapi_update_frame_format\n");
+
+  pthread_mutex_lock(&this->vaapi_lock);
+  XLockDisplay(this->display);
+
+  lprintf("vaapi_update_frame_format %s %s width %d height %d\n",
+        (frame->format == XINE_IMGFMT_VAAPI) ? "XINE_IMGFMT_VAAPI" : ((frame->format == XINE_IMGFMT_YV12) ? "XINE_IMGFMT_YV12" : "XINE_IMGFMT_YUY2") ,
+        (format == XINE_IMGFMT_VAAPI) ? "XINE_IMGFMT_VAAPI" : ((format == XINE_IMGFMT_YV12) ? "XINE_IMGFMT_YV12" : "XINE_IMGFMT_YUY2") ,
+        width, height);
+
+  frame->vo_frame.width = width;
+  frame->vo_frame.height = height;
+
+  if ((frame->width != width)
+      || (frame->height != height)
+      || (frame->format != format)) {
+
+    // (re-) allocate render space
+    av_freep (&frame->vo_frame.base[0]);
+    av_freep (&frame->vo_frame.base[1]);
+    av_freep (&frame->vo_frame.base[2]);
+
+    /* set init_vaapi on frame formats XINE_IMGFMT_YV12/XINE_IMGFMT_YUY2 only.
+     * for XINE_IMGFMT_VAAPI the init was already done.
+     */
+    if (format == XINE_IMGFMT_YV12) {
+      frame->vo_frame.pitches[0] = 8*((width + 7) / 8);
+      frame->vo_frame.pitches[1] = 8*((width + 15) / 16);
+      frame->vo_frame.pitches[2] = 8*((width + 15) / 16);
+      frame->vo_frame.base[0] = av_mallocz (frame->vo_frame.pitches[0] * height + FF_INPUT_BUFFER_PADDING_SIZE);
+      frame->vo_frame.base[1] = av_mallocz (frame->vo_frame.pitches[1] * ((height+1)/2) + FF_INPUT_BUFFER_PADDING_SIZE);
+      frame->vo_frame.base[2] = av_mallocz (frame->vo_frame.pitches[2] * ((height+1)/2) + FF_INPUT_BUFFER_PADDING_SIZE);
+      frame->vo_frame.proc_duplicate_frame_data = NULL;
+      frame->vo_frame.proc_provide_standard_frame_data = NULL;
+      lprintf("XINE_IMGFMT_YV12 width %d height %d\n", width, height);
+    } else if (format == XINE_IMGFMT_YUY2){
+      frame->vo_frame.pitches[0] = 8*((width + 3) / 4);
+      frame->vo_frame.base[0] = av_mallocz (frame->vo_frame.pitches[0] * height + FF_INPUT_BUFFER_PADDING_SIZE);
+      frame->vo_frame.proc_duplicate_frame_data = NULL;
+      frame->vo_frame.proc_provide_standard_frame_data = NULL;
+      lprintf("XINE_IMGFMT_YUY2 width %d height %d\n", width, height);
+    } else if (format == XINE_IMGFMT_VAAPI) {
+      frame->vo_frame.proc_duplicate_frame_data = vaapi_duplicate_frame_data;
+      frame->vo_frame.proc_provide_standard_frame_data = vaapi_provide_standard_frame_data;
+      lprintf("XINE_IMGFMT_VAAPI width %d height %d\n", width, height);
+    }
+
+    frame->width  = width;
+    frame->height = height;
+    frame->format = format;
+    frame->flags  = flags;
+    vaapi_frame_field ((vo_frame_t *)frame, flags);
+  }
+
+  if(this->guarded_render) {
+    ff_vaapi_surface_t *va_surface = &va_render_surfaces[accel->index];
+
+    if(va_surface->status == SURFACE_RENDER_RELEASE) {
+      va_surface->status = SURFACE_FREE;
+#ifdef DEBUG_SURFACE
+      printf("release_surface vaapi_update_frame_format 0x%08x\n", va_surface->va_surface_id);
+#endif
+    } else if(va_surface->status == SURFACE_RENDER) {
+      va_surface->status = SURFACE_RELEASE;
+#ifdef DEBUG_SURFACE
+      printf("release_surface vaapi_update_frame_format 0x%08x\n", va_surface->va_surface_id);
+#endif
+    }
+  }
+
+  XUnlockDisplay(this->display);
+  pthread_mutex_unlock(&this->vaapi_lock);
+
+  frame->ratio  = ratio;
+  frame->vo_frame.future_frame = NULL;
+}
+
+static inline uint8_t clip_uint8_vlc( int32_t a )
+{
+  if( a&(~255) ) return (-a)>>31;
+  else           return a;
+}
+
+
+static void nv12_to_yv12(const uint8_t *y_src,  int y_src_pitch,
+                         const uint8_t *uv_src, int uv_src_pitch,
+                         uint8_t *y_dst, int y_dst_pitch,
+                         uint8_t *u_dst, int u_dst_pitch,
+                         uint8_t *v_dst, int v_dst_pitch,
+                         int src_width, int src_height,
+                         int dst_width, int dst_height,
+                         int src_data_size) {
+
+  int y_src_size  = src_height * y_src_pitch;
+  int y, x;
+
+  int uv_src_size = src_height * uv_src_pitch / 2;
+  if((y_src_size + uv_src_size) != (src_data_size))
+    printf("nv12_to_yv12 strange %d\n", (y_src_size + uv_src_size) - (src_data_size));
+
+  int height  = (src_height > dst_height) ? dst_height : src_height;
+  int width   = (src_width > dst_width) ? dst_width : src_width;
+
+  for(y = 0; y < height; y++) {
+    xine_fast_memcpy(y_dst, y_src, width);
+    y_src += y_src_pitch;
+    y_dst += y_dst_pitch;
+  }
+
+  for(y = 0; y < height; y++) {
+    const uint8_t *uv_src_tmp = uv_src;
+    for(x = 0; x < u_dst_pitch; x++) {
+      if(((y * uv_src_pitch) + x) < uv_src_size) {
+        *(u_dst + x) = *(uv_src_tmp    );
+        *(v_dst + x) = *(uv_src_tmp + 1);
+      }
+      uv_src_tmp += 2;
+    }
+    uv_src += uv_src_pitch;
+    u_dst += u_dst_pitch;
+    v_dst += v_dst_pitch;
+  }
+}
+
+static void yv12_to_nv12(const uint8_t *y_src, int y_src_pitch,
+                         const uint8_t *u_src, int u_src_pitch,
+                         const uint8_t *v_src, int v_src_pitch,
+                         uint8_t *y_dst,  int y_dst_pitch,
+                         uint8_t *uv_dst, int uv_dst_pitch,
+                         int src_width, int src_height,
+                         int dst_width, int dst_height,
+                         int dst_data_size) {
+
+  int y_dst_size  = dst_height * y_dst_pitch;
+  int y, x;
+
+  lprintf("yv12_to_nv12 converter\n");
+
+  int uv_dst_size = dst_height * uv_dst_pitch / 2;
+  if((y_dst_size + uv_dst_size) != (dst_data_size))
+    printf("yv12_to_nv12 strange %d\n", (y_dst_size + uv_dst_size) - (dst_data_size));
+
+  int height  = (src_height > dst_height) ? dst_height : src_height;
+  int width   = (src_width > dst_width) ? dst_width : src_width;
+
+  for(y = 0; y < height; y++) {
+    xine_fast_memcpy(y_dst, y_src, width);
+    y_src += y_src_pitch;
+    y_dst += y_dst_pitch;
+  }
+
+  for(y = 0; y < height; y++) {
+    uint8_t *uv_dst_tmp = uv_dst;
+    for(x = 0; x < u_src_pitch; x++) {
+      if(((y * uv_dst_pitch) + x) < uv_dst_size) {
+        *(uv_dst_tmp    ) = *(u_src + x);
+        *(uv_dst_tmp + 1) = *(v_src + x);
+      }
+      uv_dst_tmp += 2;
+    }
+    uv_dst += uv_dst_pitch;
+    u_src += u_src_pitch;
+    v_src += v_src_pitch;
+  }
+}
+
+static VAStatus vaapi_software_render_frame(vo_driver_t *this_gen, vo_frame_t *frame_gen,
+                                             VAImage *va_image, VASurfaceID va_surface_id) {
+  vaapi_driver_t     *this            = (vaapi_driver_t *) this_gen;
+  vaapi_frame_t      *frame           = (vaapi_frame_t *) frame_gen;
+  ff_vaapi_context_t *va_context      = this->va_context;
+  void               *p_base          = NULL;
+  VAStatus           vaStatus;
+
+  if(va_image == NULL || va_image->image_id == VA_INVALID_ID ||
+     va_surface_id == VA_INVALID_SURFACE || !va_context->valid_context)
+    return VA_STATUS_ERROR_UNKNOWN;
+
+  lprintf("vaapi_software_render_frame : va_surface_id 0x%08x va_image.image_id 0x%08x width %d height %d f_width %d f_height %d sw_width %d sw_height %d\n",
+      va_surface_id, va_image->image_id, va_image->width, va_image->height, frame->width, frame->height,
+      va_context->sw_width, va_context->sw_height);
+
+  if(frame->width != va_image->width || frame->height != va_image->height)
+    return VA_STATUS_SUCCESS;
+
+  vaStatus = vaMapBuffer( va_context->va_display, va_image->buf, &p_base ) ;
+  if(!vaapi_check_status(va_context->driver, vaStatus, "vaMapBuffer()"))
+    return vaStatus;
+
+
+  uint8_t *dst[3] = { NULL, };
+  uint32_t  pitches[3];
+
+  if(this->swap_uv_planes) {
+    dst[0] = (uint8_t *)p_base + va_image->offsets[0]; pitches[0] = va_image->pitches[0];
+    dst[1] = (uint8_t *)p_base + va_image->offsets[1]; pitches[1] = va_image->pitches[1];
+    dst[2] = (uint8_t *)p_base + va_image->offsets[2]; pitches[2] = va_image->pitches[2];
+  } else {
+    dst[0] = (uint8_t *)p_base + va_image->offsets[0]; pitches[0] = va_image->pitches[0];
+    dst[1] = (uint8_t *)p_base + va_image->offsets[2]; pitches[1] = va_image->pitches[1];
+    dst[2] = (uint8_t *)p_base + va_image->offsets[1]; pitches[2] = va_image->pitches[2];
+  }
+
+  /* Copy xine frames into VAAPI images */
+  if(frame->format == XINE_IMGFMT_YV12) {
+
+    if (va_image->format.fourcc == VA_FOURCC( 'Y', 'V', '1', '2' ) ||
+        va_image->format.fourcc == VA_FOURCC( 'I', '4', '2', '0' ) ) {
+      lprintf("vaapi_software_render_frame yv12 -> yv12 convert\n");
+
+      yv12_to_yv12(
+              /* Y */
+              frame_gen->base[0], frame_gen->pitches[0],
+              dst[0], pitches[0],
+              /* U */
+              frame_gen->base[1], frame_gen->pitches[1],
+              dst[1], pitches[1],
+              /* V */
+              frame_gen->base[2], frame_gen->pitches[2],
+              dst[2], pitches[2],
+              /* width x height */
+              frame_gen->width, frame_gen->height);
+
+    } else if (va_image->format.fourcc == VA_FOURCC( 'N', 'V', '1', '2' )) {
+      lprintf("vaapi_software_render_frame yv12 -> nv12 convert\n");
+
+      yv12_to_nv12(frame_gen->base[0], frame_gen->pitches[0],
+                   frame_gen->base[1], frame_gen->pitches[1],
+                   frame_gen->base[2], frame_gen->pitches[2],
+                   (uint8_t *)p_base + va_image->offsets[0], va_image->pitches[0],
+                   (uint8_t *)p_base + va_image->offsets[1], va_image->pitches[1],
+                   frame_gen->width, frame_gen->height,
+                   va_image->width,  va_image->height,
+                   va_image->data_size);
+
+    }
+  } else if (frame->format == XINE_IMGFMT_YUY2) {
+
+    if (va_image->format.fourcc == VA_FOURCC( 'Y', 'V', '1', '2' ) ||
+        va_image->format.fourcc == VA_FOURCC( 'I', '4', '2', '0' ) ) {
+      lprintf("vaapi_software_render_frame yuy2 -> yv12 convert\n");
+
+      yuy2_to_yv12(frame_gen->base[0], frame_gen->pitches[0],
+                  dst[0], pitches[0],
+                  dst[1], pitches[1],
+                  dst[2], pitches[2],
+                  frame_gen->width, frame_gen->height);
+
+    } else if (va_image->format.fourcc == VA_FOURCC( 'N', 'V', '1', '2' )) {
+      lprintf("vaapi_software_render_frame yuy2 -> nv12 convert\n");
+      printf("yuy2 -> nv12 convert missing\n");
+    }
+
+  }
+
+  vaStatus = vaUnmapBuffer(va_context->va_display, va_image->buf);
+  vaapi_check_status(this_gen, vaStatus, "vaUnmapBuffer()");
+
+  if(!va_context->is_bound) {
+    vaStatus = vaPutImage(va_context->va_display, va_surface_id, va_image->image_id,
+                        0, 0, va_image->width, va_image->height,
+                        0, 0, va_image->width, va_image->height);
+  }
+
+  if(!vaapi_check_status(va_context->driver, vaStatus, "vaPutImage()"))
+    return vaStatus;
+
+  return VA_STATUS_SUCCESS;
+}
+
+static VAStatus vaapi_hardware_render_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen,
+                                             VASurfaceID va_surface_id) {
+  vaapi_driver_t     *this            = (vaapi_driver_t *) this_gen;
+  vaapi_frame_t      *frame           = (vaapi_frame_t *) frame_gen;
+  ff_vaapi_context_t *va_context      = this->va_context;
+  VAStatus           vaStatus         = VA_STATUS_ERROR_UNKNOWN;
+  int                i                = 0;
+  int                interlaced_frame = !frame->vo_frame.progressive_frame;
+  int                top_field_first  = frame->vo_frame.top_field_first;
+  int                width, height;
+
+  if(frame->format == XINE_IMGFMT_VAAPI) {
+    width  = va_context->width;
+    height = va_context->height;
+  } else {
+    width  = (frame->width > va_context->sw_width) ? va_context->sw_width : frame->width;
+    height = (frame->height > va_context->sw_height) ? va_context->sw_height : frame->height;
+  }
+
+  if(!va_context->valid_context || va_surface_id == VA_INVALID_SURFACE)
+    return VA_STATUS_ERROR_UNKNOWN;
+
+  if(this->opengl_render && !this->valid_opengl_context)
+    return VA_STATUS_ERROR_UNKNOWN;
+
+  /* Final VAAPI rendering. The deinterlacing can be controled by xine config.*/
+  unsigned int deint = this->deinterlace;
+  for(i = 0; i <= !!((deint > 1) && interlaced_frame); i++) {
+    unsigned int flags = (deint && (interlaced_frame) ? (((!!(top_field_first)) ^ i) == 0 ? VA_BOTTOM_FIELD : VA_TOP_FIELD) : VA_FRAME_PICTURE);
+
+    //flags |= vaapi_get_colorspace_flags(this_gen);
+
+    flags |= VA_CLEAR_DRAWABLE;
+    flags |= this->scaling_level;
+
+    lprintf("Putsrfc srfc 0x%08X flags 0x%08x %dx%d -> %dx%d interlaced %d top_field_first %d\n",
+            va_surface_id, flags, width, height,
+            this->sc.output_width, this->sc.output_height,
+            interlaced_frame, top_field_first);
+
+    if(this->opengl_render) {
+
+      vaapi_x11_trap_errors();
+
+      if(this->opengl_use_tfp) {
+        lprintf("opengl render tfp\n");
+        vaStatus = vaPutSurface(va_context->va_display, va_surface_id, this->gl_image_pixmap,
+                 0, 0, width, height, 0, 0, width, height, NULL, 0, flags);
+        if(!vaapi_check_status(this_gen, vaStatus, "vaPutSurface()"))
+          return vaStatus;
+      } else {
+        lprintf("opengl render\n");
+        vaStatus = vaCopySurfaceGLX(va_context->va_display, va_context->gl_surface, va_surface_id, flags);
+        if(!vaapi_check_status(this_gen, vaStatus, "vaCopySurfaceGLX()"))
+          return vaStatus;
+      }
+      if(vaapi_x11_untrap_errors())
+        return VA_STATUS_ERROR_UNKNOWN;
+      
+      vaapi_glx_flip_page(frame_gen, 0, 0, va_context->width, va_context->height);
+
+    } else {
+
+      vaStatus = vaPutSurface(va_context->va_display, va_surface_id, this->window,
+                   0, 0, width, height,
+                   this->sc.output_xoffset, this->sc.output_yoffset,
+                   this->sc.output_width, this->sc.output_height,
+                   NULL, 0, flags);
+      if(!vaapi_check_status(this_gen, vaStatus, "vaPutSurface()"))
+        return vaStatus;
+    }
+  }
+  return VA_STATUS_SUCCESS;
+}
+
+/* Used in vaapi_display_frame to determine how long displaying a frame takes
+   - if slower than 60fps, print a message
+*/
+/*
+static double timeOfDay()
+{
+    struct timeval t;
+    gettimeofday( &t, NULL );
+    return ((double)t.tv_sec) + (((double)t.tv_usec)/1000000.0);
+}
+*/
+
+static void vaapi_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
+  vaapi_driver_t     *this          = (vaapi_driver_t *) this_gen;
+  vaapi_frame_t      *frame         = (vaapi_frame_t *) frame_gen;
+  vaapi_accel_t      *accel         = &frame->vaapi_accel_data;
+  ff_vaapi_context_t *va_context    = this->va_context;
+  ff_vaapi_surface_t *va_surface    = &va_render_surfaces[accel->index];
+  VASurfaceID        va_surface_id  = VA_INVALID_SURFACE;
+  VAImage            *va_image      = NULL;
+  VAStatus           vaStatus;
+
+  lprintf("vaapi_display_frame\n");
+
+  /*
+  if((frame->height < 17 || frame->width < 17) && ((frame->format == XINE_IMGFMT_YV12) || (frame->format == XINE_IMGFMT_YUY2))) {
+    frame->vo_frame.free( frame_gen );
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " frame size to small width %d height %d\n", frame->height, frame->width);
+    return;
+  }
+  */
+
+  /*
+   * let's see if this frame is different in size / aspect
+   * ratio from the previous one
+   */
+
+  if ( (frame->width != this->sc.delivered_width)
+       || (frame->height != this->sc.delivered_height)
+       || (frame->ratio != this->sc.delivered_ratio)
+       || (frame->vo_frame.crop_left != this->sc.crop_left)
+       || (frame->vo_frame.crop_right != this->sc.crop_right)
+       || (frame->vo_frame.crop_top != this->sc.crop_top)
+       || (frame->vo_frame.crop_bottom != this->sc.crop_bottom) ) {
+    lprintf("frame format changed\n");
+    this->sc.force_redraw = 1;
+  }
+
+  /*
+   * tell gui that we are about to display a frame,
+   * ask for offset and output size
+   */
+  this->sc.delivered_height = frame->height;
+  this->sc.delivered_width  = frame->width;
+  this->sc.delivered_ratio  = frame->ratio;
+  this->sc.crop_left        = frame->vo_frame.crop_left;
+  this->sc.crop_right       = frame->vo_frame.crop_right;
+  this->sc.crop_top         = frame->vo_frame.crop_top;
+  this->sc.crop_bottom      = frame->vo_frame.crop_bottom;
+
+  /*
+   * tell gui that we are about to display a frame,
+   * ask for offset and output size
+   */
+  this->sc.delivered_height = frame->height;
+  this->sc.delivered_width  = frame->width;
+  this->sc.delivered_ratio  = frame->ratio;
+
+  this->sc.crop_left        = frame->vo_frame.crop_left;
+  this->sc.crop_right       = frame->vo_frame.crop_right;
+  this->sc.crop_top         = frame->vo_frame.crop_top;
+  this->sc.crop_bottom      = frame->vo_frame.crop_bottom;
+
+  pthread_mutex_lock(&this->vaapi_lock);
+  XLockDisplay(this->display);
+
+  lprintf("vaapi_display_frame %s frame->width %d frame->height %d va_context->sw_width %d va_context->sw_height %d valid_context %d\n",
+        (frame->format == XINE_IMGFMT_VAAPI) ? "XINE_IMGFMT_VAAPI" : ((frame->format == XINE_IMGFMT_YV12) ? "XINE_IMGFMT_YV12" : "XINE_IMGFMT_YUY2") ,
+        frame->width, frame->height, va_context->sw_width, va_context->sw_height, va_context->valid_context);
+
+  if( ((frame->format == XINE_IMGFMT_YV12) || (frame->format == XINE_IMGFMT_YUY2))
+      && ((frame->width != va_context->sw_width) ||(frame->height != va_context->sw_height )) ) {
+
+    lprintf("vaapi_display_frame %s frame->width %d frame->height %d\n",
+        (frame->format == XINE_IMGFMT_VAAPI) ? "XINE_IMGFMT_VAAPI" : ((frame->format == XINE_IMGFMT_YV12) ? "XINE_IMGFMT_YV12" : "XINE_IMGFMT_YUY2") ,
+        frame->width, frame->height);
+
+    unsigned int last_sub_img_fmt = va_context->last_sub_image_fmt;
+
+    if(last_sub_img_fmt)
+      vaapi_ovl_associate(this_gen, frame_gen->format, 0);
+
+    if(!va_context->valid_context) {
+      lprintf("vaapi_display_frame init full context\n");
+      vaapi_init_internal(frame_gen->driver, SW_CONTEXT_INIT_FORMAT, frame->width, frame->height, 0);
+    } else {
+      lprintf("vaapi_display_frame init soft surfaces\n");
+      vaapi_init_soft_surfaces(frame_gen->driver, frame->width, frame->height);
+    }
+
+    this->sc.force_redraw = 1;
+    this->init_opengl_render = 1;
+
+    if(last_sub_img_fmt)
+      vaapi_ovl_associate(this_gen, frame_gen->format, this->has_overlay);
+  }
+
+  XUnlockDisplay(this->display);
+  pthread_mutex_unlock(&this->vaapi_lock);
+
+  vaapi_redraw_needed (this_gen);
+
+  /* posible race could happen while the lock is opened */
+  if(!this->va_context || !this->va_context->valid_context)
+    return;
+
+  pthread_mutex_lock(&this->vaapi_lock);
+  XLockDisplay(this->display);
+
+  /* initialize opengl rendering */
+  if(this->opengl_render && this->init_opengl_render &&  va_context->valid_context) {
+    unsigned int last_sub_img_fmt = va_context->last_sub_image_fmt;
+
+    if(last_sub_img_fmt)
+      vaapi_ovl_associate(this_gen, frame_gen->format, 0);
+
+    destroy_glx(this_gen);
+
+    vaapi_glx_config_glx(frame_gen->driver, va_context->width, va_context->height);
+
+    vaapi_resize_glx_window(frame_gen->driver, this->sc.gui_width, this->sc.gui_height);
+
+    if(last_sub_img_fmt)
+      vaapi_ovl_associate(this_gen, frame_gen->format, this->has_overlay);
+
+    this->sc.force_redraw = 1;
+    this->init_opengl_render = 0;
+  }
+
+  /*
+  double start_time;
+  double end_time;
+  double elapse_time;
+  int factor;
+
+  start_time = timeOfDay();
+  */
+
+  if(va_context->valid_context && ( (frame->format == XINE_IMGFMT_VAAPI) || (frame->format == XINE_IMGFMT_YV12) || (frame->format == XINE_IMGFMT_YUY2) )) {
+
+    if((frame->format == XINE_IMGFMT_YUY2) || (frame->format == XINE_IMGFMT_YV12)) {
+      va_surface_id = va_soft_surface_ids[va_context->va_soft_head];
+      va_image = &va_soft_images[va_context->va_soft_head];
+      va_context->va_soft_head = (va_context->va_soft_head + 1) % (SOFT_SURFACES);
+    }
+
+    if(this->guarded_render) {
+      if(frame->format == XINE_IMGFMT_VAAPI) {
+        ff_vaapi_surface_t *va_surface = &va_render_surfaces[accel->index];
+        if(va_surface->status == SURFACE_RENDER || va_surface->status == SURFACE_RENDER_RELEASE) {
+          va_surface_id = va_surface->va_surface_id;
+        }
+        va_image      = NULL;
+      }
+#ifdef DEBUG_SURFACE
+      printf("vaapi_display_frame va_surface 0x%08x status %d index %d\n", va_surface_id, va_surface->status, accel->index);
+#endif
+    } else {
+      if(frame->format == XINE_IMGFMT_VAAPI) {
+        va_surface_id = va_surface->va_surface_id;
+        va_image      = NULL;
+      }
+    }
+
+    lprintf("2: 0x%08x\n", va_surface_id);
+
+    VASurfaceStatus surf_status = 0;
+    if(va_surface_id != VA_INVALID_SURFACE) {
+
+      if(this->query_va_status) {
+        vaStatus = vaQuerySurfaceStatus(va_context->va_display, va_surface_id, &surf_status);
+        vaapi_check_status(this_gen, vaStatus, "vaQuerySurfaceStatus()");
+      } else {
+        surf_status = VASurfaceReady;
+      }
+
+      if(surf_status != VASurfaceReady) {
+        va_surface_id = VA_INVALID_SURFACE;
+        va_image = NULL;
+#ifdef DEBUG_SURFACE
+        printf("Surface srfc 0x%08X not ready for render\n", va_surface_id);
+#endif
+      }
+    } else {
+#ifdef DEBUG_SURFACE
+      printf("Invalid srfc 0x%08X\n", va_surface_id);
+#endif
+    }
+
+    if(va_surface_id != VA_INVALID_SURFACE) {
+
+      lprintf("vaapi_display_frame: 0x%08x %d %d\n", va_surface_id, va_context->width, va_context->height);
+    
+      vaStatus = vaSyncSurface(va_context->va_display, va_surface_id);
+      vaapi_check_status(this_gen, vaStatus, "vaSyncSurface()");
+
+      /* transfer image data to a VAAPI surface */
+      if((frame->format == XINE_IMGFMT_YUY2 || frame->format == XINE_IMGFMT_YV12))
+        vaapi_software_render_frame(this_gen, frame_gen, va_image, va_surface_id);
+
+      vaapi_hardware_render_frame(this_gen, frame_gen, va_surface_id);
+
+    }
+  } else {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " unsupported image format %s width %d height %d valid_context %d\n",
+        (frame->format == XINE_IMGFMT_VAAPI) ? "XINE_IMGFMT_VAAPI" : ((frame->format == XINE_IMGFMT_YV12) ? "XINE_IMGFMT_YV12" : "XINE_IMGFMT_YUY2") ,
+        frame->width, frame->height, va_context->valid_context);
+  }
+
+  XSync(this->display, False);
+
+  //end_time = timeOfDay();
+
+  if(this->guarded_render) {
+    ff_vaapi_surface_t *va_surface = &va_render_surfaces[accel->index];
+
+    if(va_surface->status == SURFACE_RENDER_RELEASE) {
+      va_surface->status = SURFACE_FREE;
+#ifdef DEBUG_SURFACE
+      printf("release_surface vaapi_display_frame 0x%08x\n", va_surface->va_surface_id);
+#endif
+    } else if(va_surface->status == SURFACE_RENDER) {
+      va_surface->status = SURFACE_RELEASE;
+#ifdef DEBUG_SURFACE
+      printf("release_surface vaapi_display_frame 0x%08x\n", va_surface->va_surface_id);
+#endif
+    }
+  }
+
+  XUnlockDisplay(this->display);
+
+  frame->vo_frame.free( frame_gen );
+
+  pthread_mutex_unlock(&this->vaapi_lock);
+
+  /*
+  elapse_time = end_time - start_time;
+  factor = (int)(elapse_time/(1.0/60.0));
+
+  if( factor > 1 )
+  {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " PutImage %dX interval (%fs)\n", factor, elapse_time );
+  }
+  */
+}
+
+static int vaapi_get_property (vo_driver_t *this_gen, int property) {
+  vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
+
+  switch (property) {
+    case VO_PROP_WINDOW_WIDTH:
+      this->props[property].value = this->sc.gui_width;
+      break;
+    case VO_PROP_WINDOW_HEIGHT:
+      this->props[property].value = this->sc.gui_height;
+      break;
+    case VO_PROP_OUTPUT_WIDTH:
+      this->props[property].value = this->sc.output_width;
+      break;
+    case VO_PROP_OUTPUT_HEIGHT:
+      this->props[property].value = this->sc.output_height;
+      break;
+    case VO_PROP_OUTPUT_XOFFSET:
+      this->props[property].value = this->sc.output_xoffset;
+      break;
+    case VO_PROP_OUTPUT_YOFFSET:
+      this->props[property].value = this->sc.output_yoffset;
+      break;
+    case VO_PROP_MAX_NUM_FRAMES:
+      if(!this->guarded_render)
+        this->props[property].value = RENDER_SURFACES;
+      else
+        this->props[property].value = 2;
+      break;
+  }
+
+  lprintf("vaapi_get_property property=%d, value=%d\n", property, this->props[property].value );
+
+  return this->props[property].value;
+}
+
+static int vaapi_set_property (vo_driver_t *this_gen, int property, int value) {
+
+  vaapi_driver_t      *this       = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+
+  lprintf("vaapi_set_property property=%d, value=%d\n", property, value );
+
+  if(this->props[property].atom) {
+    VADisplayAttribute attr;
+
+    if((value < this->props[property].min) || (value > this->props[property].max))
+      value = (this->props[property].min + this->props[property].max) >> 1;
+
+    this->props[property].value = value;
+    attr.type   = this->props[property].type;
+    attr.value  = value;
+
+    if(va_context && va_context->valid_context) {
+      VAStatus vaStatus = vaSetDisplayAttributes(va_context->va_display, &attr, 1);
+      vaapi_check_status((vo_driver_t *)this, vaStatus, "vaSetDisplayAttributes()");
+    }
+
+    if (this->props[property].entry)
+      this->props[property].entry->num_value = this->props[property].value;
+
+    vaapi_show_display_props((vo_driver_t*)this);
+
+    return this->props[property].value;
+  } else {
+    switch (property) {
+
+      case VO_PROP_ASPECT_RATIO:
+        if (value>=XINE_VO_ASPECT_NUM_RATIOS)
+        value = XINE_VO_ASPECT_AUTO;
+        this->props[property].value = value;
+        this->sc.user_ratio = value;
+        _x_vo_scale_compute_ideal_size (&this->sc);
+        this->sc.force_redraw = 1;
+        break;
+
+      case VO_PROP_ZOOM_X:
+        if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) {
+          this->props[property].value = value;
+        this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP;
+          _x_vo_scale_compute_ideal_size (&this->sc);
+          this->sc.force_redraw = 1;
+        }
+        break;
+
+      case VO_PROP_ZOOM_Y:
+        if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) {
+          this->props[property].value = value;
+          this->sc.zoom_factor_y = (double)value / (double)XINE_VO_ZOOM_STEP;
+        _x_vo_scale_compute_ideal_size (&this->sc);
+        this->sc.force_redraw = 1;
+        }
+        break;
+    }
+  }
+  return value;
+}
+
+static void vaapi_get_property_min_max (vo_driver_t *this_gen,
+     int property, int *min, int *max) {
+  vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
+
+  *min = this->props[property].min;
+  *max = this->props[property].max;
+}
+
+static int vaapi_gui_data_exchange (vo_driver_t *this_gen,
+ int data_type, void *data) {
+  vaapi_driver_t     *this       = (vaapi_driver_t *) this_gen;
+
+  lprintf("vaapi_gui_data_exchange %d\n", data_type);
+
+  switch (data_type) {
+#ifndef XINE_DISABLE_DEPRECATED_FEATURES
+  case XINE_GUI_SEND_COMPLETION_EVENT:
+    break;
+#endif
+
+  case XINE_GUI_SEND_EXPOSE_EVENT: {
+    pthread_mutex_lock(&this->vaapi_lock);
+    XLockDisplay( this->display );
+    lprintf("XINE_GUI_SEND_EXPOSE_EVENT:\n");
+    this->sc.force_redraw = 1;
+    this->init_opengl_render = 1;
+    XUnlockDisplay( this->display );
+    pthread_mutex_unlock(&this->vaapi_lock);
+  }
+  break;
+
+  case XINE_GUI_SEND_WILL_DESTROY_DRAWABLE: {
+    printf("XINE_GUI_SEND_WILL_DESTROY_DRAWABLE\n");
+  }
+  break;
+
+  case XINE_GUI_SEND_DRAWABLE_CHANGED: {
+    pthread_mutex_lock(&this->vaapi_lock);
+    XLockDisplay( this->display );
+    lprintf("XINE_GUI_SEND_DRAWABLE_CHANGED\n");
+
+    this->drawable = (Drawable) data;
+
+    XReparentWindow(this->display, this->window, this->drawable, 0, 0);
+
+    this->sc.force_redraw = 1;
+    this->init_opengl_render = 1;
+
+    XUnlockDisplay( this->display );
+    pthread_mutex_unlock(&this->vaapi_lock);
+  }
+  break;
+
+  case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO: {
+    int x1, y1, x2, y2;
+    x11_rectangle_t *rect = data;
+
+    _x_vo_scale_translate_gui2video(&this->sc, rect->x, rect->y, &x1, &y1);
+    _x_vo_scale_translate_gui2video(&this->sc, rect->x + rect->w, rect->y + rect->h, &x2, &y2);
+    rect->x = x1;
+    rect->y = y1;
+    rect->w = x2-x1;
+    rect->h = y2-y1;
+  }
+  break;
+
+  default:
+    return -1;
+  }
+
+  return 0;
+}
+
+static void vaapi_dispose (vo_driver_t *this_gen) {
+  vaapi_driver_t      *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+
+  lprintf("vaapi_dispose\n");
+
+  pthread_mutex_lock(&this->vaapi_lock);
+  XLockDisplay(this->display);
+
+  this->ovl_yuv2rgb->dispose(this->ovl_yuv2rgb);
+  this->yuv2rgb_factory->dispose (this->yuv2rgb_factory);
+
+  vaapi_close(this_gen);
+  free(va_context);
+
+  if(this->overlay_bitmap)
+    free(this->overlay_bitmap);
+
+  if(va_surface_ids)
+    free(va_surface_ids);
+  if(va_soft_surface_ids)
+    free(va_soft_surface_ids);
+  if(va_render_surfaces)
+    free(va_render_surfaces);
+  if(va_soft_images)
+    free(va_soft_images);
+
+  XDestroyWindow(this->display, this->window);
+  XUnlockDisplay(this->display);
+
+  pthread_mutex_unlock(&this->vaapi_lock);
+  pthread_mutex_destroy(&this->vaapi_lock);
+
+  free (this);
+}
+
+static void vaapi_vdr_osd_width_flag( void *this_gen, xine_cfg_entry_t *entry )
+{
+  vaapi_driver_t  *this  = (vaapi_driver_t *) this_gen;
+
+  this->vdr_osd_width = entry->num_value;
+}
+
+static void vaapi_vdr_osd_height_flag( void *this_gen, xine_cfg_entry_t *entry )
+{
+  vaapi_driver_t  *this  = (vaapi_driver_t *) this_gen;
+
+  this->vdr_osd_height = entry->num_value;
+}
+
+static void vaapi_deinterlace_flag( void *this_gen, xine_cfg_entry_t *entry )
+{
+  vaapi_driver_t  *this  = (vaapi_driver_t *) this_gen;
+
+  this->deinterlace = entry->num_value;
+  if(this->deinterlace > 2)
+    this->deinterlace = 2;
+}
+
+static void vaapi_opengl_render( void *this_gen, xine_cfg_entry_t *entry )
+{
+  vaapi_driver_t  *this  = (vaapi_driver_t *) this_gen;
+
+  this->opengl_render = entry->num_value;
+}
+
+static void vaapi_opengl_use_tfp( void *this_gen, xine_cfg_entry_t *entry )
+{
+  vaapi_driver_t  *this  = (vaapi_driver_t *) this_gen;
+
+  this->opengl_use_tfp = entry->num_value;
+}
+
+static void vaapi_guarded_render( void *this_gen, xine_cfg_entry_t *entry )
+{
+  vaapi_driver_t  *this  = (vaapi_driver_t *) this_gen;
+
+  this->guarded_render = entry->num_value;
+}
+
+static void vaapi_scaling_level( void *this_gen, xine_cfg_entry_t *entry )
+{
+  vaapi_driver_t  *this  = (vaapi_driver_t *) this_gen;
+
+  this->scaling_level = entry->num_value;
+}
+
+static void vaapi_swap_uv_planes(void *this_gen, xine_cfg_entry_t *entry)
+{
+  vaapi_driver_t  *this  = (vaapi_driver_t *) this_gen;
+
+  this->swap_uv_planes = entry->num_value;
+}
+
+static vo_driver_t *vaapi_open_plugin (video_driver_class_t *class_gen, const void *visual_gen) {
+
+  vaapi_class_t           *class  = (vaapi_class_t *) class_gen;
+  x11_visual_t            *visual = (x11_visual_t *) visual_gen;
+  vaapi_driver_t          *this;
+  config_values_t         *config = class->config;
+  XSetWindowAttributes    xswa;
+  unsigned long           xswa_mask;
+  XWindowAttributes       wattr;
+  unsigned long           black_pixel;
+  XVisualInfo             visualInfo;
+  XVisualInfo             *vi;
+  int                     depth;
+  const int               x11_event_mask = ExposureMask |
+                                           StructureNotifyMask;
+
+  this = (vaapi_driver_t *) calloc(1, sizeof(vaapi_driver_t));
+  if (!this)
+    return NULL;
+
+  this->config                  = config;
+  this->xine                    = class->xine;
+
+  this->display                 = visual->display;
+  this->screen                  = visual->screen;
+  this->drawable                = visual->d;
+
+  this->va_context              = calloc(1, sizeof(ff_vaapi_context_t));
+
+  /* number of video frames from config - register it with the default value. */
+  int frame_num = config->register_num (config, "engine.buffers.video_num_frames", RENDER_SURFACES, /* default */
+       _("default number of video frames"),
+       _("The default number of video frames to request "
+         "from xine video out driver. Some drivers will "
+         "override this setting with their own values."),
+      20, NULL, this);
+
+  /* now make sure we have at least 22 frames, to prevent
+   * locks with vdpau_h264 */
+  if(frame_num != RENDER_SURFACES)
+    config->update_num(config,"engine.buffers.video_num_frames", RENDER_SURFACES);
+
+  this->opengl_render = config->register_bool( config, "video.output.vaapi_opengl_render", 0,
+        _("vaapi: opengl output rendering"),
+        _("vaapi: opengl output rendering"),
+        20, vaapi_opengl_render, this );
+  
+  this->init_opengl_render = 1;
+
+  this->opengl_use_tfp = config->register_bool( config, "video.output.vaapi_opengl_use_tfp", 0,
+        _("vaapi: opengl rendering tfp"),
+        _("vaapi: opengl rendering tfp"),
+        20, vaapi_opengl_use_tfp, this );
+
+  if(this->opengl_render) {
+      this->opengl_render = vaapi_opengl_verify_direct ((x11_visual_t *)visual_gen);
+      if(!this->opengl_render)
+        xprintf (this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_open: Opengl indirect/software rendering does not work. Fallback to plain VAAPI output !!!!\n");
+  }
+
+  this->valid_opengl_context            = 0;
+  this->gl_vinfo                        = NULL;
+  this->gl_pixmap                       = None;
+  this->gl_image_pixmap                 = None;
+  this->gl_texture                      = GL_NONE;
+
+  this->num_frame_buffers               = 0;
+
+  va_render_surfaces                    = calloc(RENDER_SURFACES + 1, sizeof(ff_vaapi_surface_t));
+  va_surface_ids                        = calloc(RENDER_SURFACES + 1, sizeof(VASurfaceID));
+  va_soft_surface_ids                   = calloc(SOFT_SURFACES + 1, sizeof(VASurfaceID));
+  va_soft_images                        = calloc(SOFT_SURFACES + 1, sizeof(VAImage));
+
+  vaapi_init_va_context(this);
+  vaapi_init_subpicture(this);
+
+  _x_vo_scale_init (&this->sc, 1, 0, config );
+
+  this->sc.frame_output_cb      = visual->frame_output_cb;
+  this->sc.dest_size_cb         = visual->dest_size_cb;
+  this->sc.user_data            = visual->user_data;
+  this->sc.user_ratio           = XINE_VO_ASPECT_AUTO;
+
+  black_pixel         = BlackPixel(this->display, this->screen);
+
+  XGetWindowAttributes(this->display, this->drawable, &wattr);
+
+  depth = wattr.depth;
+  if (depth != 15 && depth != 16 && depth != 24 && depth != 32)
+    depth = 24;
+
+  vi = &visualInfo;
+  XMatchVisualInfo(this->display, this->screen, depth, TrueColor, vi);
+
+  xswa_mask             = CWBorderPixel | CWBackPixel | CWColormap;
+  xswa.border_pixel     = black_pixel;
+  xswa.background_pixel = black_pixel;
+  xswa.colormap         = CopyFromParent;
+
+  this->window = XCreateWindow(this->display, this->drawable,
+                             0, 0, 1, 1, 0, depth,
+                             InputOutput, vi->visual, xswa_mask, &xswa);
+
+  if(this->window == None)
+    return NULL;
+
+  XSelectInput(this->display, this->window, x11_event_mask);
+
+  XMapWindow(this->display, this->window);
+  vaapi_x11_wait_event(this->display, this->window, MapNotify);
+
+  if(vi != &visualInfo)
+    XFree(vi);
+
+  this->capabilities            = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY | VO_CAP_ARGB_LAYER_OVERLAY | VO_CAP_VAAPI | VO_CAP_CUSTOM_EXTENT_OVERLAY;
+
+  /*  overlay converter */
+  this->yuv2rgb_factory = yuv2rgb_factory_init (MODE_24_BGR, 0, NULL);
+  this->ovl_yuv2rgb = this->yuv2rgb_factory->create_converter( this->yuv2rgb_factory );
+
+  this->vo_driver.get_capabilities     = vaapi_get_capabilities;
+  this->vo_driver.alloc_frame          = vaapi_alloc_frame;
+  this->vo_driver.update_frame_format  = vaapi_update_frame_format;
+  this->vo_driver.overlay_begin        = vaapi_overlay_begin;
+  this->vo_driver.overlay_blend        = vaapi_overlay_blend;
+  this->vo_driver.overlay_end          = vaapi_overlay_end;
+  this->vo_driver.display_frame        = vaapi_display_frame;
+  this->vo_driver.get_property         = vaapi_get_property;
+  this->vo_driver.set_property         = vaapi_set_property;
+  this->vo_driver.get_property_min_max = vaapi_get_property_min_max;
+  this->vo_driver.gui_data_exchange    = vaapi_gui_data_exchange;
+  this->vo_driver.dispose              = vaapi_dispose;
+  this->vo_driver.redraw_needed        = vaapi_redraw_needed;
+
+  this->deinterlace                    = 0;
+  this->vdr_osd_width                  = 0;
+  this->vdr_osd_height                 = 0;
+
+  this->vdr_osd_width = config->register_num( config, "video.output.vaapi_vdr_osd_width", 0,
+        _("vaapi: VDR osd width workaround."),
+        _("vaapi: VDR osd width workaround."),
+        10, vaapi_vdr_osd_width_flag, this );
+
+  this->vdr_osd_height = config->register_num( config, "video.output.vaapi_vdr_osd_height", 0,
+        _("vaapi: VDR osd height workaround."),
+        _("vaapi: VDR osd height workaround."),
+        10, vaapi_vdr_osd_height_flag, this );
+
+  this->deinterlace = config->register_num( config, "video.output.vaapi_deinterlace", 0,
+        _("vaapi: set deinterlace to 0 ( none ), 1 ( top field ), 2 ( bob )."),
+        _("vaapi: set deinterlace to 0 ( none ), 1 ( top field ), 2 ( bob )."),
+        10, vaapi_deinterlace_flag, this );
+
+  this->guarded_render = config->register_num( config, "video.output.vaapi_guarded_render", 1,
+        _("vaapi: set vaapi_guarded_render to 0 ( no ) 1 ( yes )"),
+        _("vaapi: set vaapi_guarded_render to 0 ( no ) 1 ( yes )"),
+        10, vaapi_guarded_render, this );
+
+  this->scaling_level_enum = config->register_enum(config, "video.output.vaapi_scaling_level", 0,
+    (char **)scaling_level_enum_names,
+        _("vaapi: set scaling level to : default (default) fast (fast) hq (HQ) nla (anamorphic)"),
+        _("vaapi: set scaling level to : default (default) fast (fast) hq (HQ) nla (anamorphic)"),
+    10, vaapi_scaling_level, this);
+
+  this->scaling_level = scaling_level_enum_values[this->scaling_level_enum];
+
+  this->swap_uv_planes = config->register_bool( config, "video.output.vaapi_swap_uv_planes", 0,
+    _("vaapi: swap UV planes."),
+    _("vaapi: this is a workaround for buggy drivers ( intel IronLake ).\n"
+      "There the UV planes are swapped.\n"),
+    10, vaapi_swap_uv_planes, this);
+
+
+  pthread_mutex_init(&this->vaapi_lock, NULL);
+
+  pthread_mutex_lock(&this->vaapi_lock);
+
+  int i;
+  for (i = 0; i < VO_NUM_PROPERTIES; i++) {
+    this->props[i].value = 0;
+    this->props[i].min   = 0;
+    this->props[i].max   = 0;
+    this->props[i].atom  = 0;
+    this->props[i].entry = NULL;
+    this->props[i].this  = this;
+  }
+
+  this->sc.user_ratio                        =
+    this->props[VO_PROP_ASPECT_RATIO].value  = XINE_VO_ASPECT_AUTO;
+  this->props[VO_PROP_ZOOM_X].value          = 100;
+  this->props[VO_PROP_ZOOM_Y].value          = 100;
+
+  this->va_context->last_sub_surface_id      = VA_INVALID_SURFACE;
+  this->va_context->last_sub_image_fmt       = 0;
+
+  if(vaapi_init_internal((vo_driver_t *)this, SW_CONTEXT_INIT_FORMAT, SW_WIDTH, SW_HEIGHT, 0) != VA_STATUS_SUCCESS) {
+    vaapi_dispose((vo_driver_t *)this);
+    return NULL;
+  }
+  vaapi_close((vo_driver_t *)this);
+  this->va_context->valid_context = 0;
+  this->va_context->driver        = (vo_driver_t *)this;
+
+  pthread_mutex_unlock(&this->vaapi_lock);
+
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_open: Deinterlace : %d\n", this->deinterlace);
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_open: Render surfaces : %d\n", RENDER_SURFACES);
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_open: Opengl render : %d\n", this->opengl_render);
+
+  return &this->vo_driver;
+}
+
+/*
+ * class functions
+ */
+static void *vaapi_init_class (xine_t *xine, void *visual_gen) {
+  vaapi_class_t        *this = (vaapi_class_t *) calloc(1, sizeof(vaapi_class_t));
+
+  this->driver_class.open_plugin     = vaapi_open_plugin;
+  this->driver_class.identifier      = "vaapi";
+  this->driver_class.description     = N_("xine video output plugin using the MIT X video extension");
+  this->driver_class.dispose         = default_video_driver_class_dispose;
+  this->config                       = xine->config;
+  this->xine                         = xine;
+
+  return this;
+}
+
+static const vo_info_t vo_info_vaapi = {
+  9,                      /* priority    */
+  XINE_VISUAL_TYPE_X11    /* visual type */
+};
+
+/*
+ * exported plugin catalog entry
+ */
+
+const plugin_info_t xine_plugin_info[] EXPORTED = {
+  /* type, API, "name", version, special_info, init_function */
+  { PLUGIN_VIDEO_OUT, 22, "vaapi", XINE_VERSION_CODE, &vo_info_vaapi, vaapi_init_class },
+  { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+};
diff --git a/src/xine-engine/Makefile.am b/src/xine-engine/Makefile.am
index a0131a5..baed5b7 100644
--- a/src/xine-engine/Makefile.am
+++ b/src/xine-engine/Makefile.am
@@ -11,7 +11,7 @@ XINEUTILS_LIB = $(top_builddir)/src/xine-utils/libxineutils.la
 YUV_LIB = $(top_builddir)/src/video_out/libyuv2rgb.la
 
 # FIXME: these are currently unused:
-EXTRA_DIST = lrb.c lrb.h accel_vdpau.h accel_xvmc.h
+EXTRA_DIST = lrb.c lrb.h accel_vdpau.h accel_vaapi.h accel_xvmc.h
 
 if WIN32
 DEF_FILE = libxine-$(XINE_MAJOR).def
diff --git a/src/xine-engine/accel_vaapi.h b/src/xine-engine/accel_vaapi.h
new file mode 100644
index 0000000..666b23f
--- /dev/null
+++ b/src/xine-engine/accel_vaapi.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2008 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine 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.
+ *
+ * xine 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, USA
+ *
+ *
+ * Common acceleration definitions for vdpau
+ *
+ *
+ */
+
+#ifndef HAVE_XINE_ACCEL_VAAPI_H
+#define HAVE_XINE_ACCEL_VAAPI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <va/va_x11.h>
+#include <pthread.h>
+#ifdef HAVE_FFMPEG_AVUTIL_H
+#  include <avcodec.h>
+#else
+#  include <libavcodec/avcodec.h>
+#endif
+
+#if LIBAVCODEC_VERSION_MAJOR >= 53 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 32)
+#  define AVVIDEO 2
+#else
+#  define AVVIDEO 1
+#  define pp_context pp_context_t
+#  define pp_mode pp_mode_t
+#endif
+
+#define NUM_OUTPUT_SURFACES 22
+
+#define SURFACE_FREE            0
+#define SURFACE_ALOC            1
+#define SURFACE_RELEASE         2
+#define SURFACE_RENDER          3
+#define SURFACE_RENDER_RELEASE  5
+
+struct vaapi_equalizer {
+  VADisplayAttribute brightness;
+  VADisplayAttribute contrast;
+  VADisplayAttribute hue;
+  VADisplayAttribute saturation;
+};
+
+typedef struct ff_vaapi_context_s ff_vaapi_context_t;
+
+struct ff_vaapi_context_s {
+  VADisplay         va_display;
+  VAContextID       va_context_id;
+  VAConfigID        va_config_id;
+  int               width;
+  int               height;
+  int               sw_width;
+  int               sw_height;
+  int               va_profile;
+  unsigned int      va_colorspace;
+  VAImage           va_subpic_image;
+  VASubpictureID    va_subpic_id;
+  int               va_subpic_width;
+  int               va_subpic_height;
+  int               is_bound;
+  void              *gl_surface;
+  unsigned int      soft_head;
+  unsigned int      valid_context;
+  unsigned int      va_head;
+  unsigned int      va_soft_head;
+  vo_driver_t       *driver;
+  unsigned int      last_sub_image_fmt;
+  VASurfaceID       last_sub_surface_id;
+  struct vaapi_equalizer va_equalizer;
+  VAImageFormat     *va_image_formats;
+  int               va_num_image_formats;
+  VAImageFormat     *va_subpic_formats;
+  int               va_num_subpic_formats;
+};
+
+typedef struct ff_vaapi_surface_s ff_vaapi_surface_t;
+typedef struct vaapi_accel_s vaapi_accel_t;
+
+struct ff_vaapi_surface_s {
+  unsigned int        index;
+  vaapi_accel_t       *accel;
+  VASurfaceID         va_surface_id;
+  unsigned int        status;
+};
+
+struct vaapi_accel_s {
+  unsigned int        index;
+  vo_frame_t          *vo_frame;
+
+#if AVVIDEO > 1
+  int (*avcodec_decode_video2)(vo_frame_t *frame_gen, AVCodecContext *avctx, AVFrame *picture,
+                               int *got_picture_ptr, AVPacket *avpkt);
+#else
+  int (*avcodec_decode_video)(vo_frame_t *frame_gen, AVCodecContext *avctx, AVFrame *picture,
+                              int *got_picture_ptr, uint8_t *buf, int buf_size);
+#endif
+  VAStatus (*vaapi_init)(vo_frame_t *frame_gen, int va_profile, int width, int height, int softrender);
+  int (*profile_from_imgfmt)(vo_frame_t *frame_gen, enum PixelFormat pix_fmt, int codec_id, int vaapi_mpeg_sofdec);
+  ff_vaapi_context_t *(*get_context)(vo_frame_t *frame_gen);
+  int (*guarded_render)(vo_frame_t *frame_gen);
+  ff_vaapi_surface_t *(*get_vaapi_surface)(vo_frame_t *frame_gen);
+  void (*render_vaapi_surface)(vo_frame_t *frame_gen, ff_vaapi_surface_t *va_surface);
+  void (*release_vaapi_surface)(vo_frame_t *frame_gen, ff_vaapi_surface_t *va_surface);
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c
index cc42813..819e423 100644
--- a/src/xine-engine/video_out.c
+++ b/src/xine-engine/video_out.c
@@ -737,6 +737,13 @@ static vo_frame_t *vo_get_frame (xine_video_port_t *this_gen,
   return img;
 }
 
+static double tt()
+{
+  struct timeval tv;
+  gettimeofday(&tv, 0);
+  return tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0;
+}
+
 static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) {
 
   vos_t         *this = (vos_t *) img->port;
@@ -746,6 +753,30 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) {
   int            frames_to_skip;
   int            duration;
 
+/*
+if (1)
+{
+  double t1 = tt();
+  static double t0 = -1;
+  if (t0 == -1) t0 = t1;
+  double dt = t1 - t0;
+  t0 = t1;
+  static int64_t pts = 0;
+  fprintf(stderr, "img->pts: %12" PRId64 ", pts: %12" PRId64 ", img->duration: %4d, time since last vo_frame_draw: %7.3lf ms", img->pts, pts, img->duration, dt);
+  if (img->pts)
+  {
+      if (pts != img->pts)
+            fprintf(stderr, " ERROR: %12" PRId64 "", img->pts - pts);
+        pts = img->pts + img->duration;
+  }
+  else
+  {
+      pts += img->duration;
+  }
+  fprintf(stderr, "\n");
+}
+*/
+
   /* handle anonymous streams like NULL for easy checking */
   if (stream == XINE_ANON_STREAM) stream = NULL;
 


------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure contains a
definitive record of customers, application performance, security
threats, fraudulent activity and more. Splunk takes this data and makes
sense of it. Business sense. IT sense. Common sense.
http://p.sf.net/sfu/splunk-d2d-oct
_______________________________________________
xine-devel mailing list
xine-devel@...
https://lists.sourceforge.net/lists/listinfo/xine-devel

Re: VAAPI support for xine

by ebsi4711 :: Rate this Message:

| View Threaded | Show Only this Message

Updated the patch to the last changes in xine-lib-1.2 hg and also fixed the broken mpeg12 decoding.

The fix for mpeg12 you can see here standalone :


cu

Edgar (gimli) Hucek

2011/9/26 ebsi4711 <ebsi4711@...>
The VAAPI support is clear for 1.2. For the OSD it uses similiar functionality like VDPAU. ( ARGB Overlays. )
What i can say, there are no ABI changes from my side. Attached you a patch where you can see my changes
and additions. What's not done so far is the autoconf side, to check if libva is installed. There i would need help.
Libva is a must for the support in the ffmpeg decoder. To make the support optinonal would end in an ifdef mess.

cu

Edgar (gimli) Hucek


2011/9/26 Darren Salt <linux@...>
I demand that ebsi4711 may or may not have written...

> Since a while i work on VAAPI support for xine.

> The repository moved from Sourceforge to github :

> https://github.com/huceke/xine-lib-vaapi/commits/vaapi
>  and
> https://github.com/huceke/xine-lib-vaapi/commits/vaapi-testing

Would prefer this as a mercurial-format repository. However, there's
mercurial-git, which should be sufficient to make this a non-problem.

> On the decoder side the ffmpeg VAAPI support is used.
> On the output side i wrote a new plugin which is using VAAPI, The plugin
> is based on ideas found in mplayer and vdpau output plugin.

Interesting.

Any ABI or API changes (which are not merely extensions)? If there are, that
makes this 1.2-only: such changes intended for 1.1 will be rejected outright.


--
| Darren Salt  | linux or ds at  | nr. Ashington, |  _  ASCII ribbon
| using Debian | youmustbejoking | Northumberland | ( ) campaign against
| GNU/Linux    | ,demon,co,uk    |                |  X  HTML e-mail
                                                   / \ www.asciiribbon.org
No sentence fragments.

------------------------------------------------------------------------------
All of the data generated in your IT infrastructure is seriously valuable.
Why? It contains a definitive record of application performance, security
threats, fraudulent activity, and more. Splunk takes this data and makes
sense of it. IT sense. And common sense.
http://p.sf.net/sfu/splunk-d2dcopy2
_______________________________________________
xine-devel mailing list
xine-devel@...
https://lists.sourceforge.net/lists/listinfo/xine-devel



[vaapi.patch]

diff --git a/README.vaapi b/README.vaapi
new file mode 100644
index 0000000..8ba7edc
--- /dev/null
+++ b/README.vaapi
@@ -0,0 +1,97 @@
+Make sure you have the following in your ~/.xine/config.
+
+General ffmpeg settings :
+
+# Priorität für Dekoder ffmpeg-wmv8
+# numeric, default: 0
+engine.decoder_priorities.ffmpeg-wmv8:0
+
+# Priorität für Dekoder ffmpeg-wmv9
+# numeric, default: 0
+engine.decoder_priorities.ffmpeg-wmv9:0
+
+# Priorität für Dekoder ffmpegvideo
+# numeric, default: 0
+engine.decoder_priorities.ffmpegvideo:1
+
+# Priorität für Dekoder mpeg2
+# numeric, default: 0
+#engine.decoder_priorities.mpeg2:0
+
+Video out settings :
+
+#vaapi: set deinterlace to 0 ( none ), 1 ( top field ), 2 ( bob ).
+# numeric, default: 0
+#video.output.vaapi_deinterlace:0
+
+# vaapi: VDR osd height workaround.
+# numeric, default: 0
+#video.output.vaapi_vdr_osd_height:0
+
+# vaapi: VDR osd width workaround.
+# numeric, default: 0
+#video.output.vaapi_vdr_osd_width:0
+
+# VAAPI Mpeg2 softdecoding
+# bool, default: 0
+#video.processing.vaapi_mpeg_softdec:0
+
+# VAAPI Mpeg2 softdecoding deinterlace
+# bool, default: 0
+#video.processing.vaapi_mpeg_softdec_deinterlace:0
+
+# vaapi: opengl output rendering
+# bool, default: 0
+#video.output.vaapi_opengl_render:0
+
+# vaapi: opengl rendering tfp
+# bool, default: 0
+#video.output.vaapi_opengl_use_tfp:0
+
+# vaapi: set vaapi_guarded_render to 0 ( yes ) 1 ( no )
+# numeric, default: 0
+#video.output.vaapi_guarded_render:0
+
+If you see crashes set guarded render mode.
+
+# vaapi: swap UV planes.
+# bool, default: 0
+#video.output.vaapi_swap_uv_planes:0
+
+Swap UV is a workaround for IronLake chipsets where the driver is bugy.
+
+
+Notes on use with VDR. The OSD will have some delay. This is technical and can only be overcome
+writting a complete new decoder which use VAAPI direct and not ffmpeg.
+
+For using unsclaed OSD there you can overwrite the OSD size in the config file.
+
+For xineliboutput use the defaults.
+
+For vdr-xine set in VDR the OSD size to 1920x1080 and use the following in ~/.xine/config :
+
+video.output.vaapi_vdr_osd_height:0
+video.output.vaapi_vdr_osd_width:0
+
+The workaround is needed, because vdr-xine does not report the real unscaled OSD size.
+
+
+When you get GPU hangs on Mpeg2 material set :
+
+video.processing.vaapi_mpeg_softdec:1
+
+This disables VAAPI fpr Mpeg2.
+
+
+You can use example.config.vaapi as an example config for xine.
+
+Call xine like : xine -V vaapi video.mkv
+
+xvba-vaapi hints:
+
+export LIBVA_DRIVER_NAME=xvba
+export LIBVA_DRIVERS_PATH=/usr/lib/dri/
+video.output.vaapi_opengl_render:1
+
+
+Postprocessing does not work. Do not use "--post vdr_video --post vdr-audio --post vdr" in your xine call.
diff --git a/example.config.vaapi b/example.config.vaapi
new file mode 100644
index 0000000..901860b
--- /dev/null
+++ b/example.config.vaapi
@@ -0,0 +1,749 @@
+#
+# xine config file
+#
+.version:2
+
+# Entries which are still set to their default values are commented out.
+# Remove the '#' at the beginning of the line, if you want to change them.
+
+# Deinterlacing automatisch aktivieren
+# bool, default: 0
+#gui.deinterlace_by_default:0
+
+# Erfahrenheit einstellen
+# { Beginner  Advanced  Expert  Master of the known universe }, default: 0
+#gui.experience_level:Beginner
+
+# OSD-Unterstützung aktivieren
+# bool, default: 1
+#gui.osd_enabled:1
+
+# OSD Anzeigezeit [s]
+# numeric, default: 3
+#gui.osd_timeout:3
+
+# Benutzer fragen bei Wiedergabe mit nichtunterstütztem coder
+# bool, default: 0
+#gui.play_anyway:0
+
+# Automatische alte Playliste wiederherstellen
+# bool, default: 0
+#gui.playlist_auto_reload:0
+
+# Audio-Visualisierung
+# { oscope  fftscope  fftgraph  goom }, default: 0
+#gui.post_audio_plugin:oscope
+
+# gui skin Thema
+# { xinetic }, default: 0
+#gui.skin:xinetic
+
+# xine-Verhalten für unerfahrene Benutzer anpassen
+# bool, default: 1
+#gui.smart_mode:1
+
+# Schnappschußverzeichnis
+# string, default: /home/gimli
+#gui.snapshotdir:/home/gimli
+
+# Startbildschirm anzeigen
+# bool, default: 1
+#gui.splash:1
+
+# Untertitel automatisch laden
+# bool, default: 1
+#gui.subtitle_autoload:1
+
+# Stil der Videoanimation
+# { None  Post Plugin  Stream Animation }, default: 1
+#gui.visual_anim:Post Plugin
+
+# Fensterüberlagerung (mehr)
+# bool, default: 0
+#gui.always_layer_above:0
+
+# Audiomischpultmethode
+# { Sound card  Software }, default: 0
+#gui.audio_mixer_method:Sound card
+
+# Anzeigeverhalten von Bedienfeld
+# bool, default: 0
+#gui.auto_panel_visibility:0
+
+# Anzeigeverhalten des Ausgabefensters
+# bool, default: 0
+#gui.auto_video_output_visibility:0
+
+# Deinterlace-Plugin.
+# string, default: tvtime:method=LinearBlend,cheap_mode=1,pulldown=0,use_progressive_frame_flag=1
+#gui.deinterlace_plugin:tvtime:method=LinearBlend,cheap_mode=1,pulldown=0,use_progressive_frame_flag=1
+
+# Verhalten von Ereignissender
+# bool, default: 1
+#gui.eventer_sticky:1
+
+# Fensterüberlagerung
+# bool, default: 0
+#gui.layer_above:0
+
+# Unvergrößertes OSD benutzen
+# bool, default: 1
+#gui.osd_use_unscaled:1
+
+# Bildschirmschoner Resetintervall [s]
+# numeric, default: 10
+#gui.screensaver_timeout:10
+
+# Menu Tastenkürzelstil
+# { Windows style  Emacs style }, default: 0
+#gui.shortcut_style:Windows style
+
+# Datenstrominformationen
+# bool, default: 0
+#gui.sinfo_auto_update:0
+
+# Skin-Server URL
+# string, default: http://xine.sourceforge.net/skins/skins.slx
+#gui.skin_server_url:http://xine.sourceforge.net/skins/skins.slx
+
+# Kapitelspringen
+# bool, default: 1
+#gui.skip_by_chapter:1
+
+# Neue Datemstromgröße verändert Ausgabefenstergröße
+# bool, default: 1
+#gui.stream_resize_window:1
+
+# Hinweiszeit (ms)
+# numeric, default: 5000
+#gui.tips_timeout:5000
+
+# gui Hinweise sichtbar
+# bool, default: 1
+#gui.tips_visible:1
+
+# Name des Video-Bildschirms
+# string, default:
+#gui.video_display:
+
+# Synchrones X-Protokoll (Fehlersuche)
+# bool, default: 0
+#gui.xsynchronize:0
+
+# Doppelte Größe für kleine Datemströme (Erfordert stream_resize_window)
+# bool, default: 0
+#gui.zoom_small_stream:0
+
+# Logo MRL
+# string, default: /usr/share/xine/skins/xine-ui_logo.png
+#gui.logo_mrl:/usr/share/xine/skins/xine-ui_logo.png
+
+# Benutze XVidModeExtension beim Umschalten auf Vollbild
+# bool, default: 0
+#gui.use_xvidext:0
+
+# Höhe für Xinerama-Vollbildmodus (-8192 = automatisch)
+# numeric, default: -8192
+#gui.xinerama_fullscreen_height:-8192
+
+# Breite für Xinerama-Vollbildmodus (-8192 = automatisch)
+# numeric, default: -8192
+#gui.xinerama_fullscreen_width:-8192
+
+# X-Koordinate für Xinerama-Vollbildmodus (-8192 = automatisch)
+# numeric, default: -8192
+#gui.xinerama_fullscreen_x:-8192
+
+# Y-Koordinate für Xinerama-Vollbildmodus (-8192 = automatisch)
+# numeric, default: -8192
+#gui.xinerama_fullscreen_y:-8192
+
+# Zu nutzende Bildschirme im Xinerama Vollbildmodus (z.B. 0 2 3)
+# string, default: 0 1
+#gui.xinerama_use_screens:0 1
+
+# Verstärkungslevel
+# [0..200], default: 100
+#gui.amp_level:100
+
+# gui Fenster sichtbar
+# bool, default: 1
+gui.panel_visible:0
+
+# numeric, default: 200
+#gui.panel_x:200
+
+# numeric, default: 100
+#gui.panel_y:100
+
+gui.setup_x:81
+
+gui.setup_y:104
+
+# color specification yuv-opacity
+# string, default: 8080c0-f
+#gui.osdmenu.color_focused_button:8080c0-f
+
+# color specification yuv-opacity
+# string, default: 808080-f
+#gui.osdmenu.color_focused_slider:808080-f
+
+# color specification yuv-opacity
+# string, default: ff8080-f
+#gui.osdmenu.color_focused_slider_knob:ff8080-f
+
+# color specification yuv-opacity
+# string, default: 808080-f
+#gui.osdmenu.color_focused_text_border:808080-f
+
+# color specification yuv-opacity
+# string, default: ff8080-f
+#gui.osdmenu.color_focused_text_foreground:ff8080-f
+
+# color specification yuv-opacity
+# string, default: 0080c0-f
+#gui.osdmenu.color_label_border:0080c0-f
+
+# color specification yuv-opacity
+# string, default: c08080-f
+#gui.osdmenu.color_label_foreground:c08080-f
+
+# color specification yuv-opacity
+# string, default: 0080c0-f
+#gui.osdmenu.color_label_window:0080c0-f
+
+# color specification yuv-opacity
+# string, default: 008000-f
+#gui.osdmenu.color_slider:008000-f
+
+# color specification yuv-opacity
+# string, default: ffff00-f
+#gui.osdmenu.color_slider_knob:ffff00-f
+
+# color specification yuv-opacity
+# string, default: 008000-f
+#gui.osdmenu.color_text_border:008000-f
+
+# color specification yuv-opacity
+# string, default: ffff00-f
+#gui.osdmenu.color_text_foreground:ffff00-f
+
+# color specification yuv-opacity
+# string, default: 0080c0-f
+#gui.osdmenu.color_text_window:0080c0-f
+
+# directory a media in dvd device will be mounted
+# string, default: /dvd
+#gui.osdmenu.dvd_mountpoint:/dvd
+
+# Farbpalette (Vordergrund-Rand-Hintergrund) für Untertitel und OSD
+# { white-black-transparent  white-none-transparent  white-none-translucid  yellow-black-transparent }, default: 0
+#ui.osd.text_palette:white-black-transparent
+
+# Änderungen an Hardwaremixer melden
+# bool, default: 1
+#audio.alsa_hw_mixer:1
+
+# Zu benutzender Audiotreiber
+# { auto  null  alsa  oss  file  none }, default: 0
+#audio.driver:auto
+
+# Benutze dynamische A/52 Bereichskomprimierung
+# bool, default: 0
+#audio.a52.dynamic_range:0
+
+# Heruntermischen zu Zweikanal Stereo Raumklang
+# bool, default: 0
+#audio.a52.surround_downmix:0
+
+# A/52 Lautstärke
+# [0..200], default: 100
+#audio.a52.level:100
+
+# Gerät für Monoausgabe
+# string, default: default
+#audio.device.alsa_default_device:default
+
+# Gerät für Stereoausgabe
+# string, default: plug:front:default
+audio.device.alsa_front_device:default
+
+# ALSA Mixergerät
+# string, default: PCM
+#audio.device.alsa_mixer_name:PCM
+
+# Soundkarte unterstützt mmap
+# bool, default: 0
+#audio.device.alsa_mmap_enable:0
+
+# Gerät für 5.1-Kanalausgabe
+# string, default: iec958:AES0=0x6,AES1=0x82,AES2=0x0,AES3=0x2
+#audio.device.alsa_passthrough_device:iec958:AES0=0x6,AES1=0x82,AES2=0x0,AES3=0x2
+
+# Gerät für 4-Kanalausgabe
+# string, default: plug:surround40:0
+#audio.device.alsa_surround40_device:plug:surround40:0
+
+# Gerät für 5.1-Kanalausgabe
+# string, default: plug:surround51:0
+#audio.device.alsa_surround51_device:plug:surround51:0
+
+# Lautsprecherplazierung
+# { Mono 1.0  Stereo 2.0  Headphones 2.0  Stereo 2.1  Surround 3.0  Surround 4.0  Surround 4.1  Surround 5.0  Surround 5.1  Surround 6.0  Surround 6.1  Surround 7.1  Pass Through }, default: 1
+#audio.output.speaker_arrangement:Stereo 2.0
+
+# Versatz für digitales Passthrough
+# numeric, default: 0
+#audio.synchronization.passthrough_offset:0
+
+# Audiowiedergabe während langsamer/schneller Geschwindigkeit
+# bool, default: 0
+#audio.synchronization.slow_fast_audio:0
+
+# Methode für Audio/Videosynchronisation
+# { metronom feedback  resample }, default: 0
+#audio.synchronization.av_sync_method:metronom feedback
+
+# Wenn !=0, immer auf diese Rate anpassen
+# numeric, default: 0
+#audio.synchronization.force_rate:0
+
+# Resampling benutzen
+# { auto  off  on }, default: 0
+#audio.synchronization.resample_mode:auto
+
+# Startlautstärke
+# [0..100], default: 50
+#audio.volume.mixer_volume:50
+
+# Lautstärke beim Starten wiederherstellen
+# bool, default: 0
+#audio.volume.remember_volume:0
+
+# Zu benutzender Videotreiber
+# { auto  vdpau  xv  vaapi  opengl  raw  xshm  none  fb }, default: 0
+video.driver:vaapi
+
+# Alle Videoskalierungen deaktivieren
+# bool, default: 0
+#video.output.disable_scaling:0
+
+# Horizontale Bildposition im Ausgabefenster
+# [0..100], default: 50
+#video.output.horizontal_position:50
+
+# vaapi: set deinterlace to 0 ( none ), 1 ( top field ), 2 ( bob ).
+# numeric, default: 0
+#video.output.vaapi_deinterlace:0
+
+# vaapi: indirect output rendering
+# bool, default: 0
+#video.output.vaapi_indirect_render:0
+
+# vaapi: VDR osd height workaround.
+# numeric, default: 0
+#video.output.vaapi_vdr_osd_height:0
+
+# vaapi: VDR osd width workaround.
+# numeric, default: 0
+#video.output.vaapi_vdr_osd_width:0
+
+# Vertikale Bildposition im Ausgabefenster
+# [0..100], default: 50
+#video.output.vertical_position:50
+
+# Choose speed over specification compliance
+# bool, default: 0
+#video.processing.ffmpeg_choose_speed_over_accuracy:0
+
+# Enable usage of VAAPI
+# bool, default: 1
+#video.processing.ffmpeg_enable_vaapi:1
+
+# Qualität der MPEG-4 Nachbearbeitungsstufe
+# [0..6], default: 3
+#video.processing.ffmpeg_pp_quality:3
+
+# Skip loop filter
+# { default  none  nonref  bidir  nonkey  all }, default: 0
+#video.processing.ffmpeg_skip_loop_filter:default
+
+# FFmpeg video decoding thread count
+# numeric, default: 1
+#video.processing.ffmpeg_thread_count:1
+
+# VAAPI Mpeg2 softdecoding
+# bool, default: 0
+#video.processing.vaapi_mpeg_sofdec:0
+
+# VAAPI Mpeg2 softdecoding deinterlace
+# bool, default: 0
+#video.processing.vaapi_mpeg_sofdec_deinterlace:0
+
+# Gerät für CD-Audio
+# string, default: /dev/cdrom
+#media.audio_cd.device:/dev/cdrom
+
+# Laufwerk auf diesen Faktor verlangsamen
+# numeric, default: 4
+#media.audio_cd.drive_slowdown:4
+
+# CDDB abfragen
+# bool, default: 1
+#media.audio_cd.use_cddb:1
+
+# CDDB Serverport
+# numeric, default: 8880
+#media.audio_cd.cddb_port:8880
+
+# CDDB Servername
+# string, default: freedb.freedb.org
+#media.audio_cd.cddb_server:freedb.freedb.org
+
+# BluRay player country code
+# string, default: en
+#media.bluray.country:en
+
+# device used for BluRay playback
+# string, default: /dev/dvd
+#media.bluray.device:/dev/dvd
+
+# default language for BluRay playback
+# string, default: eng
+#media.bluray.language:eng
+
+# BluRay mount point
+# string, default: /mnt/bluray
+#media.bluray.mountpoint:/mnt/bluray
+
+# parental control age limit (1-99)
+# numeric, default: 99
+#media.bluray.parental:99
+
+# BluRay player region code (1=A, 2=B, 4=C)
+# numeric, default: 7
+#media.bluray.region:7
+
+# Pfad zum Sichen von Datenströmen
+# string, default:
+#media.capture.save_dir:
+
+# Nummer der zu benutzenden DVB-Karte.
+# numeric, default: 0
+#media.dvb.adapter:0
+
+# Zuletzt gesehenen DVB-Kanal vermerken
+# bool, default: 1
+#media.dvb.remember_channel:1
+
+# Number of seconds until tuning times out.
+# numeric, default: 0
+#media.dvb.tuning_timeout:0
+
+# Enable the DVB GUI
+# bool, default: 1
+#media.dvb.gui_enabled:1
+
+# Zuletzt gesehener DVB-Kanal
+# numeric, default: -1
+#media.dvb.last_channel:-1
+
+# Standardsprache für die DVD-Wiedergabe
+# string, default: en
+#media.dvd.language:en
+
+# Region (1-8), aus der der DVD Player zu kommen scheint
+# numeric, default: 1
+#media.dvd.region:1
+
+# Gerät für DVD Wiedergabe
+# string, default: /dev/dvd
+#media.dvd.device:/dev/dvd
+
+# Pfad zum RAW-Device des DVD-Laufwerks
+# string, default: /dev/rdvd
+#media.dvd.raw_device:/dev/rdvd
+
+# Vorauseilendes Caching benutzen
+# bool, default: 1
+#media.dvd.readahead:1
+
+# CSS Entschlüsselungsmethode
+# { key  disc  title }, default: 0
+#media.dvd.css_decryption_method:key
+
+# Wiedergabemodus falls Titel/Kapitel angegeben
+# { entire dvd  one chapter }, default: 0
+#media.dvd.play_single_chapter:entire dvd
+
+# Einheit beim Suchen
+# { seek in program chain  seek in program }, default: 0
+#media.dvd.seek_behaviour:seek in program chain
+
+# Einheit für die Überspringen-Aktion
+# { skip program  skip part  skip title }, default: 0
+#media.dvd.skip_behaviour:skip program
+
+# Startverzeichnis für Dateisuche
+# string, default: /home/gimli
+#media.files.origin_path:/home/gimli
+
+# Versteckte Dateien anzeigen
+# bool, default: 0
+#media.files.show_hidden_files:0
+
+# Netzwerkbandbreite
+# { 14.4 Kbps (Modem)  19.2 Kbps (Modem)  28.8 Kbps (Modem)  33.6 Kbps (Modem)  34.4 Kbps (Modem)  57.6 Kbps (Modem)  115.2 Kbps (ISDN)  262.2 Kbps (Cable/DSL)  393.2 Kbps (Cable/DSL)  524.3 Kbps (Cable/DSL) }, default: 10
+
+# Zeitüberschreitung für Netzwerkdatenströme (in Sekunden)
+# numeric, default: 30
+#media.network.timeout:30
+
+# Domains, die den HTTP Proxy umgehen
+# string, default:
+#media.network.http_no_proxy:
+
+# HTTP Proxy Rechnername
+# string, default:
+#media.network.http_proxy_host:
+
+# HTTP Proxy Passwort
+# string, default:
+#media.network.http_proxy_password:
+
+# HTTP Proxy Portnummer
+# numeric, default: 80
+#media.network.http_proxy_port:80
+
+# HTTP Proxy Benutzername
+# string, default:
+#media.network.http_proxy_user:
+
+# MMS-Protokoll
+# { auto  TCP  HTTP }, default: 0
+#media.network.mms_protocol:auto
+
+# default VDR host
+# string, default: xvdr://127.0.0.1#nocache;demux:mpeg_block
+#media.xvdr.default_mrl:xvdr://127.0.0.1#nocache;demux:mpeg_block
+
+# Fast (low-quality) OSD scaling
+# bool, default: 0
+#media.xvdr.fast_osd_scaling:0
+
+# number of buffers for HD content
+# numeric, default: 2500
+#media.xvdr.num_buffers_hd:2500
+
+# SCR-Treshold for HD-Playback (%)
+# numeric, default: 40
+#media.xvdr.scr_treshold_hd:40
+
+# SCR-Treshold for SD-Playback (%)
+# numeric, default: 50
+#media.xvdr.scr_treshold_sd:50
+
+# SRC tuning step
+# numeric, default: 5000
+#media.xvdr.scr_tuning_step:5000
+
+# Smoother SRC tuning
+# bool, default: 0
+#media.xvdr.smooth_scr_tuning:0
+
+# opacity for the black parts of bitmapped subtitles
+# [0..100], default: 67
+#subtitles.bitmap.black_opacity:67
+
+# opacity for the colour parts of bitmapped subtitles
+# [0..100], default: 100
+#subtitles.bitmap.colour_opacity:100
+
+# Untertitelgröße
+# { tiny  small  normal  large  very large  huge }, default: 1
+#subtitles.separate.subtitle_size:small
+
+# Vertikaler Versatz für Untertitel
+# numeric, default: 0
+#subtitles.separate.vertical_offset:0
+
+# Zeichensatz für Untertitel
+# string, default: sans
+#subtitles.separate.font:sans
+
+# Zeichenkodierung für Untertitel
+# string, default: iso-8859-1
+#subtitles.separate.src_encoding:iso-8859-1
+
+# Benutze unskaliertes OSD falls möglich
+# bool, default: 1
+#subtitles.separate.use_unscaled_osd:1
+
+# Zu generierende Bilder/Sekunde
+# numeric, default: 14
+#effects.goom.fps:14
+
+# Goom Bildhöhe
+# numeric, default: 240
+#effects.goom.height:240
+
+# Goom Bildbreite
+# numeric, default: 320
+#effects.goom.width:320
+
+# Farbraumkonvertierungsmethode
+# { Fast but not photorealistic  Slow but looks better }, default: 0
+#effects.goom.csc_method:Fast but not photorealistic
+
+# Anzahl der Audiopuffer
+# numeric, default: 230
+#engine.buffers.audio_num_buffers:230
+
+# Anzahl der Videopuffer
+# numeric, default: 500
+#engine.buffers.video_num_buffers:500
+
+# Standardanzahl von Videobildern
+# numeric, default: 21
+engine.buffers.video_num_frames:22
+
+# disable decoder flush at discontinuity
+# bool, default: 0
+#engine.decoder.disable_flush_at_discontinuity:0
+
+# disable decoder flush from video out
+# bool, default: 0
+#engine.decoder.disable_flush_from_video_out:0
+
+# Priorität für Dekoder a/52
+# numeric, default: 0
+#engine.decoder_priorities.a/52:0
+
+# Priorität für Dekoder bitplane
+# numeric, default: 0
+#engine.decoder_priorities.bitplane:0
+
+# Priorität für Dekoder dts
+# numeric, default: 0
+#engine.decoder_priorities.dts:0
+
+# Priorität für Dekoder dvaudio
+# numeric, default: 0
+#engine.decoder_priorities.dvaudio:0
+
+# Priorität für Dekoder faad
+# numeric, default: 0
+#engine.decoder_priorities.faad:0
+
+# Priorität für Dekoder ffmpeg-wmv8
+# numeric, default: 0
+#engine.decoder_priorities.ffmpeg-wmv8:0
+
+# Priorität für Dekoder ffmpeg-wmv9
+# numeric, default: 0
+#engine.decoder_priorities.ffmpeg-wmv9:0
+
+# Priorität für Dekoder ffmpegaudio
+# numeric, default: 0
+#engine.decoder_priorities.ffmpegaudio:0
+
+# Priorität für Dekoder ffmpegvideo
+# numeric, default: 0
+engine.decoder_priorities.ffmpegvideo:1
+
+# Priorität für Dekoder flacdec
+# numeric, default: 0
+#engine.decoder_priorities.flacdec:0
+
+# Priorität für Dekoder gsm610
+# numeric, default: 0
+#engine.decoder_priorities.gsm610:0
+
+# Priorität für Dekoder mad
+# numeric, default: 0
+#engine.decoder_priorities.mad:0
+
+# Priorität für Dekoder mpeg2
+# numeric, default: 0
+#engine.decoder_priorities.mpeg2:0
+
+# Priorität für Dekoder pcm
+# numeric, default: 0
+#engine.decoder_priorities.pcm:0
+
+# Priorität für Dekoder rgb
+# numeric, default: 0
+#engine.decoder_priorities.rgb:0
+
+# Priorität für Dekoder spucc
+# numeric, default: 0
+#engine.decoder_priorities.spucc:0
+
+# Priorität für Dekoder spucmml
+# numeric, default: 0
+#engine.decoder_priorities.spucmml:0
+
+# Priorität für Dekoder spudec
+# numeric, default: 0
+#engine.decoder_priorities.spudec:0
+
+# Priorität für Dekoder spudvb
+# numeric, default: 0
+#engine.decoder_priorities.spudvb:0
+
+# Priorität für Dekoder spuhdmv
+# numeric, default: 0
+#engine.decoder_priorities.spuhdmv:0
+
+# Priorität für Dekoder sputext
+# numeric, default: 0
+#engine.decoder_priorities.sputext:0
+
+# Priorität für Dekoder theora
+# numeric, default: 0
+#engine.decoder_priorities.theora:0
+
+# Priorität für Dekoder vdpau_h264
+# numeric, default: 0
+#engine.decoder_priorities.vdpau_h264:0
+
+# Priorität für Dekoder vdpau_mpeg12
+# numeric, default: 0
+#engine.decoder_priorities.vdpau_mpeg12:0
+
+# Priorität für Dekoder vdpau_mpeg4
+# numeric, default: 0
+#engine.decoder_priorities.vdpau_mpeg4:0
+
+# Priorität für Dekoder vdpau_vc1
+# numeric, default: 0
+#engine.decoder_priorities.vdpau_vc1:0
+
+# Priorität für Dekoder vorbis
+# numeric, default: 0
+#engine.decoder_priorities.vorbis:0
+
+# Priorität für Dekoder yuv
+# numeric, default: 0
+#engine.decoder_priorities.yuv:0
+
+# Medienformaterkennungsstrategie
+# { default  reverse  content  extension }, default: 0
+#engine.demux.strategy:default
+
+# xines Methode zum Kopieren von Speicher
+# { probe  libc  kernel  mmx  mmxext  sse }, default: 0
+engine.performance.memcpy_method:libc
+
+# Erlaubter Prozentsatz für verworfene Frames
+# numeric, default: 10
+#engine.performance.warn_discarded_threshold:10
+
+# Erlaubter Prozentsatz für übersprungene Frames
+# numeric, default: 10
+#engine.performance.warn_skipped_threshold:10
+
+# Erlaube implizierte Änderungen an Konfiguration (z.B. durch MRL)
+# bool, default: 0
+#misc.implicit_config:0
+
diff --git a/include/xine.h b/include/xine.h
index d6f54b7..e7a2ee3 100644
--- a/include/xine.h
+++ b/include/xine.h
@@ -452,6 +452,7 @@ int  xine_get_current_frame_data (xine_stream_t *stream,
 #define XINE_IMGFMT_XVMC (('C'<<24)|('M'<<16)|('v'<<8)|'X')
 #define XINE_IMGFMT_XXMC (('C'<<24)|('M'<<16)|('x'<<8)|'X')
 #define XINE_IMGFMT_VDPAU (('A'<<24)|('P'<<16)|('D'<<8)|'V')
+#define XINE_IMGFMT_VAAPI (('P'<<24)|('A'<<16)|('A'<<8)|'V')
 
 /* get current xine's virtual presentation timestamp (1/90000 sec)
  * note: this is mostly internal data.
diff --git a/include/xine/video_out.h b/include/xine/video_out.h
index 5a04011..d648f5d 100644
--- a/include/xine/video_out.h
+++ b/include/xine/video_out.h
@@ -303,6 +303,7 @@ struct xine_video_port_s {
 #define VO_CAP_VDPAU_MPEG12           0x00000100 /* driver can use VDPAU for mpeg1/2 */
 #define VO_CAP_VDPAU_VC1              0x00000200 /* driver can use VDPAU for VC1 */
 #define VO_CAP_VDPAU_MPEG4            0x00000400 /* driver can use VDPAU for mpeg4-part2 */
+#define VO_CAP_VAAPI                  0x00000600 /* driver can use VAAPI */
 #define VO_CAP_HUE                    0x00010000
 #define VO_CAP_SATURATION             0x00020000
 #define VO_CAP_CONTRAST               0x00040000
diff --git a/src/combined/ffmpeg/Makefile.am b/src/combined/ffmpeg/Makefile.am
index c6509ed..dc2622b 100644
--- a/src/combined/ffmpeg/Makefile.am
+++ b/src/combined/ffmpeg/Makefile.am
@@ -18,12 +18,12 @@ DISTCLEANFILES = $(ff_generated)
 EXTRA_DIST = xine_video.list xine_audio.list mkcodeclist.pl
 
 xineplug_decode_ff_la_SOURCES = ffmpeg_decoder.c ff_audio_decoder.c ff_video_decoder.c \
-                                ff_mpeg_parser.c ffmpeg_decoder.h ff_mpeg_parser.h
+ ff_mpeg_parser.c ffmpeg_decoder.h ff_mpeg_parser.h
 
 nodist_xineplug_decode_ff_la_SOURCES = ffmpeg_config.h
 
 xineplug_decode_ff_la_CFLAGS = $(AM_CFLAGS) $(FFMPEG_CFLAGS) $(FFMPEG_POSTPROC_CFLAGS)
-xineplug_decode_ff_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) -lm $(ZLIB_LIBS) \
+xineplug_decode_ff_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(ZLIB_LIBS) \
  $(FFMPEG_LIBS) $(AVUTIL_LIBS) $(FFMPEG_POSTPROC_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL)
 xineplug_decode_ff_la_LDFLAGS = $(AM_LDFLAGS) $(IMPURE_TEXT_LDFLAGS)
 
diff --git a/src/combined/ffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c
index 03a4b8c..66f486f 100644
--- a/src/combined/ffmpeg/ff_video_decoder.c
+++ b/src/combined/ffmpeg/ff_video_decoder.c
@@ -50,6 +50,9 @@
 #  include <libpostproc/postprocess.h>
 #endif
 
+#include <libavcodec/vaapi.h>
+#include "accel_vaapi.h"
+
 #define VIDEOBUFSIZE        (128*1024)
 #define SLICE_BUFFER_SIZE   (1194*1024)
 
@@ -78,6 +81,9 @@ typedef struct ff_video_class_s {
   int                     thread_count;
   int8_t                  skip_loop_filter_enum;
   int8_t                  choose_speed_over_accuracy;
+  int                     enable_vaapi;
+  int                     vaapi_mpeg_softdec;
+  int                     vaapi_mpeg_softdec_deinterlace;
 
   xine_t                 *xine;
 } ff_video_class_t;
@@ -141,8 +147,12 @@ struct ff_video_decoder_s {
 #ifdef LOG
   enum PixelFormat  debug_fmt;
 #endif
-};
 
+  struct vaapi_context  vaapi_context;
+  vaapi_accel_t         *accel;
+  vo_frame_t            *accel_img;
+  uint8_t               set_stream_info;
+};
 
 static void set_stream_info(ff_video_decoder_t *this) {
   _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH,  this->bih.biWidth);
@@ -166,13 +176,72 @@ static int get_buffer(AVCodecContext *context, AVFrame *av_frame){
       this->aspect_ratio = (double)width / (double)height;
       this->aspect_ratio_prio = 1;
       lprintf("default aspect ratio: %f\n", this->aspect_ratio);
-      set_stream_info(this);
+      this->set_stream_info = 1;
     }
   }
 
   avcodec_align_dimensions(context, &width, &height);
 
-  if( this->context->pix_fmt != PIX_FMT_YUV420P && this->context->pix_fmt != PIX_FMT_YUVJ420P ) {
+  if( this->context->pix_fmt == PIX_FMT_VAAPI_VLD) {
+
+    av_frame->opaque  = NULL;
+    av_frame->data[0] = NULL;
+    av_frame->data[1] = NULL;
+    av_frame->data[2] = NULL;
+    av_frame->data[3] = NULL;
+    av_frame->type = FF_BUFFER_TYPE_USER;
+    av_frame->age = 1;
+    av_frame->reordered_opaque = context->reordered_opaque;
+
+    if(!this->accel->guarded_render(this->accel_img)) {
+      img = this->stream->video_out->get_frame (this->stream->video_out,
+                                            width,
+                                            height,
+                                            this->aspect_ratio,
+                                            this->output_format,
+                                            VO_BOTH_FIELDS|this->frame_flags);
+
+      av_frame->opaque = img;
+      xine_list_push_back(this->dr1_frames, av_frame);
+
+      vaapi_accel_t *accel = (vaapi_accel_t*)img->accel_data;
+      ff_vaapi_surface_t *va_surface = accel->get_vaapi_surface(img);
+
+      if(va_surface) {
+        av_frame->data[0] = (void *)va_surface;//(void *)(uintptr_t)va_surface->va_surface_id;
+        av_frame->data[3] = (void *)(uintptr_t)va_surface->va_surface_id;
+      }
+    } else {
+      ff_vaapi_surface_t *va_surface = this->accel->get_vaapi_surface(this->accel_img);
+
+      if(va_surface) {
+        av_frame->data[0] = (void *)va_surface;//(void *)(uintptr_t)va_surface->va_surface_id;
+        av_frame->data[3] = (void *)(uintptr_t)va_surface->va_surface_id;
+      }
+    }
+
+    lprintf("1: 0x%08x\n", av_frame->data[3]);
+
+    av_frame->linesize[0] = 0;
+    av_frame->linesize[1] = 0;
+    av_frame->linesize[2] = 0;
+    av_frame->linesize[3] = 0;
+
+    this->is_direct_rendering_disabled = 1;
+
+    return 0;
+  }
+
+  /* on vaapi out do not use direct rendeing */
+  if(this->class->enable_vaapi) {
+    this->output_format = XINE_IMGFMT_YV12;
+  }
+
+  int guarded_render = 0;
+  if(this->accel)
+    guarded_render = this->accel->guarded_render(this->accel_img);
+
+  if( (this->context->pix_fmt != PIX_FMT_YUV420P && this->context->pix_fmt != PIX_FMT_YUVJ420P) || guarded_render) {
     if (!this->is_direct_rendering_disabled) {
       xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
               _("ffmpeg_video_dec: unsupported frame format, DR1 disabled.\n"));
@@ -239,6 +308,18 @@ static int get_buffer(AVCodecContext *context, AVFrame *av_frame){
 static void release_buffer(struct AVCodecContext *context, AVFrame *av_frame){
   ff_video_decoder_t *this = (ff_video_decoder_t *)context->opaque;
 
+  if( this->context->pix_fmt == PIX_FMT_VAAPI_VLD ) {
+    if(this->accel->guarded_render(this->accel_img)) {
+      ff_vaapi_surface_t *va_surface = (ff_vaapi_surface_t *)av_frame->data[0];
+      if(va_surface != NULL) {
+        this->accel->release_vaapi_surface(this->accel_img, va_surface);
+        lprintf("release_buffer: va_surface_id 0x%08x\n", (unsigned int)av_frame->data[3]);
+      }
+    }
+  }
+
+  lprintf("3: 0x%08x\n", av_frame->data[3]);
+
   if (av_frame->type == FF_BUFFER_TYPE_USER) {
     if ( av_frame->opaque ) {
       vo_frame_t *img = (vo_frame_t *)av_frame->opaque;
@@ -249,7 +330,7 @@ static void release_buffer(struct AVCodecContext *context, AVFrame *av_frame){
     xine_list_iterator_t it;
 
     it = xine_list_find(this->dr1_frames, av_frame);
-    assert(it);
+    //assert(it);
     if( it != NULL )
       xine_list_remove(this->dr1_frames, it);
   } else {
@@ -284,6 +365,51 @@ static const int skip_loop_filter_enum_values[] = {
   AVDISCARD_ALL
 };
 
+static enum PixelFormat get_format(struct AVCodecContext *context, const enum PixelFormat *fmt)
+{
+  int i, profile;
+  ff_video_decoder_t *this = (ff_video_decoder_t *)context->opaque;
+
+  if(!this->class->enable_vaapi || !this->accel_img)
+    return PIX_FMT_YUV420P;
+
+  vaapi_accel_t *accel = (vaapi_accel_t*)this->accel_img->accel_data;
+
+  for (i = 0; fmt[i] != PIX_FMT_NONE; i++) {
+    if (fmt[i] != PIX_FMT_VAAPI_VLD)
+      continue;
+
+    profile = accel->profile_from_imgfmt(this->accel_img, fmt[i], context->codec_id, this->class->vaapi_mpeg_softdec);
+
+    if (profile >= 0) {
+      VAStatus status;
+
+      status = accel->vaapi_init(this->accel_img, profile, context->width, context->height, 0);
+
+      if( status == VA_STATUS_SUCCESS ) {
+        ff_vaapi_context_t *va_context = accel->get_context(this->accel_img);
+
+        if(!va_context)
+          return PIX_FMT_YUV420P;
+
+        context->draw_horiz_band = NULL;
+        context->slice_flags = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
+        context->dsp_mask = 0;
+
+        this->vaapi_context.config_id    = va_context->va_config_id;
+        this->vaapi_context.context_id   = va_context->va_context_id;
+        this->vaapi_context.display      = va_context->va_display;
+
+        context->hwaccel_context     = &this->vaapi_context;
+        this->pts = 0;
+
+        return fmt[i];
+      }
+    }
+  }
+  return PIX_FMT_YUV420P;
+}
+
 static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type) {
   size_t i;
 
@@ -329,6 +455,47 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type)
   if (this->class->choose_speed_over_accuracy)
     this->context->flags2 |= CODEC_FLAG2_FAST;
 
+  if(this->class->enable_vaapi)
+  {
+    this->class->thread_count = this->context->thread_count = 1;
+
+    this->context->skip_loop_filter = AVDISCARD_DEFAULT;
+    xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+     _("ffmpeg_video_dec: force AVDISCARD_DEFAULT for VAAPI\n"));
+  } else {
+    this->context->skip_loop_filter = skip_loop_filter_enum_values[this->class->skip_loop_filter_enum];
+  }
+
+  if (this->class->thread_count > 1) {
+    if (this->codec->id != CODEC_ID_SVQ3
+#ifndef DEPRECATED_AVCODEC_THREAD_INIT
+        && avcodec_thread_init(this->context, this->class->thread_count) != -1
+#endif
+      )
+      this->context->thread_count = this->class->thread_count;
+  }
+
+  /* enable direct rendering by default */
+  this->output_format = XINE_IMGFMT_YV12;
+#ifdef ENABLE_DIRECT_RENDERING
+  if( this->codec->capabilities & CODEC_CAP_DR1 && this->codec->id != CODEC_ID_H264 ) {
+    this->context->get_buffer = get_buffer;
+    this->context->release_buffer = release_buffer;
+    xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+    _("ffmpeg_video_dec: direct rendering enabled\n"));
+  }
+
+  if( this->class->enable_vaapi ) {
+    this->output_format = XINE_IMGFMT_VAAPI;
+    this->context->get_buffer = get_buffer;
+    this->context->reget_buffer = get_buffer;
+    this->context->release_buffer = release_buffer;
+    this->context->get_format = get_format;
+    xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+    _("ffmpeg_video_dec: direct rendering enabled\n"));
+  }
+#endif
+
   pthread_mutex_lock(&ffmpeg_lock);
   if (avcodec_open (this->context, this->codec) < 0) {
     pthread_mutex_unlock(&ffmpeg_lock);
@@ -356,17 +523,6 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type)
     }
   }
 
-  if (this->class->thread_count > 1) {
-    if (this->codec->id != CODEC_ID_SVQ3
-#ifndef DEPRECATED_AVCODEC_THREAD_INIT
- && avcodec_thread_init(this->context, this->class->thread_count) != -1
-#endif
- )
-      this->context->thread_count = this->class->thread_count;
-  }
-
-  this->context->skip_loop_filter = skip_loop_filter_enum_values[this->class->skip_loop_filter_enum];
-
   pthread_mutex_unlock(&ffmpeg_lock);
 
   lprintf("lavc decoder opened\n");
@@ -389,41 +545,50 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type)
 
   this->skipframes = 0;
 
-  /* enable direct rendering by default */
-  this->output_format = XINE_IMGFMT_YV12;
-#ifdef ENABLE_DIRECT_RENDERING
-  if( this->codec->capabilities & CODEC_CAP_DR1 && this->codec->id != CODEC_ID_H264 ) {
-    this->context->get_buffer = get_buffer;
-    this->context->release_buffer = release_buffer;
-    xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
-    _("ffmpeg_video_dec: direct rendering enabled\n"));
-  }
-#endif
-
   /* flag for interlaced streams */
   this->frame_flags = 0;
   /* FIXME: which codecs can be interlaced?
       FIXME: check interlaced DCT and other codec specific info. */
-  switch( codec_type ) {
-    case BUF_VIDEO_DV:
-      this->frame_flags |= VO_INTERLACED_FLAG;
-      break;
-    case BUF_VIDEO_MPEG:
-      this->frame_flags |= VO_INTERLACED_FLAG;
-      break;
-    case BUF_VIDEO_MJPEG:
-      this->frame_flags |= VO_INTERLACED_FLAG;
-      break;
-    case BUF_VIDEO_HUFFYUV:
-      this->frame_flags |= VO_INTERLACED_FLAG;
-      break;
-    case BUF_VIDEO_H264:
-      this->frame_flags |= VO_INTERLACED_FLAG;
-      break;
+  if(!this->class->enable_vaapi) {
+    switch( codec_type ) {
+      case BUF_VIDEO_DV:
+        this->frame_flags |= VO_INTERLACED_FLAG;
+        break;
+      case BUF_VIDEO_MPEG:
+        this->frame_flags |= VO_INTERLACED_FLAG;
+        break;
+      case BUF_VIDEO_MJPEG:
+        this->frame_flags |= VO_INTERLACED_FLAG;
+        break;
+      case BUF_VIDEO_HUFFYUV:
+        this->frame_flags |= VO_INTERLACED_FLAG;
+        break;
+      case BUF_VIDEO_H264:
+        this->frame_flags |= VO_INTERLACED_FLAG;
+        break;
+    }
   }
 
 }
 
+static void vaapi_enable_vaapi(void *user_data, xine_cfg_entry_t *entry) {
+  ff_video_class_t   *class = (ff_video_class_t *) user_data;
+
+  class->enable_vaapi = entry->num_value;
+}
+
+static void vaapi_mpeg_softdec_func(void *user_data, xine_cfg_entry_t *entry) {
+  ff_video_class_t   *class = (ff_video_class_t *) user_data;
+
+  class->vaapi_mpeg_softdec = entry->num_value;
+}
+
+static void vaapi_mpeg_softdec_deinterlace(void *user_data, xine_cfg_entry_t *entry) {
+  ff_video_class_t   *class = (ff_video_class_t *) user_data;
+
+  class->vaapi_mpeg_softdec_deinterlace = entry->num_value;
+}
+
 static void choose_speed_over_accuracy_cb(void *user_data, xine_cfg_entry_t *entry) {
   ff_video_class_t   *class = (ff_video_class_t *) user_data;
 
@@ -550,7 +715,7 @@ static int ff_handle_mpeg_sequence(ff_video_decoder_t *this, mpeg_parser_t *pars
   return 1;
 }
 
-static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
+static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img, AVFrame *av_frame) {
   int         y;
   uint8_t    *dy, *du, *dv, *sy, *su, *sv;
 
@@ -562,9 +727,9 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
   dy = img->base[0];
   du = img->base[1];
   dv = img->base[2];
-  sy = this->av_frame->data[0];
-  su = this->av_frame->data[1];
-  sv = this->av_frame->data[2];
+  sy = av_frame->data[0];
+  su = av_frame->data[1];
+  sv = av_frame->data[2];
 
   /* Some segfaults & heap corruption have been observed with img->height,
    * so we use this->bih.biHeight instead (which is the displayed height)
@@ -574,18 +739,18 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
 
     yuv9_to_yv12(
      /* Y */
-      this->av_frame->data[0],
-      this->av_frame->linesize[0],
+      av_frame->data[0],
+      av_frame->linesize[0],
       img->base[0],
       img->pitches[0],
      /* U */
-      this->av_frame->data[1],
-      this->av_frame->linesize[1],
+      av_frame->data[1],
+      av_frame->linesize[1],
       img->base[1],
       img->pitches[1],
      /* V */
-      this->av_frame->data[2],
-      this->av_frame->linesize[2],
+      av_frame->data[2],
+      av_frame->linesize[2],
       img->base[2],
       img->pitches[2],
      /* width x height */
@@ -596,18 +761,18 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
 
     yuv411_to_yv12(
      /* Y */
-      this->av_frame->data[0],
-      this->av_frame->linesize[0],
+      av_frame->data[0],
+      av_frame->linesize[0],
       img->base[0],
       img->pitches[0],
      /* U */
-      this->av_frame->data[1],
-      this->av_frame->linesize[1],
+      av_frame->data[1],
+      av_frame->linesize[1],
       img->base[1],
       img->pitches[1],
      /* V */
-      this->av_frame->data[2],
-      this->av_frame->linesize[2],
+      av_frame->data[2],
+      av_frame->linesize[2],
       img->base[2],
       img->pitches[2],
      /* width x height */
@@ -637,7 +802,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
         this->yuv.v[plane_ptr] = COMPUTE_V(r, g, b);
         plane_ptr++;
       }
-      sy += this->av_frame->linesize[0];
+      sy += av_frame->linesize[0];
     }
 
     yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]);
@@ -666,7 +831,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
         this->yuv.v[plane_ptr] = COMPUTE_V(r, g, b);
         plane_ptr++;
       }
-      sy += this->av_frame->linesize[0];
+      sy += av_frame->linesize[0];
     }
 
     yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]);
@@ -695,7 +860,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
         this->yuv.v[plane_ptr] = COMPUTE_V(r, g, b);
         plane_ptr++;
       }
-      sy += this->av_frame->linesize[0];
+      sy += av_frame->linesize[0];
     }
 
     yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]);
@@ -719,7 +884,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
         this->yuv.v[plane_ptr] = COMPUTE_V(r, g, b);
         plane_ptr++;
       }
-      sy += this->av_frame->linesize[0];
+      sy += av_frame->linesize[0];
     }
 
     yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]);
@@ -743,7 +908,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
         this->yuv.v[plane_ptr] = COMPUTE_V(r, g, b);
         plane_ptr++;
       }
-      sy += this->av_frame->linesize[0];
+      sy += av_frame->linesize[0];
     }
 
     yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]);
@@ -782,7 +947,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
         this->yuv.v[plane_ptr] = v_palette[pixel];
         plane_ptr++;
       }
-      sy += this->av_frame->linesize[0];
+      sy += av_frame->linesize[0];
     }
 
     yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]);
@@ -794,7 +959,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
 
       dy += img->pitches[0];
 
-      sy += this->av_frame->linesize[0];
+      sy += av_frame->linesize[0];
     }
 
     for (y = 0; y < this->bih.biHeight / 2; y++) {
@@ -831,11 +996,11 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) {
       dv += img->pitches[2];
 
       if (this->context->pix_fmt != PIX_FMT_YUV420P) {
-        su += 2*this->av_frame->linesize[1];
-        sv += 2*this->av_frame->linesize[2];
+        su += 2*av_frame->linesize[1];
+        sv += 2*av_frame->linesize[2];
       } else {
-        su += this->av_frame->linesize[1];
-        sv += this->av_frame->linesize[2];
+        su += av_frame->linesize[1];
+        sv += av_frame->linesize[2];
       }
     }
   }
@@ -900,7 +1065,6 @@ static void ff_init_mpeg12_mode(ff_video_decoder_t *this)
   if ( this->mpeg_parser == NULL ) {
     this->mpeg_parser = calloc(1, sizeof(mpeg_parser_t));
     mpeg_parser_init(this->mpeg_parser);
-    this->decoder_init_mode = 0;
   }
 }
 
@@ -1073,6 +1237,52 @@ static void ff_handle_special_buffer (ff_video_decoder_t *this, buf_element_t *b
   }
 }
 
+static uint64_t ff_tag_pts(ff_video_decoder_t *this, uint64_t pts)
+{
+  return pts | this->pts_tag;
+}
+
+static uint64_t ff_untag_pts(ff_video_decoder_t *this, uint64_t pts)
+{
+  if (this->pts_tag_mask == 0)
+    return pts; /* pts tagging inactive */
+
+  if (this->pts_tag != 0 && (pts & this->pts_tag_mask) != this->pts_tag)
+    return 0; /* reset pts if outdated while waiting for first pass (see below) */
+
+  return pts & ~this->pts_tag_mask;
+}
+
+static void ff_check_pts_tagging(ff_video_decoder_t *this, uint64_t pts)
+{
+  if (this->pts_tag_mask == 0)
+    return; /* pts tagging inactive */
+  if ((pts & this->pts_tag_mask) != this->pts_tag) {
+    this->pts_tag_stable_counter = 0;
+    return; /* pts still outdated */
+  }
+
+  /* the tag should be stable for 100 frames */
+  this->pts_tag_stable_counter++;
+
+  if (this->pts_tag != 0) {
+    if (this->pts_tag_stable_counter >= 100) {
+      /* first pass: reset pts_tag */
+      this->pts_tag = 0;
+      this->pts_tag_stable_counter = 0;
+    }
+  } else if (pts == 0)
+    return; /* cannot detect second pass */
+  else {
+    if (this->pts_tag_stable_counter >= 100) {
+      /* second pass: reset pts_tag_mask and pts_tag_counter */
+      this->pts_tag_mask = 0;
+      this->pts_tag_counter = 0;
+      this->pts_tag_stable_counter = 0;
+    }
+  }
+}
+
 static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
 
   vo_frame_t *img;
@@ -1081,6 +1291,10 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu
   int         offset = 0;
   int         flush = 0;
   int         size = buf->size;
+  uint8_t     *buf_deint = 0;
+  AVFrame     *av_framedisp = this->av_frame;
+  AVFrame     *av_framedeint = NULL;
+  int         bDeint = 0;
 
   lprintf("handle_mpeg12_buffer\n");
 
@@ -1135,12 +1349,23 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu
     avpkt.data = (uint8_t *)this->mpeg_parser->chunk_buffer;
     avpkt.size = this->mpeg_parser->buffer_size;
     avpkt.flags = AV_PKT_FLAG_KEY;
-    len = avcodec_decode_video2 (this->context, this->av_frame,
+    if(this->accel) {
+      len = this->accel->avcodec_decode_video2 ( this->accel_img, this->context, av_framedisp,
  &got_picture, &avpkt);
+    } else {
+      len = avcodec_decode_video2 ( this->context, av_framedisp,
+ &got_picture, &avpkt);
+   }
 #else
-    len = avcodec_decode_video (this->context, this->av_frame,
+    if(this->accel) {
+      len = this->accel->avcodec_decode_video ( this->accel_img, this->context, av_framedisp,
                                 &got_picture, this->mpeg_parser->chunk_buffer,
                                 this->mpeg_parser->buffer_size);
+    } else {
+      len = avcodec_decode_video (this->context, av_framedisp,
+                                &got_picture, this->mpeg_parser->chunk_buffer,
+                                this->mpeg_parser->buffer_size);
+    }
 #endif
     lprintf("avcodec_decode_video: decoded_size=%d, got_picture=%d\n",
             len, got_picture);
@@ -1158,9 +1383,24 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu
       offset += len;
     }
 
-    if (got_picture && this->av_frame->data[0]) {
+    if(got_picture && this->class->enable_vaapi) {
+      int width, height;
+      width  = this->context->width;
+      height = this->context->height;
+      if((this->bih.biWidth != width) || (this->bih.biHeight != height)) {
+        this->bih.biWidth = width;
+        this->bih.biHeight = height;
+      }
+    }
+
+    if( this->set_stream_info) {
+      set_stream_info(this);
+      this->set_stream_info = 0;
+    }
+
+    if (got_picture && av_framedisp->data[0]) {
       /* got a picture, draw it */
-      if(!this->av_frame->opaque) {
+      if(!av_framedisp->opaque) {
         /* indirect rendering */
         img = this->stream->video_out->get_frame (this->stream->video_out,
                                                   this->bih.biWidth,
@@ -1171,14 +1411,53 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu
         free_img = 1;
       } else {
         /* DR1 */
-        img = (vo_frame_t*) this->av_frame->opaque;
+        img = (vo_frame_t*) av_framedisp->opaque;
         free_img = 0;
       }
 
+      if( this->context->pix_fmt != PIX_FMT_VAAPI_VLD) {
+        if(av_framedisp->interlaced_frame && this->class->vaapi_mpeg_softdec_deinterlace) {
+          int size;
+          int ret;
+
+          av_framedeint = avcodec_alloc_frame();
+
+          size = avpicture_get_size(this->context->pix_fmt, this->context->width, this->context->height);
+          buf_deint = av_malloc(size);
+
+          if(av_framedeint) {
+            avpicture_fill((AVPicture*)av_framedeint, buf_deint, this->context->pix_fmt, this->context->width, this->context->height);
+
+            ret = avpicture_deinterlace((AVPicture*)av_framedeint, (AVPicture*) av_framedisp,
+                                         this->context->pix_fmt, this->context->width, this->context->height);
+
+            if(ret) {
+              av_free( buf_deint );
+              av_free( av_framedeint );
+            } else {
+              bDeint = 1;
+              av_framedisp = av_framedeint;
+            }
+          } else {
+            av_free( buf_deint );
+          }
+        }
+
+        if(bDeint) {
+          ff_convert_frame(this, img, av_framedeint);
+        } else {
+          ff_convert_frame(this, img, av_framedisp);
+        }
+      }
+
+      img->progressive_frame = !this->av_frame->interlaced_frame;
+      img->top_field_first   = this->av_frame->top_field_first;
+      img->bad_frame = 0;
+
       img->pts  = this->pts;
       this->pts = 0;
 
-      if (this->av_frame->repeat_pict)
+      if (av_framedisp->repeat_pict)
         img->duration = this->video_step * 3 / 2;
       else
         img->duration = this->video_step;
@@ -1186,6 +1465,14 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu
       img->crop_right  = this->crop_right;
       img->crop_bottom = this->crop_bottom;
 
+      if( this->context->pix_fmt == PIX_FMT_VAAPI_VLD) {
+        if(this->accel->guarded_render(this->accel_img)) {
+          ff_vaapi_surface_t *va_surface = (ff_vaapi_surface_t *)av_framedisp->data[0];
+          this->accel->render_vaapi_surface(img, va_surface);
+          lprintf("handle_mpeg12_buffer: render_vaapi_surface va_surface_id 0x%08x\n", av_framedisp->data[0]);
+        }
+      }
+
       this->skipframes = img->draw(img, this->stream);
 
       if(free_img)
@@ -1214,51 +1501,11 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu
         img->free(img);
       }
     }
-  }
-}
-
-static uint64_t ff_tag_pts(ff_video_decoder_t *this, uint64_t pts)
-{
-  return pts | this->pts_tag;
-}
-
-static uint64_t ff_untag_pts(ff_video_decoder_t *this, uint64_t pts)
-{
-  if (this->pts_tag_mask == 0)
-    return pts; /* pts tagging inactive */
-
-  if (this->pts_tag != 0 && (pts & this->pts_tag_mask) != this->pts_tag)
-    return 0; /* reset pts if outdated while waiting for first pass (see below) */
-
-  return pts & ~this->pts_tag_mask;
-}
-
-static void ff_check_pts_tagging(ff_video_decoder_t *this, uint64_t pts)
-{
-  if (this->pts_tag_mask == 0)
-    return; /* pts tagging inactive */
-  if ((pts & this->pts_tag_mask) != this->pts_tag) {
-    this->pts_tag_stable_counter = 0;
-    return; /* pts still outdated */
-  }
-
-  /* the tag should be stable for 100 frames */
-  this->pts_tag_stable_counter++;
 
-  if (this->pts_tag != 0) {
-    if (this->pts_tag_stable_counter >= 100) {
-      /* first pass: reset pts_tag */
-      this->pts_tag = 0;
-      this->pts_tag_stable_counter = 0;
-    }
-  } else if (pts == 0)
-    return; /* cannot detect second pass */
-  else {
-    if (this->pts_tag_stable_counter >= 100) {
-      /* second pass: reset pts_tag_mask and pts_tag_counter */
-      this->pts_tag_mask = 0;
-      this->pts_tag_counter = 0;
-      this->pts_tag_stable_counter = 0;
+    /* free deinterlace picture */
+    if(bDeint) {
+      av_free( buf_deint );
+      av_free( av_framedeint );
     }
   }
 }
@@ -1356,12 +1603,23 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
  avpkt.data = (uint8_t *)&chunk_buf[offset];
  avpkt.size = this->size;
  avpkt.flags = AV_PKT_FLAG_KEY;
- len = avcodec_decode_video2 (this->context, this->av_frame,
+  if(this->accel) {
+   len = this->accel->avcodec_decode_video2 ( this->accel_img, this->context, this->av_frame,
+     &got_picture, &avpkt);
+  } else {
+   len = avcodec_decode_video2 (this->context, this->av_frame,
      &got_picture, &avpkt);
+  }
 #else
+  if(this->accel) {
+        len = this->accel->avcodec_decode_video ( this->accel_img, this->context, this->av_frame,
+                                    &got_picture, &chunk_buf[offset],
+                                    this->size);
+  } else {
         len = avcodec_decode_video (this->context, this->av_frame,
                                     &got_picture, &chunk_buf[offset],
                                     this->size);
+  }
 #endif
         /* reset consumed pts value */
         this->context->reordered_opaque = ff_tag_pts(this, 0);
@@ -1413,6 +1671,11 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
  set_stream_info(this);
       }
 
+      if( this->set_stream_info) {
+        set_stream_info(this);
+        this->set_stream_info = 0;
+      }
+
       if (got_picture && this->av_frame->data[0]) {
         /* got a picture, draw it */
         got_one_picture = 1;
@@ -1420,7 +1683,7 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
   /* indirect rendering */
 
   /* initialize the colorspace converter */
-  if (!this->cs_convert_init) {
+  if (!this->cs_convert_init && !this->context->pix_fmt != PIX_FMT_VAAPI_VLD) {
     if ((this->context->pix_fmt == PIX_FMT_RGB32) ||
         (this->context->pix_fmt == PIX_FMT_RGB565) ||
         (this->context->pix_fmt == PIX_FMT_RGB555) ||
@@ -1456,10 +1719,10 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
         }
 
         /* post processing */
-        if(this->pp_quality != this->class->pp_quality)
+        if(this->pp_quality != this->class->pp_quality && this->context->pix_fmt != PIX_FMT_VAAPI_VLD)
           pp_change_quality(this);
 
-        if(this->pp_available && this->pp_quality) {
+        if(this->pp_available && this->pp_quality && this->context->pix_fmt != PIX_FMT_VAAPI_VLD) {
 
           if(this->av_frame->opaque) {
             /* DR1 */
@@ -1472,7 +1735,7 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
             free_img = 1;
           }
 
-          pp_postprocess(this->av_frame->data, this->av_frame->linesize,
+          pp_postprocess((const uint8_t **)this->av_frame->data, this->av_frame->linesize,
                         img->base, img->pitches,
                         img->width, img->height,
                         this->av_frame->qscale_table, this->av_frame->qstride,
@@ -1481,7 +1744,8 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
 
         } else if (!this->av_frame->opaque) {
   /* colorspace conversion or copy */
-          ff_convert_frame(this, img);
+          if( this->context->pix_fmt != PIX_FMT_VAAPI_VLD)
+            ff_convert_frame(this, img, this->av_frame);
         }
 
         img->pts  = ff_untag_pts(this, this->av_frame->reordered_opaque);
@@ -1510,6 +1774,15 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
         img->progressive_frame = !this->av_frame->interlaced_frame;
         img->top_field_first   = this->av_frame->top_field_first;
 
+        if( this->context->pix_fmt == PIX_FMT_VAAPI_VLD) {
+          if(this->accel->guarded_render(this->accel_img)) {
+            ff_vaapi_surface_t *va_surface = (ff_vaapi_surface_t *)this->av_frame->data[0];
+            this->accel->render_vaapi_surface(img, va_surface);
+            if(va_surface)
+              lprintf("handle_buffer: render_vaapi_surface va_surface_id 0x%08x\n", this->av_frame->data[0]);
+          }
+        }
+
         this->skipframes = img->draw(img, this->stream);
 
         if(free_img)
@@ -1718,6 +1991,9 @@ static void ff_dispose (video_decoder_t *this_gen) {
 
   xine_list_delete(this->dr1_frames);
 
+  if(this->accel_img)
+    this->accel_img->free(this->accel_img);
+
   free (this_gen);
 }
 
@@ -1759,11 +2035,42 @@ static video_decoder_t *ff_video_open_plugin (video_decoder_class_t *class_gen,
   this->mpeg_parser       = NULL;
 
   this->dr1_frames        = xine_list_new();
+  this->set_stream_info   = 0;
 
 #ifdef LOG
   this->debug_fmt = -1;
 #endif
 
+  memset(&this->vaapi_context, 0x0 ,sizeof(struct vaapi_context));
+
+  this->dr1_frames        = xine_list_new();
+
+  this->accel             = NULL;
+  this->accel_img         = NULL;
+
+
+  if(this->class->enable_vaapi && (stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VAAPI)) {
+    xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: vaapi_mpeg_softdec %d\n"),
+          this->class->vaapi_mpeg_softdec );
+    xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: vaapi_mpeg_softdec_deinterlace %d\n"),
+          this->class->vaapi_mpeg_softdec_deinterlace );
+
+    this->accel_img  = stream->video_out->get_frame( stream->video_out, 1920, 1080, 1, XINE_IMGFMT_VAAPI, VO_BOTH_FIELDS );
+
+    if( this->accel_img ) {
+      this->accel = (vaapi_accel_t*)this->accel_img->accel_data;
+      xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: VAAPI Enabled in config.\n"));
+    } else {
+      this->class->enable_vaapi = 0;
+      xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: VAAPI Enabled disabled by driver.\n"));
+    }
+  } else {
+    this->class->enable_vaapi = 0;
+    this->class->vaapi_mpeg_softdec = 0;
+    this->class->vaapi_mpeg_softdec_deinterlace = 0;
+    xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: VAAPI Enabled disabled by driver.\n"));
+  }
+
   return &this->video_decoder;
 }
 
@@ -1823,6 +2130,21 @@ void *init_video_plugin (xine_t *xine, void *data) {
       "A change of this setting will take effect with playing the next stream."),
     10, choose_speed_over_accuracy_cb, this);
 
+  this->vaapi_mpeg_softdec = xine->config->register_bool(config, "video.processing.vaapi_mpeg_softdec", 0,
+    _("VAAPI Mpeg2 softdecoding"),
+    _("If the machine freezes on mpeg2 decoding use mpeg2 software decoding."),
+    10, vaapi_mpeg_softdec_func, this);
+
+  this->vaapi_mpeg_softdec_deinterlace = xine->config->register_bool(config, "video.processing.vaapi_mpeg_softdec_deinterlace", 0,
+    _("VAAPI Mpeg2 softdecoding deinterlace"),
+    _("FFMPEGS simple deinterlacer with Mpeg2 software decoding."),
+    10, vaapi_mpeg_softdec_deinterlace, this);
+
+  this->enable_vaapi = xine->config->register_bool(config, "video.processing.ffmpeg_enable_vaapi", 1,
+    _("Enable VAAPI"),
+    _("Enable or disable usage of vaapi"),
+    10, vaapi_enable_vaapi, this);
+
   return this;
 }
 
diff --git a/src/combined/ffmpeg/ffmpeg_decoder.c b/src/combined/ffmpeg/ffmpeg_decoder.c
index 4f9a0f7..a0314c8 100644
--- a/src/combined/ffmpeg/ffmpeg_decoder.c
+++ b/src/combined/ffmpeg/ffmpeg_decoder.c
@@ -39,6 +39,9 @@ void init_once_routine(void) {
   pthread_mutex_init(&ffmpeg_lock, NULL);
   avcodec_init();
   avcodec_register_all();
+
+  av_log_set_level(AV_LOG_QUIET);
+
 }
 
 /*
diff --git a/src/combined/ffmpeg/xine_video.list b/src/combined/ffmpeg/xine_video.list
index 009f4da..6364c45 100644
--- a/src/combined/ffmpeg/xine_video.list
+++ b/src/combined/ffmpeg/xine_video.list
@@ -70,7 +70,7 @@ WNV1 WNV1 Winnow Video
 XL VIXL Miro/Pinnacle VideoXL
 RT21 INDEO2 Indeo/RealTime 2
 FPS1 FRAPS Fraps
-MPEG MPEG1VIDEO MPEG 1/2
+MPEG MPEG2VIDEO MPEG 1/2
 CSCD CSCD CamStudio
 AVS AVS AVS
 ALGMM MMVIDEO American Laser Games MM
diff --git a/src/post/deinterlace/xine_plugin.c b/src/post/deinterlace/xine_plugin.c
index 5615e4b..d96aafb 100644
--- a/src/post/deinterlace/xine_plugin.c
+++ b/src/post/deinterlace/xine_plugin.c
@@ -437,6 +437,8 @@ static void deinterlace_dispose(post_plugin_t *this_gen)
   if (_x_post_dispose(this_gen)) {
     _flush_frames(this);
     pthread_mutex_destroy(&this->lock);
+    if(this->tvtime)
+      free(this->tvtime );
     free(this);
   }
 }
diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am
index 45a6f03..76708e2 100644
--- a/src/video_out/Makefile.am
+++ b/src/video_out/Makefile.am
@@ -43,6 +43,8 @@ if ENABLE_VDPAU
 vdpau_module = xineplug_vo_out_vdpau.la
 endif
 
+vaapi_module = xineplug_vo_out_vaapi.la
+
 if ENABLE_XCB
 XCBOSD = xcbosd.c
 if ENABLE_XCBSHM
@@ -117,6 +119,7 @@ xineplug_LTLIBRARIES = $(xshm_module) $(xv_module) $(xvmc_module) \
   $(xcbshm_module) \
   $(xcbxv_module) \
   $(vdpau_module) \
+  $(vaapi_module) \
                   xineplug_vo_out_raw.la \
                   xineplug_vo_out_none.la
 
@@ -124,6 +127,10 @@ xineplug_vo_out_vdpau_la_SOURCES = video_out_vdpau.c
 xineplug_vo_out_vdpau_la_LIBADD = $(YUV_LIBS) $(PTHREAD_LIBS) $(X_LIBS) $(LTLIBINTL) $(VDPAU_LIBS) -lm
 xineplug_vo_out_vdpau_la_CFLAGS = $(VISIBILITY_FLAG) $(MLIB_CFLAGS) $(X_CFLAGS) $(VDPAU_CFLAGS)
 
+xineplug_vo_out_vaapi_la_SOURCES = $(X11OSD) video_out_vaapi.c
+xineplug_vo_out_vaapi_la_LIBADD = $(YUV_LIBS) $(XINE_LIB) $(OPENGL_LIBS) $(FFMPEG_LIBS) $(AVUTIL_LIBS) $(X_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) -ldl -lGLU -lva-glx -lva-x11 -lva
+xineplug_vo_out_vaapi_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) $(XV_CFLAGS) -fno-strict-aliasing
+
 xineplug_vo_out_xcbshm_la_SOURCES = video_out_xcbshm.c $(XCBOSD)
 xineplug_vo_out_xcbshm_la_LIBADD = $(YUV_LIBS) $(PTHREAD_LIBS) $(XCB_LIBS) $(XCBSHM_LIBS) $(LTLIBINTL)
 xineplug_vo_out_xcbshm_la_CFLAGS = $(AM_CFLAGS) $(XCB_CFLAGS) $(XCBSHM_CFLAGS) $(AVUTIL_CFLAGS)
diff --git a/src/video_out/video_out_vaapi.c b/src/video_out/video_out_vaapi.c
new file mode 100644
index 0000000..42a6360
--- /dev/null
+++ b/src/video_out/video_out_vaapi.c
@@ -0,0 +1,3951 @@
+/*
+ * Copyright (C) 2000-2004, 2008 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine 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.
+ *
+ * xine 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, USA
+ *
+ * video_out_vaapi.c, VAAPI video extension interface for xine
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+
+#include <sys/types.h>
+#if defined(__FreeBSD__)
+#include <machine/param.h>
+#endif
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/time.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/cursorfont.h>
+#include <time.h>
+#include <unistd.h>
+#include "yuv2rgb.h"
+
+#define LOG_MODULE "video_out_vaapi"
+#define LOG_VERBOSE
+/*
+#define LOG
+*/
+/*
+#define DEBUG_SURFACE
+*/
+#include "xine.h"
+#include <xine/video_out.h>
+#include <xine/xine_internal.h>
+#include <xine/xineutils.h>
+#include <xine/vo_scale.h>
+
+#include <GL/glu.h>
+#include <GL/glx.h>
+#include <GL/glext.h>
+#include <GL/gl.h>
+#include <dlfcn.h>
+
+#include <va/va_x11.h>
+#include <va/va_glx.h>
+
+#include "accel_vaapi.h"
+
+#define  RENDER_SURFACES  50
+#define  SOFT_SURFACES    3
+#define  SW_WIDTH         1920
+#define  SW_HEIGHT        1080
+#define  STABLE_FRAME_COUNTER 4
+#define  SW_CONTEXT_INIT_FORMAT -1 //VAProfileH264Main
+
+#if defined VA_SRC_BT601 && defined VA_SRC_BT709
+# define USE_VAAPI_COLORSPACE 1
+#else
+# define USE_VAAPI_COLORSPACE 0
+#endif
+
+#define IMGFMT_VAAPI               0x56410000 /* 'VA'00 */
+#define IMGFMT_VAAPI_MASK          0xFFFF0000
+#define IMGFMT_IS_VAAPI(fmt)       (((fmt) & IMGFMT_VAAPI_MASK) == IMGFMT_VAAPI)
+#define IMGFMT_VAAPI_CODEC_MASK    0x000000F0
+#define IMGFMT_VAAPI_CODEC(fmt)    ((fmt) & IMGFMT_VAAPI_CODEC_MASK)
+#define IMGFMT_VAAPI_CODEC_MPEG2   (0x10)
+#define IMGFMT_VAAPI_CODEC_MPEG4   (0x20)
+#define IMGFMT_VAAPI_CODEC_H264    (0x30)
+#define IMGFMT_VAAPI_CODEC_VC1     (0x40)
+#define IMGFMT_VAAPI_MPEG2         (IMGFMT_VAAPI|IMGFMT_VAAPI_CODEC_MPEG2)
+#define IMGFMT_VAAPI_MPEG2_IDCT    (IMGFMT_VAAPI|IMGFMT_VAAPI_CODEC_MPEG2|1)
+#define IMGFMT_VAAPI_MPEG2_MOCO    (IMGFMT_VAAPI|IMGFMT_VAAPI_CODEC_MPEG2|2)
+#define IMGFMT_VAAPI_MPEG4         (IMGFMT_VAAPI|IMGFMT_VAAPI_CODEC_MPEG4)
+#define IMGFMT_VAAPI_H263          (IMGFMT_VAAPI|IMGFMT_VAAPI_CODEC_MPEG4|1)
+#define IMGFMT_VAAPI_H264          (IMGFMT_VAAPI|IMGFMT_VAAPI_CODEC_H264)
+#define IMGFMT_VAAPI_VC1           (IMGFMT_VAAPI|IMGFMT_VAAPI_CODEC_VC1)
+#define IMGFMT_VAAPI_WMV3          (IMGFMT_VAAPI|IMGFMT_VAAPI_CODEC_VC1|1)
+
+#define FOVY     60.0f
+#define ASPECT   1.0f
+#define Z_NEAR   0.1f
+#define Z_FAR    100.0f
+#define Z_CAMERA 0.869f
+
+#ifndef GLAPIENTRY
+#ifdef APIENTRY
+#define GLAPIENTRY APIENTRY
+#else
+#define GLAPIENTRY
+#endif
+#endif
+
+#if defined(__linux__)
+// Linux select() changes its timeout parameter upon return to contain
+// the remaining time. Most other unixen leave it unchanged or undefined.
+#define SELECT_SETS_REMAINING
+#elif defined(__FreeBSD__) || defined(__sun__) || (defined(__MACH__) && defined(__APPLE__))
+#define USE_NANOSLEEP
+#elif defined(HAVE_PTHREADS) && defined(sgi)
+// SGI pthreads has a bug when using pthreads+signals+nanosleep,
+// so instead of using nanosleep, wait on a CV which is never signalled.
+#include <pthread.h>
+#define USE_COND_TIMEDWAIT
+#endif
+
+#define RECT_IS_EQ(a, b) ((a).x1 == (b).x1 && (a).y1 == (b).y1 && (a).x2 == (b).x2 && (a).y2 == (b).y2)
+
+static const char *const scaling_level_enum_names[] = {
+  "default",  /* VA_FILTER_SCALING_DEFAULT       */
+  "fast",     /* VA_FILTER_SCALING_FAST          */
+  "hq",       /* VA_FILTER_SCALING_HQ            */
+  "nla",      /* VA_FILTER_SCALING_NL_ANAMORPHIC */
+  NULL
+};
+
+static const int scaling_level_enum_values[] = {
+  VA_FILTER_SCALING_DEFAULT,
+  VA_FILTER_SCALING_FAST,
+  VA_FILTER_SCALING_HQ,
+  VA_FILTER_SCALING_NL_ANAMORPHIC
+};
+
+typedef struct vaapi_driver_s vaapi_driver_t;
+
+typedef struct {
+    int x0, y0;
+    int x1, y1, x2, y2;
+} vaapi_rect_t;
+
+typedef struct {
+  vo_frame_t         vo_frame;
+
+  int                width, height, format, flags;
+  double             ratio;
+
+  vaapi_accel_t     vaapi_accel_data;
+} vaapi_frame_t;
+
+typedef struct {
+  VADisplayAttribType type;
+  int                 value;
+  int                 min;
+  int                 max;
+  int                 atom;
+
+  cfg_entry_t        *entry;
+
+  vaapi_driver_t     *this;
+
+} va_property_t;
+
+struct vaapi_driver_s {
+
+  vo_driver_t        vo_driver;
+
+  config_values_t   *config;
+
+  /* X11 related stuff */
+  Display            *display;
+  int                 screen;
+  Drawable            drawable;
+  XColor              black;
+  Window              window;
+
+  uint32_t            capabilities;
+
+  int ovl_changed;
+  vo_overlay_t       *overlays[XINE_VORAW_MAX_OVL];
+  uint32_t           *overlay_bitmap;
+  int                 overlay_bitmap_size;
+  uint32_t            overlay_bitmap_width;
+  uint32_t            overlay_bitmap_height;
+  vaapi_rect_t        overlay_bitmap_src;
+  vaapi_rect_t        overlay_bitmap_dst;
+
+  uint32_t            vdr_osd_width;
+  uint32_t            vdr_osd_height;
+
+  uint32_t            overlay_output_width;
+  uint32_t            overlay_output_height;
+  vaapi_rect_t        overlay_dirty_rect;
+  int                 has_overlay;
+
+  uint32_t            overlay_unscaled_width;
+  uint32_t            overlay_unscaled_height;
+  vaapi_rect_t        overlay_unscaled_dirty_rect;
+
+  yuv2rgb_factory_t  *yuv2rgb_factory;
+  yuv2rgb_t          *ovl_yuv2rgb;
+
+  /* all scaling information goes here */
+  vo_scale_t          sc;
+
+  xine_t             *xine;
+
+  unsigned int        deinterlace;
+  
+  int                 valid_opengl_context;
+  int                 opengl_render;
+  int                 opengl_use_tfp;
+  int                 query_va_status;
+
+  GLuint              gl_texture;
+  GLXContext          gl_context;
+  XVisualInfo         *gl_vinfo;
+  Pixmap              gl_pixmap;
+  Pixmap              gl_image_pixmap;
+
+  ff_vaapi_context_t  *va_context;
+
+  int                  num_frame_buffers;
+  vaapi_frame_t       *frames[RENDER_SURFACES];
+
+  pthread_mutex_t     vaapi_lock;
+
+  unsigned int        init_opengl_render;
+  unsigned int        guarded_render;
+  unsigned int        scaling_level_enum;
+  unsigned int        scaling_level;
+  va_property_t       props[VO_NUM_PROPERTIES];
+  unsigned int        swap_uv_planes;
+};
+
+ff_vaapi_surface_t  *va_render_surfaces   = NULL;
+VASurfaceID         *va_surface_ids       = NULL;
+VASurfaceID         *va_soft_surface_ids  = NULL;
+VAImage             *va_soft_images       = NULL;
+
+static void vaapi_destroy_subpicture(vo_driver_t *this_gen);
+static void vaapi_destroy_image(vo_driver_t *this_gen, VAImage *va_image);
+static int vaapi_ovl_associate(vo_driver_t *this_gen, int format, int bShow);
+static VAStatus vaapi_destroy_soft_surfaces(vo_driver_t *this_gen);
+static VAStatus vaapi_destroy_render_surfaces(vo_driver_t *this_gen);
+static const char *vaapi_profile_to_string(VAProfile profile);
+static int vaapi_set_property (vo_driver_t *this_gen, int property, int value);
+static void vaapi_show_display_props(vo_driver_t *this_gen);
+
+static void nv12_to_yv12(const uint8_t *y_src,  int y_src_pitch,
+                         const uint8_t *uv_src, int uv_src_pitch,
+                         uint8_t *y_dst, int y_dst_pitch,
+                         uint8_t *u_dst, int u_dst_pitch,
+                         uint8_t *v_dst, int v_dst_pitch,
+                         int src_width, int src_height,
+                         int dst_width, int dst_height,
+                         int src_data_size);
+
+static void yv12_to_nv12(const uint8_t *y_src, int y_src_pitch,
+                         const uint8_t *u_src, int u_src_pitch,
+                         const uint8_t *v_src, int v_src_pitch,
+                         uint8_t *y_dst,  int y_dst_pitch,
+                         uint8_t *uv_dst, int uv_dst_pitch,
+                         int src_width, int src_height,
+                         int dst_width, int dst_height,
+                         int dst_data_size);
+
+void (GLAPIENTRY *mpglGenTextures)(GLsizei, GLuint *);
+void (GLAPIENTRY *mpglBindTexture)(GLenum, GLuint);
+void (GLAPIENTRY *mpglXBindTexImage)(Display *, GLXDrawable, int, const int *);
+void (GLAPIENTRY *mpglXReleaseTexImage)(Display *, GLXDrawable, int);
+GLXPixmap (GLAPIENTRY *mpglXCreatePixmap)(Display *, GLXFBConfig, Pixmap, const int *);
+void (GLAPIENTRY *mpglXDestroyPixmap)(Display *, GLXPixmap);
+const GLubyte *(GLAPIENTRY *mpglGetString)(GLenum);
+void (GLAPIENTRY *mpglGenPrograms)(GLsizei, GLuint *);
+
+static const char *string_of_VAImageFormat(VAImageFormat *imgfmt)
+{
+  static char str[5];
+  str[0] = imgfmt->fourcc;
+  str[1] = imgfmt->fourcc >> 8;
+  str[2] = imgfmt->fourcc >> 16;
+  str[3] = imgfmt->fourcc >> 24;
+  str[4] = '\0';
+  return str;
+}
+
+static int vaapi_check_status(vo_driver_t *this_gen, VAStatus vaStatus, const char *msg)
+{
+
+  vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
+
+  if (vaStatus != VA_STATUS_SUCCESS) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " Error : %s: %s\n", msg, vaErrorStr(vaStatus));
+    return 0;
+  }
+  return 1;
+}
+
+/* Wrapper for ffmpeg avcodec_decode_video2 */
+#if AVVIDEO > 1
+static int guarded_avcodec_decode_video2(vo_frame_t *frame_gen, AVCodecContext *avctx, AVFrame *picture,
+                                         int *got_picture_ptr, AVPacket *avpkt) {
+
+  vaapi_driver_t  *this = (vaapi_driver_t *) frame_gen->driver;
+
+  int len = 0;
+
+
+  if(this->guarded_render) {
+    lprintf("guarded_avcodec_decode_video2 enter\n");
+    pthread_mutex_lock(&this->vaapi_lock);
+    //XLockDisplay( this->display );
+  }
+
+  len = avcodec_decode_video2 (avctx, picture, got_picture_ptr, avpkt);
+
+  if(this->guarded_render) {
+    //XUnlockDisplay( this->display );
+    pthread_mutex_unlock(&this->vaapi_lock);
+    lprintf("guarded_avcodec_decode_video2 exit\n");
+  }
+
+
+  return len;
+}
+#else
+static int guarded_avcodec_decode_video(vo_frame_t *frame_gen, AVCodecContext *avctx, AVFrame *picture,
+                                        int *got_picture_ptr, uint8_t *buf, int buf_size) {
+
+  vaapi_driver_t  *this = (vaapi_driver_t *) frame_gen->driver;
+
+  int len = 0;
+
+
+  if(this->guarded_render) {
+    lprintf("guarded_avcodec_decode_video enter\n");
+    pthread_mutex_lock(&this->vaapi_lock);
+    //XLockDisplay( this->display );
+  }
+
+  len = avcodec_decode_video (avctx, picture, got_picture_ptr, buf, buf_size);
+
+  if(this->guarded_render) {
+    //XUnlockDisplay( this->display );
+    pthread_mutex_unlock(&this->vaapi_lock);
+    lprintf("guarded_avcodec_decode_video exit\n");
+  }
+
+
+  return len;
+}
+#endif
+
+static int guarded_render(vo_frame_t *frame_gen) {
+  vaapi_driver_t  *this = (vaapi_driver_t *) frame_gen->driver;
+
+  return this->guarded_render;
+}
+
+static ff_vaapi_surface_t *get_vaapi_surface(vo_frame_t *frame_gen) {
+
+  vaapi_driver_t      *this       = (vaapi_driver_t *) frame_gen->driver;
+  vaapi_frame_t       *frame      = (vaapi_frame_t *) frame_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  ff_vaapi_surface_t  *va_surface = NULL;
+  VAStatus            vaStatus;
+
+  lprintf("get_vaapi_surface\n");
+
+  if(!va_render_surfaces)
+    return NULL;
+
+  if(this->guarded_render) {
+    /* Get next VAAPI surface marked as SURFACE_FREE */
+    for(;;) {
+      int old_head = va_context->va_head;
+      va_context->va_head = (va_context->va_head + 1) % ((RENDER_SURFACES));
+
+      va_surface = &va_render_surfaces[old_head];
+
+      if( va_surface->status == SURFACE_FREE ) {
+
+        VASurfaceStatus surf_status = 0;
+
+        if(this->query_va_status) {
+          vaStatus = vaQuerySurfaceStatus(va_context->va_display, va_surface->va_surface_id, &surf_status);
+          vaapi_check_status(va_context->driver, vaStatus, "vaQuerySurfaceStatus()");
+        } else {
+          surf_status = VASurfaceReady;
+        }
+
+        if(surf_status == VASurfaceReady) {
+
+          va_surface->status = SURFACE_ALOC;
+
+#ifdef DEBUG_SURFACE
+          printf("get_vaapi_surface 0x%08x\n", va_surface->va_surface_id);
+#endif
+
+          return &va_render_surfaces[old_head];
+        } else {
+#ifdef DEBUG_SURFACE
+          printf("get_vaapi_surface busy\n");
+#endif
+        }
+      }
+#ifdef DEBUG_SURFACE
+      printf("get_vaapi_surface miss\n");
+#endif
+    }
+  } else {
+      va_surface = &va_render_surfaces[frame->vaapi_accel_data.index];
+  }
+
+  return va_surface;
+}
+
+/* Set VAAPI surface status to render */
+static void render_vaapi_surface(vo_frame_t *frame_gen, ff_vaapi_surface_t *va_surface) {
+  vaapi_driver_t  *this = (vaapi_driver_t *) frame_gen->driver;
+  vaapi_accel_t *accel = (vaapi_accel_t*)frame_gen->accel_data;
+
+  lprintf("render_vaapi_surface\n");
+
+  if(!this->guarded_render || !accel || !va_surface)
+    return;
+
+  pthread_mutex_lock(&this->vaapi_lock);
+  //XLockDisplay( this->display );
+
+  accel->index = va_surface->index;
+
+  va_surface->status = SURFACE_RENDER;
+#ifdef DEBUG_SURFACE
+  printf("render_vaapi_surface 0x%08x\n", va_surface->va_surface_id);
+#endif
+
+  //XUnlockDisplay( this->display );
+  pthread_mutex_unlock(&this->vaapi_lock);
+}
+
+/* Set VAAPI surface status to free */
+static void release_vaapi_surface(vo_frame_t *frame_gen, ff_vaapi_surface_t *va_surface) {
+  vaapi_driver_t  *this = (vaapi_driver_t *) frame_gen->driver;
+
+  lprintf("release_vaapi_surface\n");
+
+  if(va_surface == NULL || !this->guarded_render) {
+    return;
+  }
+
+  if(va_surface->status == SURFACE_RENDER) {
+    va_surface->status = SURFACE_RENDER_RELEASE;
+  } else if (va_surface->status != SURFACE_RENDER_RELEASE) {
+    va_surface->status = SURFACE_FREE;
+#ifdef DEBUG_SURFACE
+    printf("release_surface 0x%08x\n", va_surface->va_surface_id);
+#endif
+  }
+}
+
+static VADisplay vaapi_get_display(Display *display, int opengl_render)
+{
+  VADisplay ret;
+
+  if(opengl_render) {
+    ret = vaGetDisplayGLX(display);
+  } else {
+    ret = vaGetDisplay(display);
+  }
+
+  if(vaDisplayIsValid(ret))
+    return ret;
+  else
+    return 0;
+}
+
+typedef struct {
+  void *funcptr;
+  const char *extstr;
+  const char *funcnames[7];
+  void *fallback;
+} extfunc_desc_t;
+
+#define DEF_FUNC_DESC(name) {&mpgl##name, NULL, {"gl"#name, NULL}, gl ##name}
+static const extfunc_desc_t extfuncs[] = {
+  DEF_FUNC_DESC(GenTextures),
+
+  {&mpglBindTexture, NULL, {"glBindTexture", "glBindTextureARB", "glBindTextureEXT", NULL}},
+  {&mpglXBindTexImage, "GLX_EXT_texture_from_pixmap", {"glXBindTexImageEXT", NULL}},
+  {&mpglXReleaseTexImage, "GLX_EXT_texture_from_pixmap", {"glXReleaseTexImageEXT", NULL}},
+  {&mpglXCreatePixmap, "GLX_EXT_texture_from_pixmap", {"glXCreatePixmap", NULL}},
+  {&mpglXDestroyPixmap, "GLX_EXT_texture_from_pixmap", {"glXDestroyPixmap", NULL}},
+  {&mpglGenPrograms, "_program", {"glGenProgramsARB", NULL}},
+  {NULL}
+};
+
+typedef struct {
+  video_driver_class_t driver_class;
+
+  config_values_t     *config;
+  xine_t              *xine;
+} vaapi_class_t;
+
+static int gl_visual_attr[] = {
+  GLX_RGBA,
+  GLX_RED_SIZE, 1,
+  GLX_GREEN_SIZE, 1,
+  GLX_BLUE_SIZE, 1,
+  GLX_DOUBLEBUFFER,
+  GL_NONE
+};
+
+static void delay_usec(unsigned int usec)
+{
+    int was_error;
+
+#if defined(USE_NANOSLEEP)
+    struct timespec elapsed, tv;
+#elif defined(USE_COND_TIMEDWAIT)
+    // Use a local mutex and cv, so threads remain independent
+    pthread_cond_t delay_cond = PTHREAD_COND_INITIALIZER;
+    pthread_mutex_t delay_mutex = PTHREAD_MUTEX_INITIALIZER;
+    struct timespec elapsed;
+    uint64_t future;
+#else
+    struct timeval tv;
+#ifndef SELECT_SETS_REMAINING
+    uint64_t then, now, elapsed;
+#endif
+#endif
+
+    // Set the timeout interval - Linux only needs to do this once
+#if defined(SELECT_SETS_REMAINING)
+    tv.tv_sec = 0;
+    tv.tv_usec = usec;
+#elif defined(USE_NANOSLEEP)
+    elapsed.tv_sec = 0;
+    elapsed.tv_nsec = usec * 1000;
+#elif defined(USE_COND_TIMEDWAIT)
+    future = get_ticks_usec() + usec;
+    elapsed.tv_sec = future / 1000000;
+    elapsed.tv_nsec = (future % 1000000) * 1000;
+#else
+    then = get_ticks_usec();
+#endif
+
+    do {
+        errno = 0;
+#if defined(USE_NANOSLEEP)
+        tv.tv_sec = elapsed.tv_sec;
+        tv.tv_nsec = elapsed.tv_nsec;
+        was_error = nanosleep(&tv, &elapsed);
+#elif defined(USE_COND_TIMEDWAIT)
+        was_error = pthread_mutex_lock(&delay_mutex);
+        was_error = pthread_cond_timedwait(&delay_cond, &delay_mutex, &elapsed);
+        was_error = pthread_mutex_unlock(&delay_mutex);
+#else
+#ifndef SELECT_SETS_REMAINING
+        // Calculate the time interval left (in case of interrupt)
+        now = get_ticks_usec();
+        elapsed = now - then;
+        then = now;
+        if (elapsed >= usec)
+            break;
+        usec -= elapsed;
+        tv.tv_sec = 0;
+        tv.tv_usec = usec;
+#endif
+        was_error = select(0, NULL, NULL, NULL, &tv);
+#endif
+    } while (was_error && (errno == EINTR));
+}
+
+static void vaapi_x11_wait_event(Display *dpy, Window w, int type)
+{
+  XEvent e;
+  while (!XCheckTypedWindowEvent(dpy, w, type, &e))
+    delay_usec(10);
+}
+
+/* X11 Error handler and error functions */
+static int vaapi_x11_error_code = 0;
+static int (*vaapi_x11_old_error_handler)(Display *, XErrorEvent *);
+
+static int vaapi_x11_error_handler(Display *dpy, XErrorEvent *error)
+{
+    vaapi_x11_error_code = error->error_code;
+    return 0;
+}
+
+static void vaapi_x11_trap_errors(void)
+{
+    vaapi_x11_error_code    = 0;
+    vaapi_x11_old_error_handler = XSetErrorHandler(vaapi_x11_error_handler);
+}
+
+static int vaapi_x11_untrap_errors(void)
+{
+    XSetErrorHandler(vaapi_x11_old_error_handler);
+    return vaapi_x11_error_code;
+}
+
+static void vaapi_appendstr(char **dst, const char *str)
+{
+    int newsize;
+    char *newstr;
+    if (!str)
+        return;
+    newsize = strlen(*dst) + 1 + strlen(str) + 1;
+    newstr = realloc(*dst, newsize);
+    if (!newstr)
+        return;
+    *dst = newstr;
+    strcat(*dst, " ");
+    strcat(*dst, str);
+}
+
+/* Return the address of a linked function */
+static void *vaapi_getdladdr (const char *s) {
+  void *ret = NULL;
+  void *handle = dlopen(NULL, RTLD_LAZY);
+  if (!handle)
+    return NULL;
+  ret = dlsym(handle, s);
+  dlclose(handle);
+
+  return ret;
+}
+
+/* Resolve opengl functions. */
+static void vaapi_get_functions(vo_driver_t *this_gen, void *(*getProcAddress)(const GLubyte *),
+                         const char *ext2) {
+  const extfunc_desc_t *dsc;
+  const char *extensions;
+  char *allexts;
+
+  if (!getProcAddress)
+    getProcAddress = (void *)vaapi_getdladdr;
+
+  /* special case, we need glGetString before starting to find the other functions */
+  mpglGetString = getProcAddress("glGetString");
+  if (!mpglGetString)
+      mpglGetString = glGetString;
+
+  extensions = (const char *)mpglGetString(GL_EXTENSIONS);
+  if (!extensions) extensions = "";
+  if (!ext2) ext2 = "";
+  allexts = malloc(strlen(extensions) + strlen(ext2) + 2);
+  strcpy(allexts, extensions);
+  strcat(allexts, " ");
+  strcat(allexts, ext2);
+  lprintf("vaapi_get_functions: OpenGL extensions string:\n%s\n", allexts);
+  for (dsc = extfuncs; dsc->funcptr; dsc++) {
+    void *ptr = NULL;
+    int i;
+    if (!dsc->extstr || strstr(allexts, dsc->extstr)) {
+      for (i = 0; !ptr && dsc->funcnames[i]; i++)
+        ptr = getProcAddress((const GLubyte *)dsc->funcnames[i]);
+    }
+    if (!ptr)
+        ptr = dsc->fallback;
+    *(void **)dsc->funcptr = ptr;
+  }
+  lprintf("\n");
+  free(allexts);
+}
+
+/* Check if opengl indirect/software rendering is used */
+static int vaapi_opengl_verify_direct (x11_visual_t *vis) {
+  Window        root, win;
+  XVisualInfo  *visinfo;
+  GLXContext    ctx;
+  XSetWindowAttributes xattr;
+  int           ret = 0;
+
+  if (!vis || !vis->display || ! (root = RootWindow (vis->display, vis->screen))) {
+    lprintf ("vaapi_opengl_verify_direct: Don't have a root window to verify\n");
+    return 0;
+  }
+
+  if (! (visinfo = glXChooseVisual (vis->display, vis->screen, gl_visual_attr)))
+    return 0;
+
+  if (! (ctx = glXCreateContext (vis->display, visinfo, NULL, 1)))
+    return 0;
+
+  memset (&xattr, 0, sizeof (xattr));
+  xattr.colormap = XCreateColormap(vis->display, root, visinfo->visual, AllocNone);
+  xattr.event_mask = StructureNotifyMask | ExposureMask;
+
+  if ( (win = XCreateWindow (vis->display, root, 0, 0, 1, 1, 0, visinfo->depth,
+                       InputOutput, visinfo->visual,
+                       CWBackPixel | CWBorderPixel | CWColormap | CWEventMask,
+                       &xattr))) {
+    if (glXMakeCurrent (vis->display, win, ctx)) {
+    const char *renderer = (const char *) glGetString(GL_RENDERER);
+    if (glXIsDirect (vis->display, ctx) &&
+                ! strstr (renderer, "Software") &&
+                ! strstr (renderer, "Indirect"))
+      ret = 1;
+      glXMakeCurrent (vis->display, None, NULL);
+      }
+      XDestroyWindow (vis->display, win);
+  }
+  glXDestroyContext (vis->display, ctx);
+  XFreeColormap     (vis->display, xattr.colormap);
+
+  return ret;
+}
+
+static int vaapi_glx_bind_texture(vo_driver_t *this_gen)
+{
+  vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
+
+  glEnable(GL_TEXTURE_2D);
+  mpglBindTexture(GL_TEXTURE_2D, this->gl_texture);
+
+  if (this->opengl_use_tfp) {
+    vaapi_x11_trap_errors();
+    mpglXBindTexImage(this->display, this->gl_pixmap, GLX_FRONT_LEFT_EXT, NULL);
+    XSync(this->display, False);
+    if (vaapi_x11_untrap_errors())
+      xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_bind_texture : Update bind_tex_image failed\n");
+  }
+
+  return 0;
+}
+
+static int vaapi_glx_unbind_texture(vo_driver_t *this_gen)
+{
+  vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
+
+  if (this->opengl_use_tfp) {
+    vaapi_x11_trap_errors();
+    mpglXReleaseTexImage(this->display, this->gl_pixmap, GLX_FRONT_LEFT_EXT);
+    if (vaapi_x11_untrap_errors())
+      xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_unbind_texture : Failed to release?\n");
+  }
+
+  mpglBindTexture(GL_TEXTURE_2D, 0);
+  glDisable(GL_TEXTURE_2D);
+  return 0;
+}
+
+static void vaapi_glx_render_frame(vo_frame_t *frame_gen, int left, int top, int right, int bottom)
+{
+  vaapi_driver_t        *this = (vaapi_driver_t *) frame_gen->driver;
+  vaapi_frame_t         *frame = (vaapi_frame_t *) frame_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+  int             x1, x2, y1, y2;
+  float           tx, ty;
+
+  if (vaapi_glx_bind_texture(frame_gen->driver) < 0)
+    return;
+
+  /* Calc texture/rectangle coords */
+  x1 = this->sc.output_xoffset;
+  y1 = this->sc.output_yoffset;
+  x2 = x1 + this->sc.output_width;
+  y2 = y1 + this->sc.output_height;
+  tx = (float) frame->width  / va_context->width;
+  ty = (float) frame->height / va_context->height;
+
+  glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+  /* Draw quad */
+  glBegin (GL_QUADS);
+
+    glTexCoord2f (tx, ty);   glVertex2i (x2, y2);
+    glTexCoord2f (0,  ty);   glVertex2i (x1, y2);
+    glTexCoord2f (0,  0);    glVertex2i (x1, y1);
+    glTexCoord2f (tx, 0);    glVertex2i (x2, y1);
+    lprintf("render_frame left %d top %d right %d bottom %d\n", x1, y1, x2, y2);
+
+  glEnd ();
+
+  if (vaapi_glx_unbind_texture(frame_gen->driver) < 0)
+    return;
+}
+
+static void vaapi_glx_flip_page(vo_frame_t *frame_gen, int left, int top, int right, int bottom)
+{
+  vaapi_driver_t *this = (vaapi_driver_t *) frame_gen->driver;
+
+  glClear(GL_COLOR_BUFFER_BIT);
+
+  vaapi_glx_render_frame(frame_gen, left, top, right, bottom);
+
+  //if (gl_finish)
+  //  glFinish();
+
+  glXSwapBuffers(this->display, this->window);
+
+}
+
+static void destroy_glx(vo_driver_t *this_gen)
+{
+  vaapi_driver_t        *this       = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+
+  if(!this->opengl_render || !va_context->valid_context)
+    return;
+
+  //if (gl_finish)
+  //  glFinish();
+
+  if(va_context->gl_surface) {
+    VAStatus vaStatus = vaDestroySurfaceGLX(va_context->va_display, va_context->gl_surface);
+    vaapi_check_status(this_gen, vaStatus, "vaDestroySurfaceGLX()");
+    va_context->gl_surface = NULL;
+  }
+
+  if(this->gl_context)
+    glXMakeCurrent(this->display, None, NULL);
+
+  if(this->gl_pixmap) {
+    vaapi_x11_trap_errors();
+    mpglXDestroyPixmap(this->display, this->gl_pixmap);
+    XSync(this->display, False);
+    vaapi_x11_untrap_errors();
+    this->gl_pixmap = None;
+  }
+
+  if(this->gl_image_pixmap) {
+    XFreePixmap(this->display, this->gl_image_pixmap);
+    this->gl_image_pixmap = None;
+  }
+
+  if(this->gl_texture) {
+    glDeleteTextures(1, &this->gl_texture);
+    this->gl_texture = GL_NONE;
+  }
+
+  if(this->gl_context) {
+    glXDestroyContext(this->display, this->gl_context);
+    this->gl_context = 0;
+  }
+
+  if(this->gl_vinfo) {
+    XFree(this->gl_vinfo);
+    this->gl_vinfo = NULL;
+  }
+
+  this->valid_opengl_context = 0;
+}
+
+static GLXFBConfig *get_fbconfig_for_depth(vo_driver_t *this_gen, int depth)
+{
+  vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
+
+    GLXFBConfig *fbconfigs, *ret = NULL;
+    int          n_elements, i, found;
+    int          db, stencil, alpha, rgba, value;
+
+    static GLXFBConfig *cached_config = NULL;
+    static int          have_cached_config = 0;
+
+    if (have_cached_config)
+        return cached_config;
+
+    fbconfigs = glXGetFBConfigs(this->display, this->screen, &n_elements);
+
+    db      = SHRT_MAX;
+    stencil = SHRT_MAX;
+    rgba    = 0;
+
+    found = n_elements;
+
+    for (i = 0; i < n_elements; i++) {
+        XVisualInfo *vi;
+        int          visual_depth;
+
+        vi = glXGetVisualFromFBConfig(this->display, fbconfigs[i]);
+        if (!vi)
+            continue;
+
+        visual_depth = vi->depth;
+        XFree(vi);
+
+        if (visual_depth != depth)
+            continue;
+
+        glXGetFBConfigAttrib(this->display, fbconfigs[i], GLX_ALPHA_SIZE, &alpha);
+        glXGetFBConfigAttrib(this->display, fbconfigs[i], GLX_BUFFER_SIZE, &value);
+        if (value != depth && (value - alpha) != depth)
+            continue;
+
+        value = 0;
+        if (depth == 32) {
+            glXGetFBConfigAttrib(this->display, fbconfigs[i],
+                                 GLX_BIND_TO_TEXTURE_RGBA_EXT, &value);
+            if (value)
+                rgba = 1;
+        }
+
+        if (!value) {
+            if (rgba)
+                continue;
+
+            glXGetFBConfigAttrib(this->display, fbconfigs[i],
+                                 GLX_BIND_TO_TEXTURE_RGB_EXT, &value);
+            if (!value)
+                continue;
+        }
+
+        glXGetFBConfigAttrib(this->display, fbconfigs[i], GLX_DOUBLEBUFFER, &value);
+        if (value > db)
+            continue;
+        db = value;
+
+        glXGetFBConfigAttrib(this->display, fbconfigs[i], GLX_STENCIL_SIZE, &value);
+        if (value > stencil)
+            continue;
+        stencil = value;
+
+        found = i;
+    }
+
+    if (found != n_elements) {
+        ret = malloc(sizeof(*ret));
+        *ret = fbconfigs[found];
+    }
+
+    if (n_elements)
+        XFree(fbconfigs);
+
+    have_cached_config = 1;
+    cached_config = ret;
+    return ret;
+}
+
+static int vaapi_glx_config_tfp(vo_driver_t *this_gen, unsigned int width, unsigned int height)
+{
+  vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
+
+  GLXFBConfig *fbconfig;
+  int attribs[7], i = 0;
+  const int depth = 24;
+
+  if (!mpglXBindTexImage || !mpglXReleaseTexImage) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_tfp : No GLX texture-from-pixmap extension available\n");
+    return 0;
+  }
+
+  if (depth != 24 && depth != 32) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_tfp : color depth wrong.\n");
+    return 0;
+  }
+
+  this->gl_image_pixmap = XCreatePixmap(this->display, this->window, width, height, depth);
+  if (!this->gl_image_pixmap) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_tfp : Could not create X11 pixmap\n");
+    return 0;
+  }
+
+  fbconfig = get_fbconfig_for_depth(this_gen, depth);
+  if (!fbconfig) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_tfp : Could not find an FBConfig for 32-bit pixmap\n");
+    return 0;
+  }
+
+  attribs[i++] = GLX_TEXTURE_TARGET_EXT;
+  attribs[i++] = GLX_TEXTURE_2D_EXT;
+  attribs[i++] = GLX_TEXTURE_FORMAT_EXT;
+  if (depth == 24)
+    attribs[i++] = GLX_TEXTURE_FORMAT_RGB_EXT;
+  else if (depth == 32)
+    attribs[i++] = GLX_TEXTURE_FORMAT_RGBA_EXT;
+  attribs[i++] = GLX_MIPMAP_TEXTURE_EXT;
+  attribs[i++] = GL_FALSE;
+  attribs[i++] = None;
+
+  vaapi_x11_trap_errors();
+  this->gl_pixmap = mpglXCreatePixmap(this->display, *fbconfig, this->gl_image_pixmap, attribs);
+  XSync(this->display, False);
+  if (vaapi_x11_untrap_errors()) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_tfp : Could not create GLX pixmap\n");
+    return 0;
+  }
+
+  return 1;
+}
+
+static int vaapi_glx_config_glx(vo_driver_t *this_gen, unsigned int width, unsigned int height)
+{
+  vaapi_driver_t        *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+
+  this->gl_vinfo = glXChooseVisual(this->display, this->screen, gl_visual_attr);
+  if(!this->gl_vinfo) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_glx : error glXChooseVisual\n");
+    this->opengl_render = 0;
+  }
+
+  glXMakeCurrent(this->display, None, NULL);
+  this->gl_context = glXCreateContext (this->display, this->gl_vinfo, NULL, True);
+  if (this->gl_context) {
+    if(!glXMakeCurrent (this->display, this->window, this->gl_context)) {
+      xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_glx : error glXMakeCurrent\n");
+      goto error;
+    }
+  } else {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_glx : error glXCreateContext\n");
+    goto error;
+  }
+
+  void *(*getProcAddress)(const GLubyte *);
+  const char *(*glXExtStr)(Display *, int);
+  char *glxstr = strdup(" ");
+
+  getProcAddress = vaapi_getdladdr("glXGetProcAddress");
+  if (!getProcAddress)
+    getProcAddress = vaapi_getdladdr("glXGetProcAddressARB");
+  glXExtStr = vaapi_getdladdr("glXQueryExtensionsString");
+  if (glXExtStr)
+      vaapi_appendstr(&glxstr, glXExtStr(this->display, this->screen));
+  glXExtStr = vaapi_getdladdr("glXGetClientString");
+  if (glXExtStr)
+      vaapi_appendstr(&glxstr, glXExtStr(this->display, GLX_EXTENSIONS));
+  glXExtStr = vaapi_getdladdr("glXGetServerString");
+  if (glXExtStr)
+      vaapi_appendstr(&glxstr, glXExtStr(this->display, GLX_EXTENSIONS));
+
+  vaapi_get_functions(this_gen, getProcAddress, glxstr);
+  if (!mpglGenPrograms && mpglGetString &&
+      getProcAddress &&
+      strstr(mpglGetString(GL_EXTENSIONS), "GL_ARB_vertex_program")) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_glx : Broken glXGetProcAddress detected, trying workaround\n");
+    vaapi_get_functions(this_gen, NULL, glxstr);
+  }
+  free(glxstr);
+
+  glDisable(GL_DEPTH_TEST);
+  glDepthMask(GL_FALSE);
+  glDisable(GL_CULL_FACE);
+  glEnable(GL_TEXTURE_2D);
+  glDrawBuffer(GL_BACK);
+  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+  /* Create TFP resources */
+  if(this->opengl_use_tfp && vaapi_glx_config_tfp(this_gen, width, height)) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_glx : Using GLX texture-from-pixmap extension\n");
+  } else {
+    this->opengl_use_tfp = 0;
+  }
+
+  /* Create OpenGL texture */
+  /* XXX: assume GL_ARB_texture_non_power_of_two is available */
+  glEnable(GL_TEXTURE_2D);
+  glGenTextures(1, &this->gl_texture);
+  mpglBindTexture(GL_TEXTURE_2D, this->gl_texture);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  if (!this->opengl_use_tfp) {
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
+                 GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+  }
+  mpglBindTexture(GL_TEXTURE_2D, 0);
+  glDisable(GL_TEXTURE_2D);
+
+  glClearColor(0.0, 0.0, 0.0, 1.0);
+  glClear(GL_COLOR_BUFFER_BIT);
+
+  if(!this->gl_texture) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_glx_config_glx : gl_texture NULL\n");
+    goto error;
+  }
+
+  if(!this->opengl_use_tfp) {
+    VAStatus vaStatus = vaCreateSurfaceGLX(va_context->va_display, GL_TEXTURE_2D, this->gl_texture, &va_context->gl_surface);
+    if(!vaapi_check_status(this_gen, vaStatus, "vaCreateSurfaceGLX()")) {
+      va_context->gl_surface = NULL;
+      goto error;
+    }
+  } else {
+    va_context->gl_surface = NULL;
+  }
+
+  lprintf("vaapi_glx_config_glx : GL setup done\n");
+
+  this->valid_opengl_context = 1;
+  return 1;
+
+error:
+  destroy_glx(this_gen);
+  this->valid_opengl_context = 0;
+  return 0;
+}
+
+static uint32_t vaapi_get_capabilities (vo_driver_t *this_gen) {
+  vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
+
+  return this->capabilities;
+}
+
+static const struct {
+  int fmt;
+  enum PixelFormat pix_fmt;
+  enum CodecID codec_id;
+} conversion_map[] = {
+  {IMGFMT_VAAPI_MPEG2,     PIX_FMT_VAAPI_VLD,  CODEC_ID_MPEG2VIDEO},
+  {IMGFMT_VAAPI_MPEG2_IDCT,PIX_FMT_VAAPI_IDCT, CODEC_ID_MPEG2VIDEO},
+  {IMGFMT_VAAPI_MPEG2_MOCO,PIX_FMT_VAAPI_MOCO, CODEC_ID_MPEG2VIDEO},
+  {IMGFMT_VAAPI_MPEG4,     PIX_FMT_VAAPI_VLD,  CODEC_ID_MPEG4},
+  {IMGFMT_VAAPI_H263,      PIX_FMT_VAAPI_VLD,  CODEC_ID_H263},
+  {IMGFMT_VAAPI_H264,      PIX_FMT_VAAPI_VLD,  CODEC_ID_H264},
+  {IMGFMT_VAAPI_WMV3,      PIX_FMT_VAAPI_VLD,  CODEC_ID_WMV3},
+  {IMGFMT_VAAPI_VC1,       PIX_FMT_VAAPI_VLD,  CODEC_ID_VC1},
+  {0, PIX_FMT_NONE}
+};
+
+static int vaapi_pixfmt2imgfmt(enum PixelFormat pix_fmt, int codec_id)
+{
+  int i;
+  int fmt;
+  for (i = 0; conversion_map[i].pix_fmt != PIX_FMT_NONE; i++) {
+    if (conversion_map[i].pix_fmt == pix_fmt &&
+        (conversion_map[i].codec_id == 0 ||
+        conversion_map[i].codec_id == codec_id)) {
+      break;
+    }
+  }
+  fmt = conversion_map[i].fmt;
+  return fmt;
+}
+
+static int vaapi_has_profile(VAProfile *va_profiles, int va_num_profiles, VAProfile profile)
+{
+  if (va_profiles && va_num_profiles > 0) {
+    int i;
+    for (i = 0; i < va_num_profiles; i++) {
+      if (va_profiles[i] == profile)
+        return 1;
+      }
+  }
+  return 0;
+}
+
+static int profile_from_imgfmt(vo_frame_t *frame_gen, enum PixelFormat pix_fmt, int codec_id, int vaapi_mpeg_sofdec)
+{
+  vo_driver_t         *this_gen   = (vo_driver_t *) frame_gen->driver;
+  vaapi_driver_t      *this       = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  VAStatus            vaStatus;
+  int                 profile     = -1;
+  int                 maj, min;
+  int                 i;
+  int                 va_num_profiles;
+  int                 max_profiles;
+  VAProfile           *va_profiles = NULL;
+  int                 inited = 0;
+
+  if(va_context->va_display == NULL) {
+    lprintf("profile_from_imgfmt vaInitialize\n");
+    inited = 1;
+    va_context->va_display = vaapi_get_display(this->display, this->opengl_render);
+    if(!va_context->va_display)
+      goto out;
+
+    vaStatus = vaInitialize(va_context->va_display, &maj, &min);
+    if(!vaapi_check_status(this_gen, vaStatus, "vaInitialize()"))
+      goto out;
+
+  }
+
+  max_profiles = vaMaxNumProfiles(va_context->va_display);
+  va_profiles = calloc(max_profiles, sizeof(*va_profiles));
+  if (!va_profiles)
+    goto out;
+
+  vaStatus = vaQueryConfigProfiles(va_context->va_display, va_profiles, &va_num_profiles);
+  if(!vaapi_check_status(this_gen, vaStatus, "vaQueryConfigProfiles()"))
+    goto out;
+
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " VAAPI Supported Profiles : ");
+  for (i = 0; i < va_num_profiles; i++) {
+    printf("%s ", vaapi_profile_to_string(va_profiles[i]));
+  }
+  printf("\n");
+
+  uint32_t format = vaapi_pixfmt2imgfmt(pix_fmt, codec_id);
+
+  static const int mpeg2_profiles[] = { VAProfileMPEG2Main, VAProfileMPEG2Simple, -1 };
+  static const int mpeg4_profiles[] = { VAProfileMPEG4Main, VAProfileMPEG4AdvancedSimple, VAProfileMPEG4Simple, -1 };
+  static const int h264_profiles[]  = { VAProfileH264High, VAProfileH264Main, VAProfileH264Baseline, -1 };
+  static const int wmv3_profiles[]  = { VAProfileVC1Main, VAProfileVC1Simple, -1 };
+  static const int vc1_profiles[]   = { VAProfileVC1Advanced, -1 };
+
+  const int *profiles = NULL;
+  switch (IMGFMT_VAAPI_CODEC(format))
+  {
+    case IMGFMT_VAAPI_CODEC_MPEG2:
+      if(!vaapi_mpeg_sofdec) {
+        profiles = mpeg2_profiles;
+      }
+      break;
+    case IMGFMT_VAAPI_CODEC_MPEG4:
+      profiles = mpeg4_profiles;
+      break;
+    case IMGFMT_VAAPI_CODEC_H264:
+      profiles = h264_profiles;
+      break;
+    case IMGFMT_VAAPI_CODEC_VC1:
+      switch (format) {
+        case IMGFMT_VAAPI_WMV3:
+          profiles = wmv3_profiles;
+          break;
+        case IMGFMT_VAAPI_VC1:
+            profiles = vc1_profiles;
+            break;
+      }
+      break;
+  }
+
+  if (profiles) {
+    int i;
+    for (i = 0; profiles[i] != -1; i++) {
+      if (vaapi_has_profile(va_profiles, va_num_profiles, profiles[i])) {
+        profile = profiles[i];
+        xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " VAAPI Profile %s supported by your hardware\n", vaapi_profile_to_string(profiles[i]));
+        break;
+      }
+    }
+  }
+
+out:
+  if(va_profiles)
+    free(va_profiles);
+  if(inited) {
+    vaStatus = vaTerminate(va_context->va_display);
+    vaapi_check_status(this_gen, vaStatus, "vaTerminate()");
+  }
+  return profile;
+}
+
+
+static const char *vaapi_profile_to_string(VAProfile profile)
+{
+  switch(profile) {
+#define PROFILE(profile) \
+    case VAProfile##profile: return "VAProfile" #profile
+      PROFILE(MPEG2Simple);
+      PROFILE(MPEG2Main);
+      PROFILE(MPEG4Simple);
+      PROFILE(MPEG4AdvancedSimple);
+      PROFILE(MPEG4Main);
+      PROFILE(H264Baseline);
+      PROFILE(H264Main);
+      PROFILE(H264High);
+      PROFILE(VC1Simple);
+      PROFILE(VC1Main);
+      PROFILE(VC1Advanced);
+#undef PROFILE
+    default: break;
+  }
+  return "<unknown>";
+}
+
+static const char *vaapi_entrypoint_to_string(VAEntrypoint entrypoint)
+{
+  switch(entrypoint)
+  {
+#define ENTRYPOINT(entrypoint) \
+    case VAEntrypoint##entrypoint: return "VAEntrypoint" #entrypoint
+      ENTRYPOINT(VLD);
+      ENTRYPOINT(IZZ);
+      ENTRYPOINT(IDCT);
+      ENTRYPOINT(MoComp);
+      ENTRYPOINT(Deblocking);
+#undef ENTRYPOINT
+    default: break;
+  }
+  return "<unknown>";
+}
+
+/* Init subpicture */
+static void vaapi_init_subpicture(vaapi_driver_t *this_gen) {
+  vaapi_driver_t        *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+
+  va_context->va_subpic_width               = 0;
+  va_context->va_subpic_height              = 0;
+  va_context->va_subpic_id                  = VA_INVALID_ID;
+  va_context->va_subpic_image.image_id      = VA_INVALID_ID;
+
+  this->overlay_output_width = this->overlay_output_height = 0;
+  this->overlay_unscaled_width = this->overlay_unscaled_height = 0;
+  this->ovl_changed = 0;
+  this->has_overlay = 0;
+  this->overlay_bitmap = NULL;
+  this->overlay_bitmap_size = 0;
+
+}
+
+/* Init vaapi context */
+static void vaapi_init_va_context(vaapi_driver_t *this_gen) {
+  vaapi_driver_t        *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+  int i;
+
+  va_context->va_config_id              = VA_INVALID_ID;
+  va_context->va_context_id             = VA_INVALID_ID;
+  va_context->va_profile                = 0;
+  va_context->va_colorspace             = 1;
+  va_context->is_bound                  = 0;
+  va_context->gl_surface                = NULL;
+  va_context->soft_head                 = 0;
+  va_context->valid_context             = 0;
+  va_context->va_head                   = 0;
+  va_context->va_soft_head              = 0;
+
+  for(i = 0; i < RENDER_SURFACES; i++) {
+    ff_vaapi_surface_t *va_surface      = &va_render_surfaces[i];
+
+    va_surface->index                   = i;
+    va_surface->status                  = SURFACE_FREE;
+    va_surface->va_surface_id           = VA_INVALID_SURFACE;
+
+    va_surface_ids[i]                   = VA_INVALID_SURFACE;
+  }
+
+  for(i = 0; i < SOFT_SURFACES; i++) {
+    va_soft_surface_ids[i]              = VA_INVALID_SURFACE;
+    va_soft_images[i].image_id          = VA_INVALID_ID;
+  }
+
+  va_context->va_image_formats      = NULL;
+  va_context->va_num_image_formats  = 0;
+
+  va_context->va_subpic_formats     = NULL;
+  va_context->va_num_subpic_formats = 0;
+}
+
+/* Close vaapi  */
+static void vaapi_close(vo_driver_t *this_gen) {
+  vaapi_driver_t        *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+  VAStatus              vaStatus;
+
+  if(!va_context || !va_context->va_display || !va_context->valid_context)
+    return;
+
+  vaapi_ovl_associate(this_gen, 0, 0);
+  destroy_glx((vo_driver_t *)this);
+
+  vaapi_destroy_subpicture(this_gen);
+
+  vaapi_destroy_soft_surfaces(this_gen);
+
+  vaapi_destroy_render_surfaces(this_gen);
+
+  if(va_context->va_config_id != VA_INVALID_ID) {
+    vaStatus = vaDestroyConfig(va_context->va_display, va_context->va_config_id);
+    vaapi_check_status(this_gen, vaStatus, "vaDestroyConfig()");
+    va_context->va_config_id = VA_INVALID_ID;
+  }
+
+  if(va_context->va_context_id != VA_INVALID_ID) {
+    vaStatus = vaDestroyContext(va_context->va_display, va_context->va_context_id);
+    vaapi_check_status(this_gen, vaStatus, "vaDestroyContext()");
+    va_context->va_context_id = VA_INVALID_ID;
+  }
+  
+  vaStatus = vaTerminate(va_context->va_display);
+  vaapi_check_status(this_gen, vaStatus, "vaTerminate()");
+  va_context->va_display = NULL;
+
+  if(va_context->va_image_formats) {
+    free(va_context->va_image_formats);
+    va_context->va_image_formats      = NULL;
+    va_context->va_num_image_formats  = 0;
+  }
+  if(va_context->va_subpic_formats) {
+    free(va_context->va_subpic_formats);
+    va_context->va_subpic_formats     = NULL;
+    va_context->va_num_subpic_formats = 0;
+  }
+
+  va_context->valid_context = 0;
+}
+
+/* Returns internal VAAPI context */
+static ff_vaapi_context_t *get_context(vo_frame_t *frame_gen) {
+  vaapi_driver_t        *this = (vaapi_driver_t *) frame_gen->driver;
+
+  return this->va_context;
+}
+
+/* Free allocated VAAPI image */
+static void vaapi_destroy_image(vo_driver_t *this_gen, VAImage *va_image) {
+  vaapi_driver_t        *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+  VAStatus              vaStatus;
+
+  if(va_image->image_id != VA_INVALID_ID) {
+    lprintf("vaapi_destroy_image 0x%08x\n", va_image->image_id);
+    vaStatus = vaDestroyImage(va_context->va_display, va_image->image_id);
+    vaapi_check_status(this_gen, vaStatus, "vaDestroyImage()");
+  }
+  va_image->image_id      = VA_INVALID_ID;
+  va_image->width         = 0;
+  va_image->height        = 0;
+}
+
+/* Allocated VAAPI image */
+static VAStatus vaapi_create_image(vo_driver_t *this_gen, VASurfaceID va_surface_id, VAImage *va_image, int width, int height, int clear) {
+  vaapi_driver_t        *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+
+  int i = 0;
+  VAStatus vaStatus;
+
+  if(!va_context->valid_context || va_context->va_image_formats == NULL || va_context->va_num_image_formats == 0)
+    return VA_STATUS_ERROR_UNKNOWN;
+
+  va_context->is_bound = 0;
+
+  vaStatus = vaDeriveImage(va_context->va_display, va_surface_id, va_image);
+  if(vaStatus == VA_STATUS_SUCCESS) {
+    if (va_image->image_id != VA_INVALID_ID && va_image->buf != VA_INVALID_ID) {
+      va_context->is_bound = 1;
+    }
+  }
+
+  if(!va_context->is_bound) {
+    for (i = 0; i < va_context->va_num_image_formats; i++) {
+      if (va_context->va_image_formats[i].fourcc == VA_FOURCC( 'Y', 'V', '1', '2' ) ||
+          va_context->va_image_formats[i].fourcc == VA_FOURCC( 'I', '4', '2', '0' ) /*||
+          va_context->va_image_formats[i].fourcc == VA_FOURCC( 'N', 'V', '1', '2' ) */) {
+        vaStatus = vaCreateImage( va_context->va_display, &va_context->va_image_formats[i], width, height, va_image );
+        if(!vaapi_check_status(this_gen, vaStatus, "vaCreateImage()"))
+          goto error;
+        break;
+      }
+    }
+  }
+
+  void *p_base = NULL;
+
+  vaStatus = vaMapBuffer( va_context->va_display, va_image->buf, &p_base );
+  if(!vaapi_check_status(this_gen, vaStatus, "vaMapBuffer()"))
+    goto error;
+
+  if(clear) {
+    if(va_image->format.fourcc == VA_FOURCC( 'Y', 'V', '1', '2' ) ||
+       va_image->format.fourcc == VA_FOURCC( 'I', '4', '2', '0' )) {
+      memset((uint8_t*)p_base + va_image->offsets[0],   0, va_image->pitches[0] * va_image->height);
+      memset((uint8_t*)p_base + va_image->offsets[1], 128, va_image->pitches[1] * (va_image->height/2));
+      memset((uint8_t*)p_base + va_image->offsets[2], 128, va_image->pitches[2] * (va_image->height/2));
+    } else if (va_image->format.fourcc == VA_FOURCC( 'N', 'V', '1', '2' ) ) {
+      memset((uint8_t*)p_base + va_image->offsets[0],   0, va_image->pitches[0] * va_image->height);
+      memset((uint8_t*)p_base + va_image->offsets[1], 128, va_image->pitches[1] * (va_image->height/2));
+    }
+  }
+
+  vaStatus = vaUnmapBuffer( va_context->va_display, va_image->buf );
+  vaapi_check_status(this_gen, vaStatus, "vaUnmapBuffer()");
+
+  lprintf("vaapi_create_image 0x%08x width %d height %d format %s\n", va_image->image_id, va_image->width, va_image->height,
+      string_of_VAImageFormat(&va_image->format));
+
+  return VA_STATUS_SUCCESS;
+
+error:
+  /* house keeping */
+  vaapi_destroy_image(this_gen, va_image);
+  return VA_STATUS_ERROR_UNKNOWN;
+}
+
+/* Deassociate and free subpicture */
+static void vaapi_destroy_subpicture(vo_driver_t *this_gen) {
+  vaapi_driver_t        *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t    *va_context = this->va_context;
+  VAStatus              vaStatus;
+
+  lprintf("destroy sub 0x%08x 0x%08x 0x%08x\n", va_context->va_subpic_id,
+      va_context->va_subpic_image.image_id, va_context->va_subpic_image.buf);
+
+  if(va_context->va_subpic_id != VA_INVALID_ID) {
+    vaStatus = vaDestroySubpicture(va_context->va_display, va_context->va_subpic_id);
+    vaapi_check_status(this_gen, vaStatus, "vaDeassociateSubpicture()");
+  }
+  va_context->va_subpic_id = VA_INVALID_ID;
+
+  vaapi_destroy_image(this_gen, &va_context->va_subpic_image);
+
+}
+
+/* Create VAAPI subpicture */
+static VAStatus vaapi_create_subpicture(vo_driver_t *this_gen, int width, int height) {
+  vaapi_driver_t      *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  VAStatus            vaStatus;
+
+  int i = 0;
+
+  if(!va_context->valid_context || !va_context->va_subpic_formats || va_context->va_num_subpic_formats == 0)
+    return VA_STATUS_ERROR_UNKNOWN;
+
+  for (i = 0; i < va_context->va_num_subpic_formats; i++) {
+    if ( va_context->va_subpic_formats[i].fourcc == VA_FOURCC('B','G','R','A')) {
+
+      vaStatus = vaCreateImage( va_context->va_display, &va_context->va_subpic_formats[i], width, height, &va_context->va_subpic_image );
+      if(!vaapi_check_status(this_gen, vaStatus, "vaCreateImage()"))
+        goto error;
+
+      vaStatus = vaCreateSubpicture(va_context->va_display, va_context->va_subpic_image.image_id, &va_context->va_subpic_id );
+      if(!vaapi_check_status(this_gen, vaStatus, "vaCreateSubpicture()"))
+        goto error;
+    }
+  }
+
+  if(va_context->va_subpic_image.image_id == VA_INVALID_ID || va_context->va_subpic_id == VA_INVALID_ID)
+    goto error;
+
+  void *p_base = NULL;
+
+  lprintf("create sub 0x%08x 0x%08x 0x%08x\n", va_context->va_subpic_id,
+      va_context->va_subpic_image.image_id, va_context->va_subpic_image.buf);
+
+  vaStatus = vaMapBuffer(va_context->va_display, va_context->va_subpic_image.buf, &p_base);
+  if(!vaapi_check_status(this_gen, vaStatus, "vaMapBuffer()"))
+    goto error;
+
+  memset((uint32_t *)p_base, 0x0, va_context->va_subpic_image.data_size);
+  vaStatus = vaUnmapBuffer(va_context->va_display, va_context->va_subpic_image.buf);
+  vaapi_check_status(this_gen, vaStatus, "vaUnmapBuffer()");
+
+  this->overlay_output_width  = width;
+  this->overlay_output_height = height;
+
+  lprintf("vaapi_create_subpicture 0x%08x format %s\n", va_context->va_subpic_image.image_id,
+      string_of_VAImageFormat(&va_context->va_subpic_image.format));
+
+  return VA_STATUS_SUCCESS;
+
+error:
+  /* house keeping */
+  if(va_context->va_subpic_id != VA_INVALID_ID)
+    vaapi_destroy_subpicture(this_gen);
+  va_context->va_subpic_id = VA_INVALID_ID;
+
+  vaapi_destroy_image(this_gen, &va_context->va_subpic_image);
+
+  this->overlay_output_width  = 0;
+  this->overlay_output_height = 0;
+
+  return VA_STATUS_ERROR_UNKNOWN;
+}
+
+static inline int vaapi_get_colorspace_flags(vo_driver_t *this_gen)
+{
+  vaapi_driver_t      *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+
+  if(!va_context)
+    return 0;
+
+  int colorspace = 0;
+#if USE_VAAPI_COLORSPACE
+  switch (va_context->va_colorspace) {
+    case 0:
+      colorspace = ((va_context->sw_width >= 1280 || va_context->sw_height > 576) ?
+               VA_SRC_BT709 : VA_SRC_BT601);
+      break;
+    case 1:
+      colorspace = VA_SRC_BT601;
+      break;
+    case 2:
+      colorspace = VA_SRC_BT709;
+      break;
+    case 3:
+      colorspace = VA_SRC_SMPTE_240;
+      break;
+    default:
+      colorspace = VA_SRC_BT601;
+      break;
+  }
+#endif
+    return colorspace;
+}
+
+static void vaapi_property_callback (void *property_gen, xine_cfg_entry_t *entry) {
+  va_property_t       *property   = (va_property_t *) property_gen;
+  vaapi_driver_t      *this       = property->this;
+  ff_vaapi_context_t  *va_context = this->va_context;
+
+  pthread_mutex_lock(&this->vaapi_lock);
+  XLockDisplay(this->display);
+
+  VADisplayAttribute attr;
+
+  attr.type   = property->type;
+  attr.value  = entry->num_value;
+
+  lprintf("vaapi_property_callback property=%d, value=%d\n", property->type, entry->num_value );
+
+  VAStatus vaStatus = vaSetDisplayAttributes(va_context->va_display, &attr, 1);
+  vaapi_check_status((vo_driver_t *)this, vaStatus, "vaSetDisplayAttributes()");
+
+  vaapi_show_display_props((vo_driver_t*)this);
+
+  XUnlockDisplay(this->display);
+  pthread_mutex_unlock(&this->vaapi_lock);
+}
+
+/* called xlocked */
+static void vaapi_check_capability (vaapi_driver_t *this,
+         int property, VADisplayAttribute attr,
+         const char *config_name,
+         const char *config_desc,
+         const char *config_help) {
+  int int_default = 0;
+  cfg_entry_t *entry;
+
+  this->props[property].type   = attr.type;
+  this->props[property].min    = attr.min_value;
+  this->props[property].max    = attr.max_value;
+  int_default                  = attr.value;
+  this->props[property].atom   = 1;
+
+  if (config_name) {
+    /* is this a boolean property ? */
+    if ((attr.min_value == 0) && (attr.max_value == 1)) {
+      this->config->register_bool (this->config, config_name, int_default,
+           config_desc,
+           config_help, 20, vaapi_property_callback, &this->props[property]);
+
+    } else {
+      this->config->register_range (this->config, config_name, int_default,
+            this->props[property].min, this->props[property].max,
+            config_desc,
+            config_help, 20, vaapi_property_callback, &this->props[property]);
+    }
+
+    entry = this->config->lookup_entry (this->config, config_name);
+    if((entry->num_value < this->props[property].min) ||
+       (entry->num_value > this->props[property].max)) {
+
+      this->config->update_num(this->config, config_name,
+             ((this->props[property].min + this->props[property].max) >> 1));
+
+      entry = this->config->lookup_entry (this->config, config_name);
+    }
+
+    this->props[property].entry = entry;
+
+    vaapi_set_property(&this->vo_driver, property, entry->num_value);
+  } else {
+    this->props[property].value  = int_default;
+  }
+}
+
+static void vaapi_show_display_props(vo_driver_t *this_gen) {
+  /*
+  vaapi_driver_t      *this = (vaapi_driver_t *) this_gen;
+
+  if(this->capabilities & VO_CAP_BRIGHTNESS)
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : brightness     : %d\n", this->props[VO_PROP_BRIGHTNESS].value);
+  if(this->capabilities & VO_CAP_CONTRAST)
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : contrast       : %d\n", this->props[VO_PROP_CONTRAST].value);
+  if(this->capabilities & VO_CAP_HUE)
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : hue            : %d\n", this->props[VO_PROP_HUE].value);
+  if(this->capabilities & VO_CAP_SATURATION)
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : saturation     : %d\n", this->props[VO_PROP_SATURATION].value);
+  */
+}
+
+/* VAAPI display attributes. */
+static void vaapi_display_attribs(vo_driver_t *this_gen) {
+  vaapi_driver_t      *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+
+  int num_display_attrs, max_display_attrs;
+  VAStatus vaStatus;
+  VADisplayAttribute *display_attrs;
+  int i;
+
+  max_display_attrs = vaMaxNumDisplayAttributes(va_context->va_display);
+  display_attrs = calloc(max_display_attrs, sizeof(*display_attrs));
+
+  if (display_attrs) {
+    num_display_attrs = 0;
+    vaStatus = vaQueryDisplayAttributes(va_context->va_display,
+                                        display_attrs, &num_display_attrs);
+    if(vaapi_check_status(this_gen, vaStatus, "vaQueryDisplayAttributes()")) {
+      for (i = 0; i < num_display_attrs; i++) {
+        switch (display_attrs[i].type) {
+          case VADisplayAttribBrightness:
+            if( ( display_attrs[i].flags & VA_DISPLAY_ATTRIB_GETTABLE ) &&
+                ( display_attrs[i].flags & VA_DISPLAY_ATTRIB_SETTABLE ) ) {
+              this->capabilities |= VO_CAP_BRIGHTNESS;
+              vaapi_check_capability(this, VO_PROP_BRIGHTNESS, display_attrs[i], "video.output.vaapi_brightness", "Brightness setting", "Brightness setting");
+            }
+            break;
+          case VADisplayAttribContrast:
+            if( ( display_attrs[i].flags & VA_DISPLAY_ATTRIB_GETTABLE ) &&
+                ( display_attrs[i].flags & VA_DISPLAY_ATTRIB_SETTABLE ) ) {
+              this->capabilities |= VO_CAP_CONTRAST;
+              vaapi_check_capability(this, VO_PROP_CONTRAST, display_attrs[i], "video.output.vaapi_contrast", "Contrast setting", "Contrast setting");
+            }
+            break;
+          case VADisplayAttribHue:
+            if( ( display_attrs[i].flags & VA_DISPLAY_ATTRIB_GETTABLE ) &&
+                ( display_attrs[i].flags & VA_DISPLAY_ATTRIB_SETTABLE ) ) {
+              this->capabilities |= VO_CAP_HUE;
+              vaapi_check_capability(this, VO_PROP_HUE, display_attrs[i], "video.output.vaapi_hue", "Hue setting", "Hue setting");
+            }
+            break;
+          case VADisplayAttribSaturation:
+            if( ( display_attrs[i].flags & VA_DISPLAY_ATTRIB_GETTABLE ) &&
+                ( display_attrs[i].flags & VA_DISPLAY_ATTRIB_SETTABLE ) ) {
+              this->capabilities |= VO_CAP_SATURATION;
+              vaapi_check_capability(this, VO_PROP_SATURATION, display_attrs[i], "video.output.vaapi_saturation", "Saturation setting", "Saturation setting");
+            }
+            break;
+          default:
+            break;
+        }
+      }
+    }
+    free(display_attrs);
+  }
+  vaapi_show_display_props(this_gen);
+}
+
+static void vaapi_set_background_color(vo_driver_t *this_gen) {
+  vaapi_driver_t      *this = (vaapi_driver_t *)this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  VAStatus            vaStatus;
+
+  if(!va_context->valid_context)
+    return;
+
+  VADisplayAttribute attr;
+  memset( &attr, 0, sizeof(attr) );
+
+  attr.type  = VADisplayAttribBackgroundColor;
+  attr.value = 0x000000;
+
+  vaStatus = vaSetDisplayAttributes(va_context->va_display, &attr, 1);
+  vaapi_check_status(this_gen, vaStatus, "vaSetDisplayAttributes()");
+}
+
+static VAStatus vaapi_destroy_render_surfaces(vo_driver_t *this_gen) {
+  vaapi_driver_t      *this = (vaapi_driver_t *)this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  int                 i;
+  VAStatus            vaStatus;
+
+  for(i = 0; i < RENDER_SURFACES; i++) {
+    if(va_surface_ids[i] != VA_INVALID_SURFACE) {
+      vaStatus = vaSyncSurface(va_context->va_display, va_surface_ids[i]);
+      vaapi_check_status(this_gen, vaStatus, "vaSyncSurface()");
+      vaStatus = vaDestroySurfaces(va_context->va_display, &va_surface_ids[i], 1);
+      vaapi_check_status(this_gen, vaStatus, "vaDestroySurfaces()");
+      va_surface_ids[i] = VA_INVALID_SURFACE;
+
+      ff_vaapi_surface_t *va_surface  = &va_render_surfaces[i];
+      va_surface->index               = i;
+      va_surface->status              = SURFACE_FREE;
+      va_surface->va_surface_id       = va_surface_ids[i];
+    }
+  }
+
+  return VA_STATUS_SUCCESS;
+}
+
+static VAStatus vaapi_destroy_soft_surfaces(vo_driver_t *this_gen) {
+  vaapi_driver_t      *this = (vaapi_driver_t *)this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  int                 i;
+  VAStatus            vaStatus;
+
+
+  for(i = 0; i < SOFT_SURFACES; i++) {
+    if(va_soft_images[i].image_id != VA_INVALID_ID)
+      vaapi_destroy_image((vo_driver_t *)this, &va_soft_images[i]);
+    va_soft_images[i].image_id = VA_INVALID_ID;
+
+    if(va_soft_surface_ids[i] != VA_INVALID_SURFACE) {
+#ifdef DEBUG_SURFACE
+      printf("vaapi_close destroy render surface 0x%08x\n", va_soft_surface_ids[i]);
+#endif
+      vaStatus = vaSyncSurface(va_context->va_display, va_soft_surface_ids[i]);
+      vaapi_check_status(this_gen, vaStatus, "vaSyncSurface()");
+      vaStatus = vaDestroySurfaces(va_context->va_display, &va_soft_surface_ids[i], 1);
+      vaapi_check_status(this_gen, vaStatus, "vaDestroySurfaces()");
+      va_soft_surface_ids[i] = VA_INVALID_SURFACE;
+    }
+  }
+
+  va_context->sw_width  = 0;
+  va_context->sw_height = 0;
+  return VA_STATUS_SUCCESS;
+}
+
+static VAStatus vaapi_init_soft_surfaces(vo_driver_t *this_gen, int width, int height) {
+  vaapi_driver_t      *this = (vaapi_driver_t *)this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  VAStatus            vaStatus;
+  int                 i;
+
+  vaapi_destroy_soft_surfaces(this_gen);
+
+  vaStatus = vaCreateSurfaces(va_context->va_display, width, height, VA_RT_FORMAT_YUV420, SOFT_SURFACES, va_soft_surface_ids);
+  if(!vaapi_check_status(this_gen, vaStatus, "vaCreateSurfaces()"))
+    goto error;
+
+  /* allocate software surfaces */
+  for(i = 0; i < SOFT_SURFACES; i++) {
+    ff_vaapi_surface_t *va_surface  = &va_render_surfaces[i];
+
+    vaStatus = vaapi_create_image((vo_driver_t *)this, va_soft_surface_ids[i], &va_soft_images[i], width, height, 1);
+    if(!vaapi_check_status(this_gen, vaStatus, "vaapi_create_image()")) {
+      va_soft_images[i].image_id = VA_INVALID_ID;
+      goto error;
+    }
+
+    va_surface->index = i;
+
+    vaStatus = vaPutImage(va_context->va_display, va_soft_surface_ids[i], va_soft_images[i].image_id,
+               0, 0, va_soft_images[i].width, va_soft_images[i].height,
+               0, 0, va_soft_images[i].width, va_soft_images[i].height);
+    vaapi_check_status(this_gen, vaStatus, "vaPutImage()");
+#ifdef DEBUG_SURFACE
+    printf("vaapi_init_soft_surfaces 0x%08x\n", va_soft_surface_ids[i]);
+#endif
+  }
+
+  va_context->sw_width  = width;
+  va_context->sw_height = height;
+  return VA_STATUS_SUCCESS;
+
+error:
+  va_context->sw_width  = 0;
+  va_context->sw_height = 0;
+  vaapi_destroy_soft_surfaces(this_gen);
+  return VA_STATUS_ERROR_UNKNOWN;
+}
+
+static VAStatus vaapi_init_internal(vo_driver_t *this_gen, int va_profile, int width, int height, int softrender) {
+  vaapi_driver_t      *this = (vaapi_driver_t *)this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  VAConfigAttrib      va_attrib;
+  int                 maj, min, i;
+  VAStatus            vaStatus;
+
+  vaapi_close(this_gen);
+  vaapi_init_va_context(this);
+
+  this->va_context->va_display = vaapi_get_display(this->display, this->opengl_render);
+
+  if(!this->va_context->va_display)
+    goto error;
+
+  vaStatus = vaInitialize(this->va_context->va_display, &maj, &min);
+  if(!vaapi_check_status((vo_driver_t *)this, vaStatus, "vaInitialize()"))
+    goto error;
+
+  lprintf("libva: %d.%d\n", maj, min);
+
+  va_context->valid_context = 1;
+
+  int fmt_count = 0;
+  fmt_count = vaMaxNumImageFormats( va_context->va_display );
+  va_context->va_image_formats = calloc( fmt_count, sizeof(*va_context->va_image_formats) );
+
+  vaStatus = vaQueryImageFormats(va_context->va_display, va_context->va_image_formats, &va_context->va_num_image_formats);
+  if(!vaapi_check_status(this_gen, vaStatus, "vaQueryImageFormats()"))
+    goto error;
+
+  fmt_count = vaMaxNumSubpictureFormats( va_context->va_display );
+  va_context->va_subpic_formats = calloc( fmt_count, sizeof(*va_context->va_subpic_formats) );
+
+  vaStatus = vaQuerySubpictureFormats( va_context->va_display , va_context->va_subpic_formats, 0, &va_context->va_num_subpic_formats );
+  if(!vaapi_check_status(this_gen, vaStatus, "vaQuerySubpictureFormats()"))
+    goto error;
+  
+  const char *vendor = vaQueryVendorString(va_context->va_display);
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_open: Vendor : %s\n", vendor);
+    
+  this->query_va_status = 1;
+  char *p = (char *)vendor;
+  for(i = 0; i < strlen(vendor); i++, p++) {
+    if(strncmp(p, "VDPAU", strlen("VDPAU")) == 0) {
+      xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_open: Enable Splitted-Desktop Systems VDPAU-VIDEO workarounds.\n");
+      this->query_va_status = 0;
+      this->opengl_use_tfp = 0;
+      break;
+    }
+  }
+
+  vaapi_set_background_color(this_gen);
+  vaapi_display_attribs((vo_driver_t *)this);
+
+  va_context->width = width;
+  va_context->height = height;
+  va_context->va_profile = va_profile;
+
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : Context width %d height %d\n", va_context->width, va_context->height);
+
+  /* allocate decoding surfaces */
+  vaStatus = vaCreateSurfaces(va_context->va_display, va_context->width, va_context->height, VA_RT_FORMAT_YUV420, RENDER_SURFACES, va_surface_ids);
+  if(!vaapi_check_status(this_gen, vaStatus, "vaCreateSurfaces()"))
+    goto error;
+
+  /* hardware decoding needs more setup */
+  if(!softrender && va_profile >= 0) {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : Profile: %d (%s) Entrypoint %d (%s) Surfaces %d\n", va_context->va_profile, vaapi_profile_to_string(va_context->va_profile), VAEntrypointVLD, vaapi_entrypoint_to_string(VAEntrypointVLD), RENDER_SURFACES);
+
+    memset( &va_attrib, 0, sizeof(va_attrib) );
+    va_attrib.type = VAConfigAttribRTFormat;
+
+    vaStatus = vaGetConfigAttributes(va_context->va_display, va_context->va_profile, VAEntrypointVLD, &va_attrib, 1);
+    if(!vaapi_check_status(this_gen, vaStatus, "vaGetConfigAttributes()"))
+      goto error;
+  
+    if( (va_attrib.value & VA_RT_FORMAT_YUV420) == 0 )
+      goto error;
+
+    vaStatus = vaCreateConfig(va_context->va_display, va_context->va_profile, VAEntrypointVLD, &va_attrib, 1, &va_context->va_config_id);
+    if(!vaapi_check_status(this_gen, vaStatus, "vaCreateConfig()")) {
+      va_context->va_config_id = VA_INVALID_ID;
+      goto error;
+    }
+
+    vaStatus = vaCreateContext(va_context->va_display, va_context->va_config_id, va_context->width, va_context->height,
+                               VA_PROGRESSIVE, va_surface_ids, RENDER_SURFACES, &va_context->va_context_id);
+    if(!vaapi_check_status(this_gen, vaStatus, "vaCreateContext()")) {
+      va_context->va_context_id = VA_INVALID_ID;
+      goto error;
+    }
+  }
+
+  /* xine was told to allocate RENDER_SURFACES frames. assign the frames the rendering surfaces. */
+  for(i = 0; i < RENDER_SURFACES; i++) {
+    ff_vaapi_surface_t *va_surface  = &va_render_surfaces[i];
+    va_surface->index               = i;
+    va_surface->status              = SURFACE_FREE;
+    va_surface->va_surface_id       = va_surface_ids[i];
+
+    if(this->frames[i]) {
+      vaapi_frame_t *frame                  = this->frames[i];
+      frame->vaapi_accel_data.index         = i;
+
+      VAImage va_image;
+      vaStatus = vaapi_create_image(va_context->driver, va_surface_ids[i], &va_image, width, height, 1);
+      if(vaapi_check_status(va_context->driver, vaStatus, "vaapi_create_image()")) {
+        vaStatus = vaPutImage(va_context->va_display, va_surface_ids[i], va_image.image_id,
+                              0, 0, va_image.width, va_image.height,
+                              0, 0, va_image.width, va_image.height);
+        vaapi_destroy_image(va_context->driver, &va_image);
+      }
+    }
+#ifdef DEBUG_SURFACE
+    printf("vaapi_init_internal 0x%08x\n", va_surface_ids[i]);
+#endif
+  }
+
+  vaStatus = vaapi_init_soft_surfaces(this_gen, width, height);
+  if(!vaapi_check_status(this_gen, vaStatus, "vaapi_init_soft_surfaces()")) {
+    vaapi_destroy_soft_surfaces(this_gen);
+    goto error;
+  }
+
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : guarded render : %d\n", this->guarded_render);
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : glxrender      : %d\n", this->opengl_render);
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : glxrender tfp  : %d\n", this->opengl_use_tfp);
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : is_bound       : %d\n", va_context->is_bound);
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : scaling level  : name %s value 0x%08x\n", scaling_level_enum_names[this->scaling_level_enum], this->scaling_level);
+
+  this->init_opengl_render = 1;
+
+  return VA_STATUS_SUCCESS;
+
+error:
+  vaapi_close(this_gen);
+  vaapi_init_va_context(this);
+  va_context->valid_context = 0;
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_init : error init vaapi\n");
+
+  return VA_STATUS_ERROR_UNKNOWN;
+}
+
+/*
+ * Init VAAPI. This function is called from the decoder side.
+ * When the decoder uses software decoding vaapi_init is not called.
+ * Therefore we do it in vaapi_display_frame to get a valid VAAPI context
+ */
+static VAStatus vaapi_init(vo_frame_t *frame_gen, int va_profile, int width, int height, int softrender) {
+  if(!frame_gen)
+    return VA_STATUS_ERROR_UNKNOWN;
+
+  vo_driver_t         *this_gen   = (vo_driver_t *) frame_gen->driver;
+  vaapi_driver_t      *this       = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+
+  VAStatus vaStatus;
+
+  unsigned int last_sub_img_fmt = va_context->last_sub_image_fmt;
+
+  if(last_sub_img_fmt)
+    vaapi_ovl_associate(this_gen, frame_gen->format, 0);
+
+  if(!this->guarded_render) {
+    pthread_mutex_lock(&this->vaapi_lock);
+    XLockDisplay(this->display);
+  }
+
+  vaStatus = vaapi_init_internal(this_gen, va_profile, width, height, softrender);
+
+  if(!this->guarded_render) {
+    XUnlockDisplay(this->display);
+    pthread_mutex_unlock(&this->vaapi_lock);
+  }
+
+  if(last_sub_img_fmt)
+    vaapi_ovl_associate(this_gen, frame_gen->format, this->has_overlay);
+
+  return vaStatus;
+}
+
+static void vaapi_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src)
+{
+  vo_img->proc_called = 1;
+}
+
+static void vaapi_frame_field (vo_frame_t *vo_img, int which_field)
+{
+}
+
+static void vaapi_frame_dispose (vo_frame_t *vo_img) {
+  vaapi_driver_t *this  = (vaapi_driver_t *) vo_img->driver;
+  vaapi_frame_t  *frame = (vaapi_frame_t *) vo_img ;
+  vaapi_accel_t  *accel = &frame->vaapi_accel_data;
+
+  lprintf("vaapi_frame_dispose\n");
+
+  av_free (frame->vo_frame.base[0]);
+  av_free (frame->vo_frame.base[1]);
+  av_free (frame->vo_frame.base[2]);
+
+  if(this->guarded_render) {
+    ff_vaapi_surface_t *va_surface = &va_render_surfaces[accel->index];
+    va_surface->status = SURFACE_FREE;
+  }
+
+  free (frame);
+}
+
+static vo_frame_t *vaapi_alloc_frame (vo_driver_t *this_gen) {
+  vaapi_driver_t  *this = (vaapi_driver_t *) this_gen;
+  vaapi_frame_t   *frame;
+
+  frame = (vaapi_frame_t *) calloc(1, sizeof(vaapi_frame_t));
+
+  if (!frame)
+    return NULL;
+
+  this->frames[this->num_frame_buffers++] = frame;
+
+  frame->vo_frame.base[0] = frame->vo_frame.base[1] = frame->vo_frame.base[2] = NULL;
+  frame->width = frame->height = frame->format = frame->flags = 0;
+
+  frame->vo_frame.accel_data = &frame->vaapi_accel_data;
+
+  pthread_mutex_init (&frame->vo_frame.mutex, NULL);
+
+  /*
+   * supply required functions
+   */
+  frame->vo_frame.proc_duplicate_frame_data         = NULL;
+  frame->vo_frame.proc_provide_standard_frame_data  = NULL;
+  frame->vo_frame.proc_slice                        = vaapi_frame_proc_slice;
+  frame->vo_frame.proc_frame                        = NULL;
+  frame->vo_frame.field                             = vaapi_frame_field;
+  frame->vo_frame.dispose                           = vaapi_frame_dispose;
+  frame->vo_frame.driver                            = this_gen;
+
+  frame->vaapi_accel_data.vo_frame                  = &frame->vo_frame;
+  frame->vaapi_accel_data.vaapi_init                = &vaapi_init;
+  frame->vaapi_accel_data.profile_from_imgfmt       = &profile_from_imgfmt;
+  frame->vaapi_accel_data.get_context               = &get_context;
+
+#if AVVIDEO > 1
+  frame->vaapi_accel_data.avcodec_decode_video2     = &guarded_avcodec_decode_video2;
+#else
+  frame->vaapi_accel_data.avcodec_decode_video      = &guarded_avcodec_decode_video;
+#endif
+
+  frame->vaapi_accel_data.get_vaapi_surface         = &get_vaapi_surface;
+  frame->vaapi_accel_data.render_vaapi_surface      = &render_vaapi_surface;
+  frame->vaapi_accel_data.release_vaapi_surface     = &release_vaapi_surface;
+  frame->vaapi_accel_data.guarded_render            = &guarded_render;
+
+  lprintf("alloc frame\n");
+
+  return (vo_frame_t *) frame;
+}
+
+
+/* Display OSD */
+static int vaapi_ovl_associate(vo_driver_t *this_gen, int format, int bShow) {
+  vaapi_driver_t      *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+  VAStatus vaStatus;
+
+  if(!va_context->valid_context)
+    return 0;
+
+  if(va_context->last_sub_image_fmt && !bShow) {
+    if(va_context->va_subpic_id != VA_INVALID_ID) {
+      if(va_context->last_sub_image_fmt == XINE_IMGFMT_VAAPI) {
+        vaStatus = vaDeassociateSubpicture(va_context->va_display, va_context->va_subpic_id,
+                                va_surface_ids, RENDER_SURFACES);
+        vaapi_check_status(this_gen, vaStatus, "vaDeassociateSubpicture()");
+      } else if(va_context->last_sub_image_fmt == XINE_IMGFMT_YV12 ||
+                va_context->last_sub_image_fmt == XINE_IMGFMT_YUY2) {
+        vaStatus = vaDeassociateSubpicture(va_context->va_display, va_context->va_subpic_id,
+                                va_soft_surface_ids, SOFT_SURFACES);
+        vaapi_check_status(this_gen, vaStatus, "vaDeassociateSubpicture()");
+      }
+    }
+    va_context->last_sub_image_fmt = 0;
+    return 1;
+  }
+  
+  if(!va_context->last_sub_image_fmt && bShow) {
+    unsigned int flags = 0;
+    unsigned int output_width = va_context->width;
+    unsigned int output_height = va_context->height;
+    void *p_base = NULL;
+
+    VAStatus vaStatus;
+
+    vaapi_destroy_subpicture(this_gen);
+    vaStatus = vaapi_create_subpicture(this_gen, this->overlay_bitmap_width, this->overlay_bitmap_height);
+    if(!vaapi_check_status(this_gen, vaStatus, "vaapi_create_subpicture()"))
+      return 0;
+
+    vaStatus = vaMapBuffer(va_context->va_display, va_context->va_subpic_image.buf, &p_base);
+    if(!vaapi_check_status(this_gen, vaStatus, "vaMapBuffer()"))
+      return 0;
+
+    xine_fast_memcpy((uint32_t *)p_base, this->overlay_bitmap, this->overlay_bitmap_width * this->overlay_bitmap_height * sizeof(uint32_t));
+
+    vaStatus = vaUnmapBuffer(va_context->va_display, va_context->va_subpic_image.buf);
+    vaapi_check_status(this_gen, vaStatus, "vaUnmapBuffer()");
+
+    lprintf( "vaapi_ovl_associate: overlay_width=%d overlay_height=%d unscaled %d va_subpic_id 0x%08x ovl_changed %d has_overlay %d bShow %d overlay_bitmap_width %d overlay_bitmap_height %d va_context->width %d va_context->height %d\n",
+           this->overlay_output_width, this->overlay_output_height, this->has_overlay,
+           va_context->va_subpic_id, this->ovl_changed, this->has_overlay, bShow,
+           this->overlay_bitmap_width, this->overlay_bitmap_height,
+           va_context->width, va_context->height);
+
+    if(format == XINE_IMGFMT_VAAPI) {
+      lprintf("vaapi_ovl_associate hw\n");
+      vaStatus = vaAssociateSubpicture(va_context->va_display, va_context->va_subpic_id,
+                              va_surface_ids, RENDER_SURFACES,
+                              0, 0, va_context->va_subpic_image.width, va_context->va_subpic_image.height,
+                              0, 0, output_width, output_height, flags);
+    } else {
+      lprintf("vaapi_ovl_associate sw\n");
+      vaStatus = vaAssociateSubpicture(va_context->va_display, va_context->va_subpic_id,
+                              va_soft_surface_ids, SOFT_SURFACES,
+                              0, 0, va_context->va_subpic_image.width, va_context->va_subpic_image.height,
+                              0, 0, va_soft_images[0].width, va_soft_images[0].height, flags);
+    }
+
+    if(vaapi_check_status(this_gen, vaStatus, "vaAssociateSubpicture()")) {
+      va_context->last_sub_image_fmt = format;
+      return 1;
+    }
+  }
+  return 0;
+}
+
+static void vaapi_overlay_clut_yuv2rgb(vaapi_driver_t  *this, vo_overlay_t *overlay, vaapi_frame_t *frame)
+{
+  int i;
+  clut_t* clut = (clut_t*) overlay->color;
+
+  if (!overlay->rgb_clut) {
+    for ( i=0; i<sizeof(overlay->color)/sizeof(overlay->color[0]); i++ ) {
+      *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(this->ovl_yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr);
+    }
+    overlay->rgb_clut++;
+  }
+  if (!overlay->hili_rgb_clut) {
+    clut = (clut_t*) overlay->hili_color;
+    for ( i=0; i<sizeof(overlay->color)/sizeof(overlay->color[0]); i++) {
+      *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(this->ovl_yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr);
+    }
+    overlay->hili_rgb_clut++;
+  }
+}
+
+static void vaapi_overlay_begin (vo_driver_t *this_gen,
+      vo_frame_t *frame_gen, int changed) {
+  vaapi_driver_t      *this       = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+
+  if ( !changed )
+    return;
+
+  this->has_overlay = 0;
+  ++this->ovl_changed;
+
+  /* Apply OSD layer. */
+  if(va_context->valid_context) {
+    lprintf("vaapi_overlay_begin chaned %d\n", changed);
+
+    pthread_mutex_lock(&this->vaapi_lock);
+    XLockDisplay(this->display);
+
+    vaapi_ovl_associate(this_gen, frame_gen->format, this->has_overlay);
+
+    XUnlockDisplay(this->display);
+    pthread_mutex_unlock(&this->vaapi_lock);
+  }
+}
+
+static void vaapi_overlay_blend (vo_driver_t *this_gen,
+      vo_frame_t *frame_gen, vo_overlay_t *overlay) {
+  vaapi_driver_t  *this = (vaapi_driver_t *) this_gen;
+
+  int i = this->ovl_changed;
+
+  if (!i)
+    return;
+
+  if (--i >= XINE_VORAW_MAX_OVL)
+    return;
+
+  if (overlay->width <= 0 || overlay->height <= 0 || (!overlay->rle && (!overlay->argb_layer || !overlay->argb_layer->buffer)))
+    return;
+
+  if (overlay->rle)
+    lprintf("overlay[%d] rle %s%s %dx%d@%d,%d hili rect %d,%d-%d,%d\n", i,
+            overlay->unscaled ? " unscaled ": " scaled ",
+            (overlay->rgb_clut > 0 || overlay->hili_rgb_clut > 0) ? " rgb ": " ycbcr ",
+            overlay->width, overlay->height, overlay->x, overlay->y,
+            overlay->hili_left, overlay->hili_top,
+            overlay->hili_right, overlay->hili_bottom);
+  if (overlay->argb_layer && overlay->argb_layer->buffer)
+    lprintf("overlay[%d] argb %s %dx%d@%d,%d dirty rect %d,%d-%d,%d\n", i,
+            overlay->unscaled ? " unscaled ": " scaled ",
+            overlay->width, overlay->height, overlay->x, overlay->y,
+            overlay->argb_layer->x1, overlay->argb_layer->y1,
+            overlay->argb_layer->x2, overlay->argb_layer->y2);
+
+
+  this->overlays[i] = overlay;
+
+  ++this->ovl_changed;
+}
+
+static void vaapi_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
+  vaapi_driver_t      *this       = (vaapi_driver_t *) this_gen;
+  vaapi_frame_t       *frame      = (vaapi_frame_t *) frame_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+
+  int novls = this->ovl_changed;
+  if (novls < 2) {
+    this->ovl_changed = 0;
+    return;
+  }
+  --novls;
+
+  uint32_t output_width = frame->width;
+  uint32_t output_height = frame->height;
+  uint32_t unscaled_width = 0, unscaled_height = 0;
+  vo_overlay_t *first_scaled = NULL, *first_unscaled = NULL;
+  vaapi_rect_t dirty_rect, unscaled_dirty_rect;
+  int has_rle = 0;
+
+  int i;
+  for (i = 0; i < novls; ++i) {
+    vo_overlay_t *ovl = this->overlays[i];
+
+    if (ovl->rle)
+      has_rle = 1;
+
+    if (ovl->unscaled) {
+      if (first_unscaled) {
+        if (ovl->x < unscaled_dirty_rect.x1)
+          unscaled_dirty_rect.x1 = ovl->x;
+        if (ovl->y < unscaled_dirty_rect.y1)
+          unscaled_dirty_rect.y1 = ovl->y;
+        if ((ovl->x + ovl->width) > unscaled_dirty_rect.x2)
+          unscaled_dirty_rect.x2 = ovl->x + ovl->width;
+        if ((ovl->y + ovl->height) > unscaled_dirty_rect.y2)
+          unscaled_dirty_rect.y2 = ovl->y + ovl->height;
+      } else {
+        first_unscaled = ovl;
+        unscaled_dirty_rect.x1 = ovl->x;
+        unscaled_dirty_rect.y1 = ovl->y;
+        unscaled_dirty_rect.x2 = ovl->x + ovl->width;
+        unscaled_dirty_rect.y2 = ovl->y + ovl->height;
+      }
+
+      unscaled_width = unscaled_dirty_rect.x2;
+      unscaled_height = unscaled_dirty_rect.y2;
+    } else {
+      if (first_scaled) {
+        if (ovl->x < dirty_rect.x1)
+          dirty_rect.x1 = ovl->x;
+        if (ovl->y < dirty_rect.y1)
+          dirty_rect.y1 = ovl->y;
+        if ((ovl->x + ovl->width) > dirty_rect.x2)
+          dirty_rect.x2 = ovl->x + ovl->width;
+        if ((ovl->y + ovl->height) > dirty_rect.y2)
+          dirty_rect.y2 = ovl->y + ovl->height;
+      } else {
+        first_scaled = ovl;
+        dirty_rect.x1 = ovl->x;
+        dirty_rect.y1 = ovl->y;
+        dirty_rect.x2 = ovl->x + ovl->width;
+        dirty_rect.y2 = ovl->y + ovl->height;
+      }
+
+      if (dirty_rect.x2 > output_width)
+        output_width = dirty_rect.x2;
+      if (dirty_rect.y2 > output_height)
+        output_height = dirty_rect.y2;
+
+    }
+  }
+
+  int need_init = 0;
+
+  lprintf("dirty_rect.x0 %d dirty_rect.y0 %d dirty_rect.x2 %d dirty_rect.y2 %d output_width %d output_height %d\n",
+      dirty_rect.x0, dirty_rect.y0, dirty_rect.x2, dirty_rect.y2, output_width, output_height);
+
+  if (first_scaled) {
+    vaapi_rect_t dest;
+    dest.x1 = first_scaled->x;
+    dest.y1 = first_scaled->y;
+    dest.x2 = first_scaled->x + first_scaled->width;
+    dest.y2 = first_scaled->y + first_scaled->height;
+    if (!RECT_IS_EQ(dest, dirty_rect))
+      need_init = 1;
+  }
+
+  int need_unscaled_init = (first_unscaled &&
+                                  (first_unscaled->x != unscaled_dirty_rect.x1 ||
+                                   first_unscaled->y != unscaled_dirty_rect.y1 ||
+                                   (first_unscaled->x + first_unscaled->width) != unscaled_dirty_rect.x2 ||
+                                   (first_unscaled->y + first_unscaled->height) != unscaled_dirty_rect.y2));
+
+  if (first_scaled) {
+    this->overlay_output_width = output_width;
+    this->overlay_output_height = output_height;
+
+    need_init = 1;
+
+    this->overlay_dirty_rect = dirty_rect;
+  }
+
+  if (first_unscaled) {
+    this->overlay_unscaled_width = unscaled_width;
+    this->overlay_unscaled_height = unscaled_height;
+
+    need_unscaled_init = 1;
+    this->overlay_unscaled_dirty_rect = unscaled_dirty_rect;
+  }
+
+  if (has_rle || need_init || need_unscaled_init) {
+    lprintf("has_rle %d need_init %d need_unscaled_init %d unscaled_width %d unscaled_height %d output_width %d output_height %d\n",
+        has_rle, need_init, need_unscaled_init, unscaled_width, unscaled_height, output_width, output_height);
+    if (need_init) {
+      this->overlay_bitmap_width = output_width;
+      this->overlay_bitmap_height = output_height;
+    }
+    if (need_unscaled_init) {
+
+      if(this->vdr_osd_width)
+        this->overlay_bitmap_width =  (this->vdr_osd_width >  this->sc.gui_width) ? this->vdr_osd_width : this->sc.gui_width;
+      else
+        this->overlay_bitmap_width =  (unscaled_width >  this->sc.gui_width) ? unscaled_width : this->sc.gui_width;
+
+      if(this->vdr_osd_height)
+        this->overlay_bitmap_height = (this->vdr_osd_height > this->sc.gui_height) ? this->vdr_osd_height : this->sc.gui_height;
+      else
+        this->overlay_bitmap_height = (unscaled_height > this->sc.gui_height) ? unscaled_height : this->sc.gui_height;
+
+    } else if (need_init) {
+
+      if(this->vdr_osd_width)
+        this->overlay_bitmap_width =  (this->vdr_osd_width >  this->sc.gui_width) ? this->vdr_osd_width : this->sc.gui_width;
+      else
+        this->overlay_bitmap_width =  (output_width >  this->sc.gui_width) ? output_width : this->sc.gui_width;
+
+      if(this->vdr_osd_height)
+        this->overlay_bitmap_height = (this->vdr_osd_height > this->sc.gui_height) ? this->vdr_osd_height : this->sc.gui_height;
+      else
+        this->overlay_bitmap_height = (output_height > this->sc.gui_height) ? output_height : this->sc.gui_height;
+
+    }
+  }
+
+  if ((this->overlay_bitmap_width * this->overlay_bitmap_height) > this->overlay_bitmap_size) {
+    this->overlay_bitmap_size = this->overlay_bitmap_width * this->overlay_bitmap_height;
+    free(this->overlay_bitmap);
+    this->overlay_bitmap = calloc( this->overlay_bitmap_size, sizeof(uint32_t));
+  } else {
+    memset(this->overlay_bitmap, 0x0, this->overlay_bitmap_size * sizeof(uint32_t));
+  }
+
+  for (i = 0; i < novls; ++i) {
+    vo_overlay_t *ovl = this->overlays[i];
+    uint32_t *bitmap = NULL;
+    uint32_t *rgba = NULL;
+
+    if (ovl->rle) {
+      if(ovl->width<=0 || ovl->height<=0)
+        continue;
+
+      if (!ovl->rgb_clut || !ovl->hili_rgb_clut)
+        vaapi_overlay_clut_yuv2rgb (this, ovl, frame);
+
+      bitmap = rgba = calloc(ovl->width * ovl->height * 4, sizeof(uint32_t));
+
+      int num_rle = ovl->num_rle;
+      rle_elem_t *rle = ovl->rle;
+      uint32_t red, green, blue, alpha;
+      clut_t *low_colors = (clut_t*)ovl->color;
+      clut_t *hili_colors = (clut_t*)ovl->hili_color;
+      uint8_t *low_trans = ovl->trans;
+      uint8_t *hili_trans = ovl->hili_trans;
+      clut_t *colors;
+      uint8_t *trans;
+      int rlelen = 0;
+      uint8_t clr = 0;
+      int i, pos=0, x, y;
+
+      while (num_rle > 0) {
+        x = pos % ovl->width;
+        y = pos / ovl->width;
+
+        if ( (x>=ovl->hili_left && x<=ovl->hili_right) && (y>=ovl->hili_top && y<=ovl->hili_bottom) ) {
+          colors = hili_colors;
+          trans = hili_trans;
+        }
+        else {
+          colors = low_colors;
+          trans = low_trans;
+        }
+        rlelen = rle->len;
+        clr = rle->color;
+        for ( i=0; i<rlelen; ++i ) {
+          if ( trans[clr] == 0 ) {
+            alpha = red = green = blue = 0;
+          }
+          else {
+            red = colors[clr].y; // red
+            green = colors[clr].cr; // green
+            blue = colors[clr].cb; // blue
+            alpha = trans[clr]*255/15;
+          }
+          *rgba = (alpha<<24) | (red<<16) | (green<<8) | blue;
+          rgba++;
+          ++pos;
+        }
+        ++rle;
+        --num_rle;
+      }
+      lprintf("width %d height %d pos %d %d\n", ovl->width, ovl->height, pos, ovl->width * ovl->height);
+    } else {
+      pthread_mutex_lock(&ovl->argb_layer->mutex);
+      bitmap = ovl->argb_layer->buffer;
+    }
+
+    /* Blit overlay to destination */
+    uint32_t pitch = ovl->width * sizeof(uint32_t);
+    uint32_t *copy_dst = this->overlay_bitmap;
+    uint32_t *copy_src = NULL;
+    uint32_t height = 0;
+
+    copy_src = bitmap;
+  
+    copy_dst += ovl->y * this->overlay_bitmap_width;
+
+    lprintf("overlay_bitmap_width %d overlay_bitmap_height %d  ovl->x %d ovl->y %d ovl->width %d ovl->height %d width %d height %d\n",
+      this->overlay_bitmap_width, this->overlay_bitmap_height, ovl->x, ovl->y, ovl->width, ovl->height, this->overlay_bitmap_width, this->overlay_bitmap_height);
+
+    for(height = 0; height < ovl->height; height++) {
+      if((height + ovl->y) >= this->overlay_bitmap_height)
+        break;
+
+      xine_fast_memcpy(copy_dst + ovl->x, copy_src, pitch);
+      copy_dst += this->overlay_bitmap_width;
+      copy_src += ovl->width;
+    }
+
+    if (ovl->rle) {
+      if(bitmap) {
+        free(bitmap);
+        bitmap = NULL;
+      }
+    }
+
+    if (!ovl->rle)
+      pthread_mutex_unlock(&ovl->argb_layer->mutex);
+
+  }
+
+  this->ovl_changed = 0;
+  this->has_overlay = (first_scaled != NULL) | (first_unscaled != NULL);
+
+  lprintf("this->has_overlay %d\n", this->has_overlay);
+  /* Apply OSD layer. */
+  if(va_context->valid_context) {
+    pthread_mutex_lock(&this->vaapi_lock);
+    XLockDisplay(this->display);
+
+    vaapi_ovl_associate(this_gen, frame_gen->format, this->has_overlay);
+
+    XUnlockDisplay(this->display);
+    pthread_mutex_unlock(&this->vaapi_lock);
+  }
+}
+
+static void vaapi_resize_glx_window (vo_driver_t *this_gen, int width, int height) {
+  vaapi_driver_t  *this = (vaapi_driver_t *) this_gen;
+
+  if(this->valid_opengl_context) {
+    glViewport(0, 0, width, height);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    gluPerspective(FOVY, ASPECT, Z_NEAR, Z_FAR);
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+    glTranslatef(-0.5f, -0.5f, -Z_CAMERA);
+    glScalef(1.0f / (GLfloat)width,
+             -1.0f / (GLfloat)height,
+             1.0f / (GLfloat)width);
+    glTranslatef(0.0f, -1.0f * (GLfloat)height, 0.0f);
+  }
+}
+
+static int vaapi_redraw_needed (vo_driver_t *this_gen) {
+  vaapi_driver_t      *this       = (vaapi_driver_t *) this_gen;
+  int                 ret = 0;
+
+  _x_vo_scale_compute_ideal_size( &this->sc );
+
+  if ( _x_vo_scale_redraw_needed( &this->sc ) ) {
+    _x_vo_scale_compute_output_size( &this->sc );
+
+    XMoveResizeWindow(this->display, this->window,
+                      0, 0, this->sc.gui_width, this->sc.gui_height);
+
+    ret = 1;
+  }
+
+  return ret;
+}
+
+static void vaapi_provide_standard_frame_data (vo_frame_t *orig, xine_current_frame_data_t *data)
+{
+  vaapi_driver_t      *driver     = (vaapi_driver_t *) orig->driver;
+  ff_vaapi_context_t  *va_context = driver->va_context;
+
+  vaapi_accel_t       *accel      = (vaapi_accel_t *) orig->accel_data;
+  vo_frame_t          *this       = accel->vo_frame;
+  ff_vaapi_surface_t  *va_surface = &va_render_surfaces[accel->index];
+
+  uint32_t  pitches[3];
+  uint8_t   *base[3];
+
+  if(driver == NULL) {
+    return;
+  }
+
+  if (this->format != XINE_IMGFMT_VAAPI) {
+    xprintf(driver->xine, XINE_VERBOSITY_LOG, LOG_MODULE "vaapi_provide_standard_frame_data: unexpected frame format 0x%08x!\n", this->format);
+    return;
+  }
+
+  if( !accel || va_surface->va_surface_id == VA_INVALID_SURFACE )
+    return;
+
+  lprintf("vaapi_provide_standard_frame_data %s 0x%08x width %d height %d\n",
+      (this->format == XINE_IMGFMT_VAAPI) ? "XINE_IMGFMT_VAAPI" : ((this->format == XINE_IMGFMT_YV12) ? "XINE_IMGFMT_YV12" : "XINE_IMGFMT_YUY2"),
+      va_surface->va_surface_id, this->width, this->height);
+
+  pthread_mutex_lock(&driver->vaapi_lock);
+  XLockDisplay(driver->display);
+
+  int width = va_context->width;
+  int height = va_context->height;
+
+  data->format = XINE_IMGFMT_YV12;
+  data->img_size = width * height
+                   + ((width + 1) / 2) * ((height + 1) / 2)
+                   + ((width + 1) / 2) * ((height + 1) / 2);
+  if (data->img) {
+    pitches[0] = width;
+    pitches[2] = width / 2;
+    pitches[1] = width / 2;
+    base[0] = data->img;
+    base[2] = data->img + width * height;
+    base[1] = data->img + width * height + width * this->height / 4;
+
+    VAImage   va_image;
+    VAStatus  vaStatus;
+    void      *p_base;
+
+    vaStatus = vaSyncSurface(va_context->va_display, va_surface->va_surface_id);
+    vaapi_check_status(va_context->driver, vaStatus, "vaSyncSurface()");
+
+    VASurfaceStatus surf_status = 0;
+
+    if(driver->query_va_status) {
+      vaStatus = vaQuerySurfaceStatus(va_context->va_display, va_surface->va_surface_id, &surf_status);
+      vaapi_check_status(va_context->driver, vaStatus, "vaQuerySurfaceStatus()");
+    } else {
+      surf_status = VASurfaceReady;
+    }
+
+    if(surf_status != VASurfaceReady)
+      goto error;
+
+    vaStatus = vaapi_create_image(va_context->driver, va_surface->va_surface_id, &va_image, width, height, 0);
+    if(!vaapi_check_status(va_context->driver, vaStatus, "vaapi_create_image()"))
+      goto error;
+
+    lprintf("vaapi_provide_standard_frame_data accel->va_surface_id 0x%08x va_image.image_id 0x%08x va_context->width %d va_context->height %d va_image.width %d va_image.height %d width %d height %d size1 %d size2 %d %d %d %d status %d num_planes %d\n",
+       va_surface->va_surface_id, va_image.image_id, va_context->width, va_context->height, va_image.width, va_image.height, width, height, va_image.data_size, data->img_size,
+       va_image.pitches[0], va_image.pitches[1], va_image.pitches[2], surf_status, va_image.num_planes);
+
+    if(va_image.image_id == VA_INVALID_ID)
+      goto error;
+
+    if(!va_context->is_bound) {
+      vaStatus = vaGetImage(va_context->va_display, va_surface->va_surface_id, 0, 0,
+                          va_image.width, va_image.height, va_image.image_id);
+    } else {
+      vaStatus = VA_STATUS_SUCCESS;
+    }
+
+    if(vaapi_check_status(va_context->driver, vaStatus, "vaGetImage()")) {
+      vaStatus = vaMapBuffer( va_context->va_display, va_image.buf, &p_base ) ;
+      if(vaapi_check_status(va_context->driver, vaStatus, "vaMapBuffer()")) {
+
+        /*
+        uint8_t *src[3] = { NULL, };
+        src[0] = (uint8_t *)p_base + va_image.offsets[0];
+        src[1] = (uint8_t *)p_base + va_image.offsets[1];
+        src[2] = (uint8_t *)p_base + va_image.offsets[2];
+        */
+
+        if( va_image.format.fourcc == VA_FOURCC( 'Y', 'V', '1', '2' ) ||
+            va_image.format.fourcc == VA_FOURCC( 'I', '4', '2', '0' ) ) {
+          lprintf("VAAPI YV12 image\n");
+
+          yv12_to_yv12(
+            (uint8_t*)p_base + va_image.offsets[0], va_image.pitches[0],
+            base[0], pitches[0],
+            (uint8_t*)p_base + va_image.offsets[1], va_image.pitches[1],
+            base[1], pitches[1],
+            (uint8_t*)p_base + va_image.offsets[2], va_image.pitches[2],
+            base[2], pitches[2],
+            va_image.width, va_image.height);
+
+        } else if( va_image.format.fourcc == VA_FOURCC( 'N', 'V', '1', '2' ) ) {
+          lprintf("VAAPI NV12 image\n");
+
+          lprintf("va_image.offsets[0] %d va_image.offsets[1] %d va_image.offsets[2] %d size %d size %d size %d width %d height %d width %d height %d\n",
+              va_image.offsets[0], va_image.offsets[1], va_image.offsets[2], va_image.data_size, va_image.width * va_image.height,
+              data->img_size, width, height, va_image.width, va_image.height);
+
+          base[0] = data->img;
+          base[1] = data->img + width * height;
+          base[2] = data->img + width * height + width * height / 4;
+
+          nv12_to_yv12((uint8_t *)p_base + va_image.offsets[0], va_image.pitches[0],
+                       (uint8_t *)p_base + va_image.offsets[1], va_image.pitches[1],
+                       base[0], pitches[0],
+                       base[1], pitches[1],
+                       base[2], pitches[2],
+                       va_image.width,  va_image.height,
+                       width, height,
+                       va_image.data_size);
+
+        } else {
+          printf("vaapi_provide_standard_frame_data unsupported image format\n");
+        }
+
+        vaStatus = vaUnmapBuffer(va_context->va_display, va_image.buf);
+        vaapi_check_status(va_context->driver, vaStatus, "vaUnmapBuffer()");
+        vaapi_destroy_image(va_context->driver, &va_image);
+      }
+    }
+  }
+
+error:
+  XUnlockDisplay(driver->display);
+  pthread_mutex_unlock(&driver->vaapi_lock);
+}
+
+static void vaapi_duplicate_frame_data (vo_frame_t *this_gen, vo_frame_t *original)
+{
+  vaapi_driver_t      *driver     = (vaapi_driver_t *) original->driver;
+  ff_vaapi_context_t  *va_context = driver->va_context;
+
+  vaapi_frame_t *this = (vaapi_frame_t *)this_gen;
+  vaapi_frame_t *orig = (vaapi_frame_t *)original;
+
+  vaapi_accel_t      *accel_this = &this->vaapi_accel_data;
+  vaapi_accel_t      *accel_orig = &orig->vaapi_accel_data;
+
+  ff_vaapi_surface_t *va_surface_this = &va_render_surfaces[accel_this->index];
+  ff_vaapi_surface_t *va_surface_orig = &va_render_surfaces[accel_orig->index];
+
+  lprintf("vaapi_duplicate_frame_data %s %s 0x%08x 0x%08x\n",
+      (this_gen->format == XINE_IMGFMT_VAAPI) ? "XINE_IMGFMT_VAAPI" : ((this_gen->format == XINE_IMGFMT_YV12) ? "XINE_IMGFMT_YV12" : "XINE_IMGFMT_YUY2"),
+      (original->format == XINE_IMGFMT_VAAPI) ? "XINE_IMGFMT_VAAPI" : ((original->format == XINE_IMGFMT_YV12) ? "XINE_IMGFMT_YV12" : "XINE_IMGFMT_YUY2"),
+      va_surface_this->va_surface_id, va_surface_orig->va_surface_id);
+
+  if (orig->vo_frame.format != XINE_IMGFMT_VAAPI) {
+    xprintf(driver->xine, XINE_VERBOSITY_LOG, LOG_MODULE "vaapi_duplicate_frame_data: unexpected frame format 0x%08x!\n", orig->format);
+    return;
+  }
+
+  if (this->vo_frame.format != XINE_IMGFMT_VAAPI) {
+    xprintf(driver->xine, XINE_VERBOSITY_LOG, LOG_MODULE "vaapi_duplicate_frame_data: unexpected frame format 0x%08x!\n", this->format);
+    return;
+  }
+
+  pthread_mutex_lock(&driver->vaapi_lock);
+  XLockDisplay(driver->display);
+
+  VAImage   va_image_orig;
+  VAImage   va_image_this;
+  VAStatus  vaStatus;
+  void      *p_base_orig = NULL;
+  void      *p_base_this = NULL;
+
+  vaStatus = vaSyncSurface(va_context->va_display, va_surface_orig->va_surface_id);
+  vaapi_check_status(va_context->driver, vaStatus, "vaSyncSurface()");
+
+  int this_width = va_context->width;
+  int this_height = va_context->height;
+  int orig_width = va_context->width;
+  int orig_height = va_context->height;
+
+  vaStatus = vaapi_create_image(va_context->driver, va_surface_orig->va_surface_id, &va_image_orig, orig_width, orig_height, 0);
+  if(!vaapi_check_status(va_context->driver, vaStatus, "vaapi_create_image()")) {
+    va_image_orig.image_id = VA_INVALID_ID;
+    goto error;
+  }
+
+  vaStatus = vaapi_create_image(va_context->driver, va_surface_this->va_surface_id, &va_image_this, this_width, this_height, 0);
+  if(!vaapi_check_status(va_context->driver, vaStatus, "vaapi_create_image()")) {
+    va_image_this.image_id = VA_INVALID_ID;
+    goto error;
+  }
+
+  if(va_image_orig.image_id == VA_INVALID_ID || va_image_this.image_id == VA_INVALID_ID) {
+    printf("vaapi_duplicate_frame_data invalid image\n");
+    goto error;
+  }
+
+  lprintf("vaapi_duplicate_frame_data va_image_orig.image_id 0x%08x va_image_orig.width %d va_image_orig.height %d width %d height %d size %d %d %d %d\n",
+       va_image_orig.image_id, va_image_orig.width, va_image_orig.height, this->width, this->height, va_image_orig.data_size,
+       va_image_orig.pitches[0], va_image_orig.pitches[1], va_image_orig.pitches[2]);
+
+  if(!va_context->is_bound) {
+    vaStatus = vaGetImage(va_context->va_display, va_surface_orig->va_surface_id, 0, 0,
+                          va_image_orig.width, va_image_orig.height, va_image_orig.image_id);
+  } else {
+    vaStatus = VA_STATUS_SUCCESS;
+  }
+
+  if(vaapi_check_status(va_context->driver, vaStatus, "vaGetImage()")) {
+    
+    if(!va_context->is_bound) {
+      vaStatus = vaPutImage(va_context->va_display, va_surface_this->va_surface_id, va_image_orig.image_id,
+                            0, 0, va_image_orig.width, va_image_orig.height,
+                            0, 0, va_image_this.width, va_image_this.height);
+      vaapi_check_status(va_context->driver, vaStatus, "vaPutImage()");
+    } else {
+      vaStatus = vaMapBuffer( va_context->va_display, va_image_orig.buf, &p_base_orig ) ;
+      if(!vaapi_check_status(va_context->driver, vaStatus, "vaMapBuffer()"))
+        goto error;
+
+      vaStatus = vaMapBuffer( va_context->va_display, va_image_this.buf, &p_base_this ) ;
+      if(!vaapi_check_status(va_context->driver, vaStatus, "vaMapBuffer()"))
+        goto error;
+
+      int size = (va_image_orig.data_size > va_image_this.data_size) ? va_image_this.data_size : va_image_orig.data_size;
+      xine_fast_memcpy((uint8_t *) p_base_this, (uint8_t *) p_base_orig, size);
+
+    }
+  }
+
+error:
+  if(p_base_orig) {
+    vaStatus = vaUnmapBuffer(va_context->va_display, va_image_orig.buf);
+    vaapi_check_status(va_context->driver, vaStatus, "vaUnmapBuffer()");
+  }
+  if(p_base_this) {
+    vaStatus = vaUnmapBuffer(va_context->va_display, va_image_this.buf);
+    vaapi_check_status(va_context->driver, vaStatus, "vaUnmapBuffer()");
+  }
+
+  vaapi_destroy_image(va_context->driver, &va_image_orig);
+  vaapi_destroy_image(va_context->driver, &va_image_this);
+
+  XUnlockDisplay(driver->display);
+  pthread_mutex_unlock(&driver->vaapi_lock);
+}
+
+static void vaapi_update_frame_format (vo_driver_t *this_gen,
+    vo_frame_t *frame_gen,
+    uint32_t width, uint32_t height,
+    double ratio, int format, int flags) {
+  vaapi_driver_t      *this       = (vaapi_driver_t *) this_gen;
+  vaapi_frame_t       *frame      = (vaapi_frame_t*)frame_gen;
+  vaapi_accel_t       *accel      = &frame->vaapi_accel_data;
+
+  lprintf("vaapi_update_frame_format\n");
+
+  pthread_mutex_lock(&this->vaapi_lock);
+  XLockDisplay(this->display);
+
+  lprintf("vaapi_update_frame_format %s %s width %d height %d\n",
+        (frame->format == XINE_IMGFMT_VAAPI) ? "XINE_IMGFMT_VAAPI" : ((frame->format == XINE_IMGFMT_YV12) ? "XINE_IMGFMT_YV12" : "XINE_IMGFMT_YUY2") ,
+        (format == XINE_IMGFMT_VAAPI) ? "XINE_IMGFMT_VAAPI" : ((format == XINE_IMGFMT_YV12) ? "XINE_IMGFMT_YV12" : "XINE_IMGFMT_YUY2") ,
+        width, height);
+
+  frame->vo_frame.width = width;
+  frame->vo_frame.height = height;
+
+  if ((frame->width != width)
+      || (frame->height != height)
+      || (frame->format != format)) {
+
+    // (re-) allocate render space
+    av_freep (&frame->vo_frame.base[0]);
+    av_freep (&frame->vo_frame.base[1]);
+    av_freep (&frame->vo_frame.base[2]);
+
+    /* set init_vaapi on frame formats XINE_IMGFMT_YV12/XINE_IMGFMT_YUY2 only.
+     * for XINE_IMGFMT_VAAPI the init was already done.
+     */
+    if (format == XINE_IMGFMT_YV12) {
+      frame->vo_frame.pitches[0] = 8*((width + 7) / 8);
+      frame->vo_frame.pitches[1] = 8*((width + 15) / 16);
+      frame->vo_frame.pitches[2] = 8*((width + 15) / 16);
+      frame->vo_frame.base[0] = av_mallocz (frame->vo_frame.pitches[0] * height + FF_INPUT_BUFFER_PADDING_SIZE);
+      frame->vo_frame.base[1] = av_mallocz (frame->vo_frame.pitches[1] * ((height+1)/2) + FF_INPUT_BUFFER_PADDING_SIZE);
+      frame->vo_frame.base[2] = av_mallocz (frame->vo_frame.pitches[2] * ((height+1)/2) + FF_INPUT_BUFFER_PADDING_SIZE);
+      frame->vo_frame.proc_duplicate_frame_data = NULL;
+      frame->vo_frame.proc_provide_standard_frame_data = NULL;
+      lprintf("XINE_IMGFMT_YV12 width %d height %d\n", width, height);
+    } else if (format == XINE_IMGFMT_YUY2){
+      frame->vo_frame.pitches[0] = 8*((width + 3) / 4);
+      frame->vo_frame.base[0] = av_mallocz (frame->vo_frame.pitches[0] * height + FF_INPUT_BUFFER_PADDING_SIZE);
+      frame->vo_frame.proc_duplicate_frame_data = NULL;
+      frame->vo_frame.proc_provide_standard_frame_data = NULL;
+      lprintf("XINE_IMGFMT_YUY2 width %d height %d\n", width, height);
+    } else if (format == XINE_IMGFMT_VAAPI) {
+      frame->vo_frame.proc_duplicate_frame_data = vaapi_duplicate_frame_data;
+      frame->vo_frame.proc_provide_standard_frame_data = vaapi_provide_standard_frame_data;
+      lprintf("XINE_IMGFMT_VAAPI width %d height %d\n", width, height);
+    }
+
+    frame->width  = width;
+    frame->height = height;
+    frame->format = format;
+    frame->flags  = flags;
+    vaapi_frame_field ((vo_frame_t *)frame, flags);
+  }
+
+  if(this->guarded_render) {
+    ff_vaapi_surface_t *va_surface = &va_render_surfaces[accel->index];
+
+    if(va_surface->status == SURFACE_RENDER_RELEASE) {
+      va_surface->status = SURFACE_FREE;
+#ifdef DEBUG_SURFACE
+      printf("release_surface vaapi_update_frame_format 0x%08x\n", va_surface->va_surface_id);
+#endif
+    } else if(va_surface->status == SURFACE_RENDER) {
+      va_surface->status = SURFACE_RELEASE;
+#ifdef DEBUG_SURFACE
+      printf("release_surface vaapi_update_frame_format 0x%08x\n", va_surface->va_surface_id);
+#endif
+    }
+  }
+
+  XUnlockDisplay(this->display);
+  pthread_mutex_unlock(&this->vaapi_lock);
+
+  frame->ratio  = ratio;
+  frame->vo_frame.future_frame = NULL;
+}
+
+static inline uint8_t clip_uint8_vlc( int32_t a )
+{
+  if( a&(~255) ) return (-a)>>31;
+  else           return a;
+}
+
+
+static void nv12_to_yv12(const uint8_t *y_src,  int y_src_pitch,
+                         const uint8_t *uv_src, int uv_src_pitch,
+                         uint8_t *y_dst, int y_dst_pitch,
+                         uint8_t *u_dst, int u_dst_pitch,
+                         uint8_t *v_dst, int v_dst_pitch,
+                         int src_width, int src_height,
+                         int dst_width, int dst_height,
+                         int src_data_size) {
+
+  int y_src_size  = src_height * y_src_pitch;
+  int y, x;
+
+  int uv_src_size = src_height * uv_src_pitch / 2;
+  if((y_src_size + uv_src_size) != (src_data_size))
+    printf("nv12_to_yv12 strange %d\n", (y_src_size + uv_src_size) - (src_data_size));
+
+  int height  = (src_height > dst_height) ? dst_height : src_height;
+  int width   = (src_width > dst_width) ? dst_width : src_width;
+
+  for(y = 0; y < height; y++) {
+    xine_fast_memcpy(y_dst, y_src, width);
+    y_src += y_src_pitch;
+    y_dst += y_dst_pitch;
+  }
+
+  for(y = 0; y < height; y++) {
+    const uint8_t *uv_src_tmp = uv_src;
+    for(x = 0; x < u_dst_pitch; x++) {
+      if(((y * uv_src_pitch) + x) < uv_src_size) {
+        *(u_dst + x) = *(uv_src_tmp    );
+        *(v_dst + x) = *(uv_src_tmp + 1);
+      }
+      uv_src_tmp += 2;
+    }
+    uv_src += uv_src_pitch;
+    u_dst += u_dst_pitch;
+    v_dst += v_dst_pitch;
+  }
+}
+
+static void yv12_to_nv12(const uint8_t *y_src, int y_src_pitch,
+                         const uint8_t *u_src, int u_src_pitch,
+                         const uint8_t *v_src, int v_src_pitch,
+                         uint8_t *y_dst,  int y_dst_pitch,
+                         uint8_t *uv_dst, int uv_dst_pitch,
+                         int src_width, int src_height,
+                         int dst_width, int dst_height,
+                         int dst_data_size) {
+
+  int y_dst_size  = dst_height * y_dst_pitch;
+  int y, x;
+
+  lprintf("yv12_to_nv12 converter\n");
+
+  int uv_dst_size = dst_height * uv_dst_pitch / 2;
+  if((y_dst_size + uv_dst_size) != (dst_data_size))
+    printf("yv12_to_nv12 strange %d\n", (y_dst_size + uv_dst_size) - (dst_data_size));
+
+  int height  = (src_height > dst_height) ? dst_height : src_height;
+  int width   = (src_width > dst_width) ? dst_width : src_width;
+
+  for(y = 0; y < height; y++) {
+    xine_fast_memcpy(y_dst, y_src, width);
+    y_src += y_src_pitch;
+    y_dst += y_dst_pitch;
+  }
+
+  for(y = 0; y < height; y++) {
+    uint8_t *uv_dst_tmp = uv_dst;
+    for(x = 0; x < u_src_pitch; x++) {
+      if(((y * uv_dst_pitch) + x) < uv_dst_size) {
+        *(uv_dst_tmp    ) = *(u_src + x);
+        *(uv_dst_tmp + 1) = *(v_src + x);
+      }
+      uv_dst_tmp += 2;
+    }
+    uv_dst += uv_dst_pitch;
+    u_src += u_src_pitch;
+    v_src += v_src_pitch;
+  }
+}
+
+static VAStatus vaapi_software_render_frame(vo_driver_t *this_gen, vo_frame_t *frame_gen,
+                                             VAImage *va_image, VASurfaceID va_surface_id) {
+  vaapi_driver_t     *this            = (vaapi_driver_t *) this_gen;
+  vaapi_frame_t      *frame           = (vaapi_frame_t *) frame_gen;
+  ff_vaapi_context_t *va_context      = this->va_context;
+  void               *p_base          = NULL;
+  VAStatus           vaStatus;
+
+  if(va_image == NULL || va_image->image_id == VA_INVALID_ID ||
+     va_surface_id == VA_INVALID_SURFACE || !va_context->valid_context)
+    return VA_STATUS_ERROR_UNKNOWN;
+
+  lprintf("vaapi_software_render_frame : va_surface_id 0x%08x va_image.image_id 0x%08x width %d height %d f_width %d f_height %d sw_width %d sw_height %d\n",
+      va_surface_id, va_image->image_id, va_image->width, va_image->height, frame->width, frame->height,
+      va_context->sw_width, va_context->sw_height);
+
+  if(frame->width != va_image->width || frame->height != va_image->height)
+    return VA_STATUS_SUCCESS;
+
+  vaStatus = vaMapBuffer( va_context->va_display, va_image->buf, &p_base ) ;
+  if(!vaapi_check_status(va_context->driver, vaStatus, "vaMapBuffer()"))
+    return vaStatus;
+
+
+  uint8_t *dst[3] = { NULL, };
+  uint32_t  pitches[3];
+
+  if(this->swap_uv_planes) {
+    dst[0] = (uint8_t *)p_base + va_image->offsets[0]; pitches[0] = va_image->pitches[0];
+    dst[1] = (uint8_t *)p_base + va_image->offsets[1]; pitches[1] = va_image->pitches[1];
+    dst[2] = (uint8_t *)p_base + va_image->offsets[2]; pitches[2] = va_image->pitches[2];
+  } else {
+    dst[0] = (uint8_t *)p_base + va_image->offsets[0]; pitches[0] = va_image->pitches[0];
+    dst[1] = (uint8_t *)p_base + va_image->offsets[2]; pitches[1] = va_image->pitches[1];
+    dst[2] = (uint8_t *)p_base + va_image->offsets[1]; pitches[2] = va_image->pitches[2];
+  }
+
+  /* Copy xine frames into VAAPI images */
+  if(frame->format == XINE_IMGFMT_YV12) {
+
+    if (va_image->format.fourcc == VA_FOURCC( 'Y', 'V', '1', '2' ) ||
+        va_image->format.fourcc == VA_FOURCC( 'I', '4', '2', '0' ) ) {
+      lprintf("vaapi_software_render_frame yv12 -> yv12 convert\n");
+
+      yv12_to_yv12(
+              /* Y */
+              frame_gen->base[0], frame_gen->pitches[0],
+              dst[0], pitches[0],
+              /* U */
+              frame_gen->base[1], frame_gen->pitches[1],
+              dst[1], pitches[1],
+              /* V */
+              frame_gen->base[2], frame_gen->pitches[2],
+              dst[2], pitches[2],
+              /* width x height */
+              frame_gen->width, frame_gen->height);
+
+    } else if (va_image->format.fourcc == VA_FOURCC( 'N', 'V', '1', '2' )) {
+      lprintf("vaapi_software_render_frame yv12 -> nv12 convert\n");
+
+      yv12_to_nv12(frame_gen->base[0], frame_gen->pitches[0],
+                   frame_gen->base[1], frame_gen->pitches[1],
+                   frame_gen->base[2], frame_gen->pitches[2],
+                   (uint8_t *)p_base + va_image->offsets[0], va_image->pitches[0],
+                   (uint8_t *)p_base + va_image->offsets[1], va_image->pitches[1],
+                   frame_gen->width, frame_gen->height,
+                   va_image->width,  va_image->height,
+                   va_image->data_size);
+
+    }
+  } else if (frame->format == XINE_IMGFMT_YUY2) {
+
+    if (va_image->format.fourcc == VA_FOURCC( 'Y', 'V', '1', '2' ) ||
+        va_image->format.fourcc == VA_FOURCC( 'I', '4', '2', '0' ) ) {
+      lprintf("vaapi_software_render_frame yuy2 -> yv12 convert\n");
+
+      yuy2_to_yv12(frame_gen->base[0], frame_gen->pitches[0],
+                  dst[0], pitches[0],
+                  dst[1], pitches[1],
+                  dst[2], pitches[2],
+                  frame_gen->width, frame_gen->height);
+
+    } else if (va_image->format.fourcc == VA_FOURCC( 'N', 'V', '1', '2' )) {
+      lprintf("vaapi_software_render_frame yuy2 -> nv12 convert\n");
+      printf("yuy2 -> nv12 convert missing\n");
+    }
+
+  }
+
+  vaStatus = vaUnmapBuffer(va_context->va_display, va_image->buf);
+  vaapi_check_status(this_gen, vaStatus, "vaUnmapBuffer()");
+
+  if(!va_context->is_bound) {
+    vaStatus = vaPutImage(va_context->va_display, va_surface_id, va_image->image_id,
+                        0, 0, va_image->width, va_image->height,
+                        0, 0, va_image->width, va_image->height);
+  }
+
+  if(!vaapi_check_status(va_context->driver, vaStatus, "vaPutImage()"))
+    return vaStatus;
+
+  return VA_STATUS_SUCCESS;
+}
+
+static VAStatus vaapi_hardware_render_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen,
+                                             VASurfaceID va_surface_id) {
+  vaapi_driver_t     *this            = (vaapi_driver_t *) this_gen;
+  vaapi_frame_t      *frame           = (vaapi_frame_t *) frame_gen;
+  ff_vaapi_context_t *va_context      = this->va_context;
+  VAStatus           vaStatus         = VA_STATUS_ERROR_UNKNOWN;
+  int                i                = 0;
+  int                interlaced_frame = !frame->vo_frame.progressive_frame;
+  int                top_field_first  = frame->vo_frame.top_field_first;
+  int                width, height;
+
+  if(frame->format == XINE_IMGFMT_VAAPI) {
+    width  = va_context->width;
+    height = va_context->height;
+  } else {
+    width  = (frame->width > va_context->sw_width) ? va_context->sw_width : frame->width;
+    height = (frame->height > va_context->sw_height) ? va_context->sw_height : frame->height;
+  }
+
+  if(!va_context->valid_context || va_surface_id == VA_INVALID_SURFACE)
+    return VA_STATUS_ERROR_UNKNOWN;
+
+  if(this->opengl_render && !this->valid_opengl_context)
+    return VA_STATUS_ERROR_UNKNOWN;
+
+  /* Final VAAPI rendering. The deinterlacing can be controled by xine config.*/
+  unsigned int deint = this->deinterlace;
+  for(i = 0; i <= !!((deint > 1) && interlaced_frame); i++) {
+    unsigned int flags = (deint && (interlaced_frame) ? (((!!(top_field_first)) ^ i) == 0 ? VA_BOTTOM_FIELD : VA_TOP_FIELD) : VA_FRAME_PICTURE);
+
+    //flags |= vaapi_get_colorspace_flags(this_gen);
+
+    flags |= VA_CLEAR_DRAWABLE;
+    flags |= this->scaling_level;
+
+    lprintf("Putsrfc srfc 0x%08X flags 0x%08x %dx%d -> %dx%d interlaced %d top_field_first %d\n",
+            va_surface_id, flags, width, height,
+            this->sc.output_width, this->sc.output_height,
+            interlaced_frame, top_field_first);
+
+    if(this->opengl_render) {
+
+      vaapi_x11_trap_errors();
+
+      if(this->opengl_use_tfp) {
+        lprintf("opengl render tfp\n");
+        vaStatus = vaPutSurface(va_context->va_display, va_surface_id, this->gl_image_pixmap,
+                 0, 0, width, height, 0, 0, width, height, NULL, 0, flags);
+        if(!vaapi_check_status(this_gen, vaStatus, "vaPutSurface()"))
+          return vaStatus;
+      } else {
+        lprintf("opengl render\n");
+        vaStatus = vaCopySurfaceGLX(va_context->va_display, va_context->gl_surface, va_surface_id, flags);
+        if(!vaapi_check_status(this_gen, vaStatus, "vaCopySurfaceGLX()"))
+          return vaStatus;
+      }
+      if(vaapi_x11_untrap_errors())
+        return VA_STATUS_ERROR_UNKNOWN;
+      
+      vaapi_glx_flip_page(frame_gen, 0, 0, va_context->width, va_context->height);
+
+    } else {
+
+      vaStatus = vaPutSurface(va_context->va_display, va_surface_id, this->window,
+                   0, 0, width, height,
+                   this->sc.output_xoffset, this->sc.output_yoffset,
+                   this->sc.output_width, this->sc.output_height,
+                   NULL, 0, flags);
+      if(!vaapi_check_status(this_gen, vaStatus, "vaPutSurface()"))
+        return vaStatus;
+    }
+  }
+  return VA_STATUS_SUCCESS;
+}
+
+/* Used in vaapi_display_frame to determine how long displaying a frame takes
+   - if slower than 60fps, print a message
+*/
+/*
+static double timeOfDay()
+{
+    struct timeval t;
+    gettimeofday( &t, NULL );
+    return ((double)t.tv_sec) + (((double)t.tv_usec)/1000000.0);
+}
+*/
+
+static void vaapi_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
+  vaapi_driver_t     *this          = (vaapi_driver_t *) this_gen;
+  vaapi_frame_t      *frame         = (vaapi_frame_t *) frame_gen;
+  vaapi_accel_t      *accel         = &frame->vaapi_accel_data;
+  ff_vaapi_context_t *va_context    = this->va_context;
+  ff_vaapi_surface_t *va_surface    = &va_render_surfaces[accel->index];
+  VASurfaceID        va_surface_id  = VA_INVALID_SURFACE;
+  VAImage            *va_image      = NULL;
+  VAStatus           vaStatus;
+
+  lprintf("vaapi_display_frame\n");
+
+  /*
+  if((frame->height < 17 || frame->width < 17) && ((frame->format == XINE_IMGFMT_YV12) || (frame->format == XINE_IMGFMT_YUY2))) {
+    frame->vo_frame.free( frame_gen );
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " frame size to small width %d height %d\n", frame->height, frame->width);
+    return;
+  }
+  */
+
+  /*
+   * let's see if this frame is different in size / aspect
+   * ratio from the previous one
+   */
+
+  if ( (frame->width != this->sc.delivered_width)
+       || (frame->height != this->sc.delivered_height)
+       || (frame->ratio != this->sc.delivered_ratio)
+       || (frame->vo_frame.crop_left != this->sc.crop_left)
+       || (frame->vo_frame.crop_right != this->sc.crop_right)
+       || (frame->vo_frame.crop_top != this->sc.crop_top)
+       || (frame->vo_frame.crop_bottom != this->sc.crop_bottom) ) {
+    lprintf("frame format changed\n");
+    this->sc.force_redraw = 1;
+  }
+
+  /*
+   * tell gui that we are about to display a frame,
+   * ask for offset and output size
+   */
+  this->sc.delivered_height = frame->height;
+  this->sc.delivered_width  = frame->width;
+  this->sc.delivered_ratio  = frame->ratio;
+  this->sc.crop_left        = frame->vo_frame.crop_left;
+  this->sc.crop_right       = frame->vo_frame.crop_right;
+  this->sc.crop_top         = frame->vo_frame.crop_top;
+  this->sc.crop_bottom      = frame->vo_frame.crop_bottom;
+
+  /*
+   * tell gui that we are about to display a frame,
+   * ask for offset and output size
+   */
+  this->sc.delivered_height = frame->height;
+  this->sc.delivered_width  = frame->width;
+  this->sc.delivered_ratio  = frame->ratio;
+
+  this->sc.crop_left        = frame->vo_frame.crop_left;
+  this->sc.crop_right       = frame->vo_frame.crop_right;
+  this->sc.crop_top         = frame->vo_frame.crop_top;
+  this->sc.crop_bottom      = frame->vo_frame.crop_bottom;
+
+  pthread_mutex_lock(&this->vaapi_lock);
+  XLockDisplay(this->display);
+
+  lprintf("vaapi_display_frame %s frame->width %d frame->height %d va_context->sw_width %d va_context->sw_height %d valid_context %d\n",
+        (frame->format == XINE_IMGFMT_VAAPI) ? "XINE_IMGFMT_VAAPI" : ((frame->format == XINE_IMGFMT_YV12) ? "XINE_IMGFMT_YV12" : "XINE_IMGFMT_YUY2") ,
+        frame->width, frame->height, va_context->sw_width, va_context->sw_height, va_context->valid_context);
+
+  if( ((frame->format == XINE_IMGFMT_YV12) || (frame->format == XINE_IMGFMT_YUY2))
+      && ((frame->width != va_context->sw_width) ||(frame->height != va_context->sw_height )) ) {
+
+    lprintf("vaapi_display_frame %s frame->width %d frame->height %d\n",
+        (frame->format == XINE_IMGFMT_VAAPI) ? "XINE_IMGFMT_VAAPI" : ((frame->format == XINE_IMGFMT_YV12) ? "XINE_IMGFMT_YV12" : "XINE_IMGFMT_YUY2") ,
+        frame->width, frame->height);
+
+    unsigned int last_sub_img_fmt = va_context->last_sub_image_fmt;
+
+    if(last_sub_img_fmt)
+      vaapi_ovl_associate(this_gen, frame_gen->format, 0);
+
+    if(!va_context->valid_context) {
+      lprintf("vaapi_display_frame init full context\n");
+      vaapi_init_internal(frame_gen->driver, SW_CONTEXT_INIT_FORMAT, frame->width, frame->height, 0);
+    } else {
+      lprintf("vaapi_display_frame init soft surfaces\n");
+      vaapi_init_soft_surfaces(frame_gen->driver, frame->width, frame->height);
+    }
+
+    this->sc.force_redraw = 1;
+    this->init_opengl_render = 1;
+
+    if(last_sub_img_fmt)
+      vaapi_ovl_associate(this_gen, frame_gen->format, this->has_overlay);
+  }
+
+  XUnlockDisplay(this->display);
+  pthread_mutex_unlock(&this->vaapi_lock);
+
+  vaapi_redraw_needed (this_gen);
+
+  /* posible race could happen while the lock is opened */
+  if(!this->va_context || !this->va_context->valid_context)
+    return;
+
+  pthread_mutex_lock(&this->vaapi_lock);
+  XLockDisplay(this->display);
+
+  /* initialize opengl rendering */
+  if(this->opengl_render && this->init_opengl_render &&  va_context->valid_context) {
+    unsigned int last_sub_img_fmt = va_context->last_sub_image_fmt;
+
+    if(last_sub_img_fmt)
+      vaapi_ovl_associate(this_gen, frame_gen->format, 0);
+
+    destroy_glx(this_gen);
+
+    vaapi_glx_config_glx(frame_gen->driver, va_context->width, va_context->height);
+
+    vaapi_resize_glx_window(frame_gen->driver, this->sc.gui_width, this->sc.gui_height);
+
+    if(last_sub_img_fmt)
+      vaapi_ovl_associate(this_gen, frame_gen->format, this->has_overlay);
+
+    this->sc.force_redraw = 1;
+    this->init_opengl_render = 0;
+  }
+
+  /*
+  double start_time;
+  double end_time;
+  double elapse_time;
+  int factor;
+
+  start_time = timeOfDay();
+  */
+
+  if(va_context->valid_context && ( (frame->format == XINE_IMGFMT_VAAPI) || (frame->format == XINE_IMGFMT_YV12) || (frame->format == XINE_IMGFMT_YUY2) )) {
+
+    if((frame->format == XINE_IMGFMT_YUY2) || (frame->format == XINE_IMGFMT_YV12)) {
+      va_surface_id = va_soft_surface_ids[va_context->va_soft_head];
+      va_image = &va_soft_images[va_context->va_soft_head];
+      va_context->va_soft_head = (va_context->va_soft_head + 1) % (SOFT_SURFACES);
+    }
+
+    if(this->guarded_render) {
+      if(frame->format == XINE_IMGFMT_VAAPI) {
+        ff_vaapi_surface_t *va_surface = &va_render_surfaces[accel->index];
+        if(va_surface->status == SURFACE_RENDER || va_surface->status == SURFACE_RENDER_RELEASE) {
+          va_surface_id = va_surface->va_surface_id;
+        }
+        va_image      = NULL;
+      }
+#ifdef DEBUG_SURFACE
+      printf("vaapi_display_frame va_surface 0x%08x status %d index %d\n", va_surface_id, va_surface->status, accel->index);
+#endif
+    } else {
+      if(frame->format == XINE_IMGFMT_VAAPI) {
+        va_surface_id = va_surface->va_surface_id;
+        va_image      = NULL;
+      }
+    }
+
+    lprintf("2: 0x%08x\n", va_surface_id);
+
+    VASurfaceStatus surf_status = 0;
+    if(va_surface_id != VA_INVALID_SURFACE) {
+
+      if(this->query_va_status) {
+        vaStatus = vaQuerySurfaceStatus(va_context->va_display, va_surface_id, &surf_status);
+        vaapi_check_status(this_gen, vaStatus, "vaQuerySurfaceStatus()");
+      } else {
+        surf_status = VASurfaceReady;
+      }
+
+      if(surf_status != VASurfaceReady) {
+        va_surface_id = VA_INVALID_SURFACE;
+        va_image = NULL;
+#ifdef DEBUG_SURFACE
+        printf("Surface srfc 0x%08X not ready for render\n", va_surface_id);
+#endif
+      }
+    } else {
+#ifdef DEBUG_SURFACE
+      printf("Invalid srfc 0x%08X\n", va_surface_id);
+#endif
+    }
+
+    if(va_surface_id != VA_INVALID_SURFACE) {
+
+      lprintf("vaapi_display_frame: 0x%08x %d %d\n", va_surface_id, va_context->width, va_context->height);
+    
+      vaStatus = vaSyncSurface(va_context->va_display, va_surface_id);
+      vaapi_check_status(this_gen, vaStatus, "vaSyncSurface()");
+
+      /* transfer image data to a VAAPI surface */
+      if((frame->format == XINE_IMGFMT_YUY2 || frame->format == XINE_IMGFMT_YV12))
+        vaapi_software_render_frame(this_gen, frame_gen, va_image, va_surface_id);
+
+      vaapi_hardware_render_frame(this_gen, frame_gen, va_surface_id);
+
+    }
+  } else {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " unsupported image format %s width %d height %d valid_context %d\n",
+        (frame->format == XINE_IMGFMT_VAAPI) ? "XINE_IMGFMT_VAAPI" : ((frame->format == XINE_IMGFMT_YV12) ? "XINE_IMGFMT_YV12" : "XINE_IMGFMT_YUY2") ,
+        frame->width, frame->height, va_context->valid_context);
+  }
+
+  XSync(this->display, False);
+
+  //end_time = timeOfDay();
+
+  if(this->guarded_render) {
+    ff_vaapi_surface_t *va_surface = &va_render_surfaces[accel->index];
+
+    if(va_surface->status == SURFACE_RENDER_RELEASE) {
+      va_surface->status = SURFACE_FREE;
+#ifdef DEBUG_SURFACE
+      printf("release_surface vaapi_display_frame 0x%08x\n", va_surface->va_surface_id);
+#endif
+    } else if(va_surface->status == SURFACE_RENDER) {
+      va_surface->status = SURFACE_RELEASE;
+#ifdef DEBUG_SURFACE
+      printf("release_surface vaapi_display_frame 0x%08x\n", va_surface->va_surface_id);
+#endif
+    }
+  }
+
+  XUnlockDisplay(this->display);
+
+  frame->vo_frame.free( frame_gen );
+
+  pthread_mutex_unlock(&this->vaapi_lock);
+
+  /*
+  elapse_time = end_time - start_time;
+  factor = (int)(elapse_time/(1.0/60.0));
+
+  if( factor > 1 )
+  {
+    xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " PutImage %dX interval (%fs)\n", factor, elapse_time );
+  }
+  */
+}
+
+static int vaapi_get_property (vo_driver_t *this_gen, int property) {
+  vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
+
+  switch (property) {
+    case VO_PROP_WINDOW_WIDTH:
+      this->props[property].value = this->sc.gui_width;
+      break;
+    case VO_PROP_WINDOW_HEIGHT:
+      this->props[property].value = this->sc.gui_height;
+      break;
+    case VO_PROP_OUTPUT_WIDTH:
+      this->props[property].value = this->sc.output_width;
+      break;
+    case VO_PROP_OUTPUT_HEIGHT:
+      this->props[property].value = this->sc.output_height;
+      break;
+    case VO_PROP_OUTPUT_XOFFSET:
+      this->props[property].value = this->sc.output_xoffset;
+      break;
+    case VO_PROP_OUTPUT_YOFFSET:
+      this->props[property].value = this->sc.output_yoffset;
+      break;
+    case VO_PROP_MAX_NUM_FRAMES:
+      if(!this->guarded_render)
+        this->props[property].value = RENDER_SURFACES;
+      else
+        this->props[property].value = 2;
+      break;
+  }
+
+  lprintf("vaapi_get_property property=%d, value=%d\n", property, this->props[property].value );
+
+  return this->props[property].value;
+}
+
+static int vaapi_set_property (vo_driver_t *this_gen, int property, int value) {
+
+  vaapi_driver_t      *this       = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+
+  lprintf("vaapi_set_property property=%d, value=%d\n", property, value );
+
+  if(this->props[property].atom) {
+    VADisplayAttribute attr;
+
+    if((value < this->props[property].min) || (value > this->props[property].max))
+      value = (this->props[property].min + this->props[property].max) >> 1;
+
+    this->props[property].value = value;
+    attr.type   = this->props[property].type;
+    attr.value  = value;
+
+    if(va_context && va_context->valid_context) {
+      VAStatus vaStatus = vaSetDisplayAttributes(va_context->va_display, &attr, 1);
+      vaapi_check_status((vo_driver_t *)this, vaStatus, "vaSetDisplayAttributes()");
+    }
+
+    if (this->props[property].entry)
+      this->props[property].entry->num_value = this->props[property].value;
+
+    vaapi_show_display_props((vo_driver_t*)this);
+
+    return this->props[property].value;
+  } else {
+    switch (property) {
+
+      case VO_PROP_ASPECT_RATIO:
+        if (value>=XINE_VO_ASPECT_NUM_RATIOS)
+        value = XINE_VO_ASPECT_AUTO;
+        this->props[property].value = value;
+        this->sc.user_ratio = value;
+        _x_vo_scale_compute_ideal_size (&this->sc);
+        this->sc.force_redraw = 1;
+        break;
+
+      case VO_PROP_ZOOM_X:
+        if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) {
+          this->props[property].value = value;
+        this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP;
+          _x_vo_scale_compute_ideal_size (&this->sc);
+          this->sc.force_redraw = 1;
+        }
+        break;
+
+      case VO_PROP_ZOOM_Y:
+        if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) {
+          this->props[property].value = value;
+          this->sc.zoom_factor_y = (double)value / (double)XINE_VO_ZOOM_STEP;
+        _x_vo_scale_compute_ideal_size (&this->sc);
+        this->sc.force_redraw = 1;
+        }
+        break;
+    }
+  }
+  return value;
+}
+
+static void vaapi_get_property_min_max (vo_driver_t *this_gen,
+     int property, int *min, int *max) {
+  vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
+
+  *min = this->props[property].min;
+  *max = this->props[property].max;
+}
+
+static int vaapi_gui_data_exchange (vo_driver_t *this_gen,
+ int data_type, void *data) {
+  vaapi_driver_t     *this       = (vaapi_driver_t *) this_gen;
+
+  lprintf("vaapi_gui_data_exchange %d\n", data_type);
+
+  switch (data_type) {
+#ifndef XINE_DISABLE_DEPRECATED_FEATURES
+  case XINE_GUI_SEND_COMPLETION_EVENT:
+    break;
+#endif
+
+  case XINE_GUI_SEND_EXPOSE_EVENT: {
+    pthread_mutex_lock(&this->vaapi_lock);
+    XLockDisplay( this->display );
+    lprintf("XINE_GUI_SEND_EXPOSE_EVENT:\n");
+    this->sc.force_redraw = 1;
+    this->init_opengl_render = 1;
+    XUnlockDisplay( this->display );
+    pthread_mutex_unlock(&this->vaapi_lock);
+  }
+  break;
+
+  case XINE_GUI_SEND_WILL_DESTROY_DRAWABLE: {
+    printf("XINE_GUI_SEND_WILL_DESTROY_DRAWABLE\n");
+  }
+  break;
+
+  case XINE_GUI_SEND_DRAWABLE_CHANGED: {
+    pthread_mutex_lock(&this->vaapi_lock);
+    XLockDisplay( this->display );
+    lprintf("XINE_GUI_SEND_DRAWABLE_CHANGED\n");
+
+    this->drawable = (Drawable) data;
+
+    XReparentWindow(this->display, this->window, this->drawable, 0, 0);
+
+    this->sc.force_redraw = 1;
+    this->init_opengl_render = 1;
+
+    XUnlockDisplay( this->display );
+    pthread_mutex_unlock(&this->vaapi_lock);
+  }
+  break;
+
+  case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO: {
+    int x1, y1, x2, y2;
+    x11_rectangle_t *rect = data;
+
+    _x_vo_scale_translate_gui2video(&this->sc, rect->x, rect->y, &x1, &y1);
+    _x_vo_scale_translate_gui2video(&this->sc, rect->x + rect->w, rect->y + rect->h, &x2, &y2);
+    rect->x = x1;
+    rect->y = y1;
+    rect->w = x2-x1;
+    rect->h = y2-y1;
+  }
+  break;
+
+  default:
+    return -1;
+  }
+
+  return 0;
+}
+
+static void vaapi_dispose (vo_driver_t *this_gen) {
+  vaapi_driver_t      *this = (vaapi_driver_t *) this_gen;
+  ff_vaapi_context_t  *va_context = this->va_context;
+
+  lprintf("vaapi_dispose\n");
+
+  pthread_mutex_lock(&this->vaapi_lock);
+  XLockDisplay(this->display);
+
+  this->ovl_yuv2rgb->dispose(this->ovl_yuv2rgb);
+  this->yuv2rgb_factory->dispose (this->yuv2rgb_factory);
+
+  vaapi_close(this_gen);
+  free(va_context);
+
+  if(this->overlay_bitmap)
+    free(this->overlay_bitmap);
+
+  if(va_surface_ids)
+    free(va_surface_ids);
+  if(va_soft_surface_ids)
+    free(va_soft_surface_ids);
+  if(va_render_surfaces)
+    free(va_render_surfaces);
+  if(va_soft_images)
+    free(va_soft_images);
+
+  XDestroyWindow(this->display, this->window);
+  XUnlockDisplay(this->display);
+
+  pthread_mutex_unlock(&this->vaapi_lock);
+  pthread_mutex_destroy(&this->vaapi_lock);
+
+  free (this);
+}
+
+static void vaapi_vdr_osd_width_flag( void *this_gen, xine_cfg_entry_t *entry )
+{
+  vaapi_driver_t  *this  = (vaapi_driver_t *) this_gen;
+
+  this->vdr_osd_width = entry->num_value;
+}
+
+static void vaapi_vdr_osd_height_flag( void *this_gen, xine_cfg_entry_t *entry )
+{
+  vaapi_driver_t  *this  = (vaapi_driver_t *) this_gen;
+
+  this->vdr_osd_height = entry->num_value;
+}
+
+static void vaapi_deinterlace_flag( void *this_gen, xine_cfg_entry_t *entry )
+{
+  vaapi_driver_t  *this  = (vaapi_driver_t *) this_gen;
+
+  this->deinterlace = entry->num_value;
+  if(this->deinterlace > 2)
+    this->deinterlace = 2;
+}
+
+static void vaapi_opengl_render( void *this_gen, xine_cfg_entry_t *entry )
+{
+  vaapi_driver_t  *this  = (vaapi_driver_t *) this_gen;
+
+  this->opengl_render = entry->num_value;
+}
+
+static void vaapi_opengl_use_tfp( void *this_gen, xine_cfg_entry_t *entry )
+{
+  vaapi_driver_t  *this  = (vaapi_driver_t *) this_gen;
+
+  this->opengl_use_tfp = entry->num_value;
+}
+
+static void vaapi_guarded_render( void *this_gen, xine_cfg_entry_t *entry )
+{
+  vaapi_driver_t  *this  = (vaapi_driver_t *) this_gen;
+
+  this->guarded_render = entry->num_value;
+}
+
+static void vaapi_scaling_level( void *this_gen, xine_cfg_entry_t *entry )
+{
+  vaapi_driver_t  *this  = (vaapi_driver_t *) this_gen;
+
+  this->scaling_level = entry->num_value;
+}
+
+static void vaapi_swap_uv_planes(void *this_gen, xine_cfg_entry_t *entry)
+{
+  vaapi_driver_t  *this  = (vaapi_driver_t *) this_gen;
+
+  this->swap_uv_planes = entry->num_value;
+}
+
+static vo_driver_t *vaapi_open_plugin (video_driver_class_t *class_gen, const void *visual_gen) {
+
+  vaapi_class_t           *class  = (vaapi_class_t *) class_gen;
+  x11_visual_t            *visual = (x11_visual_t *) visual_gen;
+  vaapi_driver_t          *this;
+  config_values_t         *config = class->config;
+  XSetWindowAttributes    xswa;
+  unsigned long           xswa_mask;
+  XWindowAttributes       wattr;
+  unsigned long           black_pixel;
+  XVisualInfo             visualInfo;
+  XVisualInfo             *vi;
+  int                     depth;
+  const int               x11_event_mask = ExposureMask |
+                                           StructureNotifyMask;
+
+  this = (vaapi_driver_t *) calloc(1, sizeof(vaapi_driver_t));
+  if (!this)
+    return NULL;
+
+  this->config                  = config;
+  this->xine                    = class->xine;
+
+  this->display                 = visual->display;
+  this->screen                  = visual->screen;
+  this->drawable                = visual->d;
+
+  this->va_context              = calloc(1, sizeof(ff_vaapi_context_t));
+
+  /* number of video frames from config - register it with the default value. */
+  int frame_num = config->register_num (config, "engine.buffers.video_num_frames", RENDER_SURFACES, /* default */
+       _("default number of video frames"),
+       _("The default number of video frames to request "
+         "from xine video out driver. Some drivers will "
+         "override this setting with their own values."),
+      20, NULL, this);
+
+  /* now make sure we have at least 22 frames, to prevent
+   * locks with vdpau_h264 */
+  if(frame_num != RENDER_SURFACES)
+    config->update_num(config,"engine.buffers.video_num_frames", RENDER_SURFACES);
+
+  this->opengl_render = config->register_bool( config, "video.output.vaapi_opengl_render", 0,
+        _("vaapi: opengl output rendering"),
+        _("vaapi: opengl output rendering"),
+        20, vaapi_opengl_render, this );
+  
+  this->init_opengl_render = 1;
+
+  this->opengl_use_tfp = config->register_bool( config, "video.output.vaapi_opengl_use_tfp", 0,
+        _("vaapi: opengl rendering tfp"),
+        _("vaapi: opengl rendering tfp"),
+        20, vaapi_opengl_use_tfp, this );
+
+  if(this->opengl_render) {
+      this->opengl_render = vaapi_opengl_verify_direct ((x11_visual_t *)visual_gen);
+      if(!this->opengl_render)
+        xprintf (this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_open: Opengl indirect/software rendering does not work. Fallback to plain VAAPI output !!!!\n");
+  }
+
+  this->valid_opengl_context            = 0;
+  this->gl_vinfo                        = NULL;
+  this->gl_pixmap                       = None;
+  this->gl_image_pixmap                 = None;
+  this->gl_texture                      = GL_NONE;
+
+  this->num_frame_buffers               = 0;
+
+  va_render_surfaces                    = calloc(RENDER_SURFACES + 1, sizeof(ff_vaapi_surface_t));
+  va_surface_ids                        = calloc(RENDER_SURFACES + 1, sizeof(VASurfaceID));
+  va_soft_surface_ids                   = calloc(SOFT_SURFACES + 1, sizeof(VASurfaceID));
+  va_soft_images                        = calloc(SOFT_SURFACES + 1, sizeof(VAImage));
+
+  vaapi_init_va_context(this);
+  vaapi_init_subpicture(this);
+
+  _x_vo_scale_init (&this->sc, 1, 0, config );
+
+  this->sc.frame_output_cb      = visual->frame_output_cb;
+  this->sc.dest_size_cb         = visual->dest_size_cb;
+  this->sc.user_data            = visual->user_data;
+  this->sc.user_ratio           = XINE_VO_ASPECT_AUTO;
+
+  black_pixel         = BlackPixel(this->display, this->screen);
+
+  XGetWindowAttributes(this->display, this->drawable, &wattr);
+
+  depth = wattr.depth;
+  if (depth != 15 && depth != 16 && depth != 24 && depth != 32)
+    depth = 24;
+
+  vi = &visualInfo;
+  XMatchVisualInfo(this->display, this->screen, depth, TrueColor, vi);
+
+  xswa_mask             = CWBorderPixel | CWBackPixel | CWColormap;
+  xswa.border_pixel     = black_pixel;
+  xswa.background_pixel = black_pixel;
+  xswa.colormap         = CopyFromParent;
+
+  this->window = XCreateWindow(this->display, this->drawable,
+                             0, 0, 1, 1, 0, depth,
+                             InputOutput, vi->visual, xswa_mask, &xswa);
+
+  if(this->window == None)
+    return NULL;
+
+  XSelectInput(this->display, this->window, x11_event_mask);
+
+  XMapWindow(this->display, this->window);
+  vaapi_x11_wait_event(this->display, this->window, MapNotify);
+
+  if(vi != &visualInfo)
+    XFree(vi);
+
+  this->capabilities            = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY | VO_CAP_ARGB_LAYER_OVERLAY | VO_CAP_VAAPI | VO_CAP_CUSTOM_EXTENT_OVERLAY;
+
+  /*  overlay converter */
+  this->yuv2rgb_factory = yuv2rgb_factory_init (MODE_24_BGR, 0, NULL);
+  this->ovl_yuv2rgb = this->yuv2rgb_factory->create_converter( this->yuv2rgb_factory );
+
+  this->vo_driver.get_capabilities     = vaapi_get_capabilities;
+  this->vo_driver.alloc_frame          = vaapi_alloc_frame;
+  this->vo_driver.update_frame_format  = vaapi_update_frame_format;
+  this->vo_driver.overlay_begin        = vaapi_overlay_begin;
+  this->vo_driver.overlay_blend        = vaapi_overlay_blend;
+  this->vo_driver.overlay_end          = vaapi_overlay_end;
+  this->vo_driver.display_frame        = vaapi_display_frame;
+  this->vo_driver.get_property         = vaapi_get_property;
+  this->vo_driver.set_property         = vaapi_set_property;
+  this->vo_driver.get_property_min_max = vaapi_get_property_min_max;
+  this->vo_driver.gui_data_exchange    = vaapi_gui_data_exchange;
+  this->vo_driver.dispose              = vaapi_dispose;
+  this->vo_driver.redraw_needed        = vaapi_redraw_needed;
+
+  this->deinterlace                    = 0;
+  this->vdr_osd_width                  = 0;
+  this->vdr_osd_height                 = 0;
+
+  this->vdr_osd_width = config->register_num( config, "video.output.vaapi_vdr_osd_width", 0,
+        _("vaapi: VDR osd width workaround."),
+        _("vaapi: VDR osd width workaround."),
+        10, vaapi_vdr_osd_width_flag, this );
+
+  this->vdr_osd_height = config->register_num( config, "video.output.vaapi_vdr_osd_height", 0,
+        _("vaapi: VDR osd height workaround."),
+        _("vaapi: VDR osd height workaround."),
+        10, vaapi_vdr_osd_height_flag, this );
+
+  this->deinterlace = config->register_num( config, "video.output.vaapi_deinterlace", 0,
+        _("vaapi: set deinterlace to 0 ( none ), 1 ( top field ), 2 ( bob )."),
+        _("vaapi: set deinterlace to 0 ( none ), 1 ( top field ), 2 ( bob )."),
+        10, vaapi_deinterlace_flag, this );
+
+  this->guarded_render = config->register_num( config, "video.output.vaapi_guarded_render", 1,
+        _("vaapi: set vaapi_guarded_render to 0 ( no ) 1 ( yes )"),
+        _("vaapi: set vaapi_guarded_render to 0 ( no ) 1 ( yes )"),
+        10, vaapi_guarded_render, this );
+
+  this->scaling_level_enum = config->register_enum(config, "video.output.vaapi_scaling_level", 0,
+    (char **)scaling_level_enum_names,
+        _("vaapi: set scaling level to : default (default) fast (fast) hq (HQ) nla (anamorphic)"),
+        _("vaapi: set scaling level to : default (default) fast (fast) hq (HQ) nla (anamorphic)"),
+    10, vaapi_scaling_level, this);
+
+  this->scaling_level = scaling_level_enum_values[this->scaling_level_enum];
+
+  this->swap_uv_planes = config->register_bool( config, "video.output.vaapi_swap_uv_planes", 0,
+    _("vaapi: swap UV planes."),
+    _("vaapi: this is a workaround for buggy drivers ( intel IronLake ).\n"
+      "There the UV planes are swapped.\n"),
+    10, vaapi_swap_uv_planes, this);
+
+
+  pthread_mutex_init(&this->vaapi_lock, NULL);
+
+  pthread_mutex_lock(&this->vaapi_lock);
+
+  int i;
+  for (i = 0; i < VO_NUM_PROPERTIES; i++) {
+    this->props[i].value = 0;
+    this->props[i].min   = 0;
+    this->props[i].max   = 0;
+    this->props[i].atom  = 0;
+    this->props[i].entry = NULL;
+    this->props[i].this  = this;
+  }
+
+  this->sc.user_ratio                        =
+    this->props[VO_PROP_ASPECT_RATIO].value  = XINE_VO_ASPECT_AUTO;
+  this->props[VO_PROP_ZOOM_X].value          = 100;
+  this->props[VO_PROP_ZOOM_Y].value          = 100;
+
+  this->va_context->last_sub_surface_id      = VA_INVALID_SURFACE;
+  this->va_context->last_sub_image_fmt       = 0;
+
+  if(vaapi_init_internal((vo_driver_t *)this, SW_CONTEXT_INIT_FORMAT, SW_WIDTH, SW_HEIGHT, 0) != VA_STATUS_SUCCESS) {
+    vaapi_dispose((vo_driver_t *)this);
+    return NULL;
+  }
+  vaapi_close((vo_driver_t *)this);
+  this->va_context->valid_context = 0;
+  this->va_context->driver        = (vo_driver_t *)this;
+
+  pthread_mutex_unlock(&this->vaapi_lock);
+
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_open: Deinterlace : %d\n", this->deinterlace);
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_open: Render surfaces : %d\n", RENDER_SURFACES);
+  xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_open: Opengl render : %d\n", this->opengl_render);
+
+  return &this->vo_driver;
+}
+
+/*
+ * class functions
+ */
+static void *vaapi_init_class (xine_t *xine, void *visual_gen) {
+  vaapi_class_t        *this = (vaapi_class_t *) calloc(1, sizeof(vaapi_class_t));
+
+  this->driver_class.open_plugin     = vaapi_open_plugin;
+  this->driver_class.identifier      = "vaapi";
+  this->driver_class.description     = N_("xine video output plugin using the MIT X video extension");
+  this->driver_class.dispose         = default_video_driver_class_dispose;
+  this->config                       = xine->config;
+  this->xine                         = xine;
+
+  return this;
+}
+
+static const vo_info_t vo_info_vaapi = {
+  9,                      /* priority    */
+  XINE_VISUAL_TYPE_X11    /* visual type */
+};
+
+/*
+ * exported plugin catalog entry
+ */
+
+const plugin_info_t xine_plugin_info[] EXPORTED = {
+  /* type, API, "name", version, special_info, init_function */
+  { PLUGIN_VIDEO_OUT, 22, "vaapi", XINE_VERSION_CODE, &vo_info_vaapi, vaapi_init_class },
+  { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+};
diff --git a/src/xine-engine/Makefile.am b/src/xine-engine/Makefile.am
index a0131a5..baed5b7 100644
--- a/src/xine-engine/Makefile.am
+++ b/src/xine-engine/Makefile.am
@@ -11,7 +11,7 @@ XINEUTILS_LIB = $(top_builddir)/src/xine-utils/libxineutils.la
 YUV_LIB = $(top_builddir)/src/video_out/libyuv2rgb.la
 
 # FIXME: these are currently unused:
-EXTRA_DIST = lrb.c lrb.h accel_vdpau.h accel_xvmc.h
+EXTRA_DIST = lrb.c lrb.h accel_vdpau.h accel_vaapi.h accel_xvmc.h
 
 if WIN32
 DEF_FILE = libxine-$(XINE_MAJOR).def
diff --git a/src/xine-engine/accel_vaapi.h b/src/xine-engine/accel_vaapi.h
new file mode 100644
index 0000000..666b23f
--- /dev/null
+++ b/src/xine-engine/accel_vaapi.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2008 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine 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.
+ *
+ * xine 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, USA
+ *
+ *
+ * Common acceleration definitions for vdpau
+ *
+ *
+ */
+
+#ifndef HAVE_XINE_ACCEL_VAAPI_H
+#define HAVE_XINE_ACCEL_VAAPI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <va/va_x11.h>
+#include <pthread.h>
+#ifdef HAVE_FFMPEG_AVUTIL_H
+#  include <avcodec.h>
+#else
+#  include <libavcodec/avcodec.h>
+#endif
+
+#if LIBAVCODEC_VERSION_MAJOR >= 53 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 32)
+#  define AVVIDEO 2
+#else
+#  define AVVIDEO 1
+#  define pp_context pp_context_t
+#  define pp_mode pp_mode_t
+#endif
+
+#define NUM_OUTPUT_SURFACES 22
+
+#define SURFACE_FREE            0
+#define SURFACE_ALOC            1
+#define SURFACE_RELEASE         2
+#define SURFACE_RENDER          3
+#define SURFACE_RENDER_RELEASE  5
+
+struct vaapi_equalizer {
+  VADisplayAttribute brightness;
+  VADisplayAttribute contrast;
+  VADisplayAttribute hue;
+  VADisplayAttribute saturation;
+};
+
+typedef struct ff_vaapi_context_s ff_vaapi_context_t;
+
+struct ff_vaapi_context_s {
+  VADisplay         va_display;
+  VAContextID       va_context_id;
+  VAConfigID        va_config_id;
+  int               width;
+  int               height;
+  int               sw_width;
+  int               sw_height;
+  int               va_profile;
+  unsigned int      va_colorspace;
+  VAImage           va_subpic_image;
+  VASubpictureID    va_subpic_id;
+  int               va_subpic_width;
+  int               va_subpic_height;
+  int               is_bound;
+  void              *gl_surface;
+  unsigned int      soft_head;
+  unsigned int      valid_context;
+  unsigned int      va_head;
+  unsigned int      va_soft_head;
+  vo_driver_t       *driver;
+  unsigned int      last_sub_image_fmt;
+  VASurfaceID       last_sub_surface_id;
+  struct vaapi_equalizer va_equalizer;
+  VAImageFormat     *va_image_formats;
+  int               va_num_image_formats;
+  VAImageFormat     *va_subpic_formats;
+  int               va_num_subpic_formats;
+};
+
+typedef struct ff_vaapi_surface_s ff_vaapi_surface_t;
+typedef struct vaapi_accel_s vaapi_accel_t;
+
+struct ff_vaapi_surface_s {
+  unsigned int        index;
+  vaapi_accel_t       *accel;
+  VASurfaceID         va_surface_id;
+  unsigned int        status;
+};
+
+struct vaapi_accel_s {
+  unsigned int        index;
+  vo_frame_t          *vo_frame;
+
+#if AVVIDEO > 1
+  int (*avcodec_decode_video2)(vo_frame_t *frame_gen, AVCodecContext *avctx, AVFrame *picture,
+                               int *got_picture_ptr, AVPacket *avpkt);
+#else
+  int (*avcodec_decode_video)(vo_frame_t *frame_gen, AVCodecContext *avctx, AVFrame *picture,
+                              int *got_picture_ptr, uint8_t *buf, int buf_size);
+#endif
+  VAStatus (*vaapi_init)(vo_frame_t *frame_gen, int va_profile, int width, int height, int softrender);
+  int (*profile_from_imgfmt)(vo_frame_t *frame_gen, enum PixelFormat pix_fmt, int codec_id, int vaapi_mpeg_sofdec);
+  ff_vaapi_context_t *(*get_context)(vo_frame_t *frame_gen);
+  int (*guarded_render)(vo_frame_t *frame_gen);
+  ff_vaapi_surface_t *(*get_vaapi_surface)(vo_frame_t *frame_gen);
+  void (*render_vaapi_surface)(vo_frame_t *frame_gen, ff_vaapi_surface_t *va_surface);
+  void (*release_vaapi_surface)(vo_frame_t *frame_gen, ff_vaapi_surface_t *va_surface);
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c
index cc42813..819e423 100644
--- a/src/xine-engine/video_out.c
+++ b/src/xine-engine/video_out.c
@@ -737,6 +737,13 @@ static vo_frame_t *vo_get_frame (xine_video_port_t *this_gen,
   return img;
 }
 
+static double tt()
+{
+  struct timeval tv;
+  gettimeofday(&tv, 0);
+  return tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0;
+}
+
 static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) {
 
   vos_t         *this = (vos_t *) img->port;
@@ -746,6 +753,30 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) {
   int            frames_to_skip;
   int            duration;
 
+/*
+if (1)
+{
+  double t1 = tt();
+  static double t0 = -1;
+  if (t0 == -1) t0 = t1;
+  double dt = t1 - t0;
+  t0 = t1;
+  static int64_t pts = 0;
+  fprintf(stderr, "img->pts: %12" PRId64 ", pts: %12" PRId64 ", img->duration: %4d, time since last vo_frame_draw: %7.3lf ms", img->pts, pts, img->duration, dt);
+  if (img->pts)
+  {
+      if (pts != img->pts)
+            fprintf(stderr, " ERROR: %12" PRId64 "", img->pts - pts);
+        pts = img->pts + img->duration;
+  }
+  else
+  {
+      pts += img->duration;
+  }
+  fprintf(stderr, "\n");
+}
+*/
+
   /* handle anonymous streams like NULL for easy checking */
   if (stream == XINE_ANON_STREAM) stream = NULL;
 


------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure contains a
definitive record of customers, application performance, security
threats, fraudulent activity and more. Splunk takes this data and makes
sense of it. Business sense. IT sense. Common sense.
http://p.sf.net/sfu/splunk-d2d-oct
_______________________________________________
xine-devel mailing list
xine-devel@...
https://lists.sourceforge.net/lists/listinfo/xine-devel