mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 17:16:51 +00:00
Compare commits
72 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
cac1e5ce17 | ||
|
|
d6e2d04505 | ||
|
|
45a34a3381 | ||
|
|
92ffd978b0 | ||
|
|
878813f206 | ||
|
|
cb2314837c | ||
|
|
820c246148 | ||
|
|
8dda2a0b8a | ||
|
|
761c06eac1 | ||
|
|
0776bc5ee4 | ||
|
|
aba14813c0 | ||
|
|
0f449c2394 | ||
|
|
9a30d387a1 | ||
|
|
c8e70ec0fe | ||
|
|
5546354cc7 | ||
|
|
442e021d87 | ||
|
|
4301718329 | ||
|
|
3b7688b78b | ||
|
|
d2606a5d5f | ||
|
|
0d63fac2e8 | ||
|
|
c8c760a069 | ||
|
|
0c7170989d | ||
|
|
12bfab3f10 | ||
|
|
bded2ae5df | ||
|
|
1f2d1d235e | ||
|
|
f179264468 | ||
|
|
23300b0383 | ||
|
|
baf10db48e | ||
|
|
7fbfe0396e | ||
|
|
a5c28b9fe2 | ||
|
|
7f0ad63209 | ||
|
|
10ab0274ab | ||
|
|
83413c1adf | ||
|
|
63d18ea488 |
96
ChangeLog
96
ChangeLog
@@ -1,4 +1,100 @@
|
||||
User johns
|
||||
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.
|
||||
Add workaround for alsa not playing hdmi sound.
|
||||
Fix bug: broken device plugin stop and exit.
|
||||
Show transparent cursor to hide cursor.
|
||||
VDPAU: Add color standard support.
|
||||
VDPAU: Add denoise and sharpness support.
|
||||
VDPAU: Add skip chroma deinterlace support.
|
||||
VDPAU: Show OSD only if something is to display, improves performance.
|
||||
VDPAU: Add deinterlace with only 4 surfaces.
|
||||
|
||||
Date: Thu Jan 4 17:00:00 CET 2012
|
||||
|
||||
Release Version 0.1.5
|
||||
Adds OSS mixer support.
|
||||
Fix bug: audio new stream is not thread safe.
|
||||
New audio driver OSS.
|
||||
Fix bug: needed down sampling of 3/5/6 to 2 channels not reported.
|
||||
Search audio sync inside PES packets, for insane dvb streams.
|
||||
Use only the needed number of surfaces.
|
||||
|
||||
Date: Thu Dec 29 19:44:43 CET 2011
|
||||
|
||||
Release Version 0.1.4
|
||||
Prepared vdpau noise reduction support.
|
||||
Vdpau also displays a black surface, when no video is available.
|
||||
Fix bug: CodecVideoDecode destroys avpkt.
|
||||
|
||||
Date: Thu Dec 29 00:55:57 CET 2011
|
||||
|
||||
Release Version 0.1.3
|
||||
Add missing VdpauDecoderDestroy.
|
||||
Cleanup video packet ringbuffer.
|
||||
Allow build without VDPAU.
|
||||
Fix bug: swapped end and start.
|
||||
Support other than "PCM" alsa mixer channels.
|
||||
|
||||
Date: Sat Dec 24 15:26:27 CET 2011
|
||||
|
||||
Release Version 0.1.2
|
||||
|
||||
69
Makefile
69
Makefile
@@ -14,36 +14,30 @@ PLUGIN = softhddevice
|
||||
### The version number of this plugin (taken from the main source file):
|
||||
|
||||
VERSION = $(shell grep 'static const char \*const VERSION *=' $(PLUGIN).cpp | awk '{ print $$7 }' | sed -e 's/[";]//g')
|
||||
GIT_REV = $(shell git describe --always 2>/dev/null)
|
||||
|
||||
### Configuration (edit this for your needs)
|
||||
|
||||
CONFIG := #-DDEBUG
|
||||
CONFIG += $(shell pkg-config --exists libva && echo "-DUSE_VAAPI")
|
||||
#CONFIG += -DHAVE_PTHREAD_NAME
|
||||
CONFIG += $(shell pkg-config --exists vdpau && echo "-DUSE_VDPAU")
|
||||
CONFIG += $(shell pkg-config --exists libva && echo "-DUSE_VAAPI")
|
||||
CONFIG += $(shell pkg-config --exists alsa && echo "-DUSE_ALSA")
|
||||
CONFIG += -DUSE_OSS
|
||||
|
||||
### The C++ compiler and options:
|
||||
|
||||
CC ?= gcc
|
||||
CXX ?= g++
|
||||
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 alsa libavcodec libavformat)
|
||||
override LDFLAGS += -lrt \
|
||||
$(shell pkg-config --libs alsa 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` \
|
||||
`pkg-config --libs vdpau` \
|
||||
`pkg-config --libs libva-x11 libva-glx libva`
|
||||
-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:
|
||||
|
||||
@@ -62,11 +56,40 @@ 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`)
|
||||
|
||||
### The object files (add further files here):
|
||||
|
||||
@@ -89,6 +112,8 @@ DEPFILE = .dependencies
|
||||
$(DEPFILE): Makefile
|
||||
@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(SRCS) >$@
|
||||
|
||||
$(OBJS): Makefile
|
||||
|
||||
-include $(DEPFILE)
|
||||
|
||||
### Internationalization (I18N):
|
||||
@@ -121,7 +146,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
|
||||
@@ -147,5 +172,5 @@ indent:
|
||||
done
|
||||
|
||||
video_test: video.c
|
||||
$(CC) -DVIDEO_TEST -DVERSION='"$(VERSION)"' $(CFLAGS) $(LDFLAGS) $(LIBS) \
|
||||
-O0 -g -o $@ $<
|
||||
$(CC) -DVIDEO_TEST -DVERSION='"$(VERSION)"' $(CFLAGS) $(LDFLAGS) $< $(LIBS) \
|
||||
-o $@
|
||||
|
||||
123
README.txt
123
README.txt
@@ -1,6 +1,6 @@
|
||||
@file README.txt @brief A software HD output device for VDR
|
||||
|
||||
Copyright (c) 2011 by Johns. All Rights Reserved.
|
||||
Copyright (c) 2011, 2012 by Johns. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
@@ -20,14 +20,21 @@ $Id$
|
||||
|
||||
A software and GPU emulated HD output device plugin for VDR.
|
||||
|
||||
o Video VA-API/VA-API
|
||||
o Video VA-API/VA-API (with intel, nvidia and amd backend supported)
|
||||
o Video CPU/VA-API
|
||||
o Video VDPAU/VDPAU
|
||||
o Video CPU/VDPAU
|
||||
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 Audio FFMpeg/Analog
|
||||
o Audio FFMpeg/Digital
|
||||
o planned: HDMI/SPDIF Passthrough
|
||||
o planned: Video XvBA/XvBA
|
||||
o Audio FFMpeg/Alsa/Analog
|
||||
o Audio FFMpeg/Alsa/Digital
|
||||
o Audio FFMpeg/OSS/Analog
|
||||
o Alsa HDMI/SPDIF Passthrough
|
||||
o planned: OSS HDMI/SPDIF Passthrough
|
||||
|
||||
To compile you must have the 'requires' installed.
|
||||
|
||||
@@ -54,34 +61,122 @@ 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=.
|
||||
|
||||
Setup: /etc/vdr/setup.conf
|
||||
You can edit Makefile to enable/disable VDPAU / VA-API / Alsa / OSS
|
||||
support.
|
||||
|
||||
Setup: environment
|
||||
------
|
||||
Following is supported:
|
||||
|
||||
softhddevice.Deinterlace = 0
|
||||
0 = bob, 1 = weave, 2 = temporal, 3 = temporal_spatial, 4 = software
|
||||
(only 0, 1 supported)
|
||||
DISPLAY=:0.0
|
||||
x11 display name
|
||||
only if alsa is configured
|
||||
ALSA_DEVICE=default
|
||||
alsa PCM device name
|
||||
ALSA_MIXER=default
|
||||
alsa control device name
|
||||
ALSA_MIXER_CHANNEL=PCM
|
||||
alsa control channel name
|
||||
only if oss is configured
|
||||
OSS_AUDIODEV=/dev/dsp
|
||||
oss dsp device name
|
||||
OSS_MIXERDEV=/dev/mixer
|
||||
oss mixer device name
|
||||
OSS_MIXER_CHANNEL=pcm
|
||||
oss mixer channel name
|
||||
|
||||
Setup: /etc/vdr/setup.conf
|
||||
------
|
||||
Following is supported:
|
||||
|
||||
softhddevice.MakePrimary = 1
|
||||
0 = no change, 1 make softhddevice primary at start
|
||||
|
||||
softhddevice.Scaling = 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.<res>.SkipChromaDeinterlace = 0
|
||||
0 = disabled, 1 = enabled (for slower cards, poor qualit<69>t)
|
||||
|
||||
softhddevice.<res>.Denoise = 0
|
||||
0 .. 1000 noise reduction level (0 off, 1000 max)
|
||||
|
||||
softhddevice.<res>.Sharpness = 0
|
||||
-1000 .. 1000 noise reduction level (0 off, -1000 max blur,
|
||||
1000 max sharp)
|
||||
|
||||
softhddevice.AudioDelay = 0
|
||||
+n or -n ms
|
||||
|
||||
softhddevice.AudioPassthrough = 0
|
||||
0 = none, 1 = AC-3
|
||||
|
||||
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.
|
||||
|
||||
-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)
|
||||
|
||||
Running:
|
||||
--------
|
||||
|
||||
Click into video window to toggle fullscreen/window mode, only if you
|
||||
have a window manager running.
|
||||
|
||||
Warning:
|
||||
--------
|
||||
libav is not supported, expect many bugs with it.
|
||||
|
||||
Requires:
|
||||
---------
|
||||
media-video/ffmpeg
|
||||
media-video/ffmpeg (version >=0.7)
|
||||
Complete solution to record, convert and stream audio and
|
||||
video. Includes libavcodec.
|
||||
http://ffmpeg.org
|
||||
media-libs/alsa-lib
|
||||
Advanced Linux Sound Architecture Library
|
||||
http://www.alsa-project.org
|
||||
or
|
||||
kernel support for oss/oss4 or alsa oss emulation
|
||||
|
||||
x11-libs/libva
|
||||
Video Acceleration (VA) API for Linux
|
||||
http://www.freedesktop.org/wiki/Software/vaapi
|
||||
@@ -92,7 +187,7 @@ Requires:
|
||||
x11-libs/vdpau-video
|
||||
VDPAU Backend for Video Acceleration (VA) API
|
||||
http://www.freedesktop.org/wiki/Software/vaapi
|
||||
or untested
|
||||
or
|
||||
x11-libs/xvba-video
|
||||
XVBA Backend for Video Acceleration (VA) API
|
||||
http://www.freedesktop.org/wiki/Software/vaapi
|
||||
@@ -104,7 +199,7 @@ Requires:
|
||||
x11-libs/xcb-util-keysyms
|
||||
X C-language Bindings library
|
||||
http://xcb.freedesktop.org
|
||||
Only versions >= 0.3.8 are supported
|
||||
Only versions >= 0.3.8 are good supported
|
||||
|
||||
x11-libs/libX11
|
||||
X.Org X11 library
|
||||
|
||||
111
Todo
111
Todo
@@ -1,52 +1,109 @@
|
||||
@file Todo @brief A software HD output device for VDR
|
||||
|
||||
Copyright (c) 2011, 2012 by Johns. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
License: AGPLv3
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
$Id: $
|
||||
|
||||
missing:
|
||||
video out with xv
|
||||
video out with opengl
|
||||
software decoder for xv / opengl
|
||||
software deinterlace
|
||||
software deinterlace (yadif, ...)
|
||||
software decoder with software deinterlace
|
||||
auto crop
|
||||
atmolight
|
||||
zoom/fit-zoom 4:3
|
||||
multistream handling
|
||||
zoom/fit-zoom 4:3 (SetVideoDisplayFormat, SetVideoFormat?)
|
||||
ITU BT601, ITU BT709 (HD), RGB studio levels (16-235)?
|
||||
suspend output / energie saver: stop audio, stop video, configurable
|
||||
Option deinterlace off / deinterlace force!
|
||||
Make output drivers better modular.
|
||||
|
||||
video:
|
||||
subtitle not cleared
|
||||
subtitle could be asyncron
|
||||
|
||||
vdpau:
|
||||
1080i with temporal spatial too slow GT 520
|
||||
Dr. Dish H264 black picture
|
||||
VdpPreemptionCallback handling
|
||||
hard channel switch
|
||||
suspendoutput didn't show logo or black picture.
|
||||
|
||||
libva:
|
||||
hard channel switch
|
||||
yaepghd (VaapiSetOutputPosition) support
|
||||
can associate ony displayed part of osd
|
||||
|
||||
libva-intel-driver:
|
||||
intel still has hangups most with 1080i
|
||||
1080i does no v-sync (workaround written)
|
||||
osd has sometimes wrong size (workaround written)
|
||||
OSD has sometimes wrong size (workaround written)
|
||||
|
||||
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)
|
||||
|
||||
libva-xvba-driver:
|
||||
mpeg1/2 needs software decoder fixed
|
||||
|
||||
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
|
||||
CodecAudioOpen can fail "can't open audio codec" and does Fatal exit.
|
||||
Combine alsa+oss ringbuffer code.
|
||||
Make alsa thread/polled and oss thread/polled output module runtime
|
||||
selectable.
|
||||
|
||||
audio/alsa:
|
||||
video/audio asyncron
|
||||
random crash in av_parser_parse2, when switching channels
|
||||
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
|
||||
|
||||
playback of >2 channels on 2 channel hardware
|
||||
done?
|
||||
audio/oss:
|
||||
alsa oss emulation mixer "pcm" not working
|
||||
ring buffer overflow with alsa oss emulation
|
||||
|
||||
on some channels it takes long time until sound can be heared.
|
||||
this channels has packet start not at the beginning of the start packet
|
||||
HDMI/SPDIF Passthrough:
|
||||
only AC-3 written
|
||||
Channels are wrong setup, if changing setting during operation.
|
||||
split pcm and ac-3 out into two devices
|
||||
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 menu parameters aren't automatic loaded?
|
||||
Setup parameters are not used until restart.
|
||||
Setup of decoder type.
|
||||
Setup of output type.
|
||||
Setup of display type.
|
||||
Setup 4:3 zoom type
|
||||
Some setup parameters are not used until restart.
|
||||
Can a notice be added to the setup menu?
|
||||
576i, 720p, fake 1080i, 1080i
|
||||
|
||||
unsorted:
|
||||
Menu -> Setup -> Plugins -> skingenigmang -> General
|
||||
-> Try 8bpp single area: no, has missing parts.
|
||||
|
||||
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
|
||||
|
||||
upmix stereo to AC-3
|
||||
|
||||
14
audio.h
14
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,21 @@
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
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 void AudioSetVolume(int); ///< set volume
|
||||
extern int AudioSetup(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 AudioInit(void); ///< setup audio module
|
||||
extern void AudioExit(void); ///< cleanup and exit audio module
|
||||
|
||||
|
||||
354
codec.c
354
codec.c
@@ -1,7 +1,7 @@
|
||||
///
|
||||
/// @file codec.c @brief Codec functions
|
||||
///
|
||||
/// Copyright (c) 2009 - 2011 by Johns. All Rights Reserved.
|
||||
/// Copyright (c) 2009 - 2012 by Johns. All Rights Reserved.
|
||||
///
|
||||
/// Contributor(s):
|
||||
///
|
||||
@@ -26,9 +26,21 @@
|
||||
/// This module contains all decoder and codec functions.
|
||||
/// It is uses ffmpeg (http://ffmpeg.org) as backend.
|
||||
///
|
||||
/// It may work with libav (http://libav.org), but the tests show
|
||||
/// many bugs and incompatiblity in it. Don't use this shit.
|
||||
///
|
||||
|
||||
/**
|
||||
** use av_parser to support insane dvb audio streams.
|
||||
*/
|
||||
#define USE_AVPARSER
|
||||
|
||||
/// compile with passthrough support (experimental)
|
||||
#define USE_PASSTHROUGH
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <endian.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -44,6 +56,11 @@
|
||||
#include <libavcodec/vdpau.h>
|
||||
#endif
|
||||
|
||||
#ifndef __USE_GNU
|
||||
#define __USE_GNU
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef MAIN_H
|
||||
#include MAIN_H
|
||||
#endif
|
||||
@@ -52,6 +69,18 @@
|
||||
#include "audio.h"
|
||||
#include "codec.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Global
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// ffmpeg lock mutex
|
||||
///
|
||||
/// new ffmpeg dislikes simultanous open/close
|
||||
/// this breaks our code, until this is fixed use lock.
|
||||
///
|
||||
static pthread_mutex_t CodecLockMutex;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Video
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -120,6 +149,7 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
|
||||
fmts[1] = PIX_FMT_NONE;
|
||||
Codec_get_format(video_ctx, fmts);
|
||||
}
|
||||
#ifdef USE_VDPAU
|
||||
// VDPAU: PIX_FMT_VDPAU_H264 .. PIX_FMT_VDPAU_VC1 PIX_FMT_VDPAU_MPEG4
|
||||
if ((PIX_FMT_VDPAU_H264 <= video_ctx->pix_fmt
|
||||
&& video_ctx->pix_fmt <= PIX_FMT_VDPAU_VC1)
|
||||
@@ -151,6 +181,7 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
// VA-API:
|
||||
if (video_ctx->hwaccel_context) {
|
||||
unsigned surface;
|
||||
@@ -188,6 +219,7 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
|
||||
*/
|
||||
static void Codec_release_buffer(AVCodecContext * video_ctx, AVFrame * frame)
|
||||
{
|
||||
#ifdef USE_VDPAU
|
||||
// VDPAU: PIX_FMT_VDPAU_H264 .. PIX_FMT_VDPAU_VC1 PIX_FMT_VDPAU_MPEG4
|
||||
if ((PIX_FMT_VDPAU_H264 <= video_ctx->pix_fmt
|
||||
&& video_ctx->pix_fmt <= PIX_FMT_VDPAU_VC1)
|
||||
@@ -209,6 +241,7 @@ static void Codec_release_buffer(AVCodecContext * video_ctx, AVFrame * frame)
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// VA-API
|
||||
if (video_ctx->hwaccel_context) {
|
||||
VideoDecoder *decoder;
|
||||
@@ -252,6 +285,7 @@ static void Codec_draw_horiz_band(AVCodecContext * video_ctx,
|
||||
int type, __attribute__ ((unused))
|
||||
int height)
|
||||
{
|
||||
#ifdef USE_VDPAU
|
||||
// VDPAU: PIX_FMT_VDPAU_H264 .. PIX_FMT_VDPAU_VC1 PIX_FMT_VDPAU_MPEG4
|
||||
if ((PIX_FMT_VDPAU_H264 <= video_ctx->pix_fmt
|
||||
&& video_ctx->pix_fmt <= PIX_FMT_VDPAU_VC1)
|
||||
@@ -269,8 +303,12 @@ static void Codec_draw_horiz_band(AVCodecContext * video_ctx,
|
||||
//Debug(3, "codec: %d references\n", vrs->info.h264.num_ref_frames);
|
||||
|
||||
VideoDrawRenderState(decoder->HwDecoder, vrs);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#else
|
||||
(void)video_ctx;
|
||||
(void)frame;
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -337,25 +375,25 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
|
||||
if (!(decoder->VideoCtx = avcodec_alloc_context3(video_codec))) {
|
||||
Fatal(_("codec: can't allocate video codec context\n"));
|
||||
}
|
||||
// FIXME: for software decoder use all cpus, otherwise 1
|
||||
decoder->VideoCtx->thread_count = 1;
|
||||
pthread_mutex_lock(&CodecLockMutex);
|
||||
// open codec
|
||||
#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,5,0)
|
||||
if (avcodec_open(decoder->VideoCtx, video_codec) < 0) {
|
||||
pthread_mutex_unlock(&CodecLockMutex);
|
||||
Fatal(_("codec: can't open video codec!\n"));
|
||||
}
|
||||
#else
|
||||
if (avcodec_open2(decoder->VideoCtx, video_codec, NULL) < 0) {
|
||||
pthread_mutex_unlock(&CodecLockMutex);
|
||||
Fatal(_("codec: can't open video codec!\n"));
|
||||
}
|
||||
#endif
|
||||
pthread_mutex_unlock(&CodecLockMutex);
|
||||
|
||||
decoder->VideoCtx->opaque = decoder; // our structure
|
||||
|
||||
/*
|
||||
// FIXME: the number of cpu's should be configurable
|
||||
// Today this makes no big sense H264 is broken with current streams.
|
||||
avcodec_thread_init(decoder->VideoCtx, 2); // support dual-cpu's
|
||||
*/
|
||||
|
||||
Debug(3, "codec: video '%s'\n", decoder->VideoCtx->codec_name);
|
||||
if (codec_id == CODEC_ID_H264) {
|
||||
// 2.53 Ghz CPU is too slow for this codec at 1080i
|
||||
@@ -431,7 +469,9 @@ void CodecVideoClose(VideoDecoder * video_decoder)
|
||||
// FIXME: play buffered data
|
||||
av_freep(&video_decoder->Frame);
|
||||
if (video_decoder->VideoCtx) {
|
||||
pthread_mutex_lock(&CodecLockMutex);
|
||||
avcodec_close(video_decoder->VideoCtx);
|
||||
pthread_mutex_unlock(&CodecLockMutex);
|
||||
av_freep(&video_decoder->VideoCtx);
|
||||
}
|
||||
}
|
||||
@@ -441,9 +481,9 @@ void CodecVideoClose(VideoDecoder * video_decoder)
|
||||
/**
|
||||
** Display pts...
|
||||
**
|
||||
** ffmpeg 0.9 pts always AV_NOPTS_VALUE
|
||||
** ffmpeg 0.9 pkt_pts nice monotonic (only with HD)
|
||||
** ffmpeg 0.9 pkt_dts wild jumping -160 - 340 ms
|
||||
** ffmpeg-0.9 pts always AV_NOPTS_VALUE
|
||||
** ffmpeg-0.9 pkt_pts nice monotonic (only with HD)
|
||||
** ffmpeg-0.9 pkt_dts wild jumping -160 - 340 ms
|
||||
**
|
||||
** libav 0.8_pre20111116 pts always AV_NOPTS_VALUE
|
||||
** libav 0.8_pre20111116 pkt_pts always 0 (could be fixed?)
|
||||
@@ -478,32 +518,28 @@ void DisplayPts(AVCodecContext * video_ctx, AVFrame * frame)
|
||||
**
|
||||
** @param decoder video decoder data
|
||||
** @param avpkt video packet
|
||||
**
|
||||
** @note this version destroys avpkt!!
|
||||
*/
|
||||
void CodecVideoDecode(VideoDecoder * decoder, AVPacket * avpkt)
|
||||
void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
|
||||
{
|
||||
AVCodecContext *video_ctx;
|
||||
AVFrame *frame;
|
||||
int used;
|
||||
int got_frame;
|
||||
AVPacket pkt[1];
|
||||
|
||||
video_ctx = decoder->VideoCtx;
|
||||
frame = decoder->Frame;
|
||||
*pkt = *avpkt; // use copy
|
||||
|
||||
next_part:
|
||||
// FIXME: this function can crash with bad packets
|
||||
used = avcodec_decode_video2(video_ctx, frame, &got_frame, avpkt);
|
||||
Debug(4, "%s: %p %d -> %d %d\n", __FUNCTION__, avpkt->data, avpkt->size,
|
||||
used, got_frame);
|
||||
used = avcodec_decode_video2(video_ctx, frame, &got_frame, pkt);
|
||||
Debug(4, "%s: %p %d -> %d %d\n", __FUNCTION__, pkt->data, pkt->size, used,
|
||||
got_frame);
|
||||
|
||||
if (got_frame) { // frame completed
|
||||
//DisplayPts(video_ctx, frame);
|
||||
if (video_ctx->hwaccel_context) {
|
||||
VideoRenderFrame(decoder->HwDecoder, video_ctx, frame);
|
||||
} else {
|
||||
VideoRenderFrame(decoder->HwDecoder, video_ctx, frame);
|
||||
}
|
||||
} else {
|
||||
// some frames are needed for references, interlaced frames ...
|
||||
// could happen with h264 dvb streams, just drop data.
|
||||
@@ -511,23 +547,28 @@ void CodecVideoDecode(VideoDecoder * decoder, AVPacket * avpkt)
|
||||
Debug(4, "codec: %8d incomplete interlaced frame %d bytes used\n",
|
||||
video_ctx->frame_number, used);
|
||||
}
|
||||
if (used != avpkt->size) {
|
||||
if (used == 0) {
|
||||
goto next_part;
|
||||
}
|
||||
if (used != pkt->size) {
|
||||
if (used >= 0) {
|
||||
// some tv channels, produce this
|
||||
Debug(4,
|
||||
"codec: ooops didn't use complete video packet used %d of %d\n",
|
||||
used, avpkt->size);
|
||||
avpkt->data += used;
|
||||
avpkt->size -= used;
|
||||
used, pkt->size);
|
||||
pkt->data += used;
|
||||
pkt->size -= used;
|
||||
goto next_part;
|
||||
}
|
||||
Debug(3, "codec: bad frame %d\n", used);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
/**
|
||||
** Flush the video decoder.
|
||||
**
|
||||
** @param decoder video decoder data
|
||||
*/
|
||||
void CodecVideoFlushBuffers(VideoDecoder * decoder)
|
||||
{
|
||||
avcodec_flush_buffers(decoder->VideoCtx);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -549,17 +590,26 @@ struct _audio_decoder_
|
||||
AVCodec *AudioCodec; ///< audio codec
|
||||
AVCodecContext *AudioCtx; ///< audio codec context
|
||||
|
||||
/// audio parser to support wired dvb streaks
|
||||
/// audio parser to support insane dvb streaks
|
||||
AVCodecParserContext *AudioParser;
|
||||
int SampleRate; ///< current sample rate
|
||||
int Channels; ///< current channels
|
||||
int SampleRate; ///< current stream sample rate
|
||||
int Channels; ///< current stream channels
|
||||
|
||||
int HwSampleRate; ///< hw sample rate
|
||||
int HwChannels; ///< hw channels
|
||||
|
||||
ReSampleContext *ReSample; ///< audio resampling context
|
||||
|
||||
};
|
||||
|
||||
#ifdef USE_PASSTHROUGH
|
||||
//static char CodecPassthroughPCM; ///< pass pcm through (unsupported)
|
||||
static char CodecPassthroughAC3; ///< pass ac3 through
|
||||
|
||||
//static char CodecPassthroughDTS; ///< pass dts through (unsupported)
|
||||
//static char CodecPassthroughMPA; ///< pass mpa through (unsupported)
|
||||
#endif
|
||||
|
||||
/**
|
||||
** Allocate a new audio decoder context.
|
||||
**
|
||||
@@ -601,16 +651,20 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
|
||||
if (!(audio_decoder->AudioCtx = avcodec_alloc_context3(audio_codec))) {
|
||||
Fatal(_("codec: can't allocate audio codec context\n"));
|
||||
}
|
||||
pthread_mutex_lock(&CodecLockMutex);
|
||||
// open codec
|
||||
#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,5,0)
|
||||
if (avcodec_open(audio_decoder->AudioCtx, audio_codec) < 0) {
|
||||
pthread_mutex_unlock(&CodecLockMutex);
|
||||
Fatal(_("codec: can't open audio codec\n"));
|
||||
}
|
||||
#else
|
||||
if (avcodec_open2(audio_decoder->AudioCtx, audio_codec, NULL) < 0) {
|
||||
pthread_mutex_unlock(&CodecLockMutex);
|
||||
Fatal(_("codec: can't open audio codec\n"));
|
||||
}
|
||||
#endif
|
||||
pthread_mutex_unlock(&CodecLockMutex);
|
||||
Debug(3, "codec: audio '%s'\n", audio_decoder->AudioCtx->codec_name);
|
||||
|
||||
if (audio_codec->capabilities & CODEC_CAP_TRUNCATED) {
|
||||
@@ -645,31 +699,44 @@ void CodecAudioClose(AudioDecoder * audio_decoder)
|
||||
audio_decoder->AudioParser = NULL;
|
||||
}
|
||||
if (audio_decoder->AudioCtx) {
|
||||
pthread_mutex_lock(&CodecLockMutex);
|
||||
avcodec_close(audio_decoder->AudioCtx);
|
||||
pthread_mutex_unlock(&CodecLockMutex);
|
||||
av_freep(&audio_decoder->AudioCtx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Set audio pass-through.
|
||||
*/
|
||||
void CodecSetAudioPassthrough(int mask)
|
||||
{
|
||||
#ifdef USE_PASSTHROUGH
|
||||
CodecPassthroughAC3 = mask & 1 ? 1 : 0;
|
||||
#endif
|
||||
// FIXME: must update audio decoder (nr. of channels wrong)
|
||||
(void)mask;
|
||||
}
|
||||
|
||||
#ifdef USE_AVPARSER
|
||||
|
||||
/**
|
||||
** Decode an audio packet.
|
||||
**
|
||||
** PTS must be handled self.
|
||||
**
|
||||
** @param audio_decoder audio_Decoder data
|
||||
** @param audio_decoder audio decoder data
|
||||
** @param avpkt audio packet
|
||||
*/
|
||||
void CodecAudioDecode(AudioDecoder * audio_decoder, AVPacket * avpkt)
|
||||
void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
||||
{
|
||||
int16_t buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 +
|
||||
FF_INPUT_BUFFER_PADDING_SIZE] __attribute__ ((aligned(16)));
|
||||
AVCodecContext *audio_ctx;
|
||||
int index;
|
||||
|
||||
if (!audio_decoder->AudioParser) {
|
||||
Fatal(_("codec: internal error parser freeded while running\n"));
|
||||
}
|
||||
#define spkt avpkt
|
||||
#if 0 // didn't fix crash in av_parser_parse2
|
||||
//#define spkt avpkt
|
||||
#if 1 // didn't fix crash in av_parser_parse2
|
||||
AVPacket spkt[1];
|
||||
|
||||
// av_new_packet reserves FF_INPUT_BUFFER_PADDING_SIZE and clears it
|
||||
@@ -681,6 +748,11 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, 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;
|
||||
@@ -695,6 +767,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, AVPacket * avpkt)
|
||||
!index ? (uint64_t) spkt->pts : AV_NOPTS_VALUE,
|
||||
!index ? (uint64_t) spkt->dts : AV_NOPTS_VALUE, -1);
|
||||
|
||||
// FIXME: make this a function for both #ifdef cases
|
||||
if (dpkt->size) {
|
||||
int buf_sz;
|
||||
|
||||
@@ -703,7 +776,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, AVPacket * avpkt)
|
||||
buf_sz = sizeof(buf);
|
||||
l = avcodec_decode_audio3(audio_ctx, buf, &buf_sz, dpkt);
|
||||
if (l < 0) { // no audio frame could be decompressed
|
||||
Error(_("codec: error audio data\n"));
|
||||
Error(_("codec: error audio data at %d\n"), index);
|
||||
break;
|
||||
}
|
||||
#ifdef notyetFF_API_OLD_DECODE_AUDIO
|
||||
@@ -730,14 +803,24 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, AVPacket * avpkt)
|
||||
audio_decoder->SampleRate = audio_ctx->sample_rate;
|
||||
audio_decoder->HwSampleRate = audio_ctx->sample_rate;
|
||||
audio_decoder->Channels = audio_ctx->channels;
|
||||
#ifdef USE_PASSTHROUGH
|
||||
// SPDIF/HDMI passthrough
|
||||
if (CodecPassthroughAC3 && audio_ctx->codec_id == CODEC_ID_AC3) {
|
||||
audio_decoder->HwChannels = 2;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
audio_decoder->HwChannels = audio_ctx->channels;
|
||||
}
|
||||
|
||||
// channels not support?
|
||||
if ((err =
|
||||
AudioSetup(&audio_decoder->HwSampleRate,
|
||||
&audio_decoder->HwChannels))) {
|
||||
Debug(3, "codec/audio: resample %d -> %d\n",
|
||||
audio_ctx->channels, audio_decoder->HwChannels);
|
||||
Debug(3, "codec/audio: resample %dHz *%d -> %dHz *%d\n",
|
||||
audio_ctx->sample_rate, audio_ctx->channels,
|
||||
audio_decoder->HwSampleRate,
|
||||
audio_decoder->HwChannels);
|
||||
|
||||
if (err == 1) {
|
||||
audio_decoder->ReSample =
|
||||
@@ -745,10 +828,18 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, AVPacket * avpkt)
|
||||
audio_ctx->channels, audio_decoder->HwSampleRate,
|
||||
audio_ctx->sample_rate, audio_ctx->sample_fmt,
|
||||
audio_ctx->sample_fmt, 16, 10, 0, 0.8);
|
||||
// libav-0.8_pre didn't support 6 -> 2 channels
|
||||
if (!audio_decoder->ReSample) {
|
||||
Error(_("codec/audio: resample setup error\n"));
|
||||
audio_decoder->HwChannels = 0;
|
||||
audio_decoder->HwSampleRate = 0;
|
||||
}
|
||||
} else {
|
||||
Debug(3, "codec/audio: audio setup error\n");
|
||||
// FIXME: handle errors
|
||||
audio_decoder->HwChannels = 0;
|
||||
audio_decoder->HwSampleRate = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -761,11 +852,101 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, AVPacket * avpkt)
|
||||
__attribute__ ((aligned(16)));
|
||||
int outlen;
|
||||
|
||||
// FIXME: libav-0.7.2 crash here
|
||||
outlen =
|
||||
audio_resample(audio_decoder->ReSample, outbuf, buf,
|
||||
buf_sz);
|
||||
#ifdef DEBUG
|
||||
if (outlen != buf_sz) {
|
||||
Debug(3, "codec/audio: possible fixed ffmpeg\n");
|
||||
}
|
||||
#endif
|
||||
if (outlen) {
|
||||
// outlen seems to be wrong in ffmpeg-0.9
|
||||
outlen /= audio_decoder->Channels *
|
||||
av_get_bytes_per_sample(audio_ctx->sample_fmt);
|
||||
outlen *=
|
||||
audio_decoder->HwChannels *
|
||||
av_get_bytes_per_sample(audio_ctx->sample_fmt);
|
||||
Debug(4, "codec/audio: %d -> %d\n", buf_sz, outlen);
|
||||
AudioEnqueue(outbuf, outlen);
|
||||
}
|
||||
} else {
|
||||
#ifdef USE_PASSTHROUGH
|
||||
// SPDIF/HDMI passthrough
|
||||
if (CodecPassthroughAC3
|
||||
&& audio_ctx->codec_id == CODEC_ID_AC3) {
|
||||
// build SPDIF header and append A52 audio to it
|
||||
// dpkt is the original data
|
||||
buf_sz = 6144;
|
||||
if (buf_sz < dpkt->size + 8) {
|
||||
Error(_
|
||||
("codec/audio: decoded data smaller than encoded\n"));
|
||||
break;
|
||||
}
|
||||
// copy original data for output
|
||||
// FIXME: not 100% sure, if endian is correct
|
||||
buf[0] = htole16(0xF872); // iec 61937 sync word
|
||||
buf[1] = htole16(0x4E1F);
|
||||
buf[2] = htole16(0x01 | (dpkt->data[5] & 0x07) << 8);
|
||||
buf[3] = htole16(dpkt->size * 8);
|
||||
swab(dpkt->data, buf + 4, dpkt->size);
|
||||
memset(buf + 4 + dpkt->size / 2, 0,
|
||||
buf_sz - 8 - dpkt->size);
|
||||
}
|
||||
#if 0
|
||||
//
|
||||
// old experimental code
|
||||
//
|
||||
if (1) {
|
||||
// FIXME: need to detect dts
|
||||
// copy original data for output
|
||||
// FIXME: buf is sint
|
||||
buf[0] = 0x72;
|
||||
buf[1] = 0xF8;
|
||||
buf[2] = 0x1F;
|
||||
buf[3] = 0x4E;
|
||||
buf[4] = 0x00;
|
||||
switch (dpkt->size) {
|
||||
case 512:
|
||||
buf[5] = 0x0B;
|
||||
break;
|
||||
case 1024:
|
||||
buf[5] = 0x0C;
|
||||
break;
|
||||
case 2048:
|
||||
buf[5] = 0x0D;
|
||||
break;
|
||||
default:
|
||||
Debug(3,
|
||||
"codec/audio: dts sample burst not supported\n");
|
||||
buf[5] = 0x00;
|
||||
break;
|
||||
}
|
||||
buf[6] = (dpkt->size * 8);
|
||||
buf[7] = (dpkt->size * 8) >> 8;
|
||||
//buf[8] = 0x0B;
|
||||
//buf[9] = 0x77;
|
||||
//printf("%x %x\n", dpkt->data[0],dpkt->data[1]);
|
||||
// swab?
|
||||
memcpy(buf + 8, dpkt->data, dpkt->size);
|
||||
memset(buf + 8 + dpkt->size, 0,
|
||||
buf_sz - 8 - dpkt->size);
|
||||
} else if (1) {
|
||||
// FIXME: need to detect mp2
|
||||
// FIXME: mp2 passthrough
|
||||
// see softhddev.c version/layer
|
||||
// 0x04 mpeg1 layer1
|
||||
// 0x05 mpeg1 layer23
|
||||
// 0x06 mpeg2 ext
|
||||
// 0x07 mpeg2.5 layer 1
|
||||
// 0x08 mpeg2.5 layer 2
|
||||
// 0x09 mpeg2.5 layer 3
|
||||
}
|
||||
// DTS HD?
|
||||
// True HD?
|
||||
#endif
|
||||
#endif
|
||||
AudioEnqueue(buf, buf_sz);
|
||||
}
|
||||
}
|
||||
@@ -778,11 +959,96 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, AVPacket * avpkt)
|
||||
index += n;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
// or av_free_packet, make no difference here
|
||||
av_destruct_packet(spkt);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
** Decode an audio packet.
|
||||
**
|
||||
** PTS must be handled self.
|
||||
**
|
||||
** @param audio_decoder audio decoder data
|
||||
** @param avpkt audio packet
|
||||
*/
|
||||
void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
||||
{
|
||||
int16_t buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 +
|
||||
FF_INPUT_BUFFER_PADDING_SIZE] __attribute__ ((aligned(16)));
|
||||
AVCodecContext *audio_ctx;
|
||||
int index;
|
||||
|
||||
//#define spkt avpkt
|
||||
#if 1
|
||||
AVPacket spkt[1];
|
||||
|
||||
// av_new_packet reserves FF_INPUT_BUFFER_PADDING_SIZE and clears it
|
||||
if (av_new_packet(spkt, avpkt->size)) {
|
||||
Error(_("codec: out of memory\n"));
|
||||
return;
|
||||
}
|
||||
memcpy(spkt->data, avpkt->data, avpkt->size);
|
||||
spkt->pts = avpkt->pts;
|
||||
spkt->dts = avpkt->dts;
|
||||
#endif
|
||||
audio_ctx = audio_decoder->AudioCtx;
|
||||
index = 0;
|
||||
while (spkt->size > index) {
|
||||
int n;
|
||||
int buf_sz;
|
||||
AVPacket dpkt[1];
|
||||
|
||||
av_init_packet(dpkt);
|
||||
dpkt->data = spkt->data + index;
|
||||
dpkt->size = spkt->size - index;
|
||||
|
||||
buf_sz = sizeof(buf);
|
||||
n = avcodec_decode_audio3(audio_ctx, buf, &buf_sz, dpkt);
|
||||
if (n < 0) { // no audio frame could be decompressed
|
||||
Error(_("codec: error audio data at %d\n"), index);
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
Debug(4, "codec/audio: -> %d\n", buf_sz);
|
||||
if ((unsigned)buf_sz > sizeof(buf)) {
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
#ifdef notyetFF_API_OLD_DECODE_AUDIO
|
||||
// FIXME: ffmpeg git comeing
|
||||
int got_frame;
|
||||
|
||||
avcodec_decode_audio4(audio_ctx, frame, &got_frame, dpkt);
|
||||
#else
|
||||
#endif
|
||||
// FIXME: see above, old code removed
|
||||
|
||||
index += n;
|
||||
}
|
||||
|
||||
#if 1
|
||||
// or av_free_packet, make no difference here
|
||||
av_destruct_packet(spkt);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
** Flush the audio decoder.
|
||||
**
|
||||
** @param decoder audio decoder data
|
||||
*/
|
||||
void CodecAudioFlushBuffers(AudioDecoder * decoder)
|
||||
{
|
||||
// FIXME: reset audio parser
|
||||
avcodec_flush_buffers(decoder->AudioCtx);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Codec
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -802,6 +1068,7 @@ static void CodecNoopCallback( __attribute__ ((unused))
|
||||
*/
|
||||
void CodecInit(void)
|
||||
{
|
||||
pthread_mutex_init(&CodecLockMutex, NULL);
|
||||
#ifndef DEBUG
|
||||
// disable display ffmpeg error messages
|
||||
av_log_set_callback(CodecNoopCallback);
|
||||
@@ -816,4 +1083,5 @@ void CodecInit(void)
|
||||
*/
|
||||
void CodecExit(void)
|
||||
{
|
||||
pthread_mutex_destroy(&CodecLockMutex);
|
||||
}
|
||||
|
||||
24
codec.h
24
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,32 @@ typedef struct _audio_decoder_ AudioDecoder;
|
||||
/// Allocate a new video decoder context.
|
||||
extern VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder *);
|
||||
|
||||
/// Open video codec
|
||||
/// 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 *, 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
|
||||
/// 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 *, 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);
|
||||
|
||||
27
misc.h
27
misc.h
@@ -1,7 +1,7 @@
|
||||
///
|
||||
/// @file misc.h @brief Misc function header file
|
||||
///
|
||||
/// Copyright (c) 2009 - 2011 by Lutz Sammer. All Rights Reserved.
|
||||
/// Copyright (c) 2009 - 2012 by Lutz Sammer. All Rights Reserved.
|
||||
///
|
||||
/// Contributor(s):
|
||||
/// Copied from uwm.
|
||||
@@ -46,24 +46,28 @@ extern int SysLogLevel; ///< how much information wanted
|
||||
// Prototypes
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline void Debug(const int, const char *format, ...)
|
||||
static inline void Syslog(const int, const char *format, ...)
|
||||
__attribute__ ((format(printf, 2, 3)));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Inlines
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DebugLevel 4 /// private debug level
|
||||
#else
|
||||
#define DebugLevel 0 /// private debug level
|
||||
#endif
|
||||
|
||||
/**
|
||||
** Debug output function.
|
||||
** Syslog output function.
|
||||
**
|
||||
** - 0 fatal errors and errors
|
||||
** - 1 warnings
|
||||
** - 2 info
|
||||
** - 3 important debug and fixme's
|
||||
*/
|
||||
static inline void Debug(const int level, const char *format, ...)
|
||||
static inline void Syslog(const int level, const char *format, ...)
|
||||
{
|
||||
if (SysLogLevel > level || DebugLevel > level) {
|
||||
va_list ap;
|
||||
@@ -77,7 +81,7 @@ static inline void Debug(const int level, const char *format, ...)
|
||||
/**
|
||||
** Show error.
|
||||
*/
|
||||
#define Error(fmt...) Debug(0, fmt)
|
||||
#define Error(fmt...) Syslog(0, fmt)
|
||||
|
||||
/**
|
||||
** Show fatal error.
|
||||
@@ -87,12 +91,21 @@ static inline void Debug(const int level, const char *format, ...)
|
||||
/**
|
||||
** Show warning.
|
||||
*/
|
||||
#define Warning(fmt...) Debug(1, fmt)
|
||||
#define Warning(fmt...) Syslog(1, fmt)
|
||||
|
||||
/**
|
||||
** Show info.
|
||||
*/
|
||||
#define Info(fmt...) Debug(2, fmt)
|
||||
#define Info(fmt...) Syslog(2, fmt)
|
||||
|
||||
/**
|
||||
** Show debug.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
#define Debug(level, fmt...) Syslog(level, fmt)
|
||||
#else
|
||||
#define Debug(level, fmt...) /* disabled */
|
||||
#endif
|
||||
|
||||
/**
|
||||
** Get ticks in ms.
|
||||
|
||||
616
softhddev.c
616
softhddev.c
@@ -1,7 +1,7 @@
|
||||
///
|
||||
/// @file softhddev.c @brief A software HD device plugin for VDR.
|
||||
///
|
||||
/// Copyright (c) 2011 by Johns. All Rights Reserved.
|
||||
/// Copyright (c) 2011, 2012 by Johns. All Rights Reserved.
|
||||
///
|
||||
/// Contributor(s):
|
||||
///
|
||||
@@ -35,6 +35,11 @@
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
|
||||
#ifndef __USE_GNU
|
||||
#define __USE_GNU
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "softhddev.h"
|
||||
|
||||
@@ -42,18 +47,148 @@
|
||||
#include "video.h"
|
||||
#include "codec.h"
|
||||
|
||||
static char BrokenThreadsAndPlugins; ///< broken vdr threads and plugins
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Variables
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef USE_VDPAU
|
||||
static char ConfigVdpauDecoder = 1; ///< use vdpau decoder, if possible
|
||||
#else
|
||||
#define ConfigVdpauDecoder 0 ///< no vdpau decoder configured
|
||||
#endif
|
||||
|
||||
static char ConfigFullscreen; ///< fullscreen modus
|
||||
static char ConfigSuspendClose = 1; ///< suspend should close devices
|
||||
static char ConfigSuspendX11 = 1; ///< suspend should stop x11
|
||||
|
||||
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.
|
||||
**
|
||||
** BitRateTable[Version][Layer][Index]
|
||||
*/
|
||||
static const uint16_t BitRateTable[2][4][16] = {
|
||||
// MPEG Version 1
|
||||
{{},
|
||||
{0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,
|
||||
0},
|
||||
{0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0},
|
||||
{0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}},
|
||||
// MPEG Version 2 & 2.5
|
||||
{{},
|
||||
{0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0},
|
||||
{0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0},
|
||||
{0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
** mpeg samperate table.
|
||||
*/
|
||||
static const uint16_t SampleRateTable[4] = {
|
||||
44100, 48000, 32000, 0
|
||||
};
|
||||
|
||||
/**
|
||||
** Find sync in audio packet.
|
||||
**
|
||||
** @param avpkt audio packet
|
||||
**
|
||||
** From: http://www.mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm
|
||||
**
|
||||
** AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM
|
||||
**
|
||||
** o a 11x frame sync
|
||||
** o b 2x mpeg audio version (2.5, reserved, 2, 1)
|
||||
** o c 2x layer (reserved, III, II, I)
|
||||
** o e 2x BitRate index
|
||||
** o f 2x SampleRate index
|
||||
** o g 1x Paddding bit
|
||||
** o .. doesn't care
|
||||
**
|
||||
** frame length:
|
||||
** Layer I:
|
||||
** FrameLengthInBytes = (12 * BitRate / SampleRate + Padding) * 4
|
||||
** Layer II & III:
|
||||
** FrameLengthInBytes = 144 * BitRate / SampleRate + Padding
|
||||
*/
|
||||
static int FindAudioSync(const AVPacket * avpkt)
|
||||
{
|
||||
int i;
|
||||
const uint8_t *data;
|
||||
|
||||
i = 0;
|
||||
data = avpkt->data;
|
||||
while (i < avpkt->size - 4) {
|
||||
if (data[i] == 0xFF && (data[i + 1] & 0xFC) == 0xFC) {
|
||||
int mpeg2;
|
||||
int mpeg25;
|
||||
int layer;
|
||||
int bit_rate_index;
|
||||
int sample_rate_index;
|
||||
int padding;
|
||||
int bit_rate;
|
||||
int sample_rate;
|
||||
int frame_size;
|
||||
|
||||
mpeg2 = !(data[i + 1] & 0x08) && (data[i + 1] & 0x10);
|
||||
mpeg25 = !(data[i + 1] & 0x08) && !(data[i + 1] & 0x10);
|
||||
layer = 4 - ((data[i + 1] >> 1) & 0x03);
|
||||
bit_rate_index = (data[i + 2] >> 4) & 0x0F;
|
||||
sample_rate_index = (data[i + 2] >> 2) & 0x03;
|
||||
padding = (data[i + 2] >> 1) & 0x01;
|
||||
|
||||
sample_rate = SampleRateTable[sample_rate_index];
|
||||
if (!sample_rate) { // no valid sample rate try next
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
sample_rate >>= mpeg2; // mpeg 2 half rate
|
||||
sample_rate >>= mpeg25; // mpeg 2.5 quarter rate
|
||||
|
||||
bit_rate = BitRateTable[mpeg2 | mpeg25][layer][bit_rate_index];
|
||||
bit_rate *= 1000;
|
||||
switch (layer) {
|
||||
case 1:
|
||||
frame_size = (12 * bit_rate) / sample_rate;
|
||||
frame_size = (frame_size + padding) * 4;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
default:
|
||||
frame_size = (144 * bit_rate) / sample_rate;
|
||||
frame_size = frame_size + padding;
|
||||
break;
|
||||
}
|
||||
Debug(3,
|
||||
"audio: mpeg%s layer%d bitrate=%d samplerate=%d %d bytes\n",
|
||||
mpeg25 ? "2.5" : mpeg2 ? "2" : "1", layer, bit_rate,
|
||||
sample_rate, frame_size);
|
||||
if (i + frame_size < avpkt->size - 4) {
|
||||
if (data[i + frame_size] == 0xFF
|
||||
&& (data[i + frame_size + 1] & 0xFC) == 0xFC) {
|
||||
Debug(3, "audio: mpeg1/2 found at %d\n", i);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
// no valid frame size or no continuation, try next
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
** Play audio packet.
|
||||
@@ -62,25 +197,37 @@ extern void AudioTest(void); // FIXME:
|
||||
** @param size size of PES packet
|
||||
** @param id PES packet type
|
||||
*/
|
||||
void PlayAudio(const uint8_t * data, int size, uint8_t id)
|
||||
int PlayAudio(const uint8_t * data, int size,
|
||||
__attribute__ ((unused)) uint8_t id)
|
||||
{
|
||||
int n;
|
||||
int osize;
|
||||
AVPacket avpkt[1];
|
||||
|
||||
if (BrokenThreadsAndPlugins) {
|
||||
return;
|
||||
// channel switch: SetAudioChannelDevice: SetDigitalAudioDevice:
|
||||
|
||||
if (VideoFreezed) { // video freezed
|
||||
return 0;
|
||||
}
|
||||
if (NewAudioStream) {
|
||||
// FIXME: does this clear the audio ringbuffer?
|
||||
CodecAudioClose(MyAudioDecoder);
|
||||
AudioCodecID = CODEC_ID_NONE;
|
||||
NewAudioStream = 0;
|
||||
}
|
||||
if (SkipAudio) { // skip audio
|
||||
return size;
|
||||
}
|
||||
// PES header 0x00 0x00 0x01 ID
|
||||
// ID 0xBD 0xC0-0xCF
|
||||
|
||||
// channel switch: SetAudioChannelDevice: SetDigitalAudioDevice:
|
||||
|
||||
// Detect audio code
|
||||
// MPEG-PS mp2 MPEG1, MPEG2, AC3
|
||||
|
||||
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
|
||||
@@ -101,12 +248,16 @@ void PlayAudio(const uint8_t * data, int size, uint8_t id)
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -137,21 +288,37 @@ void PlayAudio(const uint8_t * data, int size, uint8_t id)
|
||||
// no start package
|
||||
// FIXME: Nick/Viva sends this shit, need to find sync in packet
|
||||
// FIXME: otherwise it takes too long until sound appears
|
||||
|
||||
if (AudioCodecID == CODEC_ID_NONE) {
|
||||
Debug(3, "[softhddev]%s: ??? %d\n", __FUNCTION__, id);
|
||||
return;
|
||||
avpkt->data = (void *)data;
|
||||
avpkt->size = size;
|
||||
n = FindAudioSync(avpkt);
|
||||
if (n < 0) {
|
||||
return osize;
|
||||
}
|
||||
if (!MyAudioDecoder) {
|
||||
MyAudioDecoder = CodecAudioNewDecoder();
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,10 +326,8 @@ void PlayAudio(const uint8_t * data, int size, uint8_t id)
|
||||
*/
|
||||
void Mute(void)
|
||||
{
|
||||
if (BrokenThreadsAndPlugins) {
|
||||
return;
|
||||
}
|
||||
AudioSetVolume(0);
|
||||
SkipAudio = 1;
|
||||
//AudioSetVolume(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,9 +337,6 @@ void Mute(void)
|
||||
*/
|
||||
void SetVolumeDevice(int volume)
|
||||
{
|
||||
if (BrokenThreadsAndPlugins) {
|
||||
return;
|
||||
}
|
||||
AudioSetVolume((volume * 100) / 255);
|
||||
}
|
||||
|
||||
@@ -184,13 +346,13 @@ void SetVolumeDevice(int volume)
|
||||
|
||||
#include <alsa/iatomic.h> // portable atomic_t
|
||||
|
||||
uint32_t VideoSwitch;
|
||||
static int NewVideoStream; ///< new video stream
|
||||
uint32_t VideoSwitch; ///< debug video switch ticks
|
||||
static volatile char NewVideoStream; ///< new video stream
|
||||
static VideoDecoder *MyVideoDecoder; ///< video decoder
|
||||
static enum CodecID VideoCodecID; ///< current codec id
|
||||
|
||||
static const char *X11DisplayName; ///< x11 display name
|
||||
static volatile int Usr1Signal; ///< true got usr1 signal
|
||||
static volatile char Usr1Signal; ///< true got usr1 signal
|
||||
|
||||
/// video PES buffer default size
|
||||
#define VIDEO_BUFFER_SIZE (512 * 1024)
|
||||
@@ -200,8 +362,8 @@ 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 char VideoFreezed; ///< video freezed
|
||||
static char VideoClearBuffers; ///< clear video buffers
|
||||
static volatile char VideoClearBuffers; ///< clear video buffers
|
||||
static volatile char SkipVideo; ///< skip video
|
||||
|
||||
#ifdef DEBUG
|
||||
static int VideoMaxPacketSize; ///< biggest used packet buffer
|
||||
@@ -213,11 +375,10 @@ static int VideoMaxPacketSize; ///< biggest used packet buffer
|
||||
static void VideoPacketInit(void)
|
||||
{
|
||||
int i;
|
||||
AVPacket *avpkt;
|
||||
|
||||
Debug(4, "[softhddev]: %s\n", __FUNCTION__);
|
||||
|
||||
for (i = 0; i < VIDEO_PACKET_MAX; ++i) {
|
||||
AVPacket *avpkt;
|
||||
|
||||
avpkt = &VideoPacketRb[i];
|
||||
// build a clean ffmpeg av packet
|
||||
if (av_new_packet(avpkt, VIDEO_BUFFER_SIZE)) {
|
||||
@@ -229,8 +390,26 @@ static void VideoPacketInit(void)
|
||||
atomic_set(&VideoPacketsFilled, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
** Cleanup video packet ringbuffer.
|
||||
*/
|
||||
static void VideoPacketExit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
atomic_set(&VideoPacketsFilled, 0);
|
||||
|
||||
for (i = 0; i < VIDEO_PACKET_MAX; ++i) {
|
||||
av_free_packet(&VideoPacketRb[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Place video data in packet ringbuffer.
|
||||
**
|
||||
** @param pts presentation timestamp of pes packet
|
||||
** @param data data of pes packet
|
||||
** @param data size of pes packet
|
||||
*/
|
||||
static void VideoEnqueue(int64_t pts, const void *data, int size)
|
||||
{
|
||||
@@ -242,18 +421,19 @@ static void VideoEnqueue(int64_t pts, const void *data, int size)
|
||||
if (!avpkt->stream_index) { // add pts only for first added
|
||||
avpkt->pts = pts;
|
||||
}
|
||||
if (avpkt->stream_index + size + FF_INPUT_BUFFER_PADDING_SIZE >=
|
||||
avpkt->size) {
|
||||
if (avpkt->stream_index + size >= avpkt->size) {
|
||||
|
||||
Warning(_("video: packet buffer too small for %d\n"),
|
||||
avpkt->stream_index + size + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
avpkt->stream_index + size);
|
||||
|
||||
av_grow_packet(avpkt,
|
||||
((size + FF_INPUT_BUFFER_PADDING_SIZE + VIDEO_BUFFER_SIZE / 2)
|
||||
// new + grow reserves FF_INPUT_BUFFER_PADDING_SIZE
|
||||
av_grow_packet(avpkt, ((size + VIDEO_BUFFER_SIZE / 2)
|
||||
/ (VIDEO_BUFFER_SIZE / 2)) * (VIDEO_BUFFER_SIZE / 2));
|
||||
#ifdef DEBUG
|
||||
if (avpkt->size <
|
||||
avpkt->stream_index + size + FF_INPUT_BUFFER_PADDING_SIZE) {
|
||||
if (avpkt->size <= avpkt->stream_index + size) {
|
||||
fprintf(stderr, "%d %d %d\n", avpkt->size, avpkt->stream_index,
|
||||
size);
|
||||
fflush(stderr);
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
@@ -271,6 +451,8 @@ static void VideoEnqueue(int64_t pts, const void *data, int size)
|
||||
|
||||
/**
|
||||
** Finish current packet advance to next.
|
||||
**
|
||||
** @param codec_id codec id of packet (MPEG/H264)
|
||||
*/
|
||||
static void VideoNextPacket(int codec_id)
|
||||
{
|
||||
@@ -301,13 +483,13 @@ static void VideoNextPacket(int codec_id)
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,6 +507,10 @@ int VideoDecode(void)
|
||||
}
|
||||
if (VideoClearBuffers) {
|
||||
atomic_set(&VideoPacketsFilled, 0);
|
||||
VideoPacketRead = VideoPacketWrite;
|
||||
if (MyVideoDecoder) {
|
||||
CodecVideoFlushBuffers(MyVideoDecoder);
|
||||
}
|
||||
VideoClearBuffers = 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -353,6 +539,7 @@ int VideoDecode(void)
|
||||
CodecVideoClose(MyVideoDecoder);
|
||||
goto skip;
|
||||
}
|
||||
goto skip;
|
||||
break;
|
||||
case CODEC_ID_MPEG2VIDEO:
|
||||
if (last_codec_id != CODEC_ID_MPEG2VIDEO) {
|
||||
@@ -394,23 +581,65 @@ 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;
|
||||
}
|
||||
VideoCodecID = CODEC_ID_NONE;
|
||||
}
|
||||
VideoPacketInit();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
/**
|
||||
** Validate mpeg video packet.
|
||||
**
|
||||
** Function to validate a mpeg packet, not needed.
|
||||
*/
|
||||
static int ValidateMpeg(const uint8_t * data, int size)
|
||||
{
|
||||
int pes_l;
|
||||
|
||||
do {
|
||||
if (size < 9) {
|
||||
return -1;
|
||||
}
|
||||
if (data[0] || data[1] || data[2] != 0x01) {
|
||||
printf("%02x: %02x %02x %02x %02x %02x\n", data[-1], data[0],
|
||||
data[1], data[2], data[3], data[4]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pes_l = (data[4] << 8) | data[5];
|
||||
if (!pes_l) { // contains unknown length
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (6 + pes_l > size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data += 6 + pes_l;
|
||||
size -= 6 + pes_l;
|
||||
} while (size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
** Play video packet.
|
||||
**
|
||||
@@ -423,6 +652,9 @@ static void StartVideo(void)
|
||||
** 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)
|
||||
{
|
||||
@@ -430,9 +662,6 @@ int PlayVideo(const uint8_t * data, int size)
|
||||
int64_t pts;
|
||||
int n;
|
||||
|
||||
if (BrokenThreadsAndPlugins) {
|
||||
return size;
|
||||
}
|
||||
if (Usr1Signal) { // x11 server ready
|
||||
Usr1Signal = 0;
|
||||
StartVideo();
|
||||
@@ -440,10 +669,17 @@ int PlayVideo(const uint8_t * data, int size)
|
||||
if (!MyVideoDecoder) { // no x11 video started
|
||||
return size;
|
||||
}
|
||||
if (NewVideoStream) {
|
||||
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
|
||||
if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
|
||||
Debug(3, "video: new video stream lost\n");
|
||||
NewVideoStream = 0;
|
||||
return 0;
|
||||
}
|
||||
@@ -452,19 +688,21 @@ int PlayVideo(const uint8_t * data, int size)
|
||||
NewVideoStream = 0;
|
||||
}
|
||||
// must be a PES start code
|
||||
if (size < 9 || data[0] || data[1] || data[2] != 0x01) {
|
||||
if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
|
||||
Error(_("[softhddev] invalid PES video packet\n"));
|
||||
return size;
|
||||
}
|
||||
n = data[8]; // header size
|
||||
// wrong size
|
||||
if (size < 9 + n) {
|
||||
Error(_("[softhddev] invalid video packet\n"));
|
||||
if (size < 9 + n + 4) {
|
||||
Error(_("[softhddev] invalid video packet %d bytes\n"), size);
|
||||
return size;
|
||||
}
|
||||
check = data + 9 + n;
|
||||
|
||||
// FIXME: get pts/dts, when we need it
|
||||
// buffer full: needed for replay
|
||||
if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
|
||||
return 0;
|
||||
}
|
||||
// get pts/dts
|
||||
|
||||
pts = AV_NOPTS_VALUE;
|
||||
if (data[7] & 0x80) {
|
||||
@@ -472,6 +710,10 @@ int PlayVideo(const uint8_t * data, int size)
|
||||
(int64_t) (data[9] & 0x0E) << 29 | data[10] << 22 | (data[11] &
|
||||
0xFE) << 14 | data[12] << 7 | (data[13] & 0xFE) >> 1;
|
||||
#ifdef DEBUG
|
||||
if (!(data[13] & 1) || !(data[11] & 1) || !(data[9] & 1)) {
|
||||
Error(_("[softhddev] invalid pts in video packet\n"));
|
||||
return size;
|
||||
}
|
||||
//Debug(3, "video: pts %#012" PRIx64 "\n", pts);
|
||||
if (data[13] != (((pts & 0x7F) << 1) | 1)) {
|
||||
abort();
|
||||
@@ -485,35 +727,46 @@ int PlayVideo(const uint8_t * data, int size)
|
||||
if (data[10] != ((pts >> 22) & 0xFF)) {
|
||||
abort();
|
||||
}
|
||||
if ((data[9] & 0x0F) != (((pts >> 30) << 1) | 1)) {
|
||||
abort();
|
||||
}
|
||||
#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]);
|
||||
}
|
||||
// PES_VIDEO_STREAM 0xE0 or PES start code
|
||||
if ((data[6] & 0xC0) != 0x80 || (!check[0] && !check[1]
|
||||
&& check[2] == 0x1)) {
|
||||
//(data[6] & 0xC0) != 0x80 ||
|
||||
if ((!check[0] && !check[1] && check[2] == 0x1)) {
|
||||
if (VideoCodecID == CODEC_ID_MPEG2VIDEO) {
|
||||
// FIXME: hack to test results
|
||||
if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
|
||||
return 0;
|
||||
}
|
||||
VideoNextPacket(CODEC_ID_MPEG2VIDEO);
|
||||
} else {
|
||||
Debug(3, "video: mpeg2 detected\n");
|
||||
Debug(3, "video: mpeg2 detected ID %02x\n", check[3]);
|
||||
VideoCodecID = CODEC_ID_MPEG2VIDEO;
|
||||
}
|
||||
// Access Unit Delimiter
|
||||
} else if (!check[0] && !check[1] && !check[2] && check[3] == 0x1
|
||||
&& check[4] == 0x09) {
|
||||
if (VideoCodecID == CODEC_ID_H264) {
|
||||
// FIXME: hack to test results
|
||||
if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
|
||||
return 0;
|
||||
#ifdef DEBUG
|
||||
if (ValidateMpeg(data, size)) {
|
||||
Debug(3, "softhddev/video: invalid mpeg2 video packet\n");
|
||||
}
|
||||
#endif
|
||||
// Access Unit Delimiter
|
||||
} else if ((data[6] & 0xC0) == 0x80 && !check[0] && !check[1]
|
||||
&& !check[2] && check[3] == 0x1 && check[4] == 0x09) {
|
||||
if (VideoCodecID == CODEC_ID_H264) {
|
||||
VideoNextPacket(CODEC_ID_H264);
|
||||
} else {
|
||||
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");
|
||||
@@ -526,11 +779,8 @@ int PlayVideo(const uint8_t * data, int size)
|
||||
return size;
|
||||
}
|
||||
if (VideoCodecID == CODEC_ID_MPEG2VIDEO) {
|
||||
// mpeg codec supports incomplete packages
|
||||
// FIXME: hack to test results
|
||||
if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
|
||||
return 0;
|
||||
}
|
||||
// mpeg codec supports incomplete packets
|
||||
// waiting for a full complete packages, increases needed delays
|
||||
VideoNextPacket(CODEC_ID_MPEG2VIDEO);
|
||||
}
|
||||
}
|
||||
@@ -548,9 +798,7 @@ int PlayVideo(const uint8_t * data, int size)
|
||||
*/
|
||||
void SetPlayMode(void)
|
||||
{
|
||||
if (BrokenThreadsAndPlugins) {
|
||||
return;
|
||||
}
|
||||
Resume();
|
||||
if (MyVideoDecoder) {
|
||||
if (VideoCodecID != CODEC_ID_NONE) {
|
||||
NewVideoStream = 1;
|
||||
@@ -558,10 +806,13 @@ void SetPlayMode(void)
|
||||
}
|
||||
}
|
||||
if (MyAudioDecoder) {
|
||||
// FIXME: does this clear the audio ringbuffer?
|
||||
CodecAudioClose(MyAudioDecoder);
|
||||
AudioCodecID = CODEC_ID_NONE;
|
||||
if (AudioCodecID != CODEC_ID_NONE) {
|
||||
NewAudioStream = 1;
|
||||
}
|
||||
}
|
||||
VideoFreezed = 0;
|
||||
SkipAudio = 0;
|
||||
SkipVideo = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -569,9 +820,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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -580,6 +838,7 @@ void Clear(void)
|
||||
void Play(void)
|
||||
{
|
||||
VideoFreezed = 0;
|
||||
SkipAudio = 0;
|
||||
// FIXME: restart audio
|
||||
}
|
||||
|
||||
@@ -590,16 +849,38 @@ 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;
|
||||
|
||||
// must be a PES start code
|
||||
if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
|
||||
Error(_("[softhddev] invalid PES video packet\n"));
|
||||
return;
|
||||
}
|
||||
Clear(); // flush video buffers
|
||||
// +1 future for deinterlace
|
||||
for (i = -1; i < (VideoCodecID == CODEC_ID_MPEG2VIDEO ? 3 : 17); ++i) {
|
||||
PlayVideo(data, size); // reference frames
|
||||
}
|
||||
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);
|
||||
@@ -609,6 +890,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
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -618,21 +915,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
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -640,9 +938,6 @@ void GetOsdSize(int *width, int *height, double *aspect)
|
||||
*/
|
||||
void OsdClose(void)
|
||||
{
|
||||
if (BrokenThreadsAndPlugins) {
|
||||
return;
|
||||
}
|
||||
VideoOsdClear();
|
||||
}
|
||||
|
||||
@@ -651,25 +946,24 @@ void OsdClose(void)
|
||||
*/
|
||||
void OsdDrawARGB(int x, int y, int height, int width, const uint8_t * argb)
|
||||
{
|
||||
if (BrokenThreadsAndPlugins) {
|
||||
return;
|
||||
}
|
||||
Resume();
|
||||
VideoOsdDrawARGB(x, y, height, width, 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"
|
||||
" -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";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -684,13 +978,16 @@ int ProcessArgs(int argc, char *const argv[])
|
||||
// Parse arguments.
|
||||
//
|
||||
for (;;) {
|
||||
switch (getopt(argc, argv, "-a:d:g:x")) {
|
||||
switch (getopt(argc, argv, "-a:d:fg:x")) {
|
||||
case 'a': // audio device
|
||||
AudioSetDevice(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,
|
||||
@@ -700,7 +997,7 @@ int ProcessArgs(int argc, char *const argv[])
|
||||
}
|
||||
continue;
|
||||
case 'x': // x11 server
|
||||
StartX11Server = 1;
|
||||
ConfigStartX11Server = 1;
|
||||
continue;
|
||||
case EOF:
|
||||
break;
|
||||
@@ -820,6 +1117,35 @@ 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;
|
||||
}
|
||||
if (MyAudioDecoder) {
|
||||
CodecAudioClose(MyAudioDecoder);
|
||||
// FIXME: CodecDelAudioDecoder(MyAudioDecoder);
|
||||
MyAudioDecoder = NULL;
|
||||
}
|
||||
|
||||
VideoOsdExit();
|
||||
VideoExit();
|
||||
AudioExit();
|
||||
CodecExit();
|
||||
VideoPacketExit();
|
||||
|
||||
if (ConfigStartX11Server) {
|
||||
Debug(3, "x-setup: Stop x11 server\n");
|
||||
|
||||
if (X11ServerPid) {
|
||||
kill(X11ServerPid, SIGTERM);
|
||||
// FIXME: wait for x11 finishing
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&SuspendLockMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -827,54 +1153,29 @@ void SoftHdDeviceExit(void)
|
||||
*/
|
||||
void Start(void)
|
||||
{
|
||||
if (StartX11Server) {
|
||||
if (ConfigStartX11Server) {
|
||||
StartXServer();
|
||||
}
|
||||
CodecInit();
|
||||
// FIXME: AudioInit for HDMI after X11 startup
|
||||
AudioInit();
|
||||
if (!StartX11Server) {
|
||||
if (!ConfigStartX11Server) {
|
||||
StartVideo();
|
||||
}
|
||||
|
||||
pthread_mutex_init(&SuspendLockMutex, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
** Stop plugin.
|
||||
**
|
||||
** @note stop everything, but don't cleanup, module is still called.
|
||||
*/
|
||||
void Stop(void)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Debug(3, "video: max used PES packet size: %d\n", VideoMaxPacketSize);
|
||||
#endif
|
||||
|
||||
// FIXME:
|
||||
// don't let any thread enter our plugin, but can still crash, when
|
||||
// a thread has called any function, while Stop is called.
|
||||
BrokenThreadsAndPlugins = 1;
|
||||
usleep(2 * 1000);
|
||||
|
||||
// lets hope that vdr does a good thead cleanup
|
||||
// no it doesn't do a good thread cleanup
|
||||
if (MyVideoDecoder) {
|
||||
CodecVideoClose(MyVideoDecoder);
|
||||
MyVideoDecoder = NULL;
|
||||
}
|
||||
if (MyAudioDecoder) {
|
||||
CodecAudioClose(MyAudioDecoder);
|
||||
MyAudioDecoder = NULL;
|
||||
}
|
||||
|
||||
VideoExit();
|
||||
AudioExit();
|
||||
CodecExit();
|
||||
|
||||
if (StartX11Server) {
|
||||
Debug(3, "x-setup: Stop x11 server\n");
|
||||
|
||||
if (X11ServerPid) {
|
||||
kill(X11ServerPid, SIGTERM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -882,5 +1183,58 @@ void Stop(void)
|
||||
*/
|
||||
void MainThreadHook(void)
|
||||
{
|
||||
VideoDisplayHandler();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Suspend/Resume
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
** Suspend plugin.
|
||||
*/
|
||||
void Suspend(void)
|
||||
{
|
||||
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 (ConfigSuspendClose) {
|
||||
pthread_mutex_lock(&SuspendLockMutex);
|
||||
// FIXME: close audio
|
||||
// FIXME: close video
|
||||
pthread_mutex_unlock(&SuspendLockMutex);
|
||||
}
|
||||
if (ConfigSuspendX11) {
|
||||
// FIXME: stop x11, if started
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Resume plugin.
|
||||
*/
|
||||
void Resume(void)
|
||||
{
|
||||
if (!SkipVideo && !SkipAudio) { // we are not suspended
|
||||
return;
|
||||
}
|
||||
|
||||
Debug(3, "[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
if (ConfigSuspendX11) {
|
||||
}
|
||||
if (ConfigSuspendClose) {
|
||||
pthread_mutex_lock(&SuspendLockMutex);
|
||||
pthread_mutex_unlock(&SuspendLockMutex);
|
||||
}
|
||||
|
||||
SkipVideo = 0;
|
||||
SkipAudio = 0;
|
||||
}
|
||||
|
||||
12
softhddev.h
12
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
|
||||
@@ -55,8 +55,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 +76,10 @@ extern "C"
|
||||
/// C plugin main thread hook
|
||||
extern void MainThreadHook(void);
|
||||
|
||||
/// Suspend plugin
|
||||
extern void Suspend(void);
|
||||
/// Resume plugin
|
||||
extern void Resume(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
581
softhddevice.cpp
581
softhddevice.cpp
@@ -1,7 +1,7 @@
|
||||
///
|
||||
/// @file softhddevice.cpp @brief A software HD device plugin for VDR.
|
||||
///
|
||||
/// Copyright (c) 2011 by Johns. All Rights Reserved.
|
||||
/// Copyright (c) 2011, 2012 by Johns. All Rights Reserved.
|
||||
///
|
||||
/// Contributor(s):
|
||||
///
|
||||
@@ -33,26 +33,53 @@
|
||||
|
||||
#include "softhddev.h"
|
||||
#include "softhddevice.h"
|
||||
extern "C" {
|
||||
#include "video.h"
|
||||
extern "C"
|
||||
{
|
||||
#include "video.h"
|
||||
extern void AudioPoller(void);
|
||||
extern void CodecSetAudioPassthrough(int);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const char *const VERSION = "0.1.2";
|
||||
static const char *const VERSION = "0.3.5";
|
||||
static const char *const DESCRIPTION =
|
||||
trNOOP("A software and GPU emulated HD device");
|
||||
|
||||
//static const char *MAINMENUENTRY = trNOOP("Soft-HD-Device");
|
||||
static const char *MAINMENUENTRY = trNOOP("Suspend Soft-HD-Device");
|
||||
static class cSoftHdDevice *MyDevice;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define RESOLUTIONS 4 ///< number of resolutions
|
||||
|
||||
/// resolutions names
|
||||
static const char *const Resolution[RESOLUTIONS] = {
|
||||
"576i", "720p", "1080i_fake", "1080i"
|
||||
};
|
||||
|
||||
static char ConfigMakePrimary; ///< config primary wanted
|
||||
static char ConfigVideoDeinterlace; ///< config deinterlace
|
||||
static char ConfigVideoScaling; ///< config scaling
|
||||
static char ConfigHideMainMenuEntry; ///< config hide main menu entry
|
||||
|
||||
/// config deinterlace
|
||||
static int ConfigVideoDeinterlace[RESOLUTIONS];
|
||||
|
||||
/// config skip chroma
|
||||
static int ConfigVideoSkipChromaDeinterlace[RESOLUTIONS];
|
||||
|
||||
/// config denoise
|
||||
static int ConfigVideoDenoise[RESOLUTIONS];
|
||||
|
||||
/// config sharpen
|
||||
static int ConfigVideoSharpen[RESOLUTIONS];
|
||||
|
||||
/// config scaling
|
||||
static int ConfigVideoScaling[RESOLUTIONS];
|
||||
|
||||
static int ConfigVideoAudioDelay; ///< config audio delay
|
||||
static char DoMakePrimary; ///< flag switch primary
|
||||
static int ConfigAudioPassthrough; ///< config audio pass-through
|
||||
|
||||
static volatile char DoMakePrimary; ///< flag switch primary
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -106,6 +133,8 @@ extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat,
|
||||
|
||||
class cSoftOsd:public cOsd
|
||||
{
|
||||
int Level; ///< level: subtitle
|
||||
|
||||
public:
|
||||
cSoftOsd(int, int, uint);
|
||||
virtual ~ cSoftOsd(void);
|
||||
@@ -120,14 +149,27 @@ cSoftOsd::cSoftOsd(int left, int top, uint level)
|
||||
dsyslog("[softhddev]%s: %dx%d+%d+%d, %d\n", __FUNCTION__, OsdWidth(),
|
||||
OsdHeight(), left, top, level);
|
||||
|
||||
this->Level = level;
|
||||
//SetActive(true);
|
||||
}
|
||||
|
||||
cSoftOsd::~cSoftOsd(void)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
SetActive(false);
|
||||
|
||||
#ifdef USE_YAEPG
|
||||
// support yaepghd, video window
|
||||
if (vidWin.bpp) { // restore fullsized video
|
||||
int width;
|
||||
int height;
|
||||
double video_aspect;
|
||||
|
||||
::GetOsdSize(&width, &height, &video_aspect);
|
||||
// works osd relative
|
||||
VideoSetOutputPosition(0, 0, width, height);
|
||||
}
|
||||
#endif
|
||||
OsdClose();
|
||||
}
|
||||
|
||||
@@ -141,7 +183,18 @@ void cSoftOsd::Flush(void)
|
||||
if (!Active()) {
|
||||
return;
|
||||
}
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
#ifdef USE_YAEPG
|
||||
// support yaepghd, video window
|
||||
if (vidWin.bpp) {
|
||||
dsyslog("[softhddev]%s: %dx%d+%d+%d\n", __FUNCTION__, vidWin.Width(),
|
||||
vidWin.Height(), vidWin.x1, vidWin.y2);
|
||||
|
||||
// FIXME: vidWin is OSD relative not video window.
|
||||
VideoSetOutputPosition(Left() + vidWin.x1, Top() + vidWin.y1,
|
||||
vidWin.Width(), vidWin.Height());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!IsTrueColor()) {
|
||||
static char warned;
|
||||
cBitmap *bitmap;
|
||||
@@ -168,6 +221,7 @@ void cSoftOsd::Flush(void)
|
||||
if (!bitmap->Dirty(x1, y1, x2, y2)) {
|
||||
continue; // nothing dirty continue
|
||||
}
|
||||
#if 0
|
||||
// FIXME: need only to convert and upload dirty areas
|
||||
|
||||
// DrawBitmap(bitmap);
|
||||
@@ -180,9 +234,44 @@ void cSoftOsd::Flush(void)
|
||||
((uint32_t *) argb)[x + y * w] = bitmap->GetColor(x, y);
|
||||
}
|
||||
}
|
||||
// check if subtitles
|
||||
if (this->Level == OSD_LEVEL_SUBTITLES) {
|
||||
int video_width;
|
||||
int video_height;
|
||||
|
||||
OsdDrawARGB(Left() + bitmap->X0(), Top() + bitmap->Y0(),
|
||||
bitmap->Width(), bitmap->Height(), argb);
|
||||
if (0) {
|
||||
dsyslog("[softhddev]%s: subtitle %d, %d\n", __FUNCTION__,
|
||||
Left() + bitmap->X0(), Top() + bitmap->Y0());
|
||||
}
|
||||
video_width = 1920;
|
||||
video_height = 1080;
|
||||
OsdDrawARGB((1920 - video_width) / 2 + Left() + bitmap->X0(),
|
||||
1080 - video_height + Top() + bitmap->Y0(), w, h, argb);
|
||||
} else {
|
||||
OsdDrawARGB(Left() + bitmap->X0(), Top() + bitmap->Y0(), w, h,
|
||||
argb);
|
||||
}
|
||||
#else
|
||||
// convert and upload only dirty areas
|
||||
w = x2 - x1 + 1;
|
||||
h = y2 - y1 + 1;
|
||||
#ifdef DEBUG
|
||||
if (w > bitmap->Width() || h > bitmap->Height()) {
|
||||
esyslog(tr("softhdev: dirty area too big\n"));
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
argb = (uint8_t *) malloc(w * h * sizeof(uint32_t));
|
||||
for (y = y1; y <= y2; ++y) {
|
||||
for (x = x1; x <= x2; ++x) {
|
||||
((uint32_t *) argb)[x - x1 + (y - y1) * w] =
|
||||
bitmap->GetColor(x, y);
|
||||
}
|
||||
}
|
||||
// check if subtitles
|
||||
OsdDrawARGB(Left() + bitmap->X0() + x1, Top() + bitmap->Y0() + y1,
|
||||
w, h, argb);
|
||||
#endif
|
||||
|
||||
bitmap->Clean();
|
||||
free(argb);
|
||||
@@ -202,8 +291,10 @@ void cSoftOsd::Flush(void)
|
||||
w = pm->ViewPort().Width();
|
||||
h = pm->ViewPort().Height();
|
||||
|
||||
/*
|
||||
dsyslog("[softhddev]%s: draw %dx%d+%d+%d %p\n", __FUNCTION__, w, h, x,
|
||||
y, pm->Data());
|
||||
*/
|
||||
|
||||
OsdDrawARGB(x, y, w, h, pm->Data());
|
||||
|
||||
@@ -232,7 +323,7 @@ cOsd *cSoftOsdProvider::Osd; ///< single osd
|
||||
*/
|
||||
cOsd *cSoftOsdProvider::CreateOsd(int left, int top, uint level)
|
||||
{
|
||||
dsyslog("[softhddev]%s: %d, %d, %d\n", __FUNCTION__, left, top, level);
|
||||
//dsyslog("[softhddev]%s: %d, %d, %d\n", __FUNCTION__, left, top, level);
|
||||
|
||||
Osd = new cSoftOsd(left, top, level);
|
||||
return Osd;
|
||||
@@ -246,10 +337,13 @@ bool cSoftOsdProvider::ProvidesTrueColor(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
** Create cOsdProvider class.
|
||||
*/
|
||||
cSoftOsdProvider::cSoftOsdProvider(void)
|
||||
: cOsdProvider()
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -260,36 +354,91 @@ class cMenuSetupSoft:public cMenuSetupPage
|
||||
{
|
||||
protected:
|
||||
int MakePrimary;
|
||||
int Deinterlace;
|
||||
int Scaling;
|
||||
int HideMainMenuEntry;
|
||||
int Scaling[RESOLUTIONS];
|
||||
int Deinterlace[RESOLUTIONS];
|
||||
int SkipChromaDeinterlace[RESOLUTIONS];
|
||||
int Denoise[RESOLUTIONS];
|
||||
int Sharpen[RESOLUTIONS];
|
||||
int AudioDelay;
|
||||
int AudioPassthrough;
|
||||
protected:
|
||||
virtual void Store(void);
|
||||
public:
|
||||
cMenuSetupSoft(void);
|
||||
};
|
||||
|
||||
/**
|
||||
** Create a seperator item.
|
||||
*/
|
||||
static inline cOsdItem *SeparatorItem(const char *label)
|
||||
{
|
||||
cOsdItem *item;
|
||||
|
||||
item = new cOsdItem(cString::sprintf("* %s: ", label));
|
||||
item->SetSelectable(false);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
** Constructor setup menu.
|
||||
*/
|
||||
cMenuSetupSoft::cMenuSetupSoft(void)
|
||||
{
|
||||
static const char * const deinterlace[] = {
|
||||
"Bob", "Weave", "Temporal", "TemporalSpatial", "Software" };
|
||||
static const char * const scaling[] = {
|
||||
"Normal", "Fast", "HQ", "Anamorphic" };
|
||||
static const char *const deinterlace[] = {
|
||||
"Bob", "Weave/None", "Temporal", "TemporalSpatial", "Software"
|
||||
};
|
||||
static const char *const scaling[] = {
|
||||
"Normal", "Fast", "HQ", "Anamorphic"
|
||||
};
|
||||
static const char *const passthrough[] = {
|
||||
"None", "AC-3"
|
||||
};
|
||||
static const char *const resolution[RESOLUTIONS] = {
|
||||
"576i", "720p", "fake 1080i", "1080i"
|
||||
};
|
||||
int i;
|
||||
|
||||
// cMenuEditBoolItem cMenuEditBitItem cMenuEditNumItem
|
||||
// cMenuEditStrItem cMenuEditStraItem cMenuEditIntItem
|
||||
MakePrimary = ConfigMakePrimary;
|
||||
Add(new cMenuEditBoolItem(tr("Make primary device"), &MakePrimary,
|
||||
tr("no"), tr("yes")));
|
||||
Deinterlace = ConfigVideoDeinterlace;
|
||||
Add(new cMenuEditStraItem(tr("Deinterlace"), &Deinterlace, 5, deinterlace));
|
||||
Scaling = ConfigVideoScaling;
|
||||
Add(new cMenuEditStraItem(tr("Scaling"), &Scaling, 4, scaling));
|
||||
trVDR("no"), trVDR("yes")));
|
||||
HideMainMenuEntry = ConfigHideMainMenuEntry;
|
||||
Add(new cMenuEditBoolItem(tr("Hide main menu entry"), &HideMainMenuEntry,
|
||||
trVDR("no"), trVDR("yes")));
|
||||
//
|
||||
// video
|
||||
//
|
||||
Add(SeparatorItem(tr("Video")));
|
||||
for (i = 0; i < RESOLUTIONS; ++i) {
|
||||
Add(SeparatorItem(resolution[i]));
|
||||
Scaling[i] = ConfigVideoScaling[i];
|
||||
Add(new cMenuEditStraItem(tr("Scaling"), &Scaling[i], 4, scaling));
|
||||
Deinterlace[i] = ConfigVideoDeinterlace[i];
|
||||
Add(new cMenuEditStraItem(tr("Deinterlace"), &Deinterlace[i], 5,
|
||||
deinterlace));
|
||||
SkipChromaDeinterlace[i] = ConfigVideoSkipChromaDeinterlace[i];
|
||||
Add(new cMenuEditBoolItem(tr("SkipChromaDeinterlace (vdpau)"),
|
||||
&SkipChromaDeinterlace[i], trVDR("no"), trVDR("yes")));
|
||||
Denoise[i] = ConfigVideoDenoise[i];
|
||||
Add(new cMenuEditIntItem(tr("Denoise (0..1000) (vdpau)"), &Denoise[i],
|
||||
0, 1000));
|
||||
Sharpen[i] = ConfigVideoSharpen[i];
|
||||
Add(new cMenuEditIntItem(tr("Sharpen (-1000..1000) (vdpau)"),
|
||||
&Sharpen[i], -1000, 1000));
|
||||
}
|
||||
//
|
||||
// audio
|
||||
//
|
||||
Add(SeparatorItem(tr("Audio")));
|
||||
AudioDelay = ConfigVideoAudioDelay;
|
||||
Add(new cMenuEditIntItem(tr("Audio delay (ms)"), &AudioDelay, -1000, 1000));
|
||||
Add(new cMenuEditIntItem(tr("Audio delay (ms)"), &AudioDelay, -1000,
|
||||
1000));
|
||||
AudioPassthrough = ConfigAudioPassthrough;
|
||||
Add(new cMenuEditStraItem(tr("Audio pass-through"), &AudioPassthrough, 2,
|
||||
passthrough));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,13 +446,38 @@ cMenuSetupSoft::cMenuSetupSoft(void)
|
||||
*/
|
||||
void cMenuSetupSoft::Store(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
SetupStore("MakePrimary", ConfigMakePrimary = MakePrimary);
|
||||
SetupStore("Deinterlace", ConfigVideoDeinterlace = Deinterlace);
|
||||
VideoSetDeinterlace(ConfigVideoDeinterlace);
|
||||
SetupStore("Scaling", ConfigVideoScaling = Scaling);
|
||||
SetupStore("HideMainMenuEntry", ConfigHideMainMenuEntry =
|
||||
HideMainMenuEntry);
|
||||
|
||||
for (i = 0; i < RESOLUTIONS; ++i) {
|
||||
char buf[128];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Scaling");
|
||||
SetupStore(buf, ConfigVideoScaling[i] = Scaling[i]);
|
||||
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Deinterlace");
|
||||
SetupStore(buf, ConfigVideoDeinterlace[i] = Deinterlace[i]);
|
||||
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i],
|
||||
"SkipChromaDeinterlace");
|
||||
SetupStore(buf, ConfigVideoSkipChromaDeinterlace[i] =
|
||||
SkipChromaDeinterlace[i]);
|
||||
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Denoise");
|
||||
SetupStore(buf, ConfigVideoDenoise[i] = Denoise[i]);
|
||||
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Sharpen");
|
||||
SetupStore(buf, ConfigVideoSharpen[i] = Sharpen[i]);
|
||||
}
|
||||
VideoSetScaling(ConfigVideoScaling);
|
||||
VideoSetDeinterlace(ConfigVideoDeinterlace);
|
||||
VideoSetSkipChromaDeinterlace(ConfigVideoSkipChromaDeinterlace);
|
||||
VideoSetDenoise(ConfigVideoDenoise);
|
||||
VideoSetSharpen(ConfigVideoSharpen);
|
||||
|
||||
SetupStore("AudioDelay", ConfigVideoAudioDelay = AudioDelay);
|
||||
VideoSetAudioDelay(ConfigVideoAudioDelay);
|
||||
SetupStore("AudioPassthrough", ConfigAudioPassthrough = AudioPassthrough);
|
||||
CodecSetAudioPassthrough(ConfigAudioPassthrough);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -329,9 +503,14 @@ class cSoftHdDevice:public cDevice
|
||||
virtual bool Poll(cPoller &, int = 0);
|
||||
virtual bool Flush(int = 0);
|
||||
virtual int64_t GetSTC(void);
|
||||
virtual void GetVideoSize(int &, int &, double &);
|
||||
virtual void GetOsdSize(int &, int &, double &);
|
||||
virtual int PlayVideo(const uchar *, int);
|
||||
|
||||
//virtual int PlayTsVideo(const uchar *, int);
|
||||
#ifndef USE_AUDIO_THREAD // FIXME: testing none threaded
|
||||
virtual int PlayTsAudio(const uchar *, int);
|
||||
#endif
|
||||
virtual void SetAudioChannelDevice(int);
|
||||
virtual int GetAudioChannelDevice(void);
|
||||
virtual void SetDigitalAudioDevice(bool);
|
||||
@@ -342,13 +521,13 @@ class cSoftHdDevice:public cDevice
|
||||
|
||||
virtual uchar *GrabImage(int &, bool, int, int, int);
|
||||
|
||||
virtual int ProvidesCa(const cChannel *) const;
|
||||
|
||||
#if 0
|
||||
// SPU facilities
|
||||
private:
|
||||
cDvbSpuDecoder * spuDecoder;
|
||||
public:
|
||||
virtual cSpuDecoder * GetSpuDecoder(void);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
virtual void MakePrimaryDevice(bool);
|
||||
@@ -356,16 +535,23 @@ class cSoftHdDevice:public cDevice
|
||||
|
||||
cSoftHdDevice::cSoftHdDevice(void)
|
||||
{
|
||||
dsyslog("[softhddev]%s\n", __FUNCTION__);
|
||||
//dsyslog("[softhddev]%s\n", __FUNCTION__);
|
||||
|
||||
#if 0
|
||||
spuDecoder = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
cSoftHdDevice::~cSoftHdDevice(void)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
** Informs a device that it will be the primary device.
|
||||
**
|
||||
** @param on flag if becoming or loosing primary
|
||||
*/
|
||||
void cSoftHdDevice::MakePrimaryDevice(bool on)
|
||||
{
|
||||
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, on);
|
||||
@@ -376,13 +562,7 @@ void cSoftHdDevice::MakePrimaryDevice(bool on)
|
||||
}
|
||||
}
|
||||
|
||||
int cSoftHdDevice::ProvidesCa(
|
||||
__attribute__ ((unused)) const cChannel * channel) const
|
||||
{
|
||||
dsyslog("[softhddev]%s: %p\n", __FUNCTION__, channel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
|
||||
cSpuDecoder *cSoftHdDevice::GetSpuDecoder(void)
|
||||
{
|
||||
@@ -394,6 +574,8 @@ cSpuDecoder *cSoftHdDevice::GetSpuDecoder(void)
|
||||
return spuDecoder;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool cSoftHdDevice::HasDecoder(void) const
|
||||
{
|
||||
return true;
|
||||
@@ -417,7 +599,7 @@ bool cSoftHdDevice::SetPlayMode(ePlayMode PlayMode)
|
||||
case pmVideoOnly:
|
||||
break;
|
||||
case pmNone:
|
||||
break;
|
||||
return true;
|
||||
case pmExtern_THIS_SHOULD_BE_AVOIDED:
|
||||
break;
|
||||
default:
|
||||
@@ -432,12 +614,17 @@ int64_t cSoftHdDevice::GetSTC(void)
|
||||
{
|
||||
// dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
return ::VideoGetClock();
|
||||
return::VideoGetClock();
|
||||
}
|
||||
|
||||
void cSoftHdDevice::TrickSpeed(int Speed)
|
||||
/**
|
||||
** Set trick play speed.
|
||||
**
|
||||
** @param speed trick speed
|
||||
*/
|
||||
void cSoftHdDevice::TrickSpeed(int speed)
|
||||
{
|
||||
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, Speed);
|
||||
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, speed);
|
||||
}
|
||||
|
||||
void cSoftHdDevice::Clear(void)
|
||||
@@ -456,6 +643,9 @@ void cSoftHdDevice::Play(void)
|
||||
::Play();
|
||||
}
|
||||
|
||||
/**
|
||||
** Puts the device into "freeze frame" mode.
|
||||
*/
|
||||
void cSoftHdDevice::Freeze(void)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
@@ -469,7 +659,6 @@ void cSoftHdDevice::Mute(void)
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
cDevice::Mute();
|
||||
|
||||
::Mute();
|
||||
}
|
||||
|
||||
@@ -480,32 +669,63 @@ void cSoftHdDevice::SetVolumeDevice(int volume)
|
||||
::SetVolumeDevice(volume);
|
||||
}
|
||||
|
||||
void cSoftHdDevice::StillPicture(
|
||||
__attribute__ ((unused)) const uchar * data, __attribute__ ((unused))
|
||||
int length)
|
||||
/**
|
||||
** Display the given I-frame as a still picture.
|
||||
*/
|
||||
void cSoftHdDevice::StillPicture(const uchar * data, int length)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
dsyslog("[softhddev]%s: %s\n", __FUNCTION__,
|
||||
data[0] == 0x47 ? "ts" : "pes");
|
||||
|
||||
if (data[0] == 0x47) { // ts sync
|
||||
cDevice::StillPicture(data, length);
|
||||
return;
|
||||
}
|
||||
|
||||
::StillPicture(data, length);
|
||||
}
|
||||
|
||||
/**
|
||||
** Check if the device is ready for further action.
|
||||
**
|
||||
** @param poller file handles (unused)
|
||||
** @param timeout_ms timeout in ms to become ready
|
||||
*/
|
||||
bool cSoftHdDevice::Poll(
|
||||
__attribute__ ((unused)) cPoller & poller, int timeout_ms)
|
||||
{
|
||||
// dsyslog("[softhddev]%s: %d\n", __FUNCTION__, timeout_ms);
|
||||
|
||||
return ::Poll(timeout_ms);
|
||||
return::Poll(timeout_ms);
|
||||
}
|
||||
|
||||
/**
|
||||
** Flush the device output buffers.
|
||||
**
|
||||
** @param timeout_ms timeout in ms to become ready
|
||||
*/
|
||||
bool cSoftHdDevice::Flush(int timeout_ms)
|
||||
{
|
||||
dsyslog("[softhddev]%s: %d ms\n", __FUNCTION__, timeout_ms);
|
||||
|
||||
return true;
|
||||
return::Flush(timeout_ms);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** Returns the With, Height and PixelAspect ratio the OSD.
|
||||
** Returns the width, height and video_aspect ratio of the currently
|
||||
** displayed video material.
|
||||
**
|
||||
** @note the size is used to scale the subtitle.
|
||||
*/
|
||||
void cSoftHdDevice::GetVideoSize(int &width, int &height, double &video_aspect)
|
||||
{
|
||||
::GetOsdSize(&width, &height, &video_aspect);
|
||||
}
|
||||
|
||||
/**
|
||||
** Returns the width, height and pixel_aspect ratio the OSD.
|
||||
**
|
||||
** FIXME: Called every second, for nothing (no OSD displayed)?
|
||||
*/
|
||||
@@ -516,34 +736,36 @@ void cSoftHdDevice::GetOsdSize(int &width, int &height, double &pixel_aspect)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** Play a audio packet.
|
||||
*/
|
||||
int cSoftHdDevice::PlayAudio(const uchar * data, int length, uchar id)
|
||||
{
|
||||
//dsyslog("[softhddev]%s: %p %p %d %d\n", __FUNCTION__, this, data, length, id);
|
||||
|
||||
::PlayAudio(data, length, id);
|
||||
|
||||
return length;
|
||||
return::PlayAudio(data, length, id);
|
||||
}
|
||||
|
||||
void cSoftHdDevice::SetAudioTrackDevice(
|
||||
__attribute__ ((unused)) eTrackType type)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void cSoftHdDevice::SetDigitalAudioDevice(bool on)
|
||||
void cSoftHdDevice::SetDigitalAudioDevice( __attribute__ ((unused)) bool on)
|
||||
{
|
||||
dsyslog("[softhddev]%s: %s\n", __FUNCTION__, on ? "true" : "false");
|
||||
//dsyslog("[softhddev]%s: %s\n", __FUNCTION__, on ? "true" : "false");
|
||||
}
|
||||
|
||||
void cSoftHdDevice::SetAudioChannelDevice(int audio_channel)
|
||||
void cSoftHdDevice::SetAudioChannelDevice( __attribute__ ((unused))
|
||||
int audio_channel)
|
||||
{
|
||||
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, audio_channel);
|
||||
//dsyslog("[softhddev]%s: %d\n", __FUNCTION__, audio_channel);
|
||||
}
|
||||
|
||||
int cSoftHdDevice::GetAudioChannelDevice(void)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -556,19 +778,38 @@ int cSoftHdDevice::PlayVideo(const uchar * data, int length)
|
||||
{
|
||||
//dsyslog("[softhddev]%s: %p %d\n", __FUNCTION__, data, length);
|
||||
|
||||
return ::PlayVideo(data, length);
|
||||
return::PlayVideo(data, length);
|
||||
}
|
||||
|
||||
#if 0
|
||||
///
|
||||
/// Play a TS video packet.
|
||||
///
|
||||
int cSoftHdDevice::PlayTsVideo(const uchar * Data, int Length)
|
||||
int cSoftHdDevice::PlayTsVideo(const uchar * data, int length)
|
||||
{
|
||||
// many code to repeat
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef USE_AUDIO_THREAD // FIXME: testing none threaded
|
||||
|
||||
///
|
||||
/// Play a TS audio packet.
|
||||
///
|
||||
/// misuse this function as audio poller
|
||||
///
|
||||
/// @param data ts data buffer
|
||||
/// @param length ts packet length
|
||||
///
|
||||
int cSoftHdDevice::PlayTsAudio(const uchar * data, int length)
|
||||
{
|
||||
AudioPoller();
|
||||
|
||||
return cDevice::PlayTsAudio(data, length);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
uchar *cSoftHdDevice::GrabImage(int &size, bool jpeg, int quality, int sizex,
|
||||
int sizey)
|
||||
{
|
||||
@@ -596,11 +837,13 @@ class cPluginSoftHdDevice:public cPlugin
|
||||
virtual void Stop(void);
|
||||
// virtual void Housekeeping(void);
|
||||
virtual void MainThreadHook(void);
|
||||
// virtual const char *MainMenuEntry(void);
|
||||
// virtual cOsdObject *MainMenuAction(void);
|
||||
virtual const char *MainMenuEntry(void);
|
||||
virtual cOsdObject *MainMenuAction(void);
|
||||
virtual cMenuSetupPage *SetupMenu(void);
|
||||
virtual bool SetupParse(const char *, const char *);
|
||||
// virtual bool Service(const char *Id, void *Data = NULL);
|
||||
// virtual bool Service(const char *, void * = NULL);
|
||||
virtual const char **SVDRPHelpPages(void);
|
||||
virtual cString SVDRPCommand(const char *, const char *, int &);
|
||||
};
|
||||
|
||||
cPluginSoftHdDevice::cPluginSoftHdDevice(void)
|
||||
@@ -608,13 +851,13 @@ cPluginSoftHdDevice::cPluginSoftHdDevice(void)
|
||||
// Initialize any member variables here.
|
||||
// DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
|
||||
// VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
cPluginSoftHdDevice::~cPluginSoftHdDevice(void)
|
||||
{
|
||||
// Clean up after yourself!
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
::SoftHdDeviceExit();
|
||||
}
|
||||
@@ -642,7 +885,7 @@ const char *cPluginSoftHdDevice::CommandLineHelp(void)
|
||||
*/
|
||||
bool cPluginSoftHdDevice::ProcessArgs(int argc, char *argv[])
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
return::ProcessArgs(argc, argv);
|
||||
}
|
||||
@@ -650,22 +893,21 @@ bool cPluginSoftHdDevice::ProcessArgs(int argc, char *argv[])
|
||||
bool cPluginSoftHdDevice::Initialize(void)
|
||||
{
|
||||
// Start any background activities the plugin shall perform.
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
MyDevice = new cSoftHdDevice();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
** Start any background activities the plugin shall perform.
|
||||
*/
|
||||
bool cPluginSoftHdDevice::Start(void)
|
||||
{
|
||||
const cDevice *primary;
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
// Start any background activities the plugin shall perform.
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
primary = cDevice::PrimaryDevice();
|
||||
if (MyDevice != primary) {
|
||||
if (!MyDevice->IsPrimaryDevice()) {
|
||||
isyslog("[softhddev] softhddevice is not the primary device!");
|
||||
if (ConfigMakePrimary) {
|
||||
// Must be done in the main thread
|
||||
@@ -685,7 +927,7 @@ bool cPluginSoftHdDevice::Start(void)
|
||||
|
||||
void cPluginSoftHdDevice::Stop(void)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
::Stop();
|
||||
}
|
||||
@@ -697,14 +939,33 @@ void cPluginSoftHdDevice::Housekeeping(void)
|
||||
// Perform any cleanup or other regular tasks.
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
** Create main menu entry.
|
||||
*/
|
||||
const char *cPluginSoftHdDevice::MainMenuEntry(void)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
return tr(MAINMENUENTRY);
|
||||
return NULL;
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
return ConfigHideMainMenuEntry ? NULL : tr(MAINMENUENTRY);
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
** Perform the action when selected from the main VDR menu.
|
||||
*/
|
||||
cOsdObject *cPluginSoftHdDevice::MainMenuAction(void)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
cDevice::PrimaryDevice()->StopReplay();
|
||||
Suspend();
|
||||
if (ShutdownHandler.GetUserInactiveTime()) {
|
||||
ShutdownHandler.SetUserInactive();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
** Called for every plugin once during every cycle of VDR's main program
|
||||
@@ -712,17 +973,95 @@ const char *cPluginSoftHdDevice::MainMenuEntry(void)
|
||||
*/
|
||||
void cPluginSoftHdDevice::MainThreadHook(void)
|
||||
{
|
||||
// dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
if (DoMakePrimary && MyDevice) {
|
||||
dsyslog("[softhddev]%s: switching primary device\n", __FUNCTION__);
|
||||
cDevice::SetPrimaryDevice(MyDevice->DeviceNumber() + 1);
|
||||
DoMakePrimary = 0;
|
||||
}
|
||||
// check if user is inactive, automatic enter suspend mode
|
||||
if (ShutdownHandler.IsUserInactive()) {
|
||||
// this is regular called, but guarded against double calls
|
||||
Suspend();
|
||||
}
|
||||
|
||||
::MainThreadHook();
|
||||
}
|
||||
|
||||
/**
|
||||
** Return our setup menu.
|
||||
*/
|
||||
cMenuSetupPage *cPluginSoftHdDevice::SetupMenu(void)
|
||||
{
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
return new cMenuSetupSoft;
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse setup parameters
|
||||
*/
|
||||
bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
|
||||
{
|
||||
int i;
|
||||
char buf[128];
|
||||
|
||||
//dsyslog("[softhddev]%s: '%s' = '%s'\n", __FUNCTION__, name, value);
|
||||
|
||||
if (!strcmp(name, "MakePrimary")) {
|
||||
ConfigMakePrimary = atoi(value);
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(name, "HideMainMenuEntry")) {
|
||||
ConfigHideMainMenuEntry = atoi(value);
|
||||
return true;
|
||||
}
|
||||
for (i = 0; i < RESOLUTIONS; ++i) {
|
||||
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Scaling");
|
||||
if (!strcmp(name, buf)) {
|
||||
ConfigVideoScaling[i] = atoi(value);
|
||||
VideoSetScaling(ConfigVideoScaling);
|
||||
return true;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Deinterlace");
|
||||
if (!strcmp(name, buf)) {
|
||||
ConfigVideoDeinterlace[i] = atoi(value);
|
||||
VideoSetDeinterlace(ConfigVideoDeinterlace);
|
||||
return true;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i],
|
||||
"SkipChromaDeinterlace");
|
||||
if (!strcmp(name, buf)) {
|
||||
ConfigVideoSkipChromaDeinterlace[i] = atoi(value);
|
||||
VideoSetSkipChromaDeinterlace(ConfigVideoSkipChromaDeinterlace);
|
||||
return true;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Denoise");
|
||||
if (!strcmp(name, buf)) {
|
||||
ConfigVideoDenoise[i] = atoi(value);
|
||||
VideoSetDenoise(ConfigVideoDenoise);
|
||||
return true;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Sharpen");
|
||||
if (!strcmp(name, buf)) {
|
||||
ConfigVideoSharpen[i] = atoi(value);
|
||||
VideoSetSharpen(ConfigVideoSharpen);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!strcmp(name, "AudioDelay")) {
|
||||
VideoSetAudioDelay(ConfigVideoAudioDelay = atoi(value));
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(name, "AudioPassthrough")) {
|
||||
CodecSetAudioPassthrough(ConfigAudioPassthrough = atoi(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
bool cPluginSoftHdDevice::Service(const char *Id, void *Data)
|
||||
@@ -732,52 +1071,42 @@ bool cPluginSoftHdDevice::Service(const char *Id, void *Data)
|
||||
return false;
|
||||
}
|
||||
|
||||
cOsdObject *cPluginSoftHdDevice::MainMenuAction(void)
|
||||
{
|
||||
// Perform the action when selected from the main VDR menu.
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// cPlugin SVDRP
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** Return SVDRP commands help pages.
|
||||
**
|
||||
** return a pointer to a list of help strings for all of the plugin's
|
||||
** SVDRP commands.
|
||||
*/
|
||||
const char **cPluginSoftHdDevice::SVDRPHelpPages(void)
|
||||
{
|
||||
// FIXME: translation?
|
||||
static const char *text[] = {
|
||||
"SUSP\n",
|
||||
" Suspend plugin",
|
||||
NULL
|
||||
};
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
** Handle SVDRP commands.
|
||||
*/
|
||||
cString cPluginSoftHdDevice::SVDRPCommand(const char *command,
|
||||
__attribute__ ((unused)) const char *option,
|
||||
__attribute__ ((unused)) int &reply_code)
|
||||
{
|
||||
if (!strcasecmp(command, "SUSP")) {
|
||||
Suspend();
|
||||
return "SoftHdDevice is suspended";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
** Return our setup menu.
|
||||
*/
|
||||
cMenuSetupPage *cPluginSoftHdDevice::SetupMenu(void)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
return new cMenuSetupSoft;
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse setup parameters
|
||||
*/
|
||||
bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
|
||||
{
|
||||
dsyslog("[softhddev]%s: '%s' = '%s'\n", __FUNCTION__, name, value);
|
||||
|
||||
// FIXME: handle the values
|
||||
if (!strcmp(name, "MakePrimary")) {
|
||||
ConfigMakePrimary = atoi(value);
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(name, "Deinterlace")) {
|
||||
VideoSetDeinterlace(ConfigVideoDeinterlace = atoi(value));
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(name, "Scaling")) {
|
||||
VideoSetScaling(ConfigVideoScaling = atoi(value));
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(name, "AudioDelay")) {
|
||||
VideoSetAudioDelay(ConfigVideoAudioDelay = atoi(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
VDRPLUGINCREATOR(cPluginSoftHdDevice); // Don't touch this!
|
||||
|
||||
72
vdr-softhddevice-9999.ebuild
Normal file
72
vdr-softhddevice-9999.ebuild
Normal file
@@ -0,0 +1,72 @@
|
||||
# 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"
|
||||
|
||||
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 )
|
||||
"
|
||||
|
||||
src_prepare() {
|
||||
vdr-plugin_src_prepare
|
||||
}
|
||||
|
||||
src_compile() {
|
||||
local myconf
|
||||
|
||||
myconf=""
|
||||
use vdpau && myconf="${myconf} -DUSE_VDPAU"
|
||||
use vaapi && myconf="${myconf} -DUSE_VAAPI"
|
||||
use alsa && myconf="${myconf} -DUSE_ALSA"
|
||||
use oss && myconf="${myconf} -DUSE_OSS"
|
||||
|
||||
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
|
||||
}
|
||||
80
video.h
80
video.h
@@ -1,7 +1,7 @@
|
||||
///
|
||||
/// @file video.h @brief Video module header file
|
||||
///
|
||||
/// Copyright (c) 2009 - 2011 by Johns. All Rights Reserved.
|
||||
/// Copyright (c) 2009 - 2012 by Johns. All Rights Reserved.
|
||||
///
|
||||
/// Contributor(s):
|
||||
///
|
||||
@@ -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,48 +58,66 @@ 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 scaling
|
||||
extern void VideoSetScaling(int);
|
||||
/// Set video mode.
|
||||
extern void VideoSetVideoMode(int, int, int, int);
|
||||
|
||||
/// set audio delay
|
||||
/// Set video fullscreen mode.
|
||||
extern void VideoSetFullscreen(int);
|
||||
|
||||
/// Set deinterlace.
|
||||
extern void VideoSetDeinterlace(int[]);
|
||||
|
||||
/// Set skip chroma deinterlace.
|
||||
extern void VideoSetSkipChromaDeinterlace(int[]);
|
||||
|
||||
/// Set scaling.
|
||||
extern void VideoSetScaling(int[]);
|
||||
|
||||
/// Set denoise.
|
||||
extern void VideoSetDenoise(int[]);
|
||||
|
||||
/// Set sharpen.
|
||||
extern void VideoSetSharpen(int[]);
|
||||
|
||||
/// Set audio delay.
|
||||
extern void VideoSetAudioDelay(int);
|
||||
|
||||
/// Clear OSD
|
||||
/// 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
|
||||
extern void VideoOsdInit(void); ///< Setup osd.
|
||||
extern void VideoOsdExit(void); ///< Cleanup osd.
|
||||
|
||||
extern void VideoFlushInput(void); ///< flush codec input buffers
|
||||
extern int VideoDecode(void); ///< decode
|
||||
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