diff --git a/README.md b/README.md index ce2df52..9bd7f1f 100644 --- a/README.md +++ b/README.md @@ -82,9 +82,9 @@ You have to adapt the Makefile. There are 3 possible Version that you can build: softhddrm (DRM=1) 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. - I recommend to use libplacebo and set LIBPLCEBO_GL=1 in the Makefile. + I recommend to use libplacebo and set LIBPLACEBO_GL=1 in the Makefile. - Libplacebo API Version >= 107 is needed. + Libplacebo API Version >= 113 is needed. Install: @@ -116,8 +116,10 @@ Beginners Guide for libplacebo: 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. + Then you should set the Monitor Type 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 use the softhddrm Version then you should set the Monitor Type to HD TV or UHD-HDR TV if you have + connected one of those. If you are colorblind you could try to remedy this with the Colorblind Settings. Realy only needed in rare cases. @@ -128,9 +130,17 @@ Beginners Guide for libplacebo: 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 ...' - I use KrigBilateral for UV scaling and then adaptive-sharpen for sharpening. This results in a perfect picture for me. + I use KrigBilateral for UV scaling and then adaptive-sharpen for sharpening. This results in a perfect + picture for me. + + You can also use a custon LUT File. It is located in $ConfigDir/shaders/lut/lut.cube. If you provide there + a lut file it will be automaticly used. In the Mainmenue you can switch LUT on and off. + +Konfig Guide for softhddrm Version +---------------------------------- + You should set the Monitor Type to HD TV or UHD-HDR TV depending on your TV Set + With softhddrm and a HDR TV Set you can view HDR-HLG content. This is tested with Kernel 5.12 and a Intel NUC. - Setup: environment diff --git a/hdr.c b/hdr.c index 668780e..91614c9 100644 --- a/hdr.c +++ b/hdr.c @@ -335,17 +335,12 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid struct AVMasteringDisplayMetadata *md = NULL; struct AVContentLightMetadata *ld = NULL; - if (render->hdr_metadata == -1) { // Metadata not supported - return; - } + // clean up FFMEPG stuff if (trc == AVCOL_TRC_BT2020_10) trc = AVCOL_TRC_ARIB_STD_B67; - if (trc == AVCOL_TRC_UNSPECIFIED) - trc = AVCOL_TRC_BT709; - if (color == AVCOL_PRI_UNSPECIFIED) - color = AVCOL_PRI_BT709; + if ((old_color == color && old_trc == trc && !sd1 && !sd2) || !render->hdr_metadata) return; // nothing to do @@ -371,12 +366,15 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid Debug(3,"Update HDR to TRC %d color %d\n",trc,color); - if (trc == AVCOL_TRC_BT2020_10) - trc = AVCOL_TRC_ARIB_STD_B67; - old_color = color; old_trc = trc; + + if (VulkanTargetColorSpace != 3) { // no HDR TV + m_need_modeset = 1; // change in colorsettings + return; + } + if (render->hdr_blob_id) drmModeDestroyPropertyBlob(render->fd_drm, render->hdr_blob_id); @@ -392,7 +390,7 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid break; case AVCOL_TRC_SMPTE2084: // 16 eotf = EOTF_ST2084; - break; + break; default: eotf = EOTF_TRADITIONAL_GAMMA_SDR; break; @@ -467,24 +465,24 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid eotf); - - ret = drmModeCreatePropertyBlob(render->fd_drm, &data, sizeof(data), &render->hdr_blob_id); - if (ret) { - printf("DRM: HDR metadata: failed blob create \n"); - render->hdr_blob_id = 0; - return; - } + + ret = drmModeCreatePropertyBlob(render->fd_drm, &data, sizeof(data), &render->hdr_blob_id); + if (ret) { + printf("DRM: HDR metadata: failed blob create \n"); + render->hdr_blob_id = 0; + return; + } - ret = drmModeConnectorSetProperty(render->fd_drm, render->connector_id, - render->hdr_metadata, render->hdr_blob_id); - if (ret) { - printf("DRM: HDR metadata: failed property set %d\n",ret); + ret = drmModeConnectorSetProperty(render->fd_drm, render->connector_id, + render->hdr_metadata, render->hdr_blob_id); + if (ret) { + printf("DRM: HDR metadata: failed property set %d\n",ret); - if (render->hdr_blob_id) - drmModeDestroyPropertyBlob(render->fd_drm, render->hdr_blob_id); - render->hdr_blob_id = 0; - return; - } + if (render->hdr_blob_id) + drmModeDestroyPropertyBlob(render->fd_drm, render->hdr_blob_id); + render->hdr_blob_id = 0; + return; + } m_need_modeset = 1; diff --git a/shaders.h b/shaders.h index c3ae07c..cc140b3 100644 --- a/shaders.h +++ b/shaders.h @@ -280,6 +280,7 @@ static GLuint sc_generate(GLuint gl_prog, enum AVColorSpace colorspace) switch (colorspace) { case AVCOL_SPC_RGB: + case AVCOL_SPC_BT470BG: m = &yuv_bt601.m[0][0]; c = &yuv_bt601.c[0]; Debug(3, "BT601 Colorspace used\n"); @@ -339,8 +340,9 @@ static GLuint sc_generate(GLuint gl_prog, enum AVColorSpace colorspace) 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(%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.rgb *= vec3(1.0/3.17955); \n"); // PL_COLOR_SDR_WHITE_HLG GLSL("// color mapping \n"); GLSL("color.rgb = cms_matrix * color.rgb; \n"); #ifndef GAMMA @@ -348,6 +350,7 @@ static GLuint sc_generate(GLuint gl_prog, enum AVColorSpace colorspace) 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 *= vec3(3.17955); \n"); // PL_COLOR_SDR_WHITE_HLG 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 diff --git a/softhdcuvid.cpp b/softhdcuvid.cpp index 7420cac..5767df6 100644 --- a/softhdcuvid.cpp +++ b/softhdcuvid.cpp @@ -63,7 +63,7 @@ extern void ToggleLUT(); /// vdr-plugin version number. /// Makefile extracts the version number for generating the file name /// for the distribution archive. -static const char *const VERSION = "3.4" +static const char *const VERSION = "3.4.1" #ifdef GIT_REV "-GIT" GIT_REV #endif @@ -1109,10 +1109,11 @@ void cMenuSetupSoft::Create(void) static const char *const resolution[RESOLUTIONS] = { "576i", "720p", "fake 1080", "1080", "2160p" }; -#ifdef PLACEBO + static const char *const target_colorspace[] = { - "Monitor", "sRGB", "BT709", "HDR-HLG", "HDR10", + "default Monitor", "sRGB Monitor", "HD TV (BT.709)", "UHD-HDR TV (BT.2020)", }; +#ifdef PLACEBO static const char *const target_colorblindness[] = { "None", "Protanomaly", "Deuteranomaly", "Tritanomaly", "Monochromacy", }; @@ -1201,12 +1202,12 @@ void cMenuSetupSoft::Create(void) Add(new cMenuEditIntItem(tr("Saturation (0..100)"), &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 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 - + Add(new cMenuEditStraItem(tr("Monitor Type"), &TargetColorSpace, 4, target_colorspace)); for (i = 0; i < RESOLUTIONS; ++i) { cString msg; diff --git a/video.c b/video.c index e065837..58fce73 100644 --- a/video.c +++ b/video.c @@ -3469,18 +3469,39 @@ static void CuvidRenderFrame(CuvidDecoder * decoder, const AVCodecContext * vide CuvidUpdateOutput(decoder); } - color = frame->colorspace; - if (color == AVCOL_SPC_UNSPECIFIED) // if unknown - color = AVCOL_SPC_BT709; - if (color == AVCOL_SPC_RGB) - color = AVCOL_SPC_BT470BG; // fix ffmpeg libav failure - frame->colorspace = color; - // more libav fixes - if (frame->color_primaries == AVCOL_PRI_UNSPECIFIED) - frame->color_primaries = AVCOL_PRI_BT709; - if (frame->color_trc == AVCOL_TRC_UNSPECIFIED) - frame->color_trc = AVCOL_TRC_BT709; +// printf("Orig colorspace %d Primaries %d TRC %d ------- ",frame->colorspace,frame->color_primaries,frame->color_trc); + + // Fix libav colorspace failure + color = frame->colorspace; + if (color == AVCOL_SPC_UNSPECIFIED) // failure with RTL HD and all SD channels with vaapi + if (frame->width > 720) + color = AVCOL_SPC_BT709; + else + color = AVCOL_SPC_BT470BG; + if (color == AVCOL_SPC_RGB) // Cuvid decoder failure with SD channels + color = AVCOL_SPC_BT470BG; + frame->colorspace = color; + + // Fix libav Color primaries failures + if (frame->color_primaries == AVCOL_PRI_UNSPECIFIED) // failure with RTL HD and all SD channels with vaapi + if (frame->width > 720) + frame->color_primaries = AVCOL_PRI_BT709; + else + frame->color_primaries = AVCOL_PRI_BT470BG; + if (frame->color_primaries == AVCOL_PRI_RESERVED0) // cuvid decoder failure with SD channels + frame->color_primaries = AVCOL_PRI_BT470BG; + + // Fix libav Color TRC failures + if (frame->color_trc == AVCOL_TRC_UNSPECIFIED) // failure with RTL HD and all SD channels with vaapi + if (frame->width > 720) + frame->color_trc = AVCOL_TRC_BT709; + else + frame->color_trc = AVCOL_TRC_SMPTE170M; + if (frame->color_trc == AVCOL_TRC_RESERVED0) // cuvid decoder failure with SD channels + frame->color_trc = AVCOL_TRC_SMPTE170M; + +// printf("Patched colorspace %d Primaries %d TRC %d\n",frame->colorspace,frame->color_primaries,frame->color_trc); #ifdef RASPI // // Check image, format, size @@ -3751,7 +3772,7 @@ static void CuvidMixVideo(CuvidDecoder * decoder, __attribute__((unused)) float xcropf, ycropf; GLint texLoc; AVFrame *frame; - AVFrameSideData *sd,*sd1,*sd2; + AVFrameSideData *sd,*sd1=NULL,*sd2=NULL; #ifdef PLACEBO if (level) { @@ -3888,9 +3909,7 @@ static void CuvidMixVideo(CuvidDecoder * decoder, __attribute__((unused)) // Make sure this value is more or less legal if (img->color.sig_peak < 1.0 || img->color.sig_peak > 50.0) img->color.sig_peak = 0.0; -#ifdef USE_DRM - set_hdr_metadata(frame->color_primaries, frame->color_trc, sd1, sd2); -#endif + #if defined VAAPI || defined USE_DRM render_params.peak_detect_params = NULL; @@ -3906,7 +3925,70 @@ static void CuvidMixVideo(CuvidDecoder * decoder, __attribute__((unused)) pl->shift_x = -0.5f; break; } + + target->repr.sys = PL_COLOR_SYSTEM_RGB; + if (VideoStudioLevels) + target->repr.levels = PL_COLOR_LEVELS_PC; + else + target->repr.levels = PL_COLOR_LEVELS_TV; + target->repr.alpha = PL_ALPHA_UNKNOWN; + // target.repr.bits.sample_depth = 16; + // target.repr.bits.color_depth = 16; + // target.repr.bits.bit_shift =0; + +#if USE_DRM + switch (VulkanTargetColorSpace) { + case 0: // Monitor + memcpy(&target->color, &pl_color_space_monitor, sizeof(struct pl_color_space)); + break; + case 1: // sRGB + memcpy(&target->color, &pl_color_space_srgb, sizeof(struct pl_color_space)); + break; + case 2: // HD TV + set_hdr_metadata(frame->color_primaries, frame->color_trc, sd1, sd2); + if (decoder->ColorSpace == AVCOL_SPC_BT470BG) { + target->color.primaries = PL_COLOR_PRIM_BT_601_625; + target->color.transfer = PL_COLOR_TRC_BT_1886; + target->color.light = PL_COLOR_LIGHT_DISPLAY; + } else { + memcpy(&target->color, &pl_color_space_bt709, sizeof(struct pl_color_space)); + } + break; + case 3: // HDR TV + set_hdr_metadata(frame->color_primaries, frame->color_trc, sd1, sd2); + if (decoder->ColorSpace == AVCOL_SPC_BT2020_NCL) { + memcpy(&target->color, &pl_color_space_bt2020_hlg, sizeof(struct pl_color_space)); + } else if (decoder->ColorSpace == AVCOL_SPC_BT470BG) { + target->color.primaries = PL_COLOR_PRIM_BT_601_625; + target->color.transfer = PL_COLOR_TRC_BT_1886; + target->color.light = PL_COLOR_LIGHT_DISPLAY;; + } else { + memcpy(&target->color, &pl_color_space_bt709, sizeof(struct pl_color_space)); + } + break; + default: + memcpy(&target->color, &pl_color_space_monitor, sizeof(struct pl_color_space)); + break; + } +#else + switch (VulkanTargetColorSpace) { + case 0: // Monitor + memcpy(&target->color, &pl_color_space_monitor, sizeof(struct pl_color_space)); + break; + case 1: // sRGB + memcpy(&target->color, &pl_color_space_srgb, sizeof(struct pl_color_space)); + break; + case 2: // HD TV + case 3: // UHD HDR TV + memcpy(&target->color, &pl_color_space_bt709, sizeof(struct pl_color_space)); + break; + default: + memcpy(&target->color, &pl_color_space_monitor, sizeof(struct pl_color_space)); + break; + } +#endif + //printf("sys %d prim %d trc %d light %d\n",img->repr.sys,img->color.primaries,img->color.transfer,img->color.light); // Source crop if (VideoScalerTest) { // right side defined scaler @@ -4258,37 +4340,9 @@ static void CuvidDisplayFrame(void) VideoSurfaceModesChanged = 0; } - target.repr.sys = PL_COLOR_SYSTEM_RGB; - if (VideoStudioLevels) - target.repr.levels = PL_COLOR_LEVELS_PC; - else - target.repr.levels = PL_COLOR_LEVELS_TV; - target.repr.alpha = PL_ALPHA_UNKNOWN; - // target.repr.bits.sample_depth = 16; - // target.repr.bits.color_depth = 16; - // target.repr.bits.bit_shift =0; - switch (VulkanTargetColorSpace) { - case 0: - memcpy(&target.color, &pl_color_space_monitor, sizeof(struct pl_color_space)); - break; - case 1: - memcpy(&target.color, &pl_color_space_srgb, sizeof(struct pl_color_space)); - break; - case 2: - memcpy(&target.color, &pl_color_space_bt709, sizeof(struct pl_color_space)); - break; - case 3: - memcpy(&target.color, &pl_color_space_bt2020_hlg, sizeof(struct pl_color_space)); - break; - case 4: - memcpy(&target.color, &pl_color_space_hdr10, sizeof(struct pl_color_space)); - break; - default: - memcpy(&target.color, &pl_color_space_monitor, sizeof(struct pl_color_space)); - break; - } + #ifdef GAMMA // target.color.transfer = PL_COLOR_TRC_LINEAR; #endif