mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 17:16:51 +00:00
Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eed708b9ea | ||
|
|
60a7c36fa6 | ||
|
|
4d74ed1bfc | ||
|
|
c3b924a239 | ||
|
|
f8d198636b | ||
|
|
bcf6ecabc1 | ||
|
|
9063b4e3ff | ||
|
|
e3681812bd | ||
|
|
9d14522121 | ||
| 2dff69dc14 | |||
|
|
5668fa22d2 | ||
|
|
c7cebe1aeb | ||
|
|
037f582bad | ||
|
|
6ca4d3c44f | ||
|
|
2ac2eb39c6 | ||
|
|
217545542d | ||
|
|
5f43803236 | ||
|
|
993d831190 | ||
|
|
1969b2a0a7 | ||
|
|
0fad02285d | ||
|
|
9546233175 | ||
|
|
98d2e0f728 | ||
| 970493fb23 | |||
|
|
329dbc5f07 | ||
|
|
bc8a13e1ef | ||
|
|
bd7e6143c7 | ||
|
|
fa27a1c73a | ||
|
|
e32857a27a | ||
|
|
5ba88bb822 | ||
|
|
0422b6aa5a | ||
|
|
eb024558de | ||
|
|
1593d5dd83 | ||
|
|
09f62307d4 | ||
|
|
87f7aa63cc | ||
|
|
b1ce88923e | ||
|
|
c6e66e0787 | ||
|
|
19d4eeed82 | ||
|
|
9f668c4750 | ||
|
|
e419742a40 | ||
|
|
2cacdc6c90 | ||
|
|
6efe558f78 | ||
|
|
80100299f3 | ||
|
|
5509d768ac | ||
|
|
c0d0a4ae7c | ||
|
|
e619f5c836 | ||
|
|
973fcfe4dd | ||
|
|
eec30433b6 | ||
|
|
baf577aba5 | ||
|
|
81d7ef9755 | ||
|
|
7f7de8678f | ||
|
|
92bb00c410 | ||
|
|
d3b98b90f4 | ||
|
|
788636ee6b | ||
|
|
8e53cbd4a9 | ||
|
|
54661f90ea | ||
|
|
30d8e8afe9 | ||
|
|
19a37bb0bf | ||
|
|
2087968d55 | ||
|
|
d983f780b3 | ||
| 712b2e0de1 | |||
|
|
54f92e67fc | ||
|
|
960cd27ab5 | ||
|
|
3a97700981 | ||
|
|
8d624224e9 | ||
|
|
96eefca699 | ||
|
|
5e005eeff5 | ||
|
|
f6df79e8e6 | ||
|
|
f1551cd321 | ||
|
|
9568c5bd93 | ||
|
|
fd60c3c132 | ||
|
|
7b6d0ecf94 |
114
ChangeLog
114
ChangeLog
@@ -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.
|
||||
|
||||
84
Makefile
84
Makefile
@@ -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 $@
|
||||
|
||||
102
README.txt
102
README.txt
@@ -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
97
Todo
@@ -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
|
||||
|
||||
17
audio.h
17
audio.h
@@ -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
65
codec.c
@@ -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
30
codec.h
@@ -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
2
misc.h
@@ -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.
|
||||
|
||||
514
softhddev.c
514
softhddev.c
@@ -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);
|
||||
}
|
||||
|
||||
14
softhddev.h
14
softhddev.h
@@ -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
|
||||
|
||||
730
softhddevice.cpp
730
softhddevice.cpp
File diff suppressed because it is too large
Load Diff
74
vdr-softhddevice-9999.ebuild
Normal file
74
vdr-softhddevice-9999.ebuild
Normal 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
|
||||
}
|
||||
90
video.h
90
video.h
@@ -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.
|
||||
|
||||
/// @}
|
||||
|
||||
Reference in New Issue
Block a user