[vdr-plugin-softhddevice] 01/04: Imported Upstream version 0.6.0+git20140727

Tobias Grimm tiber-guest at moszumanska.debian.org
Sun Jul 27 20:59:55 UTC 2014


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 08d8b38e873ab1bd71b06a4189645d6fcac385f7
Author: etobi <git at e-tobi.net>
Date:   Sun Jul 27 22:45:29 2014 +0200

    Imported Upstream version 0.6.0+git20140727
---
 ChangeLog                              |  56 ++++++++
 Makefile                               |  14 +-
 Makefile-pre1.7.36                     | 188 ------------------------
 README.txt                             |   6 +-
 Todo                                   |   2 +
 audio.c                                |  77 ++++++++--
 audio.h                                |   5 +-
 codec.c                                | 118 +++++++++++++--
 iatomic.h                              |  97 +++++++++++++
 po/de_DE.po                            |  30 +++-
 ringbuffer.c                           |   5 +-
 softhddev.c                            | 176 ++++++++++++-----------
 softhddev.h                            |   5 +-
 softhddevice.cpp                       | 141 +++++++++++++-----
 softhddevice.h                         |   2 +-
 vdr-softhddevice-9999-pre1.7.36.ebuild |  74 ----------
 vdr-softhddevice-9999.ebuild           |  86 +++++------
 video.c                                | 255 ++++++++++++++++++++++++++++-----
 18 files changed, 841 insertions(+), 496 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 990891c..a611b32 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,62 @@
 User johns
 Date:
 
+    Config for automatic AES parameters.
+    Use GCC built-in functions for atomic operations.
+
+User master_red
+Date: Wed Jun  4 14:44:32 CEST 2014
+
+    Support detach or suspend in plugin menu.
+
+User johns
+Date:  Fri May 30 10:18:20 CEST 2014
+
+    Fix "make clean-plugins".
+    Fix compile with newer libav.
+    Fix OSD bugs.
+    Add some VA-API VPP info outputs.
+    Remove build files for old unstable VDR.
+
+User  hd.brummy
+Date: Thu Jan 30 10:40:49 CET 2014
+
+    Update gentoo ebuild.
+
+User johns
+Date: Thu Jan 30 10:36:53 CET 2014
+
+    Fix spelling in arguments help.
+    Add Workaround for alsa blocking audio device.
+    Improves thread handling for audio flush and close.
+
+User mini73
+Date: Fri Jan 24 11:30:49 CET 2014
+
+    Fix bug: learing x11 remote keys fails.
+    Add support for umlauts in input fields.
+
+User johns
+Date: Tue Jan 14 14:59:44 CET 2014
+
+    Fix alternative OSD support with VDPAU bitmap surfaces.
+    Fix compile error with VDR 2.1.3.
+    Fix bug: memory leak.
+    PIP close clears the last used PIP channel.
+    Fix bug: -DOSD_DEBUG uses old (deleted) variable.
+    Fix bug: Option softhddevice.BlackPicture has no effect.
+
+User Dr. Seltsam
+Date: Tue Nov  5 16:46:34 CET 2013
+
+    Add support to configure and clear buffers on channel switch.
+
+User johns
+Date: Tue Oct  8 10:18:04 CET 2013
+
+    CLOCK_REALTIME -> CLOCK_MONOTONIC to allow time changes.
+    Add function VideoStreamOpen and always use VideoStreamClose.
+    Softer audio/video sync.
     Add function GetStats to the video output module.
     Add function ResetStart to the video output module.
     Add function SetClosing to the video output module.
diff --git a/Makefile b/Makefile
index 03a86be..187a917 100644
--- a/Makefile
+++ b/Makefile
@@ -25,6 +25,10 @@ VDPAU ?= $(shell pkg-config --exists vdpau && echo 1)
 SCREENSAVER ?= 1
     # use ffmpeg libswresample
 SWRESAMPLE ?= $(shell pkg-config --exists libswresample && echo 1)
+    # use libav libavresample
+ifneq ($(SWRESAMPLE),1)
+AVRESAMPLE ?= $(shell pkg-config --exists libavresample && echo 1)
+endif
 
 CONFIG := # -DDEBUG #-DOSD_DEBUG	# enable debug output+functions
 #CONFIG += -DSTILL_DEBUG=2		# still picture debug verbose level
@@ -37,6 +41,7 @@ CONFIG += -DUSE_PIP			# PIP support
 #CONFIG += -DUSE_MPEG_COMPLETE		# support only complete mpeg packets
 #CONFIG += -DH264_EOS_TRICKSPEED	# insert seq end packets for trickspeed
 #CONDIF += -DDUMP_TRICKSPEED		# dump trickspeed packets
+#CONFIG += -DUSE_BITMAP			# VDPAU, use bitmap surface for OSD
 CONFIG += -DUSE_VDR_SPU			# use VDR SPU decoder.
 #CONFIG += -DUSE_SOFTLIMIT		# (tobe removed) limit the buffer fill
 
@@ -77,6 +82,11 @@ CONFIG += -DUSE_SWRESAMPLE
 _CFLAGS += $(shell pkg-config --cflags libswresample)
 LIBS += $(shell pkg-config --libs libswresample)
 endif
+ifeq ($(AVRESAMPLE),1)
+CONFIG += -DUSE_AVRESAMPLE
+_CFLAGS += $(shell pkg-config --cflags libavresample)
+LIBS += $(shell pkg-config --libs libavresample)
+endif
 
 _CFLAGS += $(shell pkg-config --cflags libavcodec x11 x11-xcb xcb xcb-icccm)
 LIBS += -lrt $(shell pkg-config --libs libavcodec x11 x11-xcb xcb xcb-icccm)
@@ -102,10 +112,10 @@ export CFLAGS	= $(call PKGCFG,cflags)
 export CXXFLAGS = $(call PKGCFG,cxxflags)
 
 ifeq ($(CFLAGS),)
-$(error CFLAGS not set)
+$(warning CFLAGS not set)
 endif
 ifeq ($(CXXFLAGS),)
-$(error CXXFLAGS not set)
+$(warning CXXFLAGS not set)
 endif
 
 ### The version number of VDR's plugin API:
