Compare commits

..

65 Commits

Author SHA1 Message Date
Johns
6dfa88aecf Preparations for new ffmpeg VDPAU API. 2015-11-03 11:39:41 +01:00
Johns
ee2311d252 Fix compile error with opengl and without va-api. 2015-10-06 18:28:34 +02:00
Johns
4fa4f6616a Added VDPAU multi decoder loop changes to VA-API code. 2015-10-05 08:54:19 +02:00
Johns
5dc5601576 Fix comment spelling. 2015-10-01 15:46:38 +02:00
Johns
9e56747a56 Disabled old code before removement. 2015-10-01 12:48:37 +02:00
Johns
5b90137050 Handle change of audio ac3 downmix direct. 2015-09-30 12:24:26 +02:00
Johns
f47ee3a201 Speedup queuing output surface, when decoder buffers are full. 2015-09-30 11:27:10 +02:00
Johns
93981031aa Calculate queued output surfaces and show them in info message. 2015-09-30 11:16:50 +02:00
Johns
509329c90a Add support for new API of vdr 2.3.1. 2015-09-24 14:31:51 +02:00
Johns
8c347fdf1d Fix bug: EnableDPMSatBlackScreen only available with USE_SCREENSAVER. 2015-08-26 10:11:49 +02:00
Johns
06b8f77327 H264_EOS_TRICKSPEED and USE_MPEG_COMPLETE enabled as default. 2015-08-17 13:14:44 +02:00
master_red
700c8e8767 Configurable enable DPMS, while black screen is displayed. 2015-08-10 15:32:25 +02:00
Johns
ec58e45607 Fix bug: wrong and crash, if vdr draws pixmaps outside OSD. 2015-06-30 10:12:09 +02:00
Johns
396d5fac05 Fix bug: wrong version number check for av_frame_alloc(), ... 2015-06-19 01:06:52 +02:00
Johns
f0d31ad33c Fixed typing error. 2015-04-22 12:35:42 +02:00
Johns
e0f4a99b99 Workaround for ffmpeg 2.6 artifacts. 2015-04-22 12:14:15 +02:00
Johns
a1939eb6cb Fix bug: brightness and .. are calculated wrong. 2015-03-10 10:44:29 +01:00
Johns
28555643a5 Add automatic frame rate detection for older ffmpeg versions. 2015-03-10 10:38:00 +01:00
Johns
2866e328c6 Fix bug: destroyed vdpau surfaces still used in queue. 2015-03-10 10:31:49 +01:00
Johns
915dff8714 Fix bug: need signed char, if compiler has unsigned chars. 2015-03-10 10:20:53 +01:00
Johns
ca0181b1b1 Try smaller audio puffer, if default size fails. 2015-03-10 10:14:37 +01:00
Johns
a36221dea7 Fix bug: center cut-out didn't use cut off pixels. 2015-03-10 10:10:14 +01:00
Johns
4e72638766 Fix bug #2058: support for Make.plgcfg. 2015-03-10 09:43:09 +01:00
Johns
93ea660a38 Fix for compile with vdr 2.1.10, for older vdr versions. 2015-02-16 15:18:59 +01:00
jinx
73ce4ba803 Enable toggle AC3 downmix. 2015-02-16 10:02:27 +01:00
Johns
1d06c5ba59 Compile with vdr 2.1.10 2015-02-12 10:30:50 +01:00
Johns
2ceeb6db40 Fix bug: AVCodecContext.framerate not supported.
Older versions of ffmpeg have no member framerate in AVCodecContext.
2015-02-09 11:50:41 +01:00
Johns
4f4d304479 Use video stream frame rate for A/V sync.
Use the video stream frame rate and not the fixed 50Hz for A/V sync.
2015-02-06 09:50:54 +01:00
Antti Seppälä
9f134c1b6d Corrected black surface for va-api. 2014-10-16 14:16:01 +02:00
Johns
0adc02dd78 Newer va-api intel drivers support PutImage. 2014-10-16 14:05:17 +02:00
Johns
46e9f23355 Use more portable fork for vfork. 2014-10-16 12:54:21 +02:00
Johns
ac1d5250c8 Fix crash with VA-API vdpau backend. 2014-10-13 15:16:05 +02:00
mini73
c2556eb90a Fix bug: random rubbish at the end of letter. 2014-10-11 16:56:24 +02:00
Johns
a3c0052c4b Fix audio thread close race condition. 2014-09-23 12:36:39 +02:00
Johns
8b7402a397 Support ffmpeg new AVFrame API in the audio codec. 2014-08-13 12:04:39 +02:00
Johns
4a4de36878 Newer version of msgfmt force this. 2014-07-14 11:39:01 +02:00
Johns
37f409cb9a Use GCC built-in functions for atomic operations. 2014-06-25 15:17:00 +02:00
Johns
5207af6b2d Fix last commit. 2014-06-04 19:32:44 +02:00
Johns
90538ebfa9 Support detach or suspend in plugin menu. 2014-06-04 14:49:18 +02:00
Johns
ac7672053a Fix out of sync with ffmpeg >= 2.2.
This workaround for some special ffmpeg versions, conflicts with latest ffmpeg.
2014-05-30 10:18:20 +02:00
Johns
0cdedb88ac Fix "make clean-plugins". 2014-04-17 14:33:12 +02:00
Johns
42bbb763fd Fix compile with newer libav. 2014-02-27 14:20:25 +01:00
Johns
5bf2a9b761 No conf and rc file in git. 2014-02-18 12:26:03 +01:00
Johns
b7d372aa39 Audio flush only with audio. 2014-02-18 10:12:34 +01:00
Johns
3d3a88e76c Fix OSD bugs. 2014-02-12 14:37:35 +01:00
Johns
450c9b6309 Add some VA-API VPP info outputs. 2014-02-04 14:46:22 +01:00
Johns
23ab3707dc Remove build files for old unstable VDR. 2014-01-30 10:47:03 +01:00
hd.brummy
b3f0fe9fea Update gentoo ebuild. 2014-01-30 10:42:17 +01:00
Johns
f73f7a28f3 Fix spelling in arguments help. 2014-01-30 10:36:53 +01:00
Johns
340e10a0eb Add Workaround for alsa blocking audio device. 2014-01-29 10:07:07 +01:00
mini73
a45b9a3abe Fix bug: learing x11 remote keys fails. 2014-01-24 11:31:57 +01:00
Johns
590bae406a USE_BITMAP shouldn't be the default. 2014-01-14 14:59:44 +01:00
Johns
501d46793f Fix alternative OSD support with VDPAU bitmap surfaces. 2014-01-14 14:59:01 +01:00
Johns
978fc59aba Add support for umlauts in input fields. 2014-01-08 16:57:08 +01:00
Johns
aee9bbed90 Fix compile error with VDR 2.1.3. 2014-01-07 12:34:54 +01:00
Johns
8577292c50 Fix bug: memory leak. 2014-01-06 16:51:37 +01:00
Johns
a74a8e1c74 Added libswresample as required for ffmpeg. 2013-12-04 10:25:32 +01:00
Johns
e2a65cbf76 Missing change for PIP close, clear. 2013-12-04 10:12:31 +01:00
Johns
35a1dde089 ClearOnSwitch added to readme. 2013-12-04 10:10:09 +01:00
Johns
7ffbfea224 PIP close clears the last used PIP channel. 2013-12-04 10:01:36 +01:00
Johns
bb70c75656 Fix bug: -DOSD_DEBUG uses old (deleted) variable. 2013-11-23 16:51:30 +01:00
Johns
cfda3ba39d Fix bug: Option softhddevice.BlackPicture has no effect. 2013-11-23 16:48:02 +01:00
Dr. Seltsam
0e40f5f872 Add support to configure and clear buffers on channel switch. 2013-11-05 16:46:46 +01:00
Johns
fb2a7f9959 CLOCK_REALTIME -> CLOCK_MONOTONIC to allow time changes. 2013-10-08 10:18:04 +02:00
Johns
e3b32861b0 Add function VideoStreamOpen and always use VideoStreamClose. 2013-10-08 10:13:38 +02:00
20 changed files with 1767 additions and 823 deletions

123
ChangeLog
View File

@ -1,6 +1,129 @@
User johns User johns
Date: Date:
Preparations for new ffmpeg VDPAU API.
Added VDPAU multi decoder loop changes to VA-API code.
Reenabled VA-API auto detection.
Check and enforce USE_PIP is defined, for new code.
Fix comment spelling.
Disabled old code before removement.
Handle change of audio ac3 downmix direct.
Speedup queuing output surface, when decoder buffers are full.
Fix bug: info shows wrong decoded video surfaces.
Calculate queued output surfaces and show them in info message.
Add support for new API of vdr 2.3.1.
Fix bug: EnableDPMSatBlackScreen only available with USE_SCREENSAVER.
- H264_EOS_TRICKSPEED and USE_MPEG_COMPLETE enabled as default.
User master_red
Date: Mon Aug 10 15:29:33 CEST 2015
Configurable enable DPMS, while black screen is displayed.
User johns
Date: Tue Jun 30 10:12:09 CET 2015
Fix bug: wrong and crash, if vdr draws pixmaps outside OSD.
Fix bug: wrong version number check for av_frame_alloc(), ...
Workaround for ffmpeg 2.6 artifacts.
Fix bug: brightness and .. are calculated wrong.
Add automatic frame rate detection for older ffmpeg versions.
Fix bug: destroyed vdpau surfaces still used in queue.
Fix bug: need signed char, if compiler has unsigned chars.
Try smaller audio puffer, if default size fails.
Fix bug: center cut-out didn't use cut off pixels.
Fix bug #2058: support for Make.plgcfg.
Fix for compile with vdr 2.1.10, for older vdr versions.
User jinx
Date: Mon Feb 16 09:58:06 CET 2015
Enable toggle AC3 downmix.
User johns
Date: Thu Feb 12 10:30:50 CET 2015
Compile with vdr 2.1.10.
Fix bug: AVCodecContext.framerate not supported.
Use video stream frame rate for A/V sync.
User Antti Seppälä
Date: Thu Oct 16 14:15:15 CEST 2014
Corrected black surface for va-api.
User johns
Date: Thu Oct 16 14:05:17 CEST 2014
Newer va-api intel drivers support PutImage.
Use more portable fork for vfork.
Fix crash with VA-API vdpau backend.
User mini73
Date: Sat Oct 11 16:53:18 CEST 2014
Fix bug: random rubbish at the end of letter.
User johns
Date: Tue Sep 23 12:36:39 CEST 2014
Fix audio thread close race condition.
Support ffmpeg new AVFrame API in the audio codec.
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. Softer audio/video sync.
Add function GetStats to the video output module. Add function GetStats to the video output module.
Add function ResetStart to the video output module. Add function ResetStart to the video output module.

108
Makefile
View File

@ -18,13 +18,17 @@ OSS ?= 1
# support VDPAU video output module # support VDPAU video output module
VDPAU ?= $(shell pkg-config --exists vdpau && echo 1) VDPAU ?= $(shell pkg-config --exists vdpau && echo 1)
# support VA-API video output module (deprecated) # support VA-API video output module (deprecated)
#VAAPI ?= $(shell pkg-config --exists libva && echo 1) VAAPI ?= $(shell pkg-config --exists libva && echo 1)
# support glx output # support glx output
#OPENGL ?= $(shell pkg-config --exists gl glu && echo 1) OPENGL ?= $(shell pkg-config --exists gl glu && echo 1)
# screensaver disable/enable # screensaver disable/enable
SCREENSAVER ?= 1 SCREENSAVER ?= 1
# use ffmpeg libswresample # use ffmpeg libswresample
SWRESAMPLE ?= $(shell pkg-config --exists libswresample && echo 1) 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 := # -DDEBUG #-DOSD_DEBUG # enable debug output+functions
#CONFIG += -DSTILL_DEBUG=2 # still picture debug verbose level #CONFIG += -DSTILL_DEBUG=2 # still picture debug verbose level
@ -34,12 +38,59 @@ CONFIG += -DUSE_PIP # PIP support
#CONFIG += -DHAVE_PTHREAD_NAME # supports new pthread_setname_np #CONFIG += -DHAVE_PTHREAD_NAME # supports new pthread_setname_np
#CONFIG += -DNO_TS_AUDIO # disable ts audio parser #CONFIG += -DNO_TS_AUDIO # disable ts audio parser
#CONFIG += -DUSE_TS_VIDEO # build new ts video parser #CONFIG += -DUSE_TS_VIDEO # build new ts video parser
#CONFIG += -DUSE_MPEG_COMPLETE # support only complete mpeg packets CONFIG += -DUSE_MPEG_COMPLETE # support only complete mpeg packets
#CONFIG += -DH264_EOS_TRICKSPEED # insert seq end packets for trickspeed CONFIG += -DH264_EOS_TRICKSPEED # insert seq end packets for trickspeed
#CONDIF += -DDUMP_TRICKSPEED # dump trickspeed packets #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_VDR_SPU # use VDR SPU decoder.
#CONFIG += -DUSE_SOFTLIMIT # (tobe removed) limit the buffer fill #CONFIG += -DUSE_SOFTLIMIT # (tobe removed) limit the buffer fill
### 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)
### The directory environment:
# Use package data if installed...otherwise assume we're under the VDR source directory:
PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../.." pkg-config --variable=$(1) vdr))
LIBDIR = $(call PKGCFG,libdir)
LOCDIR = $(call PKGCFG,locdir)
PLGCFG = $(call PKGCFG,plgcfg)
#
TMPDIR ?= /tmp
### The compiler options:
export CFLAGS = $(call PKGCFG,cflags)
export CXXFLAGS = $(call PKGCFG,cxxflags)
ifeq ($(CFLAGS),)
$(warning CFLAGS not set)
endif
ifeq ($(CXXFLAGS),)
$(warning CXXFLAGS not set)
endif
### The version number of VDR's plugin API:
APIVERSION = $(call PKGCFG,apiversion)
### Allow user defined options to overwrite defaults:
-include $(PLGCFG)
### The name of the distribution archive:
ARCHIVE = $(PLUGIN)-$(VERSION)
PACKAGE = vdr-$(ARCHIVE)
### The name of the shared object file:
SOFILE = libvdr-$(PLUGIN).so
### Parse softhddevice config
ifeq ($(ALSA),1) ifeq ($(ALSA),1)
CONFIG += -DUSE_ALSA CONFIG += -DUSE_ALSA
_CFLAGS += $(shell pkg-config --cflags alsa) _CFLAGS += $(shell pkg-config --cflags alsa)
@ -77,54 +128,15 @@ CONFIG += -DUSE_SWRESAMPLE
_CFLAGS += $(shell pkg-config --cflags libswresample) _CFLAGS += $(shell pkg-config --cflags libswresample)
LIBS += $(shell pkg-config --libs libswresample) LIBS += $(shell pkg-config --libs libswresample)
endif 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) _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) LIBS += -lrt $(shell pkg-config --libs libavcodec x11 x11-xcb xcb xcb-icccm)
### 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)
### The directory environment:
# Use package data if installed...otherwise assume we're under the VDR source directory:
PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
LIBDIR = $(call PKGCFG,libdir)
LOCDIR = $(call PKGCFG,locdir)
PLGCFG = $(call PKGCFG,plgcfg)
#
TMPDIR ?= /tmp
### The compiler options:
export CFLAGS = $(call PKGCFG,cflags)
export CXXFLAGS = $(call PKGCFG,cxxflags)
ifeq ($(CFLAGS),)
$(error CFLAGS not set)
endif
ifeq ($(CXXFLAGS),)
$(error CXXFLAGS not set)
endif
### The version number of VDR's plugin API:
APIVERSION = $(call PKGCFG,apiversion)
### Allow user defined options to overwrite defaults:
-include $(PLGCFG)
### The name of the distribution archive:
ARCHIVE = $(PLUGIN)-$(VERSION)
PACKAGE = vdr-$(ARCHIVE)
### The name of the shared object file:
SOFILE = libvdr-$(PLUGIN).so
### Includes and Defines (add further entries here): ### Includes and Defines (add further entries here):
INCLUDES += INCLUDES +=

