From 7b3c47035eb12c2dcdb7d422fd13d9f8da3eb572 Mon Sep 17 00:00:00 2001 From: jojo61 Date: Fri, 7 Dec 2018 13:07:50 +0100 Subject: [PATCH] more changes --- README.md | 42 ++---------- openglosd.cpp | 11 +-- softhdcuvid.cpp | 51 ++++++++++++-- video.c | 178 ++++++++++++++++++++++++++++++++++++++++-------- video.h | 9 +++ 5 files changed, 214 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 82a189c..88d502d 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Currently I have tested it with a GTX 1050 from NVIDIA. SD, HD and UHD is workin Current Status NVIDA: 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 ompatible 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. You have to adapt the Makefile to your needs. I use FFMPEG 4.0 @@ -63,11 +63,12 @@ new: This Version supports building with libplacebo. https://github.com/haasn/libplacebo You have to enable it in the Makefile and install libplacebo yourself. -At the moment this is Work in progress and the used upscaler is hardcoded. This will be changend to be configurable. +At the moment this is Work in progress. 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. - +Also you can enable a Scaler Test feature. When enabled then the screen is split.On the left ahlf you will see the scaler defined by Scaler Test and on the right side you wil 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. Good luck jojo61 @@ -369,40 +370,5 @@ Requires: or kernel support for oss/oss4 or alsa oss emulation - x11-libs/libva (deprecated) - Video Acceleration (VA) API for Linux - http://www.freedesktop.org/wiki/Software/vaapi - x11-libs/libva-intel-driver - HW video decode support for Intel integrated graphics - http://www.freedesktop.org/wiki/Software/vaapi - or - x11-libs/vdpau-video - VDPAU Backend for Video Acceleration (VA) API - http://www.freedesktop.org/wiki/Software/vaapi - or - x11-libs/xvba-video - XVBA Backend for Video Acceleration (VA) API - http://www.freedesktop.org/wiki/Software/vaapi - - x11-libs/libvdpau - VDPAU wrapper and trace libraries - http://www.freedesktop.org/wiki/Software/VDPAU - - x11-libs/libxcb, - X C-language Bindings library - http://xcb.freedesktop.org - x11-libs/xcb-util, - x11-libs/xcb-util-wm, - x11-libs/xcb-util-keysyms - X C-language Bindings library - http://xcb.freedesktop.org - Only versions >= 0.3.8 are good supported - - x11-libs/libX11 - X.Org X11 library - http://xorg.freedesktop.org - - GNU Make 3.xx - http://www.gnu.org/software/make/make.html Optional: diff --git a/openglosd.cpp b/openglosd.cpp index 63e58f4..27fc36c 100644 --- a/openglosd.cpp +++ b/openglosd.cpp @@ -328,7 +328,7 @@ cOglFont *cOglFont::Get(const char *name, int charHeight) { fonts->Add(font); return font; } - + void cOglFont::Init(void) { fonts = new cList; if (FT_Init_FreeType(&ftLib)) @@ -442,8 +442,10 @@ cOglFb::cOglFb(GLint width, GLint height, GLint viewPortWidth, GLint viewPortHei } cOglFb::~cOglFb(void) { - glDeleteTextures(1, &texture); - glDeleteFramebuffers(1, &fb); + if (texture) + glDeleteTextures(1, &texture); + if (fb) + glDeleteFramebuffers(1, &fb); } @@ -709,7 +711,8 @@ cOglCmdDeleteFb::cOglCmdDeleteFb(cOglFb *fb) : cOglCmd(fb) { } bool cOglCmdDeleteFb::Execute(void) { - delete fb; + if (fb) + delete fb; return true; } diff --git a/softhdcuvid.cpp b/softhdcuvid.cpp index 640a98a..4bc18b9 100644 --- a/softhdcuvid.cpp +++ b/softhdcuvid.cpp @@ -116,6 +116,9 @@ static int ConfigVideoSaturation = 100; ///< config video saturation static int ConfigVideoHue; ///< config video hue static int ConfigGamma; ///< config Gamma static int ConfigTargetColorSpace; ///< config Target Colrospace +static int ConfigScalerTest; /// Test for Scalers +static int ConfigColorBlindness; +static int ConfigColorBlindnessFaktor; /// config deinterlace static int ConfigVideoDeinterlace[RESOLUTIONS]; @@ -870,6 +873,9 @@ class cMenuSetupSoft:public cMenuSetupPage int Hue; int Gamma; int TargetColorSpace; + int ScalerTest; + int ColorBlindnessFaktor; + int ColorBlindness; int ResolutionShown[RESOLUTIONS]; int Scaling[RESOLUTIONS]; @@ -1011,6 +1017,9 @@ void cMenuSetupSoft::Create(void) static const char *const target_colorspace[] = { "Monitor", "sRGB", "BT709", "HDR-HLG", "HDR10", }; + static const char *const target_colorblindness[] = { + "None", "Protanomaly", "Deuteranomaly", "Tritanomaly", "Monochromacy", + }; #endif int current; int i; @@ -1018,12 +1027,15 @@ void cMenuSetupSoft::Create(void) #ifdef PLACEBO static int scalers=0; static char *scaling[100]; + static char *scalingtest[100]; if (scalers == 0) { + scalingtest[0] = "Off"; for (scalers = 0;pl_named_filters[scalers].filter != NULL ; scalers++) { scaling[scalers] = (char*)pl_named_filters[scalers].name; + scalingtest[scalers+1] = (char*)pl_named_filters[scalers].name; // printf("Scaler %s\n",pl_named_filters[scalers].name); } - scalers -= 2; +// scalers -= 2; } #endif @@ -1092,7 +1104,10 @@ void cMenuSetupSoft::Create(void) &BlackPicture, trVDR("no"), trVDR("yes"))); Add(new cMenuEditBoolItem(tr("Clear decoder on channel switch"), &ClearOnSwitch, trVDR("no"), trVDR("yes"))); + #if PLACEBO + Add(new cMenuEditStraItem(tr("Scaler Test"), &ConfigScalerTest, scalers+1, scalingtest)); + Add(new cMenuEditIntItem(tr("Brightness (-100..100)"), &Brightness, -100, 100, tr("min"), tr("max"))); Add(new cMenuEditIntItem(tr("Contrast (0..100)"), &Contrast, @@ -1101,10 +1116,13 @@ void cMenuSetupSoft::Create(void) &Saturation, 0, 100, tr("min"), tr("max"))); Add(new cMenuEditIntItem(tr("Gamma (0..100)"), &Gamma, 0, 100, tr("min"), tr("max"))); - Add(new cMenuEditIntItem(tr("Hue (-314..314) "), &Hue, -314, - 314, tr("min"), tr("max"))); + Add(new cMenuEditIntItem(tr("Hue (-314..314) "), &Hue, -314, 314, tr("min"), tr("max"))); Add(new cMenuEditStraItem(tr("Monitor Colorspace"), &TargetColorSpace, 5, target_colorspace)); + Add(new cMenuEditStraItem(tr("Color Blindness"), &ColorBlindness, 5, target_colorblindness)); + Add(new cMenuEditIntItem(tr("Color Correction (-100..100) "), &ColorBlindnessFaktor, -100, + 100, tr("min"), tr("max"))); #endif + for (i = 0; i < RESOLUTIONS; ++i) { cString msg; @@ -1303,6 +1321,9 @@ cMenuSetupSoft::cMenuSetupSoft(void) Hue = ConfigVideoHue; Gamma = ConfigGamma; TargetColorSpace = ConfigTargetColorSpace; + ColorBlindness = ConfigColorBlindness; + ColorBlindnessFaktor = ConfigColorBlindnessFaktor; +// ScalerTest = ConfigScalerTest; for (i = 0; i < RESOLUTIONS; ++i) { ResolutionShown[i] = 0; @@ -1447,7 +1468,13 @@ void cMenuSetupSoft::Store(void) VideoSetTargetColor(ConfigTargetColorSpace); SetupStore("Hue", ConfigVideoHue = Hue); VideoSetHue(ConfigVideoHue); - + SetupStore("CBlindness", ConfigColorBlindness = ColorBlindness); + VideoSetColorBlindness(ConfigColorBlindness); + SetupStore("CBlindnessFaktor", ConfigColorBlindnessFaktor = ColorBlindnessFaktor); + VideoSetColorBlindnessFaktor(ConfigColorBlindnessFaktor); +// SetupStore("ScalerTest", ConfigScalerTest = ScalerTest); + VideoSetScalerTest(ConfigScalerTest); + for (i = 0; i < RESOLUTIONS; ++i) { char buf[128]; @@ -2680,7 +2707,7 @@ void cSoftHdDevice::StillPicture(const uchar * data, int length) data[0] == 0x47 ? "ts" : "pes", data, length); if (data[0] == 0x47) { // ts sync - cDevice::StillPicture(data, length); + cDevice::StillPicture(data, length); return; } @@ -3282,6 +3309,20 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value) VideoSetHue(ConfigVideoHue = atoi(value)); return true; } + if (!strcasecmp(name, "CBlindness")) { + VideoSetColorBlindness(ConfigColorBlindness = atoi(value)); + return true; + } + if (!strcasecmp(name, "CBlindnessFaktor")) { + VideoSetColorBlindnessFaktor(ConfigColorBlindnessFaktor = atoi(value)); + return true; + } +#if 0 + if (!strcasecmp(name, "ScalerTest")) { + VideoSetScalerTest(ConfigScalerTest = atoi(value)); + return true; + } +#endif for (i = 0; i < RESOLUTIONS; ++i) { char buf[128]; diff --git a/video.c b/video.c index 1a529d3..1d562e6 100644 --- a/video.c +++ b/video.c @@ -422,6 +422,9 @@ static float VideoSaturation = 1.0f; static float VideoHue = 0.0f; static float VideoGamma = 1.0f; static int VulkanTargetColorSpace = 0; +static int VideoScalerTest = 0; +static int VideoColorBlindness = 0; +static float VideoColorBlindnessFaktor = 1.0f; static xcb_atom_t WmDeleteWindowAtom; ///< WM delete message atom static xcb_atom_t NetWmState; ///< wm-state message atom @@ -1700,6 +1703,7 @@ typedef struct priv { const struct pl_vk_inst *vk_inst; struct pl_context *ctx; struct pl_renderer *renderer; + struct pl_renderer *renderertest; const struct pl_swapchain *swapchain; struct pl_context_params context; struct pl_render_target r_target; @@ -1876,6 +1880,8 @@ static void CuvidDestroySurfaces(CuvidDecoder * decoder) // close(decoder->pl_buf_UV->handles.fd); pl_buf_destroy(p->gpu,&decoder->pl_buf_Y); pl_buf_destroy(p->gpu,&decoder->pl_buf_UV); + pl_renderer_destroy(&p->renderer); + p->renderer = pl_renderer_create(p->ctx, p->gpu); #else glDeleteTextures(CODEC_SURFACES_MAX*2,(GLuint*)&decoder->gl_textures); GlxCheck(); @@ -2323,9 +2329,15 @@ void generateCUDAImage(CuvidDecoder * decoder,int index, const AVFrame *frame,in int n; struct ext_buf ebuf[2]; -//printf("Upload buf to texture for frame %d in size %d-%d\n",index,image_width,image_height); - while (pl_buf_poll(p->gpu,decoder->pl_buf_Y, 5000000)); // 5 ms - while (pl_buf_poll(p->gpu,decoder->pl_buf_UV, 5000000)); +//printf("Upload buf to texture for frame %d in size %d-%d\n",index,image_width,image_height); + if (decoder->pl_buf_Y) + while (pl_buf_poll(p->gpu,decoder->pl_buf_Y, 5000000)); // 5 ms + else + return; + if (decoder->pl_buf_UV) + while (pl_buf_poll(p->gpu,decoder->pl_buf_UV, 5000000)); + else + return; for (n = 0; n < 2; n++) { // Copy 2 Planes from Cuda decoder to upload Buffer // widthInBytes must account for the chroma plane @@ -3240,7 +3252,7 @@ Debug(3,"fmt %02d:%02d width %d:%d hight %d:%d\n",decoder->ColorSpace,frame->co #endif // copy to texture generateCUDAImage(decoder,surface,frame,w,h,decoder->PixFmt==AV_PIX_FMT_NV12?1:2); - + CuvidQueueVideoSurface(decoder, surface, 1); return; @@ -3354,8 +3366,10 @@ static void CuvidMixVideo(CuvidDecoder * decoder, int level) #endif { #ifdef PLACEBO - struct pl_render_params render_params = pl_render_default_params; + struct pl_render_params render_params; + struct pl_deband_params deband; struct pl_color_adjustment colors; + struct pl_cone_params cone; struct pl_tex_vk *vkp; const struct pl_fmt *fmt; VkImage Image; @@ -3437,7 +3451,10 @@ static void CuvidMixVideo(CuvidDecoder * decoder, int level) #else img = &decoder->pl_images[current]; - + + memcpy(&deband,&pl_deband_default_params,sizeof(deband)); + memcpy(&render_params,&pl_render_default_params,sizeof(render_params)); + switch (decoder->ColorSpace) { case AVCOL_SPC_RGB: img->repr.sys = PL_COLOR_SYSTEM_BT_601; @@ -3457,6 +3474,7 @@ static void CuvidMixVideo(CuvidDecoder * decoder, int level) case AVCOL_SPC_BT2020_NCL: img->repr.sys = PL_COLOR_SYSTEM_BT_2020_NC; memcpy(&img->color,&pl_color_space_bt2020_hlg,sizeof(struct pl_color_space)); + deband.grain = 0.0f; // no grain in HDR // img->color.primaries = PL_COLOR_PRIM_BT_2020; // img->color.transfer = PL_COLOR_TRC_HLG; // img->color.light = PL_COLOR_LIGHT_SCENE_HLG; @@ -3470,22 +3488,60 @@ static void CuvidMixVideo(CuvidDecoder * decoder, int level) break; } // Source crop - img->src_rect.x0 = video_src_rect.x0; - img->src_rect.y0 = video_src_rect.y0; - img->src_rect.x1 = video_src_rect.x1; - img->src_rect.y1 = video_src_rect.y1; + if (VideoScalerTest) { // right side defnied scaler + pl_tex_clear(p->gpu,target->fbo,black); // clear frame + img->src_rect.x0 = video_src_rect.x1/2+1; + img->src_rect.y0 = video_src_rect.y0; + img->src_rect.x1 = video_src_rect.x1; + img->src_rect.y1 = video_src_rect.y1; - // Video aspect ratio - target->dst_rect.x0 = dst_video_rect.x0; - target->dst_rect.y0 = dst_video_rect.y0; - target->dst_rect.x1 = dst_video_rect.x1; - target->dst_rect.y1 = dst_video_rect.y1; + // Video aspect ratio + target->dst_rect.x0 = dst_video_rect.x1/2+dst_video_rect.x0/2+1; + target->dst_rect.y0 = dst_video_rect.y0; + target->dst_rect.x1 = dst_video_rect.x1; + target->dst_rect.y1 = dst_video_rect.y1; + } else { + img->src_rect.x0 = video_src_rect.x0; + img->src_rect.y0 = video_src_rect.y0; + img->src_rect.x1 = video_src_rect.x1; + img->src_rect.y1 = video_src_rect.y1; + + // Video aspect ratio + target->dst_rect.x0 = dst_video_rect.x0; + target->dst_rect.y0 = dst_video_rect.y0; + target->dst_rect.x1 = dst_video_rect.x1; + target->dst_rect.y1 = dst_video_rect.y1; + } + + + + if (VideoColorBlindness) { + switch(VideoColorBlindness) { + case 1: memcpy(&cone,&pl_vision_protanomaly,sizeof(cone)); + break; + case 2: memcpy(&cone,&pl_vision_deuteranomaly,sizeof(cone)); + break; + case 3: memcpy(&cone,&pl_vision_tritanomaly,sizeof(cone)); + break; + case 4: memcpy(&cone,&pl_vision_monochromacy,sizeof(cone)); + break; + default: memcpy(&cone,&pl_vision_normal,sizeof(cone)); + break; + } + cone.strength = VideoColorBlindnessFaktor; + render_params.cone_params = &cone; + } + else { + render_params.cone_params = NULL; + } // render_params.upscaler = &pl_filter_ewa_lanczos; + render_params.upscaler = pl_named_filters[VideoScaling[decoder->Resolution]].filter; render_params.downscaler = pl_named_filters[VideoScaling[decoder->Resolution]].filter; render_params.color_adjustment = &colors; + render_params.deband_params = &deband; colors.brightness = VideoBrightness; colors.contrast = VideoContrast; @@ -3505,8 +3561,8 @@ static void CuvidMixVideo(CuvidDecoder * decoder, int level) if (!pl_render_image(p->renderer, &decoder->pl_images[current], target, &render_params)) { Fatal(_("Failed rendering frame!\n")); } -#if 0 - if (1) { + + if (VideoScalerTest) { // left side internal scaler (bicubic) // Source crop img->src_rect.x0 = video_src_rect.x0; img->src_rect.y0 = video_src_rect.y0; @@ -3518,13 +3574,20 @@ static void CuvidMixVideo(CuvidDecoder * decoder, int level) target->dst_rect.y0 = dst_video_rect.y0; target->dst_rect.x1 = dst_video_rect.x1/2+dst_video_rect.x0/2; target->dst_rect.y1 = dst_video_rect.y1; - render_params.upscaler = NULL; - render_params.downscaler = NULL; - if (!pl_render_image(p->renderer, &decoder->pl_images[current], target, &render_params)) { + render_params.upscaler = pl_named_filters[VideoScalerTest-1].filter; + render_params.downscaler = pl_named_filters[VideoScalerTest-1].filter; + + if (!p->renderertest) + p->renderertest = pl_renderer_create(p->ctx, p->gpu); + + if (!pl_render_image(p->renderertest, &decoder->pl_images[current], target, &render_params)) { Fatal(_("Failed rendering frame!\n")); } } -#endif + else if (p->renderertest) { + pl_renderer_destroy(&p->renderertest); + p->renderertest = NULL; + } #endif Debug(4, "video/vdpau: yy video surface %p displayed\n", current, decoder->SurfaceRead); @@ -3534,14 +3597,18 @@ static void CuvidMixVideo(CuvidDecoder * decoder, int level) void make_osd_overlay(int x, int y, int width, int height) { const struct pl_fmt *fmt; struct pl_overlay *pl; + const float black[4] = { 0.0f,0.0f,0.0f,1.0f}; + int offset = VideoWindowHeight - (VideoWindowHeight-height-y) - (VideoWindowHeight - y); fmt = pl_find_named_fmt(p->gpu, "rgba8"); // 8 Bit RGB pl = &osdoverlay; - if (pl->plane.texture) + if (pl->plane.texture) { +// pl_tex_clear(p->gpu,pl->plane.texture,black); pl_tex_destroy(p->gpu,&pl->plane.texture); + } // make texture for OSD pl->plane.texture = pl_tex_create(p->gpu, &(struct pl_tex_params) { @@ -3551,11 +3618,13 @@ void make_osd_overlay(int x, int y, int width, int height) { .format = fmt, .sampleable = true, .host_writable = true, + .blit_dst = true, .sample_mode = PL_TEX_SAMPLE_LINEAR, .address_mode = PL_TEX_ADDRESS_CLAMP, }); // make overlay + pl_tex_clear(p->gpu,pl->plane.texture,black); pl->plane.components = 4; pl->plane.shift_x = 0.0f; pl->plane.shift_y = 0.0f; @@ -3611,7 +3680,7 @@ static void CuvidDisplayFrame(void) #else pl_swapchain_swap_buffers(p->swapchain); // last_time = GetusTicks(); -// pl_swapchain_swap_buffers(p->swapchain); + // printf(" Latency %d Time wait %2.2f\n",pl_swapchain_latency(p->swapchain),(float)(GetusTicks()-last_time)/1000000.0); last_time = GetusTicks(); if (!p->swapchain) @@ -3623,7 +3692,15 @@ static void CuvidDisplayFrame(void) pl_render_target_from_swapchain(&target, &frame); // make target frame - + if (VideoSurfaceModesChanged){ + pl_renderer_destroy(&p->renderer); + p->renderer = pl_renderer_create(p->ctx, p->gpu); + if (p->renderertest) { + pl_renderer_destroy(&p->renderertest); + p->renderertest = NULL; + } + VideoSurfaceModesChanged = 0; + } target.repr.sys = PL_COLOR_SYSTEM_RGB; if (VideoStudioLevels) @@ -4175,6 +4252,9 @@ static void CuvidDisplayHandlerThread(void) decoder->Closing = -1; } } +#ifdef PLACEBO + usleep(100); +#endif continue; } decoded = 1; @@ -4845,7 +4925,7 @@ void InitPlacebo(){ Debug(3,"Init Placebo\n"); - p = malloc(sizeof(struct priv)); + p = calloc(1,sizeof(struct priv)); if (!p) Fatal(_("Cant get memory for PLACEBO struct")); @@ -4959,9 +5039,12 @@ static void *VideoDisplayHandlerThread(void *dummy) VideoUsedModule->DisplayHandlerThread(); } -#ifdef PLACEBO_ +#ifdef PLACEBO pl_renderer_destroy(&p->renderer); -// pl_tex_destroy(p->gpu, &p->final_fbo); + if (p->renderertest) { + pl_renderer_destroy(&p->renderertest); + p->renderertest = NULL; + } pl_swapchain_destroy(&p->swapchain); pl_vulkan_destroy(&p->vk); vkDestroySurfaceKHR(p->vk_inst->instance, p->pSurface, NULL); @@ -6126,7 +6209,30 @@ void VideoSetStudioLevels(int onoff) { VideoStudioLevels = onoff; } - +/// +/// Set scaler test. +/// +/// @param onoff flag on/off +/// +void VideoSetScalerTest(int onoff) +{ + VideoScalerTest = onoff; + VideoSurfaceModesChanged = 1; +} + /// +/// Set Color Blindness. +/// +void VideoSetColorBlindness(int value) +{ + VideoColorBlindness = value;; +} +/// +/// Set Color Blindness Faktor. +/// +void VideoSetColorBlindnessFaktor(int value) +{ + VideoColorBlindnessFaktor = (float)value / 100.0f + 1.0f; +} /// /// Set background color. /// @@ -6377,13 +6483,25 @@ void VideoExit(void) } #endif -#ifdef PLACEBO +#ifdef PLACEBO_ + + pl_gpu_finish(p->gpu); + if (osdoverlay.plane.texture) { + pl_tex_destroy(p->gpu,&osdoverlay.plane.texture); + } pl_renderer_destroy(&p->renderer); + if (p->renderertest) { + pl_renderer_destroy(&p->renderertest); + p->renderertest = NULL; + } pl_swapchain_destroy(&p->swapchain); vkDestroySurfaceKHR(p->vk_inst->instance, p->pSurface, NULL); - pl_vk_inst_destroy(&p->vk_inst); + pl_vk_inst_destroy(&p->vk_inst); +printf("1\n"); // pl_vulkan_destroy(&p->vk); +printf("1\n"); pl_context_destroy(&p->ctx); +printf("1\n"); free(p); #endif diff --git a/video.h b/video.h index 05b585a..f1f8b31 100644 --- a/video.h +++ b/video.h @@ -127,6 +127,12 @@ extern void VideoSetTargetColor(int); /// Set hue adjustment. extern void VideoSetHue(int); + /// Set Color Blindness. +extern void VideoSetColorBlindness(int); + + /// Set Color Blindness Faktor +extern void VideoSetColorBlindnessFaktor(int); + /// Set video output position. extern void VideoSetOutputPosition(VideoHwDecoder *, int, int, int, int); @@ -154,6 +160,9 @@ extern void VideoSetInverseTelecine(int[]); /// Set scaling. extern void VideoSetScaling(int[]); + /// Set scaler test. +extern void VideoSetScalerTest(int); + /// Set denoise. extern void VideoSetDenoise(int[]);