diff --git a/Makefile-pre1.7.36 b/Makefile-pre1.7.36
deleted file mode 100644
index 32b94a6..0000000
--- a/Makefile-pre1.7.36
+++ /dev/null
@@ -1,188 +0,0 @@
-#
-# Makefile for a Video Disk Recorder plugin
-#
-# $Id$
-
-# The official name of this plugin.
-# This name will be used in the '-P...' option of VDR to load the plugin.
-# By default the main source file also carries this name.
-# IMPORTANT: the presence of this macro is important for the Make.config
-# file. So it must be defined, even if it is not used here!
-#
-PLUGIN = softhddevice
-
-### The version number of this plugin (taken from the main source file):
-
-VERSION = $(shell grep 'static const char \*const VERSION *=' $(PLUGIN).cpp | awk '{ print $$7 }' | sed -e 's/[";]//g')
-GIT_REV = $(shell git describe --always 2>/dev/null)
-
-### Configuration (edit this for your needs)
-
-CONFIG := #-DDEBUG #-DOSD_DEBUG
-CONFIG += -DAV_INFO -DAV_INFO_TIME=3000	# debug a/v sync
-CONFIG += -DUSE_PIP			# PIP support
-#CONFIG += -DHAVE_PTHREAD_NAME		# supports new pthread_setname_np
-#CONFIG += -DNO_TS_AUDIO		# disable ts audio parser
-#CONFIG += -DUSE_TS_VIDEO		# build new ts video parser
-					# use ffmpeg libswresample
-CONFIG += $(shell pkg-config --exists libswresample && echo "-DUSE_SWRESAMPLE")
-CONFIG += -DUSE_SCREENSAVER		# use functions to disable screensaver
-CONFIG += $(shell pkg-config --exists vdpau && echo "-DUSE_VDPAU")
-CONFIG += $(shell pkg-config --exists libva && echo "-DUSE_VAAPI")
-CONFIG += $(shell pkg-config --exists alsa && echo "-DUSE_ALSA")
-CONFIG += -DUSE_OSS
-
-### The C++ compiler and options:
-
-CC	 ?= gcc
-CXX	 ?= g++
-CFLAGS	 ?=	-g -O2 -W -Wall -Wextra -Winit-self \
-		-Wdeclaration-after-statement \
-		-ftree-vectorize -msse3 -flax-vector-conversions -fPIC
-CXXFLAGS ?= -g -O2 -W -Wall -Wextra -Werror=overloaded-virtual -fPIC
-
-### The directory environment:
-
-VDRDIR ?= ../../..
-LIBDIR ?= ../../lib
-TMPDIR ?= /tmp
-
-### Make sure that necessary options are included:
-
--include $(VDRDIR)/Make.global
-
-### Allow user defined options to overwrite defaults:
-
--include $(VDRDIR)/Make.config
-
-### The version number of VDR's plugin API (taken from VDR's "config.h"):
-
-APIVERSION = $(shell sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h)
-
-### The name of the distribution archive:
-
-ARCHIVE = $(PLUGIN)-$(VERSION)
-PACKAGE = vdr-$(ARCHIVE)
-
-### Includes, Defines and dependencies (add further entries here):
-
-INCLUDES += -I$(VDRDIR)/include
-
-DEFINES += $(CONFIG) -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' \
-	$(if $(GIT_REV), -DGIT_REV='"$(GIT_REV)"')
-
-_CFLAGS = $(DEFINES) $(INCLUDES) \
-	$(shell pkg-config --cflags libavcodec) \
-	`pkg-config --cflags x11 x11-xcb xcb xcb-xv xcb-shm xcb-dpms xcb-atom\
-		xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\
-	`pkg-config --cflags gl glu` \
-	$(if $(findstring USE_SWRESAMPLE,$(CONFIG)), \
-		$(shell pkg-config --cflags libswresample)) \
-	$(if $(findstring USE_VAAPI,$(CONFIG)), \
-		`pkg-config --cflags libva-x11 libva-glx libva`) \
-	$(if $(findstring USE_ALSA,$(CONFIG)), \
-		`pkg-config --cflags alsa`)
-
-#override _CFLAGS  += -Werror
-override CXXFLAGS += $(_CFLAGS)
-override CFLAGS	  += $(_CFLAGS)
-
-LIBS += -lrt \
-	$(shell pkg-config --libs libavcodec) \
-	`pkg-config --libs x11 x11-xcb xcb xcb-xv xcb-shm xcb-dpms xcb-atom\
-		xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\
-	`pkg-config --libs gl glu` \
-	$(if $(findstring USE_SWRESAMPLE,$(CONFIG)), \
-		$(shell pkg-config --libs libswresample)) \
-	$(if $(findstring USE_VDPAU,$(CONFIG)), \
-		`pkg-config --libs vdpau`) \
-	$(if $(findstring USE_VAAPI,$(CONFIG)), \
-		`pkg-config --libs libva-x11 libva-glx libva`) \
-	$(if $(findstring USE_ALSA,$(CONFIG)), \
-		`pkg-config --libs alsa`)
-
-### The object files (add further files here):
-
-OBJS = $(PLUGIN).o softhddev.o video.o audio.o codec.o ringbuffer.o
-SRCS = $(wildcard $(OBJS:.o=.c)) $(PLUGIN).cpp
-
-### The main target:
-
-all: libvdr-$(PLUGIN).so i18n
-
-### Implicit rules:
-#
-#%.o: %.cpp
-#	$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
-
-### Dependencies:
-
-MAKEDEP = $(CC) -MM -MG
-DEPFILE = .dependencies
-$(DEPFILE): Makefile
-	@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(SRCS) >$@
-
-$(OBJS): Makefile
-
--include $(DEPFILE)
-
-### Internationalization (I18N):
-
-PODIR	  = po
-LOCALEDIR = $(VDRDIR)/locale
-I18Npo	  = $(wildcard $(PODIR)/*.po)
-I18Nmsgs  = $(addprefix $(LOCALEDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file))))))
-I18Npot	  = $(PODIR)/$(PLUGIN).pot
-
-%.mo: %.po
-	msgfmt -c -o $@ $<
-
-$(I18Npot): $(wildcard *.cpp) $(wildcard *.c)
-	xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP \
-	-k_ -k_N --package-name=VDR --package-version=$(VDRVERSION) \
-	--msgid-bugs-address='<see README>' -o $@ $^
-
-%.po: $(I18Npot)
-	msgmerge -U --no-wrap --no-location --backup=none -q $@ $<
-	@touch $@
-
-$(I18Nmsgs): $(LOCALEDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
-	@mkdir -p $(dir $@)
-	cp $< $@
-
-.PHONY: i18n
-i18n: $(I18Nmsgs) $(I18Npot)
-
-### Targets:
-
-libvdr-$(PLUGIN).so: $(OBJS) Makefile
-	$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -fPIC $(OBJS) -o $@ $(LIBS)
-	@cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION)
-
-dist: $(I18Npo) clean
-	@-rm -rf $(TMPDIR)/$(ARCHIVE)
-	@mkdir $(TMPDIR)/$(ARCHIVE)
-	@cp -a * $(TMPDIR)/$(ARCHIVE)
-	@tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE)
-	@-rm -rf $(TMPDIR)/$(ARCHIVE)
-	@echo Distribution package created as $(PACKAGE).tgz
-
-clean:
-	@-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~ $(PODIR)/*.mo $(PODIR)/*.pot
-
-install:	libvdr-$(PLUGIN).so
-	cp --remove-destination libvdr-$(PLUGIN).so \
-		/usr/lib/vdr/plugins/libvdr-$(PLUGIN).so.$(APIVERSION)
-
-HDRS=	$(wildcard *.h)
-
-indent:
-	for i in $(SRCS) $(HDRS); do \
-		indent $$i; \
-		unexpand -a $$i | sed -e s/constconst/const/ > $$i.up; \
-		mv $$i.up $$i; \
-	done
-
-video_test: video.c Makefile
-	$(CC) -DVIDEO_TEST -DVERSION='"$(VERSION)"' $(CFLAGS) $(LDFLAGS) $< $(LIBS) \
-	-o $@
diff --git a/README.txt b/README.txt
index 01f9607..62372e3 100644
--- a/README.txt
+++ b/README.txt
@@ -233,6 +233,10 @@ Setup: /etc/vdr/setup.conf
 	0 disable black picture during channel switch
 	1 enable black picture during channel switch
 
+	softhddevice.ClearOnSwitch = 0
+	0 keep video und audio buffers during channel switch
+	1 clear video and audio buffers on channel switch
+
 	softhddevice.Video4to3DisplayFormat = 1
 	0 pan and scan
 	1 letter box
@@ -352,7 +356,7 @@ Requires:
 
 	media-video/ffmpeg (version >=0.7)
 		Complete solution to record, convert and stream audio and
-		video. Includes libavcodec.
+		video. Includes libavcodec and libswresample.
 		http://ffmpeg.org
 	media-libs/alsa-lib
 		Advanced Linux Sound Architecture Library
diff --git a/Todo b/Todo
index 863de11..fbc0fb4 100644
--- a/Todo
+++ b/Todo
@@ -45,6 +45,7 @@ video:
     still-picture of PES recordings should use VideoMpegEnqueue.
     convert PIX_FMT_... PixelFormat to new names AV_PIX_FMT_..., AVPixelFormat.
     atmo service support 3D grab
+    no warnings during still picture
 
 vdpau:
     software deinterlace path not working.
@@ -127,6 +128,7 @@ unsorted:
     svdrp prim: support plugin names for device numbers.
     Workaround exists: hangup PipVideoStream -> Vdpau_get_format -> xcb -> poll
 	+ lock DecoderLockMutex
+    check compiletime and runtime ffmpeg/libav version during init.
 
 future features (not planed for 1.0 - 1.5)
 
diff --git a/audio.c b/audio.c
index 6ad2907..6ca3df1 100644
--- a/audio.c
+++ b/audio.c
@@ -1,7 +1,7 @@
 ///
 ///	@file audio.c		@brief Audio module
 ///
-///	Copyright (c) 2009 - 2013 by Johns.  All Rights Reserved.
+///	Copyright (c) 2009 - 2014 by Johns.  All Rights Reserved.
 ///
 ///	Contributor(s):
 ///
@@ -88,7 +88,7 @@
 #endif
 #endif
 
-#include <alsa/iatomic.h>		// portable atomic_t
+#include "iatomic.h"			// portable atomic_t
 
 #include "ringbuffer.h"
 #include "misc.h"
@@ -123,6 +123,8 @@ static const AudioModule NoopModule;	///< forward definition of noop module
 //----------------------------------------------------------------------------
 
 char AudioAlsaDriverBroken;		///< disable broken driver message
+char AudioAlsaNoCloseOpen;		///< disable alsa close/open fix
+char AudioAlsaCloseOpenDelay;		///< enable alsa close/open delay fix
 
 static const char *AudioModuleName;	///< which audio module to use
 
@@ -130,6 +132,7 @@ static const char *AudioModuleName;	///< which audio module to use
 static const AudioModule *AudioUsedModule = &NoopModule;
 static const char *AudioPCMDevice;	///< PCM device name
 static const char *AudioPassthroughDevice;	///< Passthrough device name
+static char AudioAppendAES;		///< flag automatic append AES
 static const char *AudioMixerDevice;	///< mixer device name
 static const char *AudioMixerChannel;	///< mixer channel name
 static char AudioDoingInit;		///> flag in init, reduce error
@@ -1005,6 +1008,26 @@ static snd_pcm_t *AlsaOpenPCM(int passthrough)
 	Info(_("audio/alsa: using %sdevice '%s'\n"),
 	    passthrough ? "pass-through " : "", device);
     }
+    //
+    // for AC3 pass-through try to set the non-audio bit, use AES0=6
+    //
+    if (passthrough && AudioAppendAES) {
+#if 0
+	// FIXME: not yet finished
+	char *buf;
+	const char *s;
+	int n;
+
+	n = strlen(device);
+	buf = alloca(n + sizeof(":AES0=6") + 1);
+	strcpy(buf, device);
+	if (!(s = strchr(buf, ':'))) {
+	    // no alsa parameters
+	    strcpy(buf + n, ":AES=6");
+	}
+	Debug(3, "audio/alsa: try '%s'\n", buf);
+#endif
+    }
     // open none blocking; if device is already used, we don't want wait
     if ((err =
 	    snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK,
@@ -1189,13 +1212,17 @@ static int AlsaSetup(int *freq, int *channels, int passthrough)
 	// FIXME: if open fails for fe. pass-through, we never recover
 	return -1;
     }
-    if (1) {				// close+open to fix HDMI no sound bug
+    if (!AudioAlsaNoCloseOpen) {	// close+open to fix HDMI no sound bug
 	snd_pcm_t *handle;
 
 	handle = AlsaPCMHandle;
 	// FIXME: need lock
 	AlsaPCMHandle = NULL;		// other threads should check handle
 	snd_pcm_close(handle);
+	if (AudioAlsaCloseOpenDelay) {
+	    usleep(50 * 1000);		// 50ms delay for alsa recovery
+	}
+	// FIXME: can use multiple retries
 	if (!(handle = AlsaOpenPCM(passthrough))) {
 	    return -1;
 	}
@@ -2043,25 +2070,27 @@ static void *AudioPlayHandlerThread(void *dummy)
 	    int read;
 	    int flush;
 	    int err;
+	    int i;
 
 	    // look if there is a flush command in the queue
 	    flush = 0;
 	    filled = atomic_read(&AudioRingFilled);
 	    read = AudioRingRead;
-	    while (filled--) {
+	    i = filled;
+	    while (i--) {
 		read = (read + 1) % AUDIO_RING_MAX;
 		if (AudioRing[read].FlushBuffers) {
 		    AudioRing[read].FlushBuffers = 0;
 		    AudioRingRead = read;
-		    atomic_set(&AudioRingFilled, filled);
 		    // handle all flush in queue
-		    flush = 1;
+		    flush = filled - i;
 		}
 	    }
 
 	    if (flush) {
-		Debug(3, "audio: flush\n");
+		Debug(3, "audio: flush %d ring buffer(s)\n", flush);
 		AudioUsedModule->FlushBuffers();
+		atomic_sub(flush, &AudioRingFilled);
 		if (AudioNextRing()) {
 		    Debug(3, "audio: break after flush\n");
 		    break;
@@ -2421,8 +2450,23 @@ void AudioFlushBuffers(void)
     int old;
     int i;
 
+    if (atomic_read(&AudioRingFilled) >= AUDIO_RING_MAX) {
+	// wait for space in ring buffer, should never happen
+	for (i = 0; i < 24 * 2; ++i) {
+	    if (atomic_read(&AudioRingFilled) < AUDIO_RING_MAX) {
+		break;
+	    }
+	    Debug(3, "audio: flush out of ring buffers\n");
+	    usleep(1 * 1000);		// avoid hot polling
+	}
+	if (atomic_read(&AudioRingFilled) >= AUDIO_RING_MAX) {
+	    // FIXME: We can set the flush flag in the last wrote ring buffer
+	    Error(_("audio: flush out of ring buffers\n"));
+	    return;
+	}
+    }
+
     old = AudioRingWrite;
-    // FIXME: check ring buffer overflow
     AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
     AudioRing[AudioRingWrite].FlushBuffers = 1;
     AudioRing[AudioRingWrite].Passthrough = AudioRing[old].Passthrough;
@@ -2439,12 +2483,13 @@ void AudioFlushBuffers(void)
 
     atomic_inc(&AudioRingFilled);
 
-    // FIXME: wait for flush complete?
+    // FIXME: wait for flush complete needed?
     for (i = 0; i < 24 * 2; ++i) {
 	if (!AudioRunning) {		// wakeup thread to flush buffers
 	    AudioRunning = 1;
 	    pthread_cond_signal(&AudioStartCond);
 	}
+	// FIXME: waiting on zero isn't correct, but currently works
 	if (!atomic_read(&AudioRingFilled)) {
 	    break;
 	}
@@ -2757,6 +2802,20 @@ void AudioSetChannel(const char *channel)
 }
 
 /**
+**	Set automatic AES flag handling.
+**
+**	@param onoff	turn setting AES flag on or off
+*/
+void AudioSetAutoAES(int onoff)
+{
+    if (onoff < 0) {
+	AudioAppendAES ^= 1;
+    } else {
+	AudioAppendAES = onoff;
+    }
+}
+
+/**
 **	Initialize audio output module.
 **
 **	@todo FIXME: make audio output module selectable.
diff --git a/audio.h b/audio.h
index 4a0ac51..da05575 100644
--- a/audio.h
+++ b/audio.h
@@ -1,7 +1,7 @@
 ///
 ///	@file audio.h		@brief Audio module headerfile
 ///
-///	Copyright (c) 2009 - 2013 by Johns.  All Rights Reserved.
+///	Copyright (c) 2009 - 2014 by Johns.  All Rights Reserved.
 ///
 ///	Contributor(s):
 ///
@@ -52,6 +52,7 @@ extern void AudioSetDevice(const char *);	///< set PCM audio device
     /// set pass-through device
 extern void AudioSetPassthroughDevice(const char *);
 extern void AudioSetChannel(const char *);	///< set mixer channel
+extern void AudioSetAutoAES(int);	///< set automatic AES flag handling
 extern void AudioInit(void);		///< setup audio module
 extern void AudioExit(void);		///< cleanup and exit audio module
 
@@ -60,5 +61,7 @@ extern void AudioExit(void);		///< cleanup and exit audio module
 //----------------------------------------------------------------------------
 
 extern char AudioAlsaDriverBroken;	///< disable broken driver message
+extern char AudioAlsaNoCloseOpen;	///< disable alsa close/open fix
+extern char AudioAlsaCloseOpenDelay;	///< enable alsa close/open delay fix
 
 /// @}
diff --git a/codec.c b/codec.c
index 4eea14f..03ba028 100644
--- a/codec.c
+++ b/codec.c
@@ -1,7 +1,7 @@
 ///
 ///	@file codec.c	@brief Codec functions
 ///
-///	Copyright (c) 2009 - 2013 by Johns.  All Rights Reserved.
+///	Copyright (c) 2009 - 2014 by Johns.  All Rights Reserved.
 ///
 ///	Contributor(s):
 ///
@@ -38,8 +38,12 @@
 #define USE_AC3_DRIFT_CORRECTION
     /// use ffmpeg libswresample API (autodected, Makefile)
 #define noUSE_SWRESAMPLE
+    /// use libav libavresample API (autodected, Makefile)
+#define noUSE_AVRESAMPLE
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #ifdef __FreeBSD__
 #include <sys/endian.h>
@@ -54,8 +58,8 @@
 #define _(str) gettext(str)		///< gettext shortcut
 #define _N(str) str			///< gettext_noop shortcut
 
-#include <alsa/iatomic.h>
 #include <libavcodec/avcodec.h>
+#include <libavutil/mem.h>
 // support old ffmpeg versions <1.0
 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,18,102)
 #define AVCodecID CodecID
@@ -70,6 +74,10 @@
 #ifdef USE_SWRESAMPLE
 #include <libswresample/swresample.h>
 #endif
+#ifdef USE_AVRESAMPLE
+#include <libavresample/avresample.h>
+#include <libavutil/opt.h>
+#endif
 
 #ifndef __USE_GNU
 #define __USE_GNU
@@ -79,6 +87,7 @@
 #ifdef MAIN_H
 #include MAIN_H
 #endif
+#include "iatomic.h"
 #include "misc.h"
 #include "video.h"
 #include "audio.h"
@@ -201,7 +210,9 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
 
 	//Debug(3, "codec: use surface %#010x\n", surface);
 
+#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,48,101)
 	frame->type = FF_BUFFER_TYPE_USER;
+#endif
 #if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,46,0)
 	frame->age = 256 * 256 * 256 * 64;
 #endif
@@ -211,12 +222,14 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
 	frame->data[2] = NULL;
 	frame->data[3] = NULL;
 
+#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,66,100)
 	// reordered frames
 	if (video_ctx->pkt) {
 	    frame->pkt_pts = video_ctx->pkt->pts;
 	} else {
 	    frame->pkt_pts = AV_NOPTS_VALUE;
 	}
+#endif
 	return 0;
     }
 #endif
@@ -228,7 +241,9 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
 
 	//Debug(3, "codec: use surface %#010x\n", surface);
 
+#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,48,101)
 	frame->type = FF_BUFFER_TYPE_USER;
+#endif
 #if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,46,0)
 	frame->age = 256 * 256 * 256 * 64;
 #endif
@@ -236,12 +251,14 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
 	frame->data[0] = (void *)(size_t) surface;
 	frame->data[3] = (void *)(size_t) surface;
 
+#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,66,100)
 	// reordered frames
 	if (video_ctx->pkt) {
 	    frame->pkt_pts = video_ctx->pkt->pts;
 	} else {
 	    frame->pkt_pts = AV_NOPTS_VALUE;
 	}
+#endif
 	return 0;
     }
     //Debug(3, "codec: fallback to default get_buffer\n");
@@ -664,15 +681,18 @@ struct _audio_decoder_
     int HwSampleRate;			///< hw sample rate
     int HwChannels;			///< hw channels
 
-#ifndef USE_SWRESAMPLE
-    ReSampleContext *ReSample;		///< audio resampling context
+#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
+    ReSampleContext *ReSample;		///< old resampling context
 #endif
 #ifdef USE_SWRESAMPLE
 #if LIBSWRESAMPLE_VERSION_INT < AV_VERSION_INT(0, 15, 100)
-    struct SwrContext *Resample;	///< audio software resample context
+    struct SwrContext *Resample;	///< ffmpeg software resample context
 #else
-    SwrContext *Resample;		///< audio software resample context
+    SwrContext *Resample;		///< ffmpeg software resample context
+#endif
 #endif
+#ifdef USE_AVRESAMPLE
+    AVAudioResampleContext *Resample;	///< libav software resample context
 #endif
 
     uint16_t Spdif[24576 / 2];		///< SPDIF output buffer
@@ -687,7 +707,7 @@ struct _audio_decoder_
     int DriftCorr;			///< audio drift correction value
     int DriftFrac;			///< audio drift fraction for ac3
 
-#ifndef USE_SWRESAMPLE
+#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
     struct AVResampleContext *AvResample;	///< second audio resample context
 #define MAX_CHANNELS 8			///< max number of channels supported
     int16_t *Buffer[MAX_CHANNELS];	///< deinterleave sample buffers
@@ -785,7 +805,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
 	    AV_CH_LAYOUT_STEREO_DOWNMIX;
     }
 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,61,100)
-    // this has no effect
+    // this has no effect (with ffmpeg and libav)
     // audio_decoder->AudioCtx->request_sample_fmt = AV_SAMPLE_FMT_S16;
 #endif
     pthread_mutex_lock(&CodecLockMutex);
@@ -834,7 +854,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
 void CodecAudioClose(AudioDecoder * audio_decoder)
 {
     // FIXME: output any buffered data
-#ifndef USE_SWRESAMPLE
+#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
     if (audio_decoder->AvResample) {
 	int ch;
 
@@ -860,6 +880,11 @@ void CodecAudioClose(AudioDecoder * audio_decoder)
 	swr_free(&audio_decoder->Resample);
     }
 #endif
+#ifdef USE_AVRESAMPLE
+    if (audio_decoder->Resample) {
+	avresample_free(&audio_decoder->Resample);
+    }
+#endif
     if (audio_decoder->AudioCtx) {
 	pthread_mutex_lock(&CodecLockMutex);
 	avcodec_close(audio_decoder->AudioCtx);
@@ -1155,7 +1180,7 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder,
     return 0;
 }
 
-#ifndef USE_SWRESAMPLE
+#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
 
 /**
 **	Set/update audio pts clock.
@@ -1557,7 +1582,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
 
 #endif
 
-#ifdef USE_SWRESAMPLE
+#if defined(USE_SWRESAMPLE) || defined(USE_AVRESAMPLE)
 
 /**
 **	Set/update audio pts clock.
@@ -1646,6 +1671,7 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
 	}
     }
 
+#ifdef USE_SWRESAMPLE
     if (audio_decoder->Resample && audio_decoder->DriftCorr) {
 	int distance;
 
@@ -1660,6 +1686,18 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
 	    Debug(3, "codec/audio: swr_set_compensation failed\n");
 	}
     }
+#endif
+#ifdef USE_AVRESAMPLE
+    if (audio_decoder->Resample && audio_decoder->DriftCorr) {
+	int distance;
+
+	distance = (pts_diff * audio_decoder->HwSampleRate) / (900 * 1000);
+	if (avresample_set_compensation(audio_decoder->Resample,
+		audio_decoder->DriftCorr / 10, distance)) {
+	    Debug(3, "codec/audio: swr_set_compensation failed\n");
+	}
+    }
+#endif
     if (1) {
 	static int c;
 
@@ -1699,6 +1737,7 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
     }
 #endif
 
+#ifdef USE_SWRESAMPLE
     audio_decoder->Resample =
 	swr_alloc_set_opts(audio_decoder->Resample, audio_ctx->channel_layout,
 	AV_SAMPLE_FMT_S16, audio_decoder->HwSampleRate,
@@ -1709,6 +1748,33 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
     } else {
 	Error(_("codec/audio: can't setup resample\n"));
     }
+#endif
+#ifdef USE_AVRESAMPLE
+    if (!(audio_decoder->Resample = avresample_alloc_context())) {
+	Error(_("codec/audio: can't setup resample\n"));
+	return;
+    }
+
+    av_opt_set_int(audio_decoder->Resample, "in_channel_layout",
+	audio_ctx->channel_layout, 0);
+    av_opt_set_int(audio_decoder->Resample, "in_sample_fmt",
+	audio_ctx->sample_fmt, 0);
+    av_opt_set_int(audio_decoder->Resample, "in_sample_rate",
+	audio_ctx->sample_rate, 0);
+    av_opt_set_int(audio_decoder->Resample, "out_channel_layout",
+	audio_ctx->channel_layout, 0);
+    av_opt_set_int(audio_decoder->Resample, "out_sample_fmt",
+	AV_SAMPLE_FMT_S16, 0);
+    av_opt_set_int(audio_decoder->Resample, "out_sample_rate",
+	audio_decoder->HwSampleRate, 0);
+
+    if (avresample_open(audio_decoder->Resample)) {
+	avresample_free(&audio_decoder->Resample);
+	audio_decoder->Resample = NULL;
+	Error(_("codec/audio: can't open resample\n"));
+	return;
+    }
+#endif
 }
 
 /**
@@ -1731,7 +1797,9 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
     audio_ctx = audio_decoder->AudioCtx;
 
     // FIXME: don't need to decode pass-through codecs
-    frame.data[0] = NULL;
+    // libav needs memset, frame.data[0] = NULL;
+    memset(&frame, 0, sizeof(frame));
+    got_frame = 0;
     n = avcodec_decode_audio4(audio_ctx, &frame, &got_frame,
 	(AVPacket *) avpkt);
     if (n != avpkt->size) {
@@ -1785,7 +1853,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
 	    "codec/audio: channels %d samples %d plane %d data %d\n",
 	    audio_ctx->channels, frame.nb_samples, plane_sz, data_sz);
     }
-
+#ifdef USE_SWRESAMPLE
     if (audio_decoder->Resample) {
 	uint8_t outbuf[8192 * 2 * 8];
 	uint8_t *out[1];
@@ -1804,6 +1872,30 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
 	}
 	return;
     }
+#endif
+
+#ifdef USE_AVRESAMPLE
+    if (audio_decoder->Resample) {
+	uint8_t outbuf[8192 * 2 * 8];
+	uint8_t *out[1];
+
+	out[0] = outbuf;
+	n = avresample_convert(audio_decoder->Resample, out, 0,
+	    sizeof(outbuf) / (2 * audio_decoder->HwChannels),
+	    (uint8_t **) frame.extended_data, 0, frame.nb_samples);
+	// FIXME: set out_linesize, in_linesize correct
+	if (n > 0) {
+	    if (!(audio_decoder->Passthrough & CodecPCM)) {
+		CodecReorderAudioFrame((int16_t *) outbuf,
+		    n * 2 * audio_decoder->HwChannels,
+		    audio_decoder->HwChannels);
+	    }
+	    AudioEnqueue(outbuf, n * 2 * audio_decoder->HwChannels);
+	}
+	return;
+    }
+#endif
+
 #ifdef DEBUG
     // should be never reached
     fprintf(stderr, "oops\n");
diff --git a/iatomic.h b/iatomic.h
new file mode 100644
index 0000000..59e1684
--- /dev/null
+++ b/iatomic.h
@@ -0,0 +1,97 @@
+///
+///	@file iatomic.h @brief Misc function header file
+///
+///	Copyright (c) 2014 by Johns.  All Rights Reserved.
+///
+///	Contributor(s):
+///
+///	License: AGPLv3
+///
+///	This program is free software: you can redistribute it and/or modify
+///	it under the terms of the GNU Affero General Public License as
+///	published by the Free Software Foundation, either version 3 of the
+///	License.
+///
+///	This program is distributed in the hope that it will be useful,
+///	but WITHOUT ANY WARRANTY; without even the implied warranty of
+///	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+///	GNU Affero General Public License for more details.
+///
+///	$Id$
+//////////////////////////////////////////////////////////////////////////////
+
+/// @addtogroup iatomic
+/// @{
+
+#define GCC_VERSION (__GNUC__ * 10000 \
+	+ __GNUC_MINOR__ * 100 \
+	+ __GNUC_PATCHLEVEL__)
+
+//	gcc before 4.7 didn't support atomic builtins,
+//	use alsa atomic functions.
+#if GCC_VERSION < 40700
+
+#include <alsa/iatomic.h>
+
+#else
+
+//////////////////////////////////////////////////////////////////////////////
+//	Defines
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+//	Declares
+//////////////////////////////////////////////////////////////////////////////
+
+///
+///	atomic type, 24 bit useable,
+///
+typedef volatile int atomic_t;
+
+//////////////////////////////////////////////////////////////////////////////
+//	Prototypes
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+//	Inlines
+//////////////////////////////////////////////////////////////////////////////
+
+///
+///	Set atomic value.
+///
+#define atomic_set(ptr, val) \
+    __atomic_store_n(ptr, val, __ATOMIC_SEQ_CST)
+
+///
+///	Read atomic value.
+///
+#define atomic_read(ptr) \
+    __atomic_load_n(ptr, __ATOMIC_SEQ_CST)
+
+///
+///	Increment atomic value.
+///
+#define atomic_inc(ptr) \
+    __atomic_add_fetch(ptr, 1, __ATOMIC_SEQ_CST)
+
+///
+///	Decrement atomic value.
+///
+#define atomic_dec(ptr) \
+    __atomic_sub_fetch(ptr, 1, __ATOMIC_SEQ_CST)
+
+///
+///	Add to atomic value.
+///
+#define atomic_add(val, ptr) \
+    __atomic_add_fetch(ptr, val, __ATOMIC_SEQ_CST)
+
+///
+///	Subtract from atomic value.
+///
+#define atomic_sub(val, ptr) \
+    __atomic_sub_fetch(ptr, val, __ATOMIC_SEQ_CST)
+
+#endif
+
+/// @}
diff --git a/po/de_DE.po b/po/de_DE.po
index 91867ef..f2a4bfc 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -7,10 +7,10 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR \n"
 "Report-Msgid-Bugs-To: <see README>\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"
+"POT-Creation-Date: 2014-03-20 11:50+0100\n"
+"PO-Revision-Date: blabla\n"
+"Last-Translator: blabla\n"
+"Language-Team: blabla\n"
 "Language: german\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
@@ -239,6 +239,9 @@ msgstr ""
 msgid "audio: can't place %d samples in ring buffer\n"
 msgstr ""
 
+msgid "audio: flush out of ring buffers\n"
+msgstr ""
+
 #, c-format
 msgid "audio: '%s' output module used\n"
 msgstr ""
@@ -306,6 +309,9 @@ msgstr ""
 msgid "codec/audio: can't setup resample\n"
 msgstr ""
 
+msgid "codec/audio: can't open resample\n"
+msgstr ""
+
 msgid "codec/audio: latm\n"
 msgstr ""
 
@@ -483,6 +489,9 @@ msgstr "OSD Höhe"
 msgid "Suspend"
 msgstr "Unterbrechen"
 
+msgid "Detach from main menu entry"
+msgstr "Detach durch Hauptmenüeintrag"
+
 msgid "Suspend closes video+audio"
 msgstr "Unterbrechen schließt Video+Audio"
 
@@ -510,6 +519,9 @@ msgstr "Sanftanlauf A/V Sync"
 msgid "Black during channel switch"
 msgstr "Schwarz während Kanalwechsel"
 
+msgid "Clear decoder on channel switch"
+msgstr "Decoder bei Kanalwechsel leeren"
+
 msgid "Brightness (-1000..1000) (vdpau)"
 msgstr "Helligkeit (-1000..1000) (vdpau)"
 
@@ -595,7 +607,7 @@ msgid "  E-AC-3 pass-through"
 msgstr ""
 
 msgid "Enable (E-)AC-3 (decoder) downmix"
-msgstr ""
+msgstr "Aktiviere (E-)AC-3 (decoder) downmix"
 
 msgid "Volume control"
 msgstr "Lautstärkesteuerung"
@@ -624,6 +636,9 @@ msgstr "Reduziere Steropegel (/1000)"
 msgid "Audio buffer size (ms)"
 msgstr "Audio Puffergröße (ms)"
 
+msgid "Enable automatic AES"
+msgstr "Aktiviere automatiche AES"
+
 msgid "Picture-In-Picture"
 msgstr "Bild in Bild (PIP)"
 
@@ -688,6 +703,9 @@ msgstr ""
 msgid "Channel not available!"
 msgstr "Kanal nicht verfügbar!"
 
+msgid "Detach SoftHdDevice"
+msgstr ""
+
 msgid "Suspend SoftHdDevice"
 msgstr "Unterbreche SoftHdDevice"
 
@@ -1031,7 +1049,7 @@ msgstr ""
 msgid "video/vaapi: can't find a supported subpicture format"
 msgstr ""
 
-msgid "video/vaapi: vaapi supports unscaled osd\n"
+msgid "video/vaapi: supports unscaled osd\n"
 msgstr ""
 
 msgid "video/vaapi: can't create osd image\n"
diff --git a/ringbuffer.c b/ringbuffer.c
index 9466852..c9497b1 100644
--- a/ringbuffer.c
+++ b/ringbuffer.c
@@ -1,7 +1,7 @@
 ///
 ///	@file ringbuffer.c	@brief Ringbuffer module
 ///
-///	Copyright (c) 2009, 2011  by Johns.  All Rights Reserved.
+///	Copyright (c) 2009, 2011, 2014	by Johns.  All Rights Reserved.
 ///
 ///	Contributor(s):
 ///
@@ -30,8 +30,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <alsa/iatomic.h>
-
+#include "iatomic.h"
 #include "ringbuffer.h"
 
     /// ring buffer structure
diff --git a/softhddev.c b/softhddev.c
index b11e43a..1759109 100644
--- a/softhddev.c
+++ b/softhddev.c
@@ -1,7 +1,7 @@
 ///
 ///	@file softhddev.c	@brief A software HD device plugin for VDR.
 ///
-///	Copyright (c) 2011 - 2013 by Johns.  All Rights Reserved.
+///	Copyright (c) 2011 - 2014 by Johns.  All Rights Reserved.
 ///
 ///	Contributor(s):
 ///
@@ -32,15 +32,18 @@
 #include <fcntl.h>
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <stdint.h>
 #include <inttypes.h>
 #include <unistd.h>
+#include <string.h>
 
 #include <libintl.h>
 #define _(str) gettext(str)		///< gettext shortcut
 #define _N(str) str			///< gettext_noop shortcut
 
 #include <libavcodec/avcodec.h>
+#include <libavutil/mem.h>
 // support old ffmpeg versions <1.0
 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,18,102)
 #define AVCodecID CodecID
@@ -60,6 +63,7 @@
 #endif
 #include <pthread.h>
 
+#include "iatomic.h"			// portable atomic_t
 #include "misc.h"
 #include "softhddev.h"
 
@@ -83,6 +87,7 @@ static char VdpauDecoder = 1;		///< vdpau decoder used
 #endif
 
 extern int ConfigAudioBufferTime;	///< config size ms of audio buffer
+extern int ConfigVideoClearOnSwitch;	//<  clear decoder on channel switch
 char ConfigStartX11Server;		///< flag start the x11 server
 static char ConfigStartSuspended;	///< flag to start in suspend mode
 static char ConfigFullscreen;		///< fullscreen modus
@@ -1303,8 +1308,6 @@ void SetVolumeDevice(int volume)
 //	Video
 //////////////////////////////////////////////////////////////////////////////
 
-#include <alsa/iatomic.h>		// portable atomic_t
-
 #define VIDEO_BUFFER_SIZE (512 * 1024)	///< video PES buffer default size
 #define VIDEO_PACKET_MAX 192		///< max number of video packets
 
@@ -1743,22 +1746,40 @@ static void FixPacketForFFMpeg(VideoDecoder * vdecoder, AVPacket * avpkt)
 #endif
 
 /**
+**	Open video stream.
+**
+**	@param stream	video stream
+*/
+static void VideoStreamOpen(VideoStream * stream)
+{
+    stream->SkipStream = 1;
+    stream->CodecID = AV_CODEC_ID_NONE;
+    stream->LastCodecID = AV_CODEC_ID_NONE;
+
+    if ((stream->HwDecoder = VideoNewHwDecoder(stream))) {
+	stream->Decoder = CodecVideoNewDecoder(stream->HwDecoder);
+	VideoPacketInit(stream);
+	stream->SkipStream = 0;
+    }
+}
+
+/**
 **	Close video stream.
 **
 **	@param stream	video stream
+**	@param delhw	flag delete hardware decoder
 **
-**	@note must be called from the video thread, othewise xcb has a
+**	@note must be called from the video thread, otherwise xcb has a
 **	deadlock.
 */
-static void VideoStreamClose(VideoStream * stream)
+static void VideoStreamClose(VideoStream * stream, int delhw)
 {
-    // FIXME: use this function to close the main video stream!
     stream->SkipStream = 1;
     if (stream->Decoder) {
 	VideoDecoder *decoder;
 
 	decoder = stream->Decoder;
-	// FIXME: this lock shouldn't be necessary now
+	// FIXME: remove this lock for main stream close
 	pthread_mutex_lock(&stream->DecoderLockMutex);
 	stream->Decoder = NULL;		// lock read thread
 	pthread_mutex_unlock(&stream->DecoderLockMutex);
@@ -1766,7 +1787,9 @@ static void VideoStreamClose(VideoStream * stream)
 	CodecVideoDelDecoder(decoder);
     }
     if (stream->HwDecoder) {
-	VideoDelHwDecoder(stream->HwDecoder);
+	if (delhw) {
+	    VideoDelHwDecoder(stream->HwDecoder);
+	}
 	stream->HwDecoder = NULL;
 	// FIXME: CodecVideoClose calls/uses hw decoder
     }
@@ -1796,13 +1819,14 @@ int VideoPollInput(VideoStream * stream)
     }
 
     if (stream->Close) {		// close stream request
-	VideoStreamClose(stream);
+	VideoStreamClose(stream, 1);
 	stream->Close = 0;
 	return 1;
     }
     if (stream->ClearBuffers) {		// clear buffer request
 	atomic_set(&stream->PacketsFilled, 0);
 	stream->PacketRead = stream->PacketWrite;
+	// FIXME: ->Decoder already checked
 	if (stream->Decoder) {
 	    CodecVideoFlushBuffers(stream->Decoder);
 	    VideoResetStart(stream->HwDecoder);
@@ -1839,13 +1863,14 @@ int VideoDecodeInput(VideoStream * stream)
     }
 
     if (stream->Close) {		// close stream request
-	VideoStreamClose(stream);
+	VideoStreamClose(stream, 1);
 	stream->Close = 0;
 	return 1;
     }
     if (stream->ClearBuffers) {		// clear buffer request
 	atomic_set(&stream->PacketsFilled, 0);
 	stream->PacketRead = stream->PacketWrite;
+	// FIXME: ->Decoder already checked
 	if (stream->Decoder) {
 	    CodecVideoFlushBuffers(stream->Decoder);
 	    VideoResetStart(stream->HwDecoder);
@@ -1988,17 +2013,8 @@ static void StartVideo(void)
     }
     VideoOsdInit();
     if (!MyVideoStream->Decoder) {
-	MyVideoStream->SkipStream = 1;
-	MyVideoStream->CodecID = AV_CODEC_ID_NONE;
-	MyVideoStream->LastCodecID = AV_CODEC_ID_NONE;
-
-	if ((MyVideoStream->HwDecoder = VideoNewHwDecoder(MyVideoStream))) {
-	    MyVideoStream->Decoder =
-		CodecVideoNewDecoder(MyVideoStream->HwDecoder);
-	    VideoPacketInit(MyVideoStream);
-	    AudioSyncStream = MyVideoStream;
-	    MyVideoStream->SkipStream = 0;
-	}
+	VideoStreamOpen(MyVideoStream);
+	AudioSyncStream = MyVideoStream;
     }
 }
 
@@ -2010,6 +2026,10 @@ static void StopVideo(void)
     VideoOsdExit();
     VideoExit();
     AudioSyncStream = NULL;
+#if 1
+    // FIXME: done by exit: VideoDelHwDecoder(MyVideoStream->HwDecoder);
+    VideoStreamClose(MyVideoStream, 0);
+#else
     MyVideoStream->SkipStream = 1;
     if (MyVideoStream->Decoder) {
 	VideoDecoder *decoder;
@@ -2030,6 +2050,7 @@ static void StopVideo(void)
 
     MyVideoStream->NewStream = 1;
     MyVideoStream->InvalidPesCounter = 0;
+#endif
 }
 
 #ifdef DEBUG
@@ -2447,45 +2468,48 @@ uint8_t *GrabImage(int *size, int jpeg, int quality, int width, int height)
 */
 int SetPlayMode(int play_mode)
 {
-    VideoDisplayWakeup();
-    // 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 != AV_CODEC_ID_NONE) {
-	    MyVideoStream->NewStream = 1;
-	    MyVideoStream->InvalidPesCounter = 0;
-	    // tell hw decoder we are closing stream
-	    VideoSetClosing(MyVideoStream->HwDecoder);
-	    VideoResetStart(MyVideoStream->HwDecoder);
+    switch (play_mode) {
+	case 0:			// audio/video from decoder
+	    // tell video parser we get new stream
+	    if (MyVideoStream->Decoder && !MyVideoStream->SkipStream) {
+		// clear buffers on close configured always or replay only
+		if (ConfigVideoClearOnSwitch || MyVideoStream->ClearClose) {
+		    Clear();		// flush all buffers
+		    MyVideoStream->ClearClose = 0;
+		}
+		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);
 #ifdef DEBUG
-	    VideoSwitch = GetMsTicks();
+		    VideoSwitch = GetMsTicks();
+		    Debug(3, "video: new stream start\n");
 #endif
-	}
-    }
-    if (MyAudioDecoder) {		// tell audio parser we have new stream
-	if (AudioCodecID != AV_CODEC_ID_NONE) {
-	    NewAudioStream = 1;
-	}
-    }
-    switch (play_mode) {
-	case 0:			// nothing
-	case 1:			// audio/video from player
+		}
+	    }
+	    if (MyAudioDecoder) {	// tell audio parser we have new stream
+		if (AudioCodecID != AV_CODEC_ID_NONE) {
+		    NewAudioStream = 1;
+		}
+	    }
 	    break;
-	case 2:			// audio only
-	    Debug(3, "softhddev: FIXME: audio only, silence video errors\n");
+	case 1:			// audio/video from player
+	    VideoDisplayWakeup();
+	    Play();
 	    break;
-	case 3:			// audio only, black screen
+	case 2:			// audio only from player, video from decoder
+	case 3:			// audio only from player, no video (black screen)
 	    Debug(3, "softhddev: FIXME: audio only, silence video errors\n");
+	    VideoDisplayWakeup();
+	    Play();
 	    break;
-	case 4:			// video only
+	case 4:			// video only from player, audio from decoder
+	    VideoDisplayWakeup();
+	    Play();
 	    break;
     }