View File

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

View File

@ -233,6 +233,10 @@ Setup: /etc/vdr/setup.conf
0 disable black picture during channel switch 0 disable black picture during channel switch
1 enable 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 softhddevice.Video4to3DisplayFormat = 1
0 pan and scan 0 pan and scan
1 letter box 1 letter box
@ -317,6 +321,7 @@ Keymacros:
@softhddevice Blue 1 2 toggle pass-through @softhddevice Blue 1 2 toggle pass-through
@softhddevice Blue 1 3 decrease audio delay by 10ms @softhddevice Blue 1 3 decrease audio delay by 10ms
@softhddevice Blue 1 4 increase audio delay by 10ms @softhddevice Blue 1 4 increase audio delay by 10ms
@softhddevice Blue 1 5 toggle ac3 mixdown
@softhddevice Blue 2 0 disable fullscreen @softhddevice Blue 2 0 disable fullscreen
@softhddevice Blue 2 1 enable fullscreen @softhddevice Blue 2 1 enable fullscreen
@softhddevice Blue 2 2 toggle fullscreen @softhddevice Blue 2 2 toggle fullscreen
@ -352,7 +357,7 @@ Requires:
media-video/ffmpeg (version >=0.7) media-video/ffmpeg (version >=0.7)
Complete solution to record, convert and stream audio and Complete solution to record, convert and stream audio and
video. Includes libavcodec. video. Includes libavcodec and libswresample.
http://ffmpeg.org http://ffmpeg.org
media-libs/alsa-lib media-libs/alsa-lib
Advanced Linux Sound Architecture Library Advanced Linux Sound Architecture Library

2
Todo
View File

@ -45,6 +45,7 @@ video:
still-picture of PES recordings should use VideoMpegEnqueue. still-picture of PES recordings should use VideoMpegEnqueue.
convert PIX_FMT_... PixelFormat to new names AV_PIX_FMT_..., AVPixelFormat. convert PIX_FMT_... PixelFormat to new names AV_PIX_FMT_..., AVPixelFormat.
atmo service support 3D grab atmo service support 3D grab
no warnings during still picture
vdpau: vdpau:
software deinterlace path not working. software deinterlace path not working.
@ -127,6 +128,7 @@ unsorted:
svdrp prim: support plugin names for device numbers. svdrp prim: support plugin names for device numbers.
Workaround exists: hangup PipVideoStream -> Vdpau_get_format -> xcb -> poll Workaround exists: hangup PipVideoStream -> Vdpau_get_format -> xcb -> poll
+ lock DecoderLockMutex + lock DecoderLockMutex
check compiletime and runtime ffmpeg/libav version during init.
future features (not planed for 1.0 - 1.5) future features (not planed for 1.0 - 1.5)

114
audio.c
View File

