71 Commits
0.2.0 ... 0.4.5

Author SHA1 Message Date
Johns
eed708b9ea Release version 0.4.5. 2012-01-28 13:44:50 +01:00
Johns
60a7c36fa6 Add configurable skip lines at video top + bottom. 2012-01-28 01:44:50 +01:00
Johns
4d74ed1bfc Add auto-crop tolerance configuration. 2012-01-27 23:49:05 +01:00
Johns
c3b924a239 Reduces audio latency, increases audio buffer time. 2012-01-27 23:33:10 +01:00
Johns
f8d198636b Video bug fix.
Made video_test working again.
Disabled VA-API Intel vaAssociateSubpicture workaround.
Fix bug: Must release lock for VideoPollEvent.
Allow faster video and audio sync.
Fix bug: Software decoder use vaPutImage with Intel backend.
Fix bug: Artefacts are shown after mpeg2 channel switch.
Fix bug: VideoReleaseSurface called after VideoExit.
2012-01-27 21:08:37 +01:00
Johns
bcf6ecabc1 Support external players. 2012-01-26 15:00:49 +01:00
Johns
9063b4e3ff Add VDPAU display preemption support. 2012-01-25 15:31:49 +01:00
Johns
e3681812bd Remove pass-through test code. 2012-01-25 15:31:18 +01:00
Johns
9d14522121 Add jpeg support to ebuild. 2012-01-25 15:30:22 +01:00
2dff69dc14 Add support for grab jpeg image. 2012-01-24 22:40:06 +01:00
Johns
5668fa22d2 Video cleanup.
More functions uses new module interface.
Fix bug: VaapiOsdExit doesn't deassociate osd surface.
Fix bug: First OSD can show random pixels.
2012-01-24 22:25:33 +01:00
Johns
c7cebe1aeb Wait for X11 exit and kill it, if not. 2012-01-24 22:20:17 +01:00
Johns
037f582bad Fix still picture handling. 2012-01-24 16:37:11 +01:00
Johns
6ca4d3c44f Fix dead-lock in VdpauExit. 2012-01-24 10:02:39 +01:00
Johns
2ac2eb39c6 Workaround for dead-lock in VdpauExit. 2012-01-24 00:32:07 +01:00
Johns
217545542d Add ac3 pass-through device to OSS module. 2012-01-23 20:23:05 +01:00
Johns
5f43803236 VDPAU: Add primitive software scaler to grab image 2012-01-23 20:04:15 +01:00
Johns
993d831190 VA-API: Add auto-crop support. 2012-01-23 15:40:59 +01:00
Johns
1969b2a0a7 Fix bug: close codec missing. 2012-01-22 22:46:52 +01:00
Johns
0fad02285d AC3 device should be called 'ALSA_AC3_DEVICE'. 2012-01-22 20:53:27 +01:00
Johns
9546233175 Suspend can close and open video and audio device. 2012-01-22 20:49:43 +01:00
Johns
98d2e0f728 Cleanups and Codec..Del.. prototypes. 2012-01-22 17:07:08 +01:00
970493fb23 Use different alsa device for AC3/pass-through. 2012-01-22 16:54:22 +01:00
Johns
329dbc5f07 Add dummy player and control for suspend mode. 2012-01-22 11:12:57 +01:00
Johns
bc8a13e1ef Call VdpauMixerSetup only, if mixer setup. 2012-01-21 21:56:19 +01:00
Johns
bd7e6143c7 Buffertime compile time configurable in ms. 2012-01-21 21:46:47 +01:00
Johns
fa27a1c73a Release Version 0.4.0. 2012-01-21 15:56:45 +01:00
Johns
e32857a27a VDPAU: Add screenshot support. 2012-01-20 21:46:22 +01:00
Johns
5ba88bb822 Use common module prefix. 2012-01-20 19:56:06 +01:00
Johns
0422b6aa5a VDPAU: Add auto-crop support. 2012-01-20 15:33:37 +01:00
Johns
eb024558de VDPAU: Changed OSD alpha calculation. 2012-01-19 22:58:02 +01:00
Johns
1593d5dd83 Fix bug: Used VideoSharpen for denoise settings.
Instant update deinterlace/... configuration changes.
2012-01-19 21:28:38 +01:00
Johns
09f62307d4 Fix bug: AudioExit called without AudioInit crash. 2012-01-19 17:01:02 +01:00
Johns
87f7aa63cc Release Version 0.3.5. 2012-01-19 16:01:05 +01:00
Johns
b1ce88923e Small miscellaneous cleanups. 2012-01-19 00:16:15 +01:00
Johns
c6e66e0787 OSD improvements:
Use OSD size equal to video window.
Update only dirty area(s) of OSD.
Show/mix only used area of OSD.
Fix bug: vpdau use previous resolution for deint, ...
2012-01-18 15:15:37 +01:00
Johns
19d4eeed82 Little speed improved Intel VA-API deinterlace. 2012-01-17 18:53:53 +01:00
Johns
9f668c4750 Fix software deinterlace with VA-API. 2012-01-17 17:41:24 +01:00
Johns
e419742a40 OSS needs kernel headers. 2012-01-16 23:55:45 +01:00
Johns
2cacdc6c90 Debug, if vaapi putsurface is too slow. 2012-01-16 23:54:48 +01:00
Johns
6efe558f78 Fix bug: transposed digits 567 should be 576. 2012-01-16 20:20:01 +01:00
Johns
80100299f3 Disable VA-API if init fails. 2012-01-16 17:05:22 +01:00
Johns
5509d768ac Remove double x11-libs/xcb-util-wm. 2012-01-16 16:39:23 +01:00
Johns
c0d0a4ae7c Audio module cleanup (more to come).
Alsa + OSS can be included/build at the same time.
Alsa or OSS can be runtime selected with -a.
Add audio thread support to OSS module.
Add polled audio support to alsa module.
Removed some debug source code.
2012-01-16 15:42:17 +01:00
Johns
e619f5c836 Release Version 0.3.1. 2012-01-15 16:57:03 +01:00
Johns
973fcfe4dd Support BBC-HD (no clean solution). 2012-01-15 14:31:54 +01:00
Johns
eec30433b6 Fix bug: AudioFreeBytes fails if no audio ready. 2012-01-13 22:39:04 +01:00
Johns
baf577aba5 Fix bug: snd_pcm_state: Assertion `pcm' failed. 2012-01-13 19:33:59 +01:00
Johns
81d7ef9755 Support xcb_ewmh.h for xcb-util <0.3.8. 2012-01-13 17:20:43 +01:00
Johns
7f7de8678f Add support for fullscreen mode. 2012-01-13 16:31:29 +01:00
Johns
92bb00c410 Add vaapi color space conversion. 2012-01-13 12:28:56 +01:00
Johns
d3b98b90f4 Fix bug: devision by zero in ...UpdateOutput, 2012-01-13 10:04:26 +01:00
Johns
788636ee6b Destroy vdpau surface only, when initialized. 2012-01-13 00:58:30 +01:00
Johns
8e53cbd4a9 VAAPI: Instant use new deinterlace configuration. 2012-01-12 23:07:06 +01:00
Johns
54661f90ea Weave is deinterlace disabled. 2012-01-12 20:54:49 +01:00
Johns
30d8e8afe9 Fix subtitle position. 2012-01-12 18:55:07 +01:00
Johns
19a37bb0bf Add SVDRP support. 2012-01-12 15:20:01 +01:00
Johns
2087968d55 Rebuild objects, when Makefile changes. 2012-01-12 15:19:19 +01:00
Johns
d983f780b3 Suspend when user is inactive. 2012-01-11 18:01:18 +01:00
712b2e0de1 Patch collection from Christian Ruppert.
Move objects before $LIBS to avoid link failures with --as-needed.
Do not override CFLAGS for video test.
Rearrange *FLAGS incl. some minor fixes.
Don't override VDRDIR, LIBDIR and TMPDIR in makefile.
Don't abuse LDFLAGS in makefile.
Define CC in makefile.
Include GL/gl.h for the GL_COLOR_BUFFER_BIT definition.
VideoInit() needs an argument.
2012-01-10 22:48:42 +01:00
Johns
54f92e67fc Don't mute hardware while replaying. 2012-01-10 16:41:46 +01:00
Johns
960cd27ab5 Add support for close and resize x11 window. 2012-01-10 15:53:54 +01:00
Johns
3a97700981 Add main menu entry, which suspends the plugin. 2012-01-10 15:52:07 +01:00
Johns
8d624224e9 Version 0.3.0 released. 2012-01-09 22:10:42 +01:00
Johns
96eefca699 Video improvements.
Fix generate of video output from StillPicture.
Add support for resolution dependend video parameterts (Deinterlace,
Scaling, Denoise, Sharpen, ...).
2012-01-09 17:03:04 +01:00
Johns
5e005eeff5 Fix audio crash in ThreadExit and snd_pcm_prepare. 2012-01-09 15:31:47 +01:00
Johns
f6df79e8e6 Improved replay of recordings. 2012-01-08 21:46:00 +01:00
Johns
f1551cd321 Ebuild bug fix. 2012-01-08 14:19:48 +01:00
Johns
9568c5bd93 Fix build with vdr without yaepg support. 2012-01-07 23:47:07 +01:00
Johns
fd60c3c132 Support yaepghd video output position change.
And code and comments cleanups.
2012-01-07 22:36:06 +01:00
Johns
7b6d0ecf94 Gentoo ebuild. 2012-01-07 17:30:27 +01:00
15 changed files with 5140 additions and 1725 deletions

114
ChangeLog
View File

@@ -1,5 +1,117 @@
User johns User johns
Data: Sat Jan 7 13:20:07 CET 2012 Date:
Release Version 0.4.5
Add configurable skip lines at video top and bottom.
Add auto-crop tolerance configuration.
Reduces audio latency, increases audio buffer time.
Made video_test working again.
Disabled VA-API Intel vaAssociateSubpicture workaround.
Fix bug: Must release lock for VideoPollEvent.
Allow faster video and audio sync.
Fix bug: Software decoder use vaPutImage with intel backend.
Fix bug: Artefacts are shown after mpeg2 channel switch.
Fix bug: VideoReleaseSurface called after VideoExit.
Support external players.
Add VDPAU display preemption support.
User m.Rcu
Date: Tue Jan 24 22:38:30 CET 2012
Add support for grab jpeg image.
User johns
Date: Tue Jan 24 22:25:33 CET 2012
Fix bug: VaapiOsdExit doesn't deassociate osd surface.
Fix bug: First OSD can show random pixels.
Wait for X11 exit and kill it, if not.
Fix still picture handling.
Fix for dead-lock in VdpauExit.
Workaround for dead-lock in VdpauExit.
VDPAU: Add very primitive software scaler for grab image.
VA-API: Add auto-crop support.
Suspend can close/open X11 window, connection and audio device.
User Morone
Date: Sun Jan 22 16:43:23 CET 2012
Use different alsa devices for AC3/pass-through and pcm.
User johns
Date: Sun Jan 22 11:12:57 CET 2012
Add dummy player and control for suspend mode.
Buffertime compile time configurable in ms.
Date: Sat Jan 21 15:49:16 CET 2012
Release Version 0.4.0
VDPAU: Add grab image support.
VDPAU: Add auto-crop support.
VDPAU: Changed OSD alpha calculation.
Fix bug: Used VideoSharpen for denoise settings.
Instant update deinterlace/... configuration changes.
Fix bug: AudioExit called without AudioInit crash.
Date: Thu Jan 19 15:58:40 CET 2012
Release Version 0.3.5
OSD improvements:
Use OSD size equal to video window.
Update only dirty area(s) of OSD.
Show/mix only used area of OSD.
Fix bug: vpdau use previous resolution for deint, ...
Fix software deinterlace with VA-API.
Fix bug: transposed digits 567 should be 576.
Audio module cleanup:
Alsa + OSS can be included/build at the same time.
Alsa or OSS can be runtime selected with -a.
Add audio thread support to OSS module.
Add polled audio support to alsa module.
Removed some debug source code.
Date: Sun Jan 15 16:56:04 CET 2012
Release Version 0.3.1
Fix bug: AudioFreeBytes didn't check if audio running/compiled.
Fix bug: snd_pcm_state: Assertion `pcm' failed.
Add support for fullscreen and fullscreen toogle.
Instant update deinterlace configuration changes.
Fix subtitle position.
Add SVDRP support.
Suspend when user is inactive.
User Christian Rupper
Date: Tue Jan 10 22:33:14 CET 2012
Move objects before $LIBS to avoid link failures with --as-needed.
Do not override CFLAGS for video test.
Rearrange *FLAGS incl. some minor fixes.
Don't override VDRDIR, LIBDIR and TMPDIR in makefile.
Don't abuse LDFLAGS in makefile.
Define CC in makefile.
Include GL/gl.h for the GL_COLOR_BUFFER_BIT definition.
VideoInit() needs an argument.
User johns
Date: Tue Jan 10 22:32:50 CET 2012
Add main menu entry, which suspends the plugin.
Add support for resize window.
Close window sends "close" as remote key press.
Date: Mon Jan 9 22:09:38 CET 2012
Release Version 0.3.0
Add support of resolution dependend video parameters (deint, scale, ...).
Add support for recording play back.
Add workaround for alsa crash in snd_pcm_prepare.
Fix bug: audio crash on exit.
Fix build with vdr without yaepg support.
Support yaepghd video picture output position change.
Date: Sat Jan 7 13:20:07 CET 2012
Release Version 0.2.0 Release Version 0.2.0
Add support for ac3 audio pass through. Add support for ac3 audio pass through.

