1
0
mirror of https://github.com/jojo61/vdr-plugin-softhdcuvid.git synced 2023-10-10 13:37:41 +02:00

Support for mpv user shaders with libplacebo

This commit is contained in:
jojo61 2020-06-07 12:31:18 +02:00
parent c7c4cb06a6
commit 03b770ce47
7 changed files with 211 additions and 29 deletions

View File

@ -648,7 +648,7 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
void CodecVideoFlushBuffers(VideoDecoder * decoder) void CodecVideoFlushBuffers(VideoDecoder * decoder)
{ {
if (decoder->VideoCtx) { if (decoder->VideoCtx) {
avcodec_flush_buffers(decoder->VideoCtx); // avcodec_flush_buffers(decoder->VideoCtx);
} }
} }

View File

@ -397,8 +397,11 @@ void cOglFont::Cleanup(void)
delete fonts; delete fonts;
fonts = 0; fonts = 0;
if (FT_Done_FreeType(ftLib)) if (ftLib) {
esyslog("failed to deinitialize FreeType library!"); if (FT_Done_FreeType(ftLib))
esyslog("failed to deinitialize FreeType library!");
}
ftLib = 0;
} }
cOglGlyph *cOglFont::Glyph(FT_ULong charCode) const cOglGlyph *cOglFont::Glyph(FT_ULong charCode) const

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.1.1" static const char *const VERSION = "3.2.0"
#ifdef GIT_REV #ifdef GIT_REV
"-GIT" GIT_REV "-GIT" GIT_REV
#endif #endif
@ -112,6 +112,7 @@ static int ConfigScalerTest; /// Test for Scalers
static int ConfigColorBlindness; static int ConfigColorBlindness;
static int ConfigColorBlindnessFaktor; static int ConfigColorBlindnessFaktor;
/// config deinterlace /// config deinterlace
static int ConfigVideoDeinterlace[RESOLUTIONS]; static int ConfigVideoDeinterlace[RESOLUTIONS];
@ -3065,7 +3066,9 @@ 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
MyConfigDir = cPlugin::ConfigDirectory("shaders");
#endif
MyDevice = new cSoftHdDevice(); MyDevice = new cSoftHdDevice();
return true; return true;

View File

@ -2874,6 +2874,7 @@ const char *CommandLineHelp(void)
" -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" " -r Refresh\tRefreshrate for DRM (default is 50 Hz)\n" " -g geometry\tx11 window geometry wxh+x+y\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" " -s\t\tstart in suspended mode\n" " -v device\tvideo driver device (cuvid)\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"
@ -2907,7 +2908,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;
@ -2919,6 +2920,12 @@ int ProcessArgs(int argc, char *const argv[])
continue; continue;
case 'r': // Connector for DRM case 'r': // Connector for DRM
VideoSetRefresh(optarg); VideoSetRefresh(optarg);
continue;
case 'S': // Shader
if (VideoSetShader(optarg) < 0) {
fprintf(stderr,_("Too much shaders definded\n"));
return 0;
}
continue; continue;
case 'p': // pass-through audio device case 'p': // pass-through audio device
AudioSetPassthroughDevice(optarg); AudioSetPassthroughDevice(optarg);

149
video.c
View File