-
-    Play();
-
     return 1;
 }
 
@@ -2569,8 +2593,10 @@ void Clear(void)
 
     VideoResetPacket(MyVideoStream);	// terminate work
     MyVideoStream->ClearBuffers = 1;
-    AudioFlushBuffers();
-    //NewAudioStream = 1;
+    if (!SkipAudio) {
+	AudioFlushBuffers();
+	//NewAudioStream = 1;
+    }
     // FIXME: audio avcodec_flush_buffers, video is done by VideoClearBuffers
 
     // wait for empty buffers
@@ -2866,6 +2892,8 @@ const char *CommandLineHelp(void)
 	"\tstill-hw-decoder\tenable hardware decoder for still-pictures\n"
 	"\tstill-h264-hw-decoder\tenable h264 hw decoder for still-pictures\n"
 	"\talsa-driver-broken\tdisable broken alsa driver message\n"
+	"\talsa-no-close-open\tdisable close open to fix alsa no sound bug\n"
+	"\talsa-close-open-delay\tenable close open delay to fix no sound bug\n"
 	"\tignore-repeat-pict\tdisable repeat pict message\n"
 	"  -D\t\tstart in detached mode\n";
 }
@@ -2942,6 +2970,10 @@ int ProcessArgs(int argc, char *const argv[])
 		    ConfigStillDecoder = 1;
 		} else if (!strcasecmp("alsa-driver-broken", optarg)) {
 		    AudioAlsaDriverBroken = 1;
+		} else if (!strcasecmp("alsa-no-close-open", optarg)) {
+		    AudioAlsaNoCloseOpen = 1;
+		} else if (!strcasecmp("alsa-close-open-delay", optarg)) {
+		    AudioAlsaCloseOpenDelay = 1;
 		} else if (!strcasecmp("ignore-repeat-pict", optarg)) {
 		    VideoIgnoreRepeatPict = 1;
 		} else {
@@ -3280,6 +3312,8 @@ void Suspend(int video, int audio, int dox11)
     DelPip();				// must stop PIP
 #endif
 
+    // FIXME: should not be correct, if not both are suspended!
+    // Move down into if (video) ...
     MyVideoStream->SkipStream = 1;
     SkipAudio = 1;
 
@@ -3426,16 +3460,7 @@ void PipStart(int x, int y, int width, int height, int pip_x, int pip_y,
     }
 
     if (!PipVideoStream->Decoder) {
-	PipVideoStream->SkipStream = 1;
-	PipVideoStream->CodecID = AV_CODEC_ID_NONE;
-	PipVideoStream->LastCodecID = AV_CODEC_ID_NONE;
-
-	if ((PipVideoStream->HwDecoder = VideoNewHwDecoder(PipVideoStream))) {
-	    PipVideoStream->Decoder =
-		CodecVideoNewDecoder(PipVideoStream->HwDecoder);
-	    VideoPacketInit(PipVideoStream);
-	    PipVideoStream->SkipStream = 0;
-	}
+	VideoStreamOpen(PipVideoStream);
     }
     PipSetPosition(x, y, width, height, pip_x, pip_y, pip_width, pip_height);
 }
