[vdr-plugin-softhddevice] 01/03: Imported Upstream version 0.6.0+git20130909

Tobias Grimm tiber-guest at alioth.debian.org
Mon Sep 9 19:30:21 UTC 2013


This is an automated email from the git hooks/post-receive script.

tiber-guest pushed a commit to branch master
in repository vdr-plugin-softhddevice.

commit 7c7b03f6e4ae4a29f3f10146eb753198ecf19856
Author: etobi <git at e-tobi.net>
Date:   Mon Sep 9 21:22:36 2013 +0200

    Imported Upstream version 0.6.0+git20130909
---
 .gitattributes               |    6 +
 .gitignore                   |   10 +
 .indent.pro                  |   37 ++
 ChangeLog                    |   28 ++
 Makefile                     |   24 +-
 README.txt                   |   27 +-
 Todo                         |    8 +-
 audio.c                      |   44 +-
 audio.h                      |    2 +-
 codec.c                      |   52 ++-
 codec.h                      |    4 +-
 greater_sync_2.diff          |   52 ---
 misc.h                       |    2 +-
 po/de_DE.po                  |   27 +-
 ringbuffer.c                 |    2 +-
 ringbuffer.h                 |    2 +-
 softhddev.c                  |  246 ++++++-----
 softhddev.h                  |    2 +-
 softhddevice.cpp             |   17 +-
 softhddevice.h               |    2 +-
 vdr-softhddevice             |    1 -
 vdr-softhddevice-9999.ebuild |    4 +-
 video.c                      |  938 +++++++++++++++++++++++++-----------------
 video.h                      |    6 +-
 24 files changed, 935 insertions(+), 608 deletions(-)

diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..c6a39fd
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,6 @@
+# gitattributes(5) file
+*.[15]	ident
+*.[ch]	ident
+*.cpp	ident
+*.txt	ident
+Makefile	ident
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7858ebc
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+# gitignore(5) file
+*.[oa]
+*~
+.*.swp
+.gdb_history
+# work directory
+.chaos
+# generated files
+.dependencies
+libvdr-softhddevice.so*
diff --git a/.indent.pro b/.indent.pro
new file mode 100644
index 0000000..1e2b436
--- /dev/null
+++ b/.indent.pro
@@ -0,0 +1,37 @@
+--blank-lines-before-block-comments
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--no-blank-lines-after-commas
+--braces-on-if-line
+--no-blank-before-sizeof
+--comment-indentation41
+--declaration-comment-column41
+--no-comment-delimiters-on-blank-lines
+--swallow-optional-blank-lines
+--dont-format-comments
+--parameter-indentation4
+--indent-level4
+--line-comments-indentation0
+--cuddle-else
+--cuddle-do-while
+--brace-indent0
+--case-brace-indentation0
+//--start-left-side-of-comments
+--leave-preprocessor-space
+//--continuation-indentation8
+--case-indentation4
+--else-endif-column0
+--no-space-after-casts
+--declaration-indentation1
+--dont-line-up-parentheses
+--no-space-after-function-call-names
+--space-special-semicolon
+--tab-size8
+--use-tabs
+--line-length79
+--comment-line-length79
+--honour-newlines
+--dont-break-procedure-type
+--break-before-boolean-operator
+--continuation-indentation4
+--ignore-newlines
diff --git a/ChangeLog b/ChangeLog
index ad4c4e3..990891c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,32 @@
 User johns
+Date:
+
+    Add function GetStats to the video output module.
+    Add function ResetStart to the video output module.
+    Add function SetClosing to the video output module.
+    Generalize GetVaapiContext to GetHwAccelContext.
+    Add compile time configurable trickspeed packets dump.
+    Fix bug #1410: wrong spelled AC-3 and E-AC-3.
+    Add compile time selectable h264 trickspeed workaround.
+    Use ffmpeg new names AVCodecID, AV_CODEC_... .
+    Fix bug: video lagging behind after recording stop.
+    Reduce PES error messages.
+    Fix bug #1392: Wrong value for mixing LFE.
+    Fix bug: wrong grab size, introduced with AMD VDPAU.
+    Use VDR SPU decoder as default.
+    Fix bug: grab image negative quality isn't the default 100.
+    Support AMD VDPAU with surface size != requested size.
+    Add cache for auto-crop buffer.
+    Fix opengl and opengl threads bugs.
+    Initial opengl support with va-api only.
+    Fix "broken driver" message if empty ring buffer.
+    Enable seamless audio track change.
+    Fix bug #1302: Unsupported pixel format crash.
+    Fix the fix, when sillpicture is called in suspend mode.
+    Fix crash, when sillpicture is called in suspend mode.
+    Add workaround for zero width+height and ffmpeg >= 1.2.
+
+User johns
 Date: Sun Mar 17 15:52:42 CET 2013
 
     Release Version 0.6.0
diff --git a/Makefile b/Makefile
index f76074c..03a86be 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 #
 # Makefile for a Video Disk Recorder plugin
 #
-# $Id: fa415ef17db86f247803e3e3ca8cca8b075189fa $
+# $Id$
 
 # The official name of this plugin.
 # This name will be used in the '-P...' option of VDR to load the plugin.
@@ -15,10 +15,12 @@ PLUGIN = softhddevice
 ALSA ?= $(shell pkg-config --exists alsa && echo 1)
     # support OSS audio output module
 OSS ?= 1
-    # support VDPAU video output modue
+    # support VDPAU video output module
 VDPAU ?= $(shell pkg-config --exists vdpau && echo 1)
-    # support VA-API video output modue
-VAAPI ?= $(shell pkg-config --exists libva && echo 1)
+    # support VA-API video output module (deprecated)
+#VAAPI ?= $(shell pkg-config --exists libva && echo 1)
+    # support glx output
+#OPENGL ?= $(shell pkg-config --exists gl glu && echo 1)
     # screensaver disable/enable
 SCREENSAVER ?= 1
     # use ffmpeg libswresample
@@ -33,7 +35,10 @@ CONFIG += -DUSE_PIP			# PIP support
 #CONFIG += -DNO_TS_AUDIO		# disable ts audio parser
 #CONFIG += -DUSE_TS_VIDEO		# build new ts video parser
 #CONFIG += -DUSE_MPEG_COMPLETE		# support only complete mpeg packets
-#CONFIG += -DUSE_VDR_SPU		# use VDR SPU decoder.
+#CONFIG += -DH264_EOS_TRICKSPEED	# insert seq end packets for trickspeed
+#CONDIF += -DDUMP_TRICKSPEED		# dump trickspeed packets
+CONFIG += -DUSE_VDR_SPU			# use VDR SPU decoder.
+#CONFIG += -DUSE_SOFTLIMIT		# (tobe removed) limit the buffer fill
 
 ifeq ($(ALSA),1)
 CONFIG += -DUSE_ALSA
@@ -52,6 +57,15 @@ ifeq ($(VAAPI),1)
 CONFIG += -DUSE_VAAPI
 _CFLAGS += $(shell pkg-config --cflags libva-x11 libva)
 LIBS += $(shell pkg-config --libs libva-x11 libva)
+ifeq ($(OPENGL),1)
+_CFLAGS += $(shell pkg-config --cflags libva-glx)
+LIBS += $(shell pkg-config --libs libva-glx)
+endif
+endif
+ifeq ($(OPENGL),1)
+CONFIG += -DUSE_GLX
+_CFLAGS += $(shell pkg-config --cflags gl glu)
+LIBS += $(shell pkg-config --libs gl glu)
 endif
 ifeq ($(SCREENSAVER),1)
 CONFIG += -DUSE_SCREENSAVER
diff --git a/README.txt b/README.txt
index ee2e67a..01f9607 100644
--- a/README.txt
+++ b/README.txt
@@ -16,18 +16,18 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.
 
-$Id: 026a82b979adeb7d75c829eb8bc05f4594c940e2 $
+$Id$
 
 A software and GPU emulated HD output device plugin for VDR.
 
-    o Video decoder CPU / VA-API / VDPAU
-    o Video output VA-API / VDPAU
+    o Video decoder CPU / VDPAU
+    o Video output VDPAU
     o Audio FFMpeg / Alsa / Analog
     o Audio FFMpeg / Alsa / Digital
     o Audio FFMpeg / OSS / Analog
     o HDMI/SPDIF pass-through
     o Software volume, compression, normalize and channel resample
-    o YaepgHD support / new >1.7.33 VDR ScaleVideo API support
+    o VDR ScaleVideo API
     o Software deinterlacer Bob (VA-API only)
     o Autocrop
     o Grab image (VDPAU only)
@@ -36,10 +36,11 @@ A software and GPU emulated HD output device plugin for VDR.
     o atmo light support with plugin http://github.com/durchflieger/DFAtmo
     o PIP (Picture-in-Picture) (VDPAU only)
 
-    o planned: Video decoder VA-API Branch: vaapi-ext/staging
-    o planned: Video output XvBA / Opengl / Xv
-    o planned: VA-API grab image
-    o planned: Improved Software Deinterlacer (yadif or/and ffmpeg filters)
+    o planned: Remove VA-API decoder and output support
+    o planned: Video decoder OpenMax
+    o planned: Video output Opengl / Xv
+    o planned: Improved software deinterlacer (yadif or/and ffmpeg filters)
+    o XvBa support is no longer planned (use future Radeon UVD VDPAU)
 
 To compile you must have the 'requires' installed.
 
@@ -83,14 +84,12 @@ Setup:	environment
 		if set don't use the hardware decoders
 	NO_MPEG_HW=1
 		if set don't use the hardware decoder for mpeg1/2
-	STUDIO_LEVELS=1
-		if set use studio levels with vdpau (deprecated use setup)
 
     only if alsa is configured
 	ALSA_DEVICE=default
 		alsa PCM device name
 	ALSA_PASSTHROUGH_DEVICE=
-		alsa pass-though (AC3,EAC3,DTS,...) device name
+		alsa pass-though (AC-3,E-AC-3,DTS,...) device name
 	ALSA_MIXER=default
 		alsa control device name
 	ALSA_MIXER_CHANNEL=PCM
@@ -100,7 +99,7 @@ Setup:	environment
 	OSS_AUDIODEV=/dev/dsp
 		oss dsp device name
 	OSS_PASSTHROUGHDEV=
-		oss pass-though (AC3,EAC3,DTS,...) device name
+		oss pass-though (AC-3,E-AC-3,DTS,...) device name
 	OSS_MIXERDEV=/dev/mixer
 		oss mixer device name
 	OSS_MIXER_CHANNEL=pcm
@@ -130,7 +129,7 @@ Setup: /etc/vdr/setup.conf
 
 	softhddevice.<res>.Deinterlace = 0
 	0 = bob, 1 = weave, 2 = temporal, 3 = temporal_spatial, 4 = software
-	(only 0, 1 supported with vaapi)
+	(only 0, 1, 4 supported with VA-API)
 
 	softhddevice.<res>.SkipChromaDeinterlace = 0
 	0 = disabled, 1 = enabled (for slower cards, poor qualit�t)
@@ -361,7 +360,7 @@ Requires:
     or
 	kernel support for oss/oss4 or alsa oss emulation
 
-	x11-libs/libva
+	x11-libs/libva (deprecated)
 		Video Acceleration (VA) API for Linux
 		http://www.freedesktop.org/wiki/Software/vaapi
 	x11-libs/libva-intel-driver
diff --git a/Todo b/Todo
index cc36bcc..863de11 100644
--- a/Todo
+++ b/Todo
@@ -1,6 +1,6 @@
 @file Todo		@brief A software HD output device for VDR
 
-Copyright (c) 2011, 2012 by Johns.  All Rights Reserved.
+Copyright (c) 2011 - 2013 by Johns.  All Rights Reserved.
 
 Contributor(s):
 
@@ -19,6 +19,9 @@ GNU Affero General Public License for more details.
 $Id: $
 
 missing:
+    documentation of the PIP hotkeys.
+    svdrp help page missing PIP hotkeys.
+    svdrp stat: add X11 crashed status.
     more software deinterlace (yadif, ...)
     more software decoder with software deinterlace
     suspend output / energie saver: stop and restart X11
@@ -40,11 +43,14 @@ video:
     check start with 24Hz display rate
     crash with ffmpeg without vaapi and vdpau.
     still-picture of PES recordings should use VideoMpegEnqueue.
+    convert PIX_FMT_... PixelFormat to new names AV_PIX_FMT_..., AVPixelFormat.
+    atmo service support 3D grab
 
 vdpau:
     software deinterlace path not working.
     OSD looses transparency, during channel switch.
     OSD looses transparency, while moving cut marks.
+    ffmpeg >=1.2 supports same API like VA-API.
 
 libva:
     yaepghd (VaapiSetOutputPosition) support
diff --git a/audio.c b/audio.c
index 3a1193f..6ad2907 100644
--- a/audio.c
+++ b/audio.c
@@ -17,7 +17,7 @@
 ///	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ///	GNU Affero General Public License for more details.
 ///
-///	$Id: 644c18a88c0714fe51c774b09118cc609d55bcd3 $
+///	$Id$
 //////////////////////////////////////////////////////////////////////////////
 
 ///