View File

@@ -14,6 +14,7 @@ PLUGIN = softhddevice
### The version number of this plugin (taken from the main source file): ### 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') 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) ### Configuration (edit this for your needs)
@@ -22,44 +23,22 @@ CONFIG := #-DDEBUG
CONFIG += $(shell pkg-config --exists vdpau && echo "-DUSE_VDPAU") CONFIG += $(shell pkg-config --exists vdpau && echo "-DUSE_VDPAU")
CONFIG += $(shell pkg-config --exists libva && echo "-DUSE_VAAPI") CONFIG += $(shell pkg-config --exists libva && echo "-DUSE_VAAPI")
CONFIG += $(shell pkg-config --exists alsa && echo "-DUSE_ALSA") CONFIG += $(shell pkg-config --exists alsa && echo "-DUSE_ALSA")
#CONFIG += -DUSE_OSS CONFIG += $(shell ls /usr/lib/libjpeg* >/dev/null 2>&1 && echo "-DUSE_JPEG")
CONFIG += -DUSE_OSS
### The C++ compiler and options: ### The C++ compiler and options:
CC ?= gcc
CXX ?= g++ CXX ?= g++
CXXFLAGS ?= -g -O2 -W -Wall -Wextra -Woverloaded-virtual -fPIC
override CXXFLAGS += $(DEFINES) $(INCLUDES)
CFLAGS ?= -g -O2 -W -Wall -Wextra -Winit-self \ CFLAGS ?= -g -O2 -W -Wall -Wextra -Winit-self \
-Wdeclaration-after-statement -fPIC -Wdeclaration-after-statement
#CFLAGS += -Werror CXXFLAGS ?= -g -O2 -W -Wall -Wextra -Woverloaded-virtual
override CFLAGS += $(DEFINES) $(INCLUDES) \
$(shell pkg-config --cflags libavcodec libavformat) \
`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_VDPAU,$(CONFIG)), \
`pkg-config --cflags vdpau`) \
$(if $(findstring USE_VAAPI,$(CONFIG)), \
`pkg-config --cflags libva-x11 libva-glx libva`) \
$(if $(findstring USE_ALSA,$(CONFIG)), \
`pkg-config --cflags alsa`)
override LDFLAGS += -lrt \
$(shell pkg-config --libs libavcodec libavformat) \
`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_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 directory environment: ### The directory environment:
VDRDIR = ../../.. VDRDIR ?= ../../..
LIBDIR = ../../lib LIBDIR ?= ../../lib
TMPDIR = /tmp TMPDIR ?= /tmp
### Make sure that necessary options are included: ### Make sure that necessary options are included:
@@ -78,11 +57,42 @@ APIVERSION = $(shell sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$$/\1/p' $(VDRDI
ARCHIVE = $(PLUGIN)-$(VERSION) ARCHIVE = $(PLUGIN)-$(VERSION)
PACKAGE = vdr-$(ARCHIVE) PACKAGE = vdr-$(ARCHIVE)
### Includes and Defines (add further entries here): ### Includes, Defines and dependencies (add further entries here):
INCLUDES += -I$(VDRDIR)/include INCLUDES += -I$(VDRDIR)/include
DEFINES += $(CONFIG) -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' DEFINES += $(CONFIG) -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' \
$(if $(GIT_REV), -DGIT_REV='"$(GIT_REV)"')
_CFLAGS = $(DEFINES) $(INCLUDES) \
$(shell pkg-config --cflags libavcodec libavformat) \
`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_VDPAU,$(CONFIG)), \
`pkg-config --cflags vdpau`) \
$(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 libavformat) \
`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_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`) \
$(if $(findstring USE_JPEG,$(CONFIG)), \
-ljpeg)
### The object files (add further files here): ### The object files (add further files here):
@@ -105,6 +115,8 @@ DEPFILE = .dependencies
$(DEPFILE): Makefile $(DEPFILE): Makefile
@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(SRCS) >$@ @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(SRCS) >$@
$(OBJS): Makefile
-include $(DEPFILE) -include $(DEPFILE)
### Internationalization (I18N): ### Internationalization (I18N):
@@ -137,7 +149,7 @@ i18n: $(I18Nmsgs) $(I18Npot)
### Targets: ### Targets:
libvdr-$(PLUGIN).so: $(OBJS) Makefile libvdr-$(PLUGIN).so: $(OBJS) Makefile
$(CXX) $(CXXFLAGS) -shared $(OBJS) -o $@ $(LDFLAGS) $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -fPIC $(OBJS) -o $@ $(LIBS)
@cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION) @cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION)
dist: $(I18Npo) clean dist: $(I18Npo) clean
@@ -162,6 +174,6 @@ indent:
indent $$i; unexpand -a $$i > $$i.up; mv $$i.up $$i; \ indent $$i; unexpand -a $$i > $$i.up; mv $$i.up $$i; \
done done
video_test: video.c video_test: video.c Makefile
$(CC) -DVIDEO_TEST -DVERSION='"$(VERSION)"' $(CFLAGS) $(LDFLAGS) $(LIBS) \ $(CC) -DVIDEO_TEST -DVERSION='"$(VERSION)"' $(CFLAGS) $(LDFLAGS) $< $(LIBS) \
-O0 -g -o $@ $< -o $@

View File

@@ -24,17 +24,20 @@ A software and GPU emulated HD output device plugin for VDR.
o Video CPU/VA-API o Video CPU/VA-API
o Video VDPAU/VDPAU o Video VDPAU/VDPAU
o Video CPU/VDPAU o Video CPU/VDPAU
o Audio FFMpeg/Alsa/Analog
o Audio FFMpeg/Alsa/Digital
o Audio FFMpeg/OSS/Analog
o HDMI/SPDIF Passthrough
o VA-API bob software deinterlace
o Auto-crop
o planned: Video VA-API/Opengl o planned: Video VA-API/Opengl
o planned: Video VDPAU/Opengl o planned: Video VDPAU/Opengl
o planned: Video CPU/Xv o planned: Video CPU/Xv
o planned: Video CPU/Opengl o planned: Video CPU/Opengl
o planned: Software Deinterlacer o planned: Improved Software Deinterlacer (yadif or/and ffmpeg filters)
o planned: Video XvBA/XvBA o planned: Video XvBA/XvBA
o Audio FFMpeg/Alsa/Analog o planned: atmo light support
o Audio FFMpeg/Alsa/Digital
o Audio FFMpeg/OSS/Analog
o planned: Alsa HDMI/SPDIF Passthrough
o planned: OSS HDMI/SPDIF Passthrough
To compile you must have the 'requires' installed. To compile you must have the 'requires' installed.
@@ -61,7 +64,7 @@ Install:
http://projects.vdr-developer.org/projects/plg-softhddevice/files http://projects.vdr-developer.org/projects/plg-softhddevice/files
tar vxf vdr-softhddevice-*.tar.bz2 tar vxf vdr-softhddevice-*.tar.bz2
cd vdr-softhddevice cd softhddevice-*
make VDRDIR=<path-to-your-vdr-files> LIBDIR=. make VDRDIR=<path-to-your-vdr-files> LIBDIR=.
You can edit Makefile to enable/disable VDPAU / VA-API / Alsa / OSS You can edit Makefile to enable/disable VDPAU / VA-API / Alsa / OSS
@@ -76,6 +79,8 @@ Setup: environment
only if alsa is configured only if alsa is configured
ALSA_DEVICE=default ALSA_DEVICE=default
alsa PCM device name alsa PCM device name
ALSA_AC3_DEVICE=
alsa AC3/pass-though device name
ALSA_MIXER=default ALSA_MIXER=default
alsa control device name alsa control device name
ALSA_MIXER_CHANNEL=PCM ALSA_MIXER_CHANNEL=PCM
@@ -83,6 +88,8 @@ Setup: environment
only if oss is configured only if oss is configured
OSS_AUDIODEV=/dev/dsp OSS_AUDIODEV=/dev/dsp
oss dsp device name oss dsp device name
OSS_AC3_AUDIODEV=
oss AC3/pass-though device name
OSS_MIXERDEV=/dev/mixer OSS_MIXERDEV=/dev/mixer
oss mixer device name oss mixer device name
OSS_MIXER_CHANNEL=pcm OSS_MIXER_CHANNEL=pcm
@@ -95,34 +102,99 @@ Setup: /etc/vdr/setup.conf
softhddevice.MakePrimary = 1 softhddevice.MakePrimary = 1
0 = no change, 1 make softhddevice primary at start 0 = no change, 1 make softhddevice primary at start
softhddevice.Deinterlace = 0 softhddevice.HideMainMenuEntry = 0
0 = show softhddevice main menu entry, 1 = hide entry
<res> of the next parameters is 567i, 720p, 1080i_fake or 1080i.
1080i_fake is 1280x1080 or 1440x1080
1080i is "real" 1920x1080
softhddevice.<res>.Scaling = 0
0 = normal, 1 = fast, 2 = HQ, 3 = anamorphic
softhddevice.<res>.Deinterlace = 0
0 = bob, 1 = weave, 2 = temporal, 3 = temporal_spatial, 4 = software 0 = bob, 1 = weave, 2 = temporal, 3 = temporal_spatial, 4 = software
(only 0, 1 supported with vaapi) (only 0, 1 supported with vaapi)
softhddevice.SkipChromaDeinterlace = 0 softhddevice.<res>.SkipChromaDeinterlace = 0
0 = disabled, 1 = enabled (for slower cards, poor qualit<69>t) 0 = disabled, 1 = enabled (for slower cards, poor qualit<69>t)
softhddevice.Denoise = 0 softhddevice.<res>.Denoise = 0
0 .. 1000 noise reduction level (0 off, 1000 max) 0 .. 1000 noise reduction level (0 off, 1000 max)
softhddevice.Sharpness = 0 softhddevice.<res>.Sharpness = 0
-1000 .. 1000 noise reduction level (0 off, -1000 max blur, -1000 .. 1000 noise reduction level (0 off, -1000 max blur,
1000 max sharp) 1000 max sharp)
softhddevice.Scaling = 0
0 = normal, 1 = fast, 2 = HQ, 3 = anamorphic
softhddevice.AudioDelay = 0 softhddevice.AudioDelay = 0
+n or -n ms +n or -n ms
softhddevice.AudioPassthrough = 0 softhddevice.AudioPassthrough = 0
0 = none, 1 = AC-3 0 = none, 1 = AC-3
for AC-3 the pass-through device is used.
softhddevice.AutoCrop.Interval = 0
0 disables auto-crop
n each 'n' frames auto-crop is checked.
softhddevice.AutoCrop.Delay = 0
if auto-crop is over 'n' intervals the same, the cropping is
used.
softhddevice.AutoCrop.Tolerance = 0
if detected crop area is too small, cut max 'n' pixels at top and
bottom.
softhddevice.Suspend.Close = 0
1 suspend closes x11 window, connection and audio device.
(use svdrpsend plug softhddevice RESU to resume, if you have no lirc)
softhddevice.Suspend.X11 = 0
1 suspend stops X11 server (not working yet)
Setup: /etc/vdr/remote.conf
------
Add "XKeySym." definitions to /etc/vdr/remote.conf to control
the vdr and plugin with the connected input device.
fe.
XKeySym.Up Up
XKeySym.Down Down
...
Additional to the x11 input sends the window close button "Close".
fe.
XKeySym.Power Close
Commandline: Commandline:
------------ ------------
Use vdr -h to see the command line arguments support by the plugin. Use vdr -h to see the command line arguments supported by the plugin.
-a audio_device
Selects audio output module and device.
"" to disable audio output
/... to use oss audio module (if compiled with oss
support)
other to use alsa audio module (if compiled with alsa
support)
SVDRP:
------
Use 'svdrpsend.pl plug softhddevice HELP' to see the SVDRP commands
help and which are supported by the plugin.
Running:
--------
Click into video window to toggle fullscreen/window mode, only if you
have a window manager running.
Warning: Warning:
-------- --------

97
Todo
View File

@@ -19,59 +19,69 @@ GNU Affero General Public License for more details.
$Id: $ $Id: $
missing: missing:
video out with xv software deinterlace (yadif, ...)
video out with opengl software decoder with software deinterlace
software decoder for xv / opengl zoom/fit-zoom 4:3 (SetVideoDisplayFormat, SetVideoFormat?)
software deinterlace
auto crop
atmolight
zoom/fit-zoom 4:3
multistream handling
disable screensaver
disable window cursor
ITU BT601, ITU BT709 (HD), RGB studio levels (16-235)? ITU BT601, ITU BT709 (HD), RGB studio levels (16-235)?
suspend output / energie saver: stop and restart X11
Option deinterlace off / deinterlace force!
Make output drivers better modular (under construction).
crash:
AudioPlayHandlerThread -> pthread_cond_wait
video:
subtitle not cleared
subtitle could be asyncron
reduce warnings after channel switch
grab image with hardware and better scaling support
suspendoutput didn't show logo or black pictures
(must detect video format to show image)
hard channel switch
skip line not configurable from setup menu.
vdpau: vdpau:
1080i with temporal spatial and level 1 scaling too slow with my GT 520
1080i with temporal spatial too slow with my GT 520 on some channels
SkipChromaDeinterlace improves performance
Improve OSD handling, show only what is used. Big OSD costs performance
VdpPreemptionCallback handling
hard channel switch
libva: libva:
hard channel switch yaepghd (VaapiSetOutputPosition) support
can associate only displayed part of osd
grab image for va-api
still many:
[drm:i915_hangcheck_elapsed] *ERROR* Hangcheck timer elapsed... GPU hung
[drm:i915_wait_request] *ERROR* i915_wait_request returns -11 ...
libva: branch vaapi-ext
add support for vaapi-ext
libva-intel-driver: libva-intel-driver:
intel still has hangups most with 1080i 1080i does no v-sync (sometimes correct working with vaapi-ext)
1080i does no v-sync (workaround written) OSD has sometimes wrong size (workaround written)
osd has sometimes wrong size (workaround written) software decoder needs UV swab
libva-vdpau-driver: libva-vdpau-driver:
G210 osd update too slow (needs hardware problem workaround) G210/GT520 OSD update too slow (needs hardware problem workaround)
OSD update is too slow
hangup on exit (VaapiDelDecoder -> VaapiCleanup hangup on exit (VaapiDelDecoder -> VaapiCleanup
-> vaDestroyContext -> pthread_rwlock_wrlock) -> vaDestroyContext -> pthread_rwlock_wrlock)
with auto-crop OSD has wrong position
libva-xvba-driver: libva-xvba-driver:
with auto-crop OSD has wrong position
x11: x11:
support resize of x11 window disable screensaver
support fullscreen window
support fullscreen / window toggle audio:
close window should send power button write TS -> PES parser, which feeds audio before the next start packet
disable cursor Combine alsa+oss ringbuffer code.
Make alsa thread/polled and oss thread/polled output module runtime
selectable.
software volume support
audio/alsa: audio/alsa:
done? video/audio asyncron
random crashes in av_parser_parse2, when switching channels
sometimes alsa hangs
better downmix of >2 channels on 2 channel hardware better downmix of >2 channels on 2 channel hardware
remix support of unsupported sample rates remix support of unsupported sample rates
libav supports only resample of mono to 2 channels libav supports only resample of mono to 2 channels
ffmpeg didn't support resample of 5 to 2 channels ffmpeg didn't support resample of 5 to 2 channels
CodecAudioOpen can fail "can't open audio codec" and does Fatal exit.
audio/oss: audio/oss:
alsa oss emulation mixer "pcm" not working alsa oss emulation mixer "pcm" not working
@@ -79,15 +89,34 @@ audio/oss:
HDMI/SPDIF Passthrough: HDMI/SPDIF Passthrough:
only AC-3 written only AC-3 written
Channels are wrong setup, if changing setting during operation.
support oss pass-through
playback of recording playback of recording
play back is too fast
pause is not reset, when replay exit pause is not reset, when replay exit
replay/pause need 100% cpu
setup: setup:
Setup of decoder type. Setup of decoder type.
Setup of output type. Setup of output type.
Setup of display type. Setup of display type.
Setup 4:3 zoom type Setup 4:3 zoom type
Setup parameters are not used until restart. Some setup parameters are not used until restart.
Can a notice be added to the setup menu? Can a notice be added to the setup menu?
unsorted:
Menu -> Setup -> Plugins -> skingenigmang -> General
-> Try 8bpp single area: no, has missing parts.
stoping vdr while plugin is suspended opens and closes a window.
future features (not planed for 1.0 - 1.5)
video out with xv
video out with opengl
video out with xvba
software decoder for xv / opengl
atmolight support
multistream handling
pip support
upmix stereo to AC-3

829
audio.c

File diff suppressed because it is too large Load Diff

17
audio.h
View File

@@ -1,7 +1,7 @@
/// ///
/// @file audio.h @brief Audio module headerfile /// @file audio.h @brief Audio module headerfile
/// ///
/// Copyright (c) 2009 - 2011 by Johns. All Rights Reserved. /// Copyright (c) 2009 - 2012 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@@ -28,21 +28,22 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
extern void AudioEnqueue(const void *, int); ///< buffer audio samples extern void AudioEnqueue(const void *, int); ///< buffer audio samples
extern void AudioFlushBuffers(void); ///< flush audio buffers
extern void AudioPoller(void); ///< poll audio events/handling
extern int AudioFreeBytes(void); ///< free bytes in audio output
//extern int AudioFreeBytes(void); ///< free bytes in audio output
//extern int AudioUsedBytes(void); ///< used bytes in audio output //extern int AudioUsedBytes(void); ///< used bytes in audio output
extern uint64_t AudioGetDelay(void); ///< get current audio delay
extern void AudioSetClock(int64_t); ///< set audio clock base extern void AudioSetClock(int64_t); ///< set audio clock base
extern int64_t AudioGetClock(); ///< get current audio clock extern int64_t AudioGetClock(); ///< get current audio clock
extern void AudioSetVolume(int); ///< set volume
extern uint64_t AudioGetDelay(void); ///< get current audio delay extern int AudioSetup(int *, int *, int); ///< setup audio output
extern int AudioSetup(int *, int *); ///< setup audio output
//extern void AudioPlay(void); ///< play audio //extern void AudioPlay(void); ///< play audio
//extern void AudioPause(void); ///< pause audio //extern void AudioPause(void); ///< pause audio
extern void AudioSetVolume(int); ///< set volume
extern void AudioSetDevice(const char *); ///< set alsa PCM audio device extern void AudioSetDevice(const char *); ///< set PCM audio device
extern void AudioSetDeviceAC3(const char *); ///< set Passthrough device
extern void AudioInit(void); ///< setup audio module extern void AudioInit(void); ///< setup audio module
extern void AudioExit(void); ///< cleanup and exit audio module extern void AudioExit(void); ///< cleanup and exit audio module

65
codec.c
View File

@@ -320,20 +320,30 @@ static void Codec_draw_horiz_band(AVCodecContext * video_ctx,
** **
** @param hw_decoder video hardware decoder ** @param hw_decoder video hardware decoder
** **
** @returns private decoder pointer for audio/video decoder. ** @returns private decoder pointer for video decoder.
*/ */
VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder * hw_decoder) VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder * hw_decoder)
{ {
VideoDecoder *decoder; VideoDecoder *decoder;
if (!(decoder = calloc(1, sizeof(*decoder)))) { if (!(decoder = calloc(1, sizeof(*decoder)))) {
Fatal(_("codec: Can't allocate vodeo decoder\n")); Fatal(_("codec: can't allocate vodeo decoder\n"));
} }
decoder->HwDecoder = hw_decoder; decoder->HwDecoder = hw_decoder;
return decoder; return decoder;
} }
/**
** Deallocate a video decoder context.
**
** @param decoder private video decoder
*/
void CodecVideoDelDecoder(VideoDecoder * decoder)
{
free(decoder);
}
/** /**
** Open video decoder. ** Open video decoder.
** **
@@ -347,6 +357,9 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
Debug(3, "codec: using codec %s or ID %#04x\n", name, codec_id); Debug(3, "codec: using codec %s or ID %#04x\n", name, codec_id);
if (decoder->VideoCtx) {
Error(_("codec: missing close\n"));
}
// //
// ffmpeg compatibility hack // ffmpeg compatibility hack
// //
@@ -548,19 +561,29 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
video_ctx->frame_number, used); video_ctx->frame_number, used);
} }
if (used != pkt->size) { if (used != pkt->size) {
if (used >= 0) { if (used >= 0 && used < pkt->size) {
// some tv channels, produce this // some tv channels, produce this
Debug(4, Debug(4,
"codec: ooops didn't use complete video packet used %d of %d\n", "codec: ooops didn't use complete video packet used %d of %d\n",
used, pkt->size); used, pkt->size);
pkt->data += used;
pkt->size -= used; pkt->size -= used;
pkt->data += used;
goto next_part; goto next_part;
} }
Debug(3, "codec: bad frame %d\n", used); Debug(3, "codec: bad frame %d\n", used);
} }
} }
/**
** Flush the video decoder.
**
** @param decoder video decoder data
*/
void CodecVideoFlushBuffers(VideoDecoder * decoder)
{
avcodec_flush_buffers(decoder->VideoCtx);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Audio // Audio
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -603,21 +626,29 @@ static char CodecPassthroughAC3; ///< pass ac3 through
/** /**
** Allocate a new audio decoder context. ** Allocate a new audio decoder context.
** **
** @param hw_decoder video hardware decoder ** @returns private decoder pointer for audio decoder.
**
** @returns private decoder pointer for audio/video decoder.
*/ */
AudioDecoder *CodecAudioNewDecoder(void) AudioDecoder *CodecAudioNewDecoder(void)
{ {
AudioDecoder *audio_decoder; AudioDecoder *audio_decoder;
if (!(audio_decoder = calloc(1, sizeof(*audio_decoder)))) { if (!(audio_decoder = calloc(1, sizeof(*audio_decoder)))) {
Fatal(_("codec: Can't allocate audio decoder\n")); Fatal(_("codec: can't allocate audio decoder\n"));
} }
return audio_decoder; return audio_decoder;
} }
/**
** Deallocate an audio decoder context.
**
** @param decoder private audio decoder
*/
void CodecAudioDelDecoder(AudioDecoder * decoder)
{
free(decoder);
}
/** /**
** Open audio decoder. ** Open audio decoder.
** **
@@ -738,9 +769,11 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
spkt->pts = avpkt->pts; spkt->pts = avpkt->pts;
spkt->dts = avpkt->dts; spkt->dts = avpkt->dts;
#endif #endif
#ifdef DEBUG
if (!audio_decoder->AudioParser) { if (!audio_decoder->AudioParser) {
Fatal(_("codec: internal error parser freeded while running\n")); Fatal(_("codec: internal error parser freeded while running\n"));
} }
#endif
audio_ctx = audio_decoder->AudioCtx; audio_ctx = audio_decoder->AudioCtx;
index = 0; index = 0;
@@ -782,6 +815,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
if (audio_decoder->SampleRate != audio_ctx->sample_rate if (audio_decoder->SampleRate != audio_ctx->sample_rate
|| audio_decoder->Channels != audio_ctx->channels) { || audio_decoder->Channels != audio_ctx->channels) {
int err; int err;
int isAC3;
if (audio_decoder->ReSample) { if (audio_decoder->ReSample) {
audio_resample_close(audio_decoder->ReSample); audio_resample_close(audio_decoder->ReSample);
@@ -795,16 +829,18 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
// SPDIF/HDMI passthrough // SPDIF/HDMI passthrough
if (CodecPassthroughAC3 && audio_ctx->codec_id == CODEC_ID_AC3) { if (CodecPassthroughAC3 && audio_ctx->codec_id == CODEC_ID_AC3) {
audio_decoder->HwChannels = 2; audio_decoder->HwChannels = 2;
isAC3 = 1;
} else } else
#endif #endif
{ {
audio_decoder->HwChannels = audio_ctx->channels; audio_decoder->HwChannels = audio_ctx->channels;
isAC3 = 0;
} }
// channels not support? // channels not support?
if ((err = if ((err =
AudioSetup(&audio_decoder->HwSampleRate, AudioSetup(&audio_decoder->HwSampleRate,
&audio_decoder->HwChannels))) { &audio_decoder->HwChannels, isAC3))) {
Debug(3, "codec/audio: resample %dHz *%d -> %dHz *%d\n", Debug(3, "codec/audio: resample %dHz *%d -> %dHz *%d\n",
audio_ctx->sample_rate, audio_ctx->channels, audio_ctx->sample_rate, audio_ctx->channels,
audio_decoder->HwSampleRate, audio_decoder->HwSampleRate,
@@ -1026,6 +1062,17 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
#endif #endif
/**
** Flush the audio decoder.
**
** @param decoder audio decoder data
*/
void CodecAudioFlushBuffers(AudioDecoder * decoder)
{
// FIXME: reset audio parser
avcodec_flush_buffers(decoder->AudioCtx);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Codec // Codec
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

30
codec.h
View File

@@ -1,7 +1,7 @@
/// ///
/// @file codec.h @brief Codec module headerfile /// @file codec.h @brief Codec module headerfile
/// ///
/// Copyright (c) 2009 - 2011 by Johns. All Rights Reserved. /// Copyright (c) 2009 - 2012 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@@ -40,26 +40,38 @@ typedef struct _audio_decoder_ AudioDecoder;
/// Allocate a new video decoder context. /// Allocate a new video decoder context.
extern VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder *); extern VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder *);
/// Open video codec /// Deallocate a video decoder context.
extern void CodecVideoDelDecoder(VideoDecoder *);
/// Open video codec.
extern void CodecVideoOpen(VideoDecoder *, const char *, int); extern void CodecVideoOpen(VideoDecoder *, const char *, int);
/// Close video codec /// Close video codec.
extern void CodecVideoClose(VideoDecoder *); extern void CodecVideoClose(VideoDecoder *);
/// Decode a video packet /// Decode a video packet.
extern void CodecVideoDecode(VideoDecoder *, const AVPacket * pkt); extern void CodecVideoDecode(VideoDecoder *, const AVPacket *);
/// Flush video buffers.
extern void CodecVideoFlushBuffers(VideoDecoder *);
/// Allocate a new audio decoder context. /// Allocate a new audio decoder context.
extern AudioDecoder *CodecAudioNewDecoder(void); extern AudioDecoder *CodecAudioNewDecoder(void);
/// Open audio codec /// Deallocate an audio decoder context.
extern void CodecAudioDelDecoder(AudioDecoder *);
/// Open audio codec.
extern void CodecAudioOpen(AudioDecoder *, const char *, int); extern void CodecAudioOpen(AudioDecoder *, const char *, int);
/// Close audio codec /// Close audio codec.
extern void CodecAudioClose(AudioDecoder *); extern void CodecAudioClose(AudioDecoder *);
/// Decode an audio packet /// Decode an audio packet.
extern void CodecAudioDecode(AudioDecoder *, const AVPacket * pkt); extern void CodecAudioDecode(AudioDecoder *, const AVPacket *);
/// Flush audio buffers.
extern void CodecAudioFlushBuffers(AudioDecoder *);
/// Setup and initialize codec module. /// Setup and initialize codec module.
extern void CodecInit(void); extern void CodecInit(void);

2
misc.h
View File

@@ -86,7 +86,7 @@ static inline void Syslog(const int level, const char *format, ...)
/** /**
** Show fatal error. ** Show fatal error.
*/ */
#define Fatal(fmt...) do { Error(fmt); exit(-1); } while (0) #define Fatal(fmt...) do { Error(fmt); abort(); } while (0)
/** /**
** Show warning. ** Show warning.

View File

@@ -35,6 +35,14 @@
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
#ifndef __USE_GNU
#define __USE_GNU
#endif
#include <pthread.h>
#ifdef USE_JPEG
#include <jpeglib.h>
#endif
#include "misc.h" #include "misc.h"
#include "softhddev.h" #include "softhddev.h"
@@ -52,18 +60,21 @@ static char ConfigVdpauDecoder = 1; ///< use vdpau decoder, if possible
#define ConfigVdpauDecoder 0 ///< no vdpau decoder configured #define ConfigVdpauDecoder 0 ///< no vdpau decoder configured
#endif #endif
static const char DeviceStopped = 1; ///< flag device stopped static char ConfigFullscreen; ///< fullscreen modus
static pthread_mutex_t SuspendLockMutex; ///< suspend lock mutex
static volatile char VideoFreezed; ///< video freezed
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// Audio // Audio
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
static volatile char NewAudioStream; ///< new audio stream static volatile char NewAudioStream; ///< new audio stream
static volatile char SkipAudio; ///< skip audio stream
static AudioDecoder *MyAudioDecoder; ///< audio decoder static AudioDecoder *MyAudioDecoder; ///< audio decoder
static enum CodecID AudioCodecID; ///< current codec id static enum CodecID AudioCodecID; ///< current codec id
extern void AudioTest(void); // FIXME:
/** /**
** mpeg bitrate table. ** mpeg bitrate table.
** **
@@ -113,6 +124,8 @@ static const uint16_t SampleRateTable[4] = {
** FrameLengthInBytes = (12 * BitRate / SampleRate + Padding) * 4 ** FrameLengthInBytes = (12 * BitRate / SampleRate + Padding) * 4
** Layer II & III: ** Layer II & III:
** FrameLengthInBytes = 144 * BitRate / SampleRate + Padding ** FrameLengthInBytes = 144 * BitRate / SampleRate + Padding
**
** @todo sometimes detects wrong position
*/ */
static int FindAudioSync(const AVPacket * avpkt) static int FindAudioSync(const AVPacket * avpkt)
{ {
@@ -187,14 +200,21 @@ static int FindAudioSync(const AVPacket * avpkt)
** @param size size of PES packet ** @param size size of PES packet
** @param id PES packet type ** @param id PES packet type
*/ */
void PlayAudio(const uint8_t * data, int size, int PlayAudio(const uint8_t * data, int size,
__attribute__ ((unused)) uint8_t id) __attribute__ ((unused)) uint8_t id)
{ {
int n; int n;
int osize;
AVPacket avpkt[1]; AVPacket avpkt[1];
// channel switch: SetAudioChannelDevice: SetDigitalAudioDevice: // channel switch: SetAudioChannelDevice: SetDigitalAudioDevice:
if (VideoFreezed) { // video freezed
return 0;
}
if (SkipAudio || !MyAudioDecoder) { // skip audio
return size;
}
if (NewAudioStream) { if (NewAudioStream) {
// FIXME: does this clear the audio ringbuffer? // FIXME: does this clear the audio ringbuffer?
CodecAudioClose(MyAudioDecoder); CodecAudioClose(MyAudioDecoder);
@@ -206,7 +226,11 @@ void PlayAudio(const uint8_t * data, int size,
if (size < 9) { if (size < 9) {
Error(_("[softhddev] invalid audio packet\n")); Error(_("[softhddev] invalid audio packet\n"));
return; return size;
}
// Don't overrun audio buffers on replay
if (AudioFreeBytes() < 3072 * 8 * 8) { // 8 channels 8 packets
return 0;
} }
n = data[8]; // header size n = data[8]; // header size
@@ -227,38 +251,29 @@ void PlayAudio(const uint8_t * data, int size,
} }
} }
osize = size;
data += 9 + n; data += 9 + n;
size -= 9 + n; // skip pes header size -= 9 + n; // skip pes header
if (size <= 0) { if (size <= 0) {
Error(_("[softhddev] invalid audio packet\n")); Error(_("[softhddev] invalid audio packet\n"));
return; return osize;
} }
// Detect audio code // Detect audio code
// MPEG-PS mp2 MPEG1, MPEG2, AC3 // MPEG-PS mp2 MPEG1, MPEG2, AC3
// Syncword - 0x0B77 // Syncword - 0x0B77
if (data[0] == 0x0B && data[1] == 0x77) { if (data[0] == 0x0B && data[1] == 0x77) {
if (!MyAudioDecoder) {
MyAudioDecoder = CodecAudioNewDecoder();
AudioCodecID = CODEC_ID_NONE;
}
if (AudioCodecID != CODEC_ID_AC3) { if (AudioCodecID != CODEC_ID_AC3) {
Debug(3, "[softhddev]%s: AC-3 %d\n", __FUNCTION__, id); Debug(3, "[softhddev]%s: AC-3 %d\n", __FUNCTION__, id);
CodecAudioClose(MyAudioDecoder); CodecAudioClose(MyAudioDecoder);
CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_AC3); CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_AC3);
AudioCodecID = CODEC_ID_AC3; AudioCodecID = CODEC_ID_AC3;
} }
// Syncword - 0xFFFC - 0xFFFF // Syncword - 0xFFFC - 0xFFFF
} else if (data[0] == 0xFF && (data[1] & 0xFC) == 0xFC) { } else if (data[0] == 0xFF && (data[1] & 0xFC) == 0xFC) {
if (!MyAudioDecoder) {
MyAudioDecoder = CodecAudioNewDecoder();
AudioCodecID = CODEC_ID_NONE;
}
if (AudioCodecID != CODEC_ID_MP2) { if (AudioCodecID != CODEC_ID_MP2) {
Debug(3, "[softhddev]%s: MP2 %d\n", __FUNCTION__, id); Debug(3, "[softhddev]%s: MP2 %d\n", __FUNCTION__, id);
CodecAudioClose(MyAudioDecoder); CodecAudioClose(MyAudioDecoder);
CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_MP2); CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_MP2);
AudioCodecID = CODEC_ID_MP2; AudioCodecID = CODEC_ID_MP2;
} }
@@ -273,28 +288,27 @@ void PlayAudio(const uint8_t * data, int size,
avpkt->size = size; avpkt->size = size;
n = FindAudioSync(avpkt); n = FindAudioSync(avpkt);
if (n < 0) { if (n < 0) {
return; return osize;
}
if (!MyAudioDecoder) {
MyAudioDecoder = CodecAudioNewDecoder();
} }
avpkt->pts = AV_NOPTS_VALUE;
CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_MP2); CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_MP2);
AudioCodecID = CODEC_ID_MP2; AudioCodecID = CODEC_ID_MP2;
data += n; data += n;
size -= n; size -= n;
} }
} // no decoder or codec known
if (AudioCodecID == CODEC_ID_NONE) {
// no decoder or codec known return osize;
if (!MyAudioDecoder || AudioCodecID == CODEC_ID_NONE) { }
return;
} }
avpkt->data = (void *)data; avpkt->data = (void *)data;
avpkt->size = size; avpkt->size = size;
//memset(avpkt->data + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); //memset(avpkt->data + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
CodecAudioDecode(MyAudioDecoder, avpkt); CodecAudioDecode(MyAudioDecoder, avpkt);
return osize;
} }
/** /**
@@ -302,7 +316,8 @@ void PlayAudio(const uint8_t * data, int size,
*/ */
void Mute(void) void Mute(void)
{ {
AudioSetVolume(0); SkipAudio = 1;
//AudioSetVolume(0);
} }
/** /**
@@ -322,7 +337,8 @@ void SetVolumeDevice(int volume)
#include <alsa/iatomic.h> // portable atomic_t #include <alsa/iatomic.h> // portable atomic_t
uint32_t VideoSwitch; ///< debug video switch ticks uint32_t VideoSwitch; ///< debug video switch ticks
static volatile char NewVideoStream; ///< new video stream static volatile char NewVideoStream; ///< flag new video stream
static VideoHwDecoder *MyHwDecoder; ///< video hw decoder
static VideoDecoder *MyVideoDecoder; ///< video decoder static VideoDecoder *MyVideoDecoder; ///< video decoder
static enum CodecID VideoCodecID; ///< current codec id static enum CodecID VideoCodecID; ///< current codec id
@@ -336,9 +352,9 @@ static volatile char Usr1Signal; ///< true got usr1 signal
static AVPacket VideoPacketRb[VIDEO_PACKET_MAX]; static AVPacket VideoPacketRb[VIDEO_PACKET_MAX];
static int VideoPacketWrite; ///< write pointer static int VideoPacketWrite; ///< write pointer
static int VideoPacketRead; ///< read pointer static int VideoPacketRead; ///< read pointer
static atomic_t VideoPacketsFilled; ///< how many of the buffer is used atomic_t VideoPacketsFilled; ///< how many of the buffer is used
static volatile char VideoFreezed; ///< video freezed
static volatile char VideoClearBuffers; ///< clear video buffers static volatile char VideoClearBuffers; ///< clear video buffers
static volatile char SkipVideo; ///< skip video
#ifdef DEBUG #ifdef DEBUG
static int VideoMaxPacketSize; ///< biggest used packet buffer static int VideoMaxPacketSize; ///< biggest used packet buffer
@@ -351,8 +367,6 @@ static void VideoPacketInit(void)
{ {
int i; int i;
Debug(4, "[softhddev]: %s\n", __FUNCTION__);
for (i = 0; i < VIDEO_PACKET_MAX; ++i) { for (i = 0; i < VIDEO_PACKET_MAX; ++i) {
AVPacket *avpkt; AVPacket *avpkt;
@@ -365,6 +379,7 @@ static void VideoPacketInit(void)
} }
atomic_set(&VideoPacketsFilled, 0); atomic_set(&VideoPacketsFilled, 0);
VideoPacketRead = VideoPacketWrite = 0;
} }
/** /**
@@ -374,16 +389,10 @@ static void VideoPacketExit(void)
{ {
int i; int i;
Debug(4, "[softhddev]: %s\n", __FUNCTION__);
atomic_set(&VideoPacketsFilled, 0); atomic_set(&VideoPacketsFilled, 0);
for (i = 0; i < VIDEO_PACKET_MAX; ++i) { for (i = 0; i < VIDEO_PACKET_MAX; ++i) {
AVPacket *avpkt; av_free_packet(&VideoPacketRb[i]);
avpkt = &VideoPacketRb[i];
// build a clean ffmpeg av packet
av_free_packet(avpkt);
} }
} }
@@ -443,10 +452,10 @@ static void VideoNextPacket(int codec_id)
avpkt = &VideoPacketRb[VideoPacketWrite]; avpkt = &VideoPacketRb[VideoPacketWrite];
if (!avpkt->stream_index) { // ignore empty packets if (!avpkt->stream_index) { // ignore empty packets
if (codec_id == CODEC_ID_NONE) { if (codec_id != CODEC_ID_NONE) {
Debug(3, "video: possible stream change loss\n"); return;
} }
return; Debug(3, "video: possible stream change loss\n");
} }
if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) { if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
@@ -460,19 +469,20 @@ static void VideoNextPacket(int codec_id)
} }
// clear area for decoder, always enough space allocated // clear area for decoder, always enough space allocated
memset(avpkt->data + avpkt->stream_index, 0, FF_INPUT_BUFFER_PADDING_SIZE); memset(avpkt->data + avpkt->stream_index, 0, FF_INPUT_BUFFER_PADDING_SIZE);
avpkt->priv = (void *)(size_t) codec_id; avpkt->priv = (void *)(size_t) codec_id;
// advance packet write // advance packet write
VideoPacketWrite = (VideoPacketWrite + 1) % VIDEO_PACKET_MAX; VideoPacketWrite = (VideoPacketWrite + 1) % VIDEO_PACKET_MAX;
atomic_inc(&VideoPacketsFilled); atomic_inc(&VideoPacketsFilled);
VideoDisplayWakeup();
// intialize next package to use // intialize next package to use
avpkt = &VideoPacketRb[VideoPacketWrite]; avpkt = &VideoPacketRb[VideoPacketWrite];
avpkt->stream_index = 0; avpkt->stream_index = 0;
avpkt->pts = AV_NOPTS_VALUE; avpkt->pts = AV_NOPTS_VALUE;
avpkt->dts = AV_NOPTS_VALUE; avpkt->dts = AV_NOPTS_VALUE;
VideoDisplayHandler();
} }
/** /**
@@ -490,6 +500,10 @@ int VideoDecode(void)
} }
if (VideoClearBuffers) { if (VideoClearBuffers) {
atomic_set(&VideoPacketsFilled, 0); atomic_set(&VideoPacketsFilled, 0);
VideoPacketRead = VideoPacketWrite;
if (MyVideoDecoder) {
CodecVideoFlushBuffers(MyVideoDecoder);
}
VideoClearBuffers = 0; VideoClearBuffers = 0;
return 1; return 1;
} }
@@ -518,8 +532,8 @@ int VideoDecode(void)
CodecVideoClose(MyVideoDecoder); CodecVideoClose(MyVideoDecoder);
goto skip; goto skip;
} }
// size can be zero
goto skip; goto skip;
break;
case CODEC_ID_MPEG2VIDEO: case CODEC_ID_MPEG2VIDEO:
if (last_codec_id != CODEC_ID_MPEG2VIDEO) { if (last_codec_id != CODEC_ID_MPEG2VIDEO) {
last_codec_id = CODEC_ID_MPEG2VIDEO; last_codec_id = CODEC_ID_MPEG2VIDEO;
@@ -560,23 +574,47 @@ int VideoDecode(void)
/** /**
** Try video start. ** Try video start.
** **
** Could be called, when already started. ** NOT TRUE: Could be called, when already started.
*/ */
static void StartVideo(void) static void StartVideo(void)
{ {
VideoInit(X11DisplayName); VideoInit(X11DisplayName);
if (ConfigFullscreen) {
// FIXME: not good looking, mapped and then resized.
VideoSetFullscreen(1);
}
VideoOsdInit(); VideoOsdInit();
if (!MyVideoDecoder) { if (!MyVideoDecoder) {
VideoHwDecoder *hw_decoder; if ((MyHwDecoder = VideoNewHwDecoder())) {
MyVideoDecoder = CodecVideoNewDecoder(MyHwDecoder);
if ((hw_decoder = VideoNewHwDecoder())) {
MyVideoDecoder = CodecVideoNewDecoder(hw_decoder);
VideoCodecID = CODEC_ID_NONE;
} }
VideoCodecID = CODEC_ID_NONE;
} }
VideoPacketInit(); VideoPacketInit();
} }
/**
** Stop video.
*/
static void StopVideo(void)
{
VideoOsdExit();
VideoExit();
if (MyVideoDecoder) {
// FIXME: this can crash, hw decoder released by video exit
CodecVideoClose(MyVideoDecoder);
CodecVideoDelDecoder(MyVideoDecoder);
MyVideoDecoder = NULL;
}
if (MyHwDecoder) {
// done by exit: VideoDelHwDecoder(MyHwDecoder);
MyHwDecoder = NULL;
}
VideoPacketExit();
NewVideoStream = 1;
}
#ifdef DEBUG #ifdef DEBUG
/** /**
@@ -627,6 +665,9 @@ static int ValidateMpeg(const uint8_t * data, int size)
** supports complete packets. ** supports complete packets.
** We buffer here until we receive an complete PES Packet, which ** We buffer here until we receive an complete PES Packet, which
** is no problem, the audio is always far behind us. ** is no problem, the audio is always far behind us.
** cTsToPes::GetPes splits the packets.
**
** @todo FIXME: combine the 5 ifs at start of the function
*/ */
int PlayVideo(const uint8_t * data, int size) int PlayVideo(const uint8_t * data, int size)
{ {
@@ -641,6 +682,12 @@ int PlayVideo(const uint8_t * data, int size)
if (!MyVideoDecoder) { // no x11 video started if (!MyVideoDecoder) { // no x11 video started
return size; return size;
} }
if (SkipVideo) { // skip video
return size;
}
if (VideoFreezed) { // video freezed
return 0;
}
if (NewVideoStream) { // channel switched if (NewVideoStream) { // channel switched
Debug(3, "video: new stream %d\n", GetMsTicks() - VideoSwitch); Debug(3, "video: new stream %d\n", GetMsTicks() - VideoSwitch);
// FIXME: hack to test results // FIXME: hack to test results
@@ -661,10 +708,10 @@ int PlayVideo(const uint8_t * data, int size)
n = data[8]; // header size n = data[8]; // header size
// wrong size // wrong size
if (size < 9 + n + 4) { if (size < 9 + n + 4) {
Error(_("[softhddev] invalid video packet\n")); Error(_("[softhddev] invalid video packet %d bytes\n"), size);
return size; return size;
} }
// FIXME: hack to test results // buffer full: needed for replay
if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) { if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
return 0; return 0;
} }
@@ -698,13 +745,15 @@ int PlayVideo(const uint8_t * data, int size)
} }
#endif #endif
} }
// FIXME: no valid mpeg2/h264 detection yet
check = data + 9 + n; check = data + 9 + n;
if (0) { if (0) {
printf("%02x: %02x %02x %02x %02x %02x\n", data[6], check[0], check[1], printf("%02x: %02x %02x %02x %02x %02x\n", data[6], check[0], check[1],
check[2], check[3], check[4]); check[2], check[3], check[4]);
} }
// FIXME: no valid mpeg2/h264 detection yet
// FIXME: better skip all zero's >3 && 0x01 0x09 h264, >2 && 0x01 -> mpeg2
// PES_VIDEO_STREAM 0xE0 or PES start code // PES_VIDEO_STREAM 0xE0 or PES start code
//(data[6] & 0xC0) != 0x80 || //(data[6] & 0xC0) != 0x80 ||
if ((!check[0] && !check[1] && check[2] == 0x1)) { if ((!check[0] && !check[1] && check[2] == 0x1)) {
@@ -728,16 +777,31 @@ int PlayVideo(const uint8_t * data, int size)
Debug(3, "video: h264 detected\n"); Debug(3, "video: h264 detected\n");
VideoCodecID = CODEC_ID_H264; VideoCodecID = CODEC_ID_H264;
} }
// Access Unit Delimiter (BBC-HD)
// FIXME: the 4 offset are try & error selected
} else if ((data[6] & 0xC0) == 0x80 && !check[4 + 0] && !check[4 + 1]
&& !check[4 + 2] && check[4 + 3] == 0x1 && check[4 + 4] == 0x09) {
if (VideoCodecID == CODEC_ID_H264) {
VideoNextPacket(CODEC_ID_H264);
} else {
Debug(3, "video: h264 detected\n");
VideoCodecID = CODEC_ID_H264;
}
} else { } else {
// this happens when vdr sends incomplete packets // this happens when vdr sends incomplete packets
if (VideoCodecID == CODEC_ID_NONE) { if (VideoCodecID == CODEC_ID_NONE) {
Debug(3, "video: not detected\n"); Debug(3, "video: not detected\n");
return size; return size;
} }
if (VideoCodecID == CODEC_ID_MPEG2VIDEO) { // incomplete packets produce artefacts after channel switch
// packet < 65526 is the last split packet, detect it here for
// better latency
if (size < 65526 && VideoCodecID == CODEC_ID_MPEG2VIDEO) {
// mpeg codec supports incomplete packets // mpeg codec supports incomplete packets
// waiting for a full complete packages, increases needed delays // waiting for a full complete packages, increases needed delays
VideoEnqueue(pts, check, size - 9 - n);
VideoNextPacket(CODEC_ID_MPEG2VIDEO); VideoNextPacket(CODEC_ID_MPEG2VIDEO);
return size;
} }
} }
@@ -747,6 +811,82 @@ int PlayVideo(const uint8_t * data, int size)
return size; return size;
} }
#ifdef USE_JPEG
uint8_t *CreateJpeg(uint8_t * image, int raw_size, int *size, int quality,
int width, int height)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPROW row_ptr[1];
int row_stride;
uint8_t *outbuf;
long unsigned int outsize;
outbuf = NULL;
outsize = 0;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_mem_dest(&cinfo, &outbuf, &outsize);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = raw_size / height / width;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE);
jpeg_start_compress(&cinfo, TRUE);
row_stride = width * 3;
while (cinfo.next_scanline < cinfo.image_height) {
row_ptr[0] = &image[cinfo.next_scanline * row_stride];
jpeg_write_scanlines(&cinfo, row_ptr, 1);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
*size = outsize;
return outbuf;
}
#endif
/**
** Grabs the currently visible screen image.
**
** @param size size of the returned data
** @param jpeg flag true, create JPEG data
** @param quality JPEG quality
** @param width number of horizontal pixels in the frame
** @param height number of vertical pixels in the frame
*/
uint8_t *GrabImage(int *size, int jpeg, int quality, int width, int height)
{
if (jpeg) {
#ifdef USE_JPEG
int raw_size;
uint8_t *image;
uint8_t *jpg_image;
raw_size = 0;
image = VideoGrab(&raw_size, &width, &height, 0);
jpg_image = CreateJpeg(image, raw_size, size, quality, width, height);
free(image);
return jpg_image;
#else
(void)quality;
Error(_("softhddev: jpeg grabbing not supported\n"));
return NULL;
#endif
}
if (width != -1 && height != -1) {
Warning(_("softhddev: scaling unsupported\n"));
}
return VideoGrab(size, &width, &height, 1);
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/** /**
@@ -754,6 +894,7 @@ int PlayVideo(const uint8_t * data, int size)
*/ */
void SetPlayMode(void) void SetPlayMode(void)
{ {
Resume();
if (MyVideoDecoder) { if (MyVideoDecoder) {
if (VideoCodecID != CODEC_ID_NONE) { if (VideoCodecID != CODEC_ID_NONE) {
NewVideoStream = 1; NewVideoStream = 1;
@@ -761,8 +902,13 @@ void SetPlayMode(void)
} }
} }
if (MyAudioDecoder) { if (MyAudioDecoder) {
NewAudioStream = 1; if (AudioCodecID != CODEC_ID_NONE) {
NewAudioStream = 1;
}
} }
VideoFreezed = 0;
SkipAudio = 0;
SkipVideo = 0;
} }
/** /**
@@ -770,9 +916,16 @@ void SetPlayMode(void)
*/ */
void Clear(void) void Clear(void)
{ {
int i;
VideoNextPacket(VideoCodecID); // terminate work
VideoClearBuffers = 1; VideoClearBuffers = 1;
// FIXME: avcodec_flush_buffers // FIXME: avcodec_flush_buffers
// FIXME: flush audio buffers AudioFlushBuffers();
for (i = 0; VideoClearBuffers && i < 20; ++i) {
usleep(1 * 1000);
}
} }
/** /**
@@ -781,6 +934,7 @@ void Clear(void)
void Play(void) void Play(void)
{ {
VideoFreezed = 0; VideoFreezed = 0;
SkipAudio = 0;
// FIXME: restart audio // FIXME: restart audio
} }
@@ -791,16 +945,70 @@ void Freeze(void)
{ {
VideoFreezed = 1; VideoFreezed = 1;
// FIXME: freeze audio // FIXME: freeze audio
AudioFlushBuffers();
}
/**
** Display the given I-frame as a still picture.
*/
void StillPicture(const uint8_t * data, int size)
{
int i;
static uint8_t seq_end_mpeg[] = { 0x00, 0x00, 0x01, 0xB7 };
static uint8_t seq_end_h264[] = { 0x00, 0x00, 0x00, 0x01, 0x10 };
// must be a PES start code
if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
Error(_("[softhddev] invalid still video packet\n"));
return;
}
if (VideoCodecID == CODEC_ID_NONE) {
// FIXME: should detect codec, see PlayVideo
Error(_("[softhddev] no codec known for still picture\n"));
return;
}
//Clear(); // flush video buffers
// +1 future for deinterlace
for (i = -1; i < (VideoCodecID == CODEC_ID_MPEG2VIDEO ? 3 : 17); ++i) {
//if ( 1 ) {
const uint8_t *split;
int n;
// split the I-frame into single pes packets
split = data;
n = size;
do {
int len;
len = (split[4] << 8) + split[5];
if (len > n) {
break;
}
PlayVideo(split, len + 6); // feed it
split += 6 + len;
n -= 6 + len;
} while (n > 6);
VideoNextPacket(VideoCodecID); // terminate last packet
if (VideoCodecID == CODEC_ID_H264) {
VideoEnqueue(AV_NOPTS_VALUE, seq_end_h264, sizeof(seq_end_h264));
} else {
VideoEnqueue(AV_NOPTS_VALUE, seq_end_mpeg, sizeof(seq_end_mpeg));
}
VideoNextPacket(VideoCodecID); // terminate last packet
}
} }
/** /**
** Poll if device is ready. Called by replay. ** Poll if device is ready. Called by replay.
**
** @param timeout timeout to become ready in ms
*/ */
int Poll(int timeout) int Poll(int timeout)
{ {
// buffers are too full // buffers are too full
if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX / 2) { if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX / 2) {
Debug(3, "replay: poll %d\n", timeout);
if (timeout) { if (timeout) {
// let display thread work // let display thread work
usleep(timeout * 1000); usleep(timeout * 1000);
@@ -810,6 +1018,22 @@ int Poll(int timeout)
return 0; return 0;
} }
/**
** Flush the device output buffers.
**
** @param timeout timeout to flush in ms
*/
int Flush(int timeout)
{
if (atomic_read(&VideoPacketsFilled)) {
if (timeout) { // let display thread work
usleep(timeout * 1000);
}
return !atomic_read(&VideoPacketsFilled);
}
return 1;
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// OSD // OSD
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@@ -819,21 +1043,22 @@ int Poll(int timeout)
*/ */
void GetOsdSize(int *width, int *height, double *aspect) void GetOsdSize(int *width, int *height, double *aspect)
{ {
static char done; #ifdef DEBUG
static int done_width;
// FIXME: should be configured! static int done_height;
*width = 1920; #endif
*height = 1080;
//*width = 768;
//*height = 576;
VideoGetOsdSize(width, height);
*aspect = 16.0 / 9.0 / (double)*width * (double)*height; *aspect = 16.0 / 9.0 / (double)*width * (double)*height;
if (!done) { #ifdef DEBUG
if (done_width != *width || done_height != *height) {
Debug(3, "[softhddev]%s: %dx%d %g\n", __FUNCTION__, *width, *height, Debug(3, "[softhddev]%s: %dx%d %g\n", __FUNCTION__, *width, *height,
*aspect); *aspect);
done = 1; done_width = *width;
done_height = *height;
} }
#endif
} }
/** /**
@@ -854,17 +1079,19 @@ void OsdDrawARGB(int x, int y, int height, int width, const uint8_t * argb)
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
static char StartX11Server; ///< flag start the x11 server static char ConfigStartX11Server; ///< flag start the x11 server
/** /**
** Return command line help string. ** Return command line help string.
*/ */
const char *CommandLineHelp(void) const char *CommandLineHelp(void)
{ {
return " -a device\talsa audio device (fe. hw:0,0)\n" return " -a device\taudio device (fe. alsa: hw:0,0 oss: /dev/dsp)\n"
" -d display\tdisplay of x11 server (f.e :0.0)\n" " -p device\taudio device (alsa only) for pass-through (hw:0,1)\n"
" -d display\tdisplay of x11 server (fe. :0.0)\n"
" -f\t\tstart with fullscreen window (only with window manager)\n"
" -g geometry\tx11 window geometry wxh+x+y\n" " -g geometry\tx11 window geometry wxh+x+y\n"
" -x\tstart x11 server\n"; " -x\t\tstart x11 server\n";
} }
/** /**
@@ -879,13 +1106,19 @@ int ProcessArgs(int argc, char *const argv[])
// Parse arguments. // Parse arguments.
// //
for (;;) { for (;;) {
switch (getopt(argc, argv, "-a:d:g:x")) { switch (getopt(argc, argv, "-a:p:d:fg:x")) {
case 'a': // audio device case 'a': // audio device
AudioSetDevice(optarg); AudioSetDevice(optarg);
continue; continue;
case 'p': // pass-through audio device
AudioSetDeviceAC3(optarg);
continue;
case 'd': // x11 display name case 'd': // x11 display name
X11DisplayName = optarg; X11DisplayName = optarg;
continue; continue;
case 'f': // fullscreen mode
ConfigFullscreen = 1;
continue;
case 'g': // geometry case 'g': // geometry
if (VideoSetGeometry(optarg) < 0) { if (VideoSetGeometry(optarg) < 0) {
fprintf(stderr, fprintf(stderr,
@@ -895,7 +1128,7 @@ int ProcessArgs(int argc, char *const argv[])
} }
continue; continue;
case 'x': // x11 server case 'x': // x11 server
StartX11Server = 1; ConfigStartX11Server = 1;
continue; continue;
case EOF: case EOF:
break; break;
@@ -1015,32 +1248,57 @@ static void StartXServer(void)
*/ */
void SoftHdDeviceExit(void) void SoftHdDeviceExit(void)
{ {
// lets hope that vdr does a good thead cleanup // lets hope that vdr does a good thread cleanup
// no it doesn't do a good thread cleanup
if (MyVideoDecoder) { AudioExit();
CodecVideoClose(MyVideoDecoder);
// FIXME: CodecDelVideoDecoder(MyVideoDecoder);
MyVideoDecoder = NULL;
}
if (MyAudioDecoder) { if (MyAudioDecoder) {
CodecAudioClose(MyAudioDecoder); CodecAudioClose(MyAudioDecoder);
// FIXME: CodecDelAudioDecoder(MyAudioDecoder); CodecAudioDelDecoder(MyAudioDecoder);
MyAudioDecoder = NULL; MyAudioDecoder = NULL;
} }
NewAudioStream = 0;
StopVideo();
VideoOsdExit();
VideoExit();
AudioExit();
CodecExit(); CodecExit();
VideoPacketExit(); VideoPacketExit();
if (StartX11Server) { if (ConfigStartX11Server) {
Debug(3, "x-setup: Stop x11 server\n"); Debug(3, "x-setup: Stop x11 server\n");
if (X11ServerPid) { if (X11ServerPid) {
int waittime;
int timeout;
pid_t wpid;
int status;
kill(X11ServerPid, SIGTERM); kill(X11ServerPid, SIGTERM);
waittime = 0;
timeout = 500; // 0.5s
// wait for x11 finishing, with timeout
do {
wpid = waitpid(X11ServerPid, &status, WNOHANG);
if (wpid) {
break;
}
if (waittime++ < timeout) {
usleep(1 * 1000);
continue;
}
kill(X11ServerPid, SIGKILL);
} while (waittime < timeout);
if (wpid && WIFEXITED(status)) {
Debug(3, "x-setup: x11 server exited (%d)\n",
WEXITSTATUS(status));
}
if (wpid && WIFSIGNALED(status)) {
Debug(3, "x-setup: x11 server killed (%d)\n",
WTERMSIG(status));
}
} }
} }
pthread_mutex_destroy(&SuspendLockMutex);
} }
/** /**
@@ -1048,15 +1306,21 @@ void SoftHdDeviceExit(void)
*/ */
void Start(void) void Start(void)
{ {
if (StartX11Server) { if (ConfigStartX11Server) {
StartXServer(); StartXServer();
} }
CodecInit(); CodecInit();
// FIXME: AudioInit for HDMI after X11 startup // FIXME: AudioInit for HDMI after X11 startup
AudioInit(); AudioInit();
if (!StartX11Server) { MyAudioDecoder = CodecAudioNewDecoder();
AudioCodecID = CODEC_ID_NONE;
if (!ConfigStartX11Server) {
StartVideo(); StartVideo();
} }
pthread_mutex_init(&SuspendLockMutex, NULL);
} }
/** /**
@@ -1076,7 +1340,81 @@ void Stop(void)
*/ */
void MainThreadHook(void) void MainThreadHook(void)
{ {
if (!DeviceStopped) { }
VideoDisplayHandler();
//////////////////////////////////////////////////////////////////////////////
// Suspend/Resume
//////////////////////////////////////////////////////////////////////////////
/**
** Suspend plugin.
**
** @param video suspend closes video
** @param audio suspend closes audio
** @param dox11 suspend closes x11 server
*/
void Suspend(int video, int audio, int dox11)
{
pthread_mutex_lock(&SuspendLockMutex);
if (SkipVideo && SkipAudio) { // already suspended
pthread_mutex_unlock(&SuspendLockMutex);
return;
}
Debug(3, "[softhddev]%s:\n", __FUNCTION__);
SkipVideo = 1;
SkipAudio = 1;
pthread_mutex_unlock(&SuspendLockMutex);
if (audio || video) {
pthread_mutex_lock(&SuspendLockMutex);
if (audio) {
AudioExit();
if (MyAudioDecoder) {
CodecAudioClose(MyAudioDecoder);
CodecAudioDelDecoder(MyAudioDecoder);
MyAudioDecoder = NULL;
}
NewAudioStream = 0;
}
if (video) {
StopVideo();
}
pthread_mutex_unlock(&SuspendLockMutex);
}
if (dox11) {
// FIXME: stop x11, if started
} }
} }
/**
** Resume plugin.
*/
void Resume(void)
{
if (!SkipVideo && !SkipAudio) { // we are not suspended
return;
}
Debug(3, "[softhddev]%s:\n", __FUNCTION__);
pthread_mutex_lock(&SuspendLockMutex);
// FIXME: start x11
if (!MyHwDecoder) { // video not running
StartVideo();
}
if (!MyAudioDecoder) { // audio not running
AudioInit();
MyAudioDecoder = CodecAudioNewDecoder();
AudioCodecID = CODEC_ID_NONE;
}
SkipVideo = 0;
SkipAudio = 0;
pthread_mutex_unlock(&SuspendLockMutex);
}

View File

@@ -1,7 +1,7 @@
/// ///
/// @file softhddev.h @brief software HD device plugin header file. /// @file softhddev.h @brief software HD device plugin header file.
/// ///
/// Copyright (c) 2011 by Johns. All Rights Reserved. /// Copyright (c) 2011 - 2012 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@@ -36,7 +36,7 @@ extern "C"
extern void OsdDrawARGB(int, int, int, int, const uint8_t *); extern void OsdDrawARGB(int, int, int, int, const uint8_t *);
/// C plugin play audio packet /// C plugin play audio packet
extern void PlayAudio(const uint8_t *, int, uint8_t); extern int PlayAudio(const uint8_t *, int, uint8_t);
/// C plugin mute audio /// C plugin mute audio
extern void Mute(void); extern void Mute(void);
/// C plugin set audio volume /// C plugin set audio volume
@@ -46,6 +46,8 @@ extern "C"
extern int PlayVideo(const uint8_t *, int); extern int PlayVideo(const uint8_t *, int);
/// C plugin play TS video packet /// C plugin play TS video packet
extern void PlayTsVideo(const uint8_t *, int); extern void PlayTsVideo(const uint8_t *, int);
/// C plugin grab an image
extern uint8_t *GrabImage(int *, int, int, int, int);
/// C plugin set play mode /// C plugin set play mode
extern void SetPlayMode(void); extern void SetPlayMode(void);
@@ -55,8 +57,12 @@ extern "C"
extern void Play(void); extern void Play(void);
/// C plugin sets the device into "freeze frame" mode /// C plugin sets the device into "freeze frame" mode
extern void Freeze(void); extern void Freeze(void);
/// C plugin display I-frame as a still picture.
extern void StillPicture(const uint8_t *, int);
/// C plugin poll if ready /// C plugin poll if ready
extern int Poll(int); extern int Poll(int);
/// C plugin flush output buffers
extern int Flush(int);
/// C plugin command line help /// C plugin command line help
extern const char *CommandLineHelp(void); extern const char *CommandLineHelp(void);
@@ -72,6 +78,10 @@ extern "C"
/// C plugin main thread hook /// C plugin main thread hook
extern void MainThreadHook(void); extern void MainThreadHook(void);
/// Suspend plugin
extern void Suspend(int, int, int);
/// Resume plugin
extern void Resume(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,74 @@
# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
EAPI="3"
inherit eutils vdr-plugin
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 jpeg"
DEPEND=">=x11-libs/libxcb-1.7
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 )
>=media-video/ffmpeg-0.7
sys-devel/gettext
sys-devel/make
dev-util/pkgconfig
yaepg? ( >=media-video/vdr-1.7[yaepg] )
!yaepg? ( >=media-video/vdr-1.7 )
vdpau? ( x11-libs/libvdpau )
vaapi? ( x11-libs/libva )
alsa? ( media-libs/alsa-lib )
oss? ( sys-kernel/linux-headers )
jpeg? ( virtual/jpeg )
"
src_prepare() {
vdr-plugin_src_prepare
}
src_compile() {
local myconf
myconf="-DHAVE_PTHREAD_NAME"
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 jpeg && myconf="${myconf} -DUSE_JPEG"
emake all CC="$(tc-getCC)" CFLAGS="${CFLAGS}" \
LDFLAGS="${LDFLAGS}" CONFIG="${myconf}" LIBDIR="." || die
}
src_install() {
vdr-plugin_src_install
dodir /etc/vdr/plugins || die
insinto /etc/vdr/plugins
fowners -R vdr:vdr /etc/vdr || die
#insinto /etc/conf.d
#doins vdr.softhddevice
}

4103
video.c

File diff suppressed because it is too large Load Diff

90
video.h
View File

@@ -30,13 +30,6 @@
/// Video hardware decoder typedef /// Video hardware decoder typedef
typedef struct _video_hw_decoder_ VideoHwDecoder; typedef struct _video_hw_decoder_ VideoHwDecoder;
//----------------------------------------------------------------------------
// Variables
//----------------------------------------------------------------------------
//extern unsigned VideoWindowWidth; ///< current video output width
//extern unsigned VideoWindowHeight; ///< current video output height
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Prototypes // Prototypes
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -44,17 +37,20 @@ typedef struct _video_hw_decoder_ VideoHwDecoder;
/// Allocate new video hardware decoder. /// Allocate new video hardware decoder.
extern VideoHwDecoder *VideoNewHwDecoder(void); extern VideoHwDecoder *VideoNewHwDecoder(void);
/// Deallocate video hardware decoder.
extern void VideoDelHwDecoder(VideoHwDecoder *);
/// Get and allocate a video hardware surface. /// Get and allocate a video hardware surface.
extern unsigned VideoGetSurface(VideoHwDecoder *); extern unsigned VideoGetSurface(VideoHwDecoder *);
/// Release a video hardware surface. /// Release a video hardware surface
extern void VideoReleaseSurface(VideoHwDecoder *, unsigned); extern void VideoReleaseSurface(VideoHwDecoder *, unsigned);
#ifdef LIBAVCODEC_VERSION #ifdef LIBAVCODEC_VERSION
/// Render a ffmpeg frame /// Render a ffmpeg frame.
extern void VideoRenderFrame(VideoHwDecoder *, AVCodecContext *, AVFrame *); extern void VideoRenderFrame(VideoHwDecoder *, AVCodecContext *, AVFrame *);
/// Get ffmpeg vaapi context /// Get ffmpeg vaapi context.
extern struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder *); extern struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder *);
/// Callback to negotiate the PixelFormat. /// Callback to negotiate the PixelFormat.
@@ -62,57 +58,75 @@ extern enum PixelFormat Video_get_format(VideoHwDecoder *, AVCodecContext *,
const enum PixelFormat *); const enum PixelFormat *);
#ifdef AVCODEC_VDPAU_H #ifdef AVCODEC_VDPAU_H
/// Draw vdpau render state /// Draw vdpau render state.
extern void VideoDrawRenderState(VideoHwDecoder *, extern void VideoDrawRenderState(VideoHwDecoder *,
struct vdpau_render_state *); struct vdpau_render_state *);
#endif #endif
#endif #endif
/// Display video TEST /// Poll video events.
extern void VideoDisplayHandler(void);
/// Poll video events
extern void VideoPollEvent(void); extern void VideoPollEvent(void);
/// set video mode /// Wakeup display handler.
//extern void VideoSetVideoMode(int, int, int, int); extern void VideoDisplayWakeup(void);
/// set video geometry /// Set video geometry.
extern int VideoSetGeometry(const char *); extern int VideoSetGeometry(const char *);
/// set deinterlace /// Set video output position.
extern void VideoSetDeinterlace(int); extern void VideoSetOutputPosition(int, int, int, int);
/// set skip chroma deinterlace /// Set video mode.
extern void VideoSetSkipChromaDeinterlace(int); extern void VideoSetVideoMode(int, int, int, int);
/// set scaling /// Set video fullscreen mode.
extern void VideoSetScaling(int); extern void VideoSetFullscreen(int);
/// set denoise /// Set deinterlace.
extern void VideoSetDenoise(int); extern void VideoSetDeinterlace(int[]);
/// set sharpen /// Set skip chroma deinterlace.
extern void VideoSetSharpen(int); extern void VideoSetSkipChromaDeinterlace(int[]);
/// set audio delay /// Set scaling.
extern void VideoSetScaling(int[]);
/// Set denoise.
extern void VideoSetDenoise(int[]);
/// Set sharpen.
extern void VideoSetSharpen(int[]);
/// Set skip lines.
extern void VideoSetSkipLines(int);
/// Set audio delay.
extern void VideoSetAudioDelay(int); extern void VideoSetAudioDelay(int);
/// Clear OSD /// Set auto-crop parameters.
extern void VideoSetAutoCrop(int, int, int);
/// Clear OSD.
extern void VideoOsdClear(void); extern void VideoOsdClear(void);
/// Draw an OSD ARGB image /// Draw an OSD ARGB image.
extern void VideoOsdDrawARGB(int, int, int, int, const uint8_t *); extern void VideoOsdDrawARGB(int, int, int, int, const uint8_t *);
extern int64_t VideoGetClock(void); ///< get video clock /// Get OSD size.
extern void VideoGetOsdSize(int *, int *);
extern void VideoOsdInit(void); ///< setup osd extern int64_t VideoGetClock(void); ///< Get video clock.
extern void VideoOsdExit(void); ///< cleanup osd
extern void VideoInit(const char *); ///< setup video module /// Grab screen.
extern void VideoExit(void); ///< cleanup and exit video module extern uint8_t *VideoGrab(int *, int *, int *, int);
extern void VideoFlushInput(void); ///< flush codec input buffers extern void VideoOsdInit(void); ///< Setup osd.
extern int VideoDecode(void); ///< decode extern void VideoOsdExit(void); ///< Cleanup osd.
extern void VideoInit(const char *); ///< Setup video module.
extern void VideoExit(void); ///< Cleanup and exit video module.
extern void VideoFlushInput(void); ///< Flush video input buffers.
extern int VideoDecode(void); ///< Decode video input buffers.
/// @} /// @}