@ -1,7 +1,7 @@
/// ///
/// @file audio.c @brief Audio module /// @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): /// Contributor(s):
/// ///
@ -88,7 +88,7 @@
#endif #endif
#endif #endif
#include <alsa/iatomic.h> // portable atomic_t #include "iatomic.h" // portable atomic_t
#include "ringbuffer.h" #include "ringbuffer.h"
#include "misc.h" #include "misc.h"
@ -123,6 +123,8 @@ static const AudioModule NoopModule; ///< forward definition of noop module
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
char AudioAlsaDriverBroken; ///< disable broken driver message 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 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 AudioModule *AudioUsedModule = &NoopModule;
static const char *AudioPCMDevice; ///< PCM device name static const char *AudioPCMDevice; ///< PCM device name
static const char *AudioPassthroughDevice; ///< Passthrough 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 *AudioMixerDevice; ///< mixer device name
static const char *AudioMixerChannel; ///< mixer channel name static const char *AudioMixerChannel; ///< mixer channel name
static char AudioDoingInit; ///> flag in init, reduce error static char AudioDoingInit; ///> flag in init, reduce error
@ -146,6 +149,7 @@ static int AudioBufferTime = 336; ///< audio buffer time in ms
static pthread_t AudioThread; ///< audio play thread static pthread_t AudioThread; ///< audio play thread
static pthread_mutex_t AudioMutex; ///< audio condition mutex static pthread_mutex_t AudioMutex; ///< audio condition mutex
static pthread_cond_t AudioStartCond; ///< condition variable static pthread_cond_t AudioStartCond; ///< condition variable
static char AudioThreadStop; ///< stop audio thread
#else #else
static const int AudioThread; ///< dummy audio thread static const int AudioThread; ///< dummy audio thread
#endif #endif
@ -939,7 +943,6 @@ static int AlsaThread(void)
return -1; return -1;
} }
for (;;) { for (;;) {
pthread_testcancel();
if (AudioPaused) { if (AudioPaused) {
return 1; return 1;
} }
@ -1005,6 +1008,26 @@ static snd_pcm_t *AlsaOpenPCM(int passthrough)
Info(_("audio/alsa: using %sdevice '%s'\n"), Info(_("audio/alsa: using %sdevice '%s'\n"),
passthrough ? "pass-through " : "", device); 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 // open none blocking; if device is already used, we don't want wait
if ((err = if ((err =
snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK,
@ -1189,17 +1212,23 @@ static int AlsaSetup(int *freq, int *channels, int passthrough)
// FIXME: if open fails for fe. pass-through, we never recover // FIXME: if open fails for fe. pass-through, we never recover
return -1; 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; snd_pcm_t *handle;
handle = AlsaPCMHandle; handle = AlsaPCMHandle;
// FIXME: need lock // no lock needed, thread exit in main loop only
//Debug(3, "audio: %s [\n", __FUNCTION__);
AlsaPCMHandle = NULL; // other threads should check handle AlsaPCMHandle = NULL; // other threads should check handle
snd_pcm_close(handle); snd_pcm_close(handle);
if (AudioAlsaCloseOpenDelay) {
usleep(50 * 1000); // 50ms delay for alsa recovery
}
// FIXME: can use multiple retries
if (!(handle = AlsaOpenPCM(passthrough))) { if (!(handle = AlsaOpenPCM(passthrough))) {
return -1; return -1;
} }
AlsaPCMHandle = handle; AlsaPCMHandle = handle;
//Debug(3, "audio: %s ]\n", __FUNCTION__);
} }
for (;;) { for (;;) {
@ -1208,6 +1237,13 @@ static int AlsaSetup(int *freq, int *channels, int passthrough)
AlsaUseMmap ? SND_PCM_ACCESS_MMAP_INTERLEAVED : AlsaUseMmap ? SND_PCM_ACCESS_MMAP_INTERLEAVED :
SND_PCM_ACCESS_RW_INTERLEAVED, *channels, *freq, 1, SND_PCM_ACCESS_RW_INTERLEAVED, *channels, *freq, 1,
96 * 1000))) { 96 * 1000))) {
// try reduced buffer size (needed for sunxi)
// FIXME: alternativ make this configurable
if ((err =
snd_pcm_set_params(AlsaPCMHandle, SND_PCM_FORMAT_S16,
AlsaUseMmap ? SND_PCM_ACCESS_MMAP_INTERLEAVED :
SND_PCM_ACCESS_RW_INTERLEAVED, *channels, *freq, 1,
72 * 1000))) {
/* /*
if ( err == -EBADFD ) { if ( err == -EBADFD ) {
@ -1224,6 +1260,7 @@ static int AlsaSetup(int *freq, int *channels, int passthrough)
// FIXME: must stop sound, AudioChannels ... invalid // FIXME: must stop sound, AudioChannels ... invalid
return -1; return -1;
} }
}
break; break;
} }
@ -1521,7 +1558,6 @@ static int OssThread(void)
for (;;) { for (;;) {
struct pollfd fds[1]; struct pollfd fds[1];
pthread_testcancel();
if (AudioPaused) { if (AudioPaused) {
return 1; return 1;
} }
@ -2023,6 +2059,12 @@ static void *AudioPlayHandlerThread(void *dummy)
{ {
Debug(3, "audio: play thread started\n"); Debug(3, "audio: play thread started\n");
for (;;) { for (;;) {
// check if we should stop the thread
if (AudioThreadStop) {
Debug(3, "audio: play thread stopped\n");
return PTHREAD_CANCELED;
}
Debug(3, "audio: wait on start condition\n"); Debug(3, "audio: wait on start condition\n");
pthread_mutex_lock(&AudioMutex); pthread_mutex_lock(&AudioMutex);
AudioRunning = 0; AudioRunning = 0;
@ -2043,25 +2085,32 @@ static void *AudioPlayHandlerThread(void *dummy)
int read; int read;
int flush; int flush;
int err; int err;
int i;
// check if we should stop the thread
if (AudioThreadStop) {
Debug(3, "audio: play thread stopped\n");
return PTHREAD_CANCELED;
}
// look if there is a flush command in the queue // look if there is a flush command in the queue
flush = 0; flush = 0;
filled = atomic_read(&AudioRingFilled); filled = atomic_read(&AudioRingFilled);
read = AudioRingRead; read = AudioRingRead;
while (filled--) { i = filled;
while (i--) {
read = (read + 1) % AUDIO_RING_MAX; read = (read + 1) % AUDIO_RING_MAX;
if (AudioRing[read].FlushBuffers) { if (AudioRing[read].FlushBuffers) {
AudioRing[read].FlushBuffers = 0; AudioRing[read].FlushBuffers = 0;
AudioRingRead = read; AudioRingRead = read;
atomic_set(&AudioRingFilled, filled);
// handle all flush in queue // handle all flush in queue
flush = 1; flush = filled - i;
} }
} }
if (flush) { if (flush) {
Debug(3, "audio: flush\n"); Debug(3, "audio: flush %d ring buffer(s)\n", flush);
AudioUsedModule->FlushBuffers(); AudioUsedModule->FlushBuffers();
atomic_sub(flush, &AudioRingFilled);
if (AudioNextRing()) { if (AudioNextRing()) {
Debug(3, "audio: break after flush\n"); Debug(3, "audio: break after flush\n");
break; break;
@ -2127,6 +2176,7 @@ static void *AudioPlayHandlerThread(void *dummy)
*/ */
static void AudioInitThread(void) static void AudioInitThread(void)
{ {
AudioThreadStop = 0;
pthread_mutex_init(&AudioMutex, NULL); pthread_mutex_init(&AudioMutex, NULL);
pthread_cond_init(&AudioStartCond, NULL); pthread_cond_init(&AudioStartCond, NULL);
pthread_create(&AudioThread, NULL, AudioPlayHandlerThread, NULL); pthread_create(&AudioThread, NULL, AudioPlayHandlerThread, NULL);
@ -2140,10 +2190,12 @@ static void AudioExitThread(void)
{ {
void *retval; void *retval;
Debug(3, "audio: %s\n", __FUNCTION__);
if (AudioThread) { if (AudioThread) {
if (pthread_cancel(AudioThread)) { AudioThreadStop = 1;
Error(_("audio: can't queue cancel play thread\n")); AudioRunning = 1; // wakeup thread, if needed
} pthread_cond_signal(&AudioStartCond);
if (pthread_join(AudioThread, &retval) || retval != PTHREAD_CANCELED) { if (pthread_join(AudioThread, &retval) || retval != PTHREAD_CANCELED) {
Error(_("audio: can't cancel play thread\n")); Error(_("audio: can't cancel play thread\n"));
} }
@ -2421,8 +2473,23 @@ void AudioFlushBuffers(void)
int old; int old;
int i; 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; old = AudioRingWrite;
// FIXME: check ring buffer overflow
AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX; AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
AudioRing[AudioRingWrite].FlushBuffers = 1; AudioRing[AudioRingWrite].FlushBuffers = 1;
AudioRing[AudioRingWrite].Passthrough = AudioRing[old].Passthrough; AudioRing[AudioRingWrite].Passthrough = AudioRing[old].Passthrough;
@ -2439,12 +2506,13 @@ void AudioFlushBuffers(void)
atomic_inc(&AudioRingFilled); atomic_inc(&AudioRingFilled);
// FIXME: wait for flush complete? // FIXME: wait for flush complete needed?
for (i = 0; i < 24 * 2; ++i) { for (i = 0; i < 24 * 2; ++i) {
if (!AudioRunning) { // wakeup thread to flush buffers if (!AudioRunning) { // wakeup thread to flush buffers
AudioRunning = 1; AudioRunning = 1;
pthread_cond_signal(&AudioStartCond); pthread_cond_signal(&AudioStartCond);
} }
// FIXME: waiting on zero isn't correct, but currently works
if (!atomic_read(&AudioRingFilled)) { if (!atomic_read(&AudioRingFilled)) {
break; break;
} }
@ -2756,6 +2824,20 @@ void AudioSetChannel(const char *channel)
AudioMixerChannel = channel; AudioMixerChannel = 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. ** Initialize audio output module.
** **
@ -2935,6 +3017,8 @@ void AudioExit(void)
{ {
const AudioModule *module; const AudioModule *module;
Debug(3, "audio: %s\n", __FUNCTION__);
#ifdef USE_AUDIO_THREAD #ifdef USE_AUDIO_THREAD
if (AudioUsedModule->Thread) { // supports threads if (AudioUsedModule->Thread) { // supports threads
AudioExitThread(); AudioExitThread();

View File

@ -1,7 +1,7 @@
/// ///
/// @file audio.h @brief Audio module headerfile /// @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): /// Contributor(s):
/// ///
@ -52,6 +52,7 @@ extern void AudioSetDevice(const char *); ///< set PCM audio device
/// set pass-through device /// set pass-through device
extern void AudioSetPassthroughDevice(const char *); extern void AudioSetPassthroughDevice(const char *);
extern void AudioSetChannel(const char *); ///< set mixer channel 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 AudioInit(void); ///< setup audio module
extern void AudioExit(void); ///< cleanup and exit 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 AudioAlsaDriverBroken; ///< disable broken driver message
extern char AudioAlsaNoCloseOpen; ///< disable alsa close/open fix
extern char AudioAlsaCloseOpenDelay; ///< enable alsa close/open delay fix
/// @} /// @}

257
codec.c
View File

@ -1,7 +1,7 @@
/// ///
/// @file codec.c @brief Codec functions /// @file codec.c @brief Codec functions
/// ///
/// Copyright (c) 2009 - 2013 by Johns. All Rights Reserved. /// Copyright (c) 2009 - 2015 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -38,8 +38,12 @@
#define USE_AC3_DRIFT_CORRECTION #define USE_AC3_DRIFT_CORRECTION
/// use ffmpeg libswresample API (autodected, Makefile) /// use ffmpeg libswresample API (autodected, Makefile)
#define noUSE_SWRESAMPLE #define noUSE_SWRESAMPLE
/// use libav libavresample API (autodected, Makefile)
#define noUSE_AVRESAMPLE
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#ifdef __FreeBSD__ #ifdef __FreeBSD__
#include <sys/endian.h> #include <sys/endian.h>
@ -54,13 +58,14 @@
#define _(str) gettext(str) ///< gettext shortcut #define _(str) gettext(str) ///< gettext shortcut
#define _N(str) str ///< gettext_noop shortcut #define _N(str) str ///< gettext_noop shortcut
#include <alsa/iatomic.h>
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
#include <libavutil/mem.h>
// support old ffmpeg versions <1.0 // support old ffmpeg versions <1.0
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,18,102) #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,18,102)
#define AVCodecID CodecID #define AVCodecID CodecID
#define AV_CODEC_ID_AC3 CODEC_ID_AC3 #define AV_CODEC_ID_AC3 CODEC_ID_AC3
#define AV_CODEC_ID_EAC3 CODEC_ID_EAC3 #define AV_CODEC_ID_EAC3 CODEC_ID_EAC3
#define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO
#define AV_CODEC_ID_H264 CODEC_ID_H264 #define AV_CODEC_ID_H264 CODEC_ID_H264
#endif #endif
#include <libavcodec/vaapi.h> #include <libavcodec/vaapi.h>
@ -70,6 +75,10 @@
#ifdef USE_SWRESAMPLE #ifdef USE_SWRESAMPLE
#include <libswresample/swresample.h> #include <libswresample/swresample.h>
#endif #endif
#ifdef USE_AVRESAMPLE
#include <libavresample/avresample.h>
#include <libavutil/opt.h>
#endif
#ifndef __USE_GNU #ifndef __USE_GNU
#define __USE_GNU #define __USE_GNU
@ -79,11 +88,22 @@
#ifdef MAIN_H #ifdef MAIN_H
#include MAIN_H #include MAIN_H
#endif #endif
#include "iatomic.h"
#include "misc.h" #include "misc.h"
#include "video.h" #include "video.h"
#include "audio.h" #include "audio.h"
#include "codec.h" #include "codec.h"
//----------------------------------------------------------------------------
// correct is AV_VERSION_INT(56,35,101) but some gentoo i* think
// they must change it.
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,26,100)
/// ffmpeg 2.6 started to show artifacts after channel switch
/// to SDTV channels
#define FFMPEG_WORKAROUND_ARTIFACTS 1
#endif
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Global // Global
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -96,6 +116,9 @@
/// ///
static pthread_mutex_t CodecLockMutex; static pthread_mutex_t CodecLockMutex;
/// Flag prefer fast channel switch
char CodecUsePossibleDefectFrames;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Video // Video
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -117,6 +140,9 @@ struct _video_decoder_
int GetFormatDone; ///< flag get format called! int GetFormatDone; ///< flag get format called!
AVCodec *VideoCodec; ///< video codec AVCodec *VideoCodec; ///< video codec
AVCodecContext *VideoCtx; ///< video codec context AVCodecContext *VideoCtx; ///< video codec context
#ifdef FFMPEG_WORKAROUND_ARTIFACTS
int FirstKeyFrame; ///< flag first frame
#endif
AVFrame *Frame; ///< decoded video frame AVFrame *Frame; ///< decoded video frame
}; };
@ -201,7 +227,9 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
//Debug(3, "codec: use surface %#010x\n", surface); //Debug(3, "codec: use surface %#010x\n", surface);
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,48,101)
frame->type = FF_BUFFER_TYPE_USER; frame->type = FF_BUFFER_TYPE_USER;
#endif
#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,46,0) #if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,46,0)
frame->age = 256 * 256 * 256 * 64; frame->age = 256 * 256 * 256 * 64;
#endif #endif
@ -211,12 +239,14 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
frame->data[2] = NULL; frame->data[2] = NULL;
frame->data[3] = NULL; frame->data[3] = NULL;
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,66,100)
// reordered frames // reordered frames
if (video_ctx->pkt) { if (video_ctx->pkt) {
frame->pkt_pts = video_ctx->pkt->pts; frame->pkt_pts = video_ctx->pkt->pts;
} else { } else {
frame->pkt_pts = AV_NOPTS_VALUE; frame->pkt_pts = AV_NOPTS_VALUE;
} }
#endif
return 0; return 0;
} }
#endif #endif
@ -228,7 +258,9 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
//Debug(3, "codec: use surface %#010x\n", surface); //Debug(3, "codec: use surface %#010x\n", surface);
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,48,101)
frame->type = FF_BUFFER_TYPE_USER; frame->type = FF_BUFFER_TYPE_USER;
#endif
#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,46,0) #if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,46,0)
frame->age = 256 * 256 * 256 * 64; frame->age = 256 * 256 * 256 * 64;
#endif #endif
@ -236,12 +268,14 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
frame->data[0] = (void *)(size_t) surface; frame->data[0] = (void *)(size_t) surface;
frame->data[3] = (void *)(size_t) surface; frame->data[3] = (void *)(size_t) surface;
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,66,100)
// reordered frames // reordered frames
if (video_ctx->pkt) { if (video_ctx->pkt) {
frame->pkt_pts = video_ctx->pkt->pts; frame->pkt_pts = video_ctx->pkt->pts;
} else { } else {
frame->pkt_pts = AV_NOPTS_VALUE; frame->pkt_pts = AV_NOPTS_VALUE;
} }
#endif
return 0; return 0;
} }
//Debug(3, "codec: fallback to default get_buffer\n"); //Debug(3, "codec: fallback to default get_buffer\n");
@ -386,22 +420,39 @@ void CodecVideoDelDecoder(VideoDecoder * decoder)
** Open video decoder. ** Open video decoder.
** **
** @param decoder private video decoder ** @param decoder private video decoder
** @param name video codec name ** @param codec_id video codec id
** @param codec_id video codec id, used if name == NULL
*/ */
void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id) void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
{ {
AVCodec *video_codec; AVCodec *video_codec;
const char *name;
Debug(3, "codec: using video codec %s or ID %#06x\n", name, codec_id); Debug(3, "codec: using video codec ID %#06x (%s)\n", codec_id,
avcodec_get_name(codec_id));
if (decoder->VideoCtx) { if (decoder->VideoCtx) {
Error(_("codec: missing close\n")); Error(_("codec: missing close\n"));
} }
#if 1
// FIXME: old vdpau API: should be updated to new API
name = NULL;
if (!strcasecmp(VideoGetDriverName(), "vdpau")) {
switch (codec_id) {
case AV_CODEC_ID_MPEG2VIDEO:
name = VideoHardwareDecoder < 0 ? "mpegvideo_vdpau" : NULL;
break;
case AV_CODEC_ID_H264:
name = VideoHardwareDecoder ? "h264_vdpau" : NULL;
break;
}
}
if (name && (video_codec = avcodec_find_decoder_by_name(name))) { if (name && (video_codec = avcodec_find_decoder_by_name(name))) {
Debug(3, "codec: vdpau decoder found\n"); Debug(3, "codec: vdpau decoder found\n");
} else if (!(video_codec = avcodec_find_decoder(codec_id))) { } else
#endif
if (!(video_codec = avcodec_find_decoder(codec_id))) {
Fatal(_("codec: codec ID %#06x not found\n"), codec_id); Fatal(_("codec: codec ID %#06x not found\n"), codec_id);
// FIXME: none fatal // FIXME: none fatal
} }
@ -440,7 +491,7 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
decoder->VideoCtx->opaque = decoder; // our structure decoder->VideoCtx->opaque = decoder; // our structure
Debug(3, "codec: video '%s'\n", decoder->VideoCtx->codec_name); Debug(3, "codec: video '%s'\n", decoder->VideoCodec->long_name);
if (codec_id == AV_CODEC_ID_H264) { if (codec_id == AV_CODEC_ID_H264) {
// 2.53 Ghz CPU is too slow for this codec at 1080i // 2.53 Ghz CPU is too slow for this codec at 1080i
//decoder->VideoCtx->skip_loop_filter = AVDISCARD_ALL; //decoder->VideoCtx->skip_loop_filter = AVDISCARD_ALL;
@ -503,11 +554,20 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
// //
// Prepare frame buffer for decoder // Prepare frame buffer for decoder
// //
if (!(decoder->Frame = avcodec_alloc_frame())) { #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,28,1)
Fatal(_("codec: can't allocate decoder frame\n")); if (!(decoder->Frame = av_frame_alloc())) {
Fatal(_("codec: can't allocate video decoder frame buffer\n"));
} }
#else
if (!(decoder->Frame = avcodec_alloc_frame())) {
Fatal(_("codec: can't allocate video decoder frame buffer\n"));
}
#endif
// reset buggy ffmpeg/libav flag // reset buggy ffmpeg/libav flag
decoder->GetFormatDone = 0; decoder->GetFormatDone = 0;
#ifdef FFMPEG_WORKAROUND_ARTIFACTS
decoder->FirstKeyFrame = 1;
#endif
} }
/** /**
@ -518,7 +578,12 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
void CodecVideoClose(VideoDecoder * video_decoder) void CodecVideoClose(VideoDecoder * video_decoder)
{ {
// FIXME: play buffered data // FIXME: play buffered data
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,28,1)
av_frame_free(&video_decoder->Frame); // callee does checks
#else
av_freep(&video_decoder->Frame); av_freep(&video_decoder->Frame);
#endif
if (video_decoder->VideoCtx) { if (video_decoder->VideoCtx) {
pthread_mutex_lock(&CodecLockMutex); pthread_mutex_lock(&CodecLockMutex);
avcodec_close(video_decoder->VideoCtx); avcodec_close(video_decoder->VideoCtx);
@ -594,8 +659,22 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
} }
if (got_frame) { // frame completed if (got_frame) { // frame completed
#ifdef FFMPEG_WORKAROUND_ARTIFACTS
if (!CodecUsePossibleDefectFrames && decoder->FirstKeyFrame) {
decoder->FirstKeyFrame++;
if (frame->key_frame) {
Debug(3, "codec: key frame after %d frames\n",
decoder->FirstKeyFrame);
decoder->FirstKeyFrame = 0;
}
} else {
//DisplayPts(video_ctx, frame); //DisplayPts(video_ctx, frame);
VideoRenderFrame(decoder->HwDecoder, video_ctx, frame); VideoRenderFrame(decoder->HwDecoder, video_ctx, frame);
}
#else
//DisplayPts(video_ctx, frame);
VideoRenderFrame(decoder->HwDecoder, video_ctx, frame);
#endif
} else { } else {
// some frames are needed for references, interlaced frames ... // some frames are needed for references, interlaced frames ...
// could happen with h264 dvb streams, just drop data. // could happen with h264 dvb streams, just drop data.
@ -624,6 +703,11 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
} }
} }
#endif #endif
// new AVFrame API
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,28,1)
av_frame_unref(frame);
#endif
} }
/** /**
@ -664,15 +748,22 @@ struct _audio_decoder_
int HwSampleRate; ///< hw sample rate int HwSampleRate; ///< hw sample rate
int HwChannels; ///< hw channels int HwChannels; ///< hw channels
#ifndef USE_SWRESAMPLE #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,28,1)
ReSampleContext *ReSample; ///< audio resampling context AVFrame *Frame; ///< decoded audio frame buffer
#endif
#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
ReSampleContext *ReSample; ///< old resampling context
#endif #endif
#ifdef USE_SWRESAMPLE #ifdef USE_SWRESAMPLE
#if LIBSWRESAMPLE_VERSION_INT < AV_VERSION_INT(0, 15, 100) #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 #else
SwrContext *Resample; ///< audio software resample context SwrContext *Resample; ///< ffmpeg software resample context
#endif #endif
#endif
#ifdef USE_AVRESAMPLE
AVAudioResampleContext *Resample; ///< libav software resample context
#endif #endif
uint16_t Spdif[24576 / 2]; ///< SPDIF output buffer uint16_t Spdif[24576 / 2]; ///< SPDIF output buffer
@ -687,7 +778,7 @@ struct _audio_decoder_
int DriftCorr; ///< audio drift correction value int DriftCorr; ///< audio drift correction value
int DriftFrac; ///< audio drift fraction for ac3 int DriftFrac; ///< audio drift fraction for ac3
#ifndef USE_SWRESAMPLE #if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
struct AVResampleContext *AvResample; ///< second audio resample context struct AVResampleContext *AvResample; ///< second audio resample context
#define MAX_CHANNELS 8 ///< max number of channels supported #define MAX_CHANNELS 8 ///< max number of channels supported
int16_t *Buffer[MAX_CHANNELS]; ///< deinterleave sample buffers int16_t *Buffer[MAX_CHANNELS]; ///< deinterleave sample buffers
@ -737,6 +828,11 @@ AudioDecoder *CodecAudioNewDecoder(void)
if (!(audio_decoder = calloc(1, sizeof(*audio_decoder)))) { if (!(audio_decoder = calloc(1, sizeof(*audio_decoder)))) {
Fatal(_("codec: can't allocate audio decoder\n")); Fatal(_("codec: can't allocate audio decoder\n"));
} }
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,28,1)
if (!(audio_decoder->Frame = av_frame_alloc())) {
Fatal(_("codec: can't allocate audio decoder frame buffer\n"));
}
#endif
return audio_decoder; return audio_decoder;
} }
@ -748,6 +844,9 @@ AudioDecoder *CodecAudioNewDecoder(void)
*/ */
void CodecAudioDelDecoder(AudioDecoder * decoder) void CodecAudioDelDecoder(AudioDecoder * decoder)
{ {
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,28,1)
av_frame_free(&decoder->Frame); // callee does checks
#endif
free(decoder); free(decoder);
} }
@ -755,19 +854,16 @@ void CodecAudioDelDecoder(AudioDecoder * decoder)
** Open audio decoder. ** Open audio decoder.
** **
** @param audio_decoder private audio decoder ** @param audio_decoder private audio decoder
** @param name audio codec name ** @param codec_id audio codec id
** @param codec_id audio codec id, used if name == NULL
*/ */
void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name, void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id)
int codec_id)
{ {
AVCodec *audio_codec; AVCodec *audio_codec;
Debug(3, "codec: using audio codec %s or ID %#06x\n", name, codec_id); Debug(3, "codec: using audio codec ID %#06x (%s)\n", codec_id,
avcodec_get_name(codec_id));
if (name && (audio_codec = avcodec_find_decoder_by_name(name))) { if (!(audio_codec = avcodec_find_decoder(codec_id))) {
Debug(3, "codec: audio decoder '%s' found\n", name);
} else if (!(audio_codec = avcodec_find_decoder(codec_id))) {
Fatal(_("codec: codec ID %#06x not found\n"), codec_id); Fatal(_("codec: codec ID %#06x not found\n"), codec_id);
// FIXME: errors aren't fatal // FIXME: errors aren't fatal
} }
@ -778,14 +874,14 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
} }
if (CodecDownmix) { if (CodecDownmix) {
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53,61,100) || FF_API_REQUEST_CHANNELS #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53,61,100)
audio_decoder->AudioCtx->request_channels = 2; audio_decoder->AudioCtx->request_channels = 2;
#endif #endif
audio_decoder->AudioCtx->request_channel_layout = audio_decoder->AudioCtx->request_channel_layout =
AV_CH_LAYOUT_STEREO_DOWNMIX; AV_CH_LAYOUT_STEREO_DOWNMIX;
} }
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,61,100) #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; // audio_decoder->AudioCtx->request_sample_fmt = AV_SAMPLE_FMT_S16;
#endif #endif
pthread_mutex_lock(&CodecLockMutex); pthread_mutex_lock(&CodecLockMutex);
@ -812,7 +908,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
} }
#endif #endif
pthread_mutex_unlock(&CodecLockMutex); pthread_mutex_unlock(&CodecLockMutex);
Debug(3, "codec: audio '%s'\n", audio_decoder->AudioCtx->codec_name); Debug(3, "codec: audio '%s'\n", audio_decoder->AudioCodec->long_name);
if (audio_codec->capabilities & CODEC_CAP_TRUNCATED) { if (audio_codec->capabilities & CODEC_CAP_TRUNCATED) {
Debug(3, "codec: audio can use truncated packets\n"); Debug(3, "codec: audio can use truncated packets\n");
@ -834,7 +930,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
void CodecAudioClose(AudioDecoder * audio_decoder) void CodecAudioClose(AudioDecoder * audio_decoder)
{ {
// FIXME: output any buffered data // FIXME: output any buffered data
#ifndef USE_SWRESAMPLE #if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
if (audio_decoder->AvResample) { if (audio_decoder->AvResample) {
int ch; int ch;
@ -859,6 +955,11 @@ void CodecAudioClose(AudioDecoder * audio_decoder)
if (audio_decoder->Resample) { if (audio_decoder->Resample) {
swr_free(&audio_decoder->Resample); swr_free(&audio_decoder->Resample);
} }
#endif
#ifdef USE_AVRESAMPLE
if (audio_decoder->Resample) {
avresample_free(&audio_decoder->Resample);
}
#endif #endif
if (audio_decoder->AudioCtx) { if (audio_decoder->AudioCtx) {
pthread_mutex_lock(&CodecLockMutex); pthread_mutex_lock(&CodecLockMutex);
@ -1155,7 +1256,7 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder,
return 0; return 0;
} }
#ifndef USE_SWRESAMPLE #if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
/** /**
** Set/update audio pts clock. ** Set/update audio pts clock.
@ -1557,7 +1658,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
#endif #endif
#ifdef USE_SWRESAMPLE #if defined(USE_SWRESAMPLE) || defined(USE_AVRESAMPLE)
/** /**
** Set/update audio pts clock. ** Set/update audio pts clock.
@ -1567,6 +1668,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
*/ */
static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts) static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
{ {
#ifdef USE_AUDIO_DRIFT_CORRECTION
struct timespec nowtime; struct timespec nowtime;
int64_t delay; int64_t delay;
int64_t tim_diff; int64_t tim_diff;
@ -1646,6 +1748,7 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
} }
} }
#ifdef USE_SWRESAMPLE
if (audio_decoder->Resample && audio_decoder->DriftCorr) { if (audio_decoder->Resample && audio_decoder->DriftCorr) {
int distance; int distance;
@ -1660,6 +1763,18 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
Debug(3, "codec/audio: swr_set_compensation failed\n"); 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) { if (1) {
static int c; static int c;
@ -1668,6 +1783,9 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
audio_decoder->DriftCorr, drift * 1000 / 90, corr); audio_decoder->DriftCorr, drift * 1000 / 90, corr);
} }
} }
#else
AudioSetClock(pts);
#endif
} }
/** /**
@ -1699,6 +1817,7 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
} }
#endif #endif
#ifdef USE_SWRESAMPLE
audio_decoder->Resample = audio_decoder->Resample =
swr_alloc_set_opts(audio_decoder->Resample, audio_ctx->channel_layout, swr_alloc_set_opts(audio_decoder->Resample, audio_ctx->channel_layout,
AV_SAMPLE_FMT_S16, audio_decoder->HwSampleRate, AV_SAMPLE_FMT_S16, audio_decoder->HwSampleRate,
@ -1709,6 +1828,33 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
} else { } else {
Error(_("codec/audio: can't setup resample\n")); 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
} }
/** /**
@ -1724,16 +1870,31 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt) void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
{ {
AVCodecContext *audio_ctx; AVCodecContext *audio_ctx;
AVFrame frame;
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56,28,1)
AVFrame frame[1];
#else
AVFrame *frame;
#endif
int got_frame; int got_frame;
int n; int n;
audio_ctx = audio_decoder->AudioCtx; audio_ctx = audio_decoder->AudioCtx;
// FIXME: don't need to decode pass-through codecs // FIXME: don't need to decode pass-through codecs
frame.data[0] = NULL;
n = avcodec_decode_audio4(audio_ctx, &frame, &got_frame, // new AVFrame API
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56,28,1)
avcodec_get_frame_defaults(frame);
#else
frame = audio_decoder->Frame;
av_frame_unref(frame);
#endif
got_frame = 0;
n = avcodec_decode_audio4(audio_ctx, frame, &got_frame,
(AVPacket *) avpkt); (AVPacket *) avpkt);
if (n != avpkt->size) { if (n != avpkt->size) {
if (n == AVERROR(EAGAIN)) { if (n == AVERROR(EAGAIN)) {
Error(_("codec/audio: latm\n")); Error(_("codec/audio: latm\n"));
@ -1775,7 +1936,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
data_sz = data_sz =
av_samples_get_buffer_size(&plane_sz, audio_ctx->channels, av_samples_get_buffer_size(&plane_sz, audio_ctx->channels,
frame.nb_samples, audio_ctx->sample_fmt, 1); frame->nb_samples, audio_ctx->sample_fmt, 1);
fprintf(stderr, "codec/audio: sample_fmt %s\n", fprintf(stderr, "codec/audio: sample_fmt %s\n",
av_get_sample_fmt_name(audio_ctx->sample_fmt)); av_get_sample_fmt_name(audio_ctx->sample_fmt));
av_get_channel_layout_string(strbuf, 32, audio_ctx->channels, av_get_channel_layout_string(strbuf, 32, audio_ctx->channels,
@ -1783,9 +1944,9 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
fprintf(stderr, "codec/audio: layout %s\n", strbuf); fprintf(stderr, "codec/audio: layout %s\n", strbuf);
fprintf(stderr, fprintf(stderr,
"codec/audio: channels %d samples %d plane %d data %d\n", "codec/audio: channels %d samples %d plane %d data %d\n",
audio_ctx->channels, frame.nb_samples, plane_sz, data_sz); audio_ctx->channels, frame->nb_samples, plane_sz, data_sz);
} }
#ifdef USE_SWRESAMPLE
if (audio_decoder->Resample) { if (audio_decoder->Resample) {
uint8_t outbuf[8192 * 2 * 8]; uint8_t outbuf[8192 * 2 * 8];
uint8_t *out[1]; uint8_t *out[1];
@ -1793,7 +1954,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
out[0] = outbuf; out[0] = outbuf;
n = swr_convert(audio_decoder->Resample, out, n = swr_convert(audio_decoder->Resample, out,
sizeof(outbuf) / (2 * audio_decoder->HwChannels), sizeof(outbuf) / (2 * audio_decoder->HwChannels),
(const uint8_t **)frame.extended_data, frame.nb_samples); (const uint8_t **)frame->extended_data, frame->nb_samples);
if (n > 0) { if (n > 0) {
if (!(audio_decoder->Passthrough & CodecPCM)) { if (!(audio_decoder->Passthrough & CodecPCM)) {
CodecReorderAudioFrame((int16_t *) outbuf, CodecReorderAudioFrame((int16_t *) outbuf,
@ -1804,6 +1965,30 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
} }
return; 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 #ifdef DEBUG
// should be never reached // should be never reached
fprintf(stderr, "oops\n"); fprintf(stderr, "oops\n");

13
codec.h
View File

@ -1,7 +1,7 @@
/// ///
/// @file codec.h @brief Codec module headerfile /// @file codec.h @brief Codec module headerfile
/// ///
/// Copyright (c) 2009 - 2013 by Johns. All Rights Reserved. /// Copyright (c) 2009 - 2013, 2015 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -43,6 +43,13 @@ typedef struct _video_decoder_ VideoDecoder;
/// Audio decoder typedef. /// Audio decoder typedef.
typedef struct _audio_decoder_ AudioDecoder; typedef struct _audio_decoder_ AudioDecoder;
//----------------------------------------------------------------------------
// Variables
//----------------------------------------------------------------------------
/// Flag prefer fast xhannel switch
extern char CodecUsePossibleDefectFrames;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Prototypes // Prototypes
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -54,7 +61,7 @@ extern VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder *);
extern void CodecVideoDelDecoder(VideoDecoder *); extern void CodecVideoDelDecoder(VideoDecoder *);
/// Open video codec. /// Open video codec.
extern void CodecVideoOpen(VideoDecoder *, const char *, int); extern void CodecVideoOpen(VideoDecoder *, int);
/// Close video codec. /// Close video codec.
extern void CodecVideoClose(VideoDecoder *); extern void CodecVideoClose(VideoDecoder *);
@ -72,7 +79,7 @@ extern AudioDecoder *CodecAudioNewDecoder(void);
extern void CodecAudioDelDecoder(AudioDecoder *); extern void CodecAudioDelDecoder(AudioDecoder *);
/// Open audio codec. /// Open audio codec.
extern void CodecAudioOpen(AudioDecoder *, const char *, int); extern void CodecAudioOpen(AudioDecoder *, int);
/// Close audio codec. /// Close audio codec.
extern void CodecAudioClose(AudioDecoder *); extern void CodecAudioClose(AudioDecoder *);

97
iatomic.h Normal file
View File

@ -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
/// @}

View File

@ -7,10 +7,10 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR \n" "Project-Id-Version: VDR \n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2013-08-03 17:21+0200\n" "POT-Creation-Date: 2015-10-20 14:39+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: blabla\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: blabla\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: blabla\n"
"Language: german\n" "Language: german\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=utf-8\n"
@ -229,9 +229,6 @@ msgstr ""
msgid "audio: can't set channels %d sample-rate %dHz\n" msgid "audio: can't set channels %d sample-rate %dHz\n"
msgstr "" msgstr ""
msgid "audio: can't queue cancel play thread\n"
msgstr ""
msgid "audio: can't cancel play thread\n" msgid "audio: can't cancel play thread\n"
msgstr "" msgstr ""
@ -239,6 +236,9 @@ msgstr ""
msgid "audio: can't place %d samples in ring buffer\n" msgid "audio: can't place %d samples in ring buffer\n"
msgstr "" msgstr ""
msgid "audio: flush out of ring buffers\n"
msgstr ""
#, c-format #, c-format
msgid "audio: '%s' output module used\n" msgid "audio: '%s' output module used\n"
msgstr "" msgstr ""
@ -270,12 +270,15 @@ msgstr ""
msgid "codec: can't open video codec!\n" msgid "codec: can't open video codec!\n"
msgstr "" msgstr ""
msgid "codec: can't allocate decoder frame\n" msgid "codec: can't allocate video decoder frame buffer\n"
msgstr "" msgstr ""
msgid "codec: can't allocate audio decoder\n" msgid "codec: can't allocate audio decoder\n"
msgstr "" msgstr ""
msgid "codec: can't allocate audio decoder frame buffer\n"
msgstr ""
msgid "codec: can't allocate audio codec context\n" msgid "codec: can't allocate audio codec context\n"
msgstr "" msgstr ""
@ -306,6 +309,9 @@ msgstr ""
msgid "codec/audio: can't setup resample\n" msgid "codec/audio: can't setup resample\n"
msgstr "" msgstr ""
msgid "codec/audio: can't open resample\n"
msgstr ""
msgid "codec/audio: latm\n" msgid "codec/audio: latm\n"
msgstr "" msgstr ""
@ -483,6 +489,9 @@ msgstr "OSD Höhe"
msgid "Suspend" msgid "Suspend"
msgstr "Unterbrechen" msgstr "Unterbrechen"
msgid "Detach from main menu entry"
msgstr "Detach durch Hauptmenüeintrag"
msgid "Suspend closes video+audio" msgid "Suspend closes video+audio"
msgstr "Unterbrechen schließt Video+Audio" msgstr "Unterbrechen schließt Video+Audio"
@ -492,6 +501,9 @@ msgstr "Unterbrechen stoppt X11"
msgid "Video" msgid "Video"
msgstr "Video" msgstr "Video"
msgid "Enable Screensaver(DPMS) at black screen"
msgstr "Bildschirmschoner(DPMS) bei schwarzen Bild aktivieren"
msgid "Video background color (RGB)" msgid "Video background color (RGB)"
msgstr "Video Hintergrundfrabe (RGB)" msgstr "Video Hintergrundfrabe (RGB)"
@ -510,6 +522,9 @@ msgstr "Sanftanlauf A/V Sync"
msgid "Black during channel switch" msgid "Black during channel switch"
msgstr "Schwarz während Kanalwechsel" msgstr "Schwarz während Kanalwechsel"
msgid "Clear decoder on channel switch"
msgstr "Decoder bei Kanalwechsel leeren"
msgid "Brightness (-1000..1000) (vdpau)" msgid "Brightness (-1000..1000) (vdpau)"
msgstr "Helligkeit (-1000..1000) (vdpau)" msgstr "Helligkeit (-1000..1000) (vdpau)"
@ -595,7 +610,7 @@ msgid " E-AC-3 pass-through"
msgstr "" msgstr ""
msgid "Enable (E-)AC-3 (decoder) downmix" msgid "Enable (E-)AC-3 (decoder) downmix"
msgstr "" msgstr "Aktiviere (E-)AC-3 (decoder) downmix"
msgid "Volume control" msgid "Volume control"
msgstr "Lautstärkesteuerung" msgstr "Lautstärkesteuerung"
@ -624,6 +639,9 @@ msgstr "Reduziere Steropegel (/1000)"
msgid "Audio buffer size (ms)" msgid "Audio buffer size (ms)"
msgstr "Audio Puffergröße (ms)" msgstr "Audio Puffergröße (ms)"
msgid "Enable automatic AES"
msgstr "Aktiviere automatiche AES"
msgid "Picture-In-Picture" msgid "Picture-In-Picture"
msgstr "Bild in Bild (PIP)" msgstr "Bild in Bild (PIP)"
@ -688,6 +706,9 @@ msgstr ""
msgid "Channel not available!" msgid "Channel not available!"
msgstr "Kanal nicht verfügbar!" msgstr "Kanal nicht verfügbar!"
msgid "Detach SoftHdDevice"
msgstr ""
msgid "Suspend SoftHdDevice" msgid "Suspend SoftHdDevice"
msgstr "Unterbreche SoftHdDevice" msgstr "Unterbreche SoftHdDevice"
@ -735,6 +756,12 @@ msgstr ""
msgid "audio delay changed to %d" msgid "audio delay changed to %d"
msgstr "" msgstr ""
msgid "surround downmix enabled"
msgstr ""
msgid "surround downmix disabled"
msgstr ""
msgid "auto-crop disabled and freezed" msgid "auto-crop disabled and freezed"
msgstr "" msgstr ""
@ -975,14 +1002,20 @@ msgstr ""
msgid "video: output buffer full, dropping frame (%d/%d)\n" msgid "video: output buffer full, dropping frame (%d/%d)\n"
msgstr "" msgstr ""
msgid "video/vaapi: can't create a surface\n" #, c-format
msgid "video/vaapi: can't create a surface: %s\n"
msgstr "" msgstr ""
#, c-format #, c-format
msgid "video/vaapi: vaDeriveImage failed %d\n" msgid "video/vaapi: can't associate subpicture: %s\n"
msgstr "" msgstr ""
msgid "video/vaapi: can't map the image!\n" #, c-format
msgid "video/vaapi: can't create image: %s\n"
msgstr ""
#, c-format
msgid "video/vaapi: can't map the image: %s\n"
msgstr "" msgstr ""
msgid "video/vaapi: can't unmap the image!\n" msgid "video/vaapi: can't unmap the image!\n"
@ -997,6 +1030,10 @@ msgstr ""
msgid "video/vaapi: can't get source image\n" msgid "video/vaapi: can't get source image\n"
msgstr "" msgstr ""
#, c-format
msgid "video/vaapi: vaDeriveImage failed %d\n"
msgstr ""
#, c-format #, c-format
msgid "video/vaapi: can't put image: %d!\n" msgid "video/vaapi: can't put image: %d!\n"
msgstr "" msgstr ""
@ -1004,6 +1041,9 @@ msgstr ""
msgid "video/vaapi: stream <-> surface size mismatch\n" msgid "video/vaapi: stream <-> surface size mismatch\n"
msgstr "" msgstr ""
msgid "video/vaapi: can't map the image!\n"
msgstr ""
#, c-format #, c-format
msgid "video/vaapi: can't put image err:%d!\n" msgid "video/vaapi: can't put image err:%d!\n"
msgstr "" msgstr ""
@ -1031,7 +1071,7 @@ msgstr ""
msgid "video/vaapi: can't find a supported subpicture format" msgid "video/vaapi: can't find a supported subpicture format"
msgstr "" msgstr ""
msgid "video/vaapi: vaapi supports unscaled osd\n" msgid "video/vaapi: supports unscaled osd\n"
msgstr "" msgstr ""
msgid "video/vaapi: can't create osd image\n" msgid "video/vaapi: can't create osd image\n"
@ -1287,6 +1327,10 @@ msgstr ""
msgid "video/vdpau: can't render mixer: %s\n" msgid "video/vdpau: can't render mixer: %s\n"
msgstr "" msgstr ""
#, c-format
msgid "video/vdpau: can't query status: %s\n"
msgstr ""
#, c-format #, c-format
msgid "video/vdpau: can't block queue: %s\n" msgid "video/vdpau: can't block queue: %s\n"
msgstr "" msgstr ""

View File

@ -1,7 +1,7 @@
/// ///
/// @file ringbuffer.c @brief Ringbuffer module /// @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): /// Contributor(s):
/// ///
@ -30,8 +30,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <alsa/iatomic.h> #include "iatomic.h"
#include "ringbuffer.h" #include "ringbuffer.h"
/// ring buffer structure /// ring buffer structure

View File

@ -1,7 +1,7 @@
/// ///
/// @file softhddev.c @brief A software HD device plugin for VDR. /// @file softhddev.c @brief A software HD device plugin for VDR.
/// ///
/// Copyright (c) 2011 - 2013 by Johns. All Rights Reserved. /// Copyright (c) 2011 - 2015 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -32,15 +32,18 @@
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <inttypes.h> #include <inttypes.h>
#include <unistd.h> #include <unistd.h>
#include <string.h>
#include <libintl.h> #include <libintl.h>
#define _(str) gettext(str) ///< gettext shortcut #define _(str) gettext(str) ///< gettext shortcut
#define _N(str) str ///< gettext_noop shortcut #define _N(str) str ///< gettext_noop shortcut
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
#include <libavutil/mem.h>
// support old ffmpeg versions <1.0 // support old ffmpeg versions <1.0
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,18,102) #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,18,102)
#define AVCodecID CodecID #define AVCodecID CodecID
@ -60,6 +63,7 @@
#endif #endif
#include <pthread.h> #include <pthread.h>
#include "iatomic.h" // portable atomic_t
#include "misc.h" #include "misc.h"
#include "softhddev.h" #include "softhddev.h"
@ -76,15 +80,10 @@ static void DumpMpeg(const uint8_t * data, int size);
// Variables // Variables
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
#ifdef USE_VDPAU
static char VdpauDecoder = 1; ///< vdpau decoder used
#else
#define VdpauDecoder 0 ///< no vdpau decoder configured
#endif
extern int ConfigAudioBufferTime; ///< config size ms of audio buffer extern int ConfigAudioBufferTime; ///< config size ms of audio buffer
extern int ConfigVideoClearOnSwitch; //< clear decoder on channel switch
char ConfigStartX11Server; ///< flag start the x11 server char ConfigStartX11Server; ///< flag start the x11 server
static char ConfigStartSuspended; ///< flag to start in suspend mode static signed char ConfigStartSuspended; ///< flag to start in suspend mode
static char ConfigFullscreen; ///< fullscreen modus static char ConfigFullscreen; ///< fullscreen modus
static const char *X11ServerArguments; ///< default command arguments static const char *X11ServerArguments; ///< default command arguments
static char ConfigStillDecoder; ///< hw/sw decoder for still picture static char ConfigStillDecoder; ///< hw/sw decoder for still picture
@ -702,7 +701,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
Debug(3, "pesdemux: new codec %#06x -> %#06x\n", Debug(3, "pesdemux: new codec %#06x -> %#06x\n",
AudioCodecID, codec_id); AudioCodecID, codec_id);
CodecAudioClose(MyAudioDecoder); CodecAudioClose(MyAudioDecoder);
CodecAudioOpen(MyAudioDecoder, NULL, codec_id); CodecAudioOpen(MyAudioDecoder, codec_id);
AudioCodecID = codec_id; AudioCodecID = codec_id;
} }
av_init_packet(avpkt); av_init_packet(avpkt);
@ -875,7 +874,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
(q[5] & 0x7) + 1); (q[5] & 0x7) + 1);
// FIXME: support resample // FIXME: support resample
} }
//CodecAudioOpen(MyAudioDecoder, NULL, AV_CODEC_ID_PCM_DVD); //CodecAudioOpen(MyAudioDecoder, AV_CODEC_ID_PCM_DVD);
AudioCodecID = AV_CODEC_ID_PCM_DVD; AudioCodecID = AV_CODEC_ID_PCM_DVD;
} }
pesdx->State = PES_LPCM_PAYLOAD; pesdx->State = PES_LPCM_PAYLOAD;
@ -1096,6 +1095,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
if (AudioChannelID != id) { // id changed audio track changed if (AudioChannelID != id) { // id changed audio track changed
AudioChannelID = id; AudioChannelID = id;
AudioCodecID = AV_CODEC_ID_NONE; AudioCodecID = AV_CODEC_ID_NONE;
Debug(3, "audio/demux: new channel id\n");
} }
// Private stream + LPCM ID // Private stream + LPCM ID
if ((id & 0xF0) == 0xA0) { if ((id & 0xF0) == 0xA0) {
@ -1137,7 +1137,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
(p[5] & 0x7) + 1); (p[5] & 0x7) + 1);
// FIXME: support resample // FIXME: support resample
} }
//CodecAudioOpen(MyAudioDecoder, NULL, AV_CODEC_ID_PCM_DVD); //CodecAudioOpen(MyAudioDecoder, AV_CODEC_ID_PCM_DVD);
AudioCodecID = AV_CODEC_ID_PCM_DVD; AudioCodecID = AV_CODEC_ID_PCM_DVD;
} }
@ -1210,7 +1210,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
// new codec id, close and open new // new codec id, close and open new
if (AudioCodecID != codec_id) { if (AudioCodecID != codec_id) {
CodecAudioClose(MyAudioDecoder); CodecAudioClose(MyAudioDecoder);
CodecAudioOpen(MyAudioDecoder, NULL, codec_id); CodecAudioOpen(MyAudioDecoder, codec_id);
AudioCodecID = codec_id; AudioCodecID = codec_id;
} }
av_init_packet(avpkt); av_init_packet(avpkt);
@ -1299,12 +1299,19 @@ void SetVolumeDevice(int volume)
AudioSetVolume((volume * 1000) / 255); AudioSetVolume((volume * 1000) / 255);
} }
/**
*** Resets channel ID (restarts audio).
**/
void ResetChannelId(void)
{
AudioChannelID = -1;
Debug(3, "audio/demux: reset channel id\n");
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// Video // Video
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
#include <alsa/iatomic.h> // portable atomic_t
#define VIDEO_BUFFER_SIZE (512 * 1024) ///< video PES buffer default size #define VIDEO_BUFFER_SIZE (512 * 1024) ///< video PES buffer default size
#define VIDEO_PACKET_MAX 192 ///< max number of video packets #define VIDEO_PACKET_MAX 192 ///< max number of video packets
@ -1742,23 +1749,41 @@ static void FixPacketForFFMpeg(VideoDecoder * vdecoder, AVPacket * avpkt)
#endif #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. ** Close video stream.
** **
** @param stream 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. ** 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; stream->SkipStream = 1;
if (stream->Decoder) { if (stream->Decoder) {
VideoDecoder *decoder; VideoDecoder *decoder;
decoder = stream->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); pthread_mutex_lock(&stream->DecoderLockMutex);
stream->Decoder = NULL; // lock read thread stream->Decoder = NULL; // lock read thread
pthread_mutex_unlock(&stream->DecoderLockMutex); pthread_mutex_unlock(&stream->DecoderLockMutex);
@ -1766,7 +1791,9 @@ static void VideoStreamClose(VideoStream * stream)
CodecVideoDelDecoder(decoder); CodecVideoDelDecoder(decoder);
} }
if (stream->HwDecoder) { if (stream->HwDecoder) {
if (delhw) {
VideoDelHwDecoder(stream->HwDecoder); VideoDelHwDecoder(stream->HwDecoder);
}
stream->HwDecoder = NULL; stream->HwDecoder = NULL;
// FIXME: CodecVideoClose calls/uses hw decoder // FIXME: CodecVideoClose calls/uses hw decoder
} }
@ -1796,13 +1823,14 @@ int VideoPollInput(VideoStream * stream)
} }
if (stream->Close) { // close stream request if (stream->Close) { // close stream request
VideoStreamClose(stream); VideoStreamClose(stream, 1);
stream->Close = 0; stream->Close = 0;
return 1; return 1;
} }
if (stream->ClearBuffers) { // clear buffer request if (stream->ClearBuffers) { // clear buffer request
atomic_set(&stream->PacketsFilled, 0); atomic_set(&stream->PacketsFilled, 0);
stream->PacketRead = stream->PacketWrite; stream->PacketRead = stream->PacketWrite;
// FIXME: ->Decoder already checked
if (stream->Decoder) { if (stream->Decoder) {
CodecVideoFlushBuffers(stream->Decoder); CodecVideoFlushBuffers(stream->Decoder);
VideoResetStart(stream->HwDecoder); VideoResetStart(stream->HwDecoder);
@ -1839,13 +1867,14 @@ int VideoDecodeInput(VideoStream * stream)
} }
if (stream->Close) { // close stream request if (stream->Close) { // close stream request
VideoStreamClose(stream); VideoStreamClose(stream, 1);
stream->Close = 0; stream->Close = 0;
return 1; return 1;
} }
if (stream->ClearBuffers) { // clear buffer request if (stream->ClearBuffers) { // clear buffer request
atomic_set(&stream->PacketsFilled, 0); atomic_set(&stream->PacketsFilled, 0);
stream->PacketRead = stream->PacketWrite; stream->PacketRead = stream->PacketWrite;
// FIXME: ->Decoder already checked
if (stream->Decoder) { if (stream->Decoder) {
CodecVideoFlushBuffers(stream->Decoder); CodecVideoFlushBuffers(stream->Decoder);
VideoResetStart(stream->HwDecoder); VideoResetStart(stream->HwDecoder);
@ -1905,16 +1934,13 @@ int VideoDecodeInput(VideoStream * stream)
case AV_CODEC_ID_MPEG2VIDEO: case AV_CODEC_ID_MPEG2VIDEO:
if (stream->LastCodecID != AV_CODEC_ID_MPEG2VIDEO) { if (stream->LastCodecID != AV_CODEC_ID_MPEG2VIDEO) {
stream->LastCodecID = AV_CODEC_ID_MPEG2VIDEO; stream->LastCodecID = AV_CODEC_ID_MPEG2VIDEO;
CodecVideoOpen(stream->Decoder, VideoHardwareDecoder < 0 CodecVideoOpen(stream->Decoder, AV_CODEC_ID_MPEG2VIDEO);
&& VdpauDecoder ? "mpegvideo_vdpau" : NULL,
AV_CODEC_ID_MPEG2VIDEO);
} }
break; break;
case AV_CODEC_ID_H264: case AV_CODEC_ID_H264:
if (stream->LastCodecID != AV_CODEC_ID_H264) { if (stream->LastCodecID != AV_CODEC_ID_H264) {
stream->LastCodecID = AV_CODEC_ID_H264; stream->LastCodecID = AV_CODEC_ID_H264;
CodecVideoOpen(stream->Decoder, VideoHardwareDecoder CodecVideoOpen(stream->Decoder, AV_CODEC_ID_H264);
&& VdpauDecoder ? "h264_vdpau" : NULL, AV_CODEC_ID_H264);
} }
break; break;
default: default:
@ -1978,9 +2004,6 @@ int VideoGetBuffers(const VideoStream * stream)
static void StartVideo(void) static void StartVideo(void)
{ {
VideoInit(X11DisplayName); VideoInit(X11DisplayName);
#ifdef USE_VDPAU
VdpauDecoder = !strcasecmp(VideoGetDriverName(), "vdpau");
#endif
if (ConfigFullscreen) { if (ConfigFullscreen) {
// FIXME: not good looking, mapped and then resized. // FIXME: not good looking, mapped and then resized.
@ -1988,17 +2011,8 @@ static void StartVideo(void)
} }
VideoOsdInit(); VideoOsdInit();
if (!MyVideoStream->Decoder) { if (!MyVideoStream->Decoder) {
MyVideoStream->SkipStream = 1; VideoStreamOpen(MyVideoStream);
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; AudioSyncStream = MyVideoStream;
MyVideoStream->SkipStream = 0;
}
} }
} }
@ -2010,6 +2024,10 @@ static void StopVideo(void)
VideoOsdExit(); VideoOsdExit();
VideoExit(); VideoExit();
AudioSyncStream = NULL; AudioSyncStream = NULL;
#if 1
// FIXME: done by exit: VideoDelHwDecoder(MyVideoStream->HwDecoder);
VideoStreamClose(MyVideoStream, 0);
#else
MyVideoStream->SkipStream = 1; MyVideoStream->SkipStream = 1;
if (MyVideoStream->Decoder) { if (MyVideoStream->Decoder) {
VideoDecoder *decoder; VideoDecoder *decoder;
@ -2030,6 +2048,7 @@ static void StopVideo(void)
MyVideoStream->NewStream = 1; MyVideoStream->NewStream = 1;
MyVideoStream->InvalidPesCounter = 0; MyVideoStream->InvalidPesCounter = 0;
#endif
} }
#ifdef DEBUG #ifdef DEBUG
@ -2447,10 +2466,12 @@ uint8_t *GrabImage(int *size, int jpeg, int quality, int width, int height)
*/ */
int SetPlayMode(int play_mode) int SetPlayMode(int play_mode)
{ {
VideoDisplayWakeup(); switch (play_mode) {
// tell video parser we have new stream case 0: // audio/video from decoder
// tell video parser we get new stream
if (MyVideoStream->Decoder && !MyVideoStream->SkipStream) { if (MyVideoStream->Decoder && !MyVideoStream->SkipStream) {
if (MyVideoStream->ClearClose) { // replay clear buffers on close // clear buffers on close configured always or replay only
if (ConfigVideoClearOnSwitch || MyVideoStream->ClearClose) {
Clear(); // flush all buffers Clear(); // flush all buffers
MyVideoStream->ClearClose = 0; MyVideoStream->ClearClose = 0;
} }
@ -2462,6 +2483,7 @@ int SetPlayMode(int play_mode)
VideoResetStart(MyVideoStream->HwDecoder); VideoResetStart(MyVideoStream->HwDecoder);
#ifdef DEBUG #ifdef DEBUG
VideoSwitch = GetMsTicks(); VideoSwitch = GetMsTicks();
Debug(3, "video: new stream start\n");
#endif #endif
} }
} }
@ -2470,22 +2492,22 @@ int SetPlayMode(int play_mode)
NewAudioStream = 1; NewAudioStream = 1;
} }
} }
switch (play_mode) { break;
case 0: // nothing
case 1: // audio/video from player case 1: // audio/video from player
VideoDisplayWakeup();
Play();
break; break;
case 2: // audio only 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"); Debug(3, "softhddev: FIXME: audio only, silence video errors\n");
VideoDisplayWakeup();
Play();
break; break;
case 3: // audio only, black screen case 4: // video only from player, audio from decoder
Debug(3, "softhddev: FIXME: audio only, silence video errors\n"); VideoDisplayWakeup();
break; Play();
case 4: // video only
break; break;
} }
Play();
return 1; return 1;
} }
@ -2569,8 +2591,10 @@ void Clear(void)
VideoResetPacket(MyVideoStream); // terminate work VideoResetPacket(MyVideoStream); // terminate work
MyVideoStream->ClearBuffers = 1; MyVideoStream->ClearBuffers = 1;
if (!SkipAudio) {
AudioFlushBuffers(); AudioFlushBuffers();
//NewAudioStream = 1; //NewAudioStream = 1;
}
// FIXME: audio avcodec_flush_buffers, video is done by VideoClearBuffers // FIXME: audio avcodec_flush_buffers, video is done by VideoClearBuffers
// wait for empty buffers // wait for empty buffers
@ -2830,17 +2854,21 @@ void OsdClose(void)
/** /**
** Draw an OSD pixmap. ** Draw an OSD pixmap.
** **
** @param xi x-coordinate in argb image
** @param yi y-coordinate in argb image
** @paran height height in pixel in argb image
** @paran width width in pixel in argb image
** @param pitch pitch of argb image
** @param argb 32bit ARGB image data
** @param x x-coordinate on screen of argb image ** @param x x-coordinate on screen of argb image
** @param y y-coordinate on screen of argb image ** @param y y-coordinate on screen of argb image
** @paran height height in pixel of argb image
** @paran width width in pixel of argb image
** @param argb height * width 32bit ARGB image data
*/ */
void OsdDrawARGB(int x, int y, int height, int width, const uint8_t * argb) void OsdDrawARGB(int xi, int yi, int height, int width, int pitch,
const uint8_t * argb, int x, int y)
{ {
// wakeup display for showing remote learning dialog // wakeup display for showing remote learning dialog
VideoDisplayWakeup(); VideoDisplayWakeup();
VideoOsdDrawARGB(x, y, height, width, argb); VideoOsdDrawARGB(xi, yi, height, width, pitch, argb, x, y);
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -2866,7 +2894,10 @@ const char *CommandLineHelp(void)
"\tstill-hw-decoder\tenable hardware decoder for still-pictures\n" "\tstill-hw-decoder\tenable hardware decoder for still-pictures\n"
"\tstill-h264-hw-decoder\tenable h264 hw 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-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" "\tignore-repeat-pict\tdisable repeat pict message\n"
"\tuse-possible-defect-frames prefer faster channel switch\n"
" -D\t\tstart in detached mode\n"; " -D\t\tstart in detached mode\n";
} }
@ -2942,8 +2973,14 @@ int ProcessArgs(int argc, char *const argv[])
ConfigStillDecoder = 1; ConfigStillDecoder = 1;
} else if (!strcasecmp("alsa-driver-broken", optarg)) { } else if (!strcasecmp("alsa-driver-broken", optarg)) {
AudioAlsaDriverBroken = 1; 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)) { } else if (!strcasecmp("ignore-repeat-pict", optarg)) {
VideoIgnoreRepeatPict = 1; VideoIgnoreRepeatPict = 1;
} else if (!strcasecmp("use-possible-defect-frames", optarg)) {
CodecUsePossibleDefectFrames = 1;
} else { } else {
fprintf(stderr, _("Workaround '%s' unsupported\n"), fprintf(stderr, _("Workaround '%s' unsupported\n"),
optarg); optarg);
@ -3060,7 +3097,7 @@ static void StartXServer(void)
Debug(3, "x-setup: Starting X server '%s' '%s'\n", args[0], Debug(3, "x-setup: Starting X server '%s' '%s'\n", args[0],
X11ServerArguments); X11ServerArguments);
// fork // fork
if ((pid = vfork())) { // parent if ((pid = fork())) { // parent
X11ServerPid = pid; X11ServerPid = pid;
Debug(3, "x-setup: Started x-server pid=%d\n", X11ServerPid); Debug(3, "x-setup: Started x-server pid=%d\n", X11ServerPid);
@ -3280,6 +3317,8 @@ void Suspend(int video, int audio, int dox11)
DelPip(); // must stop PIP DelPip(); // must stop PIP
#endif #endif
// FIXME: should not be correct, if not both are suspended!
// Move down into if (video) ...
MyVideoStream->SkipStream = 1; MyVideoStream->SkipStream = 1;
SkipAudio = 1; SkipAudio = 1;
@ -3426,16 +3465,7 @@ void PipStart(int x, int y, int width, int height, int pip_x, int pip_y,
} }
if (!PipVideoStream->Decoder) { if (!PipVideoStream->Decoder) {
PipVideoStream->SkipStream = 1; VideoStreamOpen(PipVideoStream);
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;
}
} }
PipSetPosition(x, y, width, height, pip_x, pip_y, pip_width, pip_height); PipSetPosition(x, y, width, height, pip_x, pip_y, pip_width, pip_height);
} }
@ -3453,34 +3483,11 @@ void PipStop(void)
ScaleVideo(0, 0, 0, 0); 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; PipVideoStream->Close = 1;
for (i = 0; PipVideoStream->Close && i < 50; ++i) { for (i = 0; PipVideoStream->Close && i < 50; ++i) {
usleep(1 * 1000); usleep(1 * 1000);
} }
Info("[softhddev]%s: pip close %dms\n", __FUNCTION__, i); Info("[softhddev]%s: pip close %dms\n", __FUNCTION__, i);
#endif
} }
/** /**

View File

@ -1,7 +1,7 @@
/// ///
/// @file softhddev.h @brief software HD device plugin header file. /// @file softhddev.h @brief software HD device plugin header file.
/// ///
/// Copyright (c) 2011 - 2013 by Johns. All Rights Reserved. /// Copyright (c) 2011 - 2015 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -25,7 +25,8 @@ extern "C"
{ {
#endif #endif
/// C callback feed key press /// 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 /// C plugin get osd size and ascpect
extern void GetOsdSize(int *, int *, double *); extern void GetOsdSize(int *, int *, double *);
@ -33,7 +34,8 @@ extern "C"
/// C plugin close osd /// C plugin close osd
extern void OsdClose(void); extern void OsdClose(void);
/// C plugin draw osd pixmap /// C plugin draw osd pixmap
extern void OsdDrawARGB(int, int, int, int, const uint8_t *); extern void OsdDrawARGB(int, int, int, int, int, const uint8_t *, int,
int);
/// C plugin play audio packet /// C plugin play audio packet
extern int PlayAudio(const uint8_t *, int, uint8_t); extern int PlayAudio(const uint8_t *, int, uint8_t);
@ -41,6 +43,8 @@ extern "C"
extern int PlayTsAudio(const uint8_t *, int); extern int PlayTsAudio(const uint8_t *, int);
/// C plugin set audio volume /// C plugin set audio volume
extern void SetVolumeDevice(int); extern void SetVolumeDevice(int);
/// C plugin reset channel id (restarts audio)
extern void ResetChannelId(void);
/// C plugin play video packet /// C plugin play video packet
extern int PlayVideo(const uint8_t *, int); extern int PlayVideo(const uint8_t *, int);

View File

@ -1,7 +1,7 @@
/// ///
/// @file softhddevice.cpp @brief A software HD device plugin for VDR. /// @file softhddevice.cpp @brief A software HD device plugin for VDR.
/// ///
/// Copyright (c) 2011 - 2013 by Johns. All Rights Reserved. /// Copyright (c) 2011 - 2015 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -47,6 +47,13 @@ extern "C"
#include "codec.h" #include "codec.h"
} }
#if APIVERSNUM >= 20301
#define MURKS ->
#else
#define MURKS .
#define LOCK_CHANNELS_READ do { } while (0)
#endif
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// vdr-plugin version number. /// vdr-plugin version number.
@ -79,6 +86,7 @@ static const char *const Resolution[RESOLUTIONS] = {
static char ConfigMakePrimary; ///< config primary wanted static char ConfigMakePrimary; ///< config primary wanted
static char ConfigHideMainMenuEntry; ///< config hide main menu entry 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 ConfigSuspendClose; ///< suspend should close devices
static char ConfigSuspendX11; ///< suspend should stop x11 static char ConfigSuspendX11; ///< suspend should stop x11
@ -91,6 +99,7 @@ static char ConfigVideoStudioLevels; ///< config use studio levels
static char ConfigVideo60HzMode; ///< config use 60Hz display mode static char ConfigVideo60HzMode; ///< config use 60Hz display mode
static char ConfigVideoSoftStartSync; ///< config use softstart sync static char ConfigVideoSoftStartSync; ///< config use softstart sync
static char ConfigVideoBlackPicture; ///< config enable black picture mode static char ConfigVideoBlackPicture; ///< config enable black picture mode
char ConfigVideoClearOnSwitch; ///< config enable Clear on channel switch
static int ConfigVideoBrightness; ///< config video brightness static int ConfigVideoBrightness; ///< config video brightness
static int ConfigVideoContrast = 1000; ///< config video contrast static int ConfigVideoContrast = 1000; ///< config video contrast
@ -138,6 +147,7 @@ static char ConfigAudioCompression; ///< config use volume compression
static int ConfigAudioMaxCompression; ///< config max volume compression static int ConfigAudioMaxCompression; ///< config max volume compression
static int ConfigAudioStereoDescent; ///< config reduce stereo loudness static int ConfigAudioStereoDescent; ///< config reduce stereo loudness
int ConfigAudioBufferTime; ///< config size ms of audio buffer int ConfigAudioBufferTime; ///< config size ms of audio buffer
static int ConfigAudioAutoAES; ///< config automatic AES handling
static char *ConfigX11Display; ///< config x11 display static char *ConfigX11Display; ///< config x11 display
static char *ConfigAudioDevice; ///< config audio stereo device static char *ConfigAudioDevice; ///< config audio stereo device
@ -162,13 +172,17 @@ static int ConfigPipAltVideoWidth; ///< config pip alt. video width in %
static int ConfigPipAltVideoHeight = 50; ///< config pip alt. video height in % static int ConfigPipAltVideoHeight = 50; ///< config pip alt. video height in %
#endif #endif
#ifdef USE_SCREENSAVER
static char ConfigEnableDPMSatBlackScreen; ///< Enable DPMS(Screensaver) while displaying black screen(radio)
#endif
static volatile int DoMakePrimary; ///< switch primary device to this static volatile int DoMakePrimary; ///< switch primary device to this
#define SUSPEND_EXTERNAL -1 ///< play external suspend mode #define SUSPEND_EXTERNAL -1 ///< play external suspend mode
#define NOT_SUSPENDED 0 ///< not suspend mode #define NOT_SUSPENDED 0 ///< not suspend mode
#define SUSPEND_NORMAL 1 ///< normal suspend mode #define SUSPEND_NORMAL 1 ///< normal suspend mode
#define SUSPEND_DETACHED 2 ///< detached suspend mode #define SUSPEND_DETACHED 2 ///< detached suspend mode
static char SuspendMode; ///< suspend mode static signed char SuspendMode; ///< suspend mode
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -211,9 +225,10 @@ class cSoftRemote:public cRemote
** @param key pressed/released key name ** @param key pressed/released key name
** @param repeat repeated key flag ** @param repeat repeated key flag
** @param release released 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, extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat,
int release) int release, const char *letter)
{ {
cRemote *remote; cRemote *remote;
cSoftRemote *csoft; cSoftRemote *csoft;
@ -236,9 +251,18 @@ extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat,
csoft = new cSoftRemote(keymap); 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 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)) { } else if (!csoft->Put(key, repeat, release)) {
cRemote::Put(KBDKEY(key[0])); // feed it for edit mode cRemote::Put(KBDKEY(key[0])); // feed it for edit mode
} }
@ -255,10 +279,12 @@ class cSoftOsd:public cOsd
{ {
public: public:
static volatile char Dirty; ///< flag force redraw everything 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 cSoftOsd(int, int, uint); ///< osd constructor
virtual ~ cSoftOsd(void); ///< osd destructor 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 Flush(void); ///< commits all data to the hardware
virtual void SetActive(bool); ///< sets OSD to be the active one virtual void SetActive(bool); ///< sets OSD to be the active one
}; };
@ -284,11 +310,6 @@ void cSoftOsd::SetActive(bool on)
} }
cOsd::SetActive(on); cOsd::SetActive(on);
// ignore sub-title if menu is open
if (OsdLevel >= OSD_LEVEL_SUBTITLES && IsOpen()) {
return;
}
if (on) { if (on) {
Dirty = 1; Dirty = 1;
// only flush here if there are already bitmaps // only flush here if there are already bitmaps
@ -320,7 +341,6 @@ cSoftOsd::cSoftOsd(int left, int top, uint level)
#endif #endif
OsdLevel = level; OsdLevel = level;
SetActive(true);
} }
/** /**
@ -351,6 +371,31 @@ cSoftOsd::~cSoftOsd(void)
#endif #endif
} }
/**
+* 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. ** Actually commits all data to the OSD hardware.
*/ */
@ -366,10 +411,6 @@ void cSoftOsd::Flush(void)
if (!Active()) { // this osd is not active if (!Active()) { // this osd is not active
return; return;
} }
// don't draw sub-title if menu is active
if (OsdLevel >= OSD_LEVEL_SUBTITLES && IsOpen()) {
return;
}
#ifdef USE_YAEPG #ifdef USE_YAEPG
// support yaepghd, video window // support yaepghd, video window
if (vidWin.bpp) { if (vidWin.bpp) {
@ -385,17 +426,6 @@ void cSoftOsd::Flush(void)
} }
#endif #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()) { if (!IsTrueColor()) {
cBitmap *bitmap; cBitmap *bitmap;
int i; int i;
@ -412,6 +442,8 @@ void cSoftOsd::Flush(void)
// draw all bitmaps // draw all bitmaps
for (i = 0; (bitmap = GetBitmap(i)); ++i) { for (i = 0; (bitmap = GetBitmap(i)); ++i) {
uint8_t *argb; uint8_t *argb;
int xs;
int ys;
int x; int x;
int y; int y;
int w; int w;
@ -430,22 +462,52 @@ void cSoftOsd::Flush(void)
} else if (!bitmap->Dirty(x1, y1, x2, y2)) { } else if (!bitmap->Dirty(x1, y1, x2, y2)) {
continue; // nothing dirty continue continue; // nothing dirty continue
} }
// convert and upload only dirty areas // convert and upload only visible dirty areas
xs = bitmap->X0() + Left();
ys = bitmap->Y0() + Top();
// FIXME: negtative position bitmaps
w = x2 - x1 + 1; w = x2 - x1 + 1;
h = y2 - y1 + 1; h = y2 - y1 + 1;
// clip to screen
if (1) { // just for the case it makes trouble if (1) { // just for the case it makes trouble
int width; int width;
int height; int height;
double video_aspect; double video_aspect;
::GetOsdSize(&width, &height, &video_aspect); if (xs < 0) {
if (w > width) { if (xs + x1 < 0) {
w = width; x1 -= xs + x1;
x2 = x1 + width - 1; w += xs + x1;
if (w <= 0) {
continue;
} }
if (h > height) { }
h = height; xs = 0;
y2 = y1 + height - 1; }
if (ys < 0) {
if (ys + y1 < 0) {
y1 -= ys + y1;
h += ys + y1;
if (h <= 0) {
continue;
}
}
ys = 0;
}
::GetOsdSize(&width, &height, &video_aspect);
if (w > width - xs - x1) {
w = width - xs - x1;
if (w <= 0) {
continue;
}
x2 = x1 + w - 1;
}
if (h > height - ys - y1) {
h = height - ys - y1;
if (h <= 0) {
continue;
}
y2 = y1 + h - 1;
} }
} }
#ifdef DEBUG #ifdef DEBUG
@ -463,40 +525,99 @@ void cSoftOsd::Flush(void)
} }
#ifdef OSD_DEBUG #ifdef OSD_DEBUG
dsyslog("[softhddev]%s: draw %dx%d%+d%+d bm\n", __FUNCTION__, w, h, dsyslog("[softhddev]%s: draw %dx%d%+d%+d bm\n", __FUNCTION__, w, h,
Left() + bitmap->X0() + x1, Top() + bitmap->Y0() + y1); xs + x1, ys + y1);
#endif #endif
OsdDrawARGB(Left() + bitmap->X0() + x1, Top() + bitmap->Y0() + y1, OsdDrawARGB(0, 0, w, h, w * sizeof(uint32_t), argb, xs + x1,
w, h, argb); ys + y1);
bitmap->Clean(); bitmap->Clean();
// FIXME: reuse argb // FIXME: reuse argb
free(argb); free(argb);
} }
cSoftOsd::Dirty = 0; Dirty = 0;
return; return;
} }
LOCK_PIXMAPS; LOCK_PIXMAPS;
while ((pm = RenderPixmaps())) { while ((pm = (dynamic_cast < cPixmapMemory * >(RenderPixmaps())))) {
int xp;
int yp;
int stride;
int x; int x;
int y; int y;
int w; int w;
int h; int h;
x = Left() + pm->ViewPort().X(); x = pm->ViewPort().X();
y = Top() + pm->ViewPort().Y(); y = pm->ViewPort().Y();
w = pm->ViewPort().Width(); w = pm->ViewPort().Width();
h = pm->ViewPort().Height(); h = pm->ViewPort().Height();
stride = w * sizeof(tColor);
#ifdef OSD_DEBUG // clip to osd
dsyslog("[softhddev]%s: draw %dx%d%+d%+d %p\n", __FUNCTION__, w, h, x, xp = 0;
y, pm->Data()); if (x < 0) {
#endif xp = -x;
OsdDrawARGB(x, y, w, h, pm->Data()); w -= xp;
x = 0;
delete pm;
} }
cSoftOsd::Dirty = 0;
yp = 0;
if (y < 0) {
yp = -y;
h -= yp;
y = 0;
}
if (w > Width() - x) {
w = Width() - x;
}
if (h > Height() - y) {
h = Height() - y;
}
x += Left();
y += Top();
// clip to screen
if (1) { // just for the case it makes trouble
// and it can happen!
int width;
int height;
double video_aspect;
if (x < 0) {
w += x;
xp += -x;
x = 0;
}
if (y < 0) {
h += y;
yp += -y;
y = 0;
}
::GetOsdSize(&width, &height, &video_aspect);
if (w > width - x) {
w = width - x;
}
if (h > height - y) {
h = height - y;
}
}
#ifdef OSD_DEBUG
dsyslog("[softhddev]%s: draw %dx%d%+d%+d*%d -> %+d%+d %p\n",
__FUNCTION__, w, h, xp, yp, stride, x, y, pm->Data());
#endif
OsdDrawARGB(xp, yp, w, h, stride, pm->Data(), x, y);
#if APIVERSNUM >= 20110
DestroyPixmap(pm);
#else
delete pm;
#endif
}
Dirty = 0;
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -580,6 +701,7 @@ class cMenuSetupSoft:public cMenuSetupPage
int General; int General;
int MakePrimary; int MakePrimary;
int HideMainMenuEntry; int HideMainMenuEntry;
int DetachFromMainMenu;
int OsdSize; int OsdSize;
int OsdWidth; int OsdWidth;
int OsdHeight; int OsdHeight;
@ -595,6 +717,7 @@ class cMenuSetupSoft:public cMenuSetupPage
int _60HzMode; int _60HzMode;
int SoftStartSync; int SoftStartSync;
int BlackPicture; int BlackPicture;
int ClearOnSwitch;
int Brightness; int Brightness;
int Contrast; int Contrast;
@ -630,6 +753,7 @@ class cMenuSetupSoft:public cMenuSetupPage
int AudioMaxCompression; int AudioMaxCompression;
int AudioStereoDescent; int AudioStereoDescent;
int AudioBufferTime; int AudioBufferTime;
int AudioAutoAES;
#ifdef USE_PIP #ifdef USE_PIP
int Pip; int Pip;
@ -651,6 +775,9 @@ class cMenuSetupSoft:public cMenuSetupPage
int PipAltVideoHeight; int PipAltVideoHeight;
#endif #endif
#ifdef USE_SCREENSAVER
int EnableDPMSatBlackScreen;
#endif
/// @} /// @}
private: private:
inline cOsdItem * CollapsedItem(const char *, int &, const char * = NULL); inline cOsdItem * CollapsedItem(const char *, int &, const char * = NULL);
@ -757,6 +884,8 @@ void cMenuSetupSoft::Create(void)
// suspend // suspend
// //
Add(SeparatorItem(tr("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"), Add(new cMenuEditBoolItem(tr("Suspend closes video+audio"),
&SuspendClose, trVDR("no"), trVDR("yes"))); &SuspendClose, trVDR("no"), trVDR("yes")));
Add(new cMenuEditBoolItem(tr("Suspend stops x11"), &SuspendX11, Add(new cMenuEditBoolItem(tr("Suspend stops x11"), &SuspendX11,
@ -767,6 +896,11 @@ void cMenuSetupSoft::Create(void)
// //
Add(CollapsedItem(tr("Video"), Video)); Add(CollapsedItem(tr("Video"), Video));
if (Video) { if (Video) {
#ifdef USE_SCREENSAVER
Add(new
cMenuEditBoolItem(tr("Enable Screensaver(DPMS) at black screen"),
&EnableDPMSatBlackScreen, trVDR("no"), trVDR("yes")));
#endif
Add(new cMenuEditStraItem(trVDR("4:3 video display format"), Add(new cMenuEditStraItem(trVDR("4:3 video display format"),
&Video4to3DisplayFormat, 3, video_display_formats_4_3)); &Video4to3DisplayFormat, 3, video_display_formats_4_3));
Add(new cMenuEditStraItem(trVDR("16:9+other video display format"), Add(new cMenuEditStraItem(trVDR("16:9+other video display format"),
@ -785,6 +919,8 @@ void cMenuSetupSoft::Create(void)
trVDR("no"), trVDR("yes"))); trVDR("no"), trVDR("yes")));
Add(new cMenuEditBoolItem(tr("Black during channel switch"), Add(new cMenuEditBoolItem(tr("Black during channel switch"),
&BlackPicture, trVDR("no"), trVDR("yes"))); &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)"), Add(new cMenuEditIntItem(tr("Brightness (-1000..1000) (vdpau)"),
&Brightness, -1000, 1000, tr("min"), tr("max"))); &Brightness, -1000, 1000, tr("min"), tr("max")));
@ -872,6 +1008,8 @@ void cMenuSetupSoft::Create(void)
&AudioStereoDescent, 0, 1000)); &AudioStereoDescent, 0, 1000));
Add(new cMenuEditIntItem(tr("Audio buffer size (ms)"), Add(new cMenuEditIntItem(tr("Audio buffer size (ms)"),
&AudioBufferTime, 0, 1000)); &AudioBufferTime, 0, 1000));
Add(new cMenuEditBoolItem(tr("Enable automatic AES"), &AudioAutoAES,
trVDR("no"), trVDR("yes")));
} }
#ifdef USE_PIP #ifdef USE_PIP
// //
@ -977,6 +1115,7 @@ cMenuSetupSoft::cMenuSetupSoft(void)
General = 0; General = 0;
MakePrimary = ConfigMakePrimary; MakePrimary = ConfigMakePrimary;
HideMainMenuEntry = ConfigHideMainMenuEntry; HideMainMenuEntry = ConfigHideMainMenuEntry;
DetachFromMainMenu = ConfigDetachFromMainMenu;
// //
// osd // osd
// //
@ -1010,6 +1149,7 @@ cMenuSetupSoft::cMenuSetupSoft(void)
_60HzMode = ConfigVideo60HzMode; _60HzMode = ConfigVideo60HzMode;
SoftStartSync = ConfigVideoSoftStartSync; SoftStartSync = ConfigVideoSoftStartSync;
BlackPicture = ConfigVideoBlackPicture; BlackPicture = ConfigVideoBlackPicture;
ClearOnSwitch = ConfigVideoClearOnSwitch;
Brightness = ConfigVideoBrightness; Brightness = ConfigVideoBrightness;
Contrast = ConfigVideoContrast; Contrast = ConfigVideoContrast;
@ -1053,6 +1193,7 @@ cMenuSetupSoft::cMenuSetupSoft(void)
AudioMaxCompression = ConfigAudioMaxCompression; AudioMaxCompression = ConfigAudioMaxCompression;
AudioStereoDescent = ConfigAudioStereoDescent; AudioStereoDescent = ConfigAudioStereoDescent;
AudioBufferTime = ConfigAudioBufferTime; AudioBufferTime = ConfigAudioBufferTime;
AudioAutoAES = ConfigAudioAutoAES;
#ifdef USE_PIP #ifdef USE_PIP
// //
@ -1076,6 +1217,11 @@ cMenuSetupSoft::cMenuSetupSoft(void)
PipAltVideoWidth = ConfigPipAltVideoWidth; PipAltVideoWidth = ConfigPipAltVideoWidth;
PipAltVideoHeight = ConfigPipAltVideoHeight; PipAltVideoHeight = ConfigPipAltVideoHeight;
#endif #endif
#ifdef USE_SCREENSAVER
EnableDPMSatBlackScreen = ConfigEnableDPMSatBlackScreen;
#endif
Create(); Create();
} }
@ -1089,6 +1235,8 @@ void cMenuSetupSoft::Store(void)
SetupStore("MakePrimary", ConfigMakePrimary = MakePrimary); SetupStore("MakePrimary", ConfigMakePrimary = MakePrimary);
SetupStore("HideMainMenuEntry", ConfigHideMainMenuEntry = SetupStore("HideMainMenuEntry", ConfigHideMainMenuEntry =
HideMainMenuEntry); HideMainMenuEntry);
SetupStore("DetachFromMainMenu", ConfigDetachFromMainMenu =
DetachFromMainMenu);
switch (OsdSize) { switch (OsdSize) {
case 0: case 0:
OsdWidth = 0; OsdWidth = 0;
@ -1133,6 +1281,7 @@ void cMenuSetupSoft::Store(void)
VideoSetSoftStartSync(ConfigVideoSoftStartSync); VideoSetSoftStartSync(ConfigVideoSoftStartSync);
SetupStore("BlackPicture", ConfigVideoBlackPicture = BlackPicture); SetupStore("BlackPicture", ConfigVideoBlackPicture = BlackPicture);
VideoSetBlackPicture(ConfigVideoBlackPicture); VideoSetBlackPicture(ConfigVideoBlackPicture);
SetupStore("ClearOnSwitch", ConfigVideoClearOnSwitch = ClearOnSwitch);
SetupStore("Brightness", ConfigVideoBrightness = Brightness); SetupStore("Brightness", ConfigVideoBrightness = Brightness);
VideoSetBrightness(ConfigVideoBrightness); VideoSetBrightness(ConfigVideoBrightness);
@ -1187,6 +1336,12 @@ void cMenuSetupSoft::Store(void)
VideoSetAudioDelay(ConfigVideoAudioDelay); VideoSetAudioDelay(ConfigVideoAudioDelay);
SetupStore("AudioDrift", ConfigAudioDrift = AudioDrift); SetupStore("AudioDrift", ConfigAudioDrift = AudioDrift);
CodecSetAudioDrift(ConfigAudioDrift); CodecSetAudioDrift(ConfigAudioDrift);
// FIXME: can handle more audio state changes here
// downmix changed reset audio, to get change direct
if (ConfigAudioDownmix != AudioDownmix) {
ResetChannelId();
}
ConfigAudioPassthrough = (AudioPassthroughPCM ? CodecPCM : 0) ConfigAudioPassthrough = (AudioPassthroughPCM ? CodecPCM : 0)
| (AudioPassthroughAC3 ? CodecAC3 : 0) | (AudioPassthroughAC3 ? CodecAC3 : 0)
| (AudioPassthroughEAC3 ? CodecEAC3 : 0); | (AudioPassthroughEAC3 ? CodecEAC3 : 0);
@ -1214,6 +1369,8 @@ void cMenuSetupSoft::Store(void)
AudioStereoDescent); AudioStereoDescent);
AudioSetStereoDescent(ConfigAudioStereoDescent); AudioSetStereoDescent(ConfigAudioStereoDescent);
SetupStore("AudioBufferTime", ConfigAudioBufferTime = AudioBufferTime); SetupStore("AudioBufferTime", ConfigAudioBufferTime = AudioBufferTime);
SetupStore("AudioAutoAES", ConfigAudioAutoAES = AudioAutoAES);
AudioSetAutoAES(ConfigAudioAutoAES);
#ifdef USE_PIP #ifdef USE_PIP
SetupStore("pip.X", ConfigPipX = PipX); SetupStore("pip.X", ConfigPipX = PipX);
@ -1235,6 +1392,12 @@ void cMenuSetupSoft::Store(void)
SetupStore("pip.Alt.VideoHeight", ConfigPipAltVideoHeight = SetupStore("pip.Alt.VideoHeight", ConfigPipAltVideoHeight =
PipAltVideoHeight); PipAltVideoHeight);
#endif #endif
#ifdef USE_SCREENSAVER
SetupStore("EnableDPMSatBlackScreen", ConfigEnableDPMSatBlackScreen =
EnableDPMSatBlackScreen);
SetDPMSatBlackScreen(ConfigEnableDPMSatBlackScreen);
#endif
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -1350,7 +1513,11 @@ class cSoftReceiver:public cReceiver
{ {
protected: protected:
virtual void Activate(bool); virtual void Activate(bool);
#if APIVERSNUM >= 20301
virtual void Receive(const uchar *, int);
#else
virtual void Receive(uchar *, int); virtual void Receive(uchar *, int);
#endif
public: public:
cSoftReceiver(const cChannel *); ///< receiver constructor cSoftReceiver(const cChannel *); ///< receiver constructor
virtual ~ cSoftReceiver(); ///< receiver destructor virtual ~ cSoftReceiver(); ///< receiver destructor
@ -1484,7 +1651,11 @@ static void PipPesParse(const uint8_t * data, int size, int is_start)
** @param data ts packet ** @param data ts packet
** @param size size (#TS_PACKET_SIZE=188) of tes packet ** @param size size (#TS_PACKET_SIZE=188) of tes packet
*/ */
#if APIVERSNUM >= 20301
void cSoftReceiver::Receive(const uchar * data, int size)
#else
void cSoftReceiver::Receive(uchar * data, int size) void cSoftReceiver::Receive(uchar * data, int size)
#endif
{ {
const uint8_t *p; const uint8_t *p;
@ -1576,7 +1747,8 @@ static void NewPip(int channel_nr)
if (!channel_nr) { if (!channel_nr) {
channel_nr = cDevice::CurrentChannel(); channel_nr = cDevice::CurrentChannel();
} }
if (channel_nr && (channel = Channels.GetByNumber(channel_nr)) LOCK_CHANNELS_READ;
if (channel_nr && (channel = Channels MURKS GetByNumber(channel_nr))
&& (device = cDevice::GetDevice(channel, 0, false, false))) { && (device = cDevice::GetDevice(channel, 0, false, false))) {
DelPip(); DelPip();
@ -1622,14 +1794,16 @@ static void PipNextAvailableChannel(int direction)
DelPip(); // disable PIP to free the device DelPip(); // disable PIP to free the device
LOCK_CHANNELS_READ;
while (channel) { while (channel) {
bool ndr; bool ndr;
cDevice *device; cDevice *device;
channel = direction > 0 ? Channels.Next(channel) channel = direction > 0 ? Channels MURKS Next(channel)
: Channels.Prev(channel); : Channels MURKS Prev(channel);
if (!channel && Setup.ChannelsWrap) { if (!channel && Setup.ChannelsWrap) {
channel = direction > 0 ? Channels.First() : Channels.Last(); channel =
direction > 0 ? Channels MURKS First() : Channels MURKS Last();
} }
if (channel && !channel->GroupSep() if (channel && !channel->GroupSep()
&& (device = cDevice::GetDevice(channel, 0, false, true)) && (device = cDevice::GetDevice(channel, 0, false, true))
@ -1658,7 +1832,9 @@ static void SwapPipChannels(void)
NewPip(0); NewPip(0);
if (channel) { if (channel) {
Channels.SwitchTo(channel->Number()); LOCK_CHANNELS_READ;
Channels MURKS SwitchTo(channel->Number());
} }
} }
@ -1746,7 +1922,12 @@ void cSoftHdMenu::Create(void)
Clear(); // clear the menu Clear(); // clear the menu
SetHasHotkeys(); SetHasHotkeys();
if (ConfigDetachFromMainMenu) {
Add(new cOsdItem(hk(tr("Detach SoftHdDevice")), osUser1));
} else {
Add(new cOsdItem(hk(tr("Suspend SoftHdDevice")), osUser1)); Add(new cOsdItem(hk(tr("Suspend SoftHdDevice")), osUser1));
}
#ifdef USE_PIP #ifdef USE_PIP
if (PipReceiver) { if (PipReceiver) {
Add(new cOsdItem(hk(tr("PIP toggle on/off: off")), osUser2)); Add(new cOsdItem(hk(tr("PIP toggle on/off: off")), osUser2));
@ -1842,6 +2023,17 @@ static void HandleHotkey(int code)
cString::sprintf(tr("audio delay changed to %d"), cString::sprintf(tr("audio delay changed to %d"),
ConfigVideoAudioDelay)); ConfigVideoAudioDelay));
break; break;
case 15:
ConfigAudioDownmix ^= 1;
fprintf(stderr, "toggle downmix\n");
CodecSetAudioDownmix(ConfigAudioDownmix);
if (ConfigAudioDownmix) {
Skins.QueueMessage(mtInfo, tr("surround downmix enabled"));
} else {
Skins.QueueMessage(mtInfo, tr("surround downmix disabled"));
}
ResetChannelId();
break;
case 20: // disable full screen case 20: // disable full screen
VideoSetFullscreen(0); VideoSetFullscreen(0);
@ -1916,6 +2108,7 @@ static void HandleHotkey(int code)
break; break;
case 108: case 108:
DelPip(); DelPip();
PipChannelNr = 0;
break; break;
#endif #endif
@ -1993,9 +2186,14 @@ eOSState cSoftHdMenu::ProcessKey(eKeys key)
if (SuspendMode == NOT_SUSPENDED && !cSoftHdControl::Player) { if (SuspendMode == NOT_SUSPENDED && !cSoftHdControl::Player) {
cControl::Launch(new cSoftHdControl); cControl::Launch(new cSoftHdControl);
cControl::Attach(); cControl::Attach();
if (ConfigDetachFromMainMenu) {
Suspend(1, 1, 0);
SuspendMode = SUSPEND_DETACHED;
} else {
Suspend(ConfigSuspendClose, ConfigSuspendClose, Suspend(ConfigSuspendClose, ConfigSuspendClose,
ConfigSuspendX11); ConfigSuspendX11);
SuspendMode = SUSPEND_NORMAL; SuspendMode = SUSPEND_NORMAL;
}
if (ShutdownHandler.GetUserInactiveTime()) { if (ShutdownHandler.GetUserInactiveTime()) {
dsyslog("[softhddev]%s: set user inactive\n", dsyslog("[softhddev]%s: set user inactive\n",
__FUNCTION__); __FUNCTION__);
@ -2021,6 +2219,7 @@ eOSState cSoftHdMenu::ProcessKey(eKeys key)
return osEnd; return osEnd;
case osUser8: case osUser8:
DelPip(); DelPip();
PipChannelNr = 0;
return osEnd; return osEnd;
#endif #endif
default: default:
@ -2043,7 +2242,11 @@ class cSoftHdDevice:public cDevice
virtual bool HasDecoder(void) const; virtual bool HasDecoder(void) const;
virtual bool CanReplay(void) const; virtual bool CanReplay(void) const;
virtual bool SetPlayMode(ePlayMode); virtual bool SetPlayMode(ePlayMode);
#if APIVERSNUM >= 20103
virtual void TrickSpeed(int, bool);
#else
virtual void TrickSpeed(int); virtual void TrickSpeed(int);
#endif
virtual void Clear(void); virtual void Clear(void);
virtual void Play(void); virtual void Play(void);
virtual void Freeze(void); virtual void Freeze(void);
@ -2231,13 +2434,23 @@ int64_t cSoftHdDevice::GetSTC(void)
** times. ** times.
** **
** @param speed trick speed ** @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) void cSoftHdDevice::TrickSpeed(int speed)
{ {
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, speed); dsyslog("[softhddev]%s: %d\n", __FUNCTION__, speed);
::TrickSpeed(speed); ::TrickSpeed(speed);
} }
#endif
/** /**
** Clears all video and audio data from the device. ** Clears all video and audio data from the device.
@ -2542,8 +2755,8 @@ cRect cSoftHdDevice::CanScaleVideo(const cRect & rect,
void cSoftHdDevice::ScaleVideo(const cRect & rect) void cSoftHdDevice::ScaleVideo(const cRect & rect)
{ {
#ifdef OSD_DEBUG #ifdef OSD_DEBUG
dsyslog("[softhddev]%s: %dx%d%+d%+d\n", __FUNCTION__, VidWinRect.Width(), dsyslog("[softhddev]%s: %dx%d%+d%+d\n", __FUNCTION__, rect.Width(),
VidWinRect.Height(), VidWinRect.X(), VidWinRect.Y()); rect.Height(), rect.X(), rect.Y());
#endif #endif
::ScaleVideo(rect.X(), rect.Y(), rect.Width(), rect.Height()); ::ScaleVideo(rect.X(), rect.Y(), rect.Width(), rect.Height());
} }
@ -2803,6 +3016,10 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
ConfigHideMainMenuEntry = atoi(value); ConfigHideMainMenuEntry = atoi(value);
return true; return true;
} }
if (!strcasecmp(name, "DetachFromMainMenu")) {
ConfigDetachFromMainMenu = atoi(value);
return true;
}
if (!strcasecmp(name, "Osd.Width")) { if (!strcasecmp(name, "Osd.Width")) {
ConfigOsdWidth = atoi(value); ConfigOsdWidth = atoi(value);
VideoSetOsdSize(ConfigOsdWidth, ConfigOsdHeight); VideoSetOsdSize(ConfigOsdWidth, ConfigOsdHeight);
@ -2852,6 +3069,10 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
VideoSetBlackPicture(ConfigVideoBlackPicture = atoi(value)); VideoSetBlackPicture(ConfigVideoBlackPicture = atoi(value));
return true; return true;
} }
if (!strcasecmp(name, "ClearOnSwitch")) {
ConfigVideoClearOnSwitch = atoi(value);
return true;
}
if (!strcasecmp(name, "Brightness")) { if (!strcasecmp(name, "Brightness")) {
VideoSetBrightness(ConfigVideoBrightness = atoi(value)); VideoSetBrightness(ConfigVideoBrightness = atoi(value));
return true; return true;
@ -2998,6 +3219,11 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
ConfigAudioBufferTime = atoi(value); ConfigAudioBufferTime = atoi(value);
return true; return true;
} }
if (!strcasecmp(name, "AudioAutoAES")) {
ConfigAudioAutoAES = atoi(value);
AudioSetAutoAES(ConfigAudioAutoAES);
return true;
}
#ifdef USE_PIP #ifdef USE_PIP
if (!strcasecmp(name, "pip.X")) { if (!strcasecmp(name, "pip.X")) {
ConfigPipX = atoi(value); ConfigPipX = atoi(value);
@ -3064,6 +3290,15 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
return true; return true;
} }
#endif #endif
#ifdef USE_SCREENSAVER
if (!strcasecmp(name, "EnableDPMSatBlackScreen")) {
ConfigEnableDPMSatBlackScreen = atoi(value);
SetDPMSatBlackScreen(ConfigEnableDPMSatBlackScreen);
return true;
}
#endif
return false; return false;
} }
@ -3183,7 +3418,7 @@ static const char *SVDRPHelpText[] = {
" 11: enable audio pass-through\n" " 11: enable audio pass-through\n"
" 12: toggle audio pass-through\n" " 12: toggle audio pass-through\n"
" 13: decrease audio delay by 10ms\n" " 13: decrease audio delay by 10ms\n"
" 14: increase audio delay by 10ms\n" " 14: increase audio delay by 10ms\n" " 15: toggle ac3 mixdown\n"
" 20: disable fullscreen\n\040 21: enable fullscreen\n" " 20: disable fullscreen\n\040 21: enable fullscreen\n"
" 22: toggle fullscreen\n" " 22: toggle fullscreen\n"
" 23: disable auto-crop\n\040 24: enable auto-crop\n" " 23: disable auto-crop\n\040 24: enable auto-crop\n"

View File

@ -1,7 +1,7 @@
/// ///
/// @file softhddevice.h @brief software HD device plugin header file. /// @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): /// Contributor(s):
/// ///

View File

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

View File

@ -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 # Distributed under the terms of the GNU General Public License v2
# $Header: $ # $Header: $
EAPI="5" EAPI="5"
inherit flag-o-matic toolchain-funcs vdr-plugin-2 eutils inherit vdr-plugin-2 git-2
RESTRICT="test"
if [ "${PV}" = "9999" ]; then
inherit git-2
EGIT_REPO_URI="git://projects.vdr-developer.org/vdr-plugin-softhddevice.git" EGIT_REPO_URI="git://projects.vdr-developer.org/vdr-plugin-softhddevice.git"
KEYWORDS="" KEYWORDS=""
else
SRC_URI="mirror://vdr-developerorg/889/${P}.tgz"
KEYWORDS="~amd64 ~x86"
fi
DESCRIPTION="Software and GPU emulated HD output device plugin for VDR" DESCRIPTION="VDR Plugin: Software and GPU emulated HD output device"
HOMEPAGE="http://projects.vdr-developer.org/projects/show/plg-softhddevice" HOMEPAGE="http://projects.vdr-developer.org/projects/show/plg-softhddevice"
LICENSE="AGPL-3" LICENSE="AGPL-3"
SLOT="0" 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 RDEPEND=">=media-video/vdr-2
>=virtual/ffmpeg-0.7[vdpau?,vaapi?]
x11-libs/libX11 x11-libs/libX11
>=x11-libs/libxcb-1.8 >=x11-libs/libxcb-1.8
x11-libs/xcb-util-wm x11-libs/xcb-util-wm
x11-libs/xcb-util-keysyms
x11-libs/xcb-util-renderutil
alsa? ( media-libs/alsa-lib ) alsa? ( media-libs/alsa-lib )
vdpau? ( x11-libs/libvdpau )
vaapi? ( x11-libs/libva )
opengl? ( virtual/opengl ) opengl? ( virtual/opengl )
alsa? ( media-libs/alsa-lib ) vaapi? ( x11-libs/libva
yaepg? ( >=media-video/vdr-1.7[yaepg] )" virtual/ffmpeg[vaapi] )
vdpau? ( x11-libs/libvdpau
virtual/ffmpeg[vdpau] )"
DEPEND="${RDEPEND} DEPEND="${RDEPEND}
x11-libs/xcb-util
sys-devel/gettext
virtual/pkgconfig virtual/pkgconfig
oss? ( sys-kernel/linux-headers )" x11-libs/xcb-util"
src_compile() { REQUIRED_USE="opengl? ( vaapi )
local myconf || ( 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-cppflags -DHAVE_PTHREAD_NAME
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)"
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 if has_version ">=media-video/ffmpeg-0.8"; then
myconf+=" SWRESAMPLE=1" BUILD_PARAMS+=" SWRESAMPLE=1"
fi
if has_version ">=media-video/libav-0.8"; then
BUILD_PARAMS+=" AVRESAMPLE=1"
fi fi
append-cflags -DHAVE_PTHREAD_NAME -D_GNU_SOURCE
append-cxxflags -DHAVE_PTHREAD_NAME -D_GNU_SOURCE
tc-export CC CXX
BUILD_PARAMS="${myconf}"
vdr-plugin-2_src_compile
} }
src_install() { src_install() {
vdr-plugin-2_src_install vdr-plugin-2_src_install
dodoc ChangeLog README.txt nonfatal dodoc ChangeLog Todo
} }

741
video.c

File diff suppressed because it is too large Load Diff

12
video.h
View File

@ -1,7 +1,7 @@
/// ///
/// @file video.h @brief Video module header file /// @file video.h @brief Video module header file
/// ///
/// Copyright (c) 2009 - 2013 by Johns. All Rights Reserved. /// Copyright (c) 2009 - 2015 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -37,7 +37,7 @@ typedef struct __video_stream__ VideoStream;
// Variables // Variables
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
extern char VideoHardwareDecoder; ///< flag use hardware decoder extern signed char VideoHardwareDecoder; ///< flag use hardware decoder
extern char VideoIgnoreRepeatPict; ///< disable repeat pict warning extern char VideoIgnoreRepeatPict; ///< disable repeat pict warning
extern int VideoAudioDelay; ///< audio/video delay extern int VideoAudioDelay; ///< audio/video delay
extern char ConfigStartX11Server; ///< flag start the x11 server extern char ConfigStartX11Server; ///< flag start the x11 server
@ -168,7 +168,8 @@ extern void VideoSetAutoCrop(int, int, int);
extern void VideoOsdClear(void); extern void VideoOsdClear(void);
/// Draw an OSD ARGB image. /// Draw an OSD ARGB image.
extern void VideoOsdDrawARGB(int, int, int, int, const uint8_t *); extern void VideoOsdDrawARGB(int, int, int, int, int, const uint8_t *, int,
int);
/// Get OSD size. /// Get OSD size.
extern void VideoGetOsdSize(int *, int *); extern void VideoGetOsdSize(int *, int *);
@ -221,7 +222,10 @@ extern int VideoDecodeInput(VideoStream *);
/// Get number of input buffers. /// Get number of input buffers.
extern int VideoGetBuffers(const VideoStream *); extern int VideoGetBuffers(const VideoStream *);
/// Set DPMS at Blackscreen switch
extern void SetDPMSatBlackScreen(int);
/// Raise the frontend window /// Raise the frontend window
extern int VideoRaiseWindow(); extern int VideoRaiseWindow(void);
/// @} /// @}