@@ -486,7 +486,7 @@ static void AudioSurround2Stereo(const int16_t * in, int in_chan, int frames,
 		r += in[3] * 200;	// Rs
 		l += in[4] * 300;	// C
 		r += in[4] * 300;
-		l += in[5] * 300;	// LFE
+		l += in[5] * 100;	// LFE
 		r += in[5] * 100;
 		break;
 	    case 7:			// 7.0
@@ -620,7 +620,7 @@ static void AudioResample(const int16_t * in, int in_chan, int frames,
 typedef struct _audio_ring_ring_
 {
     char FlushBuffers;			///< flag: flush buffers
-    char Passthrough;			///< flag: use pass-through (AC3, ...)
+    char Passthrough;			///< flag: use pass-through (AC-3, ...)
     int16_t PacketSize;			///< packet size
     unsigned HwSampleRate;		///< hardware sample rate in Hz
     unsigned HwChannels;		///< hardware number of channels
@@ -642,7 +642,7 @@ static unsigned AudioStartThreshold;	///< start play, if filled
 **
 **	@param sample_rate	sample-rate frequency
 **	@param channels		number of channels
-**	@param passthrough	use /pass-through (AC3, ...) device
+**	@param passthrough	use /pass-through (AC-3, ...) device
 **
 **	@retval -1	error
 **	@retval 0	okay
@@ -678,8 +678,7 @@ static int AudioRingAdd(unsigned sample_rate, int channels, int passthrough)
     }
     AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
 
-    // FIXME: don't flush buffers here
-    AudioRing[AudioRingWrite].FlushBuffers = 1;
+    AudioRing[AudioRingWrite].FlushBuffers = 0;
     AudioRing[AudioRingWrite].Passthrough = passthrough;
     AudioRing[AudioRingWrite].PacketSize = 0;
     AudioRing[AudioRingWrite].InSampleRate = sample_rate;
@@ -689,6 +688,9 @@ static int AudioRingAdd(unsigned sample_rate, int channels, int passthrough)
     AudioRing[AudioRingWrite].PTS = INT64_C(0x8000000000000000);
     RingBufferReset(AudioRing[AudioRingWrite].RingBuffer);
 
+    Debug(3, "audio: %d ring buffer prepared\n",
+	atomic_read(&AudioRingFilled) + 1);
+
     atomic_inc(&AudioRingFilled);
 
 #ifdef USE_AUDIO_THREAD
@@ -836,7 +838,7 @@ static int AlsaPlayRingbuffer(void)
 	if (!avail) {			// full or buffer empty
 	    break;
 	}
-	// muting pass-through ac3, can produce disturbance
+	// muting pass-through AC-3, can produce disturbance
 	if (AudioMute || (AudioSoftVolume
 		&& !AudioRing[AudioRingRead].Passthrough)) {
 	    // FIXME: quick&dirty cast
@@ -985,7 +987,7 @@ static int AlsaThread(void)
 /**
 **	Open alsa pcm device.
 **
-**	@param passthrough	use pass-through (AC3, ...) device
+**	@param passthrough	use pass-through (AC-3, ...) device
 */
 static snd_pcm_t *AlsaOpenPCM(int passthrough)
 {
@@ -1168,7 +1170,7 @@ static int64_t AlsaGetDelay(void)
 **
 **	@param freq		sample frequency
 **	@param channels		number of channels
-**	@param passthrough	use pass-through (AC3, ...) device
+**	@param passthrough	use pass-through (AC-3, ...) device
 **
 **	@retval 0	everything ok
 **	@retval 1	didn't support frequency/channels combination
@@ -1561,7 +1563,7 @@ static int OssThread(void)
 /**
 **	Open OSS pcm device.
 **
-**	@param passthrough	use pass-through (AC3, ...) device
+**	@param passthrough	use pass-through (AC-3, ...) device
 */
 static int OssOpenPCM(int passthrough)
 {
@@ -1725,7 +1727,7 @@ static int64_t OssGetDelay(void)
 **
 **	@param sample_rate	sample rate/frequency
 **	@param channels		number of channels
-**	@param passthrough	use pass-through (AC3, ...) device
+**	@param passthrough	use pass-through (AC-3, ...) device
 **
 **	@retval 0	everything ok
 **	@retval 1	didn't support frequency/channels combination
@@ -1743,7 +1745,7 @@ static int OssSetup(int *sample_rate, int *channels, int passthrough)
 	return -1;
     }
 
-    if (1) {				// close+open for pcm / ac3
+    if (1) {				// close+open for pcm / AC-3
 	int fildes;
 
 	fildes = OssPcmFildes;
@@ -1932,7 +1934,7 @@ static void NoopSetVolume( __attribute__ ((unused))
 **
 **	@param freq		sample frequency
 **	@param channels		number of channels
-**	@param passthrough	use pass-through (AC3, ...) device
+**	@param passthrough	use pass-through (AC-3, ...) device
 */
 static int NoopSetup( __attribute__ ((unused))
     int *channels, __attribute__ ((unused))
@@ -2031,10 +2033,10 @@ static void *AudioPlayHandlerThread(void *dummy)
 	pthread_mutex_unlock(&AudioMutex);
 
 	Debug(3, "audio: ----> %dms start\n", (AudioUsedBytes() * 1000)
-	    / (!AudioRing[AudioRingRead].HwSampleRate +
-		!AudioRing[AudioRingRead].HwChannels +
-		AudioRing[AudioRingRead].HwSampleRate *
-		AudioRing[AudioRingRead].HwChannels * AudioBytesProSample));
+	    / (!AudioRing[AudioRingWrite].HwSampleRate +
+		!AudioRing[AudioRingWrite].HwChannels +
+		AudioRing[AudioRingWrite].HwSampleRate *
+		AudioRing[AudioRingWrite].HwChannels * AudioBytesProSample));
 
 	do {
 	    int filled;
@@ -2067,7 +2069,10 @@ static void *AudioPlayHandlerThread(void *dummy)
 		Debug(3, "audio: continue after flush\n");
 	    }
 	    // try to play some samples
-	    err = AudioUsedModule->Thread();
+	    err = 0;
+	    if (RingBufferUsedBytes(AudioRing[AudioRingRead].RingBuffer)) {
+		err = AudioUsedModule->Thread();
+	    }
 	    // underrun, check if new ring buffer is available
 	    if (!err) {
 		int passthrough;
@@ -2417,6 +2422,7 @@ void AudioFlushBuffers(void)
     int i;
 
     old = AudioRingWrite;
+    // FIXME: check ring buffer overflow
     AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
     AudioRing[AudioRingWrite].FlushBuffers = 1;
     AudioRing[AudioRingWrite].Passthrough = AudioRing[old].Passthrough;
@@ -2570,7 +2576,7 @@ void AudioSetVolume(int volume)
 **
 **	@param freq		sample frequency
 **	@param channels		number of channels
-**	@param passthrough	use pass-through (AC3, ...) device
+**	@param passthrough	use pass-through (AC-3, ...) device
 **
 **	@retval 0	everything ok
 **	@retval 1	didn't support frequency/channels combination
diff --git a/audio.h b/audio.h
index 848567b..4a0ac51 100644
--- a/audio.h
+++ b/audio.h
@@ -17,7 +17,7 @@
 ///	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ///	GNU Affero General Public License for more details.
 ///
-///	$Id: 2393b6f10303c30c8a3a4d689454081e418008fe $
+///	$Id$
 //////////////////////////////////////////////////////////////////////////////
 
 /// @addtogroup Audio
diff --git a/codec.c b/codec.c
index 441b098..4eea14f 100644
--- a/codec.c
+++ b/codec.c
@@ -17,7 +17,7 @@
 ///	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ///	GNU Affero General Public License for more details.
 ///
-///	$Id: 6e1e942276363ae930aa18f81194e13cbc448d1f $
+///	$Id$
 //////////////////////////////////////////////////////////////////////////////
 
 ///
@@ -56,6 +56,13 @@
 
 #include <alsa/iatomic.h>
 #include <libavcodec/avcodec.h>
+// support old ffmpeg versions <1.0
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,18,102)
+#define AVCodecID CodecID
+#define AV_CODEC_ID_AC3 CODEC_ID_AC3
+#define AV_CODEC_ID_EAC3 CODEC_ID_EAC3
+#define AV_CODEC_ID_H264 CODEC_ID_H264
+#endif
 #include <libavcodec/vaapi.h>
 #ifdef USE_VDPAU
 #include <libavcodec/vdpau.h>
@@ -434,7 +441,7 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
     decoder->VideoCtx->opaque = decoder;	// our structure
 
     Debug(3, "codec: video '%s'\n", decoder->VideoCtx->codec_name);
-    if (codec_id == CODEC_ID_H264) {
+    if (codec_id == AV_CODEC_ID_H264) {
 	// 2.53 Ghz CPU is too slow for this codec at 1080i
 	//decoder->VideoCtx->skip_loop_filter = AVDISCARD_ALL;
 	//decoder->VideoCtx->skip_loop_filter = AVDISCARD_BIDIR;
@@ -476,7 +483,7 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
     } else {
 	decoder->VideoCtx->get_format = Codec_get_format;
 	decoder->VideoCtx->hwaccel_context =
-	    VideoGetVaapiContext(decoder->HwDecoder);
+	    VideoGetHwAccelContext(decoder->HwDecoder);
     }
 
     // our pixel format video hardware decoder hook
@@ -515,8 +522,8 @@ void CodecVideoClose(VideoDecoder * video_decoder)
     if (video_decoder->VideoCtx) {
 	pthread_mutex_lock(&CodecLockMutex);
 	avcodec_close(video_decoder->VideoCtx);
-	pthread_mutex_unlock(&CodecLockMutex);
 	av_freep(&video_decoder->VideoCtx);
+	pthread_mutex_unlock(&CodecLockMutex);
     }
 }
 
@@ -703,7 +710,7 @@ enum IEC61937
 
 #ifdef USE_AUDIO_DRIFT_CORRECTION
 #define CORRECT_PCM	1		///< do PCM audio-drift correction
-#define CORRECT_AC3	2		///< do AC3 audio-drift correction
+#define CORRECT_AC3	2		///< do AC-3 audio-drift correction
 static char CodecAudioDrift;		///< flag: enable audio-drift correction
 #else
 static const int CodecAudioDrift = 0;
@@ -856,15 +863,15 @@ void CodecAudioClose(AudioDecoder * audio_decoder)
     if (audio_decoder->AudioCtx) {
 	pthread_mutex_lock(&CodecLockMutex);
 	avcodec_close(audio_decoder->AudioCtx);
-	pthread_mutex_unlock(&CodecLockMutex);
 	av_freep(&audio_decoder->AudioCtx);
+	pthread_mutex_unlock(&CodecLockMutex);
     }
 }
 
 /**
 **	Set audio drift correction.
 **
-**	@param mask	enable mask (PCM, AC3)
+**	@param mask	enable mask (PCM, AC-3)
 */
 void CodecSetAudioDrift(int mask)
 {
@@ -877,7 +884,7 @@ void CodecSetAudioDrift(int mask)
 /**
 **	Set audio pass-through.
 **
-**	@param mask	enable mask (PCM, AC3, EAC3)
+**	@param mask	enable mask (PCM, AC-3, E-AC-3)
 */
 void CodecSetAudioPassthrough(int mask)
 {
@@ -978,8 +985,8 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder,
 	av_get_sample_fmt_name(audio_ctx->sample_fmt), audio_ctx->sample_rate,
 	audio_ctx->channels, CodecPassthrough & CodecPCM ? " PCM" : "",
 	CodecPassthrough & CodecMPA ? " MPA" : "",
-	CodecPassthrough & CodecAC3 ? " AC3" : "",
-	CodecPassthrough & CodecEAC3 ? " EAC3" : "",
+	CodecPassthrough & CodecAC3 ? " AC-3" : "",
+	CodecPassthrough & CodecEAC3 ? " E-AC-3" : "",
 	CodecPassthrough ? " pass-through" : "");
 
     *passthrough = 0;
@@ -990,11 +997,11 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder,
     audio_decoder->Passthrough = CodecPassthrough;
 
     // SPDIF/HDMI pass-through
-    if ((CodecPassthrough & CodecAC3 && audio_ctx->codec_id == CODEC_ID_AC3)
+    if ((CodecPassthrough & CodecAC3 && audio_ctx->codec_id == AV_CODEC_ID_AC3)
 	|| (CodecPassthrough & CodecEAC3
-	    && audio_ctx->codec_id == CODEC_ID_EAC3)) {
-	if (audio_ctx->codec_id == CODEC_ID_EAC3) {
-	    // EAC3 over HDMI some receivers need HBR
+	    && audio_ctx->codec_id == AV_CODEC_ID_EAC3)) {
+	if (audio_ctx->codec_id == AV_CODEC_ID_EAC3) {
+	    // E-AC-3 over HDMI some receivers need HBR
 	    audio_decoder->HwSampleRate *= 4;
 	}
 	audio_decoder->HwChannels = 2;
@@ -1007,9 +1014,9 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder,
 	    AudioSetup(&audio_decoder->HwSampleRate,
 		&audio_decoder->HwChannels, *passthrough))) {
 
-	// try EAC3 none HBR
+	// try E-AC-3 none HBR
 	audio_decoder->HwSampleRate /= 4;
-	if (audio_ctx->codec_id != CODEC_ID_EAC3
+	if (audio_ctx->codec_id != AV_CODEC_ID_EAC3
 	    || (err =
 		AudioSetup(&audio_decoder->HwSampleRate,
 		    &audio_decoder->HwChannels, *passthrough))) {
@@ -1044,7 +1051,7 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder,
 
     audio_ctx = audio_decoder->AudioCtx;
     // SPDIF/HDMI passthrough
-    if (CodecPassthrough & CodecAC3 && audio_ctx->codec_id == CODEC_ID_AC3) {
+    if (CodecPassthrough & CodecAC3 && audio_ctx->codec_id == AV_CODEC_ID_AC3) {
 	uint16_t *spdif;
 	int spdif_sz;
 
@@ -1094,7 +1101,8 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder,
 	AudioEnqueue(spdif, spdif_sz);
 	return 1;
     }
-    if (CodecPassthrough & CodecEAC3 && audio_ctx->codec_id == CODEC_ID_EAC3) {
+    if (CodecPassthrough & CodecEAC3
+	&& audio_ctx->codec_id == AV_CODEC_ID_EAC3) {
 	uint16_t *spdif;
 	int spdif_sz;
 	int repeat;
@@ -1223,9 +1231,9 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
 	corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
 	// SPDIF/HDMI passthrough
 	if ((CodecAudioDrift & CORRECT_AC3) && (!(CodecPassthrough & CodecAC3)
-		|| audio_decoder->AudioCtx->codec_id != CODEC_ID_AC3)
+		|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_AC3)
 	    && (!(CodecPassthrough & CodecEAC3)
-		|| audio_decoder->AudioCtx->codec_id != CODEC_ID_EAC3)) {
+		|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_EAC3)) {
 	    audio_decoder->DriftCorr = -corr;
 	}
 
@@ -1625,9 +1633,9 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
 	corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
 	// SPDIF/HDMI passthrough
 	if ((CodecAudioDrift & CORRECT_AC3) && (!(CodecPassthrough & CodecAC3)
-		|| audio_decoder->AudioCtx->codec_id != CODEC_ID_AC3)
+		|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_AC3)
 	    && (!(CodecPassthrough & CodecEAC3)
-		|| audio_decoder->AudioCtx->codec_id != CODEC_ID_EAC3)) {
+		|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_EAC3)) {
 	    audio_decoder->DriftCorr = -corr;
 	}
 
diff --git a/codec.h b/codec.h
index 7eb8abc..995573a 100644
--- a/codec.h
+++ b/codec.h
@@ -17,7 +17,7 @@
 ///	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ///	GNU Affero General Public License for more details.
 ///
-///	$Id: fbc32ec12f605e29deec2b5580f03985bc845ecd $
+///	$Id$
 //////////////////////////////////////////////////////////////////////////////
 
 /// @addtogroup Codec
@@ -30,7 +30,7 @@
 #define CodecPCM 0x01			///< PCM bit mask
 #define CodecMPA 0x02			///< MPA bit mask (planned)
 #define CodecAC3 0x04			///< AC-3 bit mask
-#define CodecEAC3 0x08			///< EAC-3 bit mask
+#define CodecEAC3 0x08			///< E-AC-3 bit mask
 #define CodecDTS 0x10			///< DTS bit mask (planned)
 
 //----------------------------------------------------------------------------
diff --git a/greater_sync_2.diff b/greater_sync_2.diff
deleted file mode 100644
index 76bdf7d..0000000
--- a/greater_sync_2.diff
+++ /dev/null
@@ -1,52 +0,0 @@
-diff --git a/video.c b/video.c
-index 981f5c8..fba9dd5 100644
---- a/video.c
-+++ b/video.c
-@@ -4600,7 +4600,7 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
- 	    goto out;
- 	}
- 	// both clocks are known
--	if (audio_clock + VideoAudioDelay <= video_clock + 15 * 90) {
-+	if (audio_clock + VideoAudioDelay <= video_clock + 35 * 90) {
- 	    goto out;
- 	}
- 	// out of sync: audio before video
-@@ -4644,12 +4644,12 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
- 	    ++decoder->FramesDuped;
- 	    decoder->SyncCounter = 1;
- 	    goto out;
--	} else if (video_clock > audio_clock + VideoAudioDelay + 45 * 90) {
-+	} else if (video_clock > audio_clock + VideoAudioDelay + 65 * 90) {
- 	    err = VaapiMessage(3, "video: slow down video, duping frame\n");
- 	    ++decoder->FramesDuped;
- 	    decoder->SyncCounter = 1;
- 	    goto out;
--	} else if (audio_clock + VideoAudioDelay > video_clock + 15 * 90
-+	} else if (audio_clock + VideoAudioDelay > video_clock + 35 * 90
- 	    && filled > 1 + 2 * decoder->Interlaced) {
- 	    err = VaapiMessage(3, "video: speed up video, droping frame\n");
- 	    ++decoder->FramesDropped;
-@@ -8009,7 +8009,7 @@ static void VdpauSyncDecoder(VdpauDecoder * decoder)
- 	    goto out;
- 	}
- 	// both clocks are known
--	if (audio_clock + VideoAudioDelay <= video_clock + 15 * 90) {
-+	if (audio_clock + VideoAudioDelay <= video_clock + 35 * 90) {
- 	    goto out;
- 	}
- 	// out of sync: audio before video
-@@ -8052,12 +8052,12 @@ static void VdpauSyncDecoder(VdpauDecoder * decoder)
- 	    ++decoder->FramesDuped;
- 	    decoder->SyncCounter = 1;
- 	    goto out;
--	} else if (video_clock > audio_clock + VideoAudioDelay + 45 * 90) {
-+	} else if (video_clock > audio_clock + VideoAudioDelay + 65 * 90) {
- 	    err = VdpauMessage(2, "video: slow down video, duping frame\n");
- 	    ++decoder->FramesDuped;
- 	    decoder->SyncCounter = 1;
- 	    goto out;
--	} else if (audio_clock + VideoAudioDelay > video_clock + 15 * 90
-+	} else if (audio_clock + VideoAudioDelay > video_clock + 35 * 90
- 	    && filled > 1 + 2 * decoder->Interlaced) {
- 	    err = VdpauMessage(2, "video: speed up video, droping frame\n");
- 	    ++decoder->FramesDropped;
diff --git a/misc.h b/misc.h
index a5f0ae7..f5ff4b3 100644
--- a/misc.h
+++ b/misc.h
@@ -18,7 +18,7 @@
 ///	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ///	GNU Affero General Public License for more details.
 ///
-///	$Id: f5ff4b300aa33eb721d658c0c9374c8499b67318 $
+///	$Id$
 //////////////////////////////////////////////////////////////////////////////
 
 /// @addtogroup misc
diff --git a/po/de_DE.po b/po/de_DE.po
index 4a630f0..91867ef 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR \n"
 "Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2013-03-09 19:20+0100\n"
+"POT-Creation-Date: 2013-08-03 17:21+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
 "Language-Team: LANGUAGE <LL at li.org>\n"
@@ -384,6 +384,10 @@ msgstr ""
 msgid "[softhddev] invalid PES video packet\n"
 msgstr ""
 
+#, c-format
+msgid "[softhddev] %d invalid PES video packet(s)\n"
+msgstr ""
+
 msgid "[softhddev] empty video packet\n"
 msgstr ""
 
@@ -587,10 +591,10 @@ msgstr ""
 msgid "  AC-3 pass-through"
 msgstr ""
 
-msgid "  EAC-3 pass-through"
+msgid "  E-AC-3 pass-through"
 msgstr ""
 
-msgid "Enable (E)AC-3 (decoder) downmix"
+msgid "Enable (E-)AC-3 (decoder) downmix"
 msgstr ""
 
 msgid "Volume control"
@@ -627,7 +631,7 @@ msgid "Pip X (%)"
 msgstr "PIP X (%)"
 
 msgid "Pip Y (%)"
-msgstr "PIP X (%)"
+msgstr "PIP Y (%)"
 
 msgid "Pip Width (%)"
 msgstr "PIP Breite (%)"
@@ -672,7 +676,7 @@ msgid "Alternative Video Height (%)"
 msgstr "Alternative Videohöhe (%)"
 
 #, c-format
-msgid "[softhddev]pip: invalid pes packet %d\n"
+msgid "[softhddev]pip: invalid PES packet %d\n"
 msgstr ""
 
 msgid "[softhddev]pip: pes buffer too small\n"
@@ -895,6 +899,9 @@ msgstr ""
 msgid "unsupported"
 msgstr ""
 
+msgid "video/glx: glx error\n"
+msgstr ""
+
 #, c-format
 msgid "video/vaapi: unsupported pixel format %d\n"
 msgstr ""
@@ -1265,6 +1272,9 @@ msgstr ""
 msgid "video/vdpau: can't put video surface bits: %s\n"
 msgstr ""
 
+msgid "video: get hwaccel context, not supported\n"
+msgstr ""
+
 #, c-format
 msgid "video/vdpau: can't render bitmap surface: %s\n"
 msgstr ""
@@ -1331,9 +1341,6 @@ msgstr ""
 msgid "video: repeated pict %d found, but not handled\n"
 msgstr ""
 
-msgid "video/vaapi: get vaapi context, without vaapi enabled\n"
-msgstr ""
-
 #, c-format
 msgid "video/vdpau: decoder rendering failed: %s\n"
 msgstr ""
@@ -1355,6 +1362,10 @@ msgstr ""
 msgid "video: Can't connect to X11 server on '%s'\n"
 msgstr ""
 
+#, c-format
+msgid "video: Can't initialize X11 thread support on '%s'\n"
+msgstr ""
+
 msgid "video: Can't convert XLIB display to XCB connection\n"
 msgstr ""
 
diff --git a/ringbuffer.c b/ringbuffer.c
index df70c22..9466852 100644
--- a/ringbuffer.c
+++ b/ringbuffer.c
@@ -17,7 +17,7 @@
 ///	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ///	GNU Affero General Public License for more details.
 ///
-///	$Id: 81722e214a141576181f44dfb2d7009f5ce58569 $
+///	$Id$
 //////////////////////////////////////////////////////////////////////////////
 
 ///
diff --git a/ringbuffer.h b/ringbuffer.h
index 80381c4..8a2b4c1 100644
--- a/ringbuffer.h
+++ b/ringbuffer.h
@@ -17,7 +17,7 @@
 ///	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ///	GNU Affero General Public License for more details.
 ///
-///	$Id: a5e8a6894d8406fdbe1c8efc891c8aa44eeb524e $
+///	$Id$
 //////////////////////////////////////////////////////////////////////////////
 
 /// @addtogroup Ringbuffer
diff --git a/softhddev.c b/softhddev.c
index f8230f2..b11e43a 100644
--- a/softhddev.c
+++ b/softhddev.c
@@ -17,11 +17,12 @@
 ///	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ///	GNU Affero General Public License for more details.
 ///
-///	$Id: b68b62bc8078d0e6f2f7c2cec5afb7f6e41a7434 $
+///	$Id$
 //////////////////////////////////////////////////////////////////////////////
 
 #define noUSE_SOFTLIMIT			///< add soft buffer limits to Play..
 #define noUSE_PIP			///< include PIP support + new API
+#define noDUMP_TRICKSPEED		///< dump raw trickspeed packets
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -40,6 +41,19 @@
 #define _N(str) str			///< gettext_noop shortcut
 
 #include <libavcodec/avcodec.h>
+// support old ffmpeg versions <1.0
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,18,102)
+#define AVCodecID CodecID
+#define AV_CODEC_ID_AAC CODEC_ID_AAC
+#define AV_CODEC_ID_AAC_LATM CODEC_ID_AAC_LATM
+#define AV_CODEC_ID_AC3 CODEC_ID_AC3
+#define AV_CODEC_ID_EAC3 CODEC_ID_EAC3
+#define AV_CODEC_ID_H264 CODEC_ID_H264
+#define AV_CODEC_ID_MP2 CODEC_ID_MP2
+#define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO
+#define AV_CODEC_ID_NONE CODEC_ID_NONE
+#define AV_CODEC_ID_PCM_DVD CODEC_ID_PCM_DVD
+#endif
 
 #ifndef __USE_GNU
 #define __USE_GNU
@@ -86,7 +100,7 @@ static volatile char StreamFreezed;	///< stream freezed
 static volatile char NewAudioStream;	///< new audio stream
 static volatile char SkipAudio;		///< skip audio stream
 static AudioDecoder *MyAudioDecoder;	///< audio decoder
-static enum CodecID AudioCodecID;	///< current codec id
+static enum AVCodecID AudioCodecID;	///< current codec id
 static int AudioChannelID;		///< current audio channel id
 static VideoStream *AudioSyncStream;	///< video stream for audio/video sync
 
@@ -296,7 +310,7 @@ static int LatmCheck(const uint8_t * data, int size)
 }
 
 ///
-///	Possible AC3 frame sizes.
+///	Possible AC-3 frame sizes.
 ///
 ///	from ATSC A/52 table 5.18 frame size code table.
 ///
@@ -314,9 +328,9 @@ const uint16_t Ac3FrameSizeTable[38][3] = {
 };
 
 ///
-///	Fast check for (E)AC3 audio.
+///	Fast check for (E-)AC-3 audio.
 ///
-///	5 bytes 0x0B77xxxxxx AC3 audio
+///	5 bytes 0x0B77xxxxxx AC-3 audio
 ///
 static inline int FastAc3Check(const uint8_t * p)
 {
@@ -330,7 +344,7 @@ static inline int FastAc3Check(const uint8_t * p)
 }
 
 ///
-///	Check for (E)AC-3 audio.
+///	Check for (E-)AC-3 audio.
 ///
 ///	0x0B77xxxxxx already checked.
 ///
@@ -341,7 +355,7 @@ static inline int FastAc3Check(const uint8_t * p)
 ///	@retval 0	no valid AC-3 audio
 ///	@retval >0	valid AC-3 audio
 ///
-///	o AC3 Header
+///	o AC-3 Header
 ///	AAAAAAAA AAAAAAAA BBBBBBBB BBBBBBBB CCDDDDDD EEEEEFFF
 ///
 ///	o a 16x Frame sync, always 0x0B77
@@ -351,7 +365,7 @@ static inline int FastAc3Check(const uint8_t * p)
 ///	o e 5x	Bitstream ID
 ///	o f 3x	Bitstream mode
 ///
-///	o EAC3 Header
+///	o E-AC-3 Header
 ///	AAAAAAAA AAAAAAAA BBCCCDDD DDDDDDDD EEFFGGGH IIIII...
 ///
 ///	o a 16x Frame sync, always 0x0B77
@@ -365,17 +379,17 @@ static int Ac3Check(const uint8_t * data, int size)
 {
     int frame_size;
 
-    if (size < 5) {			// need 5 bytes to see if AC3/EAC3
+    if (size < 5) {			// need 5 bytes to see if AC-3/E-AC-3
 	return -5;
     }
 
-    if (data[5] > (10 << 3)) {		// EAC3
+    if (data[5] > (10 << 3)) {		// E-AC-3
 	if ((data[4] & 0xF0) == 0xF0) {	// invalid fscod fscod2
 	    return 0;
 	}
 	frame_size = ((data[2] & 0x03) << 8) + data[3] + 1;
 	frame_size *= 2;
-    } else {				// AC3
+    } else {				// AC-3
 	int fscod;
 	int frmsizcod;
 
@@ -617,7 +631,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
 #if 0
 		// Played with PlayAudio
 		// FIXME: need 0x80 -- 0xA0 state
-		if (AudioCodecID == CODEC_ID_NONE) {
+		if (AudioCodecID == AV_CODEC_ID_NONE) {
 		    if ((*p & 0xF0) == 0x80) {	// AC-3 & DTS
 			Debug(3, "pesdemux: dvd ac-3\n");
 		    } else if ((*p & 0xFF) == 0xA0) {	// LPCM
@@ -651,8 +665,8 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
 		    unsigned codec_id;
 
 		    // 4 bytes 0xFFExxxxx Mpeg audio
-		    // 5 bytes 0x0B77xxxxxx AC3 audio
-		    // 6 bytes 0x0B77xxxxxxxx EAC3 audio
+		    // 5 bytes 0x0B77xxxxxx AC-3 audio
+		    // 6 bytes 0x0B77xxxxxxxx E-AC-3 audio
 		    // 3 bytes 0x56Exxx AAC LATM audio
 		    // 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio
 		    // PCM audio can't be found
@@ -660,22 +674,22 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
 		    r = 0;
 		    if (!r && FastMpegCheck(q)) {
 			r = MpegCheck(q, n);
-			codec_id = CODEC_ID_MP2;
+			codec_id = AV_CODEC_ID_MP2;
 		    }
 		    if (!r && FastAc3Check(q)) {
 			r = Ac3Check(q, n);
-			codec_id = CODEC_ID_AC3;
+			codec_id = AV_CODEC_ID_AC3;
 			if (r > 0 && q[5] > (10 << 3)) {
-			    codec_id = CODEC_ID_EAC3;
+			    codec_id = AV_CODEC_ID_EAC3;
 			}
 		    }
 		    if (!r && FastLatmCheck(q)) {
 			r = LatmCheck(q, n);
-			codec_id = CODEC_ID_AAC_LATM;
+			codec_id = AV_CODEC_ID_AAC_LATM;
 		    }
 		    if (!r && FastAdtsCheck(q)) {
 			r = AdtsCheck(q, n);
-			codec_id = CODEC_ID_AAC;
+			codec_id = AV_CODEC_ID_AAC;
 		    }
 		    if (r < 0) {	// need more bytes
 			break;
@@ -705,7 +719,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
 			//pesdx->State = PES_MPEG_DECODE;
 			break;
 		    }
-		    if (AudioCodecID != CODEC_ID_NONE) {
+		    if (AudioCodecID != AV_CODEC_ID_NONE) {
 			// shouldn't happen after we have a vaild codec
 			// detected
 			Debug(4, "pesdemux: skip @%d %02x\n", pesdx->Skip,
@@ -831,7 +845,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
 		    int bits_per_sample;
 		    const uint8_t *q;
 
-		    if (AudioCodecID != CODEC_ID_PCM_DVD) {
+		    if (AudioCodecID != AV_CODEC_ID_PCM_DVD) {
 
 			q = pesdx->Header;
 			Debug(3, "pesdemux: LPCM %d sr:%d bits:%d chan:%d\n",
@@ -861,8 +875,8 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
 				(q[5] & 0x7) + 1);
 			    // FIXME: support resample
 			}
-			//CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_PCM_DVD);
-			AudioCodecID = CODEC_ID_PCM_DVD;
+			//CodecAudioOpen(MyAudioDecoder, NULL, AV_CODEC_ID_PCM_DVD);
+			AudioCodecID = AV_CODEC_ID_PCM_DVD;
 		    }
 		    pesdx->State = PES_LPCM_PAYLOAD;
 		    pesdx->Index = 0;
@@ -1023,7 +1037,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
 	CodecAudioClose(MyAudioDecoder);
 	AudioFlushBuffers();
 	AudioSetBufferTime(ConfigAudioBufferTime);
-	AudioCodecID = CODEC_ID_NONE;
+	AudioCodecID = AV_CODEC_ID_NONE;
 	AudioChannelID = -1;
 	NewAudioStream = 0;
     }
@@ -1081,7 +1095,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
 
     if (AudioChannelID != id) {		// id changed audio track changed
 	AudioChannelID = id;
-	AudioCodecID = CODEC_ID_NONE;
+	AudioCodecID = AV_CODEC_ID_NONE;
     }
     // Private stream + LPCM ID
     if ((id & 0xF0) == 0xA0) {
@@ -1089,7 +1103,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
 	    Error(_("[softhddev] invalid LPCM audio packet %d bytes\n"), size);
 	    return size;
 	}
-	if (AudioCodecID != CODEC_ID_PCM_DVD) {
+	if (AudioCodecID != AV_CODEC_ID_PCM_DVD) {
 	    static int samplerates[] = { 48000, 96000, 44100, 32000 };
 	    int samplerate;
 	    int channels;
@@ -1123,8 +1137,8 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
 		    (p[5] & 0x7) + 1);
 		// FIXME: support resample
 	    }
-	    //CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_PCM_DVD);
-	    AudioCodecID = CODEC_ID_PCM_DVD;
+	    //CodecAudioOpen(MyAudioDecoder, NULL, AV_CODEC_ID_PCM_DVD);
+	    AudioCodecID = AV_CODEC_ID_PCM_DVD;
 	}
 
 	if (AudioAvPkt->pts != (int64_t) AV_NOPTS_VALUE) {
@@ -1140,7 +1154,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
     if ((id & 0xF0) == 0x80 && (p[0] & 0xF0) == 0x80) {
 	p += 4;
 	n -= 4;				// skip track header
-	if (AudioCodecID == CODEC_ID_NONE) {
+	if (AudioCodecID == AV_CODEC_ID_NONE) {
 	    // FIXME: ConfigAudioBufferTime + x
 	    AudioSetBufferTime(400);
 	}
@@ -1157,25 +1171,25 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
 
 	// 4 bytes 0xFFExxxxx Mpeg audio
 	// 3 bytes 0x56Exxx AAC LATM audio
-	// 5 bytes 0x0B77xxxxxx AC3 audio
-	// 6 bytes 0x0B77xxxxxxxx EAC3 audio
+	// 5 bytes 0x0B77xxxxxx AC-3 audio
+	// 6 bytes 0x0B77xxxxxxxx E-AC-3 audio
 	// 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio
 	// PCM audio can't be found
 	r = 0;
-	codec_id = CODEC_ID_NONE;	// keep compiler happy
+	codec_id = AV_CODEC_ID_NONE;	// keep compiler happy
 	if (id != 0xbd && FastMpegCheck(p)) {
 	    r = MpegCheck(p, n);
-	    codec_id = CODEC_ID_MP2;
+	    codec_id = AV_CODEC_ID_MP2;
 	}
 	if (id != 0xbd && !r && FastLatmCheck(p)) {
 	    r = LatmCheck(p, n);
-	    codec_id = CODEC_ID_AAC_LATM;
+	    codec_id = AV_CODEC_ID_AAC_LATM;
 	}
 	if ((id == 0xbd || (id & 0xF0) == 0x80) && !r && FastAc3Check(p)) {
 	    r = Ac3Check(p, n);
-	    codec_id = CODEC_ID_AC3;
+	    codec_id = AV_CODEC_ID_AC3;
 	    if (r > 0 && p[5] > (10 << 3)) {
-		codec_id = CODEC_ID_EAC3;
+		codec_id = AV_CODEC_ID_EAC3;
 	    }
 	    /* faster ac3 detection at end of pes packet (no improvemnts)
 	       if (AudioCodecID == codec_id && -r - 2 == n) {
@@ -1185,7 +1199,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
 	}
 	if (id != 0xbd && !r && FastAdtsCheck(p)) {
 	    r = AdtsCheck(p, n);
-	    codec_id = CODEC_ID_AAC;
+	    codec_id = AV_CODEC_ID_AAC;
 	}
 	if (r < 0) {			// need more bytes
 	    break;
@@ -1253,7 +1267,7 @@ int PlayTsAudio(const uint8_t * data, int size)
 	AudioFlushBuffers();
 	// max time between audio packets 200ms + 24ms hw buffer
 	AudioSetBufferTime(ConfigAudioBufferTime);
-	AudioCodecID = CODEC_ID_NONE;
+	AudioCodecID = AV_CODEC_ID_NONE;
 	AudioChannelID = -1;
 	NewAudioStream = 0;
 	PesReset(PesDemuxAudio);
@@ -1303,8 +1317,8 @@ struct __video_stream__
     VideoDecoder *Decoder;		///< video decoder
     pthread_mutex_t DecoderLockMutex;	///< video decoder lock mutex
 
-    enum CodecID CodecID;		///< current codec id
-    enum CodecID LastCodecID;		///< last codec id
+    enum AVCodecID CodecID;		///< current codec id
+    enum AVCodecID LastCodecID;		///< last codec id
 
     volatile char NewStream;		///< flag new video stream
     volatile char ClosingStream;	///< flag closing video stream
@@ -1316,6 +1330,9 @@ struct __video_stream__
     volatile char ClearBuffers;		///< command clear video buffers
     volatile char ClearClose;		///< clear video buffers for close
 
+    int InvalidPesCounter;		///< counter of invalid PES packets
+
+    enum AVCodecID CodecIDRb[VIDEO_PACKET_MAX];	///< codec ids in ring buffer
     AVPacket PacketRb[VIDEO_PACKET_MAX];	///< PES packet ring buffer
     int StartCodeState;			///< last three bytes start code state
 
@@ -1442,9 +1459,9 @@ static void VideoResetPacket(VideoStream * stream)
 
     stream->StartCodeState = 0;		// reset start code state
 
+    stream->CodecIDRb[stream->PacketWrite] = AV_CODEC_ID_NONE;
     avpkt = &stream->PacketRb[stream->PacketWrite];
     avpkt->stream_index = 0;
-    avpkt->priv = NULL;
     avpkt->pts = AV_NOPTS_VALUE;
     avpkt->dts = AV_NOPTS_VALUE;
 }
@@ -1461,7 +1478,7 @@ static void VideoNextPacket(VideoStream * stream, int codec_id)
 
     avpkt = &stream->PacketRb[stream->PacketWrite];
     if (!avpkt->stream_index) {		// ignore empty packets
-	if (codec_id != CODEC_ID_NONE) {
+	if (codec_id != AV_CODEC_ID_NONE) {
 	    return;
 	}
 	Debug(3, "video: possible stream change loss\n");
@@ -1471,7 +1488,7 @@ static void VideoNextPacket(VideoStream * stream, int codec_id)
 	// no free slot available drop last packet
 	Error(_("video: no empty slot in packet ringbuffer\n"));
 	avpkt->stream_index = 0;
-	if (codec_id == CODEC_ID_NONE) {
+	if (codec_id == AV_CODEC_ID_NONE) {
 	    Debug(3, "video: possible stream change loss\n");
 	}
 	return;
@@ -1479,7 +1496,7 @@ static void VideoNextPacket(VideoStream * stream, int codec_id)
     // clear area for decoder, always enough space allocated
     memset(avpkt->data + avpkt->stream_index, 0, FF_INPUT_BUFFER_PADDING_SIZE);
 
-    avpkt->priv = (void *)(size_t) codec_id;
+    stream->CodecIDRb[stream->PacketWrite] = codec_id;
     //DumpH264(avpkt->data, avpkt->stream_index);
 
     // advance packet write
@@ -1539,7 +1556,7 @@ static void VideoMpegEnqueue(VideoStream * stream, int64_t pts,
 		fprintf(stderr, "last: %d start\n", stream->StartCodeState);
 #endif
 		stream->PacketRb[stream->PacketWrite].stream_index -= 3;
-		VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
+		VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
 		VideoEnqueue(stream, pts, startcode, 3);
 		first = p[0] == 0xb3;
 		p++;
@@ -1556,7 +1573,7 @@ static void VideoMpegEnqueue(VideoStream * stream, int64_t pts,
 		fprintf(stderr, "last: %d start\n", stream->StartCodeState);
 #endif
 		stream->PacketRb[stream->PacketWrite].stream_index -= 2;
-		VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
+		VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
 		VideoEnqueue(stream, pts, startcode, 2);
 		first = p[1] == 0xb3;
 		p += 2;
@@ -1573,7 +1590,7 @@ static void VideoMpegEnqueue(VideoStream * stream, int64_t pts,
 		fprintf(stderr, "last: %d start\n", stream->StartCodeState);
 #endif
 		stream->PacketRb[stream->PacketWrite].stream_index -= 1;
-		VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
+		VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
 		VideoEnqueue(stream, pts, startcode, 1);
 		first = p[2] == 0xb3;
 		p += 3;
@@ -1606,7 +1623,7 @@ static void VideoMpegEnqueue(VideoStream * stream, int64_t pts,
 	     */
 	    // first packet goes only upto picture header
 	    VideoEnqueue(stream, pts, data, p - data);
-	    VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
+	    VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
 #ifdef DEBUG
 	    fprintf(stderr, "fix\r");
 #endif
@@ -1756,6 +1773,7 @@ static void VideoStreamClose(VideoStream * stream)
     VideoPacketExit(stream);
 
     stream->NewStream = 1;
+    stream->InvalidPesCounter = 0;
 }
 
 /**
@@ -1853,9 +1871,8 @@ int VideoDecodeInput(VideoStream * stream)
 
 	// flush buffers, if close is in the queue
 	for (f = 0; f < filled; ++f) {
-	    avpkt =
-		&stream->PacketRb[(stream->PacketRead + f) % VIDEO_PACKET_MAX];
-	    if ((int)(size_t) avpkt->priv == CODEC_ID_NONE) {
+	    if (stream->CodecIDRb[(stream->PacketRead + f) % VIDEO_PACKET_MAX]
+		== AV_CODEC_ID_NONE) {
 		if (f) {
 		    Debug(3, "video: cleared upto close\n");
 		    atomic_sub(f, &stream->PacketsFilled);
@@ -1874,30 +1891,30 @@ int VideoDecodeInput(VideoStream * stream)
     //	handle queued commands
     //
     avpkt = &stream->PacketRb[stream->PacketRead];
-    switch ((int)(size_t) avpkt->priv) {
-	case CODEC_ID_NONE:
+    switch (stream->CodecIDRb[stream->PacketRead]) {
+	case AV_CODEC_ID_NONE:
 	    stream->ClosingStream = 0;
-	    if (stream->LastCodecID != CODEC_ID_NONE) {
-		stream->LastCodecID = CODEC_ID_NONE;
+	    if (stream->LastCodecID != AV_CODEC_ID_NONE) {
+		stream->LastCodecID = AV_CODEC_ID_NONE;
 		CodecVideoClose(stream->Decoder);
 		goto skip;
 	    }
 	    // FIXME: look if more close are in the queue
 	    // size can be zero
 	    goto skip;
-	case CODEC_ID_MPEG2VIDEO:
-	    if (stream->LastCodecID != CODEC_ID_MPEG2VIDEO) {
-		stream->LastCodecID = CODEC_ID_MPEG2VIDEO;
+	case AV_CODEC_ID_MPEG2VIDEO:
+	    if (stream->LastCodecID != AV_CODEC_ID_MPEG2VIDEO) {
+		stream->LastCodecID = AV_CODEC_ID_MPEG2VIDEO;
 		CodecVideoOpen(stream->Decoder, VideoHardwareDecoder < 0
 		    && VdpauDecoder ? "mpegvideo_vdpau" : NULL,
-		    CODEC_ID_MPEG2VIDEO);
+		    AV_CODEC_ID_MPEG2VIDEO);
 	    }
 	    break;
-	case CODEC_ID_H264:
-	    if (stream->LastCodecID != CODEC_ID_H264) {
-		stream->LastCodecID = CODEC_ID_H264;
+	case AV_CODEC_ID_H264:
+	    if (stream->LastCodecID != AV_CODEC_ID_H264) {
+		stream->LastCodecID = AV_CODEC_ID_H264;
 		CodecVideoOpen(stream->Decoder, VideoHardwareDecoder
-		    && VdpauDecoder ? "h264_vdpau" : NULL, CODEC_ID_H264);
+		    && VdpauDecoder ? "h264_vdpau" : NULL, AV_CODEC_ID_H264);
 	    }
 	    break;
 	default:
@@ -1926,7 +1943,7 @@ int VideoDecodeInput(VideoStream * stream)
     //fprintf(stderr, "]\n");
 #else
     // old version
-    if (stream->LastCodecID == CODEC_ID_MPEG2VIDEO) {
+    if (stream->LastCodecID == AV_CODEC_ID_MPEG2VIDEO) {
 	FixPacketForFFMpeg(stream->Decoder, avpkt);
     } else {
 	CodecVideoDecode(stream->Decoder, avpkt);
@@ -1972,8 +1989,8 @@ static void StartVideo(void)
     VideoOsdInit();
     if (!MyVideoStream->Decoder) {
 	MyVideoStream->SkipStream = 1;
-	MyVideoStream->CodecID = CODEC_ID_NONE;
-	MyVideoStream->LastCodecID = CODEC_ID_NONE;
+	MyVideoStream->CodecID = AV_CODEC_ID_NONE;
+	MyVideoStream->LastCodecID = AV_CODEC_ID_NONE;
 
 	if ((MyVideoStream->HwDecoder = VideoNewHwDecoder(MyVideoStream))) {
 	    MyVideoStream->Decoder =
@@ -2012,6 +2029,7 @@ static void StopVideo(void)
     VideoPacketExit(MyVideoStream);
 
     MyVideoStream->NewStream = 1;
+    MyVideoStream->InvalidPesCounter = 0;
 }
 
 #ifdef DEBUG
@@ -2133,17 +2151,26 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
 	    Debug(3, "video: new video stream lost\n");
 	    return 0;
 	}
-	VideoNextPacket(stream, CODEC_ID_NONE);
-	stream->CodecID = CODEC_ID_NONE;
+	VideoNextPacket(stream, AV_CODEC_ID_NONE);
+	stream->CodecID = AV_CODEC_ID_NONE;
 	stream->ClosingStream = 1;
 	stream->NewStream = 0;
     }
     // must be a PES start code
     // FIXME: Valgrind-3.8.1 has a problem with this code
     if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
-	Error(_("[softhddev] invalid PES video packet\n"));
+	if (!stream->InvalidPesCounter++) {
+	    Error(_("[softhddev] invalid PES video packet\n"));
+	}
 	return size;
     }
+    if (stream->InvalidPesCounter) {
+	if (stream->InvalidPesCounter > 1) {
+	    Error(_("[softhddev] %d invalid PES video packet(s)\n"),
+		stream->InvalidPesCounter);
+	}
+	stream->InvalidPesCounter = 0;
+    }
     // 0xBE, filler, padding stream
     if (data[3] == PES_PADDING_STREAM) {	// from DVD plugin
 	return size;
@@ -2197,8 +2224,26 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
     if ((data[6] & 0xC0) == 0x80 && z >= 2 && check[0] == 0x01
 	&& check[1] == 0x09 && !check[3] && !check[4]) {
 	// old PES HDTV recording z == 2 -> stronger check!
-	if (stream->CodecID == CODEC_ID_H264) {
-#if 0
+	if (stream->CodecID == AV_CODEC_ID_H264) {
+#ifdef DUMP_TRICKSPEED
+	    if (stream->TrickSpeed) {
+		char buf[1024];
+		int fd;
+		static int FrameCounter;
+
+		snprintf(buf, sizeof(buf), "frame_%06d_%08d.raw", getpid(),
+		    FrameCounter++);
+		if ((fd =
+			open(buf, O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC,
+			    0666)) >= 0) {
+		    if (write(fd, data + 9 + n, size - 9 - n)) {
+			// this construct is to remove the annoying warning
+		    }
+		    close(fd);
+		}
+	    }
+#endif
+#ifdef H264_EOS_TRICKSPEED
 	    // this should improve ffwd+frew, but produce crash in ffmpeg
 	    // with some streams
 	    if (stream->TrickSpeed && pts != (int64_t) AV_NOPTS_VALUE) {
@@ -2209,16 +2254,16 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
 		// 1-5=SLICE 6=SEI 7=SPS 8=PPS
 		// NAL SPS sequence parameter set
 		if ((check[7] & 0x1F) == 0x07) {
-		    VideoNextPacket(CODEC_ID_H264);
-		    VideoEnqueue(AV_NOPTS_VALUE, seq_end_h264,
+		    VideoNextPacket(stream, AV_CODEC_ID_H264);
+		    VideoEnqueue(stream, AV_NOPTS_VALUE, seq_end_h264,
 			sizeof(seq_end_h264));
 		}
 	    }
 #endif
-	    VideoNextPacket(stream, CODEC_ID_H264);
+	    VideoNextPacket(stream, AV_CODEC_ID_H264);
 	} else {
 	    Debug(3, "video: h264 detected\n");
-	    stream->CodecID = CODEC_ID_H264;
+	    stream->CodecID = AV_CODEC_ID_H264;
 	}
 	// SKIP PES header (ffmpeg supports short start code)
 	VideoEnqueue(stream, pts, check - 2, l + 2);
@@ -2226,11 +2271,11 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
     }
     // PES start code 0x00 0x00 0x01 0x00|0xb3
     if (z > 1 && check[0] == 0x01 && (!check[1] || check[1] == 0xb3)) {
-	if (stream->CodecID == CODEC_ID_MPEG2VIDEO) {
-	    VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
+	if (stream->CodecID == AV_CODEC_ID_MPEG2VIDEO) {
+	    VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
 	} else {
 	    Debug(3, "video: mpeg2 detected ID %02x\n", check[3]);
-	    stream->CodecID = CODEC_ID_MPEG2VIDEO;
+	    stream->CodecID = AV_CODEC_ID_MPEG2VIDEO;
 	}
 #ifdef noDEBUG				// pip pes packet has no lenght
 	if (ValidateMpeg(data, size)) {
@@ -2246,12 +2291,12 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
 	return size;
     }
     // this happens when vdr sends incomplete packets
-    if (stream->CodecID == CODEC_ID_NONE) {
+    if (stream->CodecID == AV_CODEC_ID_NONE) {
 	Debug(3, "video: not detected\n");
 	return size;
     }
 #ifdef USE_PIP
-    if (stream->CodecID == CODEC_ID_MPEG2VIDEO) {
+    if (stream->CodecID == AV_CODEC_ID_MPEG2VIDEO) {
 	// SKIP PES header
 	VideoMpegEnqueue(stream, pts, data + 9 + n, size - 9 - n);
 #ifndef USE_MPEG_COMPLETE
@@ -2275,10 +2320,10 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
     // incomplete packets produce artefacts after channel switch
     // packet < 65526 is the last split packet, detect it here for
     // better latency
-    if (size < 65526 && stream->CodecID == CODEC_ID_MPEG2VIDEO) {
+    if (size < 65526 && stream->CodecID == AV_CODEC_ID_MPEG2VIDEO) {
 	// mpeg codec supports incomplete packets
 	// waiting for a full complete packages, increases needed delays
-	VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
+	VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
     }
 #endif
 
@@ -2403,13 +2448,15 @@ uint8_t *GrabImage(int *size, int jpeg, int quality, int width, int height)
 int SetPlayMode(int play_mode)
 {
     VideoDisplayWakeup();
-    if (MyVideoStream->Decoder) {	// tell video parser we have new stream
+    // tell video parser we have new stream
+    if (MyVideoStream->Decoder && !MyVideoStream->SkipStream) {
 	if (MyVideoStream->ClearClose) {	// replay clear buffers on close
 	    Clear();			// flush all buffers
 	    MyVideoStream->ClearClose = 0;
 	}
-	if (MyVideoStream->CodecID != CODEC_ID_NONE) {
+	if (MyVideoStream->CodecID != AV_CODEC_ID_NONE) {
 	    MyVideoStream->NewStream = 1;
+	    MyVideoStream->InvalidPesCounter = 0;
 	    // tell hw decoder we are closing stream
 	    VideoSetClosing(MyVideoStream->HwDecoder);
 	    VideoResetStart(MyVideoStream->HwDecoder);
@@ -2419,7 +2466,7 @@ int SetPlayMode(int play_mode)
 	}
     }
     if (MyAudioDecoder) {		// tell audio parser we have new stream
-	if (AudioCodecID != CODEC_ID_NONE) {
+	if (AudioCodecID != AV_CODEC_ID_NONE) {
 	    NewAudioStream = 1;
 	}
     }
@@ -2579,6 +2626,10 @@ void StillPicture(const uint8_t * data, int size)
     int i;
     int old_video_hardware_decoder;
 
+    // might be called in Suspended Mode
+    if (!MyVideoStream->Decoder || MyVideoStream->SkipStream) {
+	return;
+    }
     // must be a PES start code
     if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
 	Error(_("[softhddev] invalid still video packet\n"));
@@ -2593,10 +2644,10 @@ void StillPicture(const uint8_t * data, int size)
     // enable/disable hardware decoder for still picture
     if (VideoHardwareDecoder != ConfigStillDecoder) {
 	VideoHardwareDecoder = ConfigStillDecoder;
-	VideoNextPacket(MyVideoStream, CODEC_ID_NONE);	// close last stream
+	VideoNextPacket(MyVideoStream, AV_CODEC_ID_NONE);	// close last stream
     }
 
-    if (MyVideoStream->CodecID == CODEC_ID_NONE) {
+    if (MyVideoStream->CodecID == AV_CODEC_ID_NONE) {
 	// FIXME: should detect codec, see PlayVideo
 	Error(_("[softhddev] no codec known for still picture\n"));
     }
@@ -2605,7 +2656,7 @@ void StillPicture(const uint8_t * data, int size)
 #ifdef STILL_DEBUG
     fprintf(stderr, "still-picture\n");
 #endif
-    for (i = 0; i < (MyVideoStream->CodecID == CODEC_ID_MPEG2VIDEO ? 4 : 4);
+    for (i = 0; i < (MyVideoStream->CodecID == AV_CODEC_ID_MPEG2VIDEO ? 4 : 4);
 	++i) {
 	const uint8_t *split;
 	int n;
@@ -2645,13 +2696,13 @@ void StillPicture(const uint8_t * data, int size)
 
 	    VideoNextPacket(MyVideoStream, MyVideoStream->CodecID);	// terminate last packet
 	} else {			// ES packet
-	    if (MyVideoStream->CodecID != CODEC_ID_MPEG2VIDEO) {
-		VideoNextPacket(MyVideoStream, CODEC_ID_NONE);	// close last stream
-		MyVideoStream->CodecID = CODEC_ID_MPEG2VIDEO;
+	    if (MyVideoStream->CodecID != AV_CODEC_ID_MPEG2VIDEO) {
+		VideoNextPacket(MyVideoStream, AV_CODEC_ID_NONE);	// close last stream
+		MyVideoStream->CodecID = AV_CODEC_ID_MPEG2VIDEO;
 	    }
 	    VideoEnqueue(MyVideoStream, AV_NOPTS_VALUE, data, size);
 	}
-	if (MyVideoStream->CodecID == CODEC_ID_H264) {
+	if (MyVideoStream->CodecID == AV_CODEC_ID_H264) {
 	    VideoEnqueue(MyVideoStream, AV_NOPTS_VALUE, seq_end_h264,
 		sizeof(seq_end_h264));
 	} else {
@@ -2672,7 +2723,7 @@ void StillPicture(const uint8_t * data, int size)
 #endif
     if (VideoHardwareDecoder != old_video_hardware_decoder) {
 	VideoHardwareDecoder = old_video_hardware_decoder;
-	VideoNextPacket(MyVideoStream, CODEC_ID_NONE);	// close last stream
+	VideoNextPacket(MyVideoStream, AV_CODEC_ID_NONE);	// close last stream
     }
     VideoSetTrickSpeed(MyVideoStream->HwDecoder, 0);
 }
@@ -3122,7 +3173,7 @@ int Start(void)
 	AudioInit();
 	av_new_packet(AudioAvPkt, AUDIO_BUFFER_SIZE);
 	MyAudioDecoder = CodecAudioNewDecoder();
-	AudioCodecID = CODEC_ID_NONE;
+	AudioCodecID = AV_CODEC_ID_NONE;
 	AudioChannelID = -1;
 
 	if (!ConfigStartX11Server) {
@@ -3275,7 +3326,7 @@ void Resume(void)
 	AudioInit();
 	av_new_packet(AudioAvPkt, AUDIO_BUFFER_SIZE);
 	MyAudioDecoder = CodecAudioNewDecoder();
-	AudioCodecID = CODEC_ID_NONE;
+	AudioCodecID = AV_CODEC_ID_NONE;
 	AudioChannelID = -1;
     }
 
@@ -3376,8 +3427,8 @@ void PipStart(int x, int y, int width, int height, int pip_x, int pip_y,
 
     if (!PipVideoStream->Decoder) {
 	PipVideoStream->SkipStream = 1;
-	PipVideoStream->CodecID = CODEC_ID_NONE;
-	PipVideoStream->LastCodecID = CODEC_ID_NONE;
+	PipVideoStream->CodecID = AV_CODEC_ID_NONE;
+	PipVideoStream->LastCodecID = AV_CODEC_ID_NONE;
 
 	if ((PipVideoStream->HwDecoder = VideoNewHwDecoder(PipVideoStream))) {
 	    PipVideoStream->Decoder =
@@ -3422,6 +3473,7 @@ void PipStop(void)
     VideoPacketExit(PipVideoStream);
 
     PipVideoStream->NewStream = 1;
+    PipVideoStream->InvalidPesCounter = 0;
 #else
     PipVideoStream->Close = 1;
     for (i = 0; PipVideoStream->Close && i < 50; ++i) {
diff --git a/softhddev.h b/softhddev.h
index 46f8d13..6e446dc 100644
--- a/softhddev.h
+++ b/softhddev.h
@@ -17,7 +17,7 @@
 ///	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ///	GNU Affero General Public License for more details.
 ///
-///	$Id: 77181c7dc4a3d5c8ed0115a7db6820e2f9fcf40e $
+///	$Id$
 //////////////////////////////////////////////////////////////////////////////
 
 #ifdef __cplusplus
diff --git a/softhddevice.cpp b/softhddevice.cpp
index 1b5cddd..c2839ce 100644
--- a/softhddevice.cpp
+++ b/softhddevice.cpp
@@ -17,7 +17,7 @@
 ///	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ///	GNU Affero General Public License for more details.
 ///
-///	$Id: ed5d828fa572616440a5e70c50731fbfd6acb512 $
+///	$Id$
 //////////////////////////////////////////////////////////////////////////////
 
 #define __STDC_CONSTANT_MACROS		///< needed for ffmpeg UINT64_C
@@ -52,7 +52,7 @@ extern "C"
     /// vdr-plugin version number.
     /// Makefile extracts the version number for generating the file name
     /// for the distribution archive.
-static const char *const VERSION = "0.6.0"
+static const char *const VERSION = "0.6.1rc1"
 #ifdef GIT_REV
     "-GIT" GIT_REV
 #endif
@@ -854,9 +854,9 @@ void cMenuSetupSoft::Create(void)
 		&AudioPassthroughPCM, trVDR("no"), trVDR("yes")));
 	Add(new cMenuEditBoolItem(tr("\040\040AC-3 pass-through"),
 		&AudioPassthroughAC3, trVDR("no"), trVDR("yes")));
-	Add(new cMenuEditBoolItem(tr("\040\040EAC-3 pass-through"),
+	Add(new cMenuEditBoolItem(tr("\040\040E-AC-3 pass-through"),
 		&AudioPassthroughEAC3, trVDR("no"), trVDR("yes")));
-	Add(new cMenuEditBoolItem(tr("Enable (E)AC-3 (decoder) downmix"),
+	Add(new cMenuEditBoolItem(tr("Enable (E-)AC-3 (decoder) downmix"),
 		&AudioDownmix, trVDR("no"), trVDR("yes")));
 	Add(new cMenuEditBoolItem(tr("Volume control"), &AudioSoftvol,
 		tr("Hardware"), tr("Software")));
@@ -1443,12 +1443,12 @@ static void PipPesParse(const uint8_t * data, int size, int is_start)
     if (is_start) {			// start of pes packet
 	if (pes_index) {
 	    if (0) {
-		fprintf(stderr, "pip: pes packet %8d %02x%02x\n", pes_index,
+		fprintf(stderr, "pip: PES packet %8d %02x%02x\n", pes_index,
 		    pes_buf[2], pes_buf[3]);
 	    }
 	    if (pes_buf[0] || pes_buf[1] || pes_buf[2] != 0x01) {
 		// FIXME: first should always fail
-		esyslog(tr("[softhddev]pip: invalid pes packet %d\n"),
+		esyslog(tr("[softhddev]pip: invalid PES packet %d\n"),
 		    pes_index);
 	    } else {
 		PipPlayVideo(pes_buf, pes_index);
@@ -2190,7 +2190,7 @@ bool cSoftHdDevice::SetPlayMode(ePlayMode play_mode)
 	case pmVideoOnly:
 	    break;
 	case pmNone:
-	    return true;
+	    break;
 	case pmExtern_THIS_SHOULD_BE_AVOIDED:
 	    dsyslog("[softhddev] play mode external\n");
 	    // FIXME: what if already suspended?
@@ -2512,6 +2512,9 @@ uchar *cSoftHdDevice::GrabImage(int &size, bool jpeg, int quality, int width,
     if (SuspendMode != NOT_SUSPENDED) {
 	return NULL;
     }
+    if (quality < 0) {			// caller should care, but fix it
+	quality = 95;
+    }
 
     return::GrabImage(&size, jpeg, quality, width, height);
 }
diff --git a/softhddevice.h b/softhddevice.h
index 23c4ac1..1729441 100644
--- a/softhddevice.h
+++ b/softhddevice.h
@@ -17,5 +17,5 @@
 ///	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ///	GNU Affero General Public License for more details.
 ///
-///	$Id: 172944172364f1837cf05e1776e9e75e59b08bf3 $
+///	$Id$
 //////////////////////////////////////////////////////////////////////////////
diff --git a/vdr-softhddevice b/vdr-softhddevice
deleted file mode 120000
index 945c9b4..0000000
--- a/vdr-softhddevice
+++ /dev/null
@@ -1 +0,0 @@
-.
\ No newline at end of file
diff --git a/vdr-softhddevice-9999.ebuild b/vdr-softhddevice-9999.ebuild
index 85871d9..2365a52 100644
--- a/vdr-softhddevice-9999.ebuild
+++ b/vdr-softhddevice-9999.ebuild
@@ -20,7 +20,7 @@ HOMEPAGE="http://projects.vdr-developer.org/projects/show/plg-softhddevice"
 
 LICENSE="AGPL-3"
 SLOT="0"
-IUSE="alsa oss vaapi vdpau yaepg xscreensaver debug"
+IUSE="alsa oss vaapi vdpau opengl yaepg xscreensaver debug"
 
 RDEPEND=">=media-video/vdr-1.7
 	>=virtual/ffmpeg-0.7[vdpau?,vaapi?]
@@ -30,6 +30,7 @@ RDEPEND=">=media-video/vdr-1.7
 	alsa? ( media-libs/alsa-lib )
 	vdpau? ( x11-libs/libvdpau )
 	vaapi? ( x11-libs/libva )
+	opengl? ( virtual/opengl )
 	alsa? ( media-libs/alsa-lib )
 	yaepg? ( >=media-video/vdr-1.7[yaepg] )"
 DEPEND="${RDEPEND}
@@ -44,6 +45,7 @@ src_compile() {
 	myconf+=" ALSA=$(usex alsa 1 0)"
 	myconf+=" OSS=$(usex oss 1 0)"
 	myconf+=" VDPAU=$(usex vdpau 1 0)"
+	myconf+=" OPENGL=$(usex opengl 1 0)"
 	myconf+=" VAAPI=$(usex vaapi 1 0)"
 	myconf+=" SCREENSAVER=$(usex xscreensaver 1 0)"
 	if has_version ">=media-video/ffmpeg-0.8" ; then
diff --git a/video.c b/video.c
index b4aea03..afe5714 100644
--- a/video.c
+++ b/video.c
@@ -17,7 +17,7 @@
 ///	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ///	GNU Affero General Public License for more details.
 ///
-///	$Id: d4c9a5a708d44a17c8f1f84738ebd92f72796f4e $
+///	$Id$
 //////////////////////////////////////////////////////////////////////////////
 
 ///
@@ -43,7 +43,7 @@
 #define USE_AUTOCROP			///< compile auto-crop support
 #define USE_GRAB			///< experimental grab code
 #define noUSE_GLX			///< outdated GLX code
-#define noUSE_DOUBLEBUFFER		///< use GLX double buffers
+#define USE_DOUBLEBUFFER		///< use GLX double buffers
 //#define USE_VAAPI				///< enable vaapi support
 //#define USE_VDPAU				///< enable vdpau support
 #define noUSE_BITMAP			///< use vdpau bitmap surface
@@ -92,7 +92,9 @@
 
 #include <xcb/xcb.h>
 //#include <xcb/bigreq.h>
-//#include <xcb/glx.h>
+#ifdef xcb_USE_GLX
+#include <xcb/glx.h>
+#endif
 //#include <xcb/randr.h>
 #ifdef USE_SCREENSAVER
 #include <xcb/screensaver.h>
@@ -137,7 +139,7 @@ typedef enum
 #include <va/va_glx.h>
 #endif
 #ifndef VA_SURFACE_ATTRIB_SETTABLE
-/// make source compatible with old libva
+/// make source compatible with stable libva
 #define vaCreateSurfaces(d, f, w, h, s, ns, a, na) \
     vaCreateSurfaces(d, w, h, f, ns, s)
 #endif
@@ -149,14 +151,26 @@ typedef enum
 #endif
 
 #include <libavcodec/avcodec.h>
+// support old ffmpeg versions <1.0
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,18,102)
+#define AVCodecID CodecID
+#define AV_CODEC_ID_H263 CODEC_ID_H263
+#define AV_CODEC_ID_H264 CODEC_ID_H264
+#define AV_CODEC_ID_MPEG1VIDEO CODEC_ID_MPEG1VIDEO
+#define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO
+#define AV_CODEC_ID_MPEG4 CODEC_ID_MPEG4
+#define AV_CODEC_ID_VC1 CODEC_ID_VC1
+#define AV_CODEC_ID_WMV3 CODEC_ID_WMV3
+#endif
 #include <libavcodec/vaapi.h>
 #include <libavutil/pixdesc.h>
 
-#if LIBAVCODEC_VERSION_INT == AV_VERSION_INT(54,86,100)
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54,86,100)
     ///
     /// ffmpeg version 1.1.1 calls get_format with zero width and height
     /// for H264 codecs.
     /// since version 1.1.3 get_format is called twice.
+    /// ffmpeg 1.2 still buggy
     ///
 #define FFMPEG_BUG1_WORKAROUND		///< get_format bug workaround
 #endif
@@ -246,10 +260,14 @@ typedef struct _video_module_
 	const enum PixelFormat *);
     void (*const RenderFrame) (VideoHwDecoder *, const AVCodecContext *,
 	const AVFrame *);
+    void *(*const GetHwAccelContext)(VideoHwDecoder *);
     void (*const SetClock) (VideoHwDecoder *, int64_t);
      int64_t(*const GetClock) (const VideoHwDecoder *);
+    void (*const SetClosing) (const VideoHwDecoder *);
+    void (*const ResetStart) (const VideoHwDecoder *);
     void (*const SetTrickSpeed) (const VideoHwDecoder *, int);
     uint8_t *(*const GrabOutput)(int *, int *, int *);
+    void (*const GetStats) (VideoHwDecoder *, int *, int *, int *, int *);
     void (*const SetBackground) (uint32_t);
     void (*const SetVideoMode) (void);
     void (*const ResetAutoCrop) (void);
@@ -621,10 +639,15 @@ static void VideoUpdateOutput(AVRational input_aspect_ratio, int input_width,
 
 #ifdef USE_GLX
 
-static int GlxEnabled = 1;		///< use GLX
-static int GlxVSyncEnabled = 0;		///< enable/disable v-sync
+static int GlxEnabled;			///< use GLX
+static int GlxVSyncEnabled;		///< enable/disable v-sync
 static GLXContext GlxSharedContext;	///< shared gl context
 static GLXContext GlxContext;		///< our gl context
+
+#ifdef USE_VIDEO_THREAD
+static GLXContext GlxThreadContext;	///< our gl context for the thread
+#endif
+
 static XVisualInfo *GlxVisualInfo;	///< our gl visual
 
 static GLuint OsdGlTextures[2];		///< gl texture for OSD
@@ -680,26 +703,22 @@ static int GlxIsExtensionSupported(const char *ext)
     return 0;
 }
 
-#if 0
 ///
 ///	Setup GLX decoder
 ///
-///	@param decoder	VA-API decoder
+///	@param width		input video textures width
+///	@param height		input video textures height
+///	@param[OUT] textures	created and prepared textures
 ///
-void GlxSetupDecoder(VaapiDecoder * decoder)
+static void GlxSetupDecoder(int width, int height, GLuint * textures)
 {
-    int width;
-    int height;
     int i;
 
-    width = decoder->InputWidth;
-    height = decoder->InputHeight;
-
     glEnable(GL_TEXTURE_2D);		// create 2d texture
-    glGenTextures(2, decoder->GlTexture);
+    glGenTextures(2, textures);
     GlxCheck();
     for (i = 0; i < 2; ++i) {
-	glBindTexture(GL_TEXTURE_2D, decoder->GlTexture[i]);
+	glBindTexture(GL_TEXTURE_2D, textures[i]);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -713,12 +732,15 @@ void GlxSetupDecoder(VaapiDecoder * decoder)
 
     GlxCheck();
 }
-#endif
 
 ///
 ///	Render texture.
 ///
 ///	@param texture	2d texture
+///	@param x	window x
+///	@param y	window y
+///	@param width	window width
+///	@param height	window height
 ///
 static inline void GlxRenderTexture(GLuint texture, int x, int y, int width,
     int height)
@@ -736,16 +758,6 @@ static inline void GlxRenderTexture(GLuint texture, int x, int y, int width,
 	glVertex2i(x, y);
 	glTexCoord2f(1.0f, 0.0f);
 	glVertex2i(x + width, y);
-#if 0
-	glTexCoord2f(0.0f, 0.0f);
-	glVertex2i(x, y);
-	glTexCoord2f(0.0f, 1.0f);
-	glVertex2i(x, y + height);
-	glTexCoord2f(1.0f, 1.0f);
-	glVertex2i(x + width, y + height);
-	glTexCoord2f(1.0f, 0.0f);
-	glVertex2i(x + width, y);
-#endif
     }
     glEnd();
 
@@ -754,15 +766,20 @@ static inline void GlxRenderTexture(GLuint texture, int x, int y, int width,
 }
 
 ///
-///	Upload texture.
+///	Upload OSD texture.
 ///
-static void GlxUploadTexture(int x, int y, int width, int height,
+///	@param x	x coordinate texture
+///	@param y	y coordinate texture
+///	@param width	argb image width
+///	@param height	argb image height
+///	@param argb	argb image
+///
+static void GlxUploadOsdTexture(int x, int y, int width, int height,
     const uint8_t * argb)
 {
     // FIXME: use other / faster uploads
     // ARB_pixelbuffer_object GL_PIXEL_UNPACK_BUFFER glBindBufferARB()
     // glMapBuffer() glUnmapBuffer()
-    // glTexSubImage2D
 
     glEnable(GL_TEXTURE_2D);		// upload 2d texture
 
@@ -775,59 +792,164 @@ static void GlxUploadTexture(int x, int y, int width, int height,
 }
 
 ///
-///	Render to glx texture.
+///	GLX initialize OSD.
+///
+///	@param width	osd width
+///	@param height	osd height
 ///
-static void GlxRender(int osd_width, int osd_height)
+static void GlxOsdInit(int width, int height)
 {
-    static uint8_t *image;
-    static uint8_t cycle;
-    int x;
-    int y;
+    int i;
 
-    if (!OsdGlTextures[0] || !OsdGlTextures[1]) {
+#ifdef DEBUG
+    if (!GlxEnabled) {
+	Debug(3, "video/glx: %s called without glx enabled\n", __FUNCTION__);
 	return;
     }
-    // render each frame kills performance
+#endif
 
-    // osd 1920 * 1080 * 4 (RGBA) * 50 (HZ) = 396 Mb/s
+    Debug(3, "video/glx: osd init context %p <-> %p\n", glXGetCurrentContext(),
+	GlxContext);
 
-    // too big for alloca
-    if (!image) {
-	image = malloc(4 * osd_width * osd_height);
-	memset(image, 0x00, 4 * osd_width * osd_height);
+    //
+    //	create a RGBA texture.
+    //
+    glEnable(GL_TEXTURE_2D);		// create 2d texture(s)
+
+    glGenTextures(2, OsdGlTextures);
+    for (i = 0; i < 2; ++i) {
+	glBindTexture(GL_TEXTURE_2D, OsdGlTextures[i]);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	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_RGBA8, width, height, 0, GL_BGRA,
+	    GL_UNSIGNED_BYTE, NULL);
     }
-    for (y = 0; y < osd_height; ++y) {
-	for (x = 0; x < osd_width; ++x) {
-	    ((uint32_t *) image)[x + y * osd_width] =
-		0x00FFFFFF | (cycle++) << 24;
-	}
+
+    glBindTexture(GL_TEXTURE_2D, 0);
+    glDisable(GL_TEXTURE_2D);
+}
+
+///
+///	GLX cleanup osd.
+///
+static void GlxOsdExit(void)
+{
+    if (OsdGlTextures[0]) {
+	glDeleteTextures(2, OsdGlTextures);
+	OsdGlTextures[0] = 0;
+	OsdGlTextures[1] = 0;
     }
-    cycle++;
+}
 
-    // FIXME: convert is for GLX texture unneeded
-    // convert internal osd to image
-    //GfxConvert(image, 0, 4 * osd_width);
-    //
+///
+///	Upload ARGB image to texture.
+///
+///	@param x	x coordinate of image in osd texture
+///	@param y	y coordinate of image in osd texture
+///	@param width	width of image
+///	@param height	height of image
+///	@param argb	argb image
+///
+///	@note looked by caller
+///
+static void GlxOsdDrawARGB(int x, int y, int width, int height,
+    const uint8_t * argb)
+{
+#ifdef DEBUG
+    uint32_t start;
+    uint32_t end;
+#endif
+
+#ifdef DEBUG
+    if (!GlxEnabled) {
+	Debug(3, "video/glx: %s called without glx enabled\n", __FUNCTION__);
+	return;
+    }
+    start = GetMsTicks();
+    Debug(3, "video/glx: osd context %p <-> %p\n", glXGetCurrentContext(),
+	GlxContext);
+#endif
+
+    // set glx context
+    if (!glXMakeCurrent(XlibDisplay, VideoWindow, GlxContext)) {
+	Error(_("video/glx: can't make glx context current\n"));
+	return;
+    }
+    GlxUploadOsdTexture(x, y, width, height, argb);
+    glXMakeCurrent(XlibDisplay, None, NULL);
+
+#ifdef DEBUG
+    end = GetMsTicks();
+
+    Debug(3, "video/glx: osd upload %dx%d%+d%+d %dms %d\n", width, height, x,
+	y, end - start, width * height * 4);
+#endif
+}
+
+///
+///	Clear OSD texture.
+///
+///	@note looked by caller
+///
+static void GlxOsdClear(void)
+{
+    void *texbuf;
+
+#ifdef DEBUG
+    if (!GlxEnabled) {
+	Debug(3, "video/glx: %s called without glx enabled\n", __FUNCTION__);
+	return;
+    }
+
+    Debug(3, "video/glx: osd context %p <-> %p\n", glXGetCurrentContext(),
+	GlxContext);
+#endif
+
+    // FIXME: any opengl function to clear an area?
+    // FIXME: if not; use zero buffer
+    // FIXME: if not; use dirty area
+
+    texbuf = calloc(OsdWidth * OsdHeight, 4);
 
-    GlxUploadTexture(0, 0, osd_width, osd_height, image);
+    // set glx context
+    if (!glXMakeCurrent(XlibDisplay, VideoWindow, GlxContext)) {
+	Error(_("video/glx: can't make glx context current\n"));
+	return;
+    }
+    GlxUploadOsdTexture(0, 0, OsdWidth, OsdHeight, texbuf);
+    glXMakeCurrent(XlibDisplay, None, NULL);
+
+    free(texbuf);
 }
 
 ///
 ///	Setup GLX window.
 ///
-static void GlxSetupWindow(xcb_window_t window, int width, int height)
+///	@param window	xcb window id
+///	@param width	window width
+///	@param height	window height
+///	@param context	GLX context
+///
+static void GlxSetupWindow(xcb_window_t window, int width, int height,
+    GLXContext context)
 {
+#ifdef DEBUG
     uint32_t start;
     uint32_t end;
     int i;
     unsigned count;
+#endif
 
-    Debug(3, "video/glx: %s\n %x %dx%d", __FUNCTION__, window, width, height);
+    Debug(3, "video/glx: %s %x %dx%d context:%p", __FUNCTION__, window, width,
+	height, context);
 
     // set glx context
-    if (!glXMakeCurrent(XlibDisplay, window, GlxContext)) {
-	Fatal(_("video/glx: can't make glx context current\n"));
-	// FIXME: disable glx
+    if (!glXMakeCurrent(XlibDisplay, window, context)) {
+	Error(_("video/glx: can't make glx context current\n"));
+	GlxEnabled = 0;
 	return;
     }
 
@@ -995,7 +1117,8 @@ static void GlxInit(void)
     if (!context) {
 	Error(_("video/glx: can't create glx context\n"));
 	GlxEnabled = 0;
-	// FIXME: destroy GlxSharedContext
+	glXDestroyContext(XlibDisplay, GlxSharedContext);
+	GlxSharedContext = 0;
 	return;
     }
     GlxContext = context;
@@ -1092,12 +1215,10 @@ static void GlxExit(void)
     if (GlxContext) {
 	glXDestroyContext(XlibDisplay, GlxContext);
     }
-#if 0
     if (GlxThreadContext) {
 	glXDestroyContext(XlibDisplay, GlxThreadContext);
     }
     // FIXME: must free GlxVisualInfo
-#endif
 }
 
 #endif
@@ -1393,8 +1514,8 @@ struct _vaapi_decoder_
     AutoCropCtx AutoCrop[1];		///< auto-crop variables
 #endif
 #ifdef USE_GLX
-    GLuint GlTexture[2];		///< gl texture for VA-API
-    void *GlxSurface[2];		///< VA-API/GLX surface
+    GLuint GlTextures[2];		///< gl texture for VA-API
+    void *GlxSurfaces[2];		///< VA-API/GLX surface
 #endif
     VASurfaceID BlackSurface;		///< empty black surface
 
@@ -1851,8 +1972,8 @@ static VaapiDecoder *VaapiNewHwDecoder(VideoStream * stream)
     decoder->VaapiContext->context_id = VA_INVALID_ID;
 
 #ifdef USE_GLX
-    decoder->GlxSurface[0] = VA_INVALID_ID;
-    decoder->GlxSurface[1] = VA_INVALID_ID;
+    decoder->GlxSurfaces[0] = NULL;
+    decoder->GlxSurfaces[1] = NULL;
     if (GlxEnabled) {
 	// FIXME: create GLX context here
     }
@@ -2008,20 +2129,22 @@ static void VaapiDelHwDecoder(VaapiDecoder * decoder)
 	}
     }
 #ifdef USE_GLX
-    if (decoder->GlxSurface[0] != VA_INVALID_ID) {
-	if (vaDestroySurfaceGLX(VaDisplay, decoder->GlxSurface[0])
+    if (decoder->GlxSurfaces[0]) {
+	if (vaDestroySurfaceGLX(VaDisplay, decoder->GlxSurfaces[0])
 	    != VA_STATUS_SUCCESS) {
 	    Error(_("video/vaapi: can't destroy glx surface!\n"));
 	}
+	decoder->GlxSurfaces[0] = NULL;
     }
-    if (decoder->GlxSurface[1] != VA_INVALID_ID) {
-	if (vaDestroySurfaceGLX(VaDisplay, decoder->GlxSurface[1])
+    if (decoder->GlxSurfaces[1]) {
+	if (vaDestroySurfaceGLX(VaDisplay, decoder->GlxSurfaces[1])
 	    != VA_STATUS_SUCCESS) {
 	    Error(_("video/vaapi: can't destroy glx surface!\n"));
 	}
+	decoder->GlxSurfaces[0] = NULL;
     }
-    if (decoder->GlTexture[0]) {
-	glDeleteTextures(2, decoder->GlTexture);
+    if (decoder->GlTextures[0]) {
+	glDeleteTextures(2, decoder->GlTextures);
     }
 #endif
 
@@ -2243,6 +2366,33 @@ static int VaapiInit(const char *display_name)
     return 1;
 }
 
+#ifdef USE_GLX
+
+///
+///	VA-API GLX setup.
+///
+///	@param display_name	x11/xcb display name
+///
+///	@returns true if VA-API could be initialized, false otherwise.
+///
+static int VaapiGlxInit(const char *display_name)
+{
+    GlxEnabled = 1;
+
+    GlxInit();
+    if (GlxEnabled) {
+	GlxSetupWindow(VideoWindow, VideoWindowWidth, VideoWindowHeight,
+	    GlxContext);
+    }
+    if (!GlxEnabled) {
+	Error(_("video/glx: glx error\n"));
+    }
+
+    return VaapiInit(display_name);
+}
+
+#endif
+
 ///
 ///	VA-API cleanup
 ///
@@ -2250,7 +2400,7 @@ static void VaapiExit(void)
 {
     int i;
 
-    // FIXME: more VA-API cleanups...
+// FIXME: more VA-API cleanups...
 
     for (i = 0; i < VaapiDecoderN; ++i) {
 	if (VaapiDecoders[i]) {
@@ -2310,6 +2460,7 @@ static int VaapiFindImageFormat(VaapiDecoder * decoder,
 	    // intel: I420 is native format for MPEG-2 decoded surfaces
 	    // intel: NV12 is native format for H.264 decoded surfaces
 	case PIX_FMT_YUV420P:
+	case PIX_FMT_YUVJ420P:
 	    // fourcc = VA_FOURCC_YV12; // YVU
 	    fourcc = VA_FOURCC('I', '4', '2', '0');	// YUV
 	    break;
@@ -2403,16 +2554,18 @@ static void VaapiSetup(VaapiDecoder * decoder,
     if (GlxEnabled) {
 	// FIXME: destroy old context
 
-	GlxSetupDecoder(decoder);
+	GlxSetupDecoder(decoder->InputWidth, decoder->InputHeight,
+	    decoder->GlTextures);
 	// FIXME: try two textures
 	if (vaCreateSurfaceGLX(decoder->VaDisplay, GL_TEXTURE_2D,
-		decoder->GlTexture[0], &decoder->GlxSurface[0])
+		decoder->GlTextures[0], &decoder->GlxSurfaces[0])
 	    != VA_STATUS_SUCCESS) {
 	    Fatal(_("video/glx: can't create glx surfaces\n"));
+	    // FIXME: no fatal here
 	}
 	/*
 	   if (vaCreateSurfaceGLX(decoder->VaDisplay, GL_TEXTURE_2D,
-	   decoder->GlTexture[1], &decoder->GlxSurface[1])
+	   decoder->GlTextures[1], &decoder->GlxSurfaces[1])
 	   != VA_STATUS_SUCCESS) {
 	   Fatal(_("video/glx: can't create glx surfaces\n"));
 	   }
@@ -2424,6 +2577,11 @@ static void VaapiSetup(VaapiDecoder * decoder,
     //
     //	update OSD associate
     //
+#ifdef USE_GLX
+    if (GlxEnabled) {
+	return;
+    }
+#endif
     VaapiAssociate(decoder);
 }
 
@@ -2544,7 +2702,7 @@ static enum PixelFormat Vaapi_get_format(VaapiDecoder * decoder,
     int e;
     VAConfigAttrib attrib;
 
-    if (!VideoHardwareDecoder || (video_ctx->codec_id == CODEC_ID_MPEG2VIDEO
+    if (!VideoHardwareDecoder || (video_ctx->codec_id == AV_CODEC_ID_MPEG2VIDEO
 	    && VideoHardwareDecoder == 1)
 	) {				// hardware disabled by config
 	Debug(3, "codec: hardware acceleration disabled\n");
@@ -2563,19 +2721,19 @@ static enum PixelFormat Vaapi_get_format(VaapiDecoder * decoder,
 
     // check profile
     switch (video_ctx->codec_id) {
-	case CODEC_ID_MPEG2VIDEO:
+	case AV_CODEC_ID_MPEG2VIDEO:
 	    decoder->SurfacesNeeded =
 		CODEC_SURFACES_MPEG2 + VIDEO_SURFACES_MAX + 2;
 	    p = VaapiFindProfile(profiles, profile_n, VAProfileMPEG2Main);
 	    break;
-	case CODEC_ID_MPEG4:
-	case CODEC_ID_H263:
+	case AV_CODEC_ID_MPEG4:
+	case AV_CODEC_ID_H263:
 	    decoder->SurfacesNeeded =
 		CODEC_SURFACES_MPEG4 + VIDEO_SURFACES_MAX + 2;
 	    p = VaapiFindProfile(profiles, profile_n,
 		VAProfileMPEG4AdvancedSimple);
 	    break;
-	case CODEC_ID_H264:
+	case AV_CODEC_ID_H264:
 	    decoder->SurfacesNeeded =
 		CODEC_SURFACES_H264 + VIDEO_SURFACES_MAX + 2;
 	    // try more simple formats, fallback to better
@@ -2593,12 +2751,12 @@ static enum PixelFormat Vaapi_get_format(VaapiDecoder * decoder,
 		p = VaapiFindProfile(profiles, profile_n, VAProfileH264High);
 	    }
 	    break;
-	case CODEC_ID_WMV3:
+	case AV_CODEC_ID_WMV3:
 	    decoder->SurfacesNeeded =
 		CODEC_SURFACES_VC1 + VIDEO_SURFACES_MAX + 2;
 	    p = VaapiFindProfile(profiles, profile_n, VAProfileVC1Main);
 	    break;
-	case CODEC_ID_VC1:
+	case AV_CODEC_ID_VC1:
 	    decoder->SurfacesNeeded =
 		CODEC_SURFACES_VC1 + VIDEO_SURFACES_MAX + 2;
 	    p = VaapiFindProfile(profiles, profile_n, VAProfileVC1Advanced);
@@ -2826,44 +2984,6 @@ static void VaapiPutSurfaceX11(VaapiDecoder * decoder, VASurfaceID surface,
 #ifdef USE_GLX
 
 ///
-///	Render texture.
-///
-///	@param texture	2d texture
-///
-static inline void VideoRenderTexture(GLuint texture, int x, int y, int width,
-    int height)
-{
-    glEnable(GL_TEXTURE_2D);
-    glBindTexture(GL_TEXTURE_2D, texture);
-
-    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);	// no color
-    glBegin(GL_QUADS); {
-	glTexCoord2f(1.0f, 1.0f);
-	glVertex2i(x + width, y + height);
-	glTexCoord2f(0.0f, 1.0f);
-	glVertex2i(x, y + height);
-	glTexCoord2f(0.0f, 0.0f);
-	glVertex2i(x, y);
-	glTexCoord2f(1.0f, 0.0f);
-	glVertex2i(x + width, y);
-#if 0
-	glTexCoord2f(0.0f, 0.0f);
-	glVertex2i(x, y);
-	glTexCoord2f(0.0f, 1.0f);
-	glVertex2i(x, y + height);
-	glTexCoord2f(1.0f, 1.0f);
-	glVertex2i(x + width, y + height);
-	glTexCoord2f(1.0f, 0.0f);
-	glVertex2i(x + width, y);
-#endif
-    }
-    glEnd();
-
-    glBindTexture(GL_TEXTURE_2D, 0);
-    glDisable(GL_TEXTURE_2D);
-}
-
-///
 ///	Draw surface of the VA-API decoder with glx.
 ///
 ///	@param decoder	VA-API decoder
@@ -2876,12 +2996,14 @@ static void VaapiPutSurfaceGLX(VaapiDecoder * decoder, VASurfaceID surface,
     int interlaced, int top_field_first, int field)
 {
     unsigned type;
-    uint32_t start;
-    uint32_t copy;
-    uint32_t end;
+
+    //uint32_t start;
+    //uint32_t copy;
+    //uint32_t end;
 
     // deinterlace
     if (interlaced
+	&& VideoDeinterlace[decoder->Resolution] < VideoDeinterlaceSoftBob
 	&& VideoDeinterlace[decoder->Resolution] != VideoDeinterlaceWeave) {
 	if (top_field_first) {
 	    if (field) {
@@ -2899,18 +3021,20 @@ static void VaapiPutSurfaceGLX(VaapiDecoder * decoder, VASurfaceID surface,
     } else {
 	type = VA_FRAME_PICTURE;
     }
-    start = GetMsTicks();
-    if (vaCopySurfaceGLX(decoder->VaDisplay, decoder->GlxSurface[0], surface,
+
+    //start = GetMsTicks();
+    if (vaCopySurfaceGLX(decoder->VaDisplay, decoder->GlxSurfaces[0], surface,
 	    type | decoder->SurfaceFlagsTable[decoder->Resolution]) !=
 	VA_STATUS_SUCCESS) {
 	Error(_("video/glx: vaCopySurfaceGLX failed\n"));
 	return;
     }
-    copy = GetMsTicks();
+    //copy = GetMsTicks();
     // hardware surfaces are always busy
-    VideoRenderTexture(decoder->GlTexture[0], decoder->OutputX,
+    // FIXME: CropX, ...
+    GlxRenderTexture(decoder->GlTextures[0], decoder->OutputX,
 	decoder->OutputY, decoder->OutputWidth, decoder->OutputHeight);
-    end = GetMsTicks();
+    //end = GetMsTicks();
     //Debug(3, "video/vaapi/glx: %d copy %d render\n", copy - start, end - copy);
 }
 
@@ -3264,6 +3388,12 @@ static void VaapiBlackSurface(VaapiDecoder * decoder)
     uint32_t sync;
     uint32_t put1;
 
+#ifdef USE_GLX
+    if (GlxEnabled) {			// already done
+	return;
+    }
+#endif
+
     // wait until we have osd subpicture
     if (VaOsdSubpicture == VA_INVALID_ID) {
 	Warning(_("video/vaapi: no osd subpicture yet\n"));
@@ -4450,6 +4580,16 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
 }
 
 ///
+///	Get hwaccel context for ffmpeg.
+///
+///	@param decoder	VA-API hw decoder
+///
+static void *VaapiGetHwAccelContext(VaapiDecoder * decoder)
+{
+    return decoder->VaapiContext;
+}
+
+///
 ///	Advance displayed frame of decoder.
 ///
 ///	@param decoder	VA-API hw decoder
@@ -4575,8 +4715,16 @@ static void VaapiDisplayFrame(void)
 	    put2 = GetMsTicks();
 #endif
 	} else {
-	    VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced,
-		decoder->TopFieldFirst, decoder->SurfaceField);
+#ifdef USE_GLX
+	    if (GlxEnabled) {
+		VaapiPutSurfaceGLX(decoder, surface, decoder->Interlaced,
+		    decoder->TopFieldFirst, decoder->SurfaceField);
+	    } else
+#endif
+	    {
+		VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced,
+		    decoder->TopFieldFirst, decoder->SurfaceField);
+	    }
 #ifdef DEBUG
 	    put1 = GetMsTicks();
 	    put2 = put1;
@@ -4609,6 +4757,24 @@ static void VaapiDisplayFrame(void)
 
 	decoder->FrameTime = nowtime;
     }
+
+#ifdef USE_GLX
+    if (GlxEnabled) {
+	//
+	//	add OSD
+	//
+	if (OsdShown) {
+	    GlxRenderTexture(OsdGlTextures[OsdIndex], 0, 0, VideoWindowWidth,
+		VideoWindowHeight);
+	    // FIXME: toggle osd
+	}
+	//glFinish();
+	glXSwapBuffers(XlibDisplay, VideoWindow);
+	GlxCheck();
+	//glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
+	glClear(GL_COLOR_BUFFER_BIT);
+    }
+#endif
 }
 
 ///
@@ -4644,6 +4810,26 @@ static int64_t VaapiGetClock(const VaapiDecoder * decoder)
 }
 
 ///
+///	Set VA-API decoder closing stream flag.
+///
+///	@param decoder	VA-API decoder
+///
+static void VaapiSetClosing(VaapiDecoder * decoder)
+{
+    decoder->Closing = 1;
+}
+
+///
+///	Reset start of frame counter.
+///
+///	@param decoder	VA-API decoder
+///
+static void VaapiResetStart(VaapiDecoder * decoder)
+{
+    decoder->StartCounter = 0;
+}
+
+///
 ///	Set trick play speed.
 ///
 ///	@param decoder		VA-API decoder
@@ -4659,6 +4845,24 @@ static void VaapiSetTrickSpeed(VaapiDecoder * decoder, int speed)
 }
 
 ///
+///	Get VA-API decoder statistics.
+///
+///	@param decoder		VA-API decoder
+///	@param[out] missed	missed frames
+///	@param[out] duped	duped frames
+///	@param[out] dropped	dropped frames
+///	@param[out] count	number of decoded frames
+///
+void VaapiGetStats(VaapiDecoder * decoder, int *missed, int *duped,
+    int *dropped, int *counter)
+{
+    *missed = decoder->FramesMissed;
+    *duped = decoder->FramesDuped;
+    *dropped = decoder->FramesDropped;
+    *counter = decoder->FrameCounter;
+}
+
+///
 ///	Sync decoder output to audio.
 ///
 ///	trick-speed	show frame <n> times
@@ -4751,7 +4955,7 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
 	    Debug(3, "video/vaapi: synced after %d frames %dms\n",
 		decoder->StartCounter, GetMsTicks() - VideoSwitch);
 #else
-	    Debug(3, "video/vaapi: synced after %d frames\n",
+	    Info("video/vaapi: synced after %d frames\n",
 		decoder->StartCounter);
 #endif
 	    decoder->StartCounter += 1000;
@@ -5211,11 +5415,17 @@ static const VideoModule VaapiModule = {
 	    AVCodecContext *, const enum PixelFormat *))Vaapi_get_format,
     .RenderFrame = (void (*const) (VideoHwDecoder *,
 	    const AVCodecContext *, const AVFrame *))VaapiSyncRenderFrame,
+    .GetHwAccelContext = (void *(*const)(VideoHwDecoder *))
+	VaapiGetHwAccelContext,
     .SetClock = (void (*const) (VideoHwDecoder *, int64_t))VaapiSetClock,
     .GetClock = (int64_t(*const) (const VideoHwDecoder *))VaapiGetClock,
+    .SetClosing = (void (*const) (const VideoHwDecoder *))VaapiSetClosing,
+    .ResetStart = (void (*const) (const VideoHwDecoder *))VaapiResetStart,
     .SetTrickSpeed =
 	(void (*const) (const VideoHwDecoder *, int))VaapiSetTrickSpeed,
     .GrabOutput = NULL,
+    .GetStats = (void (*const) (VideoHwDecoder *, int *, int *, int *,
+	    int *))VaapiGetStats,
     .SetBackground = VaapiSetBackground,
     .SetVideoMode = VaapiSetVideoMode,
     .ResetAutoCrop = VaapiResetAutoCrop,
@@ -5228,6 +5438,50 @@ static const VideoModule VaapiModule = {
     .Exit = VaapiExit,
 };
 
+#ifdef USE_GLX
+
+///
+///	VA-API module.
+///
+static const VideoModule VaapiGlxModule = {
+    .Name = "va-api-glx",
+    .Enabled = 1,
+    .NewHwDecoder =
+	(VideoHwDecoder * (*const)(VideoStream *)) VaapiNewHwDecoder,
+    .DelHwDecoder = (void (*const) (VideoHwDecoder *))VaapiDelHwDecoder,
+    .GetSurface = (unsigned (*const) (VideoHwDecoder *,
+	    const AVCodecContext *))VaapiGetSurface,
+    .ReleaseSurface =
+	(void (*const) (VideoHwDecoder *, unsigned))VaapiReleaseSurface,
+    .get_format = (enum PixelFormat(*const) (VideoHwDecoder *,
+	    AVCodecContext *, const enum PixelFormat *))Vaapi_get_format,
+    .RenderFrame = (void (*const) (VideoHwDecoder *,
+	    const AVCodecContext *, const AVFrame *))VaapiSyncRenderFrame,
+    .GetHwAccelContext = (void *(*const)(VideoHwDecoder *))
+	VaapiGetHwAccelContext,
+    .SetClock = (void (*const) (VideoHwDecoder *, int64_t))VaapiSetClock,
+    .GetClock = (int64_t(*const) (const VideoHwDecoder *))VaapiGetClock,
+    .SetClosing = (void (*const) (const VideoHwDecoder *))VaapiSetClosing,
+    .ResetStart = (void (*const) (const VideoHwDecoder *))VaapiResetStart,
+    .SetTrickSpeed =
+	(void (*const) (const VideoHwDecoder *, int))VaapiSetTrickSpeed,
+    .GrabOutput = NULL,
+    .GetStats = (void (*const) (VideoHwDecoder *, int *, int *, int *,
+	    int *))VaapiGetStats,
+    .SetBackground = VaapiSetBackground,
+    .SetVideoMode = VaapiSetVideoMode,
+    .ResetAutoCrop = VaapiResetAutoCrop,
+    .DisplayHandlerThread = VaapiDisplayHandlerThread,
+    .OsdClear = GlxOsdClear,
+    .OsdDrawARGB = GlxOsdDrawARGB,
+    .OsdInit = GlxOsdInit,
+    .OsdExit = GlxOsdExit,
+    .Init = VaapiGlxInit,
+    .Exit = VaapiExit,
+};
+
+#endif
+
 #endif
 
 //----------------------------------------------------------------------------
@@ -5271,11 +5525,13 @@ typedef struct _vdpau_decoder_
     int CropHeight;			///< video crop height
 
 #ifdef USE_AUTOCROP
+    void *AutoCropBuffer;		///< auto-crop buffer cache
+    unsigned AutoCropBufferSize;	///< auto-crop buffer size
     AutoCropCtx AutoCrop[1];		///< auto-crop variables
 #endif
 #ifdef noyetUSE_GLX
-    GLuint GlTexture[2];		///< gl texture for VDPAU
-    void *GlxSurface[2];		///< VDPAU/GLX surface
+    GLuint GlTextures[2];		///< gl texture for VDPAU
+    void *GlxSurfaces[2];		///< VDPAU/GLX surface
 #endif
 
     VdpDecoderProfile Profile;		///< vdp decoder profile
@@ -5941,8 +6197,8 @@ static VdpauDecoder *VdpauNewHwDecoder(VideoStream * stream)
     }
     decoder->Device = VdpauDevice;
     decoder->Window = VideoWindow;
-    decoder->VideoX = 0;
-    decoder->VideoY = 0;
+    //decoder->VideoX = 0;		// done by calloc
+    //decoder->VideoY = 0;
     decoder->VideoWidth = VideoWindowWidth;
     decoder->VideoHeight = VideoWindowHeight;
 
@@ -5983,6 +6239,11 @@ static VdpauDecoder *VdpauNewHwDecoder(VideoStream * stream)
 
     decoder->PixFmt = PIX_FMT_NONE;
 
+#ifdef USE_AUTOCROP
+    //decoder->AutoCropBuffer = NULL;	// done by calloc
+    //decoder->AutoCropBufferSize = 0;
+#endif
+
     decoder->Stream = stream;
     if (!VdpauDecoderN) {		// FIXME: hack sync on audio
 	decoder->SyncOnAudio = 1;
@@ -6069,6 +6330,9 @@ static void VdpauDelHwDecoder(VdpauDecoder * decoder)
 
 	    VdpauCleanup(decoder);
 	    VdpauPrintFrames(decoder);
+#ifdef USE_AUTOCROP
+	    free(decoder->AutoCropBuffer);
+#endif
 	    free(decoder);
 
 	    return;
@@ -6741,7 +7005,7 @@ static void VdpauSetupOutput(VdpauDecoder * decoder)
     if (width != (uint32_t) decoder->InputWidth
 	|| height != (uint32_t) decoder->InputHeight) {
 	// FIXME: must rewrite the code to support this case
-	Fatal(_("video/vdpau: video surface size mismatch\n"));
+	Warning(_("video/vdpau: video surface size mismatch\n"));
     }
 }
 
@@ -6831,7 +7095,7 @@ static enum PixelFormat Vdpau_get_format(VdpauDecoder * decoder,
     VdpDecoderProfile profile;
     int max_refs;
 
-    if (!VideoHardwareDecoder || (video_ctx->codec_id == CODEC_ID_MPEG2VIDEO
+    if (!VideoHardwareDecoder || (video_ctx->codec_id == AV_CODEC_ID_MPEG2VIDEO
 	    && VideoHardwareDecoder == 1)
 	) {				// hardware disabled by config
 	Debug(3, "codec: hardware acceleration disabled\n");
@@ -6866,23 +7130,23 @@ static enum PixelFormat Vdpau_get_format(VdpauDecoder * decoder,
     max_refs = CODEC_SURFACES_DEFAULT;
     // check profile
     switch (video_ctx->codec_id) {
-	case CODEC_ID_MPEG1VIDEO:
+	case AV_CODEC_ID_MPEG1VIDEO:
 	    max_refs = CODEC_SURFACES_MPEG2;
 	    profile = VdpauCheckProfile(decoder, VDP_DECODER_PROFILE_MPEG1);
 	    break;
-	case CODEC_ID_MPEG2VIDEO:
+	case AV_CODEC_ID_MPEG2VIDEO:
 	    max_refs = CODEC_SURFACES_MPEG2;
 	    profile =
 		VdpauCheckProfile(decoder, VDP_DECODER_PROFILE_MPEG2_MAIN);
 	    break;
-	case CODEC_ID_MPEG4:
-	case CODEC_ID_H263:
+	case AV_CODEC_ID_MPEG4:
+	case AV_CODEC_ID_H263:
 	    /*
 	       p = VaapiFindProfile(profiles, profile_n,
 	       VAProfileMPEG4AdvancedSimple);
 	     */
 	    goto slow_path;
-	case CODEC_ID_H264:
+	case AV_CODEC_ID_H264:
 	    // FIXME: can calculate level 4.1 limits
 	    // vdpau supports only 16 references
 	    max_refs = 16;
@@ -6914,12 +7178,12 @@ static enum PixelFormat Vdpau_get_format(VdpauDecoder * decoder,
 		    VdpauCheckProfile(decoder, VDP_DECODER_PROFILE_H264_MAIN);
 	    }
 	    break;
-	case CODEC_ID_WMV3:
+	case AV_CODEC_ID_WMV3:
 	    /*
 	       p = VaapiFindProfile(profiles, profile_n, VAProfileVC1Main);
 	     */
 	    goto slow_path;
-	case CODEC_ID_VC1:
+	case AV_CODEC_ID_VC1:
 	    /*
 	       p = VaapiFindProfile(profiles, profile_n, VAProfileVC1Advanced);
 	     */
@@ -7023,6 +7287,7 @@ static void VdpauGrabVideoSurface(VdpauDecoder * decoder)
 	case VDP_CHROMA_TYPE_444:
 	    size = width * height + ((width + 1) / 2) * ((height + 1) / 2)
 		+ ((width + 1) / 2) * ((height + 1) / 2);
+	    // FIXME: can use auto-crop buffer cache
 	    base = malloc(size);
 	    if (!base) {
 		Error(_("video/vdpau: out of memory\n"));
@@ -7095,7 +7360,7 @@ static uint8_t *VdpauGrabOutputSurfaceLocked(int *ret_size, int *ret_width,
     source_rect.y1 = height;
 
     if (ret_width && ret_height) {
-	if (*ret_width <= -64) {	// this is a Atmo grab service request
+	if (*ret_width <= -64) {	// this is an Atmo grab service request
 	    int overscan;
 
 	    // calculate aspect correct size of analyze image
@@ -7143,6 +7408,23 @@ static uint8_t *VdpauGrabOutputSurfaceLocked(int *ret_size, int *ret_width,
 
 	    surface = VdpauGrabRenderSurface;
 	    source_rect = output_rect;
+#if 0
+	    // FIXME: what if VdpauGrabRenderSurface has different sizes
+	    //	get real surface size
+	    status =
+		VdpauOutputSurfaceGetParameters(surface, &rgba_format, &width,
+		&height);
+	    if (status != VDP_STATUS_OK) {
+		Error(_
+		    ("video/vdpau: can't get output surface parameters: %s\n"),
+		    VdpauGetErrorString(status));
+		return NULL;
+	    }
+	    if (width != output_rect.x1 || height != output_rect.y1) {
+		// FIXME: this warning can be removed, is now for debug only
+		Warning(_("video/vdpau: video surface size mismatch\n"));
+	    }
+#endif
 	}
     }
 
@@ -7238,7 +7520,7 @@ static void VdpauAutoCrop(VdpauDecoder * decoder)
     surface = decoder->SurfacesRb[(decoder->SurfaceRead + 1)
 	% VIDEO_SURFACES_MAX];
 
-    //	get real surface size
+    //	get real surface size (can be different)
     status =
 	VdpauVideoSurfaceGetParameters(surface, &chroma_type, &width, &height);
     if (status != VDP_STATUS_OK) {
@@ -7252,7 +7534,13 @@ static void VdpauAutoCrop(VdpauDecoder * decoder)
 	case VDP_CHROMA_TYPE_444:
 	    size = width * height + ((width + 1) / 2) * ((height + 1) / 2)
 		+ ((width + 1) / 2) * ((height + 1) / 2);
-	    base = malloc(size);
+	    // cache buffer for reuse
+	    base = decoder->AutoCropBuffer;
+	    if (size > decoder->AutoCropBufferSize) {
+		free(base);
+		decoder->AutoCropBuffer = malloc(size);
+		base = decoder->AutoCropBuffer;
+	    }
 	    if (!base) {
 		Error(_("video/vdpau: out of memory\n"));
 		return;
@@ -7277,7 +7565,6 @@ static void VdpauAutoCrop(VdpauDecoder * decoder)
     }
 
     AutoCropDetect(decoder->AutoCrop, width, height, data, pitches);
-    free(base);
 
     // ignore black frames
     if (decoder->AutoCrop->Y1 >= decoder->AutoCrop->Y2) {
@@ -7582,6 +7869,7 @@ static void VdpauRenderFrame(VdpauDecoder * decoder,
 	//
 	switch (video_ctx->pix_fmt) {
 	    case PIX_FMT_YUV420P:
+	    case PIX_FMT_YUVJ420P:	// some streams produce this
 		break;
 	    case PIX_FMT_YUV422P:
 	    case PIX_FMT_YUV444P:
@@ -7619,6 +7907,20 @@ static void VdpauRenderFrame(VdpauDecoder * decoder,
 }
 
 ///
+///	Get hwaccel context for ffmpeg.
+///
+///	@param decoder	VDPAU hw decoder
+///
+static void *VdpauGetHwAccelContext(VdpauDecoder * decoder)
+{
+    (void)decoder;
+
+    // FIXME: new ffmpeg versions supports struct AVVDPAUContext
+    Error(_("video: get hwaccel context, not supported\n"));
+    return NULL;
+}
+
+///
 ///	Render osd surface to output surface.
 ///
 static void VdpauMixOsd(void)
@@ -8128,10 +8430,30 @@ static int64_t VdpauGetClock(const VdpauDecoder * decoder)
 }
 
 ///
+///	Set VDPAU decoder closing stream flag.
+///
+///	@param decoder	VDPAU decoder
+///
+static void VdpauSetClosing(VdpauDecoder * decoder)
+{
+    decoder->Closing = 1;
+}
+
+///
+///	Reset start of frame counter.
+///
+///	@param decoder	VDPAU decoder
+///
+static void VdpauResetStart(VdpauDecoder * decoder)
+{
+    decoder->StartCounter = 0;
+}
+
+///
 ///	Set trick play speed.
 ///
-///	@param decoder		VDPAU decoder
-///	@param speed		trick speed (0 = normal)
+///	@param decoder	VDPAU decoder
+///	@param speed	trick speed (0 = normal)
 ///
 static void VdpauSetTrickSpeed(VdpauDecoder * decoder, int speed)
 {
@@ -8143,6 +8465,24 @@ static void VdpauSetTrickSpeed(VdpauDecoder * decoder, int speed)
 }
 
 ///
+///	Get VDPAU decoder statistics.
+///
+///	@param decoder		VDPAU decoder
+///	@param[out] missed	missed frames
+///	@param[out] duped	duped frames
+///	@param[out] dropped	dropped frames
+///	@param[out] count	number of decoded frames
+///
+void VdpauGetStats(VdpauDecoder * decoder, int *missed, int *duped,
+    int *dropped, int *counter)
+{
+    *missed = decoder->FramesMissed;
+    *duped = decoder->FramesDuped;
+    *dropped = decoder->FramesDropped;
+    *counter = decoder->FrameCounter;
+}
+
+///
 ///	Sync decoder output to audio.
 ///
 ///	trick-speed	show frame <n> times
@@ -8240,7 +8580,7 @@ static void VdpauSyncDecoder(VdpauDecoder * decoder)
 	    Debug(3, "video/vdpau: synced after %d frames %dms\n",
 		decoder->StartCounter, GetMsTicks() - VideoSwitch);
 #else
-	    Debug(3, "video/vdpau: synced after %d frames\n",
+	    Info("video/vdpau: synced after %d frames\n",
 		decoder->StartCounter);
 #endif
 	    decoder->StartCounter += 1000;
@@ -8840,11 +9180,17 @@ static const VideoModule VdpauModule = {
 	    AVCodecContext *, const enum PixelFormat *))Vdpau_get_format,
     .RenderFrame = (void (*const) (VideoHwDecoder *,
 	    const AVCodecContext *, const AVFrame *))VdpauSyncRenderFrame,
+    .GetHwAccelContext = (void *(*const)(VideoHwDecoder *))
+	VdpauGetHwAccelContext,
     .SetClock = (void (*const) (VideoHwDecoder *, int64_t))VdpauSetClock,
     .GetClock = (int64_t(*const) (const VideoHwDecoder *))VdpauGetClock,
+    .SetClosing = (void (*const) (const VideoHwDecoder *))VdpauSetClosing,
+    .ResetStart = (void (*const) (const VideoHwDecoder *))VdpauResetStart,
     .SetTrickSpeed =
 	(void (*const) (const VideoHwDecoder *, int))VdpauSetTrickSpeed,
     .GrabOutput = VdpauGrabOutputSurface,
+    .GetStats = (void (*const) (VideoHwDecoder *, int *, int *, int *,
+	    int *))VdpauGetStats,
     .SetBackground = VdpauSetBackground,
     .SetVideoMode = VdpauSetVideoMode,
     .ResetAutoCrop = VdpauResetAutoCrop,
@@ -8995,11 +9341,17 @@ static const VideoModule NoopModule = {
 	    AVCodecContext *, const enum PixelFormat *))Noop_get_format,
     .RenderFrame = (void (*const) (VideoHwDecoder *,
 	    const AVCodecContext *, const AVFrame *))NoopSyncRenderFrame,
+    .GetHwAccelContext = (void *(*const)(VideoHwDecoder *))
+	DummyGetHwAccelContext,
     .SetClock = (void (*const) (VideoHwDecoder *, int64_t))NoopSetClock,
     .GetClock = (int64_t(*const) (const VideoHwDecoder *))NoopGetClock,
+    .SetClosing = (void (*const) (const VideoHwDecoder *))NoopSetClosing,
+    .ResetStart = (void (*const) (const VideoHwDecoder *))NoopResetStart,
     .SetTrickSpeed =
 	(void (*const) (const VideoHwDecoder *, int))NoopSetTrickSpeed,
     .GrabOutput = NoopGrabOutputSurface,
+    .GetStats = (void (*const) (VideoHwDecoder *, int *, int *, int *,
+	    int *))NoopGetStats,
 #endif
     .SetBackground = NoopSetBackground,
     .SetVideoMode = NoopVoid,
@@ -9026,26 +9378,9 @@ static const VideoModule NoopModule = {
 void VideoOsdClear(void)
 {
     VideoThreadLock();
-#ifdef USE_GLX
-    if (GlxEnabled) {
-	void *texbuf;
-
-	texbuf = calloc(OsdWidth * OsdHeight, 4);
-	glEnable(GL_TEXTURE_2D);	// 2d texture
-	glBindTexture(GL_TEXTURE_2D, OsdGlTextures[OsdIndex]);
-	// upload no image data, clears texture (on some drivers only)
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, OsdWidth, OsdHeight, 0,
-	    GL_BGRA, GL_UNSIGNED_BYTE, texbuf);
-	glBindTexture(GL_TEXTURE_2D, 0);
-	glDisable(GL_TEXTURE_2D);
-	GlxCheck();
-	free(texbuf);
-    }
-#endif
-
     VideoUsedModule->OsdClear();
 
-    OsdDirtyX = OsdWidth;
+    OsdDirtyX = OsdWidth;		// reset dirty area
     OsdDirtyY = OsdHeight;
     OsdDirtyWidth = 0;
     OsdDirtyHeight = 0;
@@ -9089,14 +9424,6 @@ void VideoOsdDrawARGB(int x, int y, int width, int height,
     Debug(4, "video: osd dirty %dx%d%+d%+d -> %dx%d%+d%+d\n", width, height, x,
 	y, OsdDirtyWidth, OsdDirtyHeight, OsdDirtyX, OsdDirtyY);
 
-#ifdef USE_GLX
-    if (GlxEnabled) {
-	Debug(3, "video: %p <-> %p\n", glXGetCurrentContext(), GlxContext);
-	GlxUploadTexture(x, y, height, width, argb);
-	VideoThreadUnlock();
-	return;
-    }
-#endif
     VideoUsedModule->OsdDrawARGB(x, y, width, height, argb);
     OsdShown = 1;
 
@@ -9160,38 +9487,6 @@ void VideoOsdInit(void)
 	OsdHeight = VideoWindowHeight;
     }
 
-#ifdef USE_GLX
-    // FIXME: make an extra function for this
-    if (GlxEnabled) {
-	int i;
-
-	Debug(3, "video/glx: %p <-> %p\n", glXGetCurrentContext(), GlxContext);
-
-	//
-	//  create a RGBA texture.
-	//
-	glEnable(GL_TEXTURE_2D);	// create 2d texture(s)
-
-	glGenTextures(2, OsdGlTextures);
-	for (i = 0; i < 2; ++i) {
-	    glBindTexture(GL_TEXTURE_2D, OsdGlTextures[i]);
-	    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-	    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-	    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_RGBA8, OsdWidth, OsdHeight, 0,
-		GL_BGRA, GL_UNSIGNED_BYTE, NULL);
-	}
-	glBindTexture(GL_TEXTURE_2D, 0);
-
-	glDisable(GL_TEXTURE_2D);
-	return;
-    }
-#endif
-
     VideoThreadLock();
     VideoUsedModule->OsdInit(OsdWidth, OsdHeight);
     VideoThreadUnlock();
@@ -9210,84 +9505,6 @@ void VideoOsdExit(void)
     OsdDirtyHeight = 0;
 }
 
-#if 0
-
-//----------------------------------------------------------------------------
-//	Overlay
-//----------------------------------------------------------------------------
-
-///
-///	Render osd surface.
-///
-void VideoRenderOverlay(void)
-{
-#ifdef USE_GLX
-    if (GlxEnabled) {
-	GlxRender(OsdWidth, OsdHeight);
-    } else
-#endif
-    {
-    }
-}
-
-///
-///	Display overlay surface.
-///
-void VideoDisplayOverlay(void)
-{
-#ifdef USE_GLX
-    if (GlxEnabled) {
-	int osd_x1;
-	int osd_y1;
-
-	osd_x1 = 0;
-	osd_y1 = 0;
-#ifdef noDEBUG
-	osd_x1 = 100;
-	osd_y1 = 100;
-#endif
-	GlxRenderTexture(OsdGlTextures[OsdIndex], osd_x1, osd_y1,
-	    VideoWindowWidth, VideoWindowHeight);
-	return;
-    }
-#endif
-#ifdef USE_VAAPI
-    {
-	void *image_buffer;
-	static int counter;
-
-	// upload needs long time
-	if (counter == 5) {
-	    //return;
-	}
-	// osd image available?
-	if (VaOsdImage.image_id == VA_INVALID_ID) {
-	    return;
-	}
-	// FIXME: this version hangups
-	//return;
-
-	// map osd surface/image into memory.
-	if (vaMapBuffer(VaDisplay, VaOsdImage.buf,
-		&image_buffer) != VA_STATUS_SUCCESS) {
-	    Error(_("video/vaapi: can't map osd image buffer\n"));
-	    return;
-	}
-	// 100% transparent
-	memset(image_buffer, 0x80 | counter++, VaOsdImage.data_size);
-
-	// convert internal osd to VA-API image
-	//GfxConvert(image_buffer, VaOsdImage.offsets[0], VaOsdImage.pitches[0]);
-
-	if (vaUnmapBuffer(VaDisplay, VaOsdImage.buf) != VA_STATUS_SUCCESS) {
-	    Error(_("video/vaapi: can't unmap osd image buffer\n"));
-	}
-    }
-#endif
-}
-
-#endif
-
 //----------------------------------------------------------------------------
 //	Events
 //----------------------------------------------------------------------------
@@ -9339,7 +9556,9 @@ static void VideoEvent(void)
     char buf[64];
     uint32_t values[1];
 
+    VideoThreadLock();
     XNextEvent(XlibDisplay, &event);
+    VideoThreadUnlock();
     switch (event.type) {
 	case ClientMessage:
 	    Debug(3, "video/event: ClientMessage\n");
@@ -9352,8 +9571,10 @@ static void VideoEvent(void)
 	case MapNotify:
 	    Debug(3, "video/event: MapNotify\n");
 	    // �wm workaround
+	    VideoThreadLock();
 	    xcb_change_window_attributes(Connection, VideoWindow,
 		XCB_CW_CURSOR, &VideoBlankCursor);
+	    VideoThreadUnlock();
 	    VideoBlankTick = 0;
 	    break;
 	case Expose:
@@ -9371,13 +9592,17 @@ static void VideoEvent(void)
 	    VideoSetFullscreen(-1);
 	    break;
 	case KeyPress:
+	    VideoThreadLock();
 	    XLookupString(&event.xkey, buf, sizeof(buf), &keysym, NULL);
+	    VideoThreadUnlock();
 	    if (keysym == NoSymbol) {
 		Warning(_("video/event: No symbol for %d\n"),
 		    event.xkey.keycode);
 		break;
 	    }
+	    VideoThreadLock();
 	    keynam = XKeysymToString(keysym);
+	    VideoThreadUnlock();
 	    // check for key modifiers (Alt/Ctrl)
 	    if (event.xkey.state & (Mod1Mask | ControlMask)) {
 		if (event.xkey.state & Mod1Mask) {
@@ -9397,8 +9622,10 @@ static void VideoEvent(void)
 	    break;
 	case MotionNotify:
 	    values[0] = XCB_NONE;
+	    VideoThreadLock();
 	    xcb_change_window_attributes(Connection, VideoWindow,
 		XCB_CW_CURSOR, values);
+	    VideoThreadUnlock();
 	    VideoBlankTick = GetMsTicks();
 	    break;
 	default:
@@ -9420,11 +9647,19 @@ void VideoPollEvent(void)
     // hide cursor, after xx ms
     if (VideoBlankTick && VideoWindow != XCB_NONE
 	&& VideoBlankTick + 200 < GetMsTicks()) {
+	VideoThreadLock();
 	xcb_change_window_attributes(Connection, VideoWindow, XCB_CW_CURSOR,
 	    &VideoBlankCursor);
+	VideoThreadUnlock();
 	VideoBlankTick = 0;
     }
-    while (XlibDisplay && XPending(XlibDisplay)) {
+    while (XlibDisplay) {
+	VideoThreadLock();
+	if (!XPending(XlibDisplay)) {
+	    VideoThreadUnlock();
+	    break;
+	}
+	VideoThreadUnlock();
 	VideoEvent();
     }
 }
@@ -9435,10 +9670,6 @@ void VideoPollEvent(void)
 
 #ifdef USE_VIDEO_THREAD
 
-#ifdef USE_GLX
-static GLXContext GlxThreadContext;	///< our gl context for the thread
-#endif
-
 ///
 ///	Lock video thread.
 ///
@@ -9472,20 +9703,21 @@ static void *VideoDisplayHandlerThread(void *dummy)
 
 #ifdef USE_GLX
     if (GlxEnabled) {
-	Debug(3, "video: %p <-> %p\n", glXGetCurrentContext(),
-	    GlxThreadContext);
+	Debug(3, "video/glx: thread context %p <-> %p\n",
+	    glXGetCurrentContext(), GlxThreadContext);
+	Debug(3, "video/glx: context %p <-> %p\n", glXGetCurrentContext(),
+	    GlxContext);
+
 	GlxThreadContext =
-	    glXCreateContext(XlibDisplay, GlxVisualInfo, GlxContext, GL_TRUE);
+	    glXCreateContext(XlibDisplay, GlxVisualInfo, GlxSharedContext,
+	    GL_TRUE);
 	if (!GlxThreadContext) {
 	    Error(_("video/glx: can't create glx context\n"));
 	    return NULL;
 	}
 	// set glx context
-	if (!glXMakeCurrent(XlibDisplay, VideoWindow, GlxThreadContext)) {
-	    GlxCheck();
-	    Error(_("video/glx: can't make glx context current\n"));
-	    return NULL;
-	}
+	GlxSetupWindow(VideoWindow, VideoWindowWidth, VideoWindowHeight,
+	    GlxThreadContext);
     }
 #endif
 
@@ -9508,6 +9740,9 @@ static void *VideoDisplayHandlerThread(void *dummy)
 ///
 static void VideoThreadInit(void)
 {
+#ifdef USE_GLX
+    glXMakeCurrent(XlibDisplay, None, NULL);
+#endif
     pthread_mutex_init(&VideoMutex, NULL);
     pthread_mutex_init(&VideoLockMutex, NULL);
     pthread_cond_init(&VideoWakeupCond, NULL);
@@ -9565,7 +9800,7 @@ void VideoDisplayWakeup(void)
 //----------------------------------------------------------------------------
 
 ///
-///	Table of all audio modules.
+///	Table of all video modules.
 ///
 static const VideoModule *VideoModules[] = {
 #ifdef USE_VDPAU
@@ -9574,6 +9809,9 @@ static const VideoModule *VideoModules[] = {
 #ifdef USE_VAAPI
     &VaapiModule,
 #endif
+#ifdef USE_GLX
+    &VaapiGlxModule,			// FIXME: if working, prefer this
+#endif
     &NoopModule
 };
 
@@ -9707,20 +9945,15 @@ void VideoRenderFrame(VideoHwDecoder * hw_decoder,
 }
 
 ///
-///	Get VA-API ffmpeg context
+///	Get hwaccel context for ffmpeg.
+///
+///	FIXME: new ffmpeg supports vdpau hw context
 ///
 ///	@param hw_decoder	video hardware decoder (must be VA-API)
 ///
-struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder * hw_decoder)
+void *VideoGetHwAccelContext(VideoHwDecoder * hw_decoder)
 {
-#ifdef USE_VAAPI
-    if (VideoUsedModule == &VaapiModule) {
-	return hw_decoder->Vaapi.VaapiContext;
-    }
-#endif
-    (void)hw_decoder;
-    Error(_("video/vaapi: get vaapi context, without vaapi enabled\n"));
-    return NULL;
+    return VideoUsedModule->GetHwAccelContext(hw_decoder);
 }
 
 #ifdef USE_VDPAU
@@ -9823,17 +10056,7 @@ int64_t VideoGetClock(const VideoHwDecoder * hw_decoder)
 void VideoSetClosing(VideoHwDecoder * hw_decoder)
 {
     Debug(3, "video: set closing\n");
-    // FIXME: test to check if working, than make module function
-#ifdef USE_VDPAU
-    if (VideoUsedModule == &VdpauModule) {
-	hw_decoder->Vdpau.Closing = 1;
-    }
-#endif
-#ifdef USE_VAAPI
-    if (VideoUsedModule == &VaapiModule) {
-	hw_decoder->Vaapi.Closing = 1;
-    }
-#endif
+    VideoUsedModule->SetClosing(hw_decoder);
     // clear clock to avoid further sync
     VideoSetClock(hw_decoder, AV_NOPTS_VALUE);
 }
@@ -9846,17 +10069,7 @@ void VideoSetClosing(VideoHwDecoder * hw_decoder)
 void VideoResetStart(VideoHwDecoder * hw_decoder)
 {
     Debug(3, "video: reset start\n");
-    // FIXME: test to check if working, than make module function
-#ifdef USE_VDPAU
-    if (VideoUsedModule == &VdpauModule) {
-	hw_decoder->Vdpau.StartCounter = 0;
-    }
-#endif
-#ifdef USE_VAAPI
-    if (VideoUsedModule == &VaapiModule) {
-	hw_decoder->Vaapi.StartCounter = 0;
-    }
-#endif
+    VideoUsedModule->ResetStart(hw_decoder);
     // clear clock to trigger new video stream
     VideoSetClock(hw_decoder, AV_NOPTS_VALUE);
 }
@@ -9869,7 +10082,8 @@ void VideoResetStart(VideoHwDecoder * hw_decoder)
 ///
 void VideoSetTrickSpeed(VideoHwDecoder * hw_decoder, int speed)
 {
-    return VideoUsedModule->SetTrickSpeed(hw_decoder, speed);
+    Debug(3, "video: set trick-speed %d\n", speed);
+    VideoUsedModule->SetTrickSpeed(hw_decoder, speed);
 }
 
 ///
@@ -10029,23 +10243,7 @@ uint8_t *VideoGrabService(int *size, int *width, int *height)
 void VideoGetStats(VideoHwDecoder * hw_decoder, int *missed, int *duped,
     int *dropped, int *counter)
 {
-    // FIXME: test to check if working, than make module function
-#ifdef USE_VDPAU
-    if (VideoUsedModule == &VdpauModule) {
-	*missed = hw_decoder->Vdpau.FramesMissed;
-	*duped = hw_decoder->Vdpau.FramesDuped;
-	*dropped = hw_decoder->Vdpau.FramesDropped;
-	*counter = hw_decoder->Vdpau.FrameCounter;
-    }
-#endif
-#ifdef USE_VAAPI
-    if (VideoUsedModule == &VaapiModule) {
-	*missed = hw_decoder->Vaapi.FramesMissed;
-	*duped = hw_decoder->Vaapi.FramesDuped;
-	*dropped = hw_decoder->Vaapi.FramesDropped;
-	*counter = hw_decoder->Vaapi.FrameCounter;
-    }
-#endif
+    VideoUsedModule->GetStats(hw_decoder, missed, duped, dropped, counter);
 }
 
 ///
@@ -10413,6 +10611,7 @@ void VideoSetBlackPicture(int onoff)
 ///
 void VideoSetBrightness(int brightness)
 {
+    // FIXME: test to check if working, than make module function
 #ifdef USE_VDPAU
     if (VideoUsedModule == &VdpauModule) {
 	VdpauDecoders[0]->Procamp.brightness = brightness / 1000;
@@ -10430,6 +10629,7 @@ void VideoSetBrightness(int brightness)
 ///
 void VideoSetContrast(int contrast)
 {
+    // FIXME: test to check if working, than make module function
 #ifdef USE_VDPAU
     if (VideoUsedModule == &VdpauModule) {
 	VdpauDecoders[0]->Procamp.contrast = contrast / 1000;
@@ -10447,6 +10647,7 @@ void VideoSetContrast(int contrast)
 ///
 void VideoSetSaturation(int saturation)
 {
+    // FIXME: test to check if working, than make module function
 #ifdef USE_VDPAU
     if (VideoUsedModule == &VdpauModule) {
 	VdpauDecoders[0]->Procamp.saturation = saturation / 1000;
@@ -10464,6 +10665,7 @@ void VideoSetSaturation(int saturation)
 ///
 void VideoSetHue(int hue)
 {
+    // FIXME: test to check if working, than make module function
 #ifdef USE_VDPAU
     if (VideoUsedModule == &VdpauModule) {
 	VdpauDecoders[0]->Procamp.hue = hue / 1000;
@@ -10861,7 +11063,12 @@ void VideoInit(const char *display_name)
 	// FIXME: we need to retry connection
 	return;
     }
-    //XInitThreads();
+#ifdef USE_GLX_not_needed_done_with_locks
+    if (!XInitThreads()) {
+	Error(_("video: Can't initialize X11 thread support on '%s'\n"),
+	    display_name);
+    }
+#endif
     // Register error handler
     XSetIOErrorHandler(VideoIOErrorHandler);
 
@@ -10873,7 +11080,9 @@ void VideoInit(const char *display_name)
     }
     // prefetch extensions
     //xcb_prefetch_extension_data(Connection, &xcb_big_requests_id);
-    //xcb_prefetch_extension_data(Connection, &xcb_glx_id);
+#ifdef xcb_USE_GLX
+    xcb_prefetch_extension_data(Connection, &xcb_glx_id);
+#endif
     //xcb_prefetch_extension_data(Connection, &xcb_randr_id);
 #ifdef USE_SCREENSAVER
     xcb_prefetch_extension_data(Connection, &xcb_screensaver_id);
@@ -10909,13 +11118,15 @@ void VideoInit(const char *display_name)
     //	prepare opengl
     //
 #ifdef USE_GLX
-    if (GlxEnabled) {
+    // FIXME: module selected below
+    if (0) {
 
 	GlxInit();
 	// FIXME: use root window?
 	VideoCreateWindow(screen->root, GlxVisualInfo->visualid,
 	    GlxVisualInfo->depth);
-	GlxSetupWindow(VideoWindow, VideoWindowWidth, VideoWindowHeight);
+	GlxSetupWindow(VideoWindow, VideoWindowWidth, VideoWindowHeight,
+	    GlxContext);
     } else
 #endif
 
@@ -10962,9 +11173,6 @@ void VideoInit(const char *display_name)
     if (getenv("NO_HW")) {
 	VideoHardwareDecoder = 0;
     }
-    if (getenv("STUDIO_LEVELS")) {
-	VideoStudioLevels = 1;
-    }
     // disable x11 screensaver
     X11SuspendScreenSaver(Connection, 1);
     X11DPMSDisable(Connection);
@@ -11174,16 +11382,6 @@ int main(int argc, char *const argv[])
     start_tick = GetMsTicks();
     n = 0;
     for (;;) {
-#if 0
-	VideoRenderOverlay();
-	VideoDisplayOverlay();
-	glXSwapBuffers(XlibDisplay, VideoWindow);
-	GlxCheck();
-	glClear(GL_COLOR_BUFFER_BIT);
-
-	XSync(XlibDisplay, False);
-	XFlush(XlibDisplay);
-#endif
 #ifdef USE_VAAPI
 	if (VideoVaapiEnabled) {
 	    VaapiDisplayFrame();
diff --git a/video.h b/video.h
index 910b14e..fa3e44f 100644
--- a/video.h
+++ b/video.h
@@ -17,7 +17,7 @@
 ///	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ///	GNU Affero General Public License for more details.
 ///
-///	$Id: 08681699eb8e70b5bc9dce5e58c79dae5e67f41f $
+///	$Id$
 //////////////////////////////////////////////////////////////////////////////
 
 /// @addtogroup Video
@@ -67,8 +67,8 @@ extern enum PixelFormat Video_get_format(VideoHwDecoder *, AVCodecContext *,
 extern void VideoRenderFrame(VideoHwDecoder *, const AVCodecContext *,
     const AVFrame *);
 
-    /// Get ffmpeg vaapi context.
-extern struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder *);
+    /// Get hwaccel context for ffmpeg.
+extern void *VideoGetHwAccelContext(VideoHwDecoder *);
 
 #ifdef AVCODEC_VDPAU_H
     /// Draw vdpau render state.

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-vdr-dvb/vdr-plugin-softhddevice.git



More information about the pkg-vdr-dvb-changes mailing list