@@ -3453,34 +3478,11 @@ void PipStop(void)
 
     ScaleVideo(0, 0, 0, 0);
 
-#if 0
-    PipVideoStream->SkipStream = 1;	// lock write thread
-    if (PipVideoStream->Decoder) {
-	VideoDecoder *decoder;
-
-	decoder = PipVideoStream->Decoder;
-	pthread_mutex_lock(&PipVideoStream->DecoderLockMutex);
-	PipVideoStream->Decoder = NULL;	// lock read thread
-	pthread_mutex_unlock(&PipVideoStream->DecoderLockMutex);
-	CodecVideoClose(decoder);
-	CodecVideoDelDecoder(decoder);
-    }
-    if (PipVideoStream->HwDecoder) {
-	VideoDelHwDecoder(PipVideoStream->HwDecoder);
-	PipVideoStream->HwDecoder = NULL;
-	// FIXME: CodecVideoClose calls/uses hw decoder
-    }
-    VideoPacketExit(PipVideoStream);
-
-    PipVideoStream->NewStream = 1;
-    PipVideoStream->InvalidPesCounter = 0;
-#else
     PipVideoStream->Close = 1;
     for (i = 0; PipVideoStream->Close && i < 50; ++i) {
 	usleep(1 * 1000);
     }
     Info("[softhddev]%s: pip close %dms\n", __FUNCTION__, i);
