mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 17:16:51 +00:00
Compare commits
95 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6dfa88aecf | ||
|
ee2311d252 | ||
|
4fa4f6616a | ||
|
5dc5601576 | ||
|
9e56747a56 | ||
|
5b90137050 | ||
|
f47ee3a201 | ||
|
93981031aa | ||
|
509329c90a | ||
|
8c347fdf1d | ||
|
06b8f77327 | ||
![]() |
700c8e8767 | ||
|
ec58e45607 | ||
|
396d5fac05 | ||
|
f0d31ad33c | ||
|
e0f4a99b99 | ||
|
a1939eb6cb | ||
|
28555643a5 | ||
|
2866e328c6 | ||
|
915dff8714 | ||
|
ca0181b1b1 | ||
|
a36221dea7 | ||
|
4e72638766 | ||
|
93ea660a38 | ||
|
73ce4ba803 | ||
|
1d06c5ba59 | ||
|
2ceeb6db40 | ||
|
4f4d304479 | ||
|
9f134c1b6d | ||
|
0adc02dd78 | ||
|
46e9f23355 | ||
|
ac1d5250c8 | ||
|
c2556eb90a | ||
|
a3c0052c4b | ||
|
8b7402a397 | ||
|
4a4de36878 | ||
|
37f409cb9a | ||
|
5207af6b2d | ||
|
90538ebfa9 | ||
|
ac7672053a | ||
|
0cdedb88ac | ||
|
42bbb763fd | ||
|
5bf2a9b761 | ||
|
b7d372aa39 | ||
|
3d3a88e76c | ||
|
450c9b6309 | ||
|
23ab3707dc | ||
![]() |
b3f0fe9fea | ||
|
f73f7a28f3 | ||
|
340e10a0eb | ||
![]() |
a45b9a3abe | ||
|
590bae406a | ||
|
501d46793f | ||
|
978fc59aba | ||
|
aee9bbed90 | ||
|
8577292c50 | ||
|
a74a8e1c74 | ||
|
e2a65cbf76 | ||
|
35a1dde089 | ||
|
7ffbfea224 | ||
|
bb70c75656 | ||
|
cfda3ba39d | ||
![]() |
0e40f5f872 | ||
|
fb2a7f9959 | ||
|
e3b32861b0 | ||
|
58a76439ee | ||
|
a13c25d309 | ||
|
5265e68aa9 | ||
|
11121b5bdd | ||
|
d8e96c7871 | ||
|
8ff65a011a | ||
|
171a3f4dc9 | ||
|
93357fb1cd | ||
|
c646007db1 | ||
|
7615305960 | ||
|
cc1e2de58b | ||
|
738e9402d2 | ||
|
34fd275b42 | ||
|
64c11efc1b | ||
|
ebb8482226 | ||
|
833112eaa9 | ||
|
3022920b40 | ||
|
c1d3b9d048 | ||
|
4fe1c43c08 | ||
|
7a5e696bc4 | ||
|
8f99f80d44 | ||
|
c0286b3ab4 | ||
|
9dd248f9d0 | ||
|
238224efc8 | ||
|
5b35e70b94 | ||
|
857546a3a5 | ||
|
a1b77b1502 | ||
|
7ef5667598 | ||
|
4e3f5f5414 | ||
|
23b0e0d599 |
152
ChangeLog
152
ChangeLog
@ -1,3 +1,155 @@
|
||||
User johns
|
||||
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.
|
||||
Add function GetStats to the video output module.
|
||||
Add function ResetStart to the video output module.
|
||||
Add function SetClosing to the video output module.
|
||||
Generalize GetVaapiContext to GetHwAccelContext.
|
||||
Add compile time configurable trickspeed packets dump.
|
||||
Fix bug #1410: wrong spelled AC-3 and E-AC-3.
|
||||
Add compile time selectable h264 trickspeed workaround.
|
||||
Use ffmpeg new names AVCodecID, AV_CODEC_... .
|
||||
Fix bug: video lagging behind after recording stop.
|
||||
Reduce PES error messages.
|
||||
Fix bug #1392: Wrong value for mixing LFE.
|
||||
Fix bug: wrong grab size, introduced with AMD VDPAU.
|
||||
Use VDR SPU decoder as default.
|
||||
Fix bug: grab image negative quality isn't the default 100.
|
||||
Support AMD VDPAU with surface size != requested size.
|
||||
Add cache for auto-crop buffer.
|
||||
Fix opengl and opengl threads bugs.
|
||||
Initial opengl support with va-api only.
|
||||
Fix "broken driver" message if empty ring buffer.
|
||||
Enable seamless audio track change.
|
||||
Fix bug #1302: Unsupported pixel format crash.
|
||||
Fix the fix, when sillpicture is called in suspend mode.
|
||||
Fix crash, when sillpicture is called in suspend mode.
|
||||
Add workaround for zero width+height and ffmpeg >= 1.2.
|
||||
|
||||
User johns
|
||||
Date: Sun Mar 17 15:52:42 CET 2013
|
||||
|
||||
|
104
Makefile
104
Makefile
@ -15,14 +15,20 @@ PLUGIN = softhddevice
|
||||
ALSA ?= $(shell pkg-config --exists alsa && echo 1)
|
||||
# support OSS audio output module
|
||||
OSS ?= 1
|
||||
# support VDPAU video output modue
|
||||
# support VDPAU video output module
|
||||
VDPAU ?= $(shell pkg-config --exists vdpau && echo 1)
|
||||
# support VA-API video output modue
|
||||
# support VA-API video output module (deprecated)
|
||||
VAAPI ?= $(shell pkg-config --exists libva && echo 1)
|
||||
# support glx output
|
||||
OPENGL ?= $(shell pkg-config --exists gl glu && echo 1)
|
||||
# screensaver disable/enable
|
||||
SCREENSAVER ?= 1
|
||||
# use ffmpeg libswresample
|
||||
SWRESAMPLE ?= $(shell pkg-config --exists libswresample && echo 1)
|
||||
# use libav libavresample
|
||||
ifneq ($(SWRESAMPLE),1)
|
||||
AVRESAMPLE ?= $(shell pkg-config --exists libavresample && echo 1)
|
||||
endif
|
||||
|
||||
CONFIG := # -DDEBUG #-DOSD_DEBUG # enable debug output+functions
|
||||
#CONFIG += -DSTILL_DEBUG=2 # still picture debug verbose level
|
||||
@ -32,40 +38,12 @@ 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
|
||||
#CONFIG += -DUSE_MPEG_COMPLETE # support only complete mpeg packets
|
||||
#CONFIG += -DUSE_VDR_SPU # use VDR SPU decoder.
|
||||
|
||||
ifeq ($(ALSA),1)
|
||||
CONFIG += -DUSE_ALSA
|
||||
_CFLAGS += $(shell pkg-config --cflags alsa)
|
||||
LIBS += $(shell pkg-config --libs alsa)
|
||||
endif
|
||||
ifeq ($(OSS),1)
|
||||
CONFIG += -DUSE_OSS
|
||||
endif
|
||||
ifeq ($(VDPAU),1)
|
||||
CONFIG += -DUSE_VDPAU
|
||||
_CFLAGS += $(shell pkg-config --cflags vdpau)
|
||||
LIBS += $(shell pkg-config --libs vdpau)
|
||||
endif
|
||||
ifeq ($(VAAPI),1)
|
||||
CONFIG += -DUSE_VAAPI
|
||||
_CFLAGS += $(shell pkg-config --cflags libva-x11 libva)
|
||||
LIBS += $(shell pkg-config --libs libva-x11 libva)
|
||||
endif
|
||||
ifeq ($(SCREENSAVER),1)
|
||||
CONFIG += -DUSE_SCREENSAVER
|
||||
_CFLAGS += $(shell pkg-config --cflags xcb-screensaver xcb-dpms)
|
||||
LIBS += $(shell pkg-config --libs xcb-screensaver xcb-dpms)
|
||||
endif
|
||||
ifeq ($(SWRESAMPLE),1)
|
||||
CONFIG += -DUSE_SWRESAMPLE
|
||||
_CFLAGS += $(shell pkg-config --cflags libswresample)
|
||||
LIBS += $(shell pkg-config --libs libswresample)
|
||||
endif
|
||||
|
||||
_CFLAGS += $(shell pkg-config --cflags libavcodec x11 x11-xcb xcb xcb-icccm)
|
||||
LIBS += -lrt $(shell pkg-config --libs libavcodec x11 x11-xcb xcb xcb-icccm)
|
||||
CONFIG += -DUSE_MPEG_COMPLETE # support only complete mpeg packets
|
||||
CONFIG += -DH264_EOS_TRICKSPEED # insert seq end packets for trickspeed
|
||||
#CONDIF += -DDUMP_TRICKSPEED # dump trickspeed packets
|
||||
#CONFIG += -DUSE_BITMAP # VDPAU, use bitmap surface for OSD
|
||||
CONFIG += -DUSE_VDR_SPU # use VDR SPU decoder.
|
||||
#CONFIG += -DUSE_SOFTLIMIT # (tobe removed) limit the buffer fill
|
||||
|
||||
### The version number of this plugin (taken from the main source file):
|
||||
|
||||
@ -75,7 +53,7 @@ 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))
|
||||
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)
|
||||
@ -88,10 +66,10 @@ export CFLAGS = $(call PKGCFG,cflags)
|
||||
export CXXFLAGS = $(call PKGCFG,cxxflags)
|
||||
|
||||
ifeq ($(CFLAGS),)
|
||||
$(error CFLAGS not set)
|
||||
$(warning CFLAGS not set)
|
||||
endif
|
||||
ifeq ($(CXXFLAGS),)
|
||||
$(error CXXFLAGS not set)
|
||||
$(warning CXXFLAGS not set)
|
||||
endif
|
||||
|
||||
### The version number of VDR's plugin API:
|
||||
@ -111,6 +89,54 @@ PACKAGE = vdr-$(ARCHIVE)
|
||||
|
||||
SOFILE = libvdr-$(PLUGIN).so
|
||||
|
||||
### Parse softhddevice config
|
||||
|
||||
ifeq ($(ALSA),1)
|
||||
CONFIG += -DUSE_ALSA
|
||||
_CFLAGS += $(shell pkg-config --cflags alsa)
|
||||
LIBS += $(shell pkg-config --libs alsa)
|
||||
endif
|
||||
ifeq ($(OSS),1)
|
||||
CONFIG += -DUSE_OSS
|
||||
endif
|
||||
ifeq ($(VDPAU),1)
|
||||
CONFIG += -DUSE_VDPAU
|
||||
_CFLAGS += $(shell pkg-config --cflags vdpau)
|
||||
LIBS += $(shell pkg-config --libs vdpau)
|
||||
endif
|
||||
ifeq ($(VAAPI),1)
|
||||
CONFIG += -DUSE_VAAPI
|
||||
_CFLAGS += $(shell pkg-config --cflags libva-x11 libva)
|
||||
LIBS += $(shell pkg-config --libs libva-x11 libva)
|
||||
ifeq ($(OPENGL),1)
|
||||
_CFLAGS += $(shell pkg-config --cflags libva-glx)
|
||||
LIBS += $(shell pkg-config --libs libva-glx)
|
||||
endif
|
||||
endif
|
||||
ifeq ($(OPENGL),1)
|
||||
CONFIG += -DUSE_GLX
|
||||
_CFLAGS += $(shell pkg-config --cflags gl glu)
|
||||
LIBS += $(shell pkg-config --libs gl glu)
|
||||
endif
|
||||
ifeq ($(SCREENSAVER),1)
|
||||
CONFIG += -DUSE_SCREENSAVER
|
||||
_CFLAGS += $(shell pkg-config --cflags xcb-screensaver xcb-dpms)
|
||||
LIBS += $(shell pkg-config --libs xcb-screensaver xcb-dpms)
|
||||
endif
|
||||
ifeq ($(SWRESAMPLE),1)
|
||||
CONFIG += -DUSE_SWRESAMPLE
|
||||
_CFLAGS += $(shell pkg-config --cflags libswresample)
|
||||
LIBS += $(shell pkg-config --libs libswresample)
|
||||
endif
|
||||
ifeq ($(AVRESAMPLE),1)
|
||||
CONFIG += -DUSE_AVRESAMPLE
|
||||
_CFLAGS += $(shell pkg-config --cflags libavresample)
|
||||
LIBS += $(shell pkg-config --libs libavresample)
|
||||
endif
|
||||
|
||||
_CFLAGS += $(shell pkg-config --cflags libavcodec x11 x11-xcb xcb xcb-icccm)
|
||||
LIBS += -lrt $(shell pkg-config --libs libavcodec x11 x11-xcb xcb xcb-icccm)
|
||||
|
||||
### Includes and Defines (add further entries here):
|
||||
|
||||
INCLUDES +=
|
||||
|
@ -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 $@
|
32
README.txt
32
README.txt
@ -20,14 +20,14 @@ $Id$
|
||||
|
||||
A software and GPU emulated HD output device plugin for VDR.
|
||||
|
||||
o Video decoder CPU / VA-API / VDPAU
|
||||
o Video output VA-API / VDPAU
|
||||
o Video decoder CPU / VDPAU
|
||||
o Video output VDPAU
|
||||
o Audio FFMpeg / Alsa / Analog
|
||||
o Audio FFMpeg / Alsa / Digital
|
||||
o Audio FFMpeg / OSS / Analog
|
||||
o HDMI/SPDIF pass-through
|
||||
o Software volume, compression, normalize and channel resample
|
||||
o YaepgHD support / new >1.7.33 VDR ScaleVideo API support
|
||||
o VDR ScaleVideo API
|
||||
o Software deinterlacer Bob (VA-API only)
|
||||
o Autocrop
|
||||
o Grab image (VDPAU only)
|
||||
@ -36,10 +36,11 @@ A software and GPU emulated HD output device plugin for VDR.
|
||||
o atmo light support with plugin http://github.com/durchflieger/DFAtmo
|
||||
o PIP (Picture-in-Picture) (VDPAU only)
|
||||
|
||||
o planned: Video decoder VA-API Branch: vaapi-ext/staging
|
||||
o planned: Video output XvBA / Opengl / Xv
|
||||
o planned: VA-API grab image
|
||||
o planned: Improved Software Deinterlacer (yadif or/and ffmpeg filters)
|
||||
o planned: Remove VA-API decoder and output support
|
||||
o planned: Video decoder OpenMax
|
||||
o planned: Video output Opengl / Xv
|
||||
o planned: Improved software deinterlacer (yadif or/and ffmpeg filters)
|
||||
o XvBa support is no longer planned (use future Radeon UVD VDPAU)
|
||||
|
||||
To compile you must have the 'requires' installed.
|
||||
|
||||
@ -83,14 +84,12 @@ Setup: environment
|
||||
if set don't use the hardware decoders
|
||||
NO_MPEG_HW=1
|
||||
if set don't use the hardware decoder for mpeg1/2
|
||||
STUDIO_LEVELS=1
|
||||
if set use studio levels with vdpau (deprecated use setup)
|
||||
|
||||
only if alsa is configured
|
||||
ALSA_DEVICE=default
|
||||
alsa PCM device name
|
||||
ALSA_PASSTHROUGH_DEVICE=
|
||||
alsa pass-though (AC3,EAC3,DTS,...) device name
|
||||
alsa pass-though (AC-3,E-AC-3,DTS,...) device name
|
||||
ALSA_MIXER=default
|
||||
alsa control device name
|
||||
ALSA_MIXER_CHANNEL=PCM
|
||||
@ -100,7 +99,7 @@ Setup: environment
|
||||
OSS_AUDIODEV=/dev/dsp
|
||||
oss dsp device name
|
||||
OSS_PASSTHROUGHDEV=
|
||||
oss pass-though (AC3,EAC3,DTS,...) device name
|
||||
oss pass-though (AC-3,E-AC-3,DTS,...) device name
|
||||
OSS_MIXERDEV=/dev/mixer
|
||||
oss mixer device name
|
||||
OSS_MIXER_CHANNEL=pcm
|
||||
@ -130,7 +129,7 @@ Setup: /etc/vdr/setup.conf
|
||||
|
||||
softhddevice.<res>.Deinterlace = 0
|
||||
0 = bob, 1 = weave, 2 = temporal, 3 = temporal_spatial, 4 = software
|
||||
(only 0, 1 supported with vaapi)
|
||||
(only 0, 1, 4 supported with VA-API)
|
||||
|
||||
softhddevice.<res>.SkipChromaDeinterlace = 0
|
||||
0 = disabled, 1 = enabled (for slower cards, poor qualität)
|
||||
@ -234,6 +233,10 @@ Setup: /etc/vdr/setup.conf
|
||||
0 disable black picture during channel switch
|
||||
1 enable black picture during channel switch
|
||||
|
||||
softhddevice.ClearOnSwitch = 0
|
||||
0 keep video und audio buffers during channel switch
|
||||
1 clear video and audio buffers on channel switch
|
||||
|
||||
softhddevice.Video4to3DisplayFormat = 1
|
||||
0 pan and scan
|
||||
1 letter box
|
||||
@ -318,6 +321,7 @@ Keymacros:
|
||||
@softhddevice Blue 1 2 toggle pass-through
|
||||
@softhddevice Blue 1 3 decrease 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 1 enable fullscreen
|
||||
@softhddevice Blue 2 2 toggle fullscreen
|
||||
@ -353,7 +357,7 @@ Requires:
|
||||
|
||||
media-video/ffmpeg (version >=0.7)
|
||||
Complete solution to record, convert and stream audio and
|
||||
video. Includes libavcodec.
|
||||
video. Includes libavcodec and libswresample.
|
||||
http://ffmpeg.org
|
||||
media-libs/alsa-lib
|
||||
Advanced Linux Sound Architecture Library
|
||||
@ -361,7 +365,7 @@ Requires:
|
||||
or
|
||||
kernel support for oss/oss4 or alsa oss emulation
|
||||
|
||||
x11-libs/libva
|
||||
x11-libs/libva (deprecated)
|
||||
Video Acceleration (VA) API for Linux
|
||||
http://www.freedesktop.org/wiki/Software/vaapi
|
||||
x11-libs/libva-intel-driver
|
||||
|
10
Todo
10
Todo
@ -1,6 +1,6 @@
|
||||
@file Todo @brief A software HD output device for VDR
|
||||
|
||||
Copyright (c) 2011, 2012 by Johns. All Rights Reserved.
|
||||
Copyright (c) 2011 - 2013 by Johns. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
@ -19,6 +19,9 @@ GNU Affero General Public License for more details.
|
||||
$Id: $
|
||||
|
||||
missing:
|
||||
documentation of the PIP hotkeys.
|
||||
svdrp help page missing PIP hotkeys.
|
||||
svdrp stat: add X11 crashed status.
|
||||
more software deinterlace (yadif, ...)
|
||||
more software decoder with software deinterlace
|
||||
suspend output / energie saver: stop and restart X11
|
||||
@ -40,11 +43,15 @@ video:
|
||||
check start with 24Hz display rate
|
||||
crash with ffmpeg without vaapi and vdpau.
|
||||
still-picture of PES recordings should use VideoMpegEnqueue.
|
||||
convert PIX_FMT_... PixelFormat to new names AV_PIX_FMT_..., AVPixelFormat.
|
||||
atmo service support 3D grab
|
||||
no warnings during still picture
|
||||
|
||||
vdpau:
|
||||
software deinterlace path not working.
|
||||
OSD looses transparency, during channel switch.
|
||||
OSD looses transparency, while moving cut marks.
|
||||
ffmpeg >=1.2 supports same API like VA-API.
|
||||
|
||||
libva:
|
||||
yaepghd (VaapiSetOutputPosition) support
|
||||
@ -121,6 +128,7 @@ unsorted:
|
||||
svdrp prim: support plugin names for device numbers.
|
||||
Workaround exists: hangup PipVideoStream -> Vdpau_get_format -> xcb -> poll
|
||||
+ lock DecoderLockMutex
|
||||
check compiletime and runtime ffmpeg/libav version during init.
|
||||
|
||||
future features (not planed for 1.0 - 1.5)
|
||||
|
||||
|
178
audio.c
178
audio.c
@ -1,7 +1,7 @@
|
||||
///
|
||||
/// @file audio.c @brief Audio module
|
||||
///
|
||||
/// Copyright (c) 2009 - 2013 by Johns. All Rights Reserved.
|
||||
/// Copyright (c) 2009 - 2014 by Johns. All Rights Reserved.
|
||||
///
|
||||
/// Contributor(s):
|
||||
///
|
||||
@ -88,7 +88,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <alsa/iatomic.h> // portable atomic_t
|
||||
#include "iatomic.h" // portable atomic_t
|
||||
|
||||
#include "ringbuffer.h"
|
||||
#include "misc.h"
|
||||
@ -123,6 +123,8 @@ static const AudioModule NoopModule; ///< forward definition of noop module
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
char AudioAlsaDriverBroken; ///< disable broken driver message
|
||||
char AudioAlsaNoCloseOpen; ///< disable alsa close/open fix
|
||||
char AudioAlsaCloseOpenDelay; ///< enable alsa close/open delay fix
|
||||
|
||||
static const char *AudioModuleName; ///< which audio module to use
|
||||
|
||||
@ -130,6 +132,7 @@ static const char *AudioModuleName; ///< which audio module to use
|
||||
static const AudioModule *AudioUsedModule = &NoopModule;
|
||||
static const char *AudioPCMDevice; ///< PCM device name
|
||||
static const char *AudioPassthroughDevice; ///< Passthrough device name
|
||||
static char AudioAppendAES; ///< flag automatic append AES
|
||||
static const char *AudioMixerDevice; ///< mixer device name
|
||||
static const char *AudioMixerChannel; ///< mixer channel name
|
||||
static char AudioDoingInit; ///> flag in init, reduce error
|
||||
@ -146,6 +149,7 @@ static int AudioBufferTime = 336; ///< audio buffer time in ms
|
||||
static pthread_t AudioThread; ///< audio play thread
|
||||
static pthread_mutex_t AudioMutex; ///< audio condition mutex
|
||||
static pthread_cond_t AudioStartCond; ///< condition variable
|
||||
static char AudioThreadStop; ///< stop audio thread
|
||||
#else
|
||||
static const int AudioThread; ///< dummy audio thread
|
||||
#endif
|
||||
@ -486,7 +490,7 @@ static void AudioSurround2Stereo(const int16_t * in, int in_chan, int frames,
|
||||
r += in[3] * 200; // Rs
|
||||
l += in[4] * 300; // C
|
||||
r += in[4] * 300;
|
||||
l += in[5] * 300; // LFE
|
||||
l += in[5] * 100; // LFE
|
||||
r += in[5] * 100;
|
||||
break;
|
||||
case 7: // 7.0
|
||||
@ -620,7 +624,7 @@ static void AudioResample(const int16_t * in, int in_chan, int frames,
|
||||
typedef struct _audio_ring_ring_
|
||||
{
|
||||
char FlushBuffers; ///< flag: flush buffers
|
||||
char Passthrough; ///< flag: use pass-through (AC3, ...)
|
||||
char Passthrough; ///< flag: use pass-through (AC-3, ...)
|
||||
int16_t PacketSize; ///< packet size
|
||||
unsigned HwSampleRate; ///< hardware sample rate in Hz
|
||||
unsigned HwChannels; ///< hardware number of channels
|
||||
@ -642,7 +646,7 @@ static unsigned AudioStartThreshold; ///< start play, if filled
|
||||
**
|
||||
** @param sample_rate sample-rate frequency
|
||||
** @param channels number of channels
|
||||
** @param passthrough use /pass-through (AC3, ...) device
|
||||
** @param passthrough use /pass-through (AC-3, ...) device
|
||||
**
|
||||
** @retval -1 error
|
||||
** @retval 0 okay
|
||||
@ -678,8 +682,7 @@ static int AudioRingAdd(unsigned sample_rate, int channels, int passthrough)
|
||||
}
|
||||
AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
|
||||
|
||||
// FIXME: don't flush buffers here
|
||||
AudioRing[AudioRingWrite].FlushBuffers = 1;
|
||||
AudioRing[AudioRingWrite].FlushBuffers = 0;
|
||||
AudioRing[AudioRingWrite].Passthrough = passthrough;
|
||||
AudioRing[AudioRingWrite].PacketSize = 0;
|
||||
AudioRing[AudioRingWrite].InSampleRate = sample_rate;
|
||||
@ -689,6 +692,9 @@ static int AudioRingAdd(unsigned sample_rate, int channels, int passthrough)
|
||||
AudioRing[AudioRingWrite].PTS = INT64_C(0x8000000000000000);
|
||||
RingBufferReset(AudioRing[AudioRingWrite].RingBuffer);
|
||||
|
||||
Debug(3, "audio: %d ring buffer prepared\n",
|
||||
atomic_read(&AudioRingFilled) + 1);
|
||||
|
||||
atomic_inc(&AudioRingFilled);
|
||||
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
@ -836,7 +842,7 @@ static int AlsaPlayRingbuffer(void)
|
||||
if (!avail) { // full or buffer empty
|
||||
break;
|
||||
}
|
||||
// muting pass-through ac3, can produce disturbance
|
||||
// muting pass-through AC-3, can produce disturbance
|
||||
if (AudioMute || (AudioSoftVolume
|
||||
&& !AudioRing[AudioRingRead].Passthrough)) {
|
||||
// FIXME: quick&dirty cast
|
||||
@ -937,7 +943,6 @@ static int AlsaThread(void)
|
||||
return -1;
|
||||
}
|
||||
for (;;) {
|
||||
pthread_testcancel();
|
||||
if (AudioPaused) {
|
||||
return 1;
|
||||
}
|
||||
@ -985,7 +990,7 @@ static int AlsaThread(void)
|
||||
/**
|
||||
** Open alsa pcm device.
|
||||
**
|
||||
** @param passthrough use pass-through (AC3, ...) device
|
||||
** @param passthrough use pass-through (AC-3, ...) device
|
||||
*/
|
||||
static snd_pcm_t *AlsaOpenPCM(int passthrough)
|
||||
{
|
||||
@ -1003,6 +1008,26 @@ static snd_pcm_t *AlsaOpenPCM(int passthrough)
|
||||
Info(_("audio/alsa: using %sdevice '%s'\n"),
|
||||
passthrough ? "pass-through " : "", device);
|
||||
}
|
||||
//
|
||||
// for AC3 pass-through try to set the non-audio bit, use AES0=6
|
||||
//
|
||||
if (passthrough && AudioAppendAES) {
|
||||
#if 0
|
||||
// FIXME: not yet finished
|
||||
char *buf;
|
||||
const char *s;
|
||||
int n;
|
||||
|
||||
n = strlen(device);
|
||||
buf = alloca(n + sizeof(":AES0=6") + 1);
|
||||
strcpy(buf, device);
|
||||
if (!(s = strchr(buf, ':'))) {
|
||||
// no alsa parameters
|
||||
strcpy(buf + n, ":AES=6");
|
||||
}
|
||||
Debug(3, "audio/alsa: try '%s'\n", buf);
|
||||
#endif
|
||||
}
|
||||
// open none blocking; if device is already used, we don't want wait
|
||||
if ((err =
|
||||
snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK,
|
||||
@ -1168,7 +1193,7 @@ static int64_t AlsaGetDelay(void)
|
||||
**
|
||||
** @param freq sample frequency
|
||||
** @param channels number of channels
|
||||
** @param passthrough use pass-through (AC3, ...) device
|
||||
** @param passthrough use pass-through (AC-3, ...) device
|
||||
**
|
||||
** @retval 0 everything ok
|
||||
** @retval 1 didn't support frequency/channels combination
|
||||
@ -1187,17 +1212,23 @@ static int AlsaSetup(int *freq, int *channels, int passthrough)
|
||||
// FIXME: if open fails for fe. pass-through, we never recover
|
||||
return -1;
|
||||
}
|
||||
if (1) { // close+open to fix HDMI no sound bug
|
||||
if (!AudioAlsaNoCloseOpen) { // close+open to fix HDMI no sound bug
|
||||
snd_pcm_t *handle;
|
||||
|
||||
handle = AlsaPCMHandle;
|
||||
// FIXME: need lock
|
||||
// no lock needed, thread exit in main loop only
|
||||
//Debug(3, "audio: %s [\n", __FUNCTION__);
|
||||
AlsaPCMHandle = NULL; // other threads should check handle
|
||||
snd_pcm_close(handle);
|
||||
if (AudioAlsaCloseOpenDelay) {
|
||||
usleep(50 * 1000); // 50ms delay for alsa recovery
|
||||
}
|
||||
// FIXME: can use multiple retries
|
||||
if (!(handle = AlsaOpenPCM(passthrough))) {
|
||||
return -1;
|
||||
}
|
||||
AlsaPCMHandle = handle;
|
||||
//Debug(3, "audio: %s ]\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
@ -1206,21 +1237,29 @@ static int AlsaSetup(int *freq, int *channels, int passthrough)
|
||||
AlsaUseMmap ? SND_PCM_ACCESS_MMAP_INTERLEAVED :
|
||||
SND_PCM_ACCESS_RW_INTERLEAVED, *channels, *freq, 1,
|
||||
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 ) {
|
||||
snd_pcm_close(AlsaPCMHandle);
|
||||
AlsaPCMHandle = NULL;
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
if ( err == -EBADFD ) {
|
||||
snd_pcm_close(AlsaPCMHandle);
|
||||
AlsaPCMHandle = NULL;
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
if (!AudioDoingInit) {
|
||||
Error(_("audio/alsa: set params error: %s\n"),
|
||||
snd_strerror(err));
|
||||
if (!AudioDoingInit) {
|
||||
Error(_("audio/alsa: set params error: %s\n"),
|
||||
snd_strerror(err));
|
||||
}
|
||||
// FIXME: must stop sound, AudioChannels ... invalid
|
||||
return -1;
|
||||
}
|
||||
// FIXME: must stop sound, AudioChannels ... invalid
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1519,7 +1558,6 @@ static int OssThread(void)
|
||||
for (;;) {
|
||||
struct pollfd fds[1];
|
||||
|
||||
pthread_testcancel();
|
||||
if (AudioPaused) {
|
||||
return 1;
|
||||
}
|
||||
@ -1561,7 +1599,7 @@ static int OssThread(void)
|
||||
/**
|
||||
** Open OSS pcm device.
|
||||
**
|
||||
** @param passthrough use pass-through (AC3, ...) device
|
||||
** @param passthrough use pass-through (AC-3, ...) device
|
||||
*/
|
||||
static int OssOpenPCM(int passthrough)
|
||||
{
|
||||
@ -1725,7 +1763,7 @@ static int64_t OssGetDelay(void)
|
||||
**
|
||||
** @param sample_rate sample rate/frequency
|
||||
** @param channels number of channels
|
||||
** @param passthrough use pass-through (AC3, ...) device
|
||||
** @param passthrough use pass-through (AC-3, ...) device
|
||||
**
|
||||
** @retval 0 everything ok
|
||||
** @retval 1 didn't support frequency/channels combination
|
||||
@ -1743,7 +1781,7 @@ static int OssSetup(int *sample_rate, int *channels, int passthrough)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (1) { // close+open for pcm / ac3
|
||||
if (1) { // close+open for pcm / AC-3
|
||||
int fildes;
|
||||
|
||||
fildes = OssPcmFildes;
|
||||
@ -1932,7 +1970,7 @@ static void NoopSetVolume( __attribute__ ((unused))
|
||||
**
|
||||
** @param freq sample frequency
|
||||
** @param channels number of channels
|
||||
** @param passthrough use pass-through (AC3, ...) device
|
||||
** @param passthrough use pass-through (AC-3, ...) device
|
||||
*/
|
||||
static int NoopSetup( __attribute__ ((unused))
|
||||
int *channels, __attribute__ ((unused))
|
||||
@ -2021,6 +2059,12 @@ static void *AudioPlayHandlerThread(void *dummy)
|
||||
{
|
||||
Debug(3, "audio: play thread started\n");
|
||||
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");
|
||||
pthread_mutex_lock(&AudioMutex);
|
||||
AudioRunning = 0;
|
||||
@ -2031,35 +2075,42 @@ static void *AudioPlayHandlerThread(void *dummy)
|
||||
pthread_mutex_unlock(&AudioMutex);
|
||||
|
||||
Debug(3, "audio: ----> %dms start\n", (AudioUsedBytes() * 1000)
|
||||
/ (!AudioRing[AudioRingRead].HwSampleRate +
|
||||
!AudioRing[AudioRingRead].HwChannels +
|
||||
AudioRing[AudioRingRead].HwSampleRate *
|
||||
AudioRing[AudioRingRead].HwChannels * AudioBytesProSample));
|
||||
/ (!AudioRing[AudioRingWrite].HwSampleRate +
|
||||
!AudioRing[AudioRingWrite].HwChannels +
|
||||
AudioRing[AudioRingWrite].HwSampleRate *
|
||||
AudioRing[AudioRingWrite].HwChannels * AudioBytesProSample));
|
||||
|
||||
do {
|
||||
int filled;
|
||||
int read;
|
||||
int flush;
|
||||
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
|
||||
flush = 0;
|
||||
filled = atomic_read(&AudioRingFilled);
|
||||
read = AudioRingRead;
|
||||
while (filled--) {
|
||||
i = filled;
|
||||
while (i--) {
|
||||
read = (read + 1) % AUDIO_RING_MAX;
|
||||
if (AudioRing[read].FlushBuffers) {
|
||||
AudioRing[read].FlushBuffers = 0;
|
||||
AudioRingRead = read;
|
||||
atomic_set(&AudioRingFilled, filled);
|
||||
// handle all flush in queue
|
||||
flush = 1;
|
||||
flush = filled - i;
|
||||
}
|
||||
}
|
||||
|
||||
if (flush) {
|
||||
Debug(3, "audio: flush\n");
|
||||
Debug(3, "audio: flush %d ring buffer(s)\n", flush);
|
||||
AudioUsedModule->FlushBuffers();
|
||||
atomic_sub(flush, &AudioRingFilled);
|
||||
if (AudioNextRing()) {
|
||||
Debug(3, "audio: break after flush\n");
|
||||
break;
|
||||
@ -2067,7 +2118,10 @@ static void *AudioPlayHandlerThread(void *dummy)
|
||||
Debug(3, "audio: continue after flush\n");
|
||||
}
|
||||
// try to play some samples
|
||||
err = AudioUsedModule->Thread();
|
||||
err = 0;
|
||||
if (RingBufferUsedBytes(AudioRing[AudioRingRead].RingBuffer)) {
|
||||
err = AudioUsedModule->Thread();
|
||||
}
|
||||
// underrun, check if new ring buffer is available
|
||||
if (!err) {
|
||||
int passthrough;
|
||||
@ -2122,6 +2176,7 @@ static void *AudioPlayHandlerThread(void *dummy)
|
||||
*/
|
||||
static void AudioInitThread(void)
|
||||
{
|
||||
AudioThreadStop = 0;
|
||||
pthread_mutex_init(&AudioMutex, NULL);
|
||||
pthread_cond_init(&AudioStartCond, NULL);
|
||||
pthread_create(&AudioThread, NULL, AudioPlayHandlerThread, NULL);
|
||||
@ -2135,10 +2190,12 @@ static void AudioExitThread(void)
|
||||
{
|
||||
void *retval;
|
||||
|
||||
Debug(3, "audio: %s\n", __FUNCTION__);
|
||||
|
||||
if (AudioThread) {
|
||||
if (pthread_cancel(AudioThread)) {
|
||||
Error(_("audio: can't queue cancel play thread\n"));
|
||||
}
|
||||
AudioThreadStop = 1;
|
||||
AudioRunning = 1; // wakeup thread, if needed
|
||||
pthread_cond_signal(&AudioStartCond);
|
||||
if (pthread_join(AudioThread, &retval) || retval != PTHREAD_CANCELED) {
|
||||
Error(_("audio: can't cancel play thread\n"));
|
||||
}
|
||||
@ -2416,6 +2473,22 @@ void AudioFlushBuffers(void)
|
||||
int old;
|
||||
int i;
|
||||
|
||||
if (atomic_read(&AudioRingFilled) >= AUDIO_RING_MAX) {
|
||||
// wait for space in ring buffer, should never happen
|
||||
for (i = 0; i < 24 * 2; ++i) {
|
||||
if (atomic_read(&AudioRingFilled) < AUDIO_RING_MAX) {
|
||||
break;
|
||||
}
|
||||
Debug(3, "audio: flush out of ring buffers\n");
|
||||
usleep(1 * 1000); // avoid hot polling
|
||||
}
|
||||
if (atomic_read(&AudioRingFilled) >= AUDIO_RING_MAX) {
|
||||
// FIXME: We can set the flush flag in the last wrote ring buffer
|
||||
Error(_("audio: flush out of ring buffers\n"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
old = AudioRingWrite;
|
||||
AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
|
||||
AudioRing[AudioRingWrite].FlushBuffers = 1;
|
||||
@ -2433,12 +2506,13 @@ void AudioFlushBuffers(void)
|
||||
|
||||
atomic_inc(&AudioRingFilled);
|
||||
|
||||
// FIXME: wait for flush complete?
|
||||
// FIXME: wait for flush complete needed?
|
||||
for (i = 0; i < 24 * 2; ++i) {
|
||||
if (!AudioRunning) { // wakeup thread to flush buffers
|
||||
AudioRunning = 1;
|
||||
pthread_cond_signal(&AudioStartCond);
|
||||
}
|
||||
// FIXME: waiting on zero isn't correct, but currently works
|
||||
if (!atomic_read(&AudioRingFilled)) {
|
||||
break;
|
||||
}
|
||||
@ -2570,7 +2644,7 @@ void AudioSetVolume(int volume)
|
||||
**
|
||||
** @param freq sample frequency
|
||||
** @param channels number of channels
|
||||
** @param passthrough use pass-through (AC3, ...) device
|
||||
** @param passthrough use pass-through (AC-3, ...) device
|
||||
**
|
||||
** @retval 0 everything ok
|
||||
** @retval 1 didn't support frequency/channels combination
|
||||
@ -2750,6 +2824,20 @@ void AudioSetChannel(const char *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.
|
||||
**
|
||||
@ -2929,6 +3017,8 @@ void AudioExit(void)
|
||||
{
|
||||
const AudioModule *module;
|
||||
|
||||
Debug(3, "audio: %s\n", __FUNCTION__);
|
||||
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
if (AudioUsedModule->Thread) { // supports threads
|
||||
AudioExitThread();
|
||||
|
5
audio.h
5
audio.h
@ -1,7 +1,7 @@
|
||||
///
|
||||
/// @file audio.h @brief Audio module headerfile
|
||||
///
|
||||
/// Copyright (c) 2009 - 2013 by Johns. All Rights Reserved.
|
||||
/// Copyright (c) 2009 - 2014 by Johns. All Rights Reserved.
|
||||
///
|
||||
/// Contributor(s):
|
||||
///
|
||||
@ -52,6 +52,7 @@ extern void AudioSetDevice(const char *); ///< set PCM audio device
|
||||
/// set pass-through device
|
||||
extern void AudioSetPassthroughDevice(const char *);
|
||||
extern void AudioSetChannel(const char *); ///< set mixer channel
|
||||
extern void AudioSetAutoAES(int); ///< set automatic AES flag handling
|
||||
extern void AudioInit(void); ///< setup audio module
|
||||
extern void AudioExit(void); ///< cleanup and exit audio module
|
||||
|
||||
@ -60,5 +61,7 @@ extern void AudioExit(void); ///< cleanup and exit audio module
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
extern char AudioAlsaDriverBroken; ///< disable broken driver message
|
||||
extern char AudioAlsaNoCloseOpen; ///< disable alsa close/open fix
|
||||
extern char AudioAlsaCloseOpenDelay; ///< enable alsa close/open delay fix
|
||||
|
||||
/// @}
|
||||
|
307
codec.c
307
codec.c
@ -1,7 +1,7 @@
|
||||
///
|
||||
/// @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):
|
||||
///
|
||||
@ -38,8 +38,12 @@
|
||||
#define USE_AC3_DRIFT_CORRECTION
|
||||
/// use ffmpeg libswresample API (autodected, Makefile)
|
||||
#define noUSE_SWRESAMPLE
|
||||
/// use libav libavresample API (autodected, Makefile)
|
||||
#define noUSE_AVRESAMPLE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/endian.h>
|
||||
@ -54,8 +58,16 @@
|
||||
#define _(str) gettext(str) ///< gettext shortcut
|
||||
#define _N(str) str ///< gettext_noop shortcut
|
||||
|
||||
#include <alsa/iatomic.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/mem.h>
|
||||
// support old ffmpeg versions <1.0
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,18,102)
|
||||
#define AVCodecID CodecID
|
||||
#define AV_CODEC_ID_AC3 CODEC_ID_AC3
|
||||
#define AV_CODEC_ID_EAC3 CODEC_ID_EAC3
|
||||
#define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO
|
||||
#define AV_CODEC_ID_H264 CODEC_ID_H264
|
||||
#endif
|
||||
#include <libavcodec/vaapi.h>
|
||||
#ifdef USE_VDPAU
|
||||
#include <libavcodec/vdpau.h>
|
||||
@ -63,6 +75,10 @@
|
||||
#ifdef USE_SWRESAMPLE
|
||||
#include <libswresample/swresample.h>
|
||||
#endif
|
||||
#ifdef USE_AVRESAMPLE
|
||||
#include <libavresample/avresample.h>
|
||||
#include <libavutil/opt.h>
|
||||
#endif
|
||||
|
||||
#ifndef __USE_GNU
|
||||
#define __USE_GNU
|
||||
@ -72,11 +88,22 @@
|
||||
#ifdef MAIN_H
|
||||
#include MAIN_H
|
||||
#endif
|
||||
#include "iatomic.h"
|
||||
#include "misc.h"
|
||||
#include "video.h"
|
||||
#include "audio.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
|
||||
//----------------------------------------------------------------------------
|
||||
@ -89,6 +116,9 @@
|
||||
///
|
||||
static pthread_mutex_t CodecLockMutex;
|
||||
|
||||
/// Flag prefer fast channel switch
|
||||
char CodecUsePossibleDefectFrames;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Video
|
||||
//----------------------------------------------------------------------------
|
||||
@ -110,6 +140,9 @@ struct _video_decoder_
|
||||
int GetFormatDone; ///< flag get format called!
|
||||
AVCodec *VideoCodec; ///< video codec
|
||||
AVCodecContext *VideoCtx; ///< video codec context
|
||||
#ifdef FFMPEG_WORKAROUND_ARTIFACTS
|
||||
int FirstKeyFrame; ///< flag first frame
|
||||
#endif
|
||||
AVFrame *Frame; ///< decoded video frame
|
||||
};
|
||||
|
||||
@ -194,7 +227,9 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
|
||||
|
||||
//Debug(3, "codec: use surface %#010x\n", surface);
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,48,101)
|
||||
frame->type = FF_BUFFER_TYPE_USER;
|
||||
#endif
|
||||
#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,46,0)
|
||||
frame->age = 256 * 256 * 256 * 64;
|
||||
#endif
|
||||
@ -204,12 +239,14 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
|
||||
frame->data[2] = NULL;
|
||||
frame->data[3] = NULL;
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,66,100)
|
||||
// reordered frames
|
||||
if (video_ctx->pkt) {
|
||||
frame->pkt_pts = video_ctx->pkt->pts;
|
||||
} else {
|
||||
frame->pkt_pts = AV_NOPTS_VALUE;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@ -221,7 +258,9 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
|
||||
|
||||
//Debug(3, "codec: use surface %#010x\n", surface);
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,48,101)
|
||||
frame->type = FF_BUFFER_TYPE_USER;
|
||||
#endif
|
||||
#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,46,0)
|
||||
frame->age = 256 * 256 * 256 * 64;
|
||||
#endif
|
||||
@ -229,12 +268,14 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
|
||||
frame->data[0] = (void *)(size_t) surface;
|
||||
frame->data[3] = (void *)(size_t) surface;
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,66,100)
|
||||
// reordered frames
|
||||
if (video_ctx->pkt) {
|
||||
frame->pkt_pts = video_ctx->pkt->pts;
|
||||
} else {
|
||||
frame->pkt_pts = AV_NOPTS_VALUE;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
//Debug(3, "codec: fallback to default get_buffer\n");
|
||||
@ -379,22 +420,39 @@ void CodecVideoDelDecoder(VideoDecoder * decoder)
|
||||
** Open video decoder.
|
||||
**
|
||||
** @param decoder private video decoder
|
||||
** @param name video codec name
|
||||
** @param codec_id video codec id, used if name == NULL
|
||||
** @param codec_id video codec id
|
||||
*/
|
||||
void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
|
||||
void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
|
||||
{
|
||||
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) {
|
||||
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))) {
|
||||
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);
|
||||
// FIXME: none fatal
|
||||
}
|
||||
@ -433,8 +491,8 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
|
||||
|
||||
decoder->VideoCtx->opaque = decoder; // our structure
|
||||
|
||||
Debug(3, "codec: video '%s'\n", decoder->VideoCtx->codec_name);
|
||||
if (codec_id == CODEC_ID_H264) {
|
||||
Debug(3, "codec: video '%s'\n", decoder->VideoCodec->long_name);
|
||||
if (codec_id == AV_CODEC_ID_H264) {
|
||||
// 2.53 Ghz CPU is too slow for this codec at 1080i
|
||||
//decoder->VideoCtx->skip_loop_filter = AVDISCARD_ALL;
|
||||
//decoder->VideoCtx->skip_loop_filter = AVDISCARD_BIDIR;
|
||||
@ -476,7 +534,7 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
|
||||
} else {
|
||||
decoder->VideoCtx->get_format = Codec_get_format;
|
||||
decoder->VideoCtx->hwaccel_context =
|
||||
VideoGetVaapiContext(decoder->HwDecoder);
|
||||
VideoGetHwAccelContext(decoder->HwDecoder);
|
||||
}
|
||||
|
||||
// our pixel format video hardware decoder hook
|
||||
@ -496,11 +554,20 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
|
||||
//
|
||||
// Prepare frame buffer for decoder
|
||||
//
|
||||
if (!(decoder->Frame = avcodec_alloc_frame())) {
|
||||
Fatal(_("codec: can't allocate decoder frame\n"));
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,28,1)
|
||||
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
|
||||
decoder->GetFormatDone = 0;
|
||||
#ifdef FFMPEG_WORKAROUND_ARTIFACTS
|
||||
decoder->FirstKeyFrame = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -511,12 +578,17 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
|
||||
void CodecVideoClose(VideoDecoder * video_decoder)
|
||||
{
|
||||
// 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);
|
||||
#endif
|
||||
|
||||
if (video_decoder->VideoCtx) {
|
||||
pthread_mutex_lock(&CodecLockMutex);
|
||||
avcodec_close(video_decoder->VideoCtx);
|
||||
pthread_mutex_unlock(&CodecLockMutex);
|
||||
av_freep(&video_decoder->VideoCtx);
|
||||
pthread_mutex_unlock(&CodecLockMutex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -587,8 +659,22 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
|
||||
}
|
||||
|
||||
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);
|
||||
VideoRenderFrame(decoder->HwDecoder, video_ctx, frame);
|
||||
}
|
||||
#else
|
||||
//DisplayPts(video_ctx, frame);
|
||||
VideoRenderFrame(decoder->HwDecoder, video_ctx, frame);
|
||||
#endif
|
||||
} else {
|
||||
// some frames are needed for references, interlaced frames ...
|
||||
// could happen with h264 dvb streams, just drop data.
|
||||
@ -617,6 +703,11 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// new AVFrame API
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,28,1)
|
||||
av_frame_unref(frame);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -657,15 +748,22 @@ struct _audio_decoder_
|
||||
int HwSampleRate; ///< hw sample rate
|
||||
int HwChannels; ///< hw channels
|
||||
|
||||
#ifndef USE_SWRESAMPLE
|
||||
ReSampleContext *ReSample; ///< audio resampling context
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,28,1)
|
||||
AVFrame *Frame; ///< decoded audio frame buffer
|
||||
#endif
|
||||
|
||||
#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
|
||||
ReSampleContext *ReSample; ///< old resampling context
|
||||
#endif
|
||||
#ifdef USE_SWRESAMPLE
|
||||
#if LIBSWRESAMPLE_VERSION_INT < AV_VERSION_INT(0, 15, 100)
|
||||
struct SwrContext *Resample; ///< audio software resample context
|
||||
struct SwrContext *Resample; ///< ffmpeg software resample context
|
||||
#else
|
||||
SwrContext *Resample; ///< audio software resample context
|
||||
SwrContext *Resample; ///< ffmpeg software resample context
|
||||
#endif
|
||||
#endif
|
||||
#ifdef USE_AVRESAMPLE
|
||||
AVAudioResampleContext *Resample; ///< libav software resample context
|
||||
#endif
|
||||
|
||||
uint16_t Spdif[24576 / 2]; ///< SPDIF output buffer
|
||||
@ -680,7 +778,7 @@ struct _audio_decoder_
|
||||
int DriftCorr; ///< audio drift correction value
|
||||
int DriftFrac; ///< audio drift fraction for ac3
|
||||
|
||||
#ifndef USE_SWRESAMPLE
|
||||
#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
|
||||
struct AVResampleContext *AvResample; ///< second audio resample context
|
||||
#define MAX_CHANNELS 8 ///< max number of channels supported
|
||||
int16_t *Buffer[MAX_CHANNELS]; ///< deinterleave sample buffers
|
||||
@ -703,7 +801,7 @@ enum IEC61937
|
||||
|
||||
#ifdef USE_AUDIO_DRIFT_CORRECTION
|
||||
#define CORRECT_PCM 1 ///< do PCM audio-drift correction
|
||||
#define CORRECT_AC3 2 ///< do AC3 audio-drift correction
|
||||
#define CORRECT_AC3 2 ///< do AC-3 audio-drift correction
|
||||
static char CodecAudioDrift; ///< flag: enable audio-drift correction
|
||||
#else
|
||||
static const int CodecAudioDrift = 0;
|
||||
@ -730,6 +828,11 @@ AudioDecoder *CodecAudioNewDecoder(void)
|
||||
if (!(audio_decoder = calloc(1, sizeof(*audio_decoder)))) {
|
||||
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;
|
||||
}
|
||||
@ -741,6 +844,9 @@ AudioDecoder *CodecAudioNewDecoder(void)
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@ -748,19 +854,16 @@ void CodecAudioDelDecoder(AudioDecoder * decoder)
|
||||
** Open audio decoder.
|
||||
**
|
||||
** @param audio_decoder private audio decoder
|
||||
** @param name audio codec name
|
||||
** @param codec_id audio codec id, used if name == NULL
|
||||
** @param codec_id audio codec id
|
||||
*/
|
||||
void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
|
||||
int codec_id)
|
||||
void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id)
|
||||
{
|
||||
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))) {
|
||||
Debug(3, "codec: audio decoder '%s' found\n", name);
|
||||
} else if (!(audio_codec = avcodec_find_decoder(codec_id))) {
|
||||
if (!(audio_codec = avcodec_find_decoder(codec_id))) {
|
||||
Fatal(_("codec: codec ID %#06x not found\n"), codec_id);
|
||||
// FIXME: errors aren't fatal
|
||||
}
|
||||
@ -771,14 +874,14 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
|
||||
}
|
||||
|
||||
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;
|
||||
#endif
|
||||
audio_decoder->AudioCtx->request_channel_layout =
|
||||
AV_CH_LAYOUT_STEREO_DOWNMIX;
|
||||
}
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,61,100)
|
||||
// this has no effect
|
||||
// this has no effect (with ffmpeg and libav)
|
||||
// audio_decoder->AudioCtx->request_sample_fmt = AV_SAMPLE_FMT_S16;
|
||||
#endif
|
||||
pthread_mutex_lock(&CodecLockMutex);
|
||||
@ -805,7 +908,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
|
||||
}
|
||||
#endif
|
||||
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) {
|
||||
Debug(3, "codec: audio can use truncated packets\n");
|
||||
@ -827,7 +930,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
|
||||
void CodecAudioClose(AudioDecoder * audio_decoder)
|
||||
{
|
||||
// FIXME: output any buffered data
|
||||
#ifndef USE_SWRESAMPLE
|
||||
#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
|
||||
if (audio_decoder->AvResample) {
|
||||
int ch;
|
||||
|
||||
@ -852,19 +955,24 @@ void CodecAudioClose(AudioDecoder * audio_decoder)
|
||||
if (audio_decoder->Resample) {
|
||||
swr_free(&audio_decoder->Resample);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_AVRESAMPLE
|
||||
if (audio_decoder->Resample) {
|
||||
avresample_free(&audio_decoder->Resample);
|
||||
}
|
||||
#endif
|
||||
if (audio_decoder->AudioCtx) {
|
||||
pthread_mutex_lock(&CodecLockMutex);
|
||||
avcodec_close(audio_decoder->AudioCtx);
|
||||
pthread_mutex_unlock(&CodecLockMutex);
|
||||
av_freep(&audio_decoder->AudioCtx);
|
||||
pthread_mutex_unlock(&CodecLockMutex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Set audio drift correction.
|
||||
**
|
||||
** @param mask enable mask (PCM, AC3)
|
||||
** @param mask enable mask (PCM, AC-3)
|
||||
*/
|
||||
void CodecSetAudioDrift(int mask)
|
||||
{
|
||||
@ -877,7 +985,7 @@ void CodecSetAudioDrift(int mask)
|
||||
/**
|
||||
** Set audio pass-through.
|
||||
**
|
||||
** @param mask enable mask (PCM, AC3, EAC3)
|
||||
** @param mask enable mask (PCM, AC-3, E-AC-3)
|
||||
*/
|
||||
void CodecSetAudioPassthrough(int mask)
|
||||
{
|
||||
@ -978,8 +1086,8 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder,
|
||||
av_get_sample_fmt_name(audio_ctx->sample_fmt), audio_ctx->sample_rate,
|
||||
audio_ctx->channels, CodecPassthrough & CodecPCM ? " PCM" : "",
|
||||
CodecPassthrough & CodecMPA ? " MPA" : "",
|
||||
CodecPassthrough & CodecAC3 ? " AC3" : "",
|
||||
CodecPassthrough & CodecEAC3 ? " EAC3" : "",
|
||||
CodecPassthrough & CodecAC3 ? " AC-3" : "",
|
||||
CodecPassthrough & CodecEAC3 ? " E-AC-3" : "",
|
||||
CodecPassthrough ? " pass-through" : "");
|
||||
|
||||
*passthrough = 0;
|
||||
@ -990,11 +1098,11 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder,
|
||||
audio_decoder->Passthrough = CodecPassthrough;
|
||||
|
||||
// SPDIF/HDMI pass-through
|
||||
if ((CodecPassthrough & CodecAC3 && audio_ctx->codec_id == CODEC_ID_AC3)
|
||||
if ((CodecPassthrough & CodecAC3 && audio_ctx->codec_id == AV_CODEC_ID_AC3)
|
||||
|| (CodecPassthrough & CodecEAC3
|
||||
&& audio_ctx->codec_id == CODEC_ID_EAC3)) {
|
||||
if (audio_ctx->codec_id == CODEC_ID_EAC3) {
|
||||
// EAC3 over HDMI some receivers need HBR
|
||||
&& audio_ctx->codec_id == AV_CODEC_ID_EAC3)) {
|
||||
if (audio_ctx->codec_id == AV_CODEC_ID_EAC3) {
|
||||
// E-AC-3 over HDMI some receivers need HBR
|
||||
audio_decoder->HwSampleRate *= 4;
|
||||
}
|
||||
audio_decoder->HwChannels = 2;
|
||||
@ -1007,9 +1115,9 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder,
|
||||
AudioSetup(&audio_decoder->HwSampleRate,
|
||||
&audio_decoder->HwChannels, *passthrough))) {
|
||||
|
||||
// try EAC3 none HBR
|
||||
// try E-AC-3 none HBR
|
||||
audio_decoder->HwSampleRate /= 4;
|
||||
if (audio_ctx->codec_id != CODEC_ID_EAC3
|
||||
if (audio_ctx->codec_id != AV_CODEC_ID_EAC3
|
||||
|| (err =
|
||||
AudioSetup(&audio_decoder->HwSampleRate,
|
||||
&audio_decoder->HwChannels, *passthrough))) {
|
||||
@ -1044,7 +1152,7 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder,
|
||||
|
||||
audio_ctx = audio_decoder->AudioCtx;
|
||||
// SPDIF/HDMI passthrough
|
||||
if (CodecPassthrough & CodecAC3 && audio_ctx->codec_id == CODEC_ID_AC3) {
|
||||
if (CodecPassthrough & CodecAC3 && audio_ctx->codec_id == AV_CODEC_ID_AC3) {
|
||||
uint16_t *spdif;
|
||||
int spdif_sz;
|
||||
|
||||
@ -1094,7 +1202,8 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder,
|
||||
AudioEnqueue(spdif, spdif_sz);
|
||||
return 1;
|
||||
}
|
||||
if (CodecPassthrough & CodecEAC3 && audio_ctx->codec_id == CODEC_ID_EAC3) {
|
||||
if (CodecPassthrough & CodecEAC3
|
||||
&& audio_ctx->codec_id == AV_CODEC_ID_EAC3) {
|
||||
uint16_t *spdif;
|
||||
int spdif_sz;
|
||||
int repeat;
|
||||
@ -1147,7 +1256,7 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef USE_SWRESAMPLE
|
||||
#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
|
||||
|
||||
/**
|
||||
** Set/update audio pts clock.
|
||||
@ -1223,9 +1332,9 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
|
||||
corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
|
||||
// SPDIF/HDMI passthrough
|
||||
if ((CodecAudioDrift & CORRECT_AC3) && (!(CodecPassthrough & CodecAC3)
|
||||
|| audio_decoder->AudioCtx->codec_id != CODEC_ID_AC3)
|
||||
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_AC3)
|
||||
&& (!(CodecPassthrough & CodecEAC3)
|
||||
|| audio_decoder->AudioCtx->codec_id != CODEC_ID_EAC3)) {
|
||||
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_EAC3)) {
|
||||
audio_decoder->DriftCorr = -corr;
|
||||
}
|
||||
|
||||
@ -1549,7 +1658,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_SWRESAMPLE
|
||||
#if defined(USE_SWRESAMPLE) || defined(USE_AVRESAMPLE)
|
||||
|
||||
/**
|
||||
** Set/update audio pts clock.
|
||||
@ -1559,6 +1668,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
||||
*/
|
||||
static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
|
||||
{
|
||||
#ifdef USE_AUDIO_DRIFT_CORRECTION
|
||||
struct timespec nowtime;
|
||||
int64_t delay;
|
||||
int64_t tim_diff;
|
||||
@ -1625,9 +1735,9 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
|
||||
corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
|
||||
// SPDIF/HDMI passthrough
|
||||
if ((CodecAudioDrift & CORRECT_AC3) && (!(CodecPassthrough & CodecAC3)
|
||||
|| audio_decoder->AudioCtx->codec_id != CODEC_ID_AC3)
|
||||
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_AC3)
|
||||
&& (!(CodecPassthrough & CodecEAC3)
|
||||
|| audio_decoder->AudioCtx->codec_id != CODEC_ID_EAC3)) {
|
||||
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_EAC3)) {
|
||||
audio_decoder->DriftCorr = -corr;
|
||||
}
|
||||
|
||||
@ -1638,6 +1748,7 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_SWRESAMPLE
|
||||
if (audio_decoder->Resample && audio_decoder->DriftCorr) {
|
||||
int distance;
|
||||
|
||||
@ -1652,6 +1763,18 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
|
||||
Debug(3, "codec/audio: swr_set_compensation failed\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_AVRESAMPLE
|
||||
if (audio_decoder->Resample && audio_decoder->DriftCorr) {
|
||||
int distance;
|
||||
|
||||
distance = (pts_diff * audio_decoder->HwSampleRate) / (900 * 1000);
|
||||
if (avresample_set_compensation(audio_decoder->Resample,
|
||||
audio_decoder->DriftCorr / 10, distance)) {
|
||||
Debug(3, "codec/audio: swr_set_compensation failed\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (1) {
|
||||
static int c;
|
||||
|
||||
@ -1660,6 +1783,9 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
|
||||
audio_decoder->DriftCorr, drift * 1000 / 90, corr);
|
||||
}
|
||||
}
|
||||
#else
|
||||
AudioSetClock(pts);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1691,6 +1817,7 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SWRESAMPLE
|
||||
audio_decoder->Resample =
|
||||
swr_alloc_set_opts(audio_decoder->Resample, audio_ctx->channel_layout,
|
||||
AV_SAMPLE_FMT_S16, audio_decoder->HwSampleRate,
|
||||
@ -1701,6 +1828,33 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
|
||||
} else {
|
||||
Error(_("codec/audio: can't setup resample\n"));
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_AVRESAMPLE
|
||||
if (!(audio_decoder->Resample = avresample_alloc_context())) {
|
||||
Error(_("codec/audio: can't setup resample\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
av_opt_set_int(audio_decoder->Resample, "in_channel_layout",
|
||||
audio_ctx->channel_layout, 0);
|
||||
av_opt_set_int(audio_decoder->Resample, "in_sample_fmt",
|
||||
audio_ctx->sample_fmt, 0);
|
||||
av_opt_set_int(audio_decoder->Resample, "in_sample_rate",
|
||||
audio_ctx->sample_rate, 0);
|
||||
av_opt_set_int(audio_decoder->Resample, "out_channel_layout",
|
||||
audio_ctx->channel_layout, 0);
|
||||
av_opt_set_int(audio_decoder->Resample, "out_sample_fmt",
|
||||
AV_SAMPLE_FMT_S16, 0);
|
||||
av_opt_set_int(audio_decoder->Resample, "out_sample_rate",
|
||||
audio_decoder->HwSampleRate, 0);
|
||||
|
||||
if (avresample_open(audio_decoder->Resample)) {
|
||||
avresample_free(&audio_decoder->Resample);
|
||||
audio_decoder->Resample = NULL;
|
||||
Error(_("codec/audio: can't open resample\n"));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1716,16 +1870,31 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
|
||||
void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
||||
{
|
||||
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 n;
|
||||
|
||||
audio_ctx = audio_decoder->AudioCtx;
|
||||
|
||||
// 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);
|
||||
|
||||
if (n != avpkt->size) {
|
||||
if (n == AVERROR(EAGAIN)) {
|
||||
Error(_("codec/audio: latm\n"));
|
||||
@ -1767,7 +1936,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
||||
|
||||
data_sz =
|
||||
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",
|
||||
av_get_sample_fmt_name(audio_ctx->sample_fmt));
|
||||
av_get_channel_layout_string(strbuf, 32, audio_ctx->channels,
|
||||
@ -1775,9 +1944,9 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
||||
fprintf(stderr, "codec/audio: layout %s\n", strbuf);
|
||||
fprintf(stderr,
|
||||
"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) {
|
||||
uint8_t outbuf[8192 * 2 * 8];
|
||||
uint8_t *out[1];
|
||||
@ -1785,7 +1954,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
||||
out[0] = outbuf;
|
||||
n = swr_convert(audio_decoder->Resample, out,
|
||||
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 (!(audio_decoder->Passthrough & CodecPCM)) {
|
||||
CodecReorderAudioFrame((int16_t *) outbuf,
|
||||
@ -1796,6 +1965,30 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_AVRESAMPLE
|
||||
if (audio_decoder->Resample) {
|
||||
uint8_t outbuf[8192 * 2 * 8];
|
||||
uint8_t *out[1];
|
||||
|
||||
out[0] = outbuf;
|
||||
n = avresample_convert(audio_decoder->Resample, out, 0,
|
||||
sizeof(outbuf) / (2 * audio_decoder->HwChannels),
|
||||
(uint8_t **) frame->extended_data, 0, frame->nb_samples);
|
||||
// FIXME: set out_linesize, in_linesize correct
|
||||
if (n > 0) {
|
||||
if (!(audio_decoder->Passthrough & CodecPCM)) {
|
||||
CodecReorderAudioFrame((int16_t *) outbuf,
|
||||
n * 2 * audio_decoder->HwChannels,
|
||||
audio_decoder->HwChannels);
|
||||
}
|
||||
AudioEnqueue(outbuf, n * 2 * audio_decoder->HwChannels);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
// should be never reached
|
||||
fprintf(stderr, "oops\n");
|
||||
|
15
codec.h
15
codec.h
@ -1,7 +1,7 @@
|
||||
///
|
||||
/// @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):
|
||||
///
|
||||
@ -30,7 +30,7 @@
|
||||
#define CodecPCM 0x01 ///< PCM bit mask
|
||||
#define CodecMPA 0x02 ///< MPA bit mask (planned)
|
||||
#define CodecAC3 0x04 ///< AC-3 bit mask
|
||||
#define CodecEAC3 0x08 ///< EAC-3 bit mask
|
||||
#define CodecEAC3 0x08 ///< E-AC-3 bit mask
|
||||
#define CodecDTS 0x10 ///< DTS bit mask (planned)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@ -43,6 +43,13 @@ typedef struct _video_decoder_ VideoDecoder;
|
||||
/// Audio decoder typedef.
|
||||
typedef struct _audio_decoder_ AudioDecoder;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Variables
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/// Flag prefer fast xhannel switch
|
||||
extern char CodecUsePossibleDefectFrames;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Prototypes
|
||||
//----------------------------------------------------------------------------
|
||||
@ -54,7 +61,7 @@ extern VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder *);
|
||||
extern void CodecVideoDelDecoder(VideoDecoder *);
|
||||
|
||||
/// Open video codec.
|
||||
extern void CodecVideoOpen(VideoDecoder *, const char *, int);
|
||||
extern void CodecVideoOpen(VideoDecoder *, int);
|
||||
|
||||
/// Close video codec.
|
||||
extern void CodecVideoClose(VideoDecoder *);
|
||||
@ -72,7 +79,7 @@ extern AudioDecoder *CodecAudioNewDecoder(void);
|
||||
extern void CodecAudioDelDecoder(AudioDecoder *);
|
||||
|
||||
/// Open audio codec.
|
||||
extern void CodecAudioOpen(AudioDecoder *, const char *, int);
|
||||
extern void CodecAudioOpen(AudioDecoder *, int);
|
||||
|
||||
/// Close audio codec.
|
||||
extern void CodecAudioClose(AudioDecoder *);
|
||||
|
97
iatomic.h
Normal file
97
iatomic.h
Normal 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
|
||||
|
||||
/// @}
|
95
po/de_DE.po
95
po/de_DE.po
@ -7,10 +7,10 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR \n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2013-03-09 19:20+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"POT-Creation-Date: 2015-10-20 14:39+0200\n"
|
||||
"PO-Revision-Date: blabla\n"
|
||||
"Last-Translator: blabla\n"
|
||||
"Language-Team: blabla\n"
|
||||
"Language: german\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
@ -229,9 +229,6 @@ msgstr ""
|
||||
msgid "audio: can't set channels %d sample-rate %dHz\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "audio: can't queue cancel play thread\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "audio: can't cancel play thread\n"
|
||||
msgstr ""
|
||||
|
||||
@ -239,6 +236,9 @@ msgstr ""
|
||||
msgid "audio: can't place %d samples in ring buffer\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "audio: flush out of ring buffers\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio: '%s' output module used\n"
|
||||
msgstr ""
|
||||
@ -270,12 +270,15 @@ msgstr ""
|
||||
msgid "codec: can't open video codec!\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "codec: can't allocate decoder frame\n"
|
||||
msgid "codec: can't allocate video decoder frame buffer\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "codec: can't allocate audio decoder\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "codec: can't allocate audio decoder frame buffer\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "codec: can't allocate audio codec context\n"
|
||||
msgstr ""
|
||||
|
||||
@ -306,6 +309,9 @@ msgstr ""
|
||||
msgid "codec/audio: can't setup resample\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "codec/audio: can't open resample\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "codec/audio: latm\n"
|
||||
msgstr ""
|
||||
|
||||
@ -384,6 +390,10 @@ msgstr ""
|
||||
msgid "[softhddev] invalid PES video packet\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "[softhddev] %d invalid PES video packet(s)\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "[softhddev] empty video packet\n"
|
||||
msgstr ""
|
||||
|
||||
@ -479,6 +489,9 @@ msgstr "OSD Höhe"
|
||||
msgid "Suspend"
|
||||
msgstr "Unterbrechen"
|
||||
|
||||
msgid "Detach from main menu entry"
|
||||
msgstr "Detach durch Hauptmenüeintrag"
|
||||
|
||||
msgid "Suspend closes video+audio"
|
||||
msgstr "Unterbrechen schließt Video+Audio"
|
||||
|
||||
@ -488,6 +501,9 @@ msgstr "Unterbrechen stoppt X11"
|
||||
msgid "Video"
|
||||
msgstr "Video"
|
||||
|
||||
msgid "Enable Screensaver(DPMS) at black screen"
|
||||
msgstr "Bildschirmschoner(DPMS) bei schwarzen Bild aktivieren"
|
||||
|
||||
msgid "Video background color (RGB)"
|
||||
msgstr "Video Hintergrundfrabe (RGB)"
|
||||
|
||||
@ -506,6 +522,9 @@ msgstr "Sanftanlauf A/V Sync"
|
||||
msgid "Black during channel switch"
|
||||
msgstr "Schwarz während Kanalwechsel"
|
||||
|
||||
msgid "Clear decoder on channel switch"
|
||||
msgstr "Decoder bei Kanalwechsel leeren"
|
||||
|
||||
msgid "Brightness (-1000..1000) (vdpau)"
|
||||
msgstr "Helligkeit (-1000..1000) (vdpau)"
|
||||
|
||||
@ -587,11 +606,11 @@ msgstr ""
|
||||
msgid " AC-3 pass-through"
|
||||
msgstr ""
|
||||
|
||||
msgid " EAC-3 pass-through"
|
||||
msgid " E-AC-3 pass-through"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable (E)AC-3 (decoder) downmix"
|
||||
msgstr ""
|
||||
msgid "Enable (E-)AC-3 (decoder) downmix"
|
||||
msgstr "Aktiviere (E-)AC-3 (decoder) downmix"
|
||||
|
||||
msgid "Volume control"
|
||||
msgstr "Lautstärkesteuerung"
|
||||
@ -620,6 +639,9 @@ msgstr "Reduziere Steropegel (/1000)"
|
||||
msgid "Audio buffer size (ms)"
|
||||
msgstr "Audio Puffergröße (ms)"
|
||||
|
||||
msgid "Enable automatic AES"
|
||||
msgstr "Aktiviere automatiche AES"
|
||||
|
||||
msgid "Picture-In-Picture"
|
||||
msgstr "Bild in Bild (PIP)"
|
||||
|
||||
@ -627,7 +649,7 @@ msgid "Pip X (%)"
|
||||
msgstr "PIP X (%)"
|
||||
|
||||
msgid "Pip Y (%)"
|
||||
msgstr "PIP X (%)"
|
||||
msgstr "PIP Y (%)"
|
||||
|
||||
msgid "Pip Width (%)"
|
||||
msgstr "PIP Breite (%)"
|
||||
@ -672,7 +694,7 @@ msgid "Alternative Video Height (%)"
|
||||
msgstr "Alternative Videohöhe (%)"
|
||||
|
||||
#, c-format
|
||||
msgid "[softhddev]pip: invalid pes packet %d\n"
|
||||
msgid "[softhddev]pip: invalid PES packet %d\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "[softhddev]pip: pes buffer too small\n"
|
||||
@ -684,6 +706,9 @@ msgstr ""
|
||||
msgid "Channel not available!"
|
||||
msgstr "Kanal nicht verfügbar!"
|
||||
|
||||
msgid "Detach SoftHdDevice"
|
||||
msgstr ""
|
||||
|
||||
msgid "Suspend SoftHdDevice"
|
||||
msgstr "Unterbreche SoftHdDevice"
|
||||
|
||||
@ -731,6 +756,12 @@ msgstr ""
|
||||
msgid "audio delay changed to %d"
|
||||
msgstr ""
|
||||
|
||||
msgid "surround downmix enabled"
|
||||
msgstr ""
|
||||
|
||||
msgid "surround downmix disabled"
|
||||
msgstr ""
|
||||
|
||||
msgid "auto-crop disabled and freezed"
|
||||
msgstr ""
|
||||
|
||||
@ -895,6 +926,9 @@ msgstr ""
|
||||
msgid "unsupported"
|
||||
msgstr ""
|
||||
|
||||
msgid "video/glx: glx error\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "video/vaapi: unsupported pixel format %d\n"
|
||||
msgstr ""
|
||||
@ -968,14 +1002,20 @@ msgstr ""
|
||||
msgid "video: output buffer full, dropping frame (%d/%d)\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "video/vaapi: can't create a surface\n"
|
||||
#, c-format
|
||||
msgid "video/vaapi: can't create a surface: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "video/vaapi: vaDeriveImage failed %d\n"
|
||||
msgid "video/vaapi: can't associate subpicture: %s\n"
|
||||
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 ""
|
||||
|
||||
msgid "video/vaapi: can't unmap the image!\n"
|
||||
@ -990,6 +1030,10 @@ msgstr ""
|
||||
msgid "video/vaapi: can't get source image\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "video/vaapi: vaDeriveImage failed %d\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "video/vaapi: can't put image: %d!\n"
|
||||
msgstr ""
|
||||
@ -997,6 +1041,9 @@ msgstr ""
|
||||
msgid "video/vaapi: stream <-> surface size mismatch\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "video/vaapi: can't map the image!\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "video/vaapi: can't put image err:%d!\n"
|
||||
msgstr ""
|
||||
@ -1024,7 +1071,7 @@ msgstr ""
|
||||
msgid "video/vaapi: can't find a supported subpicture format"
|
||||
msgstr ""
|
||||
|
||||
msgid "video/vaapi: vaapi supports unscaled osd\n"
|
||||
msgid "video/vaapi: supports unscaled osd\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "video/vaapi: can't create osd image\n"
|
||||
@ -1265,6 +1312,9 @@ msgstr ""
|
||||
msgid "video/vdpau: can't put video surface bits: %s\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "video: get hwaccel context, not supported\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "video/vdpau: can't render bitmap surface: %s\n"
|
||||
msgstr ""
|
||||
@ -1277,6 +1327,10 @@ msgstr ""
|
||||
msgid "video/vdpau: can't render mixer: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "video/vdpau: can't query status: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "video/vdpau: can't block queue: %s\n"
|
||||
msgstr ""
|
||||
@ -1331,9 +1385,6 @@ msgstr ""
|
||||
msgid "video: repeated pict %d found, but not handled\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "video/vaapi: get vaapi context, without vaapi enabled\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "video/vdpau: decoder rendering failed: %s\n"
|
||||
msgstr ""
|
||||
@ -1355,6 +1406,10 @@ msgstr ""
|
||||
msgid "video: Can't connect to X11 server on '%s'\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "video: Can't initialize X11 thread support on '%s'\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "video: Can't convert XLIB display to XCB connection\n"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
///
|
||||
/// @file ringbuffer.c @brief Ringbuffer module
|
||||
///
|
||||
/// Copyright (c) 2009, 2011 by Johns. All Rights Reserved.
|
||||
/// Copyright (c) 2009, 2011, 2014 by Johns. All Rights Reserved.
|
||||
///
|
||||
/// Contributor(s):
|
||||
///
|
||||
@ -30,8 +30,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <alsa/iatomic.h>
|
||||
|
||||
#include "iatomic.h"
|
||||
#include "ringbuffer.h"
|
||||
|
||||
/// ring buffer structure
|
||||
|
449
softhddev.c
449
softhddev.c
File diff suppressed because it is too large
Load Diff
10
softhddev.h
10
softhddev.h
@ -1,7 +1,7 @@
|
||||
///
|
||||
/// @file softhddev.h @brief software HD device plugin header file.
|
||||
///
|
||||
/// Copyright (c) 2011 - 2013 by Johns. All Rights Reserved.
|
||||
/// Copyright (c) 2011 - 2015 by Johns. All Rights Reserved.
|
||||
///
|
||||
/// Contributor(s):
|
||||
///
|
||||
@ -25,7 +25,8 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
/// C callback feed key press
|
||||
extern void FeedKeyPress(const char *, const char *, int, int);
|
||||
extern void FeedKeyPress(const char *, const char *, int, int,
|
||||
const char *);
|
||||
|
||||
/// C plugin get osd size and ascpect
|
||||
extern void GetOsdSize(int *, int *, double *);
|
||||
@ -33,7 +34,8 @@ extern "C"
|
||||
/// C plugin close osd
|
||||
extern void OsdClose(void);
|
||||
/// 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
|
||||
extern int PlayAudio(const uint8_t *, int, uint8_t);
|
||||
@ -41,6 +43,8 @@ extern "C"
|
||||
extern int PlayTsAudio(const uint8_t *, int);
|
||||
/// C plugin set audio volume
|
||||
extern void SetVolumeDevice(int);
|
||||
/// C plugin reset channel id (restarts audio)
|
||||
extern void ResetChannelId(void);
|
||||
|
||||
/// C plugin play video packet
|
||||
extern int PlayVideo(const uint8_t *, int);
|
||||
|
366
softhddevice.cpp
366
softhddevice.cpp
@ -1,7 +1,7 @@
|
||||
///
|
||||
/// @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):
|
||||
///
|
||||
@ -47,12 +47,19 @@ extern "C"
|
||||
#include "codec.h"
|
||||
}
|
||||
|
||||
#if APIVERSNUM >= 20301
|
||||
#define MURKS ->
|
||||
#else
|
||||
#define MURKS .
|
||||
#define LOCK_CHANNELS_READ do { } while (0)
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// vdr-plugin version number.
|
||||
/// Makefile extracts the version number for generating the file name
|
||||
/// for the distribution archive.
|
||||
static const char *const VERSION = "0.6.0"
|
||||
static const char *const VERSION = "0.6.1rc1"
|
||||
#ifdef GIT_REV
|
||||
"-GIT" GIT_REV
|
||||
#endif
|
||||
@ -79,6 +86,7 @@ static const char *const Resolution[RESOLUTIONS] = {
|
||||
|
||||
static char ConfigMakePrimary; ///< config primary wanted
|
||||
static char ConfigHideMainMenuEntry; ///< config hide main menu entry
|
||||
static char ConfigDetachFromMainMenu; ///< detach from main menu entry instead of suspend
|
||||
static char ConfigSuspendClose; ///< suspend should close devices
|
||||
static char ConfigSuspendX11; ///< suspend should stop x11
|
||||
|
||||
@ -91,6 +99,7 @@ static char ConfigVideoStudioLevels; ///< config use studio levels
|
||||
static char ConfigVideo60HzMode; ///< config use 60Hz display mode
|
||||
static char ConfigVideoSoftStartSync; ///< config use softstart sync
|
||||
static char ConfigVideoBlackPicture; ///< config enable black picture mode
|
||||
char ConfigVideoClearOnSwitch; ///< config enable Clear on channel switch
|
||||
|
||||
static int ConfigVideoBrightness; ///< config video brightness
|
||||
static int ConfigVideoContrast = 1000; ///< config video contrast
|
||||
@ -138,6 +147,7 @@ static char ConfigAudioCompression; ///< config use volume compression
|
||||
static int ConfigAudioMaxCompression; ///< config max volume compression
|
||||
static int ConfigAudioStereoDescent; ///< config reduce stereo loudness
|
||||
int ConfigAudioBufferTime; ///< config size ms of audio buffer
|
||||
static int ConfigAudioAutoAES; ///< config automatic AES handling
|
||||
|
||||
static char *ConfigX11Display; ///< config x11 display
|
||||
static char *ConfigAudioDevice; ///< config audio stereo device
|
||||
@ -162,13 +172,17 @@ static int ConfigPipAltVideoWidth; ///< config pip alt. video width in %
|
||||
static int ConfigPipAltVideoHeight = 50; ///< config pip alt. video height in %
|
||||
#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
|
||||
|
||||
#define SUSPEND_EXTERNAL -1 ///< play external suspend mode
|
||||
#define NOT_SUSPENDED 0 ///< not suspend mode
|
||||
#define SUSPEND_NORMAL 1 ///< normal 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 repeat repeated key flag
|
||||
** @param release released key flag
|
||||
** @param letter x11 character string (system setting locale)
|
||||
*/
|
||||
extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat,
|
||||
int release)
|
||||
int release, const char *letter)
|
||||
{
|
||||
cRemote *remote;
|
||||
cSoftRemote *csoft;
|
||||
@ -236,9 +251,18 @@ extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat,
|
||||
csoft = new cSoftRemote(keymap);
|
||||
}
|
||||
|
||||
//dsyslog("[softhddev]%s %s, %s\n", __FUNCTION__, keymap, key);
|
||||
//dsyslog("[softhddev]%s %s, %s, %s\n", __FUNCTION__, keymap, key, letter);
|
||||
if (key[1]) { // no single character
|
||||
csoft->Put(key, repeat, release);
|
||||
if (!csoft->Put(key, repeat, release) && letter
|
||||
&& !cRemote::IsLearning()) {
|
||||
cCharSetConv conv;
|
||||
unsigned code;
|
||||
|
||||
code = Utf8CharGet(conv.Convert(letter));
|
||||
if (code <= 0xFF) {
|
||||
cRemote::Put(KBDKEY(code)); // feed it for edit mode
|
||||
}
|
||||
}
|
||||
} else if (!csoft->Put(key, repeat, release)) {
|
||||
cRemote::Put(KBDKEY(key[0])); // feed it for edit mode
|
||||
}
|
||||
@ -255,10 +279,12 @@ class cSoftOsd:public cOsd
|
||||
{
|
||||
public:
|
||||
static volatile char Dirty; ///< flag force redraw everything
|
||||
int OsdLevel; ///< current osd level
|
||||
int OsdLevel; ///< current osd level FIXME: remove
|
||||
|
||||
cSoftOsd(int, int, uint); ///< osd constructor
|
||||
virtual ~ cSoftOsd(void); ///< osd destructor
|
||||
/// set the sub-areas to the given areas
|
||||
virtual eOsdError SetAreas(const tArea *, int);
|
||||
virtual void Flush(void); ///< commits all data to the hardware
|
||||
virtual void SetActive(bool); ///< sets OSD to be the active one
|
||||
};
|
||||
@ -284,11 +310,6 @@ void cSoftOsd::SetActive(bool on)
|
||||
}
|
||||
cOsd::SetActive(on);
|
||||
|
||||
// ignore sub-title if menu is open
|
||||
if (OsdLevel >= OSD_LEVEL_SUBTITLES && IsOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (on) {
|
||||
Dirty = 1;
|
||||
// only flush here if there are already bitmaps
|
||||
@ -320,7 +341,6 @@ cSoftOsd::cSoftOsd(int left, int top, uint level)
|
||||
#endif
|
||||
|
||||
OsdLevel = level;
|
||||
SetActive(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -351,6 +371,31 @@ cSoftOsd::~cSoftOsd(void)
|
||||
#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.
|
||||
*/
|
||||
@ -366,10 +411,6 @@ void cSoftOsd::Flush(void)
|
||||
if (!Active()) { // this osd is not active
|
||||
return;
|
||||
}
|
||||
// don't draw sub-title if menu is active
|
||||
if (OsdLevel >= OSD_LEVEL_SUBTITLES && IsOpen()) {
|
||||
return;
|
||||
}
|
||||
#ifdef USE_YAEPG
|
||||
// support yaepghd, video window
|
||||
if (vidWin.bpp) {
|
||||
@ -385,17 +426,6 @@ void cSoftOsd::Flush(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// VDR draws subtitle without clearing the old
|
||||
//
|
||||
if (OsdLevel >= OSD_LEVEL_SUBTITLES) {
|
||||
VideoOsdClear();
|
||||
cSoftOsd::Dirty = 1;
|
||||
#ifdef OSD_DEBUG
|
||||
dsyslog("[softhddev]%s: subtitle clear\n", __FUNCTION__);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!IsTrueColor()) {
|
||||
cBitmap *bitmap;
|
||||
int i;
|
||||
@ -412,6 +442,8 @@ void cSoftOsd::Flush(void)
|
||||
// draw all bitmaps
|
||||
for (i = 0; (bitmap = GetBitmap(i)); ++i) {
|
||||
uint8_t *argb;
|
||||
int xs;
|
||||
int ys;
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
@ -430,22 +462,52 @@ void cSoftOsd::Flush(void)
|
||||
} else if (!bitmap->Dirty(x1, y1, x2, y2)) {
|
||||
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;
|
||||
h = y2 - y1 + 1;
|
||||
// clip to screen
|
||||
if (1) { // just for the case it makes trouble
|
||||
int width;
|
||||
int height;
|
||||
double video_aspect;
|
||||
|
||||
::GetOsdSize(&width, &height, &video_aspect);
|
||||
if (w > width) {
|
||||
w = width;
|
||||
x2 = x1 + width - 1;
|
||||
if (xs < 0) {
|
||||
if (xs + x1 < 0) {
|
||||
x1 -= xs + x1;
|
||||
w += xs + x1;
|
||||
if (w <= 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
xs = 0;
|
||||
}
|
||||
if (h > height) {
|
||||
h = height;
|
||||
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
|
||||
@ -463,40 +525,99 @@ void cSoftOsd::Flush(void)
|
||||
}
|
||||
#ifdef OSD_DEBUG
|
||||
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
|
||||
OsdDrawARGB(Left() + bitmap->X0() + x1, Top() + bitmap->Y0() + y1,
|
||||
w, h, argb);
|
||||
OsdDrawARGB(0, 0, w, h, w * sizeof(uint32_t), argb, xs + x1,
|
||||
ys + y1);
|
||||
|
||||
bitmap->Clean();
|
||||
// FIXME: reuse argb
|
||||
free(argb);
|
||||
}
|
||||
cSoftOsd::Dirty = 0;
|
||||
Dirty = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
LOCK_PIXMAPS;
|
||||
while ((pm = RenderPixmaps())) {
|
||||
while ((pm = (dynamic_cast < cPixmapMemory * >(RenderPixmaps())))) {
|
||||
int xp;
|
||||
int yp;
|
||||
int stride;
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
x = Left() + pm->ViewPort().X();
|
||||
y = Top() + pm->ViewPort().Y();
|
||||
x = pm->ViewPort().X();
|
||||
y = pm->ViewPort().Y();
|
||||
w = pm->ViewPort().Width();
|
||||
h = pm->ViewPort().Height();
|
||||
stride = w * sizeof(tColor);
|
||||
|
||||
// clip to osd
|
||||
xp = 0;
|
||||
if (x < 0) {
|
||||
xp = -x;
|
||||
w -= xp;
|
||||
x = 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 %p\n", __FUNCTION__, w, h, x,
|
||||
y, pm->Data());
|
||||
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(x, y, w, h, pm->Data());
|
||||
OsdDrawARGB(xp, yp, w, h, stride, pm->Data(), x, y);
|
||||
|
||||
#if APIVERSNUM >= 20110
|
||||
DestroyPixmap(pm);
|
||||
#else
|
||||
delete pm;
|
||||
#endif
|
||||
}
|
||||
cSoftOsd::Dirty = 0;
|
||||
Dirty = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -580,6 +701,7 @@ class cMenuSetupSoft:public cMenuSetupPage
|
||||
int General;
|
||||
int MakePrimary;
|
||||
int HideMainMenuEntry;
|
||||
int DetachFromMainMenu;
|
||||
int OsdSize;
|
||||
int OsdWidth;
|
||||
int OsdHeight;
|
||||
@ -595,6 +717,7 @@ class cMenuSetupSoft:public cMenuSetupPage
|
||||
int _60HzMode;
|
||||
int SoftStartSync;
|
||||
int BlackPicture;
|
||||
int ClearOnSwitch;
|
||||
|
||||
int Brightness;
|
||||
int Contrast;
|
||||
@ -630,6 +753,7 @@ class cMenuSetupSoft:public cMenuSetupPage
|
||||
int AudioMaxCompression;
|
||||
int AudioStereoDescent;
|
||||
int AudioBufferTime;
|
||||
int AudioAutoAES;
|
||||
|
||||
#ifdef USE_PIP
|
||||
int Pip;
|
||||
@ -651,6 +775,9 @@ class cMenuSetupSoft:public cMenuSetupPage
|
||||
int PipAltVideoHeight;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SCREENSAVER
|
||||
int EnableDPMSatBlackScreen;
|
||||
#endif
|
||||
/// @}
|
||||
private:
|
||||
inline cOsdItem * CollapsedItem(const char *, int &, const char * = NULL);
|
||||
@ -757,6 +884,8 @@ void cMenuSetupSoft::Create(void)
|
||||
// suspend
|
||||
//
|
||||
Add(SeparatorItem(tr("Suspend")));
|
||||
Add(new cMenuEditBoolItem(tr("Detach from main menu entry"),
|
||||
&DetachFromMainMenu, trVDR("no"), trVDR("yes")));
|
||||
Add(new cMenuEditBoolItem(tr("Suspend closes video+audio"),
|
||||
&SuspendClose, trVDR("no"), trVDR("yes")));
|
||||
Add(new cMenuEditBoolItem(tr("Suspend stops x11"), &SuspendX11,
|
||||
@ -767,6 +896,11 @@ void cMenuSetupSoft::Create(void)
|
||||
//
|
||||
Add(CollapsedItem(tr("Video"), 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"),
|
||||
&Video4to3DisplayFormat, 3, video_display_formats_4_3));
|
||||
Add(new cMenuEditStraItem(trVDR("16:9+other video display format"),
|
||||
@ -785,6 +919,8 @@ void cMenuSetupSoft::Create(void)
|
||||
trVDR("no"), trVDR("yes")));
|
||||
Add(new cMenuEditBoolItem(tr("Black during channel switch"),
|
||||
&BlackPicture, trVDR("no"), trVDR("yes")));
|
||||
Add(new cMenuEditBoolItem(tr("Clear decoder on channel switch"),
|
||||
&ClearOnSwitch, trVDR("no"), trVDR("yes")));
|
||||
|
||||
Add(new cMenuEditIntItem(tr("Brightness (-1000..1000) (vdpau)"),
|
||||
&Brightness, -1000, 1000, tr("min"), tr("max")));
|
||||
@ -854,9 +990,9 @@ void cMenuSetupSoft::Create(void)
|
||||
&AudioPassthroughPCM, trVDR("no"), trVDR("yes")));
|
||||
Add(new cMenuEditBoolItem(tr("\040\040AC-3 pass-through"),
|
||||
&AudioPassthroughAC3, trVDR("no"), trVDR("yes")));
|
||||
Add(new cMenuEditBoolItem(tr("\040\040EAC-3 pass-through"),
|
||||
Add(new cMenuEditBoolItem(tr("\040\040E-AC-3 pass-through"),
|
||||
&AudioPassthroughEAC3, trVDR("no"), trVDR("yes")));
|
||||
Add(new cMenuEditBoolItem(tr("Enable (E)AC-3 (decoder) downmix"),
|
||||
Add(new cMenuEditBoolItem(tr("Enable (E-)AC-3 (decoder) downmix"),
|
||||
&AudioDownmix, trVDR("no"), trVDR("yes")));
|
||||
Add(new cMenuEditBoolItem(tr("Volume control"), &AudioSoftvol,
|
||||
tr("Hardware"), tr("Software")));
|
||||
@ -872,6 +1008,8 @@ void cMenuSetupSoft::Create(void)
|
||||
&AudioStereoDescent, 0, 1000));
|
||||
Add(new cMenuEditIntItem(tr("Audio buffer size (ms)"),
|
||||
&AudioBufferTime, 0, 1000));
|
||||
Add(new cMenuEditBoolItem(tr("Enable automatic AES"), &AudioAutoAES,
|
||||
trVDR("no"), trVDR("yes")));
|
||||
}
|
||||
#ifdef USE_PIP
|
||||
//
|
||||
@ -977,6 +1115,7 @@ cMenuSetupSoft::cMenuSetupSoft(void)
|
||||
General = 0;
|
||||
MakePrimary = ConfigMakePrimary;
|
||||
HideMainMenuEntry = ConfigHideMainMenuEntry;
|
||||
DetachFromMainMenu = ConfigDetachFromMainMenu;
|
||||
//
|
||||
// osd
|
||||
//
|
||||
@ -1010,6 +1149,7 @@ cMenuSetupSoft::cMenuSetupSoft(void)
|
||||
_60HzMode = ConfigVideo60HzMode;
|
||||
SoftStartSync = ConfigVideoSoftStartSync;
|
||||
BlackPicture = ConfigVideoBlackPicture;
|
||||
ClearOnSwitch = ConfigVideoClearOnSwitch;
|
||||
|
||||
Brightness = ConfigVideoBrightness;
|
||||
Contrast = ConfigVideoContrast;
|
||||
@ -1053,6 +1193,7 @@ cMenuSetupSoft::cMenuSetupSoft(void)
|
||||
AudioMaxCompression = ConfigAudioMaxCompression;
|
||||
AudioStereoDescent = ConfigAudioStereoDescent;
|
||||
AudioBufferTime = ConfigAudioBufferTime;
|
||||
AudioAutoAES = ConfigAudioAutoAES;
|
||||
|
||||
#ifdef USE_PIP
|
||||
//
|
||||
@ -1076,6 +1217,11 @@ cMenuSetupSoft::cMenuSetupSoft(void)
|
||||
PipAltVideoWidth = ConfigPipAltVideoWidth;
|
||||
PipAltVideoHeight = ConfigPipAltVideoHeight;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SCREENSAVER
|
||||
EnableDPMSatBlackScreen = ConfigEnableDPMSatBlackScreen;
|
||||
#endif
|
||||
|
||||
Create();
|
||||
}
|
||||
|
||||
@ -1089,6 +1235,8 @@ void cMenuSetupSoft::Store(void)
|
||||
SetupStore("MakePrimary", ConfigMakePrimary = MakePrimary);
|
||||
SetupStore("HideMainMenuEntry", ConfigHideMainMenuEntry =
|
||||
HideMainMenuEntry);
|
||||
SetupStore("DetachFromMainMenu", ConfigDetachFromMainMenu =
|
||||
DetachFromMainMenu);
|
||||
switch (OsdSize) {
|
||||
case 0:
|
||||
OsdWidth = 0;
|
||||
@ -1133,6 +1281,7 @@ void cMenuSetupSoft::Store(void)
|
||||
VideoSetSoftStartSync(ConfigVideoSoftStartSync);
|
||||
SetupStore("BlackPicture", ConfigVideoBlackPicture = BlackPicture);
|
||||
VideoSetBlackPicture(ConfigVideoBlackPicture);
|
||||
SetupStore("ClearOnSwitch", ConfigVideoClearOnSwitch = ClearOnSwitch);
|
||||
|
||||
SetupStore("Brightness", ConfigVideoBrightness = Brightness);
|
||||
VideoSetBrightness(ConfigVideoBrightness);
|
||||
@ -1187,6 +1336,12 @@ void cMenuSetupSoft::Store(void)
|
||||
VideoSetAudioDelay(ConfigVideoAudioDelay);
|
||||
SetupStore("AudioDrift", ConfigAudioDrift = AudioDrift);
|
||||
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)
|
||||
| (AudioPassthroughAC3 ? CodecAC3 : 0)
|
||||
| (AudioPassthroughEAC3 ? CodecEAC3 : 0);
|
||||
@ -1214,6 +1369,8 @@ void cMenuSetupSoft::Store(void)
|
||||
AudioStereoDescent);
|
||||
AudioSetStereoDescent(ConfigAudioStereoDescent);
|
||||
SetupStore("AudioBufferTime", ConfigAudioBufferTime = AudioBufferTime);
|
||||
SetupStore("AudioAutoAES", ConfigAudioAutoAES = AudioAutoAES);
|
||||
AudioSetAutoAES(ConfigAudioAutoAES);
|
||||
|
||||
#ifdef USE_PIP
|
||||
SetupStore("pip.X", ConfigPipX = PipX);
|
||||
@ -1235,6 +1392,12 @@ void cMenuSetupSoft::Store(void)
|
||||
SetupStore("pip.Alt.VideoHeight", ConfigPipAltVideoHeight =
|
||||
PipAltVideoHeight);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SCREENSAVER
|
||||
SetupStore("EnableDPMSatBlackScreen", ConfigEnableDPMSatBlackScreen =
|
||||
EnableDPMSatBlackScreen);
|
||||
SetDPMSatBlackScreen(ConfigEnableDPMSatBlackScreen);
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -1350,7 +1513,11 @@ class cSoftReceiver:public cReceiver
|
||||
{
|
||||
protected:
|
||||
virtual void Activate(bool);
|
||||
#if APIVERSNUM >= 20301
|
||||
virtual void Receive(const uchar *, int);
|
||||
#else
|
||||
virtual void Receive(uchar *, int);
|
||||
#endif
|
||||
public:
|
||||
cSoftReceiver(const cChannel *); ///< receiver constructor
|
||||
virtual ~ cSoftReceiver(); ///< receiver destructor
|
||||
@ -1443,12 +1610,12 @@ static void PipPesParse(const uint8_t * data, int size, int is_start)
|
||||
if (is_start) { // start of pes packet
|
||||
if (pes_index) {
|
||||
if (0) {
|
||||
fprintf(stderr, "pip: pes packet %8d %02x%02x\n", pes_index,
|
||||
fprintf(stderr, "pip: PES packet %8d %02x%02x\n", pes_index,
|
||||
pes_buf[2], pes_buf[3]);
|
||||
}
|
||||
if (pes_buf[0] || pes_buf[1] || pes_buf[2] != 0x01) {
|
||||
// FIXME: first should always fail
|
||||
esyslog(tr("[softhddev]pip: invalid pes packet %d\n"),
|
||||
esyslog(tr("[softhddev]pip: invalid PES packet %d\n"),
|
||||
pes_index);
|
||||
} else {
|
||||
PipPlayVideo(pes_buf, pes_index);
|
||||
@ -1484,7 +1651,11 @@ static void PipPesParse(const uint8_t * data, int size, int is_start)
|
||||
** @param data ts 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)
|
||||
#endif
|
||||
{
|
||||
const uint8_t *p;
|
||||
|
||||
@ -1576,7 +1747,8 @@ static void NewPip(int channel_nr)
|
||||
if (!channel_nr) {
|
||||
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))) {
|
||||
|
||||
DelPip();
|
||||
@ -1622,14 +1794,16 @@ static void PipNextAvailableChannel(int direction)
|
||||
|
||||
DelPip(); // disable PIP to free the device
|
||||
|
||||
LOCK_CHANNELS_READ;
|
||||
while (channel) {
|
||||
bool ndr;
|
||||
cDevice *device;
|
||||
|
||||
channel = direction > 0 ? Channels.Next(channel)
|
||||
: Channels.Prev(channel);
|
||||
channel = direction > 0 ? Channels MURKS Next(channel)
|
||||
: Channels MURKS Prev(channel);
|
||||
if (!channel && Setup.ChannelsWrap) {
|
||||
channel = direction > 0 ? Channels.First() : Channels.Last();
|
||||
channel =
|
||||
direction > 0 ? Channels MURKS First() : Channels MURKS Last();
|
||||
}
|
||||
if (channel && !channel->GroupSep()
|
||||
&& (device = cDevice::GetDevice(channel, 0, false, true))
|
||||
@ -1658,7 +1832,9 @@ static void SwapPipChannels(void)
|
||||
NewPip(0);
|
||||
|
||||
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
|
||||
|
||||
SetHasHotkeys();
|
||||
Add(new cOsdItem(hk(tr("Suspend SoftHdDevice")), osUser1));
|
||||
|
||||
if (ConfigDetachFromMainMenu) {
|
||||
Add(new cOsdItem(hk(tr("Detach SoftHdDevice")), osUser1));
|
||||
} else {
|
||||
Add(new cOsdItem(hk(tr("Suspend SoftHdDevice")), osUser1));
|
||||
}
|
||||
#ifdef USE_PIP
|
||||
if (PipReceiver) {
|
||||
Add(new cOsdItem(hk(tr("PIP toggle on/off: off")), osUser2));
|
||||
@ -1842,6 +2023,17 @@ static void HandleHotkey(int code)
|
||||
cString::sprintf(tr("audio delay changed to %d"),
|
||||
ConfigVideoAudioDelay));
|
||||
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
|
||||
VideoSetFullscreen(0);
|
||||
@ -1916,6 +2108,7 @@ static void HandleHotkey(int code)
|
||||
break;
|
||||
case 108:
|
||||
DelPip();
|
||||
PipChannelNr = 0;
|
||||
break;
|
||||
#endif
|
||||
|
||||
@ -1993,9 +2186,14 @@ eOSState cSoftHdMenu::ProcessKey(eKeys key)
|
||||
if (SuspendMode == NOT_SUSPENDED && !cSoftHdControl::Player) {
|
||||
cControl::Launch(new cSoftHdControl);
|
||||
cControl::Attach();
|
||||
Suspend(ConfigSuspendClose, ConfigSuspendClose,
|
||||
ConfigSuspendX11);
|
||||
SuspendMode = SUSPEND_NORMAL;
|
||||
if (ConfigDetachFromMainMenu) {
|
||||
Suspend(1, 1, 0);
|
||||
SuspendMode = SUSPEND_DETACHED;
|
||||
} else {
|
||||
Suspend(ConfigSuspendClose, ConfigSuspendClose,
|
||||
ConfigSuspendX11);
|
||||
SuspendMode = SUSPEND_NORMAL;
|
||||
}
|
||||
if (ShutdownHandler.GetUserInactiveTime()) {
|
||||
dsyslog("[softhddev]%s: set user inactive\n",
|
||||
__FUNCTION__);
|
||||
@ -2021,6 +2219,7 @@ eOSState cSoftHdMenu::ProcessKey(eKeys key)
|
||||
return osEnd;
|
||||
case osUser8:
|
||||
DelPip();
|
||||
PipChannelNr = 0;
|
||||
return osEnd;
|
||||
#endif
|
||||
default:
|
||||
@ -2043,7 +2242,11 @@ class cSoftHdDevice:public cDevice
|
||||
virtual bool HasDecoder(void) const;
|
||||
virtual bool CanReplay(void) const;
|
||||
virtual bool SetPlayMode(ePlayMode);
|
||||
#if APIVERSNUM >= 20103
|
||||
virtual void TrickSpeed(int, bool);
|
||||
#else
|
||||
virtual void TrickSpeed(int);
|
||||
#endif
|
||||
virtual void Clear(void);
|
||||
virtual void Play(void);
|
||||
virtual void Freeze(void);
|
||||
@ -2190,7 +2393,7 @@ bool cSoftHdDevice::SetPlayMode(ePlayMode play_mode)
|
||||
case pmVideoOnly:
|
||||
break;
|
||||
case pmNone:
|
||||
return true;
|
||||
break;
|
||||
case pmExtern_THIS_SHOULD_BE_AVOIDED:
|
||||
dsyslog("[softhddev] play mode external\n");
|
||||
// FIXME: what if already suspended?
|
||||
@ -2231,13 +2434,23 @@ int64_t cSoftHdDevice::GetSTC(void)
|
||||
** times.
|
||||
**
|
||||
** @param speed trick speed
|
||||
** @param forward flag forward direction
|
||||
*/
|
||||
#if APIVERSNUM >= 20103
|
||||
void cSoftHdDevice::TrickSpeed(int speed, bool forward)
|
||||
{
|
||||
dsyslog("[softhddev]%s: %d %d\n", __FUNCTION__, speed, forward);
|
||||
|
||||
::TrickSpeed(speed);
|
||||
}
|
||||
#else
|
||||
void cSoftHdDevice::TrickSpeed(int speed)
|
||||
{
|
||||
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, speed);
|
||||
|
||||
::TrickSpeed(speed);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
** Clears all video and audio data from the device.
|
||||
@ -2512,6 +2725,9 @@ uchar *cSoftHdDevice::GrabImage(int &size, bool jpeg, int quality, int width,
|
||||
if (SuspendMode != NOT_SUSPENDED) {
|
||||
return NULL;
|
||||
}
|
||||
if (quality < 0) { // caller should care, but fix it
|
||||
quality = 95;
|
||||
}
|
||||
|
||||
return::GrabImage(&size, jpeg, quality, width, height);
|
||||
}
|
||||
@ -2539,8 +2755,8 @@ cRect cSoftHdDevice::CanScaleVideo(const cRect & rect,
|
||||
void cSoftHdDevice::ScaleVideo(const cRect & rect)
|
||||
{
|
||||
#ifdef OSD_DEBUG
|
||||
dsyslog("[softhddev]%s: %dx%d%+d%+d\n", __FUNCTION__, VidWinRect.Width(),
|
||||
VidWinRect.Height(), VidWinRect.X(), VidWinRect.Y());
|
||||
dsyslog("[softhddev]%s: %dx%d%+d%+d\n", __FUNCTION__, rect.Width(),
|
||||
rect.Height(), rect.X(), rect.Y());
|
||||
#endif
|
||||
::ScaleVideo(rect.X(), rect.Y(), rect.Width(), rect.Height());
|
||||
}
|
||||
@ -2800,6 +3016,10 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
|
||||
ConfigHideMainMenuEntry = atoi(value);
|
||||
return true;
|
||||
}
|
||||
if (!strcasecmp(name, "DetachFromMainMenu")) {
|
||||
ConfigDetachFromMainMenu = atoi(value);
|
||||
return true;
|
||||
}
|
||||
if (!strcasecmp(name, "Osd.Width")) {
|
||||
ConfigOsdWidth = atoi(value);
|
||||
VideoSetOsdSize(ConfigOsdWidth, ConfigOsdHeight);
|
||||
@ -2849,6 +3069,10 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
|
||||
VideoSetBlackPicture(ConfigVideoBlackPicture = atoi(value));
|
||||
return true;
|
||||
}
|
||||
if (!strcasecmp(name, "ClearOnSwitch")) {
|
||||
ConfigVideoClearOnSwitch = atoi(value);
|
||||
return true;
|
||||
}
|
||||
if (!strcasecmp(name, "Brightness")) {
|
||||
VideoSetBrightness(ConfigVideoBrightness = atoi(value));
|
||||
return true;
|
||||
@ -2995,6 +3219,11 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
|
||||
ConfigAudioBufferTime = atoi(value);
|
||||
return true;
|
||||
}
|
||||
if (!strcasecmp(name, "AudioAutoAES")) {
|
||||
ConfigAudioAutoAES = atoi(value);
|
||||
AudioSetAutoAES(ConfigAudioAutoAES);
|
||||
return true;
|
||||
}
|
||||
#ifdef USE_PIP
|
||||
if (!strcasecmp(name, "pip.X")) {
|
||||
ConfigPipX = atoi(value);
|
||||
@ -3061,6 +3290,15 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SCREENSAVER
|
||||
if (!strcasecmp(name, "EnableDPMSatBlackScreen")) {
|
||||
ConfigEnableDPMSatBlackScreen = atoi(value);
|
||||
SetDPMSatBlackScreen(ConfigEnableDPMSatBlackScreen);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3180,7 +3418,7 @@ static const char *SVDRPHelpText[] = {
|
||||
" 11: enable audio pass-through\n"
|
||||
" 12: toggle audio pass-through\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"
|
||||
" 22: toggle fullscreen\n"
|
||||
" 23: disable auto-crop\n\040 24: enable auto-crop\n"
|
||||
|
@ -1,7 +1,7 @@
|
||||
///
|
||||
/// @file softhddevice.h @brief software HD device plugin header file.
|
||||
///
|
||||
/// Copyright (c) 2011 by Johns. All Rights Reserved.
|
||||
/// Copyright (c) 2011, 2014 by Johns. All Rights Reserved.
|
||||
///
|
||||
/// Contributor(s):
|
||||
///
|
||||
|
@ -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
|
||||
}
|
@ -1,65 +1,73 @@
|
||||
# Copyright 1999-2012 Gentoo Foundation
|
||||
# Copyright 1999-2014 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: $
|
||||
|
||||
EAPI="5"
|
||||
|
||||
inherit flag-o-matic toolchain-funcs vdr-plugin-2 eutils
|
||||
inherit vdr-plugin-2 git-2
|
||||
|
||||
if [ "${PV}" = "9999" ]; then
|
||||
inherit git-2
|
||||
EGIT_REPO_URI="git://projects.vdr-developer.org/vdr-plugin-softhddevice.git"
|
||||
KEYWORDS=""
|
||||
else
|
||||
SRC_URI="mirror://vdr-developerorg/889/${P}.tgz"
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
fi
|
||||
RESTRICT="test"
|
||||
|
||||
DESCRIPTION="Software and GPU emulated HD output device plugin for VDR"
|
||||
EGIT_REPO_URI="git://projects.vdr-developer.org/vdr-plugin-softhddevice.git"
|
||||
KEYWORDS=""
|
||||
|
||||
DESCRIPTION="VDR Plugin: Software and GPU emulated HD output device"
|
||||
HOMEPAGE="http://projects.vdr-developer.org/projects/show/plg-softhddevice"
|
||||
|
||||
LICENSE="AGPL-3"
|
||||
SLOT="0"
|
||||
IUSE="alsa oss vaapi vdpau yaepg xscreensaver debug"
|
||||
IUSE="alsa +debug opengl oss vaapi vdpau xscreensaver"
|
||||
|
||||
RDEPEND=">=media-video/vdr-1.7
|
||||
>=virtual/ffmpeg-0.7[vdpau?,vaapi?]
|
||||
RDEPEND=">=media-video/vdr-2
|
||||
x11-libs/libX11
|
||||
>=x11-libs/libxcb-1.8
|
||||
x11-libs/xcb-util-wm
|
||||
x11-libs/xcb-util-keysyms
|
||||
x11-libs/xcb-util-renderutil
|
||||
alsa? ( media-libs/alsa-lib )
|
||||
vdpau? ( x11-libs/libvdpau )
|
||||
vaapi? ( x11-libs/libva )
|
||||
alsa? ( media-libs/alsa-lib )
|
||||
yaepg? ( >=media-video/vdr-1.7[yaepg] )"
|
||||
opengl? ( virtual/opengl )
|
||||
vaapi? ( x11-libs/libva
|
||||
virtual/ffmpeg[vaapi] )
|
||||
vdpau? ( x11-libs/libvdpau
|
||||
virtual/ffmpeg[vdpau] )"
|
||||
DEPEND="${RDEPEND}
|
||||
x11-libs/xcb-util
|
||||
sys-devel/gettext
|
||||
virtual/pkgconfig
|
||||
oss? ( sys-kernel/linux-headers )"
|
||||
x11-libs/xcb-util"
|
||||
|
||||
src_compile() {
|
||||
local myconf
|
||||
REQUIRED_USE="opengl? ( vaapi )
|
||||
|| ( vaapi vdpau )
|
||||
|| ( alsa oss )"
|
||||
|
||||
myconf+=" ALSA=$(usex alsa 1 0)"
|
||||
myconf+=" OSS=$(usex oss 1 0)"
|
||||
myconf+=" VDPAU=$(usex vdpau 1 0)"
|
||||
myconf+=" VAAPI=$(usex vaapi 1 0)"
|
||||
myconf+=" SCREENSAVER=$(usex xscreensaver 1 0)"
|
||||
if has_version ">=media-video/ffmpeg-0.8" ; then
|
||||
myconf+=" SWRESAMPLE=1"
|
||||
#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)"
|
||||
|
||||
if has_version ">=media-video/ffmpeg-0.8"; then
|
||||
BUILD_PARAMS+=" SWRESAMPLE=1"
|
||||
fi
|
||||
if has_version ">=media-video/libav-0.8"; then
|
||||
BUILD_PARAMS+=" AVRESAMPLE=1"
|
||||
fi
|
||||
|
||||
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() {
|
||||
vdr-plugin-2_src_install
|
||||
|
||||
dodoc ChangeLog README.txt
|
||||
nonfatal dodoc ChangeLog Todo
|
||||
}
|
||||
|
18
video.h
18
video.h
@ -1,7 +1,7 @@
|
||||
///
|
||||
/// @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):
|
||||
///
|
||||
@ -37,7 +37,7 @@ typedef struct __video_stream__ VideoStream;
|
||||
// Variables
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
extern char VideoHardwareDecoder; ///< flag use hardware decoder
|
||||
extern signed char VideoHardwareDecoder; ///< flag use hardware decoder
|
||||
extern char VideoIgnoreRepeatPict; ///< disable repeat pict warning
|
||||
extern int VideoAudioDelay; ///< audio/video delay
|
||||
extern char ConfigStartX11Server; ///< flag start the x11 server
|
||||
@ -67,8 +67,8 @@ extern enum PixelFormat Video_get_format(VideoHwDecoder *, AVCodecContext *,
|
||||
extern void VideoRenderFrame(VideoHwDecoder *, const AVCodecContext *,
|
||||
const AVFrame *);
|
||||
|
||||
/// Get ffmpeg vaapi context.
|
||||
extern struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder *);
|
||||
/// Get hwaccel context for ffmpeg.
|
||||
extern void *VideoGetHwAccelContext(VideoHwDecoder *);
|
||||
|
||||
#ifdef AVCODEC_VDPAU_H
|
||||
/// Draw vdpau render state.
|
||||
@ -168,7 +168,8 @@ extern void VideoSetAutoCrop(int, int, int);
|
||||
extern void VideoOsdClear(void);
|
||||
|
||||
/// 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.
|
||||
extern void VideoGetOsdSize(int *, int *);
|
||||
@ -221,7 +222,10 @@ extern int VideoDecodeInput(VideoStream *);
|
||||
/// Get number of input buffers.
|
||||
extern int VideoGetBuffers(const VideoStream *);
|
||||
|
||||
/// Raise the frontend window
|
||||
extern int VideoRaiseWindow();
|
||||
/// Set DPMS at Blackscreen switch
|
||||
extern void SetDPMSatBlackScreen(int);
|
||||
|
||||
/// Raise the frontend window
|
||||
extern int VideoRaiseWindow(void);
|
||||
|
||||
/// @}
|
||||
|
Loading…
x
Reference in New Issue
Block a user