57 Commits
v3.0 ... V3.3.1

Author SHA1 Message Date
jojo61
d553a8108d Fix AC3 dowmix 2021-01-26 09:17:39 +01:00
jojo61
cb4515f6b7 Minor updates 2021-01-14 10:40:29 +01:00
jojo61
277d7fbd86 More shader samples 2021-01-11 17:22:47 +01:00
jojo61
9347f2a502 Fix CUVID without placebo 2021-01-11 16:13:04 +01:00
jojo61
6dfd2d96aa Remove local cuda dependencie 2021-01-11 08:28:44 +01:00
jojo61
a7471e8800 Support for libplacebo API Version 106
Support for LIBPLACEBO with opengl -> needs API >= 106
2021-01-10 13:55:09 +01:00
jojo61
184cc1aa05 Fix playback for old PES recordings with vaapi 2020-08-18 11:35:11 +02:00
jojo61
072e1d6847 Fix vaapi for libplacebo > 87 2020-08-14 12:38:27 +02:00
jojo61
6c13195fda Remove hbbtv changes - not needed 2020-06-23 11:22:24 +02:00
jojo61
6a31404aa0 Optimize for hbbtv plugin 2020-06-22 16:35:37 +02:00
jojo61
a424a57036 Mangle with C and C++ 2020-06-16 08:49:03 +02:00
jojo61
05c2585238 Fix shaders for vaapi Version 2020-06-16 07:46:27 +02:00
jojo61
a28e368c1b Fix jumps between recording marks 2020-06-09 09:23:38 +02:00
jojo61
e4115f348b Update README 2020-06-07 12:56:51 +02:00
jojo61
03b770ce47 Support for mpv user shaders with libplacebo 2020-06-07 12:31:18 +02:00
jojo61
c7c4cb06a6 Fix aspect change within SD channels
Should fix #48
2020-06-01 17:15:07 +02:00
jojo61
a41f6b22fd Update for latest libplacebo 2020-05-15 16:37:06 +02:00
jojo61
628bad5006 Fix Build without PIP 2020-05-07 13:21:26 +02:00
jojo61
cb466dd894 No root for softhddrm needed anymore 2020-05-07 10:53:51 +02:00
jojo61
3578e3212d Merge pull request #54 from REELcoder/master
Fix PiP window size handling
2020-05-04 08:37:09 +02:00
jojo61
78337f5933 Update Minor Version 2020-05-01 12:08:12 +02:00
jojo61
2fea2ee69f Fix default Gamma in Initial Setup
Prepare für opengl placebo (not working yet)
2020-05-01 12:06:04 +02:00
jojo61
c1c345dd4d Merge pull request #53 from dnehring7/master
Remove unsupported auto-crop feature from source
2020-05-01 11:20:04 +02:00
Dirk Nehring
a3eedbff0c Remove unsupported auto-crop feature from source 2020-04-16 21:15:19 +02:00
jojo61
309ad1c90e Merge pull request #45 from dnehring7/master
Reindent all sources to common coding. Reworked aspect function.
2020-04-14 08:18:20 +00:00
Dirk Nehring
23651104f2 Reworked the aspect function. Now we calculate the display aspect from the pixel width and
pixel height (and not from the physical size, which was the root cause for rounding errors).
Cropping calculation is reworking, now the rounding is correct. I introduce a new aspect mode
"original" which displays the output with the original size (but after correction the
pixel aspect ratio). Tested with vaapi(X11) and vaapi(DRM) with and without libplacebo.
2020-04-13 18:04:57 +02:00
Dirk Nehring
36c208967e - Reindent all sources to common coding style again.
- Fix compile bug occurred with gcc10 (-fno-common is now default)
2020-04-10 16:17:23 +02:00
REELcoder
d1a1329beb Fix PiP window size handling 2020-04-06 20:45:01 +02:00
jojo61
5875e10479 Honor Softstartflag 2020-04-01 12:45:33 +02:00
jojo61
a6e65d953e Fix issue #42 and changes for faster a/v sync 2020-03-31 13:57:43 +02:00
jojo61
fecb81486d Revert Fix for tvguide 2020-03-29 18:36:54 +02:00
jojo61
f756334187 Fix epggrid scolling with tvguide 2020-03-26 12:36:00 +01:00
jojo61
14ba527a45 Fix issue #40 2020-03-16 16:31:47 +01:00
jojo61
ec09dbfb25 Fix issue #41 2020-03-13 08:19:58 +01:00
jojo61
34b1fccb28 Fis issues #36 #37 #38 2020-03-12 08:05:39 +01:00
jojo61
5586618c6e More fixes 2020-03-09 22:59:27 +01:00
jojo61
4dbf2dcc84 Fixes for Maintainer 2020-03-09 16:15:01 +01:00
jojo61
74a2285af0 Fixed typo 2020-03-06 13:58:56 +01:00
jojo61
b2bff4ebd0 Minor fix for vaapi compile 2020-03-06 13:03:21 +01:00
jojo61
84501d314e Switch to ffnvcodec headers 2020-03-06 12:42:14 +01:00
jojo61
04e1b8732d correct conversion BT709 colors to sRGB 2020-03-06 11:51:20 +01:00
jojo61
3e649a5cea Rework shaders - Better HLG Colors 2020-03-06 09:11:08 +01:00
jojo61
feb7479ff8 Update Readme 2020-03-06 09:02:27 +01:00
jojo61
3590eadbaa Update Readme 2020-03-06 08:59:24 +01:00
jojo61
6c0f80979f Try Fix for tvguide 2020-03-04 16:34:40 +01:00
jojo61
189d8cfa53 Fix issue #34 2020-03-04 15:55:57 +01:00
jojo61
73b355c52d Fixed issue #29 2020-03-02 16:20:34 +01:00
jojo61
3d23288bdc Fixed issue #32 2020-03-02 16:11:33 +01:00
jojo61
b1a642e64a Fixed issue #31 2020-03-02 16:06:27 +01:00
jojo61
1b7bfd2087 More openglosd fixes 2020-02-27 16:24:07 +01:00
jojo61
03e69b5e26 Use FT_ULong instead of uint 2020-02-26 16:52:48 +01:00
jojo61
a5b81f8de1 Set cache to zero for broken vaapi 2020-02-20 16:00:16 +01:00
jojo61
2485929c2b more OSD stuff 2020-02-19 15:54:09 +01:00
jojo61
b9fed82109 OSD fixes 2020-02-18 22:02:53 +01:00
jojo61
49db402de6 Fix in makefile 2020-02-02 13:28:36 +01:00
jojo61
7ce842b989 More info in Menue 2020-02-02 13:26:51 +01:00
jojo61
9d0417045e Fixed vaapi SD streams 2020-02-02 11:15:17 +01:00
20 changed files with 2861 additions and 2003 deletions

View File

@@ -9,27 +9,31 @@
### Configuration (edit this for your needs) ### Configuration (edit this for your needs)
# config as needed # comment out if not needed
# what kind of decoder do we make - # what kind of decoder do we make -
# if VAAPI is enabled the pluginname is softhdvaapi # if VAAPI is enabled the pluginname is softhdvaapi
# if CUVID is enabled the pluginname is softhdcuvid # if CUVID is enabled the pluginname is softhdcuvid
# if DRM is enabled the pluginname is softhddrm # if DRM is enabled the pluginname is softhddrm
VAAPI ?= 0 VAAPI ?= 0
CUVID ?= 1 CUVID ?= 0
# if you enable DRM then the plugin will only run without X server # if you enable DRM then the plugin will only run without X server
# only valid for VAAPI # only valid for VAAPI
# does not work with libplacebo DRM ?= 0
DRM= ?= 0
# use libplacebo - available for both decoders but not for DRM # use libplacebo -
LIBPLACEBO ?= 0 # available for all decoders but for DRM you need LIBPLACEBO_GL
LIBPLACEBO ?= 1
LIBPLACEBO_GL ?= 0
# use YADIF deint - only available with cuvid # use YADIF deint - only available with cuvid
#YADIF=1 #YADIF=1
# use gamma correction
#GAMMA ?= 0
CONFIG := #-DDEBUG # remove # to enable debug output CONFIG := #-DDEBUG # remove # to enable debug output
@@ -39,10 +43,43 @@ CONFIG := #-DDEBUG # remove # to enable debug output
#--------------------- no more config needed past this point-------------------------------- #--------------------- no more config needed past this point--------------------------------
# sanitize selections --------
ifneq "$(MAKECMDGOALS)" "clean"
ifneq "$(MAKECMDGOALS)" "indent"
ifeq ($(VAAPI),0)
ifeq ($(CUVID),0)
ifeq ($(DRM),0)
$(error Please define a plugin in the Makefile)
exit 1;
endif
endif
endif
ifeq ($(CUVID),1)
ifeq ($(DRM),1)
$(error Missmatch in Plugin selection)
exit 1;
endif
endif
ifeq ($(CUVID),1)
ifeq ($(VAAPI),1)
$(error Missmatch in Plugin selection)
exit 1;
endif
endif
endif # MAKECMDGOALS!=indent
endif # MAKECMDGOALS!=clean
#--------------------------
PLUGIN = softhdcuvid PLUGIN = softhdcuvid
# support OPENGLOSD always needed # support OPENGLOSD always needed
@@ -152,19 +189,27 @@ ifeq ($(VAAPI),1)
CONFIG += -DVAAPI CONFIG += -DVAAPI
#LIBPLACEBO=1 #LIBPLACEBO=1
PLUGIN = softhdvaapi PLUGIN = softhdvaapi
endif
ifeq ($(LIBPLACEBO_GL),1)
CONFIG += -DPLACEBO_GL -DPLACEBO
LIBS += -lepoxy
LIBS += -lplacebo
else
LIBS += -lEGL LIBS += -lEGL
endif endif
ifeq ($(LIBPLACEBO),1) ifeq ($(LIBPLACEBO),1)
CONFIG += -DPLACEBO CONFIG += -DPLACEBO
LIBS += -lEGL
LIBS += -lplacebo
endif endif
ifeq ($(DRM),1) ifeq ($(DRM),1)
PLUGIN = softhddrm PLUGIN = softhddrm
CONFIG += -DUSE_DRM -DVAAPI CONFIG += -DUSE_DRM -DVAAPI
_CFLAGS += $(shell pkg-config --cflags libdrm) _CFLAGS += $(shell pkg-config --cflags libdrm)
LIBS += -lgbm -ldrm LIBS += -lgbm -ldrm -lEGL
LIBS += -lEGL
endif endif
@@ -177,7 +222,9 @@ CONFIG += -DYADIF # Yadif only with CUVID
endif endif
endif endif
ifeq ($(GAMMA),1)
CONFIG += -DGAMMA
endif
ARCHIVE = $(PLUGIN)-$(VERSION) ARCHIVE = $(PLUGIN)-$(VERSION)
@@ -252,18 +299,13 @@ endif
_CFLAGS += $(shell pkg-config --cflags x11 x11-xcb xcb xcb-icccm) _CFLAGS += $(shell pkg-config --cflags x11 x11-xcb xcb xcb-icccm)
LIBS += -lrt $(shell pkg-config --libs x11 x11-xcb xcb xcb-icccm) LIBS += -lrt $(shell pkg-config --libs x11 x11-xcb xcb xcb-icccm)
_CFLAGS += -I/usr/local/cuda/include
_CFLAGS += -I./opengl -I./ _CFLAGS += -I./opengl -I./
LIBS += -L/usr/lib64 LIBS += -L/usr/lib64
LIBS += -L/usr/local/cuda/lib64
ifeq ($(LIBPLACEBO),1)
LIBS += -lplacebo
endif
ifeq ($(CUVID),1) ifeq ($(CUVID),1)
LIBS += -lcuda -L/usr/local/cuda/targets/x86_64-linux/lib -lcudart -lnvcuvid LIBS += -lcuda -lnvcuvid
endif endif
LIBS += -lGLEW -lGLU -ldl -lglut LIBS += -lGLEW -lGLU -ldl -lglut
@@ -284,9 +326,14 @@ override CFLAGS += $(_CFLAGS) $(DEFINES) $(INCLUDES) \
### The object files (add further files here): ### The object files (add further files here):
OBJS = softhdcuvid.o softhddev.o video.o audio.o codec.o ringbuffer.o OBJS = softhdcuvid.o softhddev.o video.o audio.o codec.o ringbuffer.o openglosd.o
ifeq ($(OPENGLOSD),1) ifeq ($(GAMMA),1)
OBJS += openglosd.o OBJS += colorramp.o
ifeq ($(DRM),1)
OBJS += gamma-drm.o
else
OBJS += gamma-vidmode.o
endif
endif endif
SRCS = $(wildcard $(OBJS:.o=.c)) *.cpp SRCS = $(wildcard $(OBJS:.o=.c)) *.cpp

128
README.md
View File

@@ -23,8 +23,8 @@ $Id: 5267da021a68b4a727b479417334bfbe67bbba14 $
A software and GPU emulated UHD output device plugin for VDR. A software and GPU emulated UHD output device plugin for VDR.
o Video decoder CPU / VDPAU o Video decoder CUVID or VAAPI
o Video output opengl o Video output opengl or DRM
o Audio FFMpeg / Alsa / Analog o Audio FFMpeg / Alsa / Analog
o Audio FFMpeg / Alsa / Digital o Audio FFMpeg / Alsa / Digital
o Audio FFMpeg / OSS / Analog o Audio FFMpeg / OSS / Analog
@@ -32,9 +32,10 @@ A software and GPU emulated UHD output device plugin for VDR.
o Software volume, compression, normalize and channel resample o Software volume, compression, normalize and channel resample
o VDR ScaleVideo API o VDR ScaleVideo API
o CUDA deinterlacer o CUDA deinterlacer
o Autocrop
o Suspend / Dettach o Suspend / Dettach
o PIP (Picture-in-Picture) (not working yet) o Support for ambilight
o Support for Screencopy
o PIP (Picture-in-Picture) (only for CUVID)
To compile you must have the 'requires' installed. To compile you must have the 'requires' installed.
@@ -47,34 +48,20 @@ Current Status NVIDIA:
The CUDA driver supports HEVC with 8 Bit and 10 Bit up to UHD resolution. Opengl is able to output also 10 Bit, but NVIDIA does not support to output 10 Bit via HDMI. The CUDA driver supports HEVC with 8 Bit and 10 Bit up to UHD resolution. Opengl is able to output also 10 Bit, but NVIDIA does not support to output 10 Bit via HDMI.
Only via DisplayPort you can get 10 Bit output to a compatible screen. This is a restriction from NVIDIA. Only via DisplayPort you can get 10 Bit output to a compatible screen. This is a restriction from NVIDIA.
Current Status with VAAPI Current Status with VAAPI:
You need libplacebo. I tested it with Intel VAAPI. If you have problmes with the shaders then copy the drirc file in your home directory as .drirc
It is still beta and I tested it with Intel VAAPI. If you have problmes with the shaders then copy the drirc file in your home directory as .drirc AMD VAAPI is broken by AMD and will not work currently.
AMD VAAPI is broken by AMD and will not work currently. The vaapi_deinterlace is broken and the amdgpu driver is instable. I have not testet with amdgpupro
You have to adapt the Makefile to your needs. I use FFMPEG 4.0 You have to adapt the Makefile to your needs. I use FFMPEG 4.0
The Makefile expects the CUDA SDK in /usr/local/cuda. Currently it is tested with CUDA 10
Unfortunatly older FFMEGs has a bug with deinterlacing cuda frames. Best to get the latest FFMPEG Version.
Otherwise you have to patch the file in libavcodec/cuviddec.c
Somewhere near line 860 and 1066 depending on your release:
old:
ctx->frame_queue = av_fifo_alloc(ctx->nb_surfaces * sizeof(CuvidParsedFrame));
new:
ctx->frame_queue = av_fifo_alloc((ctx->nb_surfaces + 2 ) * sizeof(CuvidParsedFrame));
This Version supports building with libplacebo. https://github.com/haasn/libplacebo This Version supports building with libplacebo. https://github.com/haasn/libplacebo
You have to enable it in the Makefile and install libplacebo yourself. You have to enable it in the Makefile and install libplacebo yourself.
At the moment this is Work in progress.
It also needs the NVIDIA driver 410.48 or newer as well as CUDA 10. It also needs the NVIDIA driver 410.48 or newer as well as CUDA 10.
In the settings you can enable a correction for Colorblindness. First you have to decide what kind of colorblindness to use. And then the faktor of correction. If the faktor is negativ than the selected type of colorblindness is simulated. If the faktor is positiv then the colors are enhanced to try to correct the deficiency. I recommend to use libplacebo. It has much better scaler and does colorconversion for HDR the correct way.
Also you can enable a Scaler Test feature. When enabled then the screen is split.On the left half you will see the scaler defined by Scaler Test and on the right side you will see the scaler defined at the Resolution setting. There is as small black line between the halfs to remaind you that Scaler Test is activ. If your FFMEG supports it then you can enable YADIF in the Makefile and select between the buildin NVIDIA CUDA deinterlacer and the YADIF cuda deinterlacer.
If your FFMEG supports it then you can enable YADIF in the Makefile and select btween the buildin NVIDIA CUDA deinterlacer and the YADIF cuda deinterlacer.
Good luck Good luck
jojo61 jojo61
@@ -82,7 +69,17 @@ jojo61
Quickstart: Quickstart:
----------- -----------
Just type make and use. You have to adapt the Makefile. There are 3 possible Version that you can build:
softhdcuvid
This is for NVIDA cards and uses cuvid as decoder. It uses xcb for output and needs a X Server to run.
softhdvaapi
This is for INTEL cards and uses Vaapi as decoder. It uses xcb for output and needs a X Server to run.
softhddrm
This is for INTEL cards and also uses Vaapi as decoder. It uses the DRM API for output and
runs without X Server. There are several commandline options to select the resolution and refresh rate.
Install: Install:
-------- --------
@@ -98,6 +95,34 @@ Install:
You have to start vdr with -P 'softhdcuvid -d :0.0 ..<more option>.. ' You have to start vdr with -P 'softhdcuvid -d :0.0 ..<more option>.. '
Beginners Guide for libplacebo:
-------------------------------
When using libplacebo you will find several config options.
First of all you need to set the right scaler for each resolution:
Best you beginn with setting all to "bilinear". If that works ok for you, you can try to change them
for more advanced scaler. I use ewa_robidouxsharp on my GTX1050, but your mileage may vary.
Unfortunatly on INTEL not all scalers may work or crash.
You can enable a Scaler Test feature. When enabled then the screen is split.On the left half you will
see the scaler defined by Scaler Test and on the right side you will see the scaler defined at the
Resolution setting. There is as small black line between the halfs to remaind you that Scaler Test
is activ.
Then you should set the Monitor Colorspace to "sRGB". This guarantees you the best colors on your screen.
At the moment all calculations internaly are done in RGB space and all cards output also RGB.
If you are colorblind you could try to remedy this with the Colorblind Settings. Realy only needed
in rare cases.
All other settings can be in their default state.
Beginning with libplacebo API 58 user shaders from mpv are supported. Use -S parameter to set the shader.
The plugins searches the shaders in $ConfigDir/plugins/shaders for the shaders. One example shader is
provided in the shader subdirectory. Copy it to e.g.: /etc/vdr/plugins/shaders and then start
vdr -P 'softhdcuvid -S filmgrain.glsl ...'
Setup: environment Setup: environment
------ ------
@@ -211,18 +236,6 @@ Setup: /etc/vdr/setup.conf
0 = default (336 ms) 0 = default (336 ms)
1 - 1000 = size of the buffer in ms 1 - 1000 = size of the buffer in ms
softhddevice.AutoCrop.Interval = 0
0 disables auto-crop
n each 'n' frames auto-crop is checked.
softhddevice.AutoCrop.Delay = 0
if auto-crop is over 'n' intervals the same, the cropping is
used.
softhddevice.AutoCrop.Tolerance = 0
if detected crop area is too small, cut max 'n' pixels at top and
bottom.
softhddevice.Background = 0 softhddevice.Background = 0
32bit RGBA background color 32bit RGBA background color
(Red * 16777216 + Green * 65536 + Blue * 256 + Alpha) (Red * 16777216 + Green * 65536 + Blue * 256 + Alpha)
@@ -262,11 +275,13 @@ Setup: /etc/vdr/setup.conf
0 pan and scan 0 pan and scan
1 letter box 1 letter box
2 center cut-out 2 center cut-out
3 original
softhddevice.VideoOtherDisplayFormat = 1 softhddevice.VideoOtherDisplayFormat = 1
0 pan and scan 0 pan and scan
1 pillar box 1 pillar box
2 center cut-out 2 center cut-out
3 original
softhddevice.pip.X = 79 softhddevice.pip.X = 79
softhddevice.pip.Y = 78 softhddevice.pip.Y = 78
@@ -293,22 +308,6 @@ Setup: /etc/vdr/setup.conf
PIP alternative video window position and size in percent. PIP alternative video window position and size in percent.
Setup: /etc/vdr/remote.conf
------
Add "XKeySym." definitions to /etc/vdr/remote.conf to control
the vdr and plugin with the connected input device.
fe.
XKeySym.Up Up
XKeySym.Down Down
...
Additional to the x11 input sends the window close button "Close".
fe.
XKeySym.Power Close
Commandline: Commandline:
------------ ------------
@@ -356,25 +355,4 @@ Running:
Known Bugs: Known Bugs:
----------- -----------
SD Stream not working very well SD Streams not working very well on vaapi
RESUME starts wirh black screen (channelswitch needed)
Requires:
---------
media-video/vdr (version >=1.7.xx)
Video Disk Recorder - turns a pc into a powerful set top box
for DVB.
http://www.tvdr.de/
media-video/ffmpeg (version >=0.7)
Complete solution to record, convert and stream audio and
video. Includes libavcodec and libswresample.
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
Optional:

75
audio.c
View File