-#endif
 }
 
 /**
diff --git a/softhddev.h b/softhddev.h
index 6e446dc..da16ece 100644
--- a/softhddev.h
+++ b/softhddev.h
@@ -1,7 +1,7 @@
 ///
 ///	@file softhddev.h	@brief software HD device plugin header file.
 ///
-///	Copyright (c) 2011 - 2013 by Johns.  All Rights Reserved.
+///	Copyright (c) 2011 - 2014 by Johns.  All Rights Reserved.
 ///
 ///	Contributor(s):
 ///
@@ -25,7 +25,8 @@ extern "C"
 {
 #endif
     /// C callback feed key press
-    extern void FeedKeyPress(const char *, const char *, int, int);
+    extern void FeedKeyPress(const char *, const char *, int, int,
+	const char *);
 
     /// C plugin get osd size and ascpect
     extern void GetOsdSize(int *, int *, double *);
diff --git a/softhddevice.cpp b/softhddevice.cpp
index c2839ce..b3467a5 100644
--- a/softhddevice.cpp
+++ b/softhddevice.cpp
@@ -79,6 +79,7 @@ static const char *const Resolution[RESOLUTIONS] = {
 
 static char ConfigMakePrimary;		///< config primary wanted
 static char ConfigHideMainMenuEntry;	///< config hide main menu entry
+static char ConfigDetachFromMainMenu;	///< detach from main menu entry instead of suspend
 static char ConfigSuspendClose;		///< suspend should close devices
 static char ConfigSuspendX11;		///< suspend should stop x11
 
@@ -91,6 +92,7 @@ static char ConfigVideoStudioLevels;	///< config use studio levels
 static char ConfigVideo60HzMode;	///< config use 60Hz display mode
 static char ConfigVideoSoftStartSync;	///< config use softstart sync
 static char ConfigVideoBlackPicture;	///< config enable black picture mode
+char ConfigVideoClearOnSwitch;		///< config enable Clear on channel switch
 
 static int ConfigVideoBrightness;	///< config video brightness
 static int ConfigVideoContrast = 1000;	///< config video contrast
@@ -138,6 +140,7 @@ static char ConfigAudioCompression;	///< config use volume compression
 static int ConfigAudioMaxCompression;	///< config max volume compression
 static int ConfigAudioStereoDescent;	///< config reduce stereo loudness
 int ConfigAudioBufferTime;		///< config size ms of audio buffer
+static int ConfigAudioAutoAES;		///< config automatic AES handling
 
 static char *ConfigX11Display;		///< config x11 display
 static char *ConfigAudioDevice;		///< config audio stereo device
@@ -211,9 +214,10 @@ class cSoftRemote:public cRemote
 **	@param key	pressed/released key name
 **	@param repeat	repeated key flag
 **	@param release	released key flag
+**	@param letter	x11 character string (system setting locale)
 */
 extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat,
-    int release)
+    int release, const char *letter)
 {
     cRemote *remote;
     cSoftRemote *csoft;
@@ -236,9 +240,18 @@ extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat,
 	csoft = new cSoftRemote(keymap);
     }
 
-    //dsyslog("[softhddev]%s %s, %s\n", __FUNCTION__, keymap, key);
+    //dsyslog("[softhddev]%s %s, %s, %s\n", __FUNCTION__, keymap, key, letter);
     if (key[1]) {			// no single character
-	csoft->Put(key, repeat, release);
+	if (!csoft->Put(key, repeat, release) && letter
+	    && !cRemote::IsLearning()) {
+	    cCharSetConv conv;
+	    unsigned code;
+
+	    code = Utf8CharGet(conv.Convert(letter));
+	    if (code <= 0xFF) {
+		cRemote::Put(KBDKEY(code));	// feed it for edit mode
+	    }
+	}
     } else if (!csoft->Put(key, repeat, release)) {
 	cRemote::Put(KBDKEY(key[0]));	// feed it for edit mode
     }
@@ -255,10 +268,12 @@ class cSoftOsd:public cOsd
 {
   public:
     static volatile char Dirty;		///< flag force redraw everything
-    int OsdLevel;			///< current osd level
+    int OsdLevel;			///< current osd level FIXME: remove
 
      cSoftOsd(int, int, uint);		///< osd constructor
      virtual ~ cSoftOsd(void);		///< osd destructor
+    /// set the sub-areas to the given areas
+    virtual eOsdError SetAreas(const tArea *, int);
     virtual void Flush(void);		///< commits all data to the hardware
     virtual void SetActive(bool);	///< sets OSD to be the active one
 };
@@ -284,11 +299,6 @@ void cSoftOsd::SetActive(bool on)
     }
     cOsd::SetActive(on);
 
-    // ignore sub-title if menu is open
-    if (OsdLevel >= OSD_LEVEL_SUBTITLES && IsOpen()) {
-	return;
-    }
-
     if (on) {
 	Dirty = 1;
 	// only flush here if there are already bitmaps
@@ -320,7 +330,6 @@ cSoftOsd::cSoftOsd(int left, int top, uint level)
 #endif
 
     OsdLevel = level;
-    SetActive(true);
 }
 
 /**
@@ -352,6 +361,31 @@ cSoftOsd::~cSoftOsd(void)
 }
 
 /**
++*	Set the sub-areas to the given areas
+*/
+eOsdError cSoftOsd::SetAreas(const tArea * areas, int n)
+{
+#ifdef OSD_DEBUG
+    dsyslog("[softhddev]%s: %d areas \n", __FUNCTION__, n);
+#endif
+
+    // clear old OSD, when new areas are set
+    if (!IsTrueColor()) {
+	cBitmap *bitmap;
+	int i;
+
+	for (i = 0; (bitmap = GetBitmap(i)); i++) {
+	    bitmap->Clean();
+	}
+    }
+    if (Active()) {
+	VideoOsdClear();
+	Dirty = 1;
+    }
+    return cOsd::SetAreas(areas, n);
+}
+
+/**
 **	Actually commits all data to the OSD hardware.
 */
 void cSoftOsd::Flush(void)
@@ -366,10 +400,6 @@ void cSoftOsd::Flush(void)
     if (!Active()) {			// this osd is not active
 	return;
     }
-    // don't draw sub-title if menu is active
-    if (OsdLevel >= OSD_LEVEL_SUBTITLES && IsOpen()) {
-	return;
-    }
 #ifdef USE_YAEPG
     // support yaepghd, video window
     if (vidWin.bpp) {
@@ -385,17 +415,6 @@ void cSoftOsd::Flush(void)
     }
 #endif
 
-    //
-    //	VDR draws subtitle without clearing the old
-    //
-    if (OsdLevel >= OSD_LEVEL_SUBTITLES) {
-	VideoOsdClear();
-	cSoftOsd::Dirty = 1;
-#ifdef OSD_DEBUG
-	dsyslog("[softhddev]%s: subtitle clear\n", __FUNCTION__);
-#endif
-    }
-
     if (!IsTrueColor()) {
 	cBitmap *bitmap;
 	int i;
@@ -472,7 +491,7 @@ void cSoftOsd::Flush(void)
 	    // FIXME: reuse argb
 	    free(argb);
 	}
-	cSoftOsd::Dirty = 0;
+	Dirty = 0;
 	return;
     }
 
@@ -496,7 +515,7 @@ void cSoftOsd::Flush(void)
 
 	delete pm;
     }
-    cSoftOsd::Dirty = 0;
+    Dirty = 0;
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -580,6 +599,7 @@ class cMenuSetupSoft:public cMenuSetupPage
     int General;
     int MakePrimary;
     int HideMainMenuEntry;
+    int DetachFromMainMenu;
     int OsdSize;
     int OsdWidth;
     int OsdHeight;
@@ -595,6 +615,7 @@ class cMenuSetupSoft:public cMenuSetupPage
     int _60HzMode;
     int SoftStartSync;
     int BlackPicture;
+    int ClearOnSwitch;
 
     int Brightness;
     int Contrast;
@@ -630,6 +651,7 @@ class cMenuSetupSoft:public cMenuSetupPage
     int AudioMaxCompression;
     int AudioStereoDescent;
     int AudioBufferTime;
+    int AudioAutoAES;
 
 #ifdef USE_PIP
     int Pip;
@@ -757,6 +779,8 @@ void cMenuSetupSoft::Create(void)
 	//	suspend
 	//
 	Add(SeparatorItem(tr("Suspend")));
+	Add(new cMenuEditBoolItem(tr("Detach from main menu entry"),
+		&DetachFromMainMenu, trVDR("no"), trVDR("yes")));
 	Add(new cMenuEditBoolItem(tr("Suspend closes video+audio"),
 		&SuspendClose, trVDR("no"), trVDR("yes")));
 	Add(new cMenuEditBoolItem(tr("Suspend stops x11"), &SuspendX11,
@@ -785,6 +809,8 @@ void cMenuSetupSoft::Create(void)
 		trVDR("no"), trVDR("yes")));
 	Add(new cMenuEditBoolItem(tr("Black during channel switch"),
 		&BlackPicture, trVDR("no"), trVDR("yes")));
+	Add(new cMenuEditBoolItem(tr("Clear decoder on channel switch"),
+		&ClearOnSwitch, trVDR("no"), trVDR("yes")));
 
 	Add(new cMenuEditIntItem(tr("Brightness (-1000..1000) (vdpau)"),
 		&Brightness, -1000, 1000, tr("min"), tr("max")));
@@ -872,6 +898,8 @@ void cMenuSetupSoft::Create(void)
 		&AudioStereoDescent, 0, 1000));
 	Add(new cMenuEditIntItem(tr("Audio buffer size (ms)"),
 		&AudioBufferTime, 0, 1000));
+	Add(new cMenuEditBoolItem(tr("Enable automatic AES"), &AudioAutoAES,
+		trVDR("no"), trVDR("yes")));
     }
 #ifdef USE_PIP
     //
@@ -977,6 +1005,7 @@ cMenuSetupSoft::cMenuSetupSoft(void)
     General = 0;
     MakePrimary = ConfigMakePrimary;
     HideMainMenuEntry = ConfigHideMainMenuEntry;
+    DetachFromMainMenu = ConfigDetachFromMainMenu;
     //
     //	osd
     //
