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
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
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):
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)
@@ -22,44 +23,22 @@ CONFIG := #-DDEBUG
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
CONFIG += $(shell ls /usr/lib/libjpeg* >/dev/null 2>&1 && echo "-DUSE_JPEG")
CONFIG += -DUSE_OSS
### The C++ compiler and options:
CC ?= gcc
CXX ?= g++
CXXFLAGS ?= -g -O2 -W -Wall -Wextra -Woverloaded-virtual -fPIC
override CXXFLAGS += $(DEFINES) $(INCLUDES)
CFLAGS ?= -g -O2 -W -Wall -Wextra -Winit-self \
-Wdeclaration-after-statement -fPIC
#CFLAGS += -Werror
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`)
-Wdeclaration-after-statement
CXXFLAGS ?= -g -O2 -W -Wall -Wextra -Woverloaded-virtual
### The directory environment:
VDRDIR = ../../..
LIBDIR = ../../lib
TMPDIR = /tmp
VDRDIR ?= ../../..
LIBDIR ?= ../../lib
TMPDIR ?= /tmp
### Make sure that necessary options are included:
@@ -78,11 +57,42 @@ APIVERSION = $(shell sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$$/\1/p' $(VDRDI
ARCHIVE = $(PLUGIN)-$(VERSION)
PACKAGE = vdr-$(ARCHIVE)
### Includes and Defines (add further entries here):
### Includes, Defines and dependencies (add further entries here):
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):
@@ -105,6 +115,8 @@ DEPFILE = .dependencies
$(DEPFILE): Makefile
@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(SRCS) >$@
$(OBJS): Makefile
-include $(DEPFILE)
### Internationalization (I18N):
@@ -137,7 +149,7 @@ i18n: $(I18Nmsgs) $(I18Npot)
### Targets:
libvdr-$(PLUGIN).so: $(OBJS) Makefile
$(CXX) $(CXXFLAGS) -shared $(OBJS) -o $@ $(LDFLAGS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -fPIC $(OBJS) -o $@ $(LIBS)
@cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION)
dist: $(I18Npo) clean
@@ -162,6 +174,6 @@ indent:
indent $$i; unexpand -a $$i > $$i.up; mv $$i.up $$i; \
done
video_test: video.c
$(CC) -DVIDEO_TEST -DVERSION='"$(VERSION)"' $(CFLAGS) $(LDFLAGS) $(LIBS) \
-O0 -g -o $@ $<
video_test: video.c Makefile
$(CC) -DVIDEO_TEST -DVERSION='"$(VERSION)"' $(CFLAGS) $(LDFLAGS) $< $(LIBS) \
-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 VDPAU/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 VDPAU/Opengl
o planned: Video CPU/Xv
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 Audio FFMpeg/Alsa/Analog
o Audio FFMpeg/Alsa/Digital
o Audio FFMpeg/OSS/Analog
o planned: Alsa HDMI/SPDIF Passthrough
o planned: OSS HDMI/SPDIF Passthrough
o planned: atmo light support
To compile you must have the 'requires' installed.
@@ -61,7 +64,7 @@ Install:
http://projects.vdr-developer.org/projects/plg-softhddevice/files
tar vxf vdr-softhddevice-*.tar.bz2
cd vdr-softhddevice
cd softhddevice-*
make VDRDIR=<path-to-your-vdr-files> LIBDIR=.
You can edit Makefile to enable/disable VDPAU / VA-API / Alsa / OSS
@@ -76,6 +79,8 @@ Setup: environment
only if alsa is configured
ALSA_DEVICE=default
alsa PCM device name
ALSA_AC3_DEVICE=
alsa AC3/pass-though device name
ALSA_MIXER=default
alsa control device name
ALSA_MIXER_CHANNEL=PCM
@@ -83,6 +88,8 @@ Setup: environment
only if oss is configured
OSS_AUDIODEV=/dev/dsp
oss dsp device name
OSS_AC3_AUDIODEV=
oss AC3/pass-though device name
OSS_MIXERDEV=/dev/mixer
oss mixer device name
OSS_MIXER_CHANNEL=pcm
@@ -95,34 +102,99 @@ Setup: /etc/vdr/setup.conf
softhddevice.MakePrimary = 1
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
(only 0, 1 supported with vaapi)
softhddevice.SkipChromaDeinterlace = 0
softhddevice.<res>.SkipChromaDeinterlace = 0
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)
softhddevice.Sharpness = 0
softhddevice.<res>.Sharpness = 0
-1000 .. 1000 noise reduction level (0 off, -1000 max blur,
1000 max sharp)
softhddevice.Scaling = 0
0 = normal, 1 = fast, 2 = HQ, 3 = anamorphic
softhddevice.AudioDelay = 0
+n or -n ms
softhddevice.AudioPassthrough = 0
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:
------------
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:
--------

97
Todo
View File

@@ -19,59 +19,69 @@ GNU Affero General Public License for more details.
$Id: $
missing:
video out with xv
video out with opengl
software decoder for xv / opengl
software deinterlace
auto crop
atmolight
zoom/fit-zoom 4:3
multistream handling
disable screensaver
disable window cursor
software deinterlace (yadif, ...)
software decoder with software deinterlace
zoom/fit-zoom 4:3 (SetVideoDisplayFormat, SetVideoFormat?)
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:
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:
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:
intel still has hangups most with 1080i
1080i does no v-sync (workaround written)
osd has sometimes wrong size (workaround written)
1080i does no v-sync (sometimes correct working with vaapi-ext)
OSD has sometimes wrong size (workaround written)
software decoder needs UV swab
libva-vdpau-driver:
G210 osd update too slow (needs hardware problem workaround)
OSD update is too slow
G210/GT520 OSD update too slow (needs hardware problem workaround)
hangup on exit (VaapiDelDecoder -> VaapiCleanup
-> vaDestroyContext -> pthread_rwlock_wrlock)
with auto-crop OSD has wrong position
libva-xvba-driver:
with auto-crop OSD has wrong position
x11:
support resize of x11 window
support fullscreen window
support fullscreen / window toggle
close window should send power button
disable cursor
disable screensaver
audio:
write TS -> PES parser, which feeds audio before the next start packet
Combine alsa+oss ringbuffer code.
Make alsa thread/polled and oss thread/polled output module runtime
selectable.
software volume support
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
remix support of unsupported sample rates
libav supports only resample of mono 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:
alsa oss emulation mixer "pcm" not working
@@ -79,15 +89,34 @@ audio/oss:
HDMI/SPDIF Passthrough:
only AC-3 written
Channels are wrong setup, if changing setting during operation.
support oss pass-through
playback of recording
play back is too fast
pause is not reset, when replay exit
replay/pause need 100% cpu
setup:
Setup of decoder type.
Setup of output type.
Setup of display 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?
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
///
/// Copyright (c) 2009 - 2011 by Johns. All Rights Reserved.
/// Copyright (c) 2009 - 2012 by Johns. All Rights Reserved.
///
/// Contributor(s):
///
@@ -28,21 +28,22 @@
//----------------------------------------------------------------------------
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 uint64_t AudioGetDelay(void); ///< get current audio delay
extern void AudioSetClock(int64_t); ///< set audio clock base
extern int64_t AudioGetClock(); ///< get current audio clock
extern uint64_t AudioGetDelay(void); ///< get current audio delay
extern int AudioSetup(int *, int *); ///< setup audio output
extern void AudioSetVolume(int); ///< set volume
extern int AudioSetup(int *, int *, int); ///< setup audio output
//extern void AudioPlay(void); ///< play 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 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
**
** @returns private decoder pointer for audio/video decoder.
** @returns private decoder pointer for video decoder.
*/
VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder * hw_decoder)
{
VideoDecoder *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;
return decoder;
}
/**
** Deallocate a video decoder context.
**
** @param decoder private video decoder
*/
void CodecVideoDelDecoder(VideoDecoder * decoder)
{
free(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);
if (decoder->VideoCtx) {
Error(_("codec: missing close\n"));
}
//
// ffmpeg compatibility hack
//
@@ -548,19 +561,29 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
video_ctx->frame_number, used);
}
if (used != pkt->size) {
if (used >= 0) {
if (used >= 0 && used < pkt->size) {
// some tv channels, produce this
Debug(4,
"codec: ooops didn't use complete video packet used %d of %d\n",
used, pkt->size);
pkt->data += used;
pkt->size -= used;
pkt->data += used;
goto next_part;
}
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
//----------------------------------------------------------------------------
@@ -603,21 +626,29 @@ static char CodecPassthroughAC3; ///< pass ac3 through
/**
** Allocate a new audio decoder context.
**
** @param hw_decoder video hardware decoder
**
** @returns private decoder pointer for audio/video decoder.
** @returns private decoder pointer for audio decoder.
*/
AudioDecoder *CodecAudioNewDecoder(void)
{
AudioDecoder *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;
}
/**
** Deallocate an audio decoder context.
**
** @param decoder private audio decoder
*/
void CodecAudioDelDecoder(AudioDecoder * decoder)
{
free(decoder);
}
/**
** Open audio decoder.
**
@@ -738,9 +769,11 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
spkt->pts = avpkt->pts;
spkt->dts = avpkt->dts;
#endif
#ifdef DEBUG
if (!audio_decoder->AudioParser) {
Fatal(_("codec: internal error parser freeded while running\n"));
}
#endif
audio_ctx = audio_decoder->AudioCtx;
index = 0;
@@ -782,6 +815,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
if (audio_decoder->SampleRate != audio_ctx->sample_rate
|| audio_decoder->Channels != audio_ctx->channels) {
int err;
int isAC3;
if (audio_decoder->ReSample) {
audio_resample_close(audio_decoder->ReSample);
@@ -795,16 +829,18 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
// SPDIF/HDMI passthrough
if (CodecPassthroughAC3 && audio_ctx->codec_id == CODEC_ID_AC3) {
audio_decoder->HwChannels = 2;
isAC3 = 1;
} else
#endif
{
audio_decoder->HwChannels = audio_ctx->channels;
isAC3 = 0;
}
// channels not support?
if ((err =
AudioSetup(&audio_decoder->HwSampleRate,
&audio_decoder->HwChannels))) {
&audio_decoder->HwChannels, isAC3))) {
Debug(3, "codec/audio: resample %dHz *%d -> %dHz *%d\n",
audio_ctx->sample_rate, audio_ctx->channels,
audio_decoder->HwSampleRate,
@@ -1026,6 +1062,17 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
#endif
/**
** Flush the audio decoder.
**
** @param decoder audio decoder data
*/
void CodecAudioFlushBuffers(AudioDecoder * decoder)
{
// FIXME: reset audio parser
avcodec_flush_buffers(decoder->AudioCtx);
}
//----------------------------------------------------------------------------
// Codec
//----------------------------------------------------------------------------

30
codec.h
View File

@@ -1,7 +1,7 @@
///
/// @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):
///
@@ -40,26 +40,38 @@ typedef struct _audio_decoder_ AudioDecoder;
/// Allocate a new video decoder context.
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);
/// Close video codec
/// Close video codec.
extern void CodecVideoClose(VideoDecoder *);
/// Decode a video packet
extern void CodecVideoDecode(VideoDecoder *, const AVPacket * pkt);
/// Decode a video packet.
extern void CodecVideoDecode(VideoDecoder *, const AVPacket *);
/// Flush video buffers.
extern void CodecVideoFlushBuffers(VideoDecoder *);
/// Allocate a new audio decoder context.
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);
/// Close audio codec
/// Close audio codec.
extern void CodecAudioClose(AudioDecoder *);
/// Decode an audio packet
extern void CodecAudioDecode(AudioDecoder *, const AVPacket * pkt);
/// Decode an audio packet.
extern void CodecAudioDecode(AudioDecoder *, const AVPacket *);
/// Flush audio buffers.
extern void CodecAudioFlushBuffers(AudioDecoder *);
/// Setup and initialize codec module.
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.
*/
#define Fatal(fmt...) do { Error(fmt); exit(-1); } while (0)
#define Fatal(fmt...) do { Error(fmt); abort(); } while (0)
/**
** Show warning.

View File

@@ -35,6 +35,14 @@
#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 "softhddev.h"
@@ -52,18 +60,21 @@ static char ConfigVdpauDecoder = 1; ///< use vdpau decoder, if possible
#define ConfigVdpauDecoder 0 ///< no vdpau decoder configured
#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
//////////////////////////////////////////////////////////////////////////////
static volatile char NewAudioStream; ///< new audio stream
static volatile char SkipAudio; ///< skip audio stream
static AudioDecoder *MyAudioDecoder; ///< audio decoder
static enum CodecID AudioCodecID; ///< current codec id
extern void AudioTest(void); // FIXME:
/**
** mpeg bitrate table.
**
@@ -113,6 +124,8 @@ static const uint16_t SampleRateTable[4] = {
** FrameLengthInBytes = (12 * BitRate / SampleRate + Padding) * 4
** Layer II & III:
** FrameLengthInBytes = 144 * BitRate / SampleRate + Padding
**
** @todo sometimes detects wrong position
*/
static int FindAudioSync(const AVPacket * avpkt)
{
@@ -187,14 +200,21 @@ static int FindAudioSync(const AVPacket * avpkt)
** @param size size of PES packet
** @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)
{
int n;
int osize;
AVPacket avpkt[1];
// channel switch: SetAudioChannelDevice: SetDigitalAudioDevice:
if (VideoFreezed) { // video freezed
return 0;
}
if (SkipAudio || !MyAudioDecoder) { // skip audio
return size;
}
if (NewAudioStream) {
// FIXME: does this clear the audio ringbuffer?
CodecAudioClose(MyAudioDecoder);
@@ -206,7 +226,11 @@ void PlayAudio(const uint8_t * data, int size,
if (size < 9) {
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
@@ -227,38 +251,29 @@ void PlayAudio(const uint8_t * data, int size,
}
}
osize = size;
data += 9 + n;
size -= 9 + n; // skip pes header
if (size <= 0) {
Error(_("[softhddev] invalid audio packet\n"));
return;
return osize;
}
// Detect audio code
// MPEG-PS mp2 MPEG1, MPEG2, AC3
// Syncword - 0x0B77
if (data[0] == 0x0B && data[1] == 0x77) {
if (!MyAudioDecoder) {
MyAudioDecoder = CodecAudioNewDecoder();
AudioCodecID = CODEC_ID_NONE;
}
if (AudioCodecID != CODEC_ID_AC3) {
Debug(3, "[softhddev]%s: AC-3 %d\n", __FUNCTION__, id);
CodecAudioClose(MyAudioDecoder);
CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_AC3);
AudioCodecID = CODEC_ID_AC3;
}
// Syncword - 0xFFFC - 0xFFFF
} else if (data[0] == 0xFF && (data[1] & 0xFC) == 0xFC) {
if (!MyAudioDecoder) {
MyAudioDecoder = CodecAudioNewDecoder();
AudioCodecID = CODEC_ID_NONE;
}
if (AudioCodecID != CODEC_ID_MP2) {
Debug(3, "[softhddev]%s: MP2 %d\n", __FUNCTION__, id);
CodecAudioClose(MyAudioDecoder);
CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_MP2);
AudioCodecID = CODEC_ID_MP2;
}
@@ -273,28 +288,27 @@ void PlayAudio(const uint8_t * data, int size,
avpkt->size = size;
n = FindAudioSync(avpkt);
if (n < 0) {
return;
}
if (!MyAudioDecoder) {
MyAudioDecoder = CodecAudioNewDecoder();
return osize;
}
avpkt->pts = AV_NOPTS_VALUE;
CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_MP2);
AudioCodecID = CODEC_ID_MP2;
data += n;
size -= n;
}
}
// no decoder or codec known
if (!MyAudioDecoder || AudioCodecID == CODEC_ID_NONE) {
return;
// no decoder or codec known
if (AudioCodecID == CODEC_ID_NONE) {
return osize;
}
}
avpkt->data = (void *)data;
avpkt->size = size;
//memset(avpkt->data + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
CodecAudioDecode(MyAudioDecoder, avpkt);
return osize;
}
/**
@@ -302,7 +316,8 @@ void PlayAudio(const uint8_t * data, int size,
*/
void Mute(void)
{
AudioSetVolume(0);
SkipAudio = 1;
//AudioSetVolume(0);
}
/**
@@ -322,7 +337,8 @@ void SetVolumeDevice(int volume)
#include <alsa/iatomic.h> // portable atomic_t
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 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 int VideoPacketWrite; ///< write pointer
static int VideoPacketRead; ///< read pointer
static atomic_t VideoPacketsFilled; ///< how many of the buffer is used
static volatile char VideoFreezed; ///< video freezed
atomic_t VideoPacketsFilled; ///< how many of the buffer is used
static volatile char VideoClearBuffers; ///< clear video buffers
static volatile char SkipVideo; ///< skip video
#ifdef DEBUG
static int VideoMaxPacketSize; ///< biggest used packet buffer
@@ -351,8 +367,6 @@ static void VideoPacketInit(void)
{
int i;
Debug(4, "[softhddev]: %s\n", __FUNCTION__);
for (i = 0; i < VIDEO_PACKET_MAX; ++i) {
AVPacket *avpkt;
@@ -365,6 +379,7 @@ static void VideoPacketInit(void)
}
atomic_set(&VideoPacketsFilled, 0);
VideoPacketRead = VideoPacketWrite = 0;
}
/**
@@ -374,16 +389,10 @@ static void VideoPacketExit(void)
{
int i;
Debug(4, "[softhddev]: %s\n", __FUNCTION__);
atomic_set(&VideoPacketsFilled, 0);
for (i = 0; i < VIDEO_PACKET_MAX; ++i) {
AVPacket *avpkt;
avpkt = &VideoPacketRb[i];
// build a clean ffmpeg av packet
av_free_packet(avpkt);
av_free_packet(&VideoPacketRb[i]);
}
}
@@ -443,10 +452,10 @@ static void VideoNextPacket(int codec_id)
avpkt = &VideoPacketRb[VideoPacketWrite];
if (!avpkt->stream_index) { // ignore empty packets
if (codec_id == CODEC_ID_NONE) {
Debug(3, "video: possible stream change loss\n");
if (codec_id != CODEC_ID_NONE) {
return;
}
return;
Debug(3, "video: possible stream change loss\n");
}
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
memset(avpkt->data + avpkt->stream_index, 0, FF_INPUT_BUFFER_PADDING_SIZE);
avpkt->priv = (void *)(size_t) codec_id;
// advance packet write
VideoPacketWrite = (VideoPacketWrite + 1) % VIDEO_PACKET_MAX;
atomic_inc(&VideoPacketsFilled);
VideoDisplayWakeup();
// intialize next package to use
avpkt = &VideoPacketRb[VideoPacketWrite];
avpkt->stream_index = 0;
avpkt->pts = AV_NOPTS_VALUE;
avpkt->dts = AV_NOPTS_VALUE;
VideoDisplayHandler();
}
/**
@@ -490,6 +500,10 @@ int VideoDecode(void)
}
if (VideoClearBuffers) {
atomic_set(&VideoPacketsFilled, 0);
VideoPacketRead = VideoPacketWrite;
if (MyVideoDecoder) {
CodecVideoFlushBuffers(MyVideoDecoder);
}
VideoClearBuffers = 0;
return 1;
}
@@ -518,8 +532,8 @@ int VideoDecode(void)
CodecVideoClose(MyVideoDecoder);
goto skip;
}
// size can be zero
goto skip;
break;
case CODEC_ID_MPEG2VIDEO:
if (last_codec_id != CODEC_ID_MPEG2VIDEO) {
last_codec_id = CODEC_ID_MPEG2VIDEO;
@@ -560,23 +574,47 @@ int VideoDecode(void)
/**
** Try video start.
**
** Could be called, when already started.
** NOT TRUE: Could be called, when already started.
*/
static void StartVideo(void)
{
VideoInit(X11DisplayName);
if (ConfigFullscreen) {
// FIXME: not good looking, mapped and then resized.
VideoSetFullscreen(1);
}
VideoOsdInit();
if (!MyVideoDecoder) {
VideoHwDecoder *hw_decoder;
if ((hw_decoder = VideoNewHwDecoder())) {
MyVideoDecoder = CodecVideoNewDecoder(hw_decoder);
VideoCodecID = CODEC_ID_NONE;
if ((MyHwDecoder = VideoNewHwDecoder())) {
MyVideoDecoder = CodecVideoNewDecoder(MyHwDecoder);
}
VideoCodecID = CODEC_ID_NONE;
}
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
/**
@@ -627,6 +665,9 @@ static int ValidateMpeg(const uint8_t * data, int size)
** supports complete packets.
** We buffer here until we receive an complete PES Packet, which
** 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)
{
@@ -641,6 +682,12 @@ int PlayVideo(const uint8_t * data, int size)
if (!MyVideoDecoder) { // no x11 video started
return size;
}
if (SkipVideo) { // skip video
return size;
}
if (VideoFreezed) { // video freezed
return 0;
}
if (NewVideoStream) { // channel switched
Debug(3, "video: new stream %d\n", GetMsTicks() - VideoSwitch);
// FIXME: hack to test results
@@ -661,10 +708,10 @@ int PlayVideo(const uint8_t * data, int size)
n = data[8]; // header size
// wrong size
if (size < 9 + n + 4) {
Error(_("[softhddev] invalid video packet\n"));
Error(_("[softhddev] invalid video packet %d bytes\n"), size);
return size;
}
// FIXME: hack to test results
// buffer full: needed for replay
if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
return 0;
}
@@ -698,13 +745,15 @@ int PlayVideo(const uint8_t * data, int size)
}
#endif
}
// FIXME: no valid mpeg2/h264 detection yet
check = data + 9 + n;
if (0) {
printf("%02x: %02x %02x %02x %02x %02x\n", data[6], check[0], check[1],
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
//(data[6] & 0xC0) != 0x80 ||
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");
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 {
// this happens when vdr sends incomplete packets
if (VideoCodecID == CODEC_ID_NONE) {
Debug(3, "video: not detected\n");
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
// waiting for a full complete packages, increases needed delays
VideoEnqueue(pts, check, size - 9 - n);
VideoNextPacket(CODEC_ID_MPEG2VIDEO);
return size;
}
}
@@ -747,6 +811,82 @@ int PlayVideo(const uint8_t * data, int 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)
{
Resume();
if (MyVideoDecoder) {
if (VideoCodecID != CODEC_ID_NONE) {
NewVideoStream = 1;
@@ -761,8 +902,13 @@ void SetPlayMode(void)
}
}
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)
{
int i;
VideoNextPacket(VideoCodecID); // terminate work
VideoClearBuffers = 1;
// 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)
{
VideoFreezed = 0;
SkipAudio = 0;
// FIXME: restart audio
}
@@ -791,16 +945,70 @@ void Freeze(void)
{
VideoFreezed = 1;
// 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.
**
** @param timeout timeout to become ready in ms
*/
int Poll(int timeout)
{
// buffers are too full
if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX / 2) {
Debug(3, "replay: poll %d\n", timeout);
if (timeout) {
// let display thread work
usleep(timeout * 1000);
@@ -810,6 +1018,22 @@ int Poll(int timeout)
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
//////////////////////////////////////////////////////////////////////////////
@@ -819,21 +1043,22 @@ int Poll(int timeout)
*/
void GetOsdSize(int *width, int *height, double *aspect)
{
static char done;
// FIXME: should be configured!
*width = 1920;
*height = 1080;
//*width = 768;
//*height = 576;
#ifdef DEBUG
static int done_width;
static int done_height;
#endif
VideoGetOsdSize(width, 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,
*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.
*/
const char *CommandLineHelp(void)
{
return " -a device\talsa audio device (fe. hw:0,0)\n"
" -d display\tdisplay of x11 server (f.e :0.0)\n"
return " -a device\taudio device (fe. alsa: hw:0,0 oss: /dev/dsp)\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"
" -x\tstart x11 server\n";
" -x\t\tstart x11 server\n";
}
/**
@@ -879,13 +1106,19 @@ int ProcessArgs(int argc, char *const argv[])
// Parse arguments.
//
for (;;) {
switch (getopt(argc, argv, "-a:d:g:x")) {
switch (getopt(argc, argv, "-a:p:d:fg:x")) {
case 'a': // audio device
AudioSetDevice(optarg);
continue;
case 'p': // pass-through audio device
AudioSetDeviceAC3(optarg);
continue;
case 'd': // x11 display name
X11DisplayName = optarg;
continue;
case 'f': // fullscreen mode
ConfigFullscreen = 1;
continue;
case 'g': // geometry
if (VideoSetGeometry(optarg) < 0) {
fprintf(stderr,
@@ -895,7 +1128,7 @@ int ProcessArgs(int argc, char *const argv[])
}
continue;
case 'x': // x11 server
StartX11Server = 1;
ConfigStartX11Server = 1;
continue;
case EOF:
break;
@@ -1015,32 +1248,57 @@ static void StartXServer(void)
*/
void SoftHdDeviceExit(void)
{
// lets hope that vdr does a good thead cleanup
// no it doesn't do a good thread cleanup
if (MyVideoDecoder) {
CodecVideoClose(MyVideoDecoder);
// FIXME: CodecDelVideoDecoder(MyVideoDecoder);
MyVideoDecoder = NULL;
}
// lets hope that vdr does a good thread cleanup
AudioExit();
if (MyAudioDecoder) {
CodecAudioClose(MyAudioDecoder);
// FIXME: CodecDelAudioDecoder(MyAudioDecoder);
CodecAudioDelDecoder(MyAudioDecoder);
MyAudioDecoder = NULL;
}
NewAudioStream = 0;
StopVideo();
VideoOsdExit();
VideoExit();
AudioExit();
CodecExit();
VideoPacketExit();
if (StartX11Server) {
if (ConfigStartX11Server) {
Debug(3, "x-setup: Stop x11 server\n");
if (X11ServerPid) {
int waittime;
int timeout;
pid_t wpid;
int status;
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)
{
if (StartX11Server) {
if (ConfigStartX11Server) {
StartXServer();
}
CodecInit();
// FIXME: AudioInit for HDMI after X11 startup
AudioInit();
if (!StartX11Server) {
MyAudioDecoder = CodecAudioNewDecoder();
AudioCodecID = CODEC_ID_NONE;
if (!ConfigStartX11Server) {
StartVideo();
}
pthread_mutex_init(&SuspendLockMutex, NULL);
}
/**
@@ -1076,7 +1340,81 @@ void Stop(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.
///
/// Copyright (c) 2011 by Johns. All Rights Reserved.
/// Copyright (c) 2011 - 2012 by Johns. All Rights Reserved.
///
/// Contributor(s):
///
@@ -36,7 +36,7 @@ extern "C"
extern void OsdDrawARGB(int, int, int, int, const uint8_t *);
/// 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
extern void Mute(void);
/// C plugin set audio volume
@@ -46,6 +46,8 @@ extern "C"
extern int PlayVideo(const uint8_t *, int);
/// C plugin play TS video packet
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
extern void SetPlayMode(void);
@@ -55,8 +57,12 @@ extern "C"
extern void Play(void);
/// C plugin sets the device into "freeze frame" mode
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
extern int Poll(int);
/// C plugin flush output buffers
extern int Flush(int);
/// C plugin command line help
extern const char *CommandLineHelp(void);
@@ -72,6 +78,10 @@ extern "C"
/// C plugin main thread hook
extern void MainThreadHook(void);
/// Suspend plugin
extern void Suspend(int, int, int);
/// Resume plugin
extern void Resume(void);
#ifdef __cplusplus
}
#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
typedef struct _video_hw_decoder_ VideoHwDecoder;
//----------------------------------------------------------------------------
// Variables
//----------------------------------------------------------------------------
//extern unsigned VideoWindowWidth; ///< current video output width
//extern unsigned VideoWindowHeight; ///< current video output height
//----------------------------------------------------------------------------
// Prototypes
//----------------------------------------------------------------------------
@@ -44,17 +37,20 @@ typedef struct _video_hw_decoder_ VideoHwDecoder;
/// Allocate new video hardware decoder.
extern VideoHwDecoder *VideoNewHwDecoder(void);
/// Deallocate video hardware decoder.
extern void VideoDelHwDecoder(VideoHwDecoder *);
/// Get and allocate a video hardware surface.
extern unsigned VideoGetSurface(VideoHwDecoder *);
/// Release a video hardware surface.
/// Release a video hardware surface
extern void VideoReleaseSurface(VideoHwDecoder *, unsigned);
#ifdef LIBAVCODEC_VERSION
/// Render a ffmpeg frame
/// Render a ffmpeg frame.
extern void VideoRenderFrame(VideoHwDecoder *, AVCodecContext *, AVFrame *);
/// Get ffmpeg vaapi context
/// Get ffmpeg vaapi context.
extern struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder *);
/// Callback to negotiate the PixelFormat.
@@ -62,57 +58,75 @@ extern enum PixelFormat Video_get_format(VideoHwDecoder *, AVCodecContext *,
const enum PixelFormat *);
#ifdef AVCODEC_VDPAU_H
/// Draw vdpau render state
/// Draw vdpau render state.
extern void VideoDrawRenderState(VideoHwDecoder *,
struct vdpau_render_state *);
#endif
#endif
/// Display video TEST
extern void VideoDisplayHandler(void);
/// Poll video events
/// Poll video events.
extern void VideoPollEvent(void);
/// set video mode
//extern void VideoSetVideoMode(int, int, int, int);
/// Wakeup display handler.
extern void VideoDisplayWakeup(void);
/// set video geometry
/// Set video geometry.
extern int VideoSetGeometry(const char *);
/// set deinterlace
extern void VideoSetDeinterlace(int);
/// Set video output position.
extern void VideoSetOutputPosition(int, int, int, int);
/// set skip chroma deinterlace
extern void VideoSetSkipChromaDeinterlace(int);
/// Set video mode.
extern void VideoSetVideoMode(int, int, int, int);
/// set scaling
extern void VideoSetScaling(int);
/// Set video fullscreen mode.
extern void VideoSetFullscreen(int);
/// set denoise
extern void VideoSetDenoise(int);
/// Set deinterlace.
extern void VideoSetDeinterlace(int[]);
/// set sharpen
extern void VideoSetSharpen(int);
/// Set skip chroma deinterlace.
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);
/// Clear OSD
/// Set auto-crop parameters.
extern void VideoSetAutoCrop(int, int, int);
/// Clear OSD.
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 int64_t VideoGetClock(void); ///< get video clock
/// Get OSD size.
extern void VideoGetOsdSize(int *, int *);
extern void VideoOsdInit(void); ///< setup osd
extern void VideoOsdExit(void); ///< cleanup osd
extern int64_t VideoGetClock(void); ///< Get video clock.
extern void VideoInit(const char *); ///< setup video module
extern void VideoExit(void); ///< cleanup and exit video module
/// Grab screen.
extern uint8_t *VideoGrab(int *, int *, int *, int);
extern void VideoFlushInput(void); ///< flush codec input buffers
extern int VideoDecode(void); ///< decode
extern void VideoOsdInit(void); ///< Setup osd.
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.
/// @}