@@ -86,6 +86,8 @@
#define __USE_GNU #define __USE_GNU
#endif #endif
#include <pthread.h> #include <pthread.h>
#include <sys/syscall.h>
#include <sys/resource.h>
#ifndef HAVE_PTHREAD_NAME #ifndef HAVE_PTHREAD_NAME
/// only available with newer glibc /// only available with newer glibc
#define pthread_setname_np(thread, name) #define pthread_setname_np(thread, name)
@@ -144,7 +146,6 @@ static volatile char AudioRunning; ///< thread running / stopped
static volatile char AudioPaused; ///< audio paused static volatile char AudioPaused; ///< audio paused
static volatile char AudioVideoIsReady; ///< video ready start early static volatile char AudioVideoIsReady; ///< video ready start early
static int AudioSkip; ///< skip audio to sync to video static int AudioSkip; ///< skip audio to sync to video
int AudioDelay; /// delay audio to sync to video
static const int AudioBytesProSample = 2; ///< number of bytes per sample static const int AudioBytesProSample = 2; ///< number of bytes per sample
@@ -688,7 +689,7 @@ static int AudioRingAdd(unsigned sample_rate, int channels, int passthrough)
AudioRing[AudioRingWrite].InChannels = channels; AudioRing[AudioRingWrite].InChannels = channels;
AudioRing[AudioRingWrite].HwSampleRate = sample_rate; AudioRing[AudioRingWrite].HwSampleRate = sample_rate;
AudioRing[AudioRingWrite].HwChannels = AudioChannelMatrix[u][channels]; AudioRing[AudioRingWrite].HwChannels = AudioChannelMatrix[u][channels];
AudioRing[AudioRingWrite].PTS = INT64_C(0x8000000000000000); AudioRing[AudioRingWrite].PTS = AV_NOPTS_VALUE;
RingBufferReset(AudioRing[AudioRingWrite].RingBuffer); RingBufferReset(AudioRing[AudioRingWrite].RingBuffer);
Debug(3, "audio: %d ring buffer prepared\n", atomic_read(&AudioRingFilled) + 1); Debug(3, "audio: %d ring buffer prepared\n", atomic_read(&AudioRingFilled) + 1);
@@ -1156,7 +1157,7 @@ static int64_t AlsaGetDelay(void)
//Debug(3, "audio/alsa: %ld frames delay ok, but not running\n", delay); //Debug(3, "audio/alsa: %ld frames delay ok, but not running\n", delay);
#endif #endif
} }
//Debug(3, "audio/alsa: %ld frames hw delay\n", delay); Debug(4, "audio/alsa: %ld frames hw delay\n", delay);
// delay can be negative, when underrun occur // delay can be negative, when underrun occur
if (delay < 0) { if (delay < 0) {
@@ -1291,7 +1292,6 @@ static int AlsaSetup(int *freq, int *channels, int passthrough)
Info(_("audio/alsa: start delay %ums\n"), (AudioStartThreshold * 1000) Info(_("audio/alsa: start delay %ums\n"), (AudioStartThreshold * 1000)
/ (*freq * *channels * AudioBytesProSample)); / (*freq * *channels * AudioBytesProSample));
} }
return 0; return 0;
} }
@@ -1989,7 +1989,7 @@ static int AudioNextRing(void)
// stop, if not enough in next buffer // stop, if not enough in next buffer
used = RingBufferUsedBytes(AudioRing[AudioRingRead].RingBuffer); used = RingBufferUsedBytes(AudioRing[AudioRingRead].RingBuffer);
if (AudioStartThreshold * 10 < used || (AudioVideoIsReady && AudioStartThreshold < used)) { if (AudioStartThreshold * 4 < used || (AudioVideoIsReady && AudioStartThreshold < used)) {
return 0; return 0;
} }
return 1; return 1;
@@ -2004,6 +2004,7 @@ static void *AudioPlayHandlerThread(void *dummy)
{ {
Debug(3, "audio: play thread started\n"); Debug(3, "audio: play thread started\n");
prctl(PR_SET_NAME, "cuvid audio", 0, 0, 0); prctl(PR_SET_NAME, "cuvid audio", 0, 0, 0);
for (;;) { for (;;) {
// check if we should stop the thread // check if we should stop the thread
if (AudioThreadStop) { if (AudioThreadStop) {
@@ -2020,9 +2021,10 @@ static void *AudioPlayHandlerThread(void *dummy)
} while (!AudioRunning); } while (!AudioRunning);
pthread_mutex_unlock(&AudioMutex); pthread_mutex_unlock(&AudioMutex);
Debug(3, "audio: ----> %dms start\n", (AudioUsedBytes() * 1000) Debug(3, "audio: ----> %dms %d start\n", (AudioUsedBytes() * 1000)
/ (!AudioRing[AudioRingWrite].HwSampleRate + !AudioRing[AudioRingWrite].HwChannels + / (!AudioRing[AudioRingWrite].HwSampleRate + !AudioRing[AudioRingWrite].HwChannels +
AudioRing[AudioRingWrite].HwSampleRate * AudioRing[AudioRingWrite].HwChannels * AudioBytesProSample)); AudioRing[AudioRingWrite].HwSampleRate * AudioRing[AudioRingWrite].HwChannels * AudioBytesProSample),
AudioUsedBytes());
do { do {
int filled; int filled;
@@ -2056,10 +2058,8 @@ static void *AudioPlayHandlerThread(void *dummy)
AudioUsedModule->FlushBuffers(); AudioUsedModule->FlushBuffers();
atomic_sub(flush, &AudioRingFilled); atomic_sub(flush, &AudioRingFilled);
if (AudioNextRing()) { if (AudioNextRing()) {
Debug(3, "audio: HandlerThread break after flush\n");
break; break;
} }
Debug(3, "audio: continue after flush\n");
} }
// try to play some samples // try to play some samples
err = 0; err = 0;
@@ -2284,18 +2284,18 @@ void AudioEnqueue(const void *samples, int count)
} }
// forced start or enough video + audio buffered // forced start or enough video + audio buffered
// for some exotic channels * 4 too small // for some exotic channels * 4 too small
if (AudioStartThreshold * 10 < n || (AudioVideoIsReady if (AudioStartThreshold * 4 < n || (AudioVideoIsReady
// if ((AudioVideoIsReady // if ((AudioVideoIsReady
&& AudioStartThreshold < n)) { && AudioStartThreshold < n)) {
// restart play-back // restart play-back
// no lock needed, can wakeup next time // no lock needed, can wakeup next time
AudioRunning = 1; AudioRunning = 1;
pthread_cond_signal(&AudioStartCond); pthread_cond_signal(&AudioStartCond);
Debug(3, "Start on AudioEnque\n"); Debug(3, "Start on AudioEnque Threshold %d n %d\n", AudioStartThreshold, n);
} }
} }
// Update audio clock (stupid gcc developers thinks INT64_C is unsigned) // Update audio clock (stupid gcc developers thinks INT64_C is unsigned)
if (AudioRing[AudioRingWrite].PTS != (int64_t) INT64_C(0x8000000000000000)) { if (AudioRing[AudioRingWrite].PTS != (int64_t) AV_NOPTS_VALUE) {
AudioRing[AudioRingWrite].PTS += ((int64_t) count * 90 * 1000) AudioRing[AudioRingWrite].PTS += ((int64_t) count * 90 * 1000)
/ (AudioRing[AudioRingWrite].HwSampleRate * AudioRing[AudioRingWrite].HwChannels * AudioBytesProSample); / (AudioRing[AudioRingWrite].HwSampleRate * AudioRing[AudioRingWrite].HwChannels * AudioBytesProSample);
} }
@@ -2311,13 +2311,13 @@ void AudioVideoReady(int64_t pts)
int64_t audio_pts; int64_t audio_pts;
size_t used; size_t used;
if (pts == (int64_t) INT64_C(0x8000000000000000)) { if (pts == (int64_t) AV_NOPTS_VALUE) {
Debug(3, "audio: a/v start, no valid video\n"); Debug(3, "audio: a/v start, no valid video\n");
return; return;
} }
// no valid audio known // no valid audio known
if (!AudioRing[AudioRingWrite].HwSampleRate || !AudioRing[AudioRingWrite].HwChannels if (!AudioRing[AudioRingWrite].HwSampleRate || !AudioRing[AudioRingWrite].HwChannels
|| AudioRing[AudioRingWrite].PTS == (int64_t) INT64_C(0x8000000000000000)) { || AudioRing[AudioRingWrite].PTS == (int64_t) AV_NOPTS_VALUE) {
Debug(3, "audio: a/v start, no valid audio\n"); Debug(3, "audio: a/v start, no valid audio\n");
AudioVideoIsReady = 1; AudioVideoIsReady = 1;
return; return;
@@ -2340,9 +2340,9 @@ void AudioVideoReady(int64_t pts)
// buffer ~15 video frames // buffer ~15 video frames
// FIXME: HDTV can use smaller video buffer // FIXME: HDTV can use smaller video buffer
skip = pts - 15 * 20 * 90 - AudioBufferTime * 90 - audio_pts + VideoAudioDelay; skip = pts - 0 * 20 * 90 - AudioBufferTime * 90 - audio_pts + VideoAudioDelay;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "%dms %dms %dms\n", (int)(pts - audio_pts) / 90, VideoAudioDelay / 90, skip / 90); // fprintf(stderr, "a/v-diff %dms a/v-delay %dms skip %dms Audiobuffer %d\n", (int)(pts - audio_pts) / 90, VideoAudioDelay / 90, skip / 90,AudioBufferTime);
#endif #endif
// guard against old PTS // guard against old PTS
if (skip > 0 && skip < 4000 * 90) { if (skip > 0 && skip < 4000 * 90) {
@@ -2353,9 +2353,9 @@ void AudioVideoReady(int64_t pts)
AudioSkip = skip - used; AudioSkip = skip - used;
skip = used; skip = used;
} }
Debug(3, "audio: sync advance %dms %d/%zd\n", Debug(3, "audio: sync advance %dms %d/%zd Rest %d\n",
(skip * 1000) / (AudioRing[AudioRingWrite].HwSampleRate * AudioRing[AudioRingWrite].HwChannels * (skip * 1000) / (AudioRing[AudioRingWrite].HwSampleRate * AudioRing[AudioRingWrite].HwChannels *
AudioBytesProSample), skip, used); AudioBytesProSample), skip, used, AudioSkip);
RingBufferReadAdvance(AudioRing[AudioRingWrite].RingBuffer, skip); RingBufferReadAdvance(AudioRing[AudioRingWrite].RingBuffer, skip);
used = RingBufferUsedBytes(AudioRing[AudioRingWrite].RingBuffer); used = RingBufferUsedBytes(AudioRing[AudioRingWrite].RingBuffer);
@@ -2363,7 +2363,6 @@ void AudioVideoReady(int64_t pts)
Debug(3, "No audio skip -> should skip %d\n", skip / 90); Debug(3, "No audio skip -> should skip %d\n", skip / 90);
} }
// FIXME: skip<0 we need bigger audio buffer // FIXME: skip<0 we need bigger audio buffer
// enough video + audio buffered // enough video + audio buffered
if (AudioStartThreshold < used) { if (AudioStartThreshold < used) {
AudioRunning = 1; AudioRunning = 1;
@@ -2373,38 +2372,7 @@ void AudioVideoReady(int64_t pts)
} }
AudioVideoIsReady = 1; AudioVideoIsReady = 1;
#if 0
if (AudioRing[AudioRingWrite].HwSampleRate && AudioRing[AudioRingWrite].HwChannels) {
if (pts != (int64_t) INT64_C(0x8000000000000000)
&& AudioRing[AudioRingWrite].PTS != (int64_t) INT64_C(0x8000000000000000)) {
Debug(3, "audio: a/v %d %s\n", (int)(pts - AudioRing[AudioRingWrite].PTS) / 90,
AudioRunning ? "running" : "stopped");
}
Debug(3, "audio: start %4zdms %s|%s video ready\n",
(RingBufferUsedBytes(AudioRing[AudioRingWrite].RingBuffer) * 1000)
/ (AudioRing[AudioRingWrite].HwSampleRate * AudioRing[AudioRingWrite].HwChannels * AudioBytesProSample),
Timestamp2String(pts), Timestamp2String(AudioRing[AudioRingWrite].PTS));
if (!AudioRunning) {
size_t used;
used = RingBufferUsedBytes(AudioRing[AudioRingWrite].RingBuffer);
// enough video + audio buffered
if (AudioStartThreshold < used) {
// too much audio buffered, skip it
if (AudioStartThreshold < used) {
Debug(3, "audio: start %4zdms skip video ready\n", ((used - AudioStartThreshold) * 1000)
/ (AudioRing[AudioRingWrite].HwSampleRate * AudioRing[AudioRingWrite].HwChannels *
AudioBytesProSample));
RingBufferReadAdvance(AudioRing[AudioRingWrite].RingBuffer, used - AudioStartThreshold);
}
AudioRunning = 1;
pthread_cond_signal(&AudioStartCond);
}
}
}
AudioVideoIsReady = 1;
#endif
} }
/** /**
@@ -2439,7 +2407,7 @@ void AudioFlushBuffers(void)
AudioRing[AudioRingWrite].HwChannels = AudioRing[old].HwChannels; AudioRing[AudioRingWrite].HwChannels = AudioRing[old].HwChannels;
AudioRing[AudioRingWrite].InSampleRate = AudioRing[old].InSampleRate; AudioRing[AudioRingWrite].InSampleRate = AudioRing[old].InSampleRate;
AudioRing[AudioRingWrite].InChannels = AudioRing[old].InChannels; AudioRing[AudioRingWrite].InChannels = AudioRing[old].InChannels;
AudioRing[AudioRingWrite].PTS = INT64_C(0x8000000000000000); AudioRing[AudioRingWrite].PTS = AV_NOPTS_VALUE;
RingBufferReadAdvance(AudioRing[AudioRingWrite].RingBuffer, RingBufferReadAdvance(AudioRing[AudioRingWrite].RingBuffer,
RingBufferUsedBytes(AudioRing[AudioRingWrite].RingBuffer)); RingBufferUsedBytes(AudioRing[AudioRingWrite].RingBuffer));
Debug(3, "audio: reset video ready\n"); Debug(3, "audio: reset video ready\n");
@@ -2529,6 +2497,7 @@ void AudioSetClock(int64_t pts)
Debug(4, "audio: set clock %s -> %s pts\n", Timestamp2String(AudioRing[AudioRingWrite].PTS), Debug(4, "audio: set clock %s -> %s pts\n", Timestamp2String(AudioRing[AudioRingWrite].PTS),
Timestamp2String(pts)); Timestamp2String(pts));
} }
// printf("Audiosetclock pts %#012" PRIx64 " %d\n",pts,RingBufferUsedBytes(AudioRing[AudioRingWrite].RingBuffer));
AudioRing[AudioRingWrite].PTS = pts; AudioRing[AudioRingWrite].PTS = pts;
} }
@@ -2540,7 +2509,7 @@ void AudioSetClock(int64_t pts)
int64_t AudioGetClock(void) int64_t AudioGetClock(void)
{ {
// (cast) needed for the evil gcc // (cast) needed for the evil gcc
if (AudioRing[AudioRingRead].PTS != (int64_t) INT64_C(0x8000000000000000)) { if (AudioRing[AudioRingRead].PTS != (int64_t) AV_NOPTS_VALUE) {
int64_t delay; int64_t delay;
// delay zero, if no valid time stamp // delay zero, if no valid time stamp
@@ -2551,7 +2520,7 @@ int64_t AudioGetClock(void)
return AudioRing[AudioRingRead].PTS + 0 * 90 - delay; return AudioRing[AudioRingRead].PTS + 0 * 90 - delay;
} }
} }
return INT64_C(0x8000000000000000); return AV_NOPTS_VALUE;
} }
/** /**

468
codec.c
View File

@@ -75,9 +75,6 @@
#endif #endif
#include <pthread.h> #include <pthread.h>
#ifdef MAIN_H
#include MAIN_H
#endif
#include "iatomic.h" #include "iatomic.h"
#include "misc.h" #include "misc.h"
#include "video.h" #include "video.h"
@@ -259,18 +256,18 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
#endif #endif
#ifdef RASPI #ifdef RASPI
switch (codec_id) { switch (codec_id) {
case AV_CODEC_ID_MPEG2VIDEO: case AV_CODEC_ID_MPEG2VIDEO:
name = "mpeg2_v4l2m2m"; name = "mpeg2_v4l2m2m";
break; break;
case AV_CODEC_ID_H264: case AV_CODEC_ID_H264:
name = "h264_v4l2m2m"; name = "h264_v4l2m2m";
// name = "h264_mmal"; // name = "h264_mmal";
break; break;
case AV_CODEC_ID_HEVC: case AV_CODEC_ID_HEVC:
name = "hevc_v4l2m2m"; name = "hevc_v4l2m2m";
break; break;
} }
#endif #endif
if (name && (video_codec = avcodec_find_decoder_by_name(name))) { if (name && (video_codec = avcodec_find_decoder_by_name(name))) {
Debug(3, "codec: decoder found\n"); Debug(3, "codec: decoder found\n");
} else if ((video_codec = avcodec_find_decoder(codec_id)) == NULL) { } else if ((video_codec = avcodec_find_decoder(codec_id)) == NULL) {
@@ -285,15 +282,15 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
if (!(decoder->VideoCtx = avcodec_alloc_context3(video_codec))) { if (!(decoder->VideoCtx = avcodec_alloc_context3(video_codec))) {
Fatal(_("codec: can't allocate video codec context\n")); Fatal(_("codec: can't allocate video codec context\n"));
} }
#ifndef RASPI #ifndef RASPI
if (!HwDeviceContext) { if (!HwDeviceContext) {
Fatal("codec: no hw device context to be used"); Fatal("codec: no hw device context to be used");
} }
decoder->VideoCtx->hw_device_ctx = av_buffer_ref(HwDeviceContext); decoder->VideoCtx->hw_device_ctx = av_buffer_ref(HwDeviceContext);
#else #else
decoder->VideoCtx->pix_fmt = AV_PIX_FMT_DRM_PRIME; /* request a DRM frame decoder->VideoCtx->pix_fmt = AV_PIX_FMT_DRM_PRIME; /* request a DRM frame */
// decoder->VideoCtx->pix_fmt = AV_PIX_FMT_MMAL; /* request a DRM frame */ // decoder->VideoCtx->pix_fmt = AV_PIX_FMT_MMAL; /* request a DRM frame */
#endif #endif
// FIXME: for software decoder use all cpus, otherwise 1 // FIXME: for software decoder use all cpus, otherwise 1
@@ -314,7 +311,7 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
if (video_codec->capabilities & (AV_CODEC_CAP_AUTO_THREADS)) { if (video_codec->capabilities & (AV_CODEC_CAP_AUTO_THREADS)) {
Debug(3, "codec: auto threads enabled"); Debug(3, "codec: auto threads enabled");
// decoder->VideoCtx->thread_count = 0; // decoder->VideoCtx->thread_count = 0;
} }
if (video_codec->capabilities & AV_CODEC_CAP_TRUNCATED) { if (video_codec->capabilities & AV_CODEC_CAP_TRUNCATED) {
Debug(3, "codec: supports truncated packets"); Debug(3, "codec: supports truncated packets");
@@ -337,9 +334,9 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
// if (av_opt_set_int(decoder->VideoCtx, "refcounted_frames", 1, 0) < 0) // if (av_opt_set_int(decoder->VideoCtx, "refcounted_frames", 1, 0) < 0)
// Fatal(_("VAAPI Refcounts invalid\n")); // Fatal(_("VAAPI Refcounts invalid\n"));
decoder->VideoCtx->thread_safe_callbacks = 0; decoder->VideoCtx->thread_safe_callbacks = 0;
#endif #endif
#ifdef RASPI #ifdef RASPI
decoder->VideoCtx->codec_id = codec_id; decoder->VideoCtx->codec_id = codec_id;
decoder->VideoCtx->flags |= AV_CODEC_FLAG_BITEXACT; decoder->VideoCtx->flags |= AV_CODEC_FLAG_BITEXACT;
@@ -498,7 +495,7 @@ void DisplayPts(AVCodecContext * video_ctx, AVFrame * frame)
*/ */
extern int CuvidTestSurfaces(); extern int CuvidTestSurfaces();
#ifdef YADIF #if defined YADIF || defined (VAAPI)
extern int init_filters(AVCodecContext * dec_ctx, void *decoder, AVFrame * frame); extern int init_filters(AVCodecContext * dec_ctx, void *decoder, AVFrame * frame);
extern int push_filters(AVCodecContext * dec_ctx, void *decoder, AVFrame * frame); extern int push_filters(AVCodecContext * dec_ctx, void *decoder, AVFrame * frame);
#endif #endif
@@ -512,18 +509,18 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
int ret; int ret;
AVPacket pkt[1]; AVPacket pkt[1];
AVFrame *frame; AVFrame *frame;
*pkt = *avpkt; // use copy *pkt = *avpkt; // use copy
ret = avcodec_send_packet(video_ctx, pkt); ret = avcodec_send_packet(video_ctx, pkt);
if (ret < 0) { if (ret < 0) {
return; return;
} }
if (!CuvidTestSurfaces()) if (!CuvidTestSurfaces())
usleep(1000); usleep(1000);
ret = 0; ret = 0;
while (ret >= 0 && CuvidTestSurfaces()) { while (ret >= 0 && CuvidTestSurfaces()) {
frame = av_frame_alloc(); frame = av_frame_alloc();
ret = avcodec_receive_frame(video_ctx, frame); ret = avcodec_receive_frame(video_ctx, frame);
@@ -553,7 +550,7 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
av_frame_free(&frame); av_frame_free(&frame);
return; return;
} }
} }
} }
} }
#endif #endif
@@ -600,8 +597,9 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
} else { } else {
got_frame = 0; got_frame = 0;
} }
// printf("got %s packet from decoder\n",got_frame?"1":"no"); // printf("got %s packet from decoder\n",got_frame?"1":"no");
if (got_frame) { // frame completed if (got_frame) { // frame completed
// printf("video frame pts %#012" PRIx64 " %dms\n",frame->pts,(int)(apts - frame->pts) / 90);
#ifdef YADIF #ifdef YADIF
if (decoder->filter) { if (decoder->filter) {
if (decoder->filter == 1) { if (decoder->filter == 1) {
@@ -682,9 +680,6 @@ struct _audio_decoder_
AVFrame *Frame; ///< decoded audio frame buffer AVFrame *Frame; ///< decoded audio frame buffer
#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
ReSampleContext *ReSample; ///< old resampling context
#endif
#ifdef USE_SWRESAMPLE #ifdef USE_SWRESAMPLE
#if LIBSWRESAMPLE_VERSION_INT < AV_VERSION_INT(0, 15, 100) #if LIBSWRESAMPLE_VERSION_INT < AV_VERSION_INT(0, 15, 100)
struct SwrContext *Resample; ///< ffmpeg software resample context struct SwrContext *Resample; ///< ffmpeg software resample context
@@ -707,16 +702,6 @@ struct _audio_decoder_
int Drift; ///< accumulated audio drift int Drift; ///< accumulated audio drift
int DriftCorr; ///< audio drift correction value int DriftCorr; ///< audio drift correction value
int DriftFrac; ///< audio drift fraction for ac3 int DriftFrac; ///< audio drift fraction for ac3
#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
struct AVResampleContext *AvResample; ///< second audio resample context
#define MAX_CHANNELS 8 ///< max number of channels supported
int16_t *Buffer[MAX_CHANNELS]; ///< deinterleave sample buffers
int BufferSize; ///< size of sample buffer
int16_t *Remain[MAX_CHANNELS]; ///< filter remaining samples
int RemainSize; ///< size of remain buffer
int RemainCount; ///< number of remaining samples
#endif
}; };
/// ///
@@ -799,7 +784,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id)
} }
if (CodecDownmix) { if (CodecDownmix) {
audio_decoder->AudioCtx->request_channel_layout = AV_CH_LAYOUT_STEREO_DOWNMIX; audio_decoder->AudioCtx->request_channel_layout = AV_CH_LAYOUT_STEREO;
} }
pthread_mutex_lock(&CodecLockMutex); pthread_mutex_lock(&CodecLockMutex);
// open codec // open codec
@@ -835,27 +820,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id)
void CodecAudioClose(AudioDecoder * audio_decoder) void CodecAudioClose(AudioDecoder * audio_decoder)
{ {
// FIXME: output any buffered data // FIXME: output any buffered data
#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
if (audio_decoder->AvResample) {
int ch;
av_resample_close(audio_decoder->AvResample);
audio_decoder->AvResample = NULL;
audio_decoder->RemainCount = 0;
audio_decoder->BufferSize = 0;
audio_decoder->RemainSize = 0;
for (ch = 0; ch < MAX_CHANNELS; ++ch) {
free(audio_decoder->Buffer[ch]);
audio_decoder->Buffer[ch] = NULL;
free(audio_decoder->Remain[ch]);
audio_decoder->Remain[ch] = NULL;
}
}
if (audio_decoder->ReSample) {
audio_resample_close(audio_decoder->ReSample);
audio_decoder->ReSample = NULL;
}
#endif
#ifdef USE_SWRESAMPLE #ifdef USE_SWRESAMPLE
if (audio_decoder->Resample) { if (audio_decoder->Resample) {
swr_free(&audio_decoder->Resample); swr_free(&audio_decoder->Resample);
@@ -1147,386 +1112,6 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder, const AVPac
return 0; return 0;
} }
#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
/**
** Set/update audio pts clock.
**
** @param audio_decoder audio decoder data
** @param pts presentation timestamp
*/
static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
{
struct timespec nowtime;
int64_t delay;
int64_t tim_diff;
int64_t pts_diff;
int drift;
int corr;
AudioSetClock(pts);
delay = AudioGetDelay();
if (!delay) {
return;
}
clock_gettime(CLOCK_MONOTONIC, &nowtime);
if (!audio_decoder->LastDelay) {
audio_decoder->LastTime = nowtime;
audio_decoder->LastPTS = pts;
audio_decoder->LastDelay = delay;
audio_decoder->Drift = 0;
audio_decoder->DriftFrac = 0;
Debug(3, "codec/audio: inital drift delay %" PRId64 "ms\n", delay / 90);
return;
}
// collect over some time
pts_diff = pts - audio_decoder->LastPTS;
if (pts_diff < 10 * 1000 * 90) {
return;
}
tim_diff = (nowtime.tv_sec - audio_decoder->LastTime.tv_sec)
* 1000 * 1000 * 1000 + (nowtime.tv_nsec - audio_decoder->LastTime.tv_nsec);
drift = (tim_diff * 90) / (1000 * 1000) - pts_diff + delay - audio_decoder->LastDelay;
// adjust rounding error
nowtime.tv_nsec -= nowtime.tv_nsec % (1000 * 1000 / 90);
audio_decoder->LastTime = nowtime;
audio_decoder->LastPTS = pts;
audio_decoder->LastDelay = delay;
if (0) {
Debug(3, "codec/audio: interval P:%5" PRId64 "ms T:%5" PRId64 "ms D:%4" PRId64 "ms %f %d\n", pts_diff / 90,
tim_diff / (1000 * 1000), delay / 90, drift / 90.0, audio_decoder->DriftCorr);
}
// underruns and av_resample have the same time :(((
if (abs(drift) > 10 * 90) {
// drift too big, pts changed?
Debug(3, "codec/audio: drift(%6d) %3dms reset\n", audio_decoder->DriftCorr, drift / 90);
audio_decoder->LastDelay = 0;
#ifdef DEBUG
corr = 0; // keep gcc happy
#endif
} else {
drift += audio_decoder->Drift;
audio_decoder->Drift = drift;
corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
// SPDIF/HDMI passthrough
if ((CodecAudioDrift & CORRECT_AC3) && (!(CodecPassthrough & CodecAC3)
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_AC3)
&& (!(CodecPassthrough & CodecEAC3)
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_EAC3)) {
audio_decoder->DriftCorr = -corr;
}
if (audio_decoder->DriftCorr < -20000) { // limit correction
audio_decoder->DriftCorr = -20000;
} else if (audio_decoder->DriftCorr > 20000) {
audio_decoder->DriftCorr = 20000;
}
}
// FIXME: this works with libav 0.8, and only with >10ms with ffmpeg 0.10
if (audio_decoder->AvResample && audio_decoder->DriftCorr) {
int distance;
// try workaround for buggy ffmpeg 0.10
if (abs(audio_decoder->DriftCorr) < 2000) {
distance = (pts_diff * audio_decoder->HwSampleRate) / (900 * 1000);
} else {
distance = (pts_diff * audio_decoder->HwSampleRate) / (90 * 1000);
}
av_resample_compensate(audio_decoder->AvResample, audio_decoder->DriftCorr / 10, distance);
}
if (1) {
static int c;
if (!(c++ % 10)) {
Debug(3, "codec/audio: drift(%6d) %8dus %5d\n", audio_decoder->DriftCorr, drift * 1000 / 90, corr);
}
}
}
/**
** Handle audio format changes.
**
** @param audio_decoder audio decoder data
**
** @note this is the old not good supported version
*/
static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
{
int passthrough;
const AVCodecContext *audio_ctx;
int err;
if (audio_decoder->ReSample) {
audio_resample_close(audio_decoder->ReSample);
audio_decoder->ReSample = NULL;
}
if (audio_decoder->AvResample) {
av_resample_close(audio_decoder->AvResample);
audio_decoder->AvResample = NULL;
audio_decoder->RemainCount = 0;
}
audio_ctx = audio_decoder->AudioCtx;
if ((err = CodecAudioUpdateHelper(audio_decoder, &passthrough))) {
Debug(3, "codec/audio: resample %dHz *%d -> %dHz *%d err %d\n", audio_ctx->sample_rate, audio_ctx->channels,
audio_decoder->HwSampleRate, audio_decoder->HwChannels, err);
if (err == 1) {
audio_decoder->ReSample =
av_audio_resample_init(audio_decoder->HwChannels, 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;
}
return;
}
Debug(3, "codec/audio: audio setup error\n");
// FIXME: handle errors
audio_decoder->HwChannels = 0;
audio_decoder->HwSampleRate = 0;
return;
}
if (passthrough) { // pass-through no conversion allowed
return;
}
// prepare audio drift resample
#ifdef USE_AUDIO_DRIFT_CORRECTION
if (CodecAudioDrift & CORRECT_PCM) {
if (audio_decoder->AvResample) {
Error(_("codec/audio: overwrite resample\n"));
}
audio_decoder->AvResample =
av_resample_init(audio_decoder->HwSampleRate, audio_decoder->HwSampleRate, 16, 10, 0, 0.8);
if (!audio_decoder->AvResample) {
Error(_("codec/audio: AvResample setup error\n"));
} else {
// reset drift to some default value
audio_decoder->DriftCorr /= 2;
audio_decoder->DriftFrac = 0;
av_resample_compensate(audio_decoder->AvResample, audio_decoder->DriftCorr / 10,
10 * audio_decoder->HwSampleRate);
}
}
#endif
}
/**
** Codec enqueue audio samples.
**
** @param audio_decoder audio decoder data
** @param data samples data
** @param count number of bytes in sample data
*/
void CodecAudioEnqueue(AudioDecoder * audio_decoder, int16_t * data, int count)
{
#ifdef USE_AUDIO_DRIFT_CORRECTION
if ((CodecAudioDrift & CORRECT_PCM) && audio_decoder->AvResample) {
int16_t buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 + AV_INPUT_BUFFER_PADDING_SIZE]
__attribute__((aligned(16)));
int16_t buftmp[MAX_CHANNELS][(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4];
int consumed;
int i;
int n;
int ch;
int bytes_n;
bytes_n = count / audio_decoder->HwChannels;
// resize sample buffer, if needed
if (audio_decoder->RemainCount + bytes_n > audio_decoder->BufferSize) {
audio_decoder->BufferSize = audio_decoder->RemainCount + bytes_n;
for (ch = 0; ch < MAX_CHANNELS; ++ch) {
audio_decoder->Buffer[ch] = realloc(audio_decoder->Buffer[ch], audio_decoder->BufferSize);
}
}
// copy remaining bytes into sample buffer
for (ch = 0; ch < audio_decoder->HwChannels; ++ch) {
memcpy(audio_decoder->Buffer[ch], audio_decoder->Remain[ch], audio_decoder->RemainCount);
}
// deinterleave samples into sample buffer
for (i = 0; i < bytes_n / 2; i++) {
for (ch = 0; ch < audio_decoder->HwChannels; ++ch) {
audio_decoder->Buffer[ch][audio_decoder->RemainCount / 2 + i]
= data[i * audio_decoder->HwChannels + ch];
}
}
bytes_n += audio_decoder->RemainSize;
n = 0; // keep gcc lucky
// resample the sample buffer into tmp buffer
for (ch = 0; ch < audio_decoder->HwChannels; ++ch) {
n = av_resample(audio_decoder->AvResample, buftmp[ch], audio_decoder->Buffer[ch], &consumed, bytes_n / 2,
sizeof(buftmp[ch]) / 2, ch == audio_decoder->HwChannels - 1);
// fixme remaining channels
if (bytes_n - consumed * 2 > audio_decoder->RemainSize) {
audio_decoder->RemainSize = bytes_n - consumed * 2;
}
audio_decoder->Remain[ch] = realloc(audio_decoder->Remain[ch], audio_decoder->RemainSize);
memcpy(audio_decoder->Remain[ch], audio_decoder->Buffer[ch] + consumed, audio_decoder->RemainSize);
audio_decoder->RemainCount = audio_decoder->RemainSize;
}
// interleave samples from sample buffer
for (i = 0; i < n; i++) {
for (ch = 0; ch < audio_decoder->HwChannels; ++ch) {
buf[i * audio_decoder->HwChannels + ch] = buftmp[ch][i];
}
}
n *= 2;
n *= audio_decoder->HwChannels;
if (!(audio_decoder->Passthrough & CodecPCM)) {
CodecReorderAudioFrame(buf, n, audio_decoder->HwChannels);
}
AudioEnqueue(buf, n);
return;
}
#endif
if (!(audio_decoder->Passthrough & CodecPCM)) {
CodecReorderAudioFrame(data, count, audio_decoder->HwChannels);
}
AudioEnqueue(data, count);
}
int myavcodec_decode_audio3(AVCodecContext * avctx, int16_t * samples, int *frame_size_ptr, AVPacket * avpkt)
{
AVFrame *frame = av_frame_alloc();
int ret, got_frame = 0;
if (!frame)
return AVERROR(ENOMEM);
#if 0
ret = avcodec_decode_audio4(avctx, frame, &got_frame, avpkt);
#else
// SUGGESTION
// Now that avcodec_decode_audio4 is deprecated and replaced
// by 2 calls (receive frame and send packet), this could be optimized
// into separate routines or separate threads.
// Also now that it always consumes a whole buffer some code
// in the caller may be able to be optimized.
ret = avcodec_receive_frame(avctx, frame);
if (ret == 0)
got_frame = 1;
if (ret == AVERROR(EAGAIN))
ret = 0;
if (ret == 0)
ret = avcodec_send_packet(avctx, avpkt);
if (ret == AVERROR(EAGAIN))
ret = 0;
else if (ret < 0) {
// Debug(3, "codec/audio: audio decode error: %1 (%2)\n",av_make_error_string(error, sizeof(error), ret),got_frame);
return ret;
} else
ret = avpkt->size;
#endif
if (ret >= 0 && got_frame) {
int i, ch;
int planar = av_sample_fmt_is_planar(avctx->sample_fmt);
int data_size = av_get_bytes_per_sample(avctx->sample_fmt);
if (data_size < 0) {
/* This should not occur, checking just for paranoia */
fprintf(stderr, "Failed to calculate data size\n");
exit(1);
}
for (i = 0; i < frame->nb_samples; i++) {
for (ch = 0; ch < avctx->channels; ch++) {
memcpy(samples, frame->extended_data[ch] + data_size * i, data_size);
samples = (char *)samples + data_size;
}
}
// Debug(3,"data_size %d nb_samples %d sample_fmt %d channels %d planar %d\n",data_size,frame->nb_samples,avctx->sample_fmt,avctx->channels,planar);
*frame_size_ptr = data_size * avctx->channels * frame->nb_samples;
} else {
*frame_size_ptr = 0;
}
av_frame_free(&frame);
return ret;
}
/**
** 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 + AV_INPUT_BUFFER_PADDING_SIZE] __attribute__((aligned(16)));
int buf_sz;
int l;
AVCodecContext *audio_ctx;
audio_ctx = audio_decoder->AudioCtx;
// FIXME: don't need to decode pass-through codecs
buf_sz = sizeof(buf);
l = myavcodec_decode_audio3(audio_ctx, buf, &buf_sz, (AVPacket *) avpkt);
if (avpkt->size != l) {
if (l == AVERROR(EAGAIN)) {
Error(_("codec: latm\n"));
return;
}
if (l < 0) { // no audio frame could be decompressed
Error(_("codec: error audio data\n"));
return;
}
Error(_("codec: error more than one frame data\n"));
}
// update audio clock
if (avpkt->pts != (int64_t) AV_NOPTS_VALUE) {
CodecAudioSetClock(audio_decoder, avpkt->pts);
}
// FIXME: must first play remainings bytes, than change and play new.
if (audio_decoder->Passthrough != CodecPassthrough || audio_decoder->SampleRate != audio_ctx->sample_rate
|| audio_decoder->Channels != audio_ctx->channels) {
CodecAudioUpdateFormat(audio_decoder);
}
if (audio_decoder->HwSampleRate && audio_decoder->HwChannels) {
// need to resample audio
if (audio_decoder->ReSample) {
int16_t outbuf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 + AV_INPUT_BUFFER_PADDING_SIZE]
__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);
CodecAudioEnqueue(audio_decoder, outbuf, outlen);
}
} else {
if (CodecAudioPassthroughHelper(audio_decoder, avpkt)) {
return;
}
CodecAudioEnqueue(audio_decoder, buf, buf_sz);
}
}
}
#endif
#if defined(USE_SWRESAMPLE) || defined(USE_AVRESAMPLE) #if defined(USE_SWRESAMPLE) || defined(USE_AVRESAMPLE)
/** /**
@@ -1787,6 +1372,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
*/ */
void CodecAudioFlushBuffers(AudioDecoder * decoder) void CodecAudioFlushBuffers(AudioDecoder * decoder)
{ {
avcodec_flush_buffers(decoder->AudioCtx); avcodec_flush_buffers(decoder->AudioCtx);
} }

129
drm.c
View File

@@ -18,13 +18,13 @@ struct _Drm_Render_
int fd_drm; int fd_drm;
drmModeModeInfo mode; drmModeModeInfo mode;
drmModeCrtc *saved_crtc; drmModeCrtc *saved_crtc;
// drmEventContext ev; // drmEventContext ev;
int bpp; int bpp;
uint32_t connector_id, crtc_id, video_plane; uint32_t connector_id, crtc_id, video_plane;
uint32_t hdr_metadata; uint32_t hdr_metadata;
uint32_t mmWidth,mmHeight; // Size in mm uint32_t mmWidth,mmHeight; // Size in mm
uint32_t hdr_blob_id; uint32_t hdr_blob_id;
}; };
typedef struct _Drm_Render_ VideoRender; typedef struct _Drm_Render_ VideoRender;
@@ -193,12 +193,12 @@ void set_video_mode(int width, int height)
return; return;
connector = drmModeGetConnector(render->fd_drm, render->connector_id); connector = drmModeGetConnector(render->fd_drm, render->connector_id);
for (ii = 0; ii < connector->count_modes; ii++) { for (ii = 0; ii < connector->count_modes; ii++) {
mode = &connector->modes[ii]; mode = &connector->modes[ii];
printf("Mode %d %dx%d Rate %d\n",ii,mode->hdisplay,mode->vdisplay,mode->vrefresh); printf("Mode %d %dx%d Rate %d\n",ii,mode->hdisplay,mode->vdisplay,mode->vrefresh);
if (width == mode->hdisplay && if (width == mode->hdisplay &&
height == mode->vdisplay && height == mode->vdisplay &&
mode->vrefresh == DRMRefresh && mode->vrefresh == DRMRefresh &&
render->mode.hdisplay != width && render->mode.hdisplay != width &&
render->mode.vdisplay != height && render->mode.vdisplay != height &&
!(mode->flags & DRM_MODE_FLAG_INTERLACE)) { !(mode->flags & DRM_MODE_FLAG_INTERLACE)) {
memcpy(&render->mode, mode, sizeof(drmModeModeInfo)); memcpy(&render->mode, mode, sizeof(drmModeModeInfo));
@@ -211,7 +211,7 @@ void set_video_mode(int width, int height)
CuvidSetVideoMode(); CuvidSetVideoMode();
Debug(3,"Set new mode %d:%d\n",mode->hdisplay,mode->vdisplay); Debug(3,"Set new mode %d:%d\n",mode->hdisplay,mode->vdisplay);
break; break;
} }
} }
} }
@@ -240,11 +240,31 @@ static int FindDevice(VideoRender * render)
fprintf(stderr, "FindDevice: cannot open /dev/dri/card0: %m\n"); fprintf(stderr, "FindDevice: cannot open /dev/dri/card0: %m\n");
return -errno; return -errno;
} }
drmSetMaster(render->fd_drm);
int ret = drmSetMaster(render->fd_drm);
if (ret < 0)
{
drm_magic_t magic;
ret = drmGetMagic(render->fd_drm, &magic);
if (ret < 0)
{
Debug(3, "drm:%s - failed to get drm magic: %s\n", __FUNCTION__, strerror(errno));
return -1;
}
ret = drmAuthMagic(render->fd_drm, magic);
if (ret < 0)
{
Debug(3, "drm:%s - failed to authorize drm magic: %s\n", __FUNCTION__, strerror(errno));
return -1;
}
}
version = drmGetVersion(render->fd_drm); version = drmGetVersion(render->fd_drm);
fprintf(stderr, "FindDevice: open /dev/dri/card0: %s\n", version->name); fprintf(stderr, "FindDevice: open /dev/dri/card0: %s\n", version->name);
// check capability // check capability
if (drmGetCap(render->fd_drm, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0 || has_dumb == 0) if (drmGetCap(render->fd_drm, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0 || has_dumb == 0)
fprintf(stderr, "FindDevice: drmGetCap DRM_CAP_DUMB_BUFFER failed or doesn't have dumb buffer\n"); fprintf(stderr, "FindDevice: drmGetCap DRM_CAP_DUMB_BUFFER failed or doesn't have dumb buffer\n");
@@ -263,7 +283,7 @@ static int FindDevice(VideoRender * render)
if (drmGetCap(render->fd_drm, DRM_PRIME_CAP_IMPORT, &has_prime) < 0) if (drmGetCap(render->fd_drm, DRM_PRIME_CAP_IMPORT, &has_prime) < 0)
fprintf(stderr, "FindDevice: DRM_PRIME_CAP_IMPORT not available.\n"); fprintf(stderr, "FindDevice: DRM_PRIME_CAP_IMPORT not available.\n");
if ((resources = drmModeGetResources(render->fd_drm)) == NULL){ if ((resources = drmModeGetResources(render->fd_drm)) == NULL){
fprintf(stderr, "FindDevice: cannot retrieve DRM resources (%d): %m\n", errno); fprintf(stderr, "FindDevice: cannot retrieve DRM resources (%d): %m\n", errno);
return -errno; return -errno;
@@ -282,18 +302,18 @@ static int FindDevice(VideoRender * render)
fprintf(stderr, "FindDevice: cannot retrieve DRM connector (%d): %m\n", errno); fprintf(stderr, "FindDevice: cannot retrieve DRM connector (%d): %m\n", errno);
return -errno; return -errno;
} }
sprintf(connectorstr,"%s-%u",util_lookup_connector_type_name(connector->connector_type),connector->connector_type_id); sprintf(connectorstr,"%s-%u",util_lookup_connector_type_name(connector->connector_type),connector->connector_type_id);
printf("Connector >%s< is %sconnected\n",connectorstr,connector->connection == DRM_MODE_CONNECTED?"":"not "); printf("Connector >%s< is %sconnected\n",connectorstr,connector->connection == DRM_MODE_CONNECTED?"":"not ");
if (DRMConnector && strcmp(DRMConnector,connectorstr)) if (DRMConnector && strcmp(DRMConnector,connectorstr))
continue; continue;
if (connector->connection == DRM_MODE_CONNECTED && connector->count_modes > 0) { if (connector->connection == DRM_MODE_CONNECTED && connector->count_modes > 0) {
float aspect = (float)connector->mmWidth / (float)connector->mmHeight; float aspect = (float)connector->mmWidth / (float)connector->mmHeight;
if ((aspect > 1.70) && (aspect < 1.85)) { if ((aspect > 1.70) && (aspect < 1.85)) {
render->mmHeight = 90; render->mmHeight = 90;
render->mmWidth = 160; render->mmWidth = 160;
} else { } else {
render->mmHeight = connector->mmHeight; render->mmHeight = connector->mmHeight;
render->mmWidth = connector->mmWidth; render->mmWidth = connector->mmWidth;
} }
@@ -304,27 +324,27 @@ static int FindDevice(VideoRender * render)
return -errno; return -errno;
} }
render->crtc_id = encoder->crtc_id; render->crtc_id = encoder->crtc_id;
render->hdr_metadata = GetPropertyID(render->fd_drm, connector->connector_id, render->hdr_metadata = GetPropertyID(render->fd_drm, connector->connector_id,
DRM_MODE_OBJECT_CONNECTOR, "HDR_OUTPUT_METADATA"); DRM_MODE_OBJECT_CONNECTOR, "HDR_OUTPUT_METADATA");
printf("ID %d of METADATA in Connector %d connected %d\n",render->hdr_metadata,connector->connector_id,connector->connection); printf("ID %d of METADATA in Connector %d connected %d\n",render->hdr_metadata,connector->connector_id,connector->connection);
memcpy(&render->mode, &connector->modes[0], sizeof(drmModeModeInfo)); // set fallback memcpy(&render->mode, &connector->modes[0], sizeof(drmModeModeInfo)); // set fallback
// search Modes for Connector // search Modes for Connector
for (ii = 0; ii < connector->count_modes; ii++) { for (ii = 0; ii < connector->count_modes; ii++) {
mode = &connector->modes[ii]; mode = &connector->modes[ii];
printf("Mode %d %dx%d Rate %d\n",ii,mode->hdisplay,mode->vdisplay,mode->vrefresh); printf("Mode %d %dx%d Rate %d\n",ii,mode->hdisplay,mode->vdisplay,mode->vrefresh);
if (VideoWindowWidth && VideoWindowHeight) { // preset by command line if (VideoWindowWidth && VideoWindowHeight) { // preset by command line
if (VideoWindowWidth == mode->hdisplay && if (VideoWindowWidth == mode->hdisplay &&
VideoWindowHeight == mode->vdisplay && VideoWindowHeight == mode->vdisplay &&
mode->vrefresh == DRMRefresh && mode->vrefresh == DRMRefresh &&
!(mode->flags & DRM_MODE_FLAG_INTERLACE)) { !(mode->flags & DRM_MODE_FLAG_INTERLACE)) {
memcpy(&render->mode, mode, sizeof(drmModeModeInfo)); memcpy(&render->mode, mode, sizeof(drmModeModeInfo));
break; break;
} }
} }
else { else {
if (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) { if (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) {
memcpy(&render->mode, mode, sizeof(drmModeModeInfo)); memcpy(&render->mode, mode, sizeof(drmModeModeInfo));
@@ -335,7 +355,7 @@ static int FindDevice(VideoRender * render)
} }
} }
found = 1; found = 1;
i = resources->count_connectors; // uuuuhh i = resources->count_connectors; // uuuuhh
} }
VideoWindowWidth = render->mode.hdisplay; VideoWindowWidth = render->mode.hdisplay;
VideoWindowHeight = render->mode.vdisplay; VideoWindowHeight = render->mode.vdisplay;
@@ -348,7 +368,7 @@ static int FindDevice(VideoRender * render)
printf("Requested Connector not found or not connected\n"); printf("Requested Connector not found or not connected\n");
return -1; return -1;
} }
// find first plane // find first plane
if ((plane_res = drmModeGetPlaneResources(render->fd_drm)) == NULL) if ((plane_res = drmModeGetPlaneResources(render->fd_drm)) == NULL)
fprintf(stderr, "FindDevice: cannot retrieve PlaneResources (%d): %m\n", errno); fprintf(stderr, "FindDevice: cannot retrieve PlaneResources (%d): %m\n", errno);
@@ -366,7 +386,7 @@ static int FindDevice(VideoRender * render)
uint64_t type = GetPropertyValue(render->fd_drm, plane_res->planes[j], uint64_t type = GetPropertyValue(render->fd_drm, plane_res->planes[j],
DRM_MODE_OBJECT_PLANE, "type"); DRM_MODE_OBJECT_PLANE, "type");
uint64_t zpos = 0; uint64_t zpos = 0;
#ifdef DRM_DEBUG // If more then 2 crtcs this must rewriten!!! #ifdef DRM_DEBUG // If more then 2 crtcs this must rewriten!!!
printf("[FindDevice] Plane id %i crtc_id %i possible_crtcs %i possible CRTC %i type %s\n", printf("[FindDevice] Plane id %i crtc_id %i possible_crtcs %i possible CRTC %i type %s\n",
@@ -384,7 +404,7 @@ static int FindDevice(VideoRender * render)
case DRM_FORMAT_ARGB8888: case DRM_FORMAT_ARGB8888:
#else #else
case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_XRGB2101010:
#endif #endif
if (!render->video_plane) { if (!render->video_plane) {
render->video_plane = plane->plane_id; render->video_plane = plane->plane_id;
} }
@@ -419,25 +439,25 @@ static int FindDevice(VideoRender * render)
void VideoInitDrm() void VideoInitDrm()
{ {
int i; int i;
if (!(render = calloc(1, sizeof(*render)))) { if (!(render = calloc(1, sizeof(*render)))) {
Fatal(_("video/DRM: out of memory\n")); Fatal(_("video/DRM: out of memory\n"));
return; return;
} }
if (FindDevice(render)){ if (FindDevice(render)){
Fatal(_( "VideoInit: FindDevice() failed\n")); Fatal(_( "VideoInit: FindDevice() failed\n"));
} }
gbm.dev = gbm_create_device (render->fd_drm); gbm.dev = gbm_create_device (render->fd_drm);
assert (gbm.dev != NULL); assert (gbm.dev != NULL);
PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display = NULL; PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display = NULL;
get_platform_display = get_platform_display =
(void *) eglGetProcAddress("eglGetPlatformDisplay"); (void *) eglGetProcAddress("eglGetPlatformDisplay");
assert(get_platform_display != NULL); assert(get_platform_display != NULL);
eglDisplay = get_platform_display(EGL_PLATFORM_GBM_KHR, gbm.dev, NULL); eglDisplay = get_platform_display(EGL_PLATFORM_GBM_KHR, gbm.dev, NULL);
assert (eglDisplay != NULL); assert (eglDisplay != NULL);
@@ -462,22 +482,21 @@ void VideoInitDrm()
DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", render->crtc_id); DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", render->crtc_id);
SetPropertyRequest(ModeReq, render->fd_drm, render->crtc_id, SetPropertyRequest(ModeReq, render->fd_drm, render->crtc_id,
DRM_MODE_OBJECT_CRTC, "ACTIVE", 1); DRM_MODE_OBJECT_CRTC, "ACTIVE", 1);
if (drmModeAtomicCommit(render->fd_drm, ModeReq, flags, NULL) != 0) if (drmModeAtomicCommit(render->fd_drm, ModeReq, flags, NULL) != 0)
fprintf(stderr, "cannot set atomic mode (%d): %m\n", errno); fprintf(stderr, "cannot set atomic mode (%d): %m\n", errno);
if (drmModeDestroyPropertyBlob(render->fd_drm, modeID) != 0) if (drmModeDestroyPropertyBlob(render->fd_drm, modeID) != 0)
fprintf(stderr, "cannot destroy property blob (%d): %m\n", errno); fprintf(stderr, "cannot destroy property blob (%d): %m\n", errno);
drmModeAtomicFree(ModeReq); drmModeAtomicFree(ModeReq);
} }
void get_drm_aspect(int *num,int *den) void get_drm_aspect(int *num,int *den)
{ {
Debug(3,"mmHeight %d mmWidth %d VideoHeight %d VideoWidth %d\n",render->mmHeight,render->mmWidth,VideoWindowHeight,VideoWindowWidth); *num = VideoWindowWidth;
*num = VideoWindowWidth * render->mmHeight; *den = VideoWindowHeight;
*den = VideoWindowHeight * render->mmWidth;
} }
struct gbm_bo *bo = NULL, *next_bo=NULL; struct gbm_bo *bo = NULL, *next_bo=NULL;
@@ -488,8 +507,8 @@ static int old_color=-1,old_trc=-1;
void InitBo(int bpp) { void InitBo(int bpp) {
// create the GBM and EGL surface // create the GBM and EGL surface
render->bpp = bpp; render->bpp = bpp;
gbm.surface = gbm_surface_create (gbm.dev, VideoWindowWidth,VideoWindowHeight, gbm.surface = gbm_surface_create (gbm.dev, VideoWindowWidth,VideoWindowHeight,
bpp==10?GBM_FORMAT_XRGB2101010:GBM_FORMAT_ARGB8888, bpp==10?GBM_FORMAT_XRGB2101010:GBM_FORMAT_ARGB8888,
GBM_BO_USE_SCANOUT|GBM_BO_USE_RENDERING); GBM_BO_USE_SCANOUT|GBM_BO_USE_RENDERING);
assert(gbm.surface != NULL); assert(gbm.surface != NULL);
eglSurface = eglCreateWindowSurface (eglDisplay, eglConfig, gbm.surface, NULL); eglSurface = eglCreateWindowSurface (eglDisplay, eglConfig, gbm.surface, NULL);
@@ -501,10 +520,10 @@ static struct gbm_bo *previous_bo = NULL;
static uint32_t previous_fb; static uint32_t previous_fb;
static void drm_swap_buffers () { static void drm_swap_buffers () {
uint32_t fb; uint32_t fb;
eglSwapBuffers (eglDisplay, eglSurface); eglSwapBuffers (eglDisplay, eglSurface);
struct gbm_bo *bo = gbm_surface_lock_front_buffer (gbm.surface); struct gbm_bo *bo = gbm_surface_lock_front_buffer (gbm.surface);
#if 1 #if 1
if (bo == NULL) if (bo == NULL)
@@ -517,7 +536,7 @@ static void drm_swap_buffers () {
drmModeAddFB (render->fd_drm, VideoWindowWidth,VideoWindowHeight,render->bpp==10? 30:24, 32, pitch, handle, &fb); drmModeAddFB (render->fd_drm, VideoWindowWidth,VideoWindowHeight,render->bpp==10? 30:24, 32, pitch, handle, &fb);
// drmModeSetCrtc (render->fd_drm, render->crtc_id, fb, 0, 0, &render->connector_id, 1, &render->mode); // drmModeSetCrtc (render->fd_drm, render->crtc_id, fb, 0, 0, &render->connector_id, 1, &render->mode);
if (m_need_modeset) { if (m_need_modeset) {
drmModeAtomicReqPtr ModeReq; drmModeAtomicReqPtr ModeReq;
const uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET; const uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
@@ -531,14 +550,14 @@ static void drm_swap_buffers () {
fprintf(stderr, "cannot allocate atomic request (%d): %m\n", errno); fprintf(stderr, "cannot allocate atomic request (%d): %m\n", errno);
return; return;
} }
// Need to disable the CRTC in order to submit the HDR data.... // Need to disable the CRTC in order to submit the HDR data....
SetPropertyRequest(ModeReq, render->fd_drm, render->crtc_id, SetPropertyRequest(ModeReq, render->fd_drm, render->crtc_id,
DRM_MODE_OBJECT_CRTC, "ACTIVE", 0); DRM_MODE_OBJECT_CRTC, "ACTIVE", 0);
if (drmModeAtomicCommit(render->fd_drm, ModeReq, flags, NULL) != 0) if (drmModeAtomicCommit(render->fd_drm, ModeReq, flags, NULL) != 0)
fprintf(stderr, "cannot set atomic mode (%d): %m\n", errno); fprintf(stderr, "cannot set atomic mode (%d): %m\n", errno);
sleep(2); sleep(2);
SetPropertyRequest(ModeReq, render->fd_drm, render->connector_id, SetPropertyRequest(ModeReq, render->fd_drm, render->connector_id,
DRM_MODE_OBJECT_CONNECTOR, "Colorspace",old_color==AVCOL_PRI_BT2020?9:2 ); DRM_MODE_OBJECT_CONNECTOR, "Colorspace",old_color==AVCOL_PRI_BT2020?9:2 );
SetPropertyRequest(ModeReq, render->fd_drm, render->crtc_id, SetPropertyRequest(ModeReq, render->fd_drm, render->crtc_id,
@@ -547,7 +566,7 @@ static void drm_swap_buffers () {
DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", render->crtc_id); DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", render->crtc_id);
SetPropertyRequest(ModeReq, render->fd_drm, render->crtc_id, SetPropertyRequest(ModeReq, render->fd_drm, render->crtc_id,
DRM_MODE_OBJECT_CRTC, "ACTIVE", 1); DRM_MODE_OBJECT_CRTC, "ACTIVE", 1);
if (drmModeAtomicCommit(render->fd_drm, ModeReq, flags, NULL) != 0) if (drmModeAtomicCommit(render->fd_drm, ModeReq, flags, NULL) != 0)
fprintf(stderr, "cannot set atomic mode (%d): %m\n", errno); fprintf(stderr, "cannot set atomic mode (%d): %m\n", errno);
@@ -558,7 +577,7 @@ static void drm_swap_buffers () {
m_need_modeset = 0; m_need_modeset = 0;
} }
drmModeSetCrtc (render->fd_drm, render->crtc_id, fb, 0, 0, &render->connector_id, 1, &render->mode); drmModeSetCrtc (render->fd_drm, render->crtc_id, fb, 0, 0, &render->connector_id, 1, &render->mode);
if (previous_bo) { if (previous_bo) {
drmModeRmFB (render->fd_drm, previous_fb); drmModeRmFB (render->fd_drm, previous_fb);
gbm_surface_release_buffer (gbm.surface, previous_bo); gbm_surface_release_buffer (gbm.surface, previous_bo);
@@ -579,15 +598,15 @@ static void drm_clean_up () {
drmModeRmFB (render->fd_drm, previous_fb); drmModeRmFB (render->fd_drm, previous_fb);
gbm_surface_release_buffer (gbm.surface, previous_bo); gbm_surface_release_buffer (gbm.surface, previous_bo);
} }
drmModeSetCrtc (render->fd_drm, render->saved_crtc->crtc_id, render->saved_crtc->buffer_id, drmModeSetCrtc (render->fd_drm, render->saved_crtc->crtc_id, render->saved_crtc->buffer_id,
render->saved_crtc->x, render->saved_crtc->y, &render->connector_id, 1, &render->saved_crtc->mode); render->saved_crtc->x, render->saved_crtc->y, &render->connector_id, 1, &render->saved_crtc->mode);
drmModeFreeCrtc (render->saved_crtc); drmModeFreeCrtc (render->saved_crtc);
if (render->hdr_blob_id) if (render->hdr_blob_id)
drmModeDestroyPropertyBlob(render->fd_drm, render->hdr_blob_id); drmModeDestroyPropertyBlob(render->fd_drm, render->hdr_blob_id);
render->hdr_blob_id = 0; render->hdr_blob_id = 0;
eglDestroySurface (eglDisplay, eglSurface); eglDestroySurface (eglDisplay, eglSurface);
EglCheck(); EglCheck();
gbm_surface_destroy (gbm.surface); gbm_surface_destroy (gbm.surface);
@@ -597,9 +616,9 @@ static void drm_clean_up () {
EglCheck(); EglCheck();
eglSharedContext = NULL; eglSharedContext = NULL;
eglTerminate (eglDisplay); eglTerminate (eglDisplay);
EglCheck(); EglCheck();
gbm_device_destroy (gbm.dev); gbm_device_destroy (gbm.dev);
drmDropMaster(render->fd_drm); drmDropMaster(render->fd_drm);
close (render->fd_drm); close (render->fd_drm);

View File

@@ -17,8 +17,6 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef __cuda_cuda_h__ // check to see if CUDA_H is included above
// Error Code string definitions here // Error Code string definitions here
typedef struct typedef struct
{ {
@@ -453,6 +451,4 @@ static inline const char *getCudaDrvErrorString(CUresult error_id)
return (const char *)"CUDA_ERROR not found!"; return (const char *)"CUDA_ERROR not found!";
} }
#endif // __cuda_cuda_h__
#endif #endif

42
hdr.c
View File

@@ -334,11 +334,11 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid
int max_lum=4000,min_lum=0050; int max_lum=4000,min_lum=0050;
struct AVMasteringDisplayMetadata *md = NULL; struct AVMasteringDisplayMetadata *md = NULL;
struct AVContentLightMetadata *ld = NULL; struct AVContentLightMetadata *ld = NULL;
if (render->hdr_metadata == -1) { // Metadata not supported if (render->hdr_metadata == -1) { // Metadata not supported
return; return;
} }
// clean up FFMEPG stuff // clean up FFMEPG stuff
if (trc == AVCOL_TRC_BT2020_10) if (trc == AVCOL_TRC_BT2020_10)
trc = AVCOL_TRC_ARIB_STD_B67; trc = AVCOL_TRC_ARIB_STD_B67;
@@ -346,16 +346,16 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid
trc = AVCOL_TRC_BT709; trc = AVCOL_TRC_BT709;
if (color == AVCOL_PRI_UNSPECIFIED) if (color == AVCOL_PRI_UNSPECIFIED)
color = AVCOL_PRI_BT709; color = AVCOL_PRI_BT709;
if ((old_color == color && old_trc == trc && !sd1 && !sd2) || !render->hdr_metadata) if ((old_color == color && old_trc == trc && !sd1 && !sd2) || !render->hdr_metadata)
return; // nothing to do return; // nothing to do
if (sd1) if (sd1)
md = sd1->data; md = sd1->data;
if (sd2) if (sd2)
ld = sd2->data; ld = sd2->data;
if (md && !memcmp(md,&md_save,sizeof(md_save))) if (md && !memcmp(md,&md_save,sizeof(md_save)))
if (ld && !memcmp(ld,&ld_save,sizeof(ld_save))) { if (ld && !memcmp(ld,&ld_save,sizeof(ld_save))) {
return; return;
@@ -363,23 +363,23 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid
else if (ld && !memcmp(ld,&ld_save,sizeof(ld_save))) { else if (ld && !memcmp(ld,&ld_save,sizeof(ld_save))) {
return; return;
} }
if (ld) if (ld)
memcpy(&ld_save,ld,sizeof(ld_save)); memcpy(&ld_save,ld,sizeof(ld_save));
if (md) if (md)
memcpy(&md_save,md,sizeof(md_save)); memcpy(&md_save,md,sizeof(md_save));
Debug(3,"Update HDR to TRC %d color %d\n",trc,color); Debug(3,"Update HDR to TRC %d color %d\n",trc,color);
if (trc == AVCOL_TRC_BT2020_10) if (trc == AVCOL_TRC_BT2020_10)
trc = AVCOL_TRC_ARIB_STD_B67; trc = AVCOL_TRC_ARIB_STD_B67;
old_color = color; old_color = color;
old_trc = trc; old_trc = trc;
if (render->hdr_blob_id) if (render->hdr_blob_id)
drmModeDestroyPropertyBlob(render->fd_drm, render->hdr_blob_id); drmModeDestroyPropertyBlob(render->fd_drm, render->hdr_blob_id);
switch(trc) { switch(trc) {
case AVCOL_TRC_BT709: // 1 case AVCOL_TRC_BT709: // 1
case AVCOL_TRC_UNSPECIFIED: // 2 case AVCOL_TRC_UNSPECIFIED: // 2
@@ -387,16 +387,17 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid
break; break;
case AVCOL_TRC_BT2020_10: // 14 case AVCOL_TRC_BT2020_10: // 14
case AVCOL_TRC_BT2020_12: case AVCOL_TRC_BT2020_12:
case AVCOL_TRC_ARIB_STD_B67: // 18 HLG case AVCOL_TRC_ARIB_STD_B67: // 18 HLG
eotf = EOTF_HLG; eotf = EOTF_HLG;
break; break;
case AVCOL_TRC_SMPTE2084: // 16 case AVCOL_TRC_SMPTE2084: // 16
eotf = EOTF_ST2084; eotf = EOTF_ST2084;
break;
default: default:
eotf = EOTF_TRADITIONAL_GAMMA_SDR; eotf = EOTF_TRADITIONAL_GAMMA_SDR;
break; break;
} }
switch (color) { switch (color) {
case AVCOL_PRI_BT709: // 1 case AVCOL_PRI_BT709: // 1
case AVCOL_PRI_UNSPECIFIED: // 2 case AVCOL_PRI_UNSPECIFIED: // 2
@@ -412,7 +413,7 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid
cs = weston_colorspace_lookup("BT.709"); cs = weston_colorspace_lookup("BT.709");
break; break;
} }
if (md) { // we got Metadata if (md) { // we got Metadata
if (md->has_primaries) { if (md->has_primaries) {
Debug(3,"Mastering Display Metadata,\n has_primaries:%d has_luminance:%d \n" Debug(3,"Mastering Display Metadata,\n has_primaries:%d has_luminance:%d \n"
@@ -464,9 +465,9 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid
MaxCLL, // Maximum Content Light Level (MaxCLL) MaxCLL, // Maximum Content Light Level (MaxCLL)
MaxFALL, // Maximum Frame-Average Light Level (MaxFALL) MaxFALL, // Maximum Frame-Average Light Level (MaxFALL)
eotf); eotf);
ret = drmModeCreatePropertyBlob(render->fd_drm, &data, sizeof(data), &render->hdr_blob_id); ret = drmModeCreatePropertyBlob(render->fd_drm, &data, sizeof(data), &render->hdr_blob_id);
if (ret) { if (ret) {
printf("DRM: HDR metadata: failed blob create \n"); printf("DRM: HDR metadata: failed blob create \n");
@@ -478,15 +479,14 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid
render->hdr_metadata, render->hdr_blob_id); render->hdr_metadata, render->hdr_blob_id);
if (ret) { if (ret) {
printf("DRM: HDR metadata: failed property set %d\n",ret); printf("DRM: HDR metadata: failed property set %d\n",ret);
if (render->hdr_blob_id) if (render->hdr_blob_id)
drmModeDestroyPropertyBlob(render->fd_drm, render->hdr_blob_id); drmModeDestroyPropertyBlob(render->fd_drm, render->hdr_blob_id);
render->hdr_blob_id = 0; render->hdr_blob_id = 0;
return; return;
} }
m_need_modeset = 1; m_need_modeset = 1;
Debug(3,"DRM: HDR metadata: prop set\n");
}
Debug(3,"DRM: HDR metadata: prop set\n");
}

File diff suppressed because it is too large Load Diff

View File

@@ -103,14 +103,14 @@ class cOglGlyph:public cListObject
struct tKerning struct tKerning
{ {
public: public:
tKerning(uint prevSym, GLfloat kerning = 0.0f) { tKerning(FT_ULong prevSym, GLfloat kerning = 0.0f) {
this->prevSym = prevSym; this->prevSym = prevSym;
this->kerning = kerning; this->kerning = kerning;
} }
uint prevSym; FT_ULong prevSym;
GLfloat kerning; GLfloat kerning;
}; };
uint charCode; FT_ULong charCode;
int bearingLeft; int bearingLeft;
int bearingTop; int bearingTop;
int width; int width;
@@ -122,9 +122,9 @@ class cOglGlyph:public cListObject
void LoadTexture(FT_BitmapGlyph ftGlyph); void LoadTexture(FT_BitmapGlyph ftGlyph);
public: public:
cOglGlyph(uint charCode, FT_BitmapGlyph ftGlyph); cOglGlyph(FT_ULong charCode, FT_BitmapGlyph ftGlyph);
virtual ~ cOglGlyph(); virtual ~ cOglGlyph();
uint CharCode(void) FT_ULong CharCode(void)
{ {
return charCode; return charCode;
} }
@@ -148,8 +148,8 @@ class cOglGlyph:public cListObject
{ {
return height; return height;
} }
int GetKerningCache(uint prevSym); int GetKerningCache(FT_ULong prevSym);
void SetKerningCache(uint prevSym, int kerning); void SetKerningCache(FT_ULong prevSym, int kerning);
void BindTexture(void); void BindTexture(void);
}; };
@@ -190,8 +190,8 @@ class cOglFont:public cListObject
{ {
return height; return height;
}; };
cOglGlyph *Glyph(uint charCode) const; cOglGlyph *Glyph(FT_ULong charCode) const;
int Kerning(cOglGlyph * glyph, uint prevSym) const; int Kerning(cOglGlyph * glyph, FT_ULong prevSym) const;
}; };
/**************************************************************************************** /****************************************************************************************

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR \n" "Project-Id-Version: VDR \n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2019-10-26 18:41+0200\n" "POT-Creation-Date: 2020-04-15 18:57+0200\n"
"PO-Revision-Date: blabla\n" "PO-Revision-Date: blabla\n"
"Last-Translator: blabla\n" "Last-Translator: blabla\n"
"Language-Team: blabla\n" "Language-Team: blabla\n"
@@ -263,9 +263,6 @@ msgstr ""
msgid "codec: can't allocate video codec context\n" msgid "codec: can't allocate video codec context\n"
msgstr "" msgstr ""
msgid "VAAPI Refcounts invalid\n"
msgstr ""
msgid "codec: can't set option deint to video codec!\n" msgid "codec: can't set option deint to video codec!\n"
msgstr "" msgstr ""
@@ -306,24 +303,6 @@ msgstr ""
msgid "codec/audio: decoded data smaller than encoded\n" msgid "codec/audio: decoded data smaller than encoded\n"
msgstr "" msgstr ""
msgid "codec/audio: resample setup error\n"
msgstr ""
msgid "codec/audio: overwrite resample\n"
msgstr ""
msgid "codec/audio: AvResample setup error\n"
msgstr ""
msgid "codec: latm\n"
msgstr ""
msgid "codec: error audio data\n"
msgstr ""
msgid "codec: error more than one frame data\n"
msgstr ""
msgid "codec/audio: can't setup resample\n" msgid "codec/audio: can't setup resample\n"
msgstr "" msgstr ""
@@ -471,18 +450,6 @@ msgstr "Schneide oben und unten ab (Pixel)"
msgid "Cut left and right (pixel)" msgid "Cut left and right (pixel)"
msgstr "Schneide links und rechts ab (Pixel)" msgstr "Schneide links und rechts ab (Pixel)"
msgid "Auto-crop"
msgstr ""
msgid "Autocrop interval (frames)"
msgstr ""
msgid "Autocrop delay (n * interval)"
msgstr ""
msgid "Autocrop tolerance (pixel)"
msgstr ""
msgid "Audio" msgid "Audio"
msgstr "Audio" msgstr "Audio"
@@ -642,7 +609,7 @@ msgid " Frames missed(%d) duped(%d) dropped(%d) total(%d)"
msgstr " Frames verloren(%d) verdoppelt(%d) übersprungen(%d) Gesamt(%d)" msgstr " Frames verloren(%d) verdoppelt(%d) übersprungen(%d) Gesamt(%d)"
#, c-format #, c-format
msgid " Frame Process time %2.2fms" msgid " Video %dx%d Color: %s Gamma: %s"
msgstr "" msgstr ""
msgid "pass-through disabled" msgid "pass-through disabled"
@@ -661,12 +628,6 @@ msgstr ""
msgid "surround downmix disabled" msgid "surround downmix disabled"
msgstr "" msgstr ""
msgid "auto-crop disabled and freezed"
msgstr ""
msgid "auto-crop enabled"
msgstr ""
#, c-format #, c-format
msgid "[softhddev]: hot key %d is not supported\n" msgid "[softhddev]: hot key %d is not supported\n"
msgstr "" msgstr ""
@@ -807,10 +768,6 @@ msgstr ""
msgid "video/glx: no GLX support\n" msgid "video/glx: no GLX support\n"
msgstr "" msgstr ""
#, c-format
msgid "video/glx: glx version %d.%d\n"
msgstr ""
msgid "did not get FBconfig" msgid "did not get FBconfig"
msgstr "" msgstr ""
@@ -898,11 +855,10 @@ msgid "Failed rendering frame!\n"
msgstr "" msgstr ""
#, c-format #, c-format
msgid "video/vdpau: output buffer full, dropping frame (%d/%d)\n" msgid "video/cuvid: output buffer full, dropping frame (%d/%d)\n"
msgstr "" msgstr ""
#, c-format msgid "Could not dynamically load CUDA\n"
msgid "video/vdpau: pixel format %d not supported\n"
msgstr "" msgstr ""
msgid "Kein Cuda device gefunden" msgid "Kein Cuda device gefunden"
@@ -943,12 +899,6 @@ msgstr ""
msgid "video/egl: can't create thread egl context\n" msgid "video/egl: can't create thread egl context\n"
msgstr "" msgstr ""
msgid "video: can't queue cancel video display thread\n"
msgstr ""
msgid "video: can't cancel video display thread\n"
msgstr ""
#, c-format #, c-format
msgid "video: repeated pict %d found, but not handled\n" msgid "video: repeated pict %d found, but not handled\n"
msgstr "" msgstr ""

409
shaders.h
View File

@@ -1,4 +1,5 @@
// shader // shader
#define SHADER_LENGTH 10000
#ifdef CUVID #ifdef CUVID
const char *gl_version = "#version 330"; const char *gl_version = "#version 330";
@@ -10,174 +11,6 @@ const char *gl_version = "#version 300 es ";
#endif #endif
#endif #endif
char vertex_3[] = {"\
%s\n\
in vec2 vertex_position;\n\
in vec2 vertex_texcoord0;\n\
out vec2 texcoord0;\n\
in vec2 vertex_texcoord1;\n\
out vec2 texcoord1;\n\
in vec2 vertex_texcoord2;\n\
out vec2 texcoord2;\n\
void main() {\n\
gl_Position = vec4(vertex_position, 1.0, 1.0);\n\
texcoord0 = vertex_texcoord0;\n\
texcoord1 = vertex_texcoord1;\n\
texcoord2 = vertex_texcoord1;\n\
}\n"};
char fragment_3[] = {"\
%s\n\
#define texture1D texture\n\
#define texture3D texture\n\
precision mediump float; \
layout(location = 0) out vec4 out_color;\n\
in vec2 texcoord0;\n\
in vec2 texcoord1;\n\
in vec2 texcoord2;\n\
uniform mat3 colormatrix;\n\
uniform vec3 colormatrix_c;\n\
uniform sampler2D texture0;\n\
uniform sampler2D texture1;\n\
uniform sampler2D texture2;\n\
//#define LUT_POS(x, lut_size) mix(0.5 / (lut_size), 1.0 - 0.5 / (lut_size), (x))\n\
void main() {\n\
vec4 color; // = vec4(0.0, 0.0, 0.0, 1.0);\n\
color.r = 1.000000 * vec4(texture(texture0, texcoord0)).r;\n\
color.g = 1.000000 * vec4(texture(texture1, texcoord1)).r;\n\
color.b = 1.000000 * vec4(texture(texture2, texcoord2)).r;\n\
// color conversion\n\
color.rgb = mat3(colormatrix) * color.rgb + colormatrix_c;\n\
color.a = 1.0;\n\
// color mapping\n\
out_color = color;\n\
}\n"};
char fragment_bt2100_3[] = {"\
%s\n \
#define texture1D texture\n\
#define texture3D texture\n\
precision mediump float; \
layout(location = 0) out vec4 out_color;\n\
in vec2 texcoord0;\n\
in vec2 texcoord1;\n\
in vec2 texcoord2;\n\
uniform mat3 colormatrix;\n\
uniform vec3 colormatrix_c;\n\
uniform mat3 cms_matrix;\n\
uniform sampler2D texture0;\n\
uniform sampler2D texture1;\n\
uniform sampler2D texture2;\n\
//#define LUT_POS(x, lut_size) mix(0.5 / (lut_size), 1.0 - 0.5 / (lut_size), (x))\n\
void main() {\n\
vec4 color; // = vec4(0.0, 0.0, 0.0, 1.0);\n\
color.r = 1.003906 * vec4(texture(texture0, texcoord0)).r;\n\
color.g = 1.003906 * vec4(texture(texture1, texcoord1)).r;\n\
color.b = 1.003906 * vec4(texture(texture2, texcoord2)).r;\n\
// color conversion\n\
color.rgb = mat3(colormatrix) * color.rgb + colormatrix_c;\n\
color.a = 1.0;\n\
// color mapping\n\
color.rgb = clamp(color.rgb, 0.0, 1.0);\n\
color.rgb = pow(color.rgb, vec3(2.4));\n\
color.rgb = cms_matrix * color.rgb;\n\
color.rgb = clamp(color.rgb, 0.0, 1.0);\n\
color.rgb = pow(color.rgb, vec3(1.0/2.4));\n\
out_color = color;\n\
}\n"};
char vertex_osd[] = { "\
%s\n\
in vec2 vertex_position;\n\
in vec2 vertex_texcoord0;\n\
out vec2 texcoord0;\n\
void main() {\n\
gl_Position = vec4(vertex_position, 1.0, 1.0);\n\
texcoord0 = vertex_texcoord0;\n\
}\n" };
char fragment_osd[] = { "\
%s\n\
#define texture1D texture\n\
precision mediump float; \
layout(location = 0) out vec4 out_color;\n\
in vec2 texcoord0;\n\
uniform sampler2D texture0;\n\
void main() {\n\
vec4 color; \n\
color = vec4(texture(texture0, texcoord0));\n\
out_color = color;\n\
}\n" };
char vertex[] = { "\
%s\n\
in vec2 vertex_position;\n\
in vec2 vertex_texcoord0;\n\
out vec2 texcoord0;\n\
in vec2 vertex_texcoord1;\n\
out vec2 texcoord1;\n\
void main() {\n\
gl_Position = vec4(vertex_position, 1.0, 1.0);\n\
texcoord0 = vertex_texcoord0;\n\
texcoord1 = vertex_texcoord1;\n\
}\n" };
char fragment[] = { "\
%s\n\
#define texture1D texture\n\
#define texture3D texture\n\
precision mediump float; \
layout(location = 0) out vec4 out_color;\n\
in vec2 texcoord0;\n\
in vec2 texcoord1;\n\
uniform mat3 colormatrix;\n\
uniform vec3 colormatrix_c;\n\
uniform sampler2D texture0;\n\
uniform sampler2D texture1;\n\
//#define LUT_POS(x, lut_size) mix(0.5 / (lut_size), 1.0 - 0.5 / (lut_size), (x))\n\
void main() {\n\
vec4 color; // = vec4(0.0, 0.0, 0.0, 1.0);\n\
color.r = 1.000000 * vec4(texture(texture0, texcoord0)).r;\n\
color.gb = 1.000000 * vec4(texture(texture1, texcoord1)).rg;\n\
// color conversion\n\
color.rgb = mat3(colormatrix) * color.rgb + colormatrix_c;\n\
color.a = 1.0;\n\
// color mapping\n\
out_color = color;\n\
}\n" };
char fragment_bt2100[] = { "\
%s\n \
#define texture1D texture\n\
#define texture3D texture\n\
precision mediump float; \
layout(location = 0) out vec4 out_color;\n\
in vec2 texcoord0;\n\
in vec2 texcoord1;\n\
uniform mat3 colormatrix;\n\
uniform vec3 colormatrix_c;\n\
uniform mat3 cms_matrix;\n\
uniform sampler2D texture0;\n\
uniform sampler2D texture1;\n\
//#define LUT_POS(x, lut_size) mix(0.5 / (lut_size), 1.0 - 0.5 / (lut_size), (x))\n\
void main() {\n\
vec4 color; // = vec4(0.0, 0.0, 0.0, 1.0);\n\
color.r = 1.003906 * vec4(texture(texture0, texcoord0)).r;\n\
color.gb = 1.003906 * vec4(texture(texture1, texcoord1)).rg;\n\
// color conversion\n\
color.rgb = mat3(colormatrix) * color.rgb + colormatrix_c;\n\
color.a = 1.0;\n\
// color mapping\n\
color.rgb = clamp(color.rgb, 0.0, 1.0);\n\
color.rgb = pow(color.rgb, vec3(2.4));\n\
color.rgb = cms_matrix * color.rgb;\n\
color.rgb = clamp(color.rgb, 0.0, 1.0);\n\
color.rgb = pow(color.rgb, vec3(1.0/2.4));\n\
out_color = color;\n\
}\n" };
/* Color conversion matrix: RGB = m * YUV + c /* Color conversion matrix: RGB = m * YUV + c
* m is in row-major matrix, with m[row][col], e.g.: * m is in row-major matrix, with m[row][col], e.g.:
* [ a11 a12 a13 ] float m[3][3] = { { a11, a12, a13 }, * [ a11 a12 a13 ] float m[3][3] = { { a11, a12, a13 },
@@ -205,37 +38,49 @@ struct mp_mat
// YUV input limited range (16-235 for luma, 16-240 for chroma) // YUV input limited range (16-235 for luma, 16-240 for chroma)
// ITU-R BT.601 (SD) // ITU-R BT.601 (SD)
struct mp_cmat yuv_bt601 = { {{1.164384, 1.164384, 1.164384}, struct mp_cmat yuv_bt601 = { {{1.164384, 1.164384, 1.164384},
{0.00000, -0.391762, 2.017232}, {0.00000, -0.391762, 2.017232},
{1.596027, -0.812968, 0.000000}}, {1.596027, -0.812968, 0.000000}},
{-0.874202, 0.531668, -1.085631} {-0.874202, 0.531668, -1.085631}
}; };
// ITU-R BT.709 (HD) // ITU-R BT.709 (HD)
struct mp_cmat yuv_bt709 = { {{1.164384, 1.164384, 1.164384}, struct mp_cmat yuv_bt709 = { {{1.164384, 1.164384, 1.164384},
{0.00000, -0.213249, 2.112402}, {0.00000, -0.213249, 2.112402},
{1.792741, -0.532909, 0.000000}}, {1.792741, -0.532909, 0.000000}},
{-0.972945, 0.301483, -1.133402} {-0.972945, 0.301483, -1.133402}
}; };
// ITU-R BT.2020 non-constant luminance system // ITU-R BT.2020 non-constant luminance system
struct mp_cmat yuv_bt2020ncl = { {{1.164384, 1.164384, 1.164384}, struct mp_cmat yuv_bt2020ncl = { {{1.164384, 1.164384, 1.164384},
{0.00000, -0.187326, 2.141772}, {0.00000, -0.187326, 2.141772},
{1.678674, -0.650424, 0.000000}}, {1.678674, -0.650424, 0.000000}},
{-0.915688, 0.347459, -1.148145} {-0.915688, 0.347459, -1.148145}
}; };
// ITU-R BT.2020 constant luminance system // ITU-R BT.2020 constant luminance system
struct mp_cmat yuv_bt2020cl = { {{0.0000, 1.164384, 0.000000}, struct mp_cmat yuv_bt2020cl = { {{0.0000, 1.164384, 0.000000},
{0.00000, 0.000000, 1.138393}, {0.00000, 0.000000, 1.138393},
{1.138393, 0.000000, 0.000000}}, {1.138393, 0.000000, 0.000000}},
{-0.571429, -0.073059, -0.571429} {-0.571429, -0.073059, -0.571429}
}; };
float cms_matrix[3][3] = { {1.660497, -0.124547, -0.018154}, float cms_matrix[3][3] = { {1.660497, -0.124547, -0.018154},
{-0.587657, 1.132895, -0.100597}, {-0.587657, 1.132895, -0.100597},
{-0.072840, -0.008348, 1.118751} {-0.072840, -0.008348, 1.118751}
}; };
// Common constants for SMPTE ST.2084 (PQ)
static const float PQ_M1 = 2610. / 4096 * 1. / 4,
PQ_M2 = 2523. / 4096 * 128,
PQ_C1 = 3424. / 4096,
PQ_C2 = 2413. / 4096 * 32,
PQ_C3 = 2392. / 4096 * 32;
// Common constants for ARIB STD-B67 (HLG)
static const float HLG_A = 0.17883277,
HLG_B = 0.28466892,
HLG_C = 0.55991073;
struct gl_vao_entry struct gl_vao_entry
{ {
// used for shader / glBindAttribLocation // used for shader / glBindAttribLocation
@@ -272,16 +117,61 @@ static const struct gl_vao_entry vertex_vao[] = {
{0} {0}
}; };
#define GLSL(...) pl_shader_append(__VA_ARGS__)
#define GLSLV(...) pl_shader_append_v(__VA_ARGS__)
char sh[SHADER_LENGTH];
char shv[SHADER_LENGTH];
GL_init()
{
sh[0] = 0;
}
GLV_init()
{
shv[0] = 0;
}
pl_shader_append(const char *fmt, ...)
{
char temp[1000];
va_list ap;
va_start(ap, fmt);
vsprintf(temp, fmt, ap);
va_end(ap);
if (strlen(sh) + strlen(temp) > SHADER_LENGTH)
Fatal(_("Shaderlenght fault\n"));
strcat(sh, temp);
}
pl_shader_append_v(const char *fmt, ...)
{
char temp[1000];
va_list ap;
va_start(ap, fmt);
vsprintf(temp, fmt, ap);
va_end(ap);
if (strlen(shv) + strlen(temp) > SHADER_LENGTH)
Fatal(_("Shaderlenght fault\n"));
strcat(shv, temp);
}
static void compile_attach_shader(GLuint program, GLenum type, const char *source) static void compile_attach_shader(GLuint program, GLenum type, const char *source)
{ {
GLuint shader; GLuint shader;
GLint status, log_length; GLint status = 1234, log_length;
char log[4000]; char log[4000];
GLsizei len; GLsizei len;
char *buffer = (char *) malloc(1000);
sprintf(buffer,source,gl_version);
shader = glCreateShader(type); shader = glCreateShader(type);
glShaderSource(shader, 1, (const GLchar **)&buffer, NULL); glShaderSource(shader, 1, (const GLchar **)&source, NULL); // &buffer, NULL);
glCompileShader(shader); glCompileShader(shader);
status = 0; status = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status); glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
@@ -293,7 +183,7 @@ static void compile_attach_shader(GLuint program, GLenum type, const char *sourc
glAttachShader(program, shader); glAttachShader(program, shader);
glDeleteShader(shader); glDeleteShader(shader);
free(buffer);
} }
static void link_shader(GLuint program) static void link_shader(GLuint program)
@@ -313,14 +203,43 @@ static GLuint sc_generate_osd(GLuint gl_prog)
Debug(3, "vor create osd\n"); Debug(3, "vor create osd\n");
gl_prog = glCreateProgram(); gl_prog = glCreateProgram();
GL_init();
GLSL("%s\n", gl_version);
GLSL("in vec2 vertex_position;\n");
GLSL("in vec2 vertex_texcoord0;\n");
GLSL("out vec2 texcoord0;\n");
GLSL("void main() {\n");
GLSL("gl_Position = vec4(vertex_position, 1.0, 1.0);\n");
GLSL("texcoord0 = vertex_texcoord0;\n");
GLSL("}\n");
Debug(3, "vor compile vertex osd\n"); Debug(3, "vor compile vertex osd\n");
compile_attach_shader(gl_prog, GL_VERTEX_SHADER, vertex_osd); compile_attach_shader(gl_prog, GL_VERTEX_SHADER, sh); // vertex_osd);
GL_init();
GLSL("%s\n", gl_version);
GLSL("#define texture1D texture\n");
GLSL("precision mediump float; \n");
GLSL("layout(location = 0) out vec4 out_color;\n");
GLSL("in vec2 texcoord0;\n");
GLSL("uniform sampler2D texture0;\n");
GLSL("void main() {\n");
GLSL("vec4 color; \n");
GLSL("color = vec4(texture(texture0, texcoord0));\n");
#ifdef GAMMA
GLSL("// delinearize gamma \n");
GLSL("color.rgb = clamp(color.rgb, 0.0, 1.0); \n"); // delinearize gamma
GLSL("color.rgb = pow(color.rgb, vec3(2.4)); \n");
#endif
GLSL("out_color = color;\n");
GLSL("}\n");
Debug(3, "vor compile fragment osd \n"); Debug(3, "vor compile fragment osd \n");
compile_attach_shader(gl_prog, GL_FRAGMENT_SHADER, fragment_osd); compile_attach_shader(gl_prog, GL_FRAGMENT_SHADER, sh); //fragment_osd);
glBindAttribLocation(gl_prog, 0, "vertex_position"); glBindAttribLocation(gl_prog, 0, "vertex_position");
glBindAttribLocation(gl_prog, 1, "vertex_texcoord0"); glBindAttribLocation(gl_prog, 1, "vertex_texcoord0");
link_shader(gl_prog); link_shader(gl_prog);
return gl_prog; return gl_prog;
} }
@@ -333,41 +252,135 @@ static GLuint sc_generate(GLuint gl_prog, enum AVColorSpace colorspace)
float *m, *c, *cms; float *m, *c, *cms;
char *frag; char *frag;
GL_init();
GLSL("%s\n", gl_version);
GLSL("in vec2 vertex_position; \n");
GLSL("in vec2 vertex_texcoord0; \n");
GLSL("out vec2 texcoord0; \n");
GLSL("in vec2 vertex_texcoord1; \n");
GLSL("out vec2 texcoord1; \n");
if (Planes == 3) {
GLSL("in vec2 vertex_texcoord2; \n");
GLSL("out vec2 texcoord2; \n");
}
GLSL("void main() { \n");
GLSL("gl_Position = vec4(vertex_position, 1.0, 1.0);\n");
GLSL("texcoord0 = vertex_texcoord0; \n");
GLSL("texcoord1 = vertex_texcoord1; \n");
if (Planes == 3) {
GLSL("texcoord2 = vertex_texcoord1; \n"); // texcoord1 ist hier richtig
}
GLSL("} \n");
Debug(3, "vor create\n");
gl_prog = glCreateProgram();
Debug(3, "vor compile vertex\n");
// printf("%s",sh);
compile_attach_shader(gl_prog, GL_VERTEX_SHADER, sh);
switch (colorspace) { switch (colorspace) {
case AVCOL_SPC_RGB: case AVCOL_SPC_RGB:
m = &yuv_bt601.m[0][0]; m = &yuv_bt601.m[0][0];
c = &yuv_bt601.c[0]; c = &yuv_bt601.c[0];
frag = Planes == 3?fragment_3:fragment;
Debug(3, "BT601 Colorspace used\n"); Debug(3, "BT601 Colorspace used\n");
break; break;
case AVCOL_SPC_BT709: case AVCOL_SPC_BT709:
case AVCOL_SPC_UNSPECIFIED: // comes with UHD case AVCOL_SPC_UNSPECIFIED: // comes with UHD
m = &yuv_bt709.m[0][0]; m = &yuv_bt709.m[0][0];
c = &yuv_bt709.c[0]; c = &yuv_bt709.c[0];
frag = Planes==3?fragment_3:fragment;
Debug(3, "BT709 Colorspace used\n"); Debug(3, "BT709 Colorspace used\n");
break; break;
case AVCOL_SPC_BT2020_NCL: case AVCOL_SPC_BT2020_NCL:
m = &yuv_bt2020ncl.m[0][0]; m = &yuv_bt2020ncl.m[0][0];
c = &yuv_bt2020ncl.c[0]; c = &yuv_bt2020ncl.c[0];
cms = &cms_matrix[0][0]; cms = &cms_matrix[0][0];
frag = Planes == 3?fragment_bt2100_3:fragment_bt2100;
Debug(3, "BT2020NCL Colorspace used\n"); Debug(3, "BT2020NCL Colorspace used\n");
break; break;
default: // fallback default: // fallback
m = &yuv_bt709.m[0][0]; m = &yuv_bt709.m[0][0];
c = &yuv_bt709.c[0]; c = &yuv_bt709.c[0];
frag = Planes==3?fragment_3:fragment;
Debug(3, "default BT709 Colorspace used %d\n", colorspace); Debug(3, "default BT709 Colorspace used %d\n", colorspace);
break; break;
} }
Debug(3, "vor create\n"); GL_init();
gl_prog = glCreateProgram();
Debug(3, "vor compile vertex\n"); GLSL("%s\n", gl_version);
compile_attach_shader(gl_prog, GL_VERTEX_SHADER, Planes==3?vertex_3:vertex); GLSL("precision mediump float; \n");
GLSL("layout(location = 0) out vec4 out_color;\n");
GLSL("in vec2 texcoord0; \n");
GLSL("in vec2 texcoord1; \n");
if (Planes == 3)
GLSL("in vec2 texcoord2; \n");
GLSL("uniform mat3 colormatrix; \n");
GLSL("uniform vec3 colormatrix_c; \n");
if (colorspace == AVCOL_SPC_BT2020_NCL)
GLSL("uniform mat3 cms_matrix;\n");
GLSL("uniform sampler2D texture0; \n");
GLSL("uniform sampler2D texture1; \n");
if (Planes == 3)
GLSL("uniform sampler2D texture2; \n");
GLSL("void main() { \n");
GLSL("vec4 color; \n");
if (colorspace == AVCOL_SPC_BT2020_NCL) {
GLSL("color.r = 1.003906 * vec4(texture(texture0, texcoord0)).r; \n");
if (Planes == 3) {
GLSL("color.g = 1.003906 * vec4(texture(texture1, texcoord1)).r; \n");
GLSL("color.b = 1.003906 * vec4(texture(texture2, texcoord2)).r; \n");
} else {
GLSL("color.gb = 1.003906 * vec4(texture(texture1, texcoord1)).rg;\n");
}
GLSL("// color conversion\n");
GLSL("color.rgb = mat3(colormatrix) * color.rgb + colormatrix_c; \n");
GLSL("color.a = 1.0; \n");
GLSL("// pl_shader_linearize \n");
GLSL("color.rgb = max(color.rgb, 0.0); \n");
// GLSL("color.rgb = clamp(color.rgb, 0.0, 1.0); \n");
// GLSL("color.rgb = pow(color.rgb, vec3(2.4)); \n");
// GLSL("color.rgb = mix(vec3(4.0) * color.rgb * color.rgb,exp((color.rgb - vec3(%f)) * vec3(1.0/%f)) + vec3(%f),bvec3(lessThan(vec3(0.5), color.rgb)));\n",HLG_C, HLG_A, HLG_B);
GLSL("color.rgb = mix(vec3(4.0) * color.rgb * color.rgb,exp((color.rgb - vec3(0.55991073)) * vec3(1.0/0.17883277)) + vec3(0.28466892), bvec3(lessThan(vec3(0.5), color.rgb)));\n");
GLSL("// color mapping \n");
GLSL("color.rgb = cms_matrix * color.rgb; \n");
#ifndef GAMMA
GLSL("// pl_shader_delinearize \n");
GLSL("color.rgb = max(color.rgb, 0.0); \n");
// GLSL("color.rgb = clamp(color.rgb, 0.0, 1.0); \n");
// GLSL("color.rgb = pow(color.rgb, vec3(1.0/2.4)); \n");
GLSL("color.rgb = mix(vec3(0.5) * sqrt(color.rgb), vec3(0.17883277) * log(color.rgb - vec3(0.28466892)) + vec3(0.55991073), bvec3(lessThan(vec3(1.0), color.rgb))); \n");
#endif
GLSL("out_color = color; \n");
GLSL("} \n");
} else {
GLSL("color.r = 1.000000 * vec4(texture(texture0, texcoord0)).r; \n");
if (Planes == 3) {
GLSL("color.g = 1.000000 * vec4(texture(texture1, texcoord1)).r;\n");
GLSL("color.b = 1.000000 * vec4(texture(texture2, texcoord2)).r;\n");
} else {
GLSL("color.gb = 1.000000 * vec4(texture(texture1, texcoord1)).rg; \n");
}
GLSL("// color conversion \n");
GLSL("color.rgb = mat3(colormatrix) * color.rgb + colormatrix_c; \n");
GLSL("color.a = 1.0; \n");
GLSL("// linearize gamma \n");
GLSL("color.rgb = clamp(color.rgb, 0.0, 1.0); \n"); // linearize gamma
GLSL("color.rgb = pow(color.rgb, vec3(2.4)); \n");
#ifndef GAMMA
GLSL("// delinearize gamma to sRGB \n");
GLSL("color.rgb = max(color.rgb, 0.0); \n");
GLSL("color.rgb = mix(color.rgb * vec3(12.92), vec3(1.055) * pow(color.rgb, vec3(1.0/2.4)) - vec3(0.055), bvec3(lessThanEqual(vec3(0.0031308), color.rgb))); \n");
#endif
GLSL("// color mapping \n");
GLSL("out_color = color; \n");
GLSL("} \n");
}
//printf(">%s<",sh);
Debug(3, "vor compile fragment\n"); Debug(3, "vor compile fragment\n");
compile_attach_shader(gl_prog, GL_FRAGMENT_SHADER, frag); compile_attach_shader(gl_prog, GL_FRAGMENT_SHADER, sh);
glBindAttribLocation(gl_prog, 0, "vertex_position"); glBindAttribLocation(gl_prog, 0, "vertex_position");
for (n = 0; n < 6; n++) { for (n = 0; n < 6; n++) {

222
shaders/KrigBilateral.glsl Normal file
View File

@@ -0,0 +1,222 @@
// KrigBilateral by Shiandow
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3.0 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library.
//!HOOK CHROMA
//!BIND HOOKED
//!BIND LUMA
//!SAVE LOWRES_Y
//!WIDTH LUMA.w
//!WHEN CHROMA.w LUMA.w <
//!DESC KrigBilateral Downscaling Y pass 1
#define offset vec2(0,0)
#define axis 1
#define Kernel(x) dot(vec3(0.42659, -0.49656, 0.076849), cos(vec3(0, 1, 2) * acos(-1.) * (x + 1.)))
vec4 hook() {
// Calculate bounds
float low = ceil((LUMA_pos - CHROMA_pt) * LUMA_size - offset - 0.5)[axis];
float high = floor((LUMA_pos + CHROMA_pt) * LUMA_size - offset - 0.5)[axis];
float W = 0.0;
vec4 avg = vec4(0);
vec2 pos = LUMA_pos;
for (float k = low; k <= high; k++) {
pos[axis] = LUMA_pt[axis] * (k - offset[axis] + 0.5);
float rel = (pos[axis] - LUMA_pos[axis])*CHROMA_size[axis];
float w = Kernel(rel);
vec4 y = textureGrad(LUMA_raw, pos, vec2(0.0), vec2(0.0)).xxxx * LUMA_mul;
y.y *= y.y;
avg += w * y;
W += w;
}
avg /= W;
avg.y = abs(avg.y - pow(avg.x, 2.0));
return avg;
}
//!HOOK CHROMA
//!BIND HOOKED
//!BIND LOWRES_Y
//!SAVE LOWRES_Y
//!WHEN CHROMA.w LUMA.w <
//!DESC KrigBilateral Downscaling Y pass 2
#define offset vec2(0,0)
#define axis 0
#define Kernel(x) dot(vec3(0.42659, -0.49656, 0.076849), cos(vec3(0, 1, 2) * acos(-1.) * (x + 1.)))
vec4 hook() {
// Calculate bounds
float low = ceil((LOWRES_Y_pos - CHROMA_pt) * LOWRES_Y_size - offset - 0.5)[axis];
float high = floor((LOWRES_Y_pos + CHROMA_pt) * LOWRES_Y_size - offset - 0.5)[axis];
float W = 0.0;
vec4 avg = vec4(0);
vec2 pos = LOWRES_Y_pos;
for (float k = low; k <= high; k++) {
pos[axis] = LOWRES_Y_pt[axis] * (k - offset[axis] + 0.5);
float rel = (pos[axis] - LOWRES_Y_pos[axis])*CHROMA_size[axis];
float w = Kernel(rel);
vec4 y = textureGrad(LOWRES_Y_raw, pos, vec2(0.0), vec2(0.0)).xxxx * LOWRES_Y_mul;
y.y *= y.y;
avg += w * y;
W += w;
}
avg /= W;
avg.y = abs(avg.y - pow(avg.x, 2.0)) + LOWRES_Y_texOff(0).y;
return avg;
}
//!HOOK CHROMA
//!BIND HOOKED
//!BIND LUMA
//!BIND LOWRES_Y
//!WIDTH LUMA.w
//!HEIGHT LUMA.h
//!WHEN CHROMA.w LUMA.w <
//!OFFSET ALIGN
//!DESC KrigBilateral Upscaling UV
// -- Convenience --
#define sqr(x) dot(x,x)
#define bitnoise 1.0/(2.0*255.0)
#define noise 0.05//5.0*bitnoise
#define chromaOffset vec2(0.0, 0.0)
// -- Window Size --
#define taps 3
#define even (float(taps) - 2.0 * floor(float(taps) / 2.0) == 0.0)
#define minX int(1.0-ceil(float(taps)/2.0))
#define maxX int(floor(float(taps)/2.0))
#define Kernel(x) (cos(acos(-1.0)*(x)/float(taps))) // Hann kernel
// -- Input processing --
#define GetY(coord) LOWRES_Y_tex(LOWRES_Y_pt*(pos+coord+vec2(0.5))).xy
#define GetUV(coord) CHROMA_tex(CHROMA_pt*(pos+coord+vec2(0.5))).xy
#define N (taps*taps - 1)
#define M(i,j) Mx[min(i,j)*N + max(i,j) - min(i,j)*(min(i,j)+1)/2]
#define C(i,j) (inversesqrt(1.0 + (X[i].y + X[j].y)/localVar) * exp(-0.5*(sqr(X[i].x - X[j].x)/(localVar + X[i].y + X[j].y) + sqr((coords[i] - coords[j])/radius))) + (X[i].x - y) * (X[j].x - y) / localVar)
#define c(i) (inversesqrt(1.0 + X[i].y/localVar) * exp(-0.5*(sqr(X[i].x - y)/(localVar + X[i].y) + sqr((coords[i] - offset)/radius))))
vec4 hook() {
vec2 pos = CHROMA_pos * HOOKED_size - chromaOffset - vec2(0.5);
vec2 offset = pos - (even ? floor(pos) : round(pos));
pos -= offset;
vec2 coords[N+1];
vec4 X[N+1];
float y = LUMA_texOff(0).x;
vec4 total = vec4(0);
coords[0] = vec2(-1,-1); coords[1] = vec2(-1, 0); coords[2] = vec2(-1, 1);
coords[3] = vec2( 0,-1); coords[4] = vec2( 0, 1); coords[5] = vec2( 1,-1);
coords[6] = vec2( 1, 0); coords[7] = vec2( 1, 1); coords[8] = vec2( 0, 0);
for (int i=0; i<N+1; i++) {
X[i] = vec4(GetY(coords[i]), GetUV(coords[i]));
vec2 w = clamp(1.5 - abs(coords[i] - offset), 0.0, 1.0);
total += w.x*w.y*vec4(X[i].x, pow(X[i].x, 2.0), X[i].y, 1.0);
}
total.xyz /= total.w;
float localVar = sqr(noise) + abs(total.y - pow(total.x, 2.0)) + total.z;
float radius = 1.0;
float Mx[N*(N+1)/2];
float b[N];
vec4 interp = X[N];
b[0] = c(0) - c(N) - C(0,N) + C(N,N); M(0, 0) = C(0,0) - C(0,N) - C(0,N) + C(N,N); M(0, 1) = C(0,1) - C(1,N) - C(0,N) + C(N,N); M(0, 2) = C(0,2) - C(2,N) - C(0,N) + C(N,N); M(0, 3) = C(0,3) - C(3,N) - C(0,N) + C(N,N); M(0, 4) = C(0,4) - C(4,N) - C(0,N) + C(N,N); M(0, 5) = C(0,5) - C(5,N) - C(0,N) + C(N,N); M(0, 6) = C(0,6) - C(6,N) - C(0,N) + C(N,N); M(0, 7) = C(0,7) - C(7,N) - C(0,N) + C(N,N);
b[1] = c(1) - c(N) - C(1,N) + C(N,N); M(1, 1) = C(1,1) - C(1,N) - C(1,N) + C(N,N); M(1, 2) = C(1,2) - C(2,N) - C(1,N) + C(N,N); M(1, 3) = C(1,3) - C(3,N) - C(1,N) + C(N,N); M(1, 4) = C(1,4) - C(4,N) - C(1,N) + C(N,N); M(1, 5) = C(1,5) - C(5,N) - C(1,N) + C(N,N); M(1, 6) = C(1,6) - C(6,N) - C(1,N) + C(N,N); M(1, 7) = C(1,7) - C(7,N) - C(1,N) + C(N,N);
b[2] = c(2) - c(N) - C(2,N) + C(N,N); M(2, 2) = C(2,2) - C(2,N) - C(2,N) + C(N,N); M(2, 3) = C(2,3) - C(3,N) - C(2,N) + C(N,N); M(2, 4) = C(2,4) - C(4,N) - C(2,N) + C(N,N); M(2, 5) = C(2,5) - C(5,N) - C(2,N) + C(N,N); M(2, 6) = C(2,6) - C(6,N) - C(2,N) + C(N,N); M(2, 7) = C(2,7) - C(7,N) - C(2,N) + C(N,N);
b[3] = c(3) - c(N) - C(3,N) + C(N,N); M(3, 3) = C(3,3) - C(3,N) - C(3,N) + C(N,N); M(3, 4) = C(3,4) - C(4,N) - C(3,N) + C(N,N); M(3, 5) = C(3,5) - C(5,N) - C(3,N) + C(N,N); M(3, 6) = C(3,6) - C(6,N) - C(3,N) + C(N,N); M(3, 7) = C(3,7) - C(7,N) - C(3,N) + C(N,N);
b[4] = c(4) - c(N) - C(4,N) + C(N,N); M(4, 4) = C(4,4) - C(4,N) - C(4,N) + C(N,N); M(4, 5) = C(4,5) - C(5,N) - C(4,N) + C(N,N); M(4, 6) = C(4,6) - C(6,N) - C(4,N) + C(N,N); M(4, 7) = C(4,7) - C(7,N) - C(4,N) + C(N,N);
b[5] = c(5) - c(N) - C(5,N) + C(N,N); M(5, 5) = C(5,5) - C(5,N) - C(5,N) + C(N,N); M(5, 6) = C(5,6) - C(6,N) - C(5,N) + C(N,N); M(5, 7) = C(5,7) - C(7,N) - C(5,N) + C(N,N);
b[6] = c(6) - c(N) - C(6,N) + C(N,N); M(6, 6) = C(6,6) - C(6,N) - C(6,N) + C(N,N); M(6, 7) = C(6,7) - C(7,N) - C(6,N) + C(N,N);
b[7] = c(7) - c(N) - C(7,N) + C(N,N); M(7, 7) = C(7,7) - C(7,N) - C(7,N) + C(N,N);
b[1] -= b[0] * M(1, 0) / M(0, 0); M(1, 1) -= M(0, 1) * M(1, 0) / M(0, 0); M(1, 2) -= M(0, 2) * M(1, 0) / M(0, 0); M(1, 3) -= M(0, 3) * M(1, 0) / M(0, 0); M(1, 4) -= M(0, 4) * M(1, 0) / M(0, 0); M(1, 5) -= M(0, 5) * M(1, 0) / M(0, 0); M(1, 6) -= M(0, 6) * M(1, 0) / M(0, 0); M(1, 7) -= M(0, 7) * M(1, 0) / M(0, 0);
b[2] -= b[0] * M(2, 0) / M(0, 0); M(2, 2) -= M(0, 2) * M(2, 0) / M(0, 0); M(2, 3) -= M(0, 3) * M(2, 0) / M(0, 0); M(2, 4) -= M(0, 4) * M(2, 0) / M(0, 0); M(2, 5) -= M(0, 5) * M(2, 0) / M(0, 0); M(2, 6) -= M(0, 6) * M(2, 0) / M(0, 0); M(2, 7) -= M(0, 7) * M(2, 0) / M(0, 0);
b[3] -= b[0] * M(3, 0) / M(0, 0); M(3, 3) -= M(0, 3) * M(3, 0) / M(0, 0); M(3, 4) -= M(0, 4) * M(3, 0) / M(0, 0); M(3, 5) -= M(0, 5) * M(3, 0) / M(0, 0); M(3, 6) -= M(0, 6) * M(3, 0) / M(0, 0); M(3, 7) -= M(0, 7) * M(3, 0) / M(0, 0);
b[4] -= b[0] * M(4, 0) / M(0, 0); M(4, 4) -= M(0, 4) * M(4, 0) / M(0, 0); M(4, 5) -= M(0, 5) * M(4, 0) / M(0, 0); M(4, 6) -= M(0, 6) * M(4, 0) / M(0, 0); M(4, 7) -= M(0, 7) * M(4, 0) / M(0, 0);
b[5] -= b[0] * M(5, 0) / M(0, 0); M(5, 5) -= M(0, 5) * M(5, 0) / M(0, 0); M(5, 6) -= M(0, 6) * M(5, 0) / M(0, 0); M(5, 7) -= M(0, 7) * M(5, 0) / M(0, 0);
b[6] -= b[0] * M(6, 0) / M(0, 0); M(6, 6) -= M(0, 6) * M(6, 0) / M(0, 0); M(6, 7) -= M(0, 7) * M(6, 0) / M(0, 0);
b[7] -= b[0] * M(7, 0) / M(0, 0); M(7, 7) -= M(0, 7) * M(7, 0) / M(0, 0);
b[2] -= b[1] * M(2, 1) / M(1, 1); M(2, 2) -= M(1, 2) * M(2, 1) / M(1, 1); M(2, 3) -= M(1, 3) * M(2, 1) / M(1, 1); M(2, 4) -= M(1, 4) * M(2, 1) / M(1, 1); M(2, 5) -= M(1, 5) * M(2, 1) / M(1, 1); M(2, 6) -= M(1, 6) * M(2, 1) / M(1, 1); M(2, 7) -= M(1, 7) * M(2, 1) / M(1, 1);
b[3] -= b[1] * M(3, 1) / M(1, 1); M(3, 3) -= M(1, 3) * M(3, 1) / M(1, 1); M(3, 4) -= M(1, 4) * M(3, 1) / M(1, 1); M(3, 5) -= M(1, 5) * M(3, 1) / M(1, 1); M(3, 6) -= M(1, 6) * M(3, 1) / M(1, 1); M(3, 7) -= M(1, 7) * M(3, 1) / M(1, 1);
b[4] -= b[1] * M(4, 1) / M(1, 1); M(4, 4) -= M(1, 4) * M(4, 1) / M(1, 1); M(4, 5) -= M(1, 5) * M(4, 1) / M(1, 1); M(4, 6) -= M(1, 6) * M(4, 1) / M(1, 1); M(4, 7) -= M(1, 7) * M(4, 1) / M(1, 1);
b[5] -= b[1] * M(5, 1) / M(1, 1); M(5, 5) -= M(1, 5) * M(5, 1) / M(1, 1); M(5, 6) -= M(1, 6) * M(5, 1) / M(1, 1); M(5, 7) -= M(1, 7) * M(5, 1) / M(1, 1);
b[6] -= b[1] * M(6, 1) / M(1, 1); M(6, 6) -= M(1, 6) * M(6, 1) / M(1, 1); M(6, 7) -= M(1, 7) * M(6, 1) / M(1, 1);
b[7] -= b[1] * M(7, 1) / M(1, 1); M(7, 7) -= M(1, 7) * M(7, 1) / M(1, 1);
b[3] -= b[2] * M(3, 2) / M(2, 2); M(3, 3) -= M(2, 3) * M(3, 2) / M(2, 2); M(3, 4) -= M(2, 4) * M(3, 2) / M(2, 2); M(3, 5) -= M(2, 5) * M(3, 2) / M(2, 2); M(3, 6) -= M(2, 6) * M(3, 2) / M(2, 2); M(3, 7) -= M(2, 7) * M(3, 2) / M(2, 2);
b[4] -= b[2] * M(4, 2) / M(2, 2); M(4, 4) -= M(2, 4) * M(4, 2) / M(2, 2); M(4, 5) -= M(2, 5) * M(4, 2) / M(2, 2); M(4, 6) -= M(2, 6) * M(4, 2) / M(2, 2); M(4, 7) -= M(2, 7) * M(4, 2) / M(2, 2);
b[5] -= b[2] * M(5, 2) / M(2, 2); M(5, 5) -= M(2, 5) * M(5, 2) / M(2, 2); M(5, 6) -= M(2, 6) * M(5, 2) / M(2, 2); M(5, 7) -= M(2, 7) * M(5, 2) / M(2, 2);
b[6] -= b[2] * M(6, 2) / M(2, 2); M(6, 6) -= M(2, 6) * M(6, 2) / M(2, 2); M(6, 7) -= M(2, 7) * M(6, 2) / M(2, 2);
b[7] -= b[2] * M(7, 2) / M(2, 2); M(7, 7) -= M(2, 7) * M(7, 2) / M(2, 2);
b[4] -= b[3] * M(4, 3) / M(3, 3); M(4, 4) -= M(3, 4) * M(4, 3) / M(3, 3); M(4, 5) -= M(3, 5) * M(4, 3) / M(3, 3); M(4, 6) -= M(3, 6) * M(4, 3) / M(3, 3); M(4, 7) -= M(3, 7) * M(4, 3) / M(3, 3);
b[5] -= b[3] * M(5, 3) / M(3, 3); M(5, 5) -= M(3, 5) * M(5, 3) / M(3, 3); M(5, 6) -= M(3, 6) * M(5, 3) / M(3, 3); M(5, 7) -= M(3, 7) * M(5, 3) / M(3, 3);
b[6] -= b[3] * M(6, 3) / M(3, 3); M(6, 6) -= M(3, 6) * M(6, 3) / M(3, 3); M(6, 7) -= M(3, 7) * M(6, 3) / M(3, 3);
b[7] -= b[3] * M(7, 3) / M(3, 3); M(7, 7) -= M(3, 7) * M(7, 3) / M(3, 3);
b[5] -= b[4] * M(5, 4) / M(4, 4); M(5, 5) -= M(4, 5) * M(5, 4) / M(4, 4); M(5, 6) -= M(4, 6) * M(5, 4) / M(4, 4); M(5, 7) -= M(4, 7) * M(5, 4) / M(4, 4);
b[6] -= b[4] * M(6, 4) / M(4, 4); M(6, 6) -= M(4, 6) * M(6, 4) / M(4, 4); M(6, 7) -= M(4, 7) * M(6, 4) / M(4, 4);
b[7] -= b[4] * M(7, 4) / M(4, 4); M(7, 7) -= M(4, 7) * M(7, 4) / M(4, 4);
b[6] -= b[5] * M(6, 5) / M(5, 5); M(6, 6) -= M(5, 6) * M(6, 5) / M(5, 5); M(6, 7) -= M(5, 7) * M(6, 5) / M(5, 5);
b[7] -= b[5] * M(7, 5) / M(5, 5); M(7, 7) -= M(5, 7) * M(7, 5) / M(5, 5);
b[7] -= b[6] * M(7, 6) / M(6, 6); M(7, 7) -= M(6, 7) * M(7, 6) / M(6, 6);
b[N-1-0] /= M(N-1-0, N-1-0);
interp += b[N-1-0] * (X[N-1-0] - X[N]);
b[N-1-1] -= M(N-1-1, 7) * b[7]; b[N-1-1] /= M(N-1-1, N-1-1);
interp += b[N-1-1] * (X[N-1-1] - X[N]);
b[N-1-2] -= M(N-1-2, 6) * b[6]; b[N-1-2] -= M(N-1-2, 7) * b[7]; b[N-1-2] /= M(N-1-2, N-1-2);
interp += b[N-1-2] * (X[N-1-2] - X[N]);
b[N-1-3] -= M(N-1-3, 5) * b[5]; b[N-1-3] -= M(N-1-3, 6) * b[6]; b[N-1-3] -= M(N-1-3, 7) * b[7]; b[N-1-3] /= M(N-1-3, N-1-3);
interp += b[N-1-3] * (X[N-1-3] - X[N]);
b[N-1-4] -= M(N-1-4, 4) * b[4]; b[N-1-4] -= M(N-1-4, 5) * b[5]; b[N-1-4] -= M(N-1-4, 6) * b[6]; b[N-1-4] -= M(N-1-4, 7) * b[7]; b[N-1-4] /= M(N-1-4, N-1-4);
interp += b[N-1-4] * (X[N-1-4] - X[N]);
b[N-1-5] -= M(N-1-5, 3) * b[3]; b[N-1-5] -= M(N-1-5, 4) * b[4]; b[N-1-5] -= M(N-1-5, 5) * b[5]; b[N-1-5] -= M(N-1-5, 6) * b[6]; b[N-1-5] -= M(N-1-5, 7) * b[7]; b[N-1-5] /= M(N-1-5, N-1-5);
interp += b[N-1-5] * (X[N-1-5] - X[N]);
b[N-1-6] -= M(N-1-6, 2) * b[2]; b[N-1-6] -= M(N-1-6, 3) * b[3]; b[N-1-6] -= M(N-1-6, 4) * b[4]; b[N-1-6] -= M(N-1-6, 5) * b[5]; b[N-1-6] -= M(N-1-6, 6) * b[6]; b[N-1-6] -= M(N-1-6, 7) * b[7]; b[N-1-6] /= M(N-1-6, N-1-6);
interp += b[N-1-6] * (X[N-1-6] - X[N]);
b[N-1-7] -= M(N-1-7, 1) * b[1]; b[N-1-7] -= M(N-1-7, 2) * b[2]; b[N-1-7] -= M(N-1-7, 3) * b[3]; b[N-1-7] -= M(N-1-7, 4) * b[4]; b[N-1-7] -= M(N-1-7, 5) * b[5]; b[N-1-7] -= M(N-1-7, 6) * b[6]; b[N-1-7] -= M(N-1-7, 7) * b[7]; b[N-1-7] /= M(N-1-7, N-1-7);
interp += b[N-1-7] * (X[N-1-7] - X[N]);
return interp.zwxx;
}

View File

@@ -0,0 +1,206 @@
// vim: set ft=glsl:
/*
LumaSharpenHook 0.3
original hlsl by Christian Cann Schuldt Jensen ~ CeeJay.dk
port to glsl by Anon
It blurs the original pixel with the surrounding pixels and then subtracts this blur to sharpen the image.
It does this in luma to avoid color artifacts and allows limiting the maximum sharpning to avoid or lessen halo artifacts.
This is similar to using Unsharp Mask in Photoshop.
*/
// -- Hooks --
//!HOOK LUMA
//!BIND HOOKED
// -- Sharpening --
#define sharp_strength 0.30 //[0.10 to 3.00] Strength of the sharpening
#define sharp_clamp 0.035 //[0.000 to 1.000] Limits maximum amount of sharpening a pixel recieves - Default is 0.035
// -- Advanced sharpening settings --
#define pattern 2 //[1|2|3|4] Choose a sample pattern. 1 = Fast, 2 = Normal, 3 = Wider, 4 = Pyramid shaped.
//[8|9] Experimental slower patterns. 8 = 9 tap 9 fetch gaussian, 9 = 9 tap 9 fetch high pass.
#define offset_bias 1.0 //[0.0 to 6.0] Offset bias adjusts the radius of the sampling pattern.
vec4 hook(){
vec4 colorInput = LUMA_tex(LUMA_pos);
//We are on luma plane: xyzw = [luma_val, 0.0, 0.0, 1.0]
float ori = colorInput.x;
// -- Combining the strength and luma multipliers --
float sharp_strength_luma = sharp_strength; //I'll be combining even more multipliers with it later on
float px = 1.0;
float py = 1.0;
// Sampling patterns
// [ NW, , NE ] Each texture lookup (except ori)
// [ ,ori, ] samples 4 pixels
// [ SW, , SE ]
// -- Pattern 1 -- A (fast) 7 tap gaussian using only 2+1 texture fetches.
#if pattern == 1
// -- Gaussian filter --
// [ 1/9, 2/9, ] [ 1 , 2 , ]
// [ 2/9, 8/9, 2/9] = [ 2 , 8 , 2 ]
// [ , 2/9, 1/9] [ , 2 , 1 ]
px = (px / 3.0) * offset_bias;
py = (py / 3.0) * offset_bias;
float blur_ori = LUMA_texOff(vec2(px,py)).x; // North West
blur_ori += LUMA_texOff(vec2(-px,-py)).x; // South East
//blur_ori += LUMA_texOff(vec2(px,py)).x; // North East
//blur_ori += LUMA_texOff(vec2(-px,-py)).x; // South West
blur_ori *= 0.5; //Divide by the number of texture fetches
sharp_strength_luma *= 1.5; // Adjust strength to aproximate the strength of pattern 2
#endif
// -- Pattern 2 -- A 9 tap gaussian using 4+1 texture fetches.
#if pattern == 2
// -- Gaussian filter --
// [ .25, .50, .25] [ 1 , 2 , 1 ]
// [ .50, 1, .50] = [ 2 , 4 , 2 ]
// [ .25, .50, .25] [ 1 , 2 , 1 ]
px = px * 0.5 * offset_bias;
py = py * 0.5 * offset_bias;
float blur_ori = LUMA_texOff(vec2(px,-py)).x; // South East
blur_ori += LUMA_texOff(vec2(-px,-py)).x; // South West
blur_ori += LUMA_texOff(vec2(px,py)).x; // North East
blur_ori += LUMA_texOff(vec2(-px,py)).x; // North West
blur_ori *= 0.25; // ( /= 4) Divide by the number of texture fetches
#endif
// -- Pattern 3 -- An experimental 17 tap gaussian using 4+1 texture fetches.
#if pattern == 3
// -- Gaussian filter --
// [ , 4 , 6 , , ]
// [ ,16 ,24 ,16 , 4 ]
// [ 6 ,24 , ,24 , 6 ]
// [ 4 ,16 ,24 ,16 , ]
// [ , , 6 , 4 , ]
px = px * offset_bias;
py = py * offset_bias;
float blur_ori = LUMA_texOff(vec2(0.4*px,-1.2*py)).x; // South South East
blur_ori += LUMA_texOff(vec2(-1.2*px,-0.4*py)).x; // West South West
blur_ori += LUMA_texOff(vec2(1.2*px,0.4*py)).x; // East North East
blur_ori += LUMA_texOff(vec2(-0.4*px,1.2*py)).x; // North North West
blur_ori *= 0.25; // ( /= 4) Divide by the number of texture fetches
sharp_strength_luma *= 0.51;
#endif
// -- Pattern 4 -- A 9 tap high pass (pyramid filter) using 4+1 texture fetches.
#if pattern == 4
// -- Gaussian filter --
// [ .50, .50, .50] [ 1 , 1 , 1 ]
// [ .50, , .50] = [ 1 , , 1 ]
// [ .50, .50, .50] [ 1 , 1 , 1 ]
float blur_ori = LUMA_texOff(vec2(0.5 * px,-py * offset_bias)).x; // South South East
blur_ori += LUMA_texOff(vec2(offset_bias * -px,0.5 * -py)).x; // West South West
blur_ori += LUMA_texOff(vec2(offset_bias * px,0.5 * py)).x; // East North East
blur_ori += LUMA_texOff(vec2(0.5 * -px,py * offset_bias)).x; // North North West
//blur_ori += (2.0 * ori); // Probably not needed. Only serves to lessen the effect.
blur_ori *= 0.25; //Divide by the number of texture fetches
sharp_strength_luma *= 0.666; // Adjust strength to aproximate the strength of pattern 2
#endif
// -- Pattern 8 -- A (slower) 9 tap gaussian using 9 texture fetches.
#if pattern == 8
// -- Gaussian filter --
// [ 1 , 2 , 1 ]
// [ 2 , 4 , 2 ]
// [ 1 , 2 , 1 ]
px = px * offset_bias;
py = py * offset_bias;
float blur_ori = LUMA_texOff(vec2(-px,py)).x; // North West
blur_ori += LUMA_texOff(vec2(px,-py)).x; // South East
blur_ori += LUMA_texOff(vec2(-px,-py)).x; // South West
blur_ori += LUMA_texOff(vec2(px,py)).x; // North East
float blur_ori2 = LUMA_texOff(vec2(0.0,py)).x; // North
blur_ori2 += LUMA_texOff(vec2(0.0,-py)).x; // South
blur_ori2 += LUMA_texOff(vec2(-px,0.0)).x; // West
blur_ori2 += LUMA_texOff(vec2(px,0.0)).x; // East
blur_ori2 *= 2.0;
blur_ori += blur_ori2;
blur_ori += (ori * 4.0); // Probably not needed. Only serves to lessen the effect.
// dot()s with gaussian strengths here?
blur_ori /= 16.0; //Divide by the number of texture fetches
sharp_strength_luma *= 0.75; // Adjust strength to aproximate the strength of pattern 2
#endif
// -- Pattern 9 -- A (slower) 9 tap high pass using 9 texture fetches.
#if pattern == 9
// -- Gaussian filter --
// [ 1 , 1 , 1 ]
// [ 1 , 1 , 1 ]
// [ 1 , 1 , 1 ]
px = px * offset_bias;
py = py * offset_bias;
float blur_ori = LUMA_texOff(vec2(-px,py)).x; // North West
blur_ori += LUMA_texOff(vec2(px,-py)).x; // South East
blur_ori += LUMA_texOff(vec2(-px,-py)).x; // South West
blur_ori += LUMA_texOff(vec2(px,py)).x; // North East
blur_ori += ori; // Probably not needed. Only serves to lessen the effect.
blur_ori += LUMA_texOff(vec2(0.0,py)).x; // North
blur_ori += LUMA_texOff(vec2(0.0,-py)).x; // South
blur_ori += LUMA_texOff(vec2(-px,0.0)).x; // West
blur_ori += LUMA_texOff(vec2(px,0.0)).x; // East
blur_ori /= 9.0; //Divide by the number of texture fetches
sharp_strength_luma *= (8.0/9.0); // Adjust strength to aproximate the strength of pattern 2
#endif
// -- Calculate the sharpening --
float sharp = ori - blur_ori; //Subtracting the blurred image from the original image
// -- Adjust strength of the sharpening and clamp it--
float sharp_strength_luma_clamp = sharp_strength_luma / (2.0 * sharp_clamp); //Roll part of the clamp into the dot
float sharp_luma = clamp((sharp * sharp_strength_luma_clamp + 0.5), 0.0,1.0 ); //Calculate the luma, adjust the strength, scale up and clamp
sharp_luma = (sharp_clamp * 2.0) * sharp_luma - sharp_clamp; //scale down
// -- Combining the values to get the final sharpened pixel --
colorInput.x = colorInput.x + sharp_luma; // Add the sharpening to the input color.
return clamp(colorInput, 0.0,1.0);
}

View File

@@ -0,0 +1,246 @@
// Copyright (c) 2015-2018, bacondither
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer
// in this position and unchanged.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Adaptive sharpen - version 2018-04-14 - (requires ps >= 3.0)
// Tuned for use post resize
//!HOOK SCALED
//!BIND HOOKED
//!SAVE ASSD
//!COMPONENTS 2
//!DESC adaptive-sharpen
//--------------------------------------- Settings ------------------------------------------------
#define curve_height 1.6 // Main control of sharpening strength [>0]
// 0.3 <-> 2.0 is a reasonable range of values
// Defined values under this row are "optimal" DO NOT CHANGE IF YOU DO NOT KNOW WHAT YOU ARE DOING!
#define curveslope 0.5 // Sharpening curve slope, high edge values
#define L_overshoot 0.003 // Max light overshoot before compression [>0.001]
#define L_compr_low 0.167 // Light compression, default (0.169=~9x)
#define L_compr_high 0.334 // Light compression, surrounded by edges (0.337=~4x)
#define D_overshoot 0.009 // Max dark overshoot before compression [>0.001]
#define D_compr_low 0.250 // Dark compression, default (0.253=~6x)
#define D_compr_high 0.500 // Dark compression, surrounded by edges (0.504=~2.5x)
#define scale_lim 0.1 // Abs max change before compression (0.1=+-10%)
#define scale_cs 0.056 // Compression slope above scale_lim
#define pm_p sat(1.0/curve_height) // Power mean p-value [>0-1.0]
//-------------------------------------------------------------------------------------------------
// Soft limit
#define soft_lim(v,s) ( (exp(2.0*min(abs(v), s*24.0)/s) - 1.0)/(exp(2.0*min(abs(v), s*24.0)/s) + 1.0)*s )
// Weighted power mean
#define wpmean(a,b,c) ( pow((c*pow(abs(a), pm_p) + (1.0-c)*pow(b, pm_p)), (1.0/pm_p)) )
// Get destination pixel values
#define get(x,y) ( HOOKED_texOff(vec2(x, y)).rgb )
#define sat(x) ( clamp(x, 0.0, 1.0) )
// Colour to luma, fast approx gamma, avg of rec. 709 & 601 luma coeffs
#define CtL(RGB) ( sqrt(dot(vec3(0.2558, 0.6511, 0.0931), pow(sat(RGB), vec3(2.0)))) )
// Center pixel diff
#define mdiff(a,b,c,d,e,f,g) ( abs(luma[g]-luma[a]) + abs(luma[g]-luma[b]) \
+ abs(luma[g]-luma[c]) + abs(luma[g]-luma[d]) \
+ 0.5*(abs(luma[g]-luma[e]) + abs(luma[g]-luma[f])) )
#define b_diff(pix) ( abs(blur-c[pix]) )
vec4 hook() {
vec4 o = HOOKED_tex(HOOKED_pos);
// Get points, saturate colour data in c[0]
// [ c22 ]
// [ c24, c9, c23 ]
// [ c21, c1, c2, c3, c18 ]
// [ c19, c10, c4, c0, c5, c11, c16 ]
// [ c20, c6, c7, c8, c17 ]
// [ c15, c12, c14 ]
// [ c13 ]
vec3 c[25] = vec3[](sat(o.rgb), get(-1,-1), get( 0,-1), get( 1,-1), get(-1, 0),
get( 1, 0), get(-1, 1), get( 0, 1), get( 1, 1), get( 0,-2),
get(-2, 0), get( 2, 0), get( 0, 2), get( 0, 3), get( 1, 2),
get(-1, 2), get( 3, 0), get( 2, 1), get( 2,-1), get(-3, 0),
get(-2, 1), get(-2,-1), get( 0,-3), get( 1,-2), get(-1,-2));
// Blur, gauss 3x3
vec3 blur = (2.0 * (c[2]+c[4]+c[5]+c[7]) + (c[1]+c[3]+c[6]+c[8]) + 4.0 * c[0]) / 16.0;
// Contrast compression, center = 0.5, scaled to 1/3
float c_comp = sat(0.266666681f + 0.9*exp2(dot(blur, vec3(-7.4/3.0))));
// Edge detection
// Relative matrix weights
// [ 1 ]
// [ 4, 5, 4 ]
// [ 1, 5, 6, 5, 1 ]
// [ 4, 5, 4 ]
// [ 1 ]
float edge = length( 1.38*b_diff(0)
+ 1.15*(b_diff(2) + b_diff(4) + b_diff(5) + b_diff(7))
+ 0.92*(b_diff(1) + b_diff(3) + b_diff(6) + b_diff(8))
+ 0.23*(b_diff(9) + b_diff(10) + b_diff(11) + b_diff(12)) ) * c_comp;
// RGB to luma
float c0_Y = CtL(c[0]);
float luma[25] = float[](c0_Y, CtL(c[1]), CtL(c[2]), CtL(c[3]), CtL(c[4]), CtL(c[5]), CtL(c[6]),
CtL(c[7]), CtL(c[8]), CtL(c[9]), CtL(c[10]), CtL(c[11]), CtL(c[12]),
CtL(c[13]), CtL(c[14]), CtL(c[15]), CtL(c[16]), CtL(c[17]), CtL(c[18]),
CtL(c[19]), CtL(c[20]), CtL(c[21]), CtL(c[22]), CtL(c[23]), CtL(c[24]));
// Precalculated default squared kernel weights
const vec3 w1 = vec3(0.5, 1.0, 1.41421356237); // 0.25, 1.0, 2.0
const vec3 w2 = vec3(0.86602540378, 1.0, 0.54772255751); // 0.75, 1.0, 0.3
// Transition to a concave kernel if the center edge val is above thr
vec3 dW = pow(mix( w1, w2, smoothstep( 0.3, 0.8, edge)), vec3(2.0));
float mdiff_c0 = 0.02 + 3.0*( abs(luma[0]-luma[2]) + abs(luma[0]-luma[4])
+ abs(luma[0]-luma[5]) + abs(luma[0]-luma[7])
+ 0.25*(abs(luma[0]-luma[1]) + abs(luma[0]-luma[3])
+abs(luma[0]-luma[6]) + abs(luma[0]-luma[8])) );
// Use lower weights for pixels in a more active area relative to center pixel area
// This results in narrower and less visible overshoots around sharp edges
float weights[12] = float[](( min((mdiff_c0/mdiff(24, 21, 2, 4, 9, 10, 1)), dW.y) ),
( dW.x ),
( min((mdiff_c0/mdiff(23, 18, 5, 2, 9, 11, 3)), dW.y) ),
( dW.x ),
( dW.x ),
( min((mdiff_c0/mdiff(4, 20, 15, 7, 10, 12, 6)), dW.y) ),
( dW.x ),
( min((mdiff_c0/mdiff(5, 7, 17, 14, 12, 11, 8)), dW.y) ),
( min((mdiff_c0/mdiff(2, 24, 23, 22, 1, 3, 9)), dW.z) ),
( min((mdiff_c0/mdiff(20, 19, 21, 4, 1, 6, 10)), dW.z) ),
( min((mdiff_c0/mdiff(17, 5, 18, 16, 3, 8, 11)), dW.z) ),
( min((mdiff_c0/mdiff(13, 15, 7, 14, 6, 8, 12)), dW.z) ));
weights[0] = (max(max((weights[8] + weights[9])/4.0, weights[0]), 0.25) + weights[0])/2.0;
weights[2] = (max(max((weights[8] + weights[10])/4.0, weights[2]), 0.25) + weights[2])/2.0;
weights[5] = (max(max((weights[9] + weights[11])/4.0, weights[5]), 0.25) + weights[5])/2.0;
weights[7] = (max(max((weights[10] + weights[11])/4.0, weights[7]), 0.25) + weights[7])/2.0;
// Calculate the negative part of the laplace kernel
float weightsum = 0.0;
float neg_laplace = 0.0;
for (int pix = 0; pix < 12; ++pix)
{
neg_laplace += luma[pix+1]*weights[pix];
weightsum += weights[pix];
}
neg_laplace = neg_laplace / weightsum;
// Compute sharpening magnitude function
float sharpen_val = (curve_height/(curve_height*curveslope*pow((edge), 3.5) + 0.625));
// Calculate sharpening diff and scale
float sharpdiff = (c0_Y - neg_laplace)*(sharpen_val + 0.01);
// Calculate local near min & max, partial sort
float temp;
for (int i1 = 0; i1 < 24; i1 += 2)
{
temp = luma[i1];
luma[i1] = min(luma[i1], luma[i1+1]);
luma[i1+1] = max(temp, luma[i1+1]);
}
for (int i2 = 24; i2 > 0; i2 -= 2)
{
temp = luma[0];
luma[0] = min(luma[0], luma[i2]);
luma[i2] = max(temp, luma[i2]);
temp = luma[24];
luma[24] = max(luma[24], luma[i2-1]);
luma[i2-1] = min(temp, luma[i2-1]);
}
for (int i1 = 1; i1 < 24-1; i1 += 2)
{
temp = luma[i1];
luma[i1] = min(luma[i1], luma[i1+1]);
luma[i1+1] = max(temp, luma[i1+1]);
}
for (int i2 = 24-1; i2 > 1; i2 -= 2)
{
temp = luma[1];
luma[1] = min(luma[1], luma[i2]);
luma[i2] = max(temp, luma[i2]);
temp = luma[24-1];
luma[24-1] = max(luma[24-1], luma[i2-1]);
luma[i2-1] = min(temp, luma[i2-1]);
}
float nmax = (max(luma[23], c0_Y)*3.0 + luma[24])/4.0;
float nmin = (min(luma[1], c0_Y)*3.0 + luma[0])/4.0;
// Calculate tanh scale factors
float min_dist = min(abs(nmax - c0_Y), abs(c0_Y - nmin));
float pos_scale = min_dist + min(L_overshoot, 1.0001 - min_dist - c0_Y);
float neg_scale = min_dist + min(D_overshoot, 0.0001 + c0_Y - min_dist);
pos_scale = min(pos_scale, scale_lim*(1.0 - scale_cs) + pos_scale*scale_cs);
neg_scale = min(neg_scale, scale_lim*(1.0 - scale_cs) + neg_scale*scale_cs);
// Soft limited anti-ringing with tanh, wpmean to control compression slope
sharpdiff = wpmean(max(sharpdiff, 0.0), soft_lim( max(sharpdiff, 0.0), pos_scale ), L_compr_low )
- wpmean(min(sharpdiff, 0.0), soft_lim( min(sharpdiff, 0.0), neg_scale ), D_compr_low );
return vec4(sharpdiff, c0_Y, 0, 1);
}
//!HOOK SCALED
//!BIND HOOKED
//!BIND ASSD
//!DESC adaptive-sharpen equalization
#define video_level_out false // True to preserve BTB & WTW (minor summation error)
// Normally it should be set to false
#define SD(x,y) ASSD_texOff(vec2(x,y)).r
vec4 hook() {
vec4 o = HOOKED_texOff(0);
float sharpdiff = SD( 0, 0) - 0.6 * 0.25 * (SD(-0.5,-0.5) + SD( 0.5,-0.5) + SD(-0.5, 0.5) + SD( 0.5, 0.5));
float c0_Y = ASSD_texOff(vec2(0)).g;
float sharpdiff_lim = clamp(c0_Y + sharpdiff, 0.0, 1.0) - c0_Y;
float satmul = (c0_Y + max(sharpdiff_lim*0.9, sharpdiff_lim)*1.03 + 0.03)/(c0_Y + 0.03);
vec3 res = c0_Y + (sharpdiff_lim*3 + sharpdiff)/4 + (clamp(o.rgb, 0.0, 1.0) - c0_Y)*satmul;
o.rgb = video_level_out == true ? res + o.rgb - clamp(o.rgb, 0.0, 1.0) : res;
return o;
}

41
shaders/filmgrain.glsl Normal file
View File

@@ -0,0 +1,41 @@
//!HOOK LUMA
//!BIND HOOKED
//!DESC gaussian film grain
#normal value is 0.05 changed for demo purposes
#define INTENSITY 0.55
float permute(float x)
{
x = (34.0 * x + 1.0) * x;
return fract(x * 1.0/289.0) * 289.0;
}
float rand(inout float state)
{
state = permute(state);
return fract(state * 1.0/41.0);
}
vec4 hook()
{
vec3 m = vec3(HOOKED_pos, random) + vec3(1.0);
float state = permute(permute(m.x) + m.y) + m.z;
const float a0 = 0.151015505647689;
const float a1 = -0.5303572634357367;
const float a2 = 1.365020122861334;
const float b0 = 0.132089632343748;
const float b1 = -0.7607324991323768;
float p = 0.95 * rand(state) + 0.025;
float q = p - 0.5;
float r = q * q;
float grain = q * (a2 + (a1 * r + a0) / (r*r + b1*r + b0));
grain *= 0.255121822830526; // normalize to [-1,1)
vec4 color = HOOKED_tex(HOOKED_pos);
color.rgb += vec3(INTENSITY * grain);
return color;
}

View File

@@ -61,7 +61,7 @@ extern "C"
/// vdr-plugin version number. /// vdr-plugin version number.
/// Makefile extracts the version number for generating the file name /// Makefile extracts the version number for generating the file name
/// for the distribution archive. /// for the distribution archive.
static const char *const VERSION = "3.0.0" static const char *const VERSION = "3.3.1"
#ifdef GIT_REV #ifdef GIT_REV
"-GIT" GIT_REV "-GIT" GIT_REV
#endif #endif
@@ -106,7 +106,7 @@ static int ConfigVideoBrightness; ///< config video brightness
static int ConfigVideoContrast = 100; ///< config video contrast static int ConfigVideoContrast = 100; ///< config video contrast
static int ConfigVideoSaturation = 100; ///< config video saturation static int ConfigVideoSaturation = 100; ///< config video saturation
static int ConfigVideoHue; ///< config video hue static int ConfigVideoHue; ///< config video hue
static int ConfigGamma; ///< config Gamma static int ConfigGamma=100; ///< config Gamma
static int ConfigTargetColorSpace; ///< config Target Colrospace static int ConfigTargetColorSpace; ///< config Target Colrospace
static int ConfigScalerTest; /// Test for Scalers static int ConfigScalerTest; /// Test for Scalers
static int ConfigColorBlindness; static int ConfigColorBlindness;
@@ -136,11 +136,6 @@ static int ConfigVideoCutTopBottom[RESOLUTIONS];
/// config cut left and right pixels /// config cut left and right pixels
static int ConfigVideoCutLeftRight[RESOLUTIONS]; static int ConfigVideoCutLeftRight[RESOLUTIONS];
static int ConfigAutoCropEnabled; ///< auto crop detection enabled
static int ConfigAutoCropInterval; ///< auto crop detection interval
static int ConfigAutoCropDelay; ///< auto crop detection delay
static int ConfigAutoCropTolerance; ///< auto crop detection tolerance
static int ConfigVideoAudioDelay; ///< config audio delay static int ConfigVideoAudioDelay; ///< config audio delay
static char ConfigAudioDrift; ///< config audio drift static char ConfigAudioDrift; ///< config audio drift
static char ConfigAudioPassthrough; ///< config audio pass-through mask static char ConfigAudioPassthrough; ///< config audio pass-through mask
@@ -997,10 +992,6 @@ class cMenuSetupSoft:public cMenuSetupPage
int CutTopBottom[RESOLUTIONS]; int CutTopBottom[RESOLUTIONS];
int CutLeftRight[RESOLUTIONS]; int CutLeftRight[RESOLUTIONS];
int AutoCropInterval;
int AutoCropDelay;
int AutoCropTolerance;
int Audio; int Audio;
int AudioDelay; int AudioDelay;
int AudioDrift; int AudioDrift;
@@ -1096,10 +1087,10 @@ void cMenuSetupSoft::Create(void)
"auto", "1920x1080", "1280x720", "custom", "auto", "1920x1080", "1280x720", "custom",
}; };
static const char *const video_display_formats_4_3[] = { static const char *const video_display_formats_4_3[] = {
"pan&scan", "letterbox", "center cut-out", "pan&scan", "letterbox", "center cut-out", "original"
}; };
static const char *const video_display_formats_16_9[] = { static const char *const video_display_formats_16_9[] = {
"pan&scan", "pillarbox", "center cut-out", "pan&scan", "pillarbox", "center cut-out", "original"
}; };
#ifdef YADIF #ifdef YADIF
static const char *const deinterlace[] = { static const char *const deinterlace[] = {
@@ -1133,7 +1124,7 @@ void cMenuSetupSoft::Create(void)
static char *scalingtest[100]; static char *scalingtest[100];
if (scalers == 0) { if (scalers == 0) {
scalingtest[0] = "Off"; scalingtest[0] = (char *)"Off";
for (scalers = 0; pl_named_filters[scalers].filter != NULL; scalers++) { for (scalers = 0; pl_named_filters[scalers].filter != NULL; scalers++) {
scaling[scalers] = (char *)pl_named_filters[scalers].name; scaling[scalers] = (char *)pl_named_filters[scalers].name;
scalingtest[scalers + 1] = (char *)pl_named_filters[scalers].name; scalingtest[scalers + 1] = (char *)pl_named_filters[scalers].name;
@@ -1182,9 +1173,9 @@ void cMenuSetupSoft::Create(void)
Add(new cMenuEditBoolItem(tr("Enable Screensaver(DPMS) at black screen"), &EnableDPMSatBlackScreen, Add(new cMenuEditBoolItem(tr("Enable Screensaver(DPMS) at black screen"), &EnableDPMSatBlackScreen,
trVDR("no"), trVDR("yes"))); trVDR("no"), trVDR("yes")));
#endif #endif
Add(new cMenuEditStraItem(trVDR("4:3 video display format"), &Video4to3DisplayFormat, 3, Add(new cMenuEditStraItem(trVDR("4:3 video display format"), &Video4to3DisplayFormat, 4,
video_display_formats_4_3)); video_display_formats_4_3));
Add(new cMenuEditStraItem(trVDR("16:9+other video display format"), &VideoOtherDisplayFormat, 3, Add(new cMenuEditStraItem(trVDR("16:9+other video display format"), &VideoOtherDisplayFormat, 4,
video_display_formats_16_9)); video_display_formats_16_9));
#if 0 #if 0
@@ -1243,15 +1234,6 @@ void cMenuSetupSoft::Create(void)
Add(new cMenuEditIntItem(tr("Cut left and right (pixel)"), &CutLeftRight[i], 0, 250)); Add(new cMenuEditIntItem(tr("Cut left and right (pixel)"), &CutLeftRight[i], 0, 250));
} }
} }
#ifdef USE_AUTOCROP
//
// auto-crop
//
Add(SeparatorItem(tr("Auto-crop")));
Add(new cMenuEditIntItem(tr("Autocrop interval (frames)"), &AutoCropInterval, 0, 200, tr("off")));
Add(new cMenuEditIntItem(tr("Autocrop delay (n * interval)"), &AutoCropDelay, 0, 200));
Add(new cMenuEditIntItem(tr("Autocrop tolerance (pixel)"), &AutoCropTolerance, 0, 32));
#endif
} }
// //
// audio // audio
@@ -1261,12 +1243,15 @@ void cMenuSetupSoft::Create(void)
if (Audio) { if (Audio) {
Add(new cMenuEditIntItem(tr("Audio/Video delay (ms)"), &AudioDelay, -1000, 1000)); Add(new cMenuEditIntItem(tr("Audio/Video delay (ms)"), &AudioDelay, -1000, 1000));
Add(new cMenuEditStraItem(tr("Audio drift correction"), &AudioDrift, 4, audiodrift)); Add(new cMenuEditStraItem(tr("Audio drift correction"), &AudioDrift, 4, audiodrift));
Add(new cMenuEditBoolItem(tr("Pass-through default"), &AudioPassthroughDefault, trVDR("off"), trVDR("on"))); Add(new cMenuEditBoolItem(tr("Pass-through default"), &AudioPassthroughDefault, trVDR("off"), trVDR("on")));
Add(new cMenuEditBoolItem(tr("\040\040PCM pass-through"), &AudioPassthroughPCM, trVDR("no"), trVDR("yes"))); if (AudioPassthroughDefault) {
Add(new cMenuEditBoolItem(tr("\040\040AC-3 pass-through"), &AudioPassthroughAC3, trVDR("no"), trVDR("yes"))); Add(new cMenuEditBoolItem(tr("\040\040PCM pass-through"), &AudioPassthroughPCM, trVDR("no"), trVDR("yes")));
Add(new cMenuEditBoolItem(tr("\040\040E-AC-3 pass-through"), &AudioPassthroughEAC3, trVDR("no"), Add(new cMenuEditBoolItem(tr("\040\040AC-3 pass-through"), &AudioPassthroughAC3, trVDR("no"), trVDR("yes")));
trVDR("yes"))); Add(new cMenuEditBoolItem(tr("\040\040E-AC-3 pass-through"), &AudioPassthroughEAC3, trVDR("no"),trVDR("yes")));
Add(new cMenuEditBoolItem(tr("Enable (E-)AC-3 (decoder) downmix"), &AudioDownmix, trVDR("no"), trVDR("yes"))); } else {
Add(new cMenuEditBoolItem(tr("Enable (E-)AC-3 (decoder) downmix"), &AudioDownmix, trVDR("no"), trVDR("yes")));
}
Add(new cMenuEditBoolItem(tr("Volume control"), &AudioSoftvol, tr("Hardware"), tr("Software"))); Add(new cMenuEditBoolItem(tr("Volume control"), &AudioSoftvol, tr("Hardware"), tr("Software")));
Add(new cMenuEditBoolItem(tr("Enable normalize volume"), &AudioNormalize, trVDR("no"), trVDR("yes"))); Add(new cMenuEditBoolItem(tr("Enable normalize volume"), &AudioNormalize, trVDR("no"), trVDR("yes")));
Add(new cMenuEditIntItem(tr(" Max normalize factor (/1000)"), &AudioMaxNormalize, 0, 10000)); Add(new cMenuEditIntItem(tr(" Max normalize factor (/1000)"), &AudioMaxNormalize, 0, 10000));
@@ -1322,10 +1307,12 @@ eOSState cMenuSetupSoft::ProcessKey(eKeys key)
int old_osd_size; int old_osd_size;
int old_resolution_shown[RESOLUTIONS]; int old_resolution_shown[RESOLUTIONS];
int i; int i;
int old_pass;
old_general = General; old_general = General;
old_video = Video; old_video = Video;
old_audio = Audio; old_audio = Audio;
old_pass = AudioPassthroughDefault;
#ifdef USE_PIP #ifdef USE_PIP
old_pip = Pip; old_pip = Pip;
#endif #endif
@@ -1340,6 +1327,7 @@ eOSState cMenuSetupSoft::ProcessKey(eKeys key)
#ifdef USE_PIP #ifdef USE_PIP
|| old_pip != Pip || old_pip != Pip
#endif #endif
|| old_pass != AudioPassthroughDefault
|| old_osd_size != OsdSize) { || old_osd_size != OsdSize) {
Create(); // update menu Create(); // update menu
} else { } else {
@@ -1428,13 +1416,6 @@ cMenuSetupSoft::cMenuSetupSoft(void)
CutTopBottom[i] = ConfigVideoCutTopBottom[i]; CutTopBottom[i] = ConfigVideoCutTopBottom[i];
CutLeftRight[i] = ConfigVideoCutLeftRight[i]; CutLeftRight[i] = ConfigVideoCutLeftRight[i];
} }
//
// auto-crop
//
AutoCropInterval = ConfigAutoCropInterval;
AutoCropDelay = ConfigAutoCropDelay;
AutoCropTolerance = ConfigAutoCropTolerance;
// //
// audio // audio
// //
@@ -1591,12 +1572,6 @@ void cMenuSetupSoft::Store(void)
VideoSetCutTopBottom(ConfigVideoCutTopBottom); VideoSetCutTopBottom(ConfigVideoCutTopBottom);
VideoSetCutLeftRight(ConfigVideoCutLeftRight); VideoSetCutLeftRight(ConfigVideoCutLeftRight);
SetupStore("AutoCrop.Interval", ConfigAutoCropInterval = AutoCropInterval);
SetupStore("AutoCrop.Delay", ConfigAutoCropDelay = AutoCropDelay);
SetupStore("AutoCrop.Tolerance", ConfigAutoCropTolerance = AutoCropTolerance);
VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay, ConfigAutoCropTolerance);
ConfigAutoCropEnabled = ConfigAutoCropInterval != 0;
SetupStore("AudioDelay", ConfigVideoAudioDelay = AudioDelay); SetupStore("AudioDelay", ConfigVideoAudioDelay = AudioDelay);
VideoSetAudioDelay(ConfigVideoAudioDelay); VideoSetAudioDelay(ConfigVideoAudioDelay);
SetupStore("AudioDrift", ConfigAudioDrift = AudioDrift); SetupStore("AudioDrift", ConfigAudioDrift = AudioDrift);
@@ -2153,6 +2128,10 @@ void cSoftHdMenu::Create(void)
int dropped; int dropped;
int counter; int counter;
float frametime; float frametime;
int width, height;
int color;
int eotf;
char *colorstr, *eotfstr;
current = Current(); // get current menu item index current = Current(); // get current menu item index
Clear(); // clear the menu Clear(); // clear the menu
@@ -2187,10 +2166,31 @@ void cSoftHdMenu::Create(void)
#endif #endif
Add(new cOsdItem(NULL, osUnknown, false)); Add(new cOsdItem(NULL, osUnknown, false));
Add(new cOsdItem(NULL, osUnknown, false)); Add(new cOsdItem(NULL, osUnknown, false));
GetStats(&missed, &duped, &dropped, &counter, &frametime); GetStats(&missed, &duped, &dropped, &counter, &frametime, &width, &height, &color, &eotf);
switch (color) {
case AVCOL_SPC_RGB:
colorstr = strdup("BT 601");
eotfstr = strdup("BT 1886");
break;
case AVCOL_SPC_BT709:
case AVCOL_SPC_UNSPECIFIED: // comes with UHD
colorstr = strdup("BT 709");
eotfstr = strdup("BT 1886");
break;
case AVCOL_SPC_BT2020_NCL:
colorstr = strdup("BT 2020");
eotfstr = strdup("HDR-HLG");
break;
default: // fallback
colorstr = strdup("Fallback BT 709");
eotfstr = strdup("BT 1886");
break;
}
Add(new cOsdItem(cString::sprintf(tr(" Frames missed(%d) duped(%d) dropped(%d) total(%d)"), missed, duped, dropped, Add(new cOsdItem(cString::sprintf(tr(" Frames missed(%d) duped(%d) dropped(%d) total(%d)"), missed, duped, dropped,
counter), osUnknown, false)); counter), osUnknown, false));
Add(new cOsdItem(cString::sprintf(tr(" Frame Process time %2.2fms"), frametime), osUnknown, false)); Add(new cOsdItem(cString::sprintf(tr(" Video %dx%d Color: %s Gamma: %s"), width, height, colorstr, eotfstr),
osUnknown, false));
// Add(new cOsdItem(cString::sprintf(tr(" Frame Process time %2.2fms"), frametime), osUnknown, false));
SetCurrent(Get(current)); // restore selected menu entry SetCurrent(Get(current)); // restore selected menu entry
Display(); // display build menu Display(); // display build menu
} }
@@ -2273,33 +2273,6 @@ static void HandleHotkey(int code)
case 22: // toggle full screen case 22: // toggle full screen
VideoSetFullscreen(-1); VideoSetFullscreen(-1);
break; break;
case 23: // disable auto-crop
ConfigAutoCropEnabled = 0;
VideoSetAutoCrop(0, ConfigAutoCropDelay, ConfigAutoCropTolerance);
Skins.QueueMessage(mtInfo, tr("auto-crop disabled and freezed"));
break;
case 24: // enable auto-crop
ConfigAutoCropEnabled = 1;
if (!ConfigAutoCropInterval) {
ConfigAutoCropInterval = 50;
}
VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay, ConfigAutoCropTolerance);
Skins.QueueMessage(mtInfo, tr("auto-crop enabled"));
break;
case 25: // toggle auto-crop
ConfigAutoCropEnabled ^= 1;
// no interval configured, use some default
if (!ConfigAutoCropInterval) {
ConfigAutoCropInterval = 50;
}
VideoSetAutoCrop(ConfigAutoCropEnabled * ConfigAutoCropInterval, ConfigAutoCropDelay,
ConfigAutoCropTolerance);
if (ConfigAutoCropEnabled) {
Skins.QueueMessage(mtInfo, tr("auto-crop enabled"));
} else {
Skins.QueueMessage(mtInfo, tr("auto-crop disabled and freezed"));
}
break;
case 30: // change 4:3 -> window mode case 30: // change 4:3 -> window mode
case 31: case 31:
case 32: case 32:
@@ -3098,7 +3071,11 @@ bool cPluginSoftHdDevice::ProcessArgs(int argc, char *argv[])
bool cPluginSoftHdDevice::Initialize(void) bool cPluginSoftHdDevice::Initialize(void)
{ {
// dsyslog("[softhddev]%s:\n", __FUNCTION__); // dsyslog("[softhddev]%s:\n", __FUNCTION__);
#if defined PLACEBO
const char *d;
d = cPlugin::ConfigDirectory("shaders");
strcpy(MyConfigDir,d);
#endif
MyDevice = new cSoftHdDevice(); MyDevice = new cSoftHdDevice();
return true; return true;
@@ -3269,7 +3246,6 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
ConfigSuspendX11 = atoi(value); ConfigSuspendX11 = atoi(value);
return true; return true;
} }
if (!strcasecmp(name, "Video4to3DisplayFormat")) { if (!strcasecmp(name, "Video4to3DisplayFormat")) {
Config4to3DisplayFormat = atoi(value); Config4to3DisplayFormat = atoi(value);
VideoSet4to3DisplayFormat(Config4to3DisplayFormat); VideoSet4to3DisplayFormat(Config4to3DisplayFormat);
@@ -3412,20 +3388,6 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
} }
} }
if (!strcasecmp(name, "AutoCrop.Interval")) {
VideoSetAutoCrop(ConfigAutoCropInterval = atoi(value), ConfigAutoCropDelay, ConfigAutoCropTolerance);
ConfigAutoCropEnabled = ConfigAutoCropInterval != 0;
return true;
}
if (!strcasecmp(name, "AutoCrop.Delay")) {
VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay = atoi(value), ConfigAutoCropTolerance);
return true;
}
if (!strcasecmp(name, "AutoCrop.Tolerance")) {
VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay, ConfigAutoCropTolerance = atoi(value));
return true;
}
if (!strcasecmp(name, "AudioDelay")) { if (!strcasecmp(name, "AudioDelay")) {
VideoSetAudioDelay(ConfigVideoAudioDelay = atoi(value)); VideoSetAudioDelay(ConfigVideoAudioDelay = atoi(value));
return true; return true;
@@ -3435,11 +3397,11 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
return true; return true;
} }
if (!strcasecmp(name, "AudioPassthrough")) { if (!strcasecmp(name, "AudioPassthrough")) {
int i; int ii;
i = atoi(value); ii = atoi(value);
AudioPassthroughState = i > 0; AudioPassthroughState = ii > 0;
ConfigAudioPassthrough = abs(i); ConfigAudioPassthrough = abs(ii);
if (AudioPassthroughState) { if (AudioPassthroughState) {
CodecSetAudioPassthrough(ConfigAudioPassthrough); CodecSetAudioPassthrough(ConfigAudioPassthrough);
} else { } else {
@@ -3681,7 +3643,6 @@ static const char *SVDRPHelpText[] = {
" 12: toggle audio pass-through\n" " 13: decrease audio delay by 10ms\n" " 12: toggle audio pass-through\n" " 13: decrease audio delay by 10ms\n"
" 14: increase audio delay by 10ms\n" " 15: toggle ac3 mixdown\n" " 14: increase audio delay by 10ms\n" " 15: toggle ac3 mixdown\n"
" 20: disable fullscreen\n\040 21: enable fullscreen\n" " 22: toggle fullscreen\n" " 20: disable fullscreen\n\040 21: enable fullscreen\n" " 22: toggle fullscreen\n"
" 23: disable auto-crop\n\040 24: enable auto-crop\n" " 25: toggle auto-crop\n"
" 30: stretch 4:3 to display\n\040 31: pillar box 4:3 in display\n" " 30: stretch 4:3 to display\n\040 31: pillar box 4:3 in display\n"
" 32: center cut-out 4:3 to display\n" " 39: rotate 4:3 to display zoom mode\n" " 32: center cut-out 4:3 to display\n" " 39: rotate 4:3 to display zoom mode\n"
" 40: stretch other aspect ratios to display\n" " 41: letter box other aspect ratios in display\n" " 40: stretch other aspect ratios to display\n" " 41: letter box other aspect ratios in display\n"

View File

@@ -645,7 +645,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size, int is_st
q = pesdx->Buffer + pesdx->Skip; q = pesdx->Buffer + pesdx->Skip;
n = pesdx->Index - pesdx->Skip; n = pesdx->Index - pesdx->Skip;
while (n >= 5) { while (n >= 5) {
int r; int r = 0;
unsigned codec_id = AV_CODEC_ID_NONE; unsigned codec_id = AV_CODEC_ID_NONE;
// 4 bytes 0xFFExxxxx Mpeg audio // 4 bytes 0xFFExxxxx Mpeg audio
@@ -655,8 +655,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size, int is_st
// 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio // 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio
// PCM audio can't be found // PCM audio can't be found
// FIXME: simple+faster detection, if codec already known // FIXME: simple+faster detection, if codec already known
r = 0; if (FastMpegCheck(q)) {
if (!r && FastMpegCheck(q)) {
r = MpegCheck(q, n); r = MpegCheck(q, n);
codec_id = AV_CODEC_ID_MP2; codec_id = AV_CODEC_ID_MP2;
} }
@@ -1327,6 +1326,7 @@ static VideoStream MyVideoStream[1]; ///< normal video stream
#ifdef USE_PIP #ifdef USE_PIP
static VideoStream PipVideoStream[1]; ///< pip video stream static VideoStream PipVideoStream[1]; ///< pip video stream
static int PiPActive = 0, mwx, mwy, mww, mwh; ///< main window frame for PiP
#endif #endif
#ifdef DEBUG #ifdef DEBUG
@@ -1490,7 +1490,7 @@ static void VideoNextPacket(VideoStream * stream, int codec_id)
VideoResetPacket(stream); VideoResetPacket(stream);
} }
#ifdef USE_PIP #if defined(USE_PIP) || defined(VAAPI)
/** /**
** Place mpeg video data in packet ringbuffer. ** Place mpeg video data in packet ringbuffer.
@@ -1832,7 +1832,7 @@ int VideoPollInput(VideoStream * stream)
** @retval 1 stream paused ** @retval 1 stream paused
** @retval -1 empty stream ** @retval -1 empty stream
*/ */
int VideoDecodeInput(VideoStream * stream) int VideoDecodeInput(VideoStream * stream, int trick)
{ {
int filled; int filled;
AVPacket *avpkt; AVPacket *avpkt;
@@ -1850,6 +1850,9 @@ int VideoDecodeInput(VideoStream * stream)
stream->Close = 0; stream->Close = 0;
return 1; return 1;
} }
if (stream->ClearBuffers && trick)
stream->ClearBuffers = 0;
if (stream->ClearBuffers) { // clear buffer request if (stream->ClearBuffers) { // clear buffer request
atomic_set(&stream->PacketsFilled, 0); atomic_set(&stream->PacketsFilled, 0);
stream->PacketRead = stream->PacketWrite; stream->PacketRead = stream->PacketWrite;
@@ -1940,7 +1943,7 @@ int VideoDecodeInput(VideoStream * stream)
avpkt->size = avpkt->stream_index; avpkt->size = avpkt->stream_index;
avpkt->stream_index = 0; avpkt->stream_index = 0;
#ifdef USE_PIP #if defined(USE_PIP) || defined(VAAPI)
// fprintf(stderr, "["); // fprintf(stderr, "[");
// DumpMpeg(avpkt->data, avpkt->size); // DumpMpeg(avpkt->data, avpkt->size);
#ifdef STILL_DEBUG #ifdef STILL_DEBUG
@@ -2302,7 +2305,7 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
} }
// SKIP PES header, begin of start code // SKIP PES header, begin of start code
#ifdef USE_PIP #if defined(USE_PIP) || defined(VAAPI)
VideoMpegEnqueue(stream, pts, dts, check - 2, l + 2); VideoMpegEnqueue(stream, pts, dts, check - 2, l + 2);
#else #else
VideoEnqueue(stream, pts, dts, check - 2, l + 2); VideoEnqueue(stream, pts, dts, check - 2, l + 2);
@@ -2315,7 +2318,7 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
return size; return size;
} }
#ifdef USE_PIP #if defined(USE_PIP) || defined(VAAPI)
if (stream->CodecID == AV_CODEC_ID_MPEG2VIDEO) { if (stream->CodecID == AV_CODEC_ID_MPEG2VIDEO) {
// SKIP PES header // SKIP PES header
VideoMpegEnqueue(stream, pts, dts, data + 9 + n, size - 9 - n); VideoMpegEnqueue(stream, pts, dts, data + 9 + n, size - 9 - n);
@@ -2676,12 +2679,14 @@ void StillPicture(const uint8_t * data, int size)
#ifdef STILL_DEBUG #ifdef STILL_DEBUG
fprintf(stderr, "still-picture\n"); fprintf(stderr, "still-picture\n");
#endif #endif
for (i = 0; i < (MyVideoStream->CodecID == AV_CODEC_ID_HEVC ? 12 : 12); ++i) { for (i = 0; i < (MyVideoStream->CodecID == AV_CODEC_ID_HEVC ? 12 : 12); ++i) {
const uint8_t *split; const uint8_t *split;
int n; int n;
// FIXME: vdr pes recordings sends mixed audio/video // FIXME: vdr pes recordings sends mixed audio/video
if ((data[3] & 0xF0) == 0xE0) { // PES packet if ((data[3] & 0xF0) == 0xE0) { // PES packet
split = data; split = data;
n = size; n = size;
// split the I-frame into single pes packets // split the I-frame into single pes packets
@@ -2715,7 +2720,7 @@ void StillPicture(const uint8_t * data, int size)
VideoNextPacket(MyVideoStream, MyVideoStream->CodecID); // terminate last packet VideoNextPacket(MyVideoStream, MyVideoStream->CodecID); // terminate last packet
} else { // ES packet } else { // ES packet
if (MyVideoStream->CodecID != AV_CODEC_ID_MPEG2VIDEO) { if (0 && MyVideoStream->CodecID != AV_CODEC_ID_MPEG2VIDEO) {
VideoNextPacket(MyVideoStream, AV_CODEC_ID_NONE); // close last stream VideoNextPacket(MyVideoStream, AV_CODEC_ID_NONE); // close last stream
MyVideoStream->CodecID = AV_CODEC_ID_MPEG2VIDEO; MyVideoStream->CodecID = AV_CODEC_ID_MPEG2VIDEO;
} }
@@ -2872,11 +2877,11 @@ const char *CommandLineHelp(void)
" -p device\taudio device for pass-through (hw:0,1 or /dev/dsp1)\n" " -p device\taudio device for pass-through (hw:0,1 or /dev/dsp1)\n"
" -c channel\taudio mixer channel name (fe. PCM)\n" " -d display\tdisplay of x11 server (fe. :0.0)\n" " -c channel\taudio mixer channel name (fe. PCM)\n" " -d display\tdisplay of x11 server (fe. :0.0)\n"
" -f\t\tstart with fullscreen window (only with window manager)\n" " -f\t\tstart with fullscreen window (only with window manager)\n"
" -g geometry\tx11 window geometry wxh+x+y\n" " -g geometry\tx11 window geometry wxh+x+y\n" " -r Refresh\tRefreshrate for DRM (default is 50 Hz)\n"
" -r Refresh\tRefreshrate for DRM (default is 50 Hz)\n" " -C Connector\tConnector for DRM (default is current Connector)\n"
" -C Connector\tConnector for DRM (default is current Connector)\n" " -S shader\tShader to use.\n\t\tOnly with placebo. Can be repeated for more shaders\n"
" -v device\tvideo driver device (cuvid)\n" " -v device\tvideo driver device (cuvid)\n" " -s\t\tstart in suspended mode\n"
" -s\t\tstart in suspended mode\n" " -x\t\tstart x11 server, with -xx try to connect, if this fails\n" " -x\t\tstart x11 server, with -xx try to connect, if this fails\n"
" -X args\tX11 server arguments (f.e. -nocursor)\n" " -w workaround\tenable/disable workarounds\n" " -X args\tX11 server arguments (f.e. -nocursor)\n" " -w workaround\tenable/disable workarounds\n"
"\tno-hw-decoder\t\tdisable hw decoder, use software decoder only\n" "\tno-hw-decoder\t\tdisable hw decoder, use software decoder only\n"
"\tno-mpeg-hw-decoder\tdisable hw decoder for mpeg only\n" "\tno-mpeg-hw-decoder\tdisable hw decoder for mpeg only\n"
@@ -2908,7 +2913,7 @@ int ProcessArgs(int argc, char *const argv[])
#endif #endif
for (;;) { for (;;) {
switch (getopt(argc, argv, "-a:c:C:r:d:fg:p:sv:w:xDX:")) { switch (getopt(argc, argv, "-a:c:C:r:d:fg:p:S:sv:w:xDX:")) {
case 'a': // audio device for pcm case 'a': // audio device for pcm
AudioSetDevice(optarg); AudioSetDevice(optarg);
continue; continue;
@@ -2917,10 +2922,16 @@ int ProcessArgs(int argc, char *const argv[])
continue; continue;
case 'C': // Connector for DRM case 'C': // Connector for DRM
VideoSetConnector(optarg); VideoSetConnector(optarg);
continue; continue;
case 'r': // Connector for DRM case 'r': // Connector for DRM
VideoSetRefresh(optarg); VideoSetRefresh(optarg);
continue; continue;
case 'S': // Shader
if (VideoSetShader(optarg) < 0) {
fprintf(stderr,_("Too much shaders definded\n"));
return 0;
}
continue;
case 'p': // pass-through audio device case 'p': // pass-through audio device
AudioSetPassthroughDevice(optarg); AudioSetPassthroughDevice(optarg);
continue; continue;
@@ -3370,15 +3381,21 @@ void Resume(void)
** @param[out] dropped dropped frames ** @param[out] dropped dropped frames
** @param[out] count number of decoded frames ** @param[out] count number of decoded frames
*/ */
void GetStats(int *missed, int *duped, int *dropped, int *counter, float *frametime) void GetStats(int *missed, int *duped, int *dropped, int *counter, float *frametime, int *width, int *height,
int *color, int *eotf)
{ {
*missed = 0; *missed = 0;
*duped = 0; *duped = 0;
*dropped = 0; *dropped = 0;
*counter = 0; *counter = 0;
*frametime = 0.0f; *frametime = 0.0f;
*width = 0;
*height = 0;
*color = NULL;
*eotf = NULL;
if (MyVideoStream->HwDecoder) { if (MyVideoStream->HwDecoder) {
VideoGetStats(MyVideoStream->HwDecoder, missed, duped, dropped, counter, frametime); VideoGetStats(MyVideoStream->HwDecoder, missed, duped, dropped, counter, frametime, width, height, color,
eotf);
} }
} }
@@ -3392,6 +3409,12 @@ void GetStats(int *missed, int *duped, int *dropped, int *counter, float *framet
*/ */
void ScaleVideo(int x, int y, int width, int height) void ScaleVideo(int x, int y, int width, int height)
{ {
#ifdef USE_PIP
if (PiPActive && !(x & y & width & height)) {
Info("[softhddev]%s: fullscreen with PiP active.\n", __FUNCTION__);
x = mwx; y = mwy; width = mww; height = mwh;
}
#endif
if (MyVideoStream->HwDecoder) { if (MyVideoStream->HwDecoder) {
VideoSetOutputPosition(MyVideoStream->HwDecoder, x, y, width, height); VideoSetOutputPosition(MyVideoStream->HwDecoder, x, y, width, height);
} }
@@ -3450,6 +3473,8 @@ void PipStart(int x, int y, int width, int height, int pip_x, int pip_y, int pip
VideoStreamOpen(PipVideoStream); VideoStreamOpen(PipVideoStream);
} }
PipSetPosition(x, y, width, height, pip_x, pip_y, pip_width, pip_height); PipSetPosition(x, y, width, height, pip_x, pip_y, pip_width, pip_height);
mwx = x; mwy = y; mww = width; mwh = height;
PiPActive = 1;
} }
/** /**
@@ -3463,6 +3488,8 @@ void PipStop(void)
return; return;
} }
PiPActive = 0;
mwx = 0; mwy = 0; mww = 0; mwh = 0;
ScaleVideo(0, 0, 0, 0); ScaleVideo(0, 0, 0, 0);
PipVideoStream->Close = 1; PipVideoStream->Close = 1;

View File

@@ -96,7 +96,7 @@ extern "C"
extern void Resume(void); extern void Resume(void);
/// Get decoder statistics /// Get decoder statistics
extern void GetStats(int *, int *, int *, int *, float *); extern void GetStats(int *, int *, int *, int *, float *, int *, int *, int *, int *);
/// C plugin scale video /// C plugin scale video
extern void ScaleVideo(int, int, int, int); extern void ScaleVideo(int, int, int, int);

1462
video.c

File diff suppressed because it is too large Load Diff

20
video.h
View File

@@ -44,7 +44,7 @@ extern signed char VideoHardwareDecoder; ///< flag use hardware decoder
extern char VideoIgnoreRepeatPict; ///< disable repeat pict warning extern char VideoIgnoreRepeatPict; ///< disable repeat pict warning
extern int VideoAudioDelay; ///< audio/video delay extern int VideoAudioDelay; ///< audio/video delay
extern char ConfigStartX11Server; ///< flag start the x11 server extern char ConfigStartX11Server; ///< flag start the x11 server
extern char MyConfigDir[];
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Prototypes // Prototypes
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -179,9 +179,6 @@ extern void VideoSetBackground(uint32_t);
/// Set audio delay. /// Set audio delay.
extern void VideoSetAudioDelay(int); extern void VideoSetAudioDelay(int);
/// Set auto-crop parameters.
extern void VideoSetAutoCrop(int, int, int);
/// Clear OSD. /// Clear OSD.
extern void VideoOsdClear(void); extern void VideoOsdClear(void);
@@ -219,7 +216,7 @@ extern uint8_t *VideoGrab(int *, int *, int *, int);
extern uint8_t *VideoGrabService(int *, int *, int *); extern uint8_t *VideoGrabService(int *, int *, int *);
/// Get decoder statistics. /// Get decoder statistics.
extern void VideoGetStats(VideoHwDecoder *, int *, int *, int *, int *, float *); extern void VideoGetStats(VideoHwDecoder *, int *, int *, int *, int *, float *, int *, int *, int *, int *);
/// Get video stream size /// Get video stream size
extern void VideoGetVideoSize(VideoHwDecoder *, int *, int *, int *, int *); extern void VideoGetVideoSize(VideoHwDecoder *, int *, int *, int *, int *);
@@ -234,7 +231,7 @@ extern void VideoExit(void); ///< Cleanup and exit video module.
extern int VideoPollInput(VideoStream *); extern int VideoPollInput(VideoStream *);
/// Decode video input buffers. /// Decode video input buffers.
extern int VideoDecodeInput(VideoStream *); extern int VideoDecodeInput(VideoStream *, int);
/// Get number of input buffers. /// Get number of input buffers.
extern int VideoGetBuffers(const VideoStream *); extern int VideoGetBuffers(const VideoStream *);
@@ -245,9 +242,20 @@ extern void SetDPMSatBlackScreen(int);
/// Raise the frontend window /// Raise the frontend window
extern int VideoRaiseWindow(void); extern int VideoRaiseWindow(void);
/// Set Shaders
extern int VideoSetShader(char *);
#ifdef USE_OPENGLOSD #ifdef USE_OPENGLOSD
extern void ActivateOsd(GLuint, int, int, int, int); extern void ActivateOsd(GLuint, int, int, int, int);
#endif #endif
#ifdef GAMMA
extern void Init_Gamma();
extern void Exit_Gamma();
extern void Set_Gamma(float, int);
extern void Get_Gamma();
#endif
#if 0 #if 0
long int gettid() long int gettid()
{ {