@@ -1010,6 +1039,7 @@ cMenuSetupSoft::cMenuSetupSoft(void)
     _60HzMode = ConfigVideo60HzMode;
     SoftStartSync = ConfigVideoSoftStartSync;
     BlackPicture = ConfigVideoBlackPicture;
+    ClearOnSwitch = ConfigVideoClearOnSwitch;
 
     Brightness = ConfigVideoBrightness;
     Contrast = ConfigVideoContrast;
@@ -1053,6 +1083,7 @@ cMenuSetupSoft::cMenuSetupSoft(void)
     AudioMaxCompression = ConfigAudioMaxCompression;
     AudioStereoDescent = ConfigAudioStereoDescent;
     AudioBufferTime = ConfigAudioBufferTime;
+    AudioAutoAES = ConfigAudioAutoAES;
 
 #ifdef USE_PIP
     //
@@ -1089,6 +1120,8 @@ void cMenuSetupSoft::Store(void)
     SetupStore("MakePrimary", ConfigMakePrimary = MakePrimary);
     SetupStore("HideMainMenuEntry", ConfigHideMainMenuEntry =
 	HideMainMenuEntry);
+    SetupStore("DetachFromMainMenu", ConfigDetachFromMainMenu =
+	DetachFromMainMenu);
     switch (OsdSize) {
 	case 0:
 	    OsdWidth = 0;
@@ -1133,6 +1166,7 @@ void cMenuSetupSoft::Store(void)
     VideoSetSoftStartSync(ConfigVideoSoftStartSync);
     SetupStore("BlackPicture", ConfigVideoBlackPicture = BlackPicture);
     VideoSetBlackPicture(ConfigVideoBlackPicture);
+    SetupStore("ClearOnSwitch", ConfigVideoClearOnSwitch = ClearOnSwitch);
 
     SetupStore("Brightness", ConfigVideoBrightness = Brightness);
     VideoSetBrightness(ConfigVideoBrightness);
@@ -1214,6 +1248,8 @@ void cMenuSetupSoft::Store(void)
 	AudioStereoDescent);
     AudioSetStereoDescent(ConfigAudioStereoDescent);
     SetupStore("AudioBufferTime", ConfigAudioBufferTime = AudioBufferTime);
+    SetupStore("AudioAutoAES", ConfigAudioAutoAES = AudioAutoAES);
+    AudioSetAutoAES(ConfigAudioAutoAES);
 
 #ifdef USE_PIP
     SetupStore("pip.X", ConfigPipX = PipX);
@@ -1746,7 +1782,12 @@ void cSoftHdMenu::Create(void)
     Clear();				// clear the menu
 
     SetHasHotkeys();
