[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