@ -332,6 +332,8 @@ typedef struct
#define VIDEO_SURFACES_MAX 6 ///< video output surfaces for queue #define VIDEO_SURFACES_MAX 6 ///< video output surfaces for queue
#define NUM_SHADERS 5 // Number of supported user shaders with placebo
#if defined VAAPI && !defined RASPI #if defined VAAPI && !defined RASPI
#define PIXEL_FORMAT AV_PIX_FMT_VAAPI #define PIXEL_FORMAT AV_PIX_FMT_VAAPI
#define SWAP_BUFFER_SIZE 3 #define SWAP_BUFFER_SIZE 3
@ -445,6 +447,10 @@ static int VideoScalerTest = 0;
static int VideoColorBlindness = 0; static int VideoColorBlindness = 0;
static float VideoColorBlindnessFaktor = 1.0f; static float VideoColorBlindnessFaktor = 1.0f;
static char* shadersp[NUM_SHADERS];
const char *MyConfigDir;
static int num_shaders = 0;
static xcb_atom_t WmDeleteWindowAtom; ///< WM delete message atom static xcb_atom_t WmDeleteWindowAtom; ///< WM delete message atom
static xcb_atom_t NetWmState; ///< wm-state message atom static xcb_atom_t NetWmState; ///< wm-state message atom
static xcb_atom_t NetWmStateFullscreen; ///< fullscreen wm-state message atom static xcb_atom_t NetWmStateFullscreen; ///< fullscreen wm-state message atom
@ -1409,7 +1415,12 @@ typedef struct priv
#ifdef PLACEBO_GL #ifdef PLACEBO_GL
struct pl_opengl *gl; struct pl_opengl *gl;
#endif #endif
#if PL_API_VER >= 58
const struct pl_hook *hook[NUM_SHADERS];
int num_shaders;
#endif
} priv; } priv;
static priv *p; static priv *p;
static struct pl_overlay osdoverlay; static struct pl_overlay osdoverlay;
@ -1535,6 +1546,7 @@ static void CuvidDestroySurfaces(CuvidDecoder * decoder)
Debug(3, "video/cuvid: %s\n", __FUNCTION__); Debug(3, "video/cuvid: %s\n", __FUNCTION__);
#ifndef PLACEBO #ifndef PLACEBO
#ifdef CUVID #ifdef CUVID
glXMakeCurrent(XlibDisplay, VideoWindow, glxSharedContext); glXMakeCurrent(XlibDisplay, VideoWindow, glxSharedContext);
@ -1544,6 +1556,11 @@ static void CuvidDestroySurfaces(CuvidDecoder * decoder)
EglCheck(); EglCheck();
#endif #endif
#endif #endif
#if defined PLACEBO && API_VER >= 58
p->num_shaders = 0;
#endif
for (i = 0; i < decoder->SurfacesNeeded; i++) { for (i = 0; i < decoder->SurfacesNeeded; i++) {
if (decoder->frames[i]) { if (decoder->frames[i]) {
av_frame_free(&decoder->frames[i]); av_frame_free(&decoder->frames[i]);
@ -1575,9 +1592,12 @@ static void CuvidDestroySurfaces(CuvidDecoder * decoder)
#endif #endif
} }
} }
#ifdef PLACEBO #ifdef PLACEBO
pl_renderer_destroy(&p->renderer);
p->renderer = pl_renderer_create(p->ctx, p->gpu); // pl_renderer_destroy(&p->renderer);
// p->renderer = pl_renderer_create(p->ctx, p->gpu);
#else #else
glDeleteTextures(CODEC_SURFACES_MAX * 2, (GLuint *) & decoder->gl_textures); glDeleteTextures(CODEC_SURFACES_MAX * 2, (GLuint *) & decoder->gl_textures);
GlxCheck(); GlxCheck();
@ -1601,6 +1621,7 @@ static void CuvidDestroySurfaces(CuvidDecoder * decoder)
decoder->SurfaceFreeN = 0; decoder->SurfaceFreeN = 0;
decoder->SurfaceUsedN = 0; decoder->SurfaceUsedN = 0;
} }
/// ///
@ -2238,6 +2259,7 @@ void createTextureDst(CuvidDecoder * decoder, int anz, unsigned int size_x, unsi
.export_handle = PL_HANDLE_FD, .export_handle = PL_HANDLE_FD,
}); });
} }
// make planes for image // make planes for image
pl = &decoder->pl_images[i].planes[n]; pl = &decoder->pl_images[i].planes[n];
pl->components = n == 0 ? 1 : 2; pl->components = n == 0 ? 1 : 2;
@ -3544,6 +3566,55 @@ static void CuvidAdvanceDecoderFrame(CuvidDecoder * decoder)
decoder->SurfaceField = 1; decoder->SurfaceField = 1;
} }
#if defined PLACEBO && PL_API_VER >= 58
static const struct pl_hook *
parse_user_shader(char *shader)
{
char tmp[200];
if (!shader )
return NULL;
const struct pl_hook *hook = NULL;
char *str = NULL;
// Debug(3,"Parse user shader %s/%s\n",MyConfigDir,shader);
sprintf(tmp,"%s/%s",MyConfigDir,shader);
FILE *f = fopen(tmp, "rb");
if (!f) {
Debug(3, "Failed to open shader file %s: %s\n", shader, strerror(errno));
goto error;
}
int ret = fseek(f, 0, SEEK_END);
if (ret == -1)
goto error;
long length = ftell(f);
if (length == -1)
goto error;
rewind(f);
str = malloc(length);
if (!str)
goto error;
ret = fread(str, length, 1, f);
if (ret != 1)
goto error;
hook = pl_mpv_user_shader_parse(p->gpu, str, length);
// fall through
Debug(3,"User shader %p\n",hook);
error:
if (f)
fclose(f);
free(str);
return hook;
}
#endif
/// ///
/// Render video surface to output surface. /// Render video surface to output surface.
/// ///
@ -3733,6 +3804,7 @@ static void CuvidMixVideo(CuvidDecoder * decoder, __attribute__((unused))
target->dst_rect.x1 = dst_video_rect.x1; target->dst_rect.x1 = dst_video_rect.x1;
target->dst_rect.y1 = dst_video_rect.y1; target->dst_rect.y1 = dst_video_rect.y1;
} }
if (level == 0) if (level == 0)
pl_tex_clear(p->gpu, target->fbo, (float[4]) { 0 } pl_tex_clear(p->gpu, target->fbo, (float[4]) { 0 }
); );
@ -3782,12 +3854,37 @@ static void CuvidMixVideo(CuvidDecoder * decoder, __attribute__((unused))
target->num_overlays = 0; target->num_overlays = 0;
} }
#if PL_API_VER >= 58
if (decoder->newchannel == 1 && !level) { // got new textures
p->num_shaders = 0;
for (int i=NUM_SHADERS-1;i>=0;i--) { // Remove shaders in invers order
if (p->hook[i]) {
pl_mpv_user_shader_destroy(&p->hook[i]);
p->hook[i] = NULL;
Debug(3,"remove shader %d\n",i);
}
}
for (int i = 0;i<num_shaders;i++) {
if (p->hook[i] == NULL && shadersp[i]) {
p->hook[i] = parse_user_shader(shadersp[i]);
if (!p->hook[i])
shadersp[i]= 0;
else
p->num_shaders++;
}
}
}
render_params.hooks = &p->hook;
render_params.num_hooks = p->num_shaders;
#endif
if (decoder->newchannel && current == 0) { if (decoder->newchannel && current == 0) {
colors.brightness = -1.0f; colors.brightness = -1.0f;
colors.contrast = 0.0f; colors.contrast = 0.0f;
if (!pl_render_image(p->renderer, &decoder->pl_images[current], target, &render_params)) { if (!pl_render_image(p->renderer, &decoder->pl_images[current], target, &render_params)) {
Debug(3, "Failed rendering frame!\n"); Debug(3, "Failed rendering first frame!\n");
} }
decoder->newchannel = 2;
return; return;
} }
@ -3905,6 +4002,7 @@ static void CuvidDisplayFrame(void)
struct pl_render_target target; struct pl_render_target target;
bool ok; bool ok;
const struct pl_fmt *fmt; const struct pl_fmt *fmt;
const float black[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; const float black[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
#endif #endif
@ -3961,11 +4059,13 @@ static void CuvidDisplayFrame(void)
#ifdef CUVID #ifdef CUVID
VideoThreadLock(); VideoThreadLock();
#if 0
if (!first) { if (!first) {
if (!pl_swapchain_submit_frame(p->swapchain)) if (!pl_swapchain_submit_frame(p->swapchain))
Error(_("Failed to submit swapchain buffer\n")); Error(_("Failed to submit swapchain buffer\n"));
pl_swapchain_swap_buffers(p->swapchain); // swap buffers pl_swapchain_swap_buffers(p->swapchain); // swap buffers
} }
#endif
#endif #endif
first = 0; first = 0;
@ -4154,13 +4254,13 @@ static void CuvidDisplayFrame(void)
#endif #endif
#ifdef PLACEBO #ifdef PLACEBO
#ifdef VAAPI //#ifdef VAAPI
// first_time = GetusTicks(); // first_time = GetusTicks();
if (!pl_swapchain_submit_frame(p->swapchain)) if (!pl_swapchain_submit_frame(p->swapchain))
Fatal(_("Failed to submit swapchain buffer\n")); Fatal(_("Failed to submit swapchain buffer\n"));
pl_swapchain_swap_buffers(p->swapchain); // swap buffers pl_swapchain_swap_buffers(p->swapchain); // swap buffers
#endif //#endif
VideoThreadUnlock(); VideoThreadUnlock();
#else // not PLACEBO #else // not PLACEBO
#ifdef CUVID #ifdef CUVID
@ -5356,9 +5456,11 @@ void exit_display()
#ifdef PLACEBO #ifdef PLACEBO
Debug(3, "delete placebo\n"); Debug(3, "delete placebo\n");
if (p == NULL) if (p == NULL) {
Debug(3,"Placebo not initialised\n");
return; return;
}
pl_gpu_finish(p->gpu);
if (osdoverlay.plane.texture) if (osdoverlay.plane.texture)
pl_tex_destroy(p->gpu, &osdoverlay.plane.texture); pl_tex_destroy(p->gpu, &osdoverlay.plane.texture);
@ -5367,20 +5469,22 @@ void exit_display()
pl_renderer_destroy(&p->renderertest); pl_renderer_destroy(&p->renderertest);
p->renderertest = NULL; p->renderertest = NULL;
} }
pl_swapchain_destroy(&p->swapchain); pl_swapchain_destroy(&p->swapchain);
#ifdef PLACEBO_GL #ifdef PLACEBO_GL
pl_opengl_destroy(&p->gl); pl_opengl_destroy(&p->gl);
#else #else
// pl_vulkan_destroy(&p->vk); // pl_vulkan_destroy(&p->vk);
vkDestroySurfaceKHR(p->vk_inst->instance, p->pSurface, NULL); vkDestroySurfaceKHR(p->vk_inst->instance, p->pSurface, NULL);
pl_vk_inst_destroy(&p->vk_inst); pl_vk_inst_destroy(&p->vk_inst);
#endif #endif
pl_context_destroy(&p->ctx); pl_context_destroy(&p->ctx);
free(p); free(p);
p = NULL; p = NULL;
#endif #endif
#ifdef CUVID #ifdef CUVID
if (glxThreadContext) { if (glxThreadContext) {
glXDestroyContext(XlibDisplay, glxThreadContext); glXDestroyContext(XlibDisplay, glxThreadContext);
@ -5395,7 +5499,6 @@ void exit_display()
} }
#endif #endif
Debug(3, "display thread exit\n"); Debug(3, "display thread exit\n");
} }
static void *VideoHandlerThread(void *dummy) static void *VideoHandlerThread(void *dummy)
@ -5434,7 +5537,7 @@ static void *VideoHandlerThread(void *dummy)
#endif #endif
pthread_cleanup_push(exit_display, NULL); pthread_cleanup_push(exit_display, NULL);
for (;;) { while (1) {
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_testcancel(); pthread_testcancel();
@ -5446,7 +5549,6 @@ static void *VideoHandlerThread(void *dummy)
CuvidSyncDisplayFrame(); CuvidSyncDisplayFrame();
// printf("syncdisplayframe exec %d\n",(GetusTicks()-first_time)/1000); // printf("syncdisplayframe exec %d\n",(GetusTicks()-first_time)/1000);
} }
pthread_cleanup_pop(NULL); pthread_cleanup_pop(NULL);
return dummy; return dummy;
@ -5465,6 +5567,7 @@ static void VideoThreadInit(void)
// eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglContext); // eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglContext);
#endif #endif
#endif #endif
pthread_mutex_init(&VideoMutex, NULL); pthread_mutex_init(&VideoMutex, NULL);
pthread_mutex_init(&VideoLockMutex, NULL); pthread_mutex_init(&VideoLockMutex, NULL);
pthread_mutex_init(&OSDMutex, NULL); pthread_mutex_init(&OSDMutex, NULL);
@ -5504,6 +5607,7 @@ static void VideoThreadExit(void)
} }
VideoDisplayThread = 0; VideoDisplayThread = 0;
} }
VideoThread = 0; VideoThread = 0;
pthread_cond_destroy(&VideoWakeupCond); pthread_cond_destroy(&VideoWakeupCond);
pthread_mutex_destroy(&VideoLockMutex); pthread_mutex_destroy(&VideoLockMutex);
@ -5747,7 +5851,9 @@ void VideoSetClosing(VideoHwDecoder * hw_decoder)
/// ///
void VideoResetStart(VideoHwDecoder * hw_decoder) void VideoResetStart(VideoHwDecoder * hw_decoder)
{ {
Debug(3, "video: reset start\n"); Debug(3, "video: reset start\n");
VideoUsedModule->ResetStart(hw_decoder); VideoUsedModule->ResetStart(hw_decoder);
// clear clock to trigger new video stream // clear clock to trigger new video stream
VideoSetClock(hw_decoder, AV_NOPTS_VALUE); VideoSetClock(hw_decoder, AV_NOPTS_VALUE);
@ -6198,6 +6304,7 @@ void VideoSetDevice(const char *device)
void VideoSetConnector(char *c) void VideoSetConnector(char *c)
{ {
DRMConnector = c; DRMConnector = c;
} }
@ -6206,6 +6313,24 @@ void VideoSetRefresh(char *r)
DRMRefresh = atoi(r); DRMRefresh = atoi(r);
} }
int VideoSetShader(char *s)
{
#if defined CUVID && PL_API_VER >= 58
if(num_shaders == NUM_SHADERS)
return -1;
p = malloc(strlen(s)+1);
memcpy(p,s,strlen(s)+1);
shadersp[num_shaders++] = p;
Debug(3,"Use Shader %s\n",s);
return 0;
#else
printf("Shaders are only support with placebo\n");
return -1;
#endif
}
/// ///
/// Get video driver name. /// Get video driver name.
/// ///

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 const char* MyConfigDir;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Prototypes // Prototypes
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -242,6 +242,9 @@ 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