-    Add(new cOsdItem(hk(tr("Suspend SoftHdDevice")), osUser1));
+
+    if (ConfigDetachFromMainMenu) {
+	Add(new cOsdItem(hk(tr("Detach SoftHdDevice")), osUser1));
+    } else {
+	Add(new cOsdItem(hk(tr("Suspend SoftHdDevice")), osUser1));
+    }
 #ifdef USE_PIP
     if (PipReceiver) {
 	Add(new cOsdItem(hk(tr("PIP toggle on/off: off")), osUser2));
@@ -1916,6 +1957,7 @@ static void HandleHotkey(int code)
 	    break;
 	case 108:
 	    DelPip();
+	    PipChannelNr = 0;
 	    break;
 #endif
 
@@ -1993,9 +2035,14 @@ eOSState cSoftHdMenu::ProcessKey(eKeys key)
 	    if (SuspendMode == NOT_SUSPENDED && !cSoftHdControl::Player) {
 		cControl::Launch(new cSoftHdControl);
 		cControl::Attach();
-		Suspend(ConfigSuspendClose, ConfigSuspendClose,
-		    ConfigSuspendX11);
-		SuspendMode = SUSPEND_NORMAL;
+		if (ConfigDetachFromMainMenu) {
+		    Suspend(1, 1, 0);
+		    SuspendMode = SUSPEND_DETACHED;
+		} else {
+		    Suspend(ConfigSuspendClose, ConfigSuspendClose,
+			ConfigSuspendX11);
+		    SuspendMode = SUSPEND_NORMAL;
+		}
 		if (ShutdownHandler.GetUserInactiveTime()) {
 		    dsyslog("[softhddev]%s: set user inactive\n",
 			__FUNCTION__);
@@ -2021,6 +2068,7 @@ eOSState cSoftHdMenu::ProcessKey(eKeys key)
 	    return osEnd;
 	case osUser8:
 	    DelPip();
+	    PipChannelNr = 0;
 	    return osEnd;
 #endif
 	default:
@@ -2043,7 +2091,11 @@ class cSoftHdDevice:public cDevice
     virtual bool HasDecoder(void) const;
     virtual bool CanReplay(void) const;
     virtual bool SetPlayMode(ePlayMode);
+#if APIVERSNUM >= 20103
+    virtual void TrickSpeed(int, bool);
+#else
     virtual void TrickSpeed(int);
+#endif
     virtual void Clear(void);
     virtual void Play(void);
     virtual void Freeze(void);
@@ -2231,13 +2283,23 @@ int64_t cSoftHdDevice::GetSTC(void)
 **	times.
 **
 **	@param speed	trick speed
+**	@param forward	flag forward direction
 */
+#if APIVERSNUM >= 20103
+void cSoftHdDevice::TrickSpeed(int speed, bool forward)
+{
+    dsyslog("[softhddev]%s: %d $d\n", __FUNCTION__, speed, forward);
+
+    ::TrickSpeed(speed);
+}
+#else
 void cSoftHdDevice::TrickSpeed(int speed)
 {
     dsyslog("[softhddev]%s: %d\n", __FUNCTION__, speed);
 
     ::TrickSpeed(speed);
 }
+#endif
 
 /**
 **	Clears all video and audio data from the device.
@@ -2542,8 +2604,8 @@ cRect cSoftHdDevice::CanScaleVideo(const cRect & rect,
 void cSoftHdDevice::ScaleVideo(const cRect & rect)
 {
 #ifdef OSD_DEBUG
-    dsyslog("[softhddev]%s: %dx%d%+d%+d\n", __FUNCTION__, VidWinRect.Width(),
-	VidWinRect.Height(), VidWinRect.X(), VidWinRect.Y());
+    dsyslog("[softhddev]%s: %dx%d%+d%+d\n", __FUNCTION__, rect.Width(),
+	rect.Height(), rect.X(), rect.Y());
 #endif
     ::ScaleVideo(rect.X(), rect.Y(), rect.Width(), rect.Height());
 }
@@ -2803,6 +2865,10 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
 	ConfigHideMainMenuEntry = atoi(value);
 	return true;
     }
+    if (!strcasecmp(name, "DetachFromMainMenu")) {
+	ConfigDetachFromMainMenu = atoi(value);
+	return true;
+    }
     if (!strcasecmp(name, "Osd.Width")) {
 	ConfigOsdWidth = atoi(value);
 	VideoSetOsdSize(ConfigOsdWidth, ConfigOsdHeight);
@@ -2852,6 +2918,10 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
 	VideoSetBlackPicture(ConfigVideoBlackPicture = atoi(value));
 	return true;
     }
+    if (!strcasecmp(name, "ClearOnSwitch")) {
+	ConfigVideoClearOnSwitch = atoi(value);
+	return true;
+    }
     if (!strcasecmp(name, "Brightness")) {
 	VideoSetBrightness(ConfigVideoBrightness = atoi(value));
 	return true;
@@ -2998,6 +3068,11 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
 	ConfigAudioBufferTime = atoi(value);
 	return true;
     }
+    if (!strcasecmp(name, "AudioAutoAES")) {
+	ConfigAudioAutoAES = atoi(value);
+	AudioSetAutoAES(ConfigAudioAutoAES);
+	return true;
+    }
 #ifdef USE_PIP
     if (!strcasecmp(name, "pip.X")) {
 	ConfigPipX = atoi(value);
diff --git a/softhddevice.h b/softhddevice.h
index 1729441..3bc4480 100644
--- a/softhddevice.h
+++ b/softhddevice.h
@@ -1,7 +1,7 @@
 ///
 ///	@file softhddevice.h	@brief software HD device plugin header file.
 ///
-///	Copyright (c) 2011 by Johns.  All Rights Reserved.
+///	Copyright (c) 2011, 2014 by Johns.  All Rights Reserved.
 ///
 ///	Contributor(s):
 ///
diff --git a/vdr-softhddevice-9999-pre1.7.36.ebuild b/vdr-softhddevice-9999-pre1.7.36.ebuild
deleted file mode 100644
index b5f708f..0000000
--- a/vdr-softhddevice-9999-pre1.7.36.ebuild
+++ /dev/null
@@ -1,74 +0,0 @@
-# Copyright 1999-2012 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-# $Header: $
-
-EAPI="4"
-
-inherit eutils vdr-plugin-2
-
-if [[ ${PV} == "9999" ]] ; then
-		inherit git-2
-		EGIT_REPO_URI="git://projects.vdr-developer.org/vdr-plugin-softhddevice.git"
-else
-		SRC_URI="http://projects.vdr-developer.org/attachments/download/838/${P}.tgz"
-fi
-
-
-DESCRIPTION="A software and GPU emulated HD output device plugin for VDR."
-HOMEPAGE="http://projects.vdr-developer.org/projects/show/plg-softhddevice"
-SRC_URI=""
-
-LICENSE="AGPL-3"
-SLOT="0"
-KEYWORDS="~x86 ~amd64"
-IUSE="vaapi vdpau alsa oss yaepg opengl debug"
-
-DEPEND=">=x11-libs/libxcb-1.8
-		x11-libs/xcb-util
-		x11-libs/xcb-util-wm
-		x11-libs/xcb-util-keysyms
-		x11-libs/xcb-util-renderutil
-		x11-libs/libX11
-		opengl? ( virtual/opengl )
-		>=virtual/ffmpeg-0.7
-		sys-devel/gettext
-		sys-devel/make
-		dev-util/pkgconfig
-		yaepg? ( >=media-video/vdr-1.7.23[yaepg] )
-		!yaepg? ( >=media-video/vdr-1.7.23 )
-		vdpau? ( x11-libs/libvdpau virtual/ffmpeg[vdpau] )
-		vaapi? ( x11-libs/libva virtual/ffmpeg[vaapi] )
-		alsa? ( media-libs/alsa-lib )
-		oss? ( sys-kernel/linux-headers )
-"
-
-src_prepare() {
-		vdr-plugin-2_src_prepare
-}
-
-src_compile() {
-		local myconf
-
-		myconf="-DHAVE_PTHREAD_NAME -DAV_INFO -DAV_INFO_TIME=15000"
-		use vdpau && myconf="${myconf} -DUSE_VDPAU"
-		use vaapi && myconf="${myconf} -DUSE_VAAPI"
-		use alsa && myconf="${myconf} -DUSE_ALSA"
-		use oss && myconf="${myconf} -DUSE_OSS"
-		use debug && myconf="${myconf} -DDEBUG"
-
-		#vdr-plugin-2_src_compile
-		cd "${S}"
-
-		BUILD_TARGETS=${BUILD_TARGETS:-${VDRPLUGIN_MAKE_TARGET:-all}}
-
-		emake ${BUILD_PARAMS} CONFIG="${myconf}" \
-				${BUILD_TARGETS} \
-				LOCALEDIR="${TMP_LOCALE_DIR}" \
-				LIBDIR="${S}" \
-				TMPDIR="${T}" \
-		|| die "emake failed"
-}
-
-src_install() {
-		vdr-plugin-2_src_install
-}
diff --git a/vdr-softhddevice-9999.ebuild b/vdr-softhddevice-9999.ebuild
index 2365a52..7a2fbea 100644
--- a/vdr-softhddevice-9999.ebuild
+++ b/vdr-softhddevice-9999.ebuild
@@ -1,67 +1,73 @@
-# Copyright 1999-2012 Gentoo Foundation
+# Copyright 1999-2014 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 # $Header: $
 
 EAPI="5"
 
-inherit flag-o-matic toolchain-funcs vdr-plugin-2 eutils
+inherit vdr-plugin-2 git-2
 
-if [ "${PV}" = "9999" ]; then
-	inherit git-2
-	EGIT_REPO_URI="git://projects.vdr-developer.org/vdr-plugin-softhddevice.git"
-	KEYWORDS=""
-else
-	SRC_URI="mirror://vdr-developerorg/889/${P}.tgz"
-	KEYWORDS="~amd64 ~x86"
-fi
+RESTRICT="test"
 
-DESCRIPTION="Software and GPU emulated HD output device plugin for VDR"
+EGIT_REPO_URI="git://projects.vdr-developer.org/vdr-plugin-softhddevice.git"
+KEYWORDS=""
+
+DESCRIPTION="VDR Plugin: Software and GPU emulated HD output device"
 HOMEPAGE="http://projects.vdr-developer.org/projects/show/plg-softhddevice"
 
 LICENSE="AGPL-3"
 SLOT="0"
-IUSE="alsa oss vaapi vdpau opengl yaepg xscreensaver debug"
+IUSE="alsa +debug opengl oss vaapi vdpau xscreensaver"
 
-RDEPEND=">=media-video/vdr-1.7
-	>=virtual/ffmpeg-0.7[vdpau?,vaapi?]
+RDEPEND=">=media-video/vdr-2
 	x11-libs/libX11
 	>=x11-libs/libxcb-1.8
 	x11-libs/xcb-util-wm
+	x11-libs/xcb-util-keysyms
+	x11-libs/xcb-util-renderutil
 	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] )"
+	vaapi? ( x11-libs/libva
+		virtual/ffmpeg[vaapi] )
+	vdpau? ( x11-libs/libvdpau
+		virtual/ffmpeg[vdpau] )"
 DEPEND="${RDEPEND}
-	x11-libs/xcb-util
-	sys-devel/gettext
 	virtual/pkgconfig
-	oss? ( sys-kernel/linux-headers )"
-
-src_compile() {
-	local myconf
-
-	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
-		myconf+=" SWRESAMPLE=1"
-	fi
+	x11-libs/xcb-util"
+
+REQUIRED_USE="opengl? ( vaapi )
+			|| ( vaapi vdpau )
+			|| ( alsa oss )"
+
+#VDR_CONFD_FILE="${FILESDIR}/confd-0.6.0"
+#VDR_RCADDON_FILE="${FILESDIR}/rc-addon-0.6.0.sh"
+
+pkg_setup() {
+	vdr-plugin-2_pkg_setup
 
-	append-cflags -DHAVE_PTHREAD_NAME -D_GNU_SOURCE
-	append-cxxflags -DHAVE_PTHREAD_NAME -D_GNU_SOURCE
-	tc-export CC CXX
+	append-cppflags -DHAVE_PTHREAD_NAME
 
-	BUILD_PARAMS="${myconf}"
-	vdr-plugin-2_src_compile
+	use debug && append-cppflags -DDEBUG -DOSD_DEBUG
+}
+src_prepare() {
+	vdr-plugin-2_src_prepare
+
+	BUILD_PARAMS+=" ALSA=$(usex alsa 1 0)"
+	BUILD_PARAMS+=" OPENGL=$(usex opengl 1 0)"
+	BUILD_PARAMS+=" OSS=$(usex oss 1 0)"
+	BUILD_PARAMS+=" VAAPI=$(usex vaapi 1 0)"
+	BUILD_PARAMS+=" VDPAU=$(usex vdpau 1 0)"
+	BUILD_PARAMS+=" SCREENSAVER=$(usex xscreensaver 1 0)"
+
+	if has_version ">=media-video/ffmpeg-0.8"; then
+		BUILD_PARAMS+=" SWRESAMPLE=1"
+	fi
+	if has_version ">=media-video/libav-0.8"; then
+		BUILD_PARAMS+=" AVRESAMPLE=1"
+	fi
 }
 
 src_install() {
 	vdr-plugin-2_src_install
 
-	dodoc ChangeLog README.txt
+	nonfatal dodoc ChangeLog Todo
 }
diff --git a/video.c b/video.c
index afe5714..a5b3a5a 100644
--- a/video.c
+++ b/video.c
@@ -1,7 +1,7 @@
 ///
 ///	@file video.c	@brief Video module
 ///
-///	Copyright (c) 2009 - 2013 by Johns.  All Rights Reserved.
+///	Copyright (c) 2009 - 2014 by Johns.  All Rights Reserved.
 ///
 ///	Contributor(s):
 ///
@@ -46,7 +46,7 @@
 #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
+//#define USE_BITMAP			///< use vdpau bitmap surface
 //#define AV_INFO				///< log a/v sync informations
 #ifndef AV_INFO_TIME
 #define AV_INFO_TIME (50 * 60)		///< a/v info every minute
@@ -64,13 +64,12 @@
 #include <stdint.h>
 #include <string.h>
 #include <unistd.h>
+#include <math.h>
 
 #include <libintl.h>
 #define _(str) gettext(str)		///< gettext shortcut
 #define _N(str) str			///< gettext_noop shortcut
 
-#include <alsa/iatomic.h>		// portable atomic_t
-
 #ifdef USE_VIDEO_THREAD
 #ifndef __USE_GNU
 #define __USE_GNU
@@ -135,6 +134,9 @@ typedef enum
 
 #ifdef USE_VAAPI
 #include <va/va_x11.h>
+#if VA_CHECK_VERSION(0,33,99)
+#include <va/va_vpp.h>
+#endif
 #ifdef USE_GLX
 #include <va/va_glx.h>
 #endif
@@ -175,6 +177,7 @@ typedef enum
 #define FFMPEG_BUG1_WORKAROUND		///< get_format bug workaround
 #endif
 
+#include "iatomic.h"			// portable atomic_t
 #include "misc.h"
 #include "video.h"
 #include "audio.h"
@@ -912,13 +915,13 @@ static void GlxOsdClear(void)
     // FIXME: if not; use zero buffer
     // FIXME: if not; use dirty area
 
-    texbuf = calloc(OsdWidth * OsdHeight, 4);
-
     // set glx context
     if (!glXMakeCurrent(XlibDisplay, VideoWindow, GlxContext)) {
 	Error(_("video/glx: can't make glx context current\n"));
 	return;
     }
+
+    texbuf = calloc(OsdWidth * OsdHeight, 4);
     GlxUploadOsdTexture(0, 0, OsdWidth, OsdHeight, texbuf);
     glXMakeCurrent(XlibDisplay, None, NULL);
 
@@ -1454,6 +1457,10 @@ static VAImage VaOsdImage = {
 static VASubpictureID VaOsdSubpicture = VA_INVALID_ID;	///< osd VA-API subpicture
 static char VaapiUnscaledOsd;		///< unscaled osd supported
 
+#if VA_CHECK_VERSION(0,33,99)
+static char VaapiVideoProcessing;	///< supports video processing
+#endif
+
     /// VA-API decoder typedef
 typedef struct _vaapi_decoder_ VaapiDecoder;
 
@@ -1537,6 +1544,7 @@ struct _vaapi_decoder_
     int SyncOnAudio;			///< flag sync to audio
     int64_t PTS;			///< video PTS clock
 
+    int LastAVDiff;			///< last audio - video difference
     int SyncCounter;			///< counter to sync frames
     int StartCounter;			///< counter for video start
     int FramesDuped;			///< number of frames duplicated
@@ -2363,6 +2371,28 @@ static int VaapiInit(const char *display_name)
     Vaapi1080i();
 #endif
 
+#if VA_CHECK_VERSION(0,33,99)
+    //
+    //	check vpp support
+    //
+    if (1) {
+	VAEntrypoint entrypoints[vaMaxNumEntrypoints(VaDisplay)];
+	int entrypoint_n;
+	int i;
+
+	vaQueryConfigEntrypoints(VaDisplay, VAProfileNone, entrypoints,
+	    &entrypoint_n);
+
+	VaapiVideoProcessing = 0;
+	for (i = 0; i < entrypoint_n; i++) {
+	    if (entrypoints[i] == VAEntrypointVideoProc) {
+		Info("video/vaapi: supports video processing\n");
+		VaapiVideoProcessing = 1;
+		break;
+	    }
+	}
+    }
+#endif
     return 1;
 }
 
@@ -2586,6 +2616,126 @@ static void VaapiSetup(VaapiDecoder * decoder,
 }
 
 ///
+///	Configure VA-API for new video format.
+///
+///	@param decoder	VA-API decoder
+///
+static void VaapiSetupVideoProcessing(VaapiDecoder * decoder)
+{
+#if VA_CHECK_VERSION(0,33,99)
+    VAProcFilterType filtertypes[VAProcFilterCount];
+    unsigned filtertype_n;
+    unsigned u;
+    unsigned v;
+    VAProcFilterCap denoise_caps[1];
+    unsigned denoise_cap_n;
+    VAProcFilterCapDeinterlacing deinterlacing_caps[VAProcDeinterlacingCount];
+    unsigned deinterlacing_cap_n;
+    VABufferID denoise_filter;
+    VABufferID deint_filter;
+    VABufferID sharpen_filter;
+    VABufferID color_filter;
+    VABufferID filters[VAProcFilterCount];
+    unsigned filter_n;
+
+    if (!VaapiVideoProcessing) {
+	return;
+    }
+    //
+    //	display and filter infos.
+    //
+    filtertype_n = VAProcFilterCount;	// API break this must be done
+    vaQueryVideoProcFilters(VaDisplay, decoder->VaapiContext->context_id,
+	filtertypes, &filtertype_n);
+    for (u = 0; u < filtertype_n; ++u) {
+	switch (filtertypes[u]) {
+	    case VAProcFilterNoiseReduction:
+		Info("video/vaapi: noise reduction supported\n");
+
+		denoise_cap_n = 1;
+		vaQueryVideoProcFilterCaps(VaDisplay,
+		    decoder->VaapiContext->context_id,
+		    VAProcFilterNoiseReduction, denoise_caps, &denoise_cap_n);
+		if (denoise_cap_n) {
+		    Info("video/vaapi: %.2f - %.2f ++ %.2f = %.2f\n",
+			denoise_caps->range.min_value,
+			denoise_caps->range.max_value,
+			denoise_caps->range.step,
+			denoise_caps->range.default_value);
+		}
+		break;
+	    case VAProcFilterDeinterlacing:
+		Info("video/vaapi: deinterlacing supported\n");
+
+		deinterlacing_cap_n = VAProcDeinterlacingCount;
+		vaQueryVideoProcFilterCaps(VaDisplay,
+		    decoder->VaapiContext->context_id,
+		    VAProcFilterDeinterlacing, deinterlacing_caps,
+		    &deinterlacing_cap_n);
+		for (v = 0; v < deinterlacing_cap_n; ++v) {
+		    switch (deinterlacing_caps[v].type) {
+			case VAProcDeinterlacingBob:
+			    Info("video/vaapi: bob deinterlace supported\n");
+			    break;
+			case VAProcDeinterlacingWeave:
+			    Info("video/vaapi: weave deinterlace supported\n");
+			    break;
+			case VAProcDeinterlacingMotionAdaptive:
+			    Info("video/vaapi: motion adaptive deinterlace supported\n");
+			    break;
+			case VAProcDeinterlacingMotionCompensated:
+			    Info("video/vaapi: motion compensated deinterlace supported\n");
+			    break;
+			default:
+			    Info("video/vaapi: unsupported deinterlace #%02x\n", deinterlacing_caps[v].type);
+			    break;
+		    }
+		}
+		break;
+	    case VAProcFilterSharpening:
+		Info("video/vaapi: sharpening supported\n");
+		break;
+	    case VAProcFilterColorBalance:
+		Info("video/vaapi: color balance supported\n");
+		break;
+	    default:
+		Info("video/vaapi: unsupported filter #%02x\n",
+		    filtertypes[u]);
+		break;
+	}
+    }
+
+    //
+    //	create pipeline filters
+    //
+    filter_n = 0;
+
+    filtertype_n = VAProcFilterCount;
+    vaQueryVideoProcFilters(VaDisplay, decoder->VaapiContext->context_id,
+	filtertypes, &filtertype_n);
+    for (u = 0; u < filtertype_n; ++u) {
+	switch (filtertypes[u]) {
+	    case VAProcFilterNoiseReduction:
+		break;
+	    case VAProcFilterDeinterlacing:
+		break;
+	    case VAProcFilterSharpening:
+		break;
+	    case VAProcFilterColorBalance:
+		break;
+	    default:
+		break;
+	}
+    }
+
+    //
+    //	query pipeline caps
+    //
+
+#endif
+}
+
+///
 ///	Get a free surface.  Called from ffmpeg.
 ///
 ///	@param decoder		VA-API decoder
@@ -2626,6 +2776,7 @@ static VASurfaceID VaapiGetSurface(VaapiDecoder * decoder,
 		vaErrorStr(status));
 	}
 	// FIXME: too late to switch to software rending on failures
+	VaapiSetupVideoProcessing(decoder);
     }
 #else
     (void)video_ctx;
@@ -2858,6 +3009,7 @@ static enum PixelFormat Vaapi_get_format(VaapiDecoder * decoder,
 	    Error(_("codec: can't create context '%s'\n"), vaErrorStr(status));
 	    goto slow_path;
 	}
+	VaapiSetupVideoProcessing(decoder);
     }
 #endif
 
@@ -3490,7 +3642,7 @@ static void VaapiBlackSurface(VaapiDecoder * decoder)
 		VA_FRAME_PICTURE)) != VA_STATUS_SUCCESS) {
 	Error(_("video/vaapi: vaPutSurface failed %d\n"), status);
     }
-    clock_gettime(CLOCK_REALTIME, &decoder->FrameTime);
+    clock_gettime(CLOCK_MONOTONIC, &decoder->FrameTime);
 
     put1 = GetMsTicks();
     if (put1 - sync > 2000) {
@@ -4730,7 +4882,7 @@ static void VaapiDisplayFrame(void)
 	    put2 = put1;
 #endif
 	}
-	clock_gettime(CLOCK_REALTIME, &nowtime);
+	clock_gettime(CLOCK_MONOTONIC, &nowtime);
 	// FIXME: 31 only correct for 50Hz
 	if ((nowtime.tv_sec - decoder->FrameTime.tv_sec)
 	    * 1000 * 1000 * 1000 + (nowtime.tv_nsec -
@@ -4893,7 +5045,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 + 25 * 90) {
 	    goto out;
 	}
 	// out of sync: audio before video
@@ -4928,22 +5080,26 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
     if (audio_clock != (int64_t) AV_NOPTS_VALUE
 	&& video_clock != (int64_t) AV_NOPTS_VALUE) {
 	// both clocks are known
+	int diff;
 
-	if (abs(video_clock - audio_clock + VideoAudioDelay) > 5000 * 90) {
+	diff = video_clock - audio_clock - VideoAudioDelay;
+	diff = (decoder->LastAVDiff + diff) / 2;
+	decoder->LastAVDiff = diff;
+
+	if (abs(diff) > 5000 * 90) {	// more than 5s
 	    err = VaapiMessage(2, "video: audio/video difference too big\n");
-	} else if (video_clock > audio_clock + VideoAudioDelay + 100 * 90) {
+	} else if (diff > 100 * 90) {
 	    // FIXME: this quicker sync step, did not work with new code!
 	    err = VaapiMessage(2, "video: slow down video, duping frame\n");
 	    ++decoder->FramesDuped;
 	    decoder->SyncCounter = 1;
 	    goto out;
-	} else if (video_clock > audio_clock + VideoAudioDelay + 45 * 90) {
+	} else if (diff > 55 * 90) {
 	    err = VaapiMessage(2, "video: slow down video, duping frame\n");
 	    ++decoder->FramesDuped;
 	    decoder->SyncCounter = 1;
 	    goto out;
-	} else if (audio_clock + VideoAudioDelay > video_clock + 15 * 90
-	    && filled > 1 + 2 * decoder->Interlaced) {
+	} else if (diff < -25 * 90 && filled > 1 + 2 * decoder->Interlaced) {
 	    err = VaapiMessage(2, "video: speed up video, droping frame\n");
 	    ++decoder->FramesDropped;
 	    VaapiAdvanceDecoderFrame(decoder);
@@ -4974,7 +5130,10 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
 		_("video: decoder buffer empty, "
 		    "duping frame (%d/%d) %d v-buf\n"), decoder->FramesDuped,
 		decoder->FrameCounter, VideoGetBuffers(decoder->Stream));
-	    if (decoder->Closing < -300) {
+	    // some time no new picture or black video configured
+	    if (decoder->Closing < -300 || (VideoShowBlackPicture
+		    && decoder->Closing)) {
+		// clear ring buffer to trigger black picture
 		atomic_set(&decoder->SurfacesFilled, 0);
 	    }
 	}
@@ -5154,7 +5313,7 @@ static void VaapiDisplayHandlerThread(void)
 	}
     }
 
-    clock_gettime(CLOCK_REALTIME, &nowtime);
+    clock_gettime(CLOCK_MONOTONIC, &nowtime);
     // time for one frame over?
     if ((nowtime.tv_sec - decoder->FrameTime.tv_sec)
 	* 1000 * 1000 * 1000 + (nowtime.tv_nsec - decoder->FrameTime.tv_nsec) <
@@ -5336,7 +5495,7 @@ static void VaapiOsdInit(int width, int height)
 
     VaapiUnscaledOsd = 0;
     if (flags[u] & VA_SUBPICTURE_DESTINATION_IS_SCREEN_COORD) {
-	Info(_("video/vaapi: vaapi supports unscaled osd\n"));
+	Info(_("video/vaapi: supports unscaled osd\n"));
 	VaapiUnscaledOsd = 1;
     }
     //VaapiUnscaledOsd = 0;
@@ -5563,6 +5722,7 @@ typedef struct _vdpau_decoder_
     int SyncOnAudio;			///< flag sync to audio
     int64_t PTS;			///< video PTS clock
 
+    int LastAVDiff;			///< last audio - video difference
     int SyncCounter;			///< counter to sync frames
     int StartCounter;			///< counter for video start
     int FramesDuped;			///< number of frames duplicated
@@ -8015,7 +8175,7 @@ static void VdpauMixOsd(void)
 	status =
 	    VdpauOutputSurfaceRenderBitmapSurface(VdpauSurfacesRb
 	    [VdpauSurfaceIndex], &output_double_rect,
-	    VdpauOsdOutputSurface[!VdpauOsdSurfaceIndex], &source_rect, NULL,
+	    VdpauOsdBitmapSurface[!VdpauOsdSurfaceIndex], &source_rect, NULL,
 	    VideoTransparentOsd ? &blend_state : NULL,
 	    VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);
 	if (status != VDP_STATUS_OK) {
@@ -8244,15 +8404,29 @@ static void VdpauBlackSurface(VdpauDecoder * decoder)
 	output_rect.y1 = decoder->VideoHeight;
     }
 
+    // FIXME: double buffered osd disabled
+    // VdpauOsdSurfaceIndex always 0 and only 0 valid
+#ifdef USE_BITMAP
+    status =
+	VdpauOutputSurfaceRenderBitmapSurface(VdpauSurfacesRb
+	[VdpauSurfaceIndex], &output_rect,
+	VdpauOsdBitmapSurface[VdpauOsdSurfaceIndex], &source_rect, NULL, NULL,
+	VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);
+    if (status != VDP_STATUS_OK) {
+	Error(_("video/vdpau: can't render output surface: %s\n"),
+	    VdpauGetErrorString(status));
+    }
+#else
     status =
 	VdpauOutputSurfaceRenderOutputSurface(VdpauSurfacesRb
 	[VdpauSurfaceIndex], &output_rect,
-	VdpauOsdOutputSurface[!VdpauOsdSurfaceIndex], &source_rect, NULL, NULL,
+	VdpauOsdOutputSurface[VdpauOsdSurfaceIndex], &source_rect, NULL, NULL,
 	VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);
     if (status != VDP_STATUS_OK) {
 	Error(_("video/vdpau: can't render output surface: %s\n"),
 	    VdpauGetErrorString(status));
     }
+#endif
 }
 
 ///
@@ -8376,7 +8550,7 @@ static void VdpauDisplayFrame(void)
 	    VdpauGetErrorString(status));
     }
     // FIXME: CLOCK_MONOTONIC_RAW
-    clock_gettime(CLOCK_REALTIME, &VdpauFrameTime);
+    clock_gettime(CLOCK_MONOTONIC, &VdpauFrameTime);
     for (i = 0; i < VdpauDecoderN; ++i) {
 	// remember time of last shown surface
 	VdpauDecoders[i]->FrameTime = VdpauFrameTime;
@@ -8519,7 +8693,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 + 25 * 90) {
 	    goto out;
 	}
 	// out of sync: audio before video
@@ -8553,22 +8727,26 @@ static void VdpauSyncDecoder(VdpauDecoder * decoder)
     if (audio_clock != (int64_t) AV_NOPTS_VALUE
 	&& video_clock != (int64_t) AV_NOPTS_VALUE) {
 	// both clocks are known
+	int diff;
+
+	diff = video_clock - audio_clock - VideoAudioDelay;
+	diff = (decoder->LastAVDiff + diff) / 2;
+	decoder->LastAVDiff = diff;
 
-	if (abs(video_clock - audio_clock + VideoAudioDelay) > 5000 * 90) {
+	if (abs(diff) > 5000 * 90) {	// more than 5s
 	    err = VdpauMessage(2, "video: audio/video difference too big\n");
-	} else if (video_clock > audio_clock + VideoAudioDelay + 100 * 90) {
+	} else if (diff > 100 * 90) {
 	    // FIXME: this quicker sync step, did not work with new code!
 	    err = VdpauMessage(2, "video: slow down video, duping frame\n");
 	    ++decoder->FramesDuped;
 	    decoder->SyncCounter = 1;
 	    goto out;
-	} else if (video_clock > audio_clock + VideoAudioDelay + 45 * 90) {
+	} else if (diff > 55 * 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
-	    && filled > 1 + 2 * decoder->Interlaced) {
+	} else if (diff < -25 * 90 && filled > 1 + 2 * decoder->Interlaced) {
 	    err = VdpauMessage(2, "video: speed up video, droping frame\n");
 	    ++decoder->FramesDropped;
 	    VdpauAdvanceDecoderFrame(decoder);
@@ -8599,7 +8777,10 @@ static void VdpauSyncDecoder(VdpauDecoder * decoder)
 		_("video: decoder buffer empty, "
 		    "duping frame (%d/%d) %d v-buf\n"), decoder->FramesDuped,
 		decoder->FrameCounter, VideoGetBuffers(decoder->Stream));
-	    if (decoder->Closing < -300) {
+	    // some time no new picture or black video configured
+	    if (decoder->Closing < -300 || (VideoShowBlackPicture
+		    && decoder->Closing)) {
+		// clear ring buffer to trigger black picture
 		atomic_set(&decoder->SurfacesFilled, 0);
 	    }
 	}
@@ -8874,7 +9055,7 @@ static void VdpauDisplayHandlerThread(void)
 	usleep(5 * 1000);
     }
 
-    clock_gettime(CLOCK_REALTIME, &nowtime);
+    clock_gettime(CLOCK_MONOTONIC, &nowtime);
     // time for one frame over?
     if ((nowtime.tv_sec - VdpauFrameTime.tv_sec) * 1000 * 1000 * 1000 +
 	(nowtime.tv_nsec - VdpauFrameTime.tv_nsec) < 15 * 1000 * 1000) {
@@ -8883,7 +9064,7 @@ static void VdpauDisplayHandlerThread(void)
 
     if (VdpauPreemption) {		// display preempted
 	if (VdpauPreemptionRecover()) {
-	    clock_gettime(CLOCK_REALTIME, &VdpauFrameTime);
+	    clock_gettime(CLOCK_MONOTONIC, &VdpauFrameTime);
 	    return;
 	}
     }
@@ -8915,7 +9096,7 @@ static void VdpauDisplayHandlerThread(void)
 static void VdpauSetOutputPosition(VdpauDecoder * decoder, int x, int y,
     int width, int height)
 {
-    Debug(3, "video/vdapu: output %dx%d%+d%+d\n", width, height, x, y);
+    Debug(3, "video/vdpau: output %dx%d%+d%+d\n", width, height, x, y);
 
     decoder->VideoX = x;
     decoder->VideoY = y;
@@ -9510,7 +9691,7 @@ void VideoOsdExit(void)
 //----------------------------------------------------------------------------
 
 /// C callback feed key press
-extern void FeedKeyPress(const char *, const char *, int, int);
+extern void FeedKeyPress(const char *, const char *, int, int, const char *);
 
 ///
 ///	Handle XLib I/O Errors.
@@ -9554,6 +9735,7 @@ static void VideoEvent(void)
     KeySym keysym;
     const char *keynam;
     char buf[64];
+    char letter[64];
     uint32_t values[1];
 
     VideoThreadLock();
@@ -9564,7 +9746,7 @@ static void VideoEvent(void)
 	    Debug(3, "video/event: ClientMessage\n");
 	    if (event.xclient.data.l[0] == (long)WmDeleteWindowAtom) {
 		Debug(3, "video/event: wm-delete-message\n");
-		FeedKeyPress("XKeySym", "Close", 0, 0);
+		FeedKeyPress("XKeySym", "Close", 0, 0, NULL);
 	    }
 	    break;
 
@@ -9593,7 +9775,7 @@ static void VideoEvent(void)
 	    break;
 	case KeyPress:
 	    VideoThreadLock();
-	    XLookupString(&event.xkey, buf, sizeof(buf), &keysym, NULL);
+	    XLookupString(&event.xkey, letter, sizeof(letter), &keysym, NULL);
 	    VideoThreadUnlock();
 	    if (keysym == NoSymbol) {
 		Warning(_("video/event: No symbol for %d\n"),
@@ -9616,7 +9798,7 @@ static void VideoEvent(void)
 		strncat(buf, keynam, sizeof(buf) - 10);
 		keynam = buf;
 	    }
-	    FeedKeyPress("XKeySym", keynam, 0, 0);
+	    FeedKeyPress("XKeySym", keynam, 0, 0, letter);
 	    break;
 	case KeyRelease:
 	    break;
@@ -11273,7 +11455,8 @@ void FeedKeyPress( __attribute__ ((unused))
     const char *x, __attribute__ ((unused))
     const char *y, __attribute__ ((unused))
     int a, __attribute__ ((unused))
-    int b)
+    int b, __attribute__ ((unused))
+    const char *s)
 {
 }
 
@@ -11291,7 +11474,7 @@ static void PrintVersion(void)
 #ifdef GIT_REV
 	"(GIT-" GIT_REV ")"
 #endif
-	",\n\t(c) 2009 - 2013 by Johns\n"
+	",\n\t(c) 2009 - 2014 by Johns\n"
 	"\tLicense AGPLv3: GNU Affero General Public License version 3\n");
 }
 

-- 
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