From b1fb51033375a6146bc954e297c43147b5dde091 Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Thu, 19 Dec 2024 21:04:51 -0500 Subject: [PATCH] fix Full vs Restricted color issue by conversion to sRGB thanks to @PancakeTAS for this discovery --- CMakeLists.txt | 4 +++- README.html | 14 ++++++++++++-- README.md | 15 +++++++++++++-- README.txt | 15 +++++++++++++-- renderers/video_renderer.c | 6 +++--- uxplay.1 | 6 ++++++ uxplay.cpp | 29 +++++++++++++++++++++++++++-- 7 files changed, 77 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 03cd02d9..b03bbd6f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,9 @@ if ( ( UNIX AND NOT APPLE ) OR USE_X11 ) endif() if( UNIX AND NOT APPLE ) - add_definitions( -DSUPPRESS_AVAHI_COMPAT_WARNING ) + add_definitions( -DSUPPRESS_AVAHI_COMPAT_WARNING ) + # convert AirPlay colormap 1:3:7:1 to sRGB (1:1:7:1), needed on Linux and BSD + add_definitions( -DFULL_RANGE_RGB_FIX ) else() set( CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE ) endif() diff --git a/README.html b/README.html index 48a88d47..a441989d 100644 --- a/README.html +++ b/README.html @@ -1107,8 +1107,18 @@

Usage

-bt709 A workaround for the failure of the older Video4Linux2 plugin to recognize Apple’s use of an uncommon (but permitted) “full-range color” variant of the bt709 color standard for -digital TV. This is no longer needed by GStreamer-1.20.4 and backports -from it.

+digital TV. This was no longer needed by GStreamer-1.20.4 and backports +from it, but appears to again be required in GStreamer-1.22 and +later.

+

-srgb A workaround for a failure to display +full-range 8-bit color [0-255], and instead restrict to limited range +[16-235] “legal BT709” HDTV format. The workaround works on x86_64 +desktop systems, but does not yet work on Raspberry Pi. The issue may be +fixed in a future GStreamer release: it only occurs in Linux and +*BSD.

+

-srbg no. Disables the -srgb option, which is +enabled by default in Linux and *BSD, but may be useless on Raspberry +Pi, and may be unwanted, as it adds extra processing load.

-rpi Equivalent to “-v4l2” (Not valid for Raspberry Pi model 5, and removed in UxPlay 1.67)

-rpigl Equivalent to “-rpi -vs glimagesink”. diff --git a/README.md b/README.md index 2d0fd7a7..ab3f8723 100644 --- a/README.md +++ b/README.md @@ -1121,8 +1121,19 @@ Video4Linux2. Equivalent to `-vd v4l2h264dec -vc v4l2convert`. **-bt709** A workaround for the failure of the older Video4Linux2 plugin to recognize Apple's use of an uncommon (but permitted) "full-range -color" variant of the bt709 color standard for digital TV. This is no -longer needed by GStreamer-1.20.4 and backports from it. +color" variant of the bt709 color standard for digital TV. This was no +longer needed by GStreamer-1.20.4 and backports from it, but appears to +again be required in GStreamer-1.22 and later. + +**-srgb** A workaround for a failure to display full-range 8-bit color +[0-255], and instead restrict to limited range [16-235] "legal BT709" +HDTV format. The workaround works on x86_64 desktop systems, but +does not yet work on Raspberry Pi. The issue may be fixed in a future GStreamer +release: it only occurs in Linux and \*BSD. + +**-srbg no**. Disables the -srgb option, which is enabled by default in +Linux and *BSD, but may be useless on Raspberry Pi, and may be unwanted, +as it adds extra processing load. **-rpi** Equivalent to "-v4l2" (Not valid for Raspberry Pi model 5, and removed in UxPlay 1.67) diff --git a/README.txt b/README.txt index 0ee38e98..01ed6877 100644 --- a/README.txt +++ b/README.txt @@ -1122,8 +1122,19 @@ Video4Linux2. Equivalent to `-vd v4l2h264dec -vc v4l2convert`. **-bt709** A workaround for the failure of the older Video4Linux2 plugin to recognize Apple's use of an uncommon (but permitted) "full-range -color" variant of the bt709 color standard for digital TV. This is no -longer needed by GStreamer-1.20.4 and backports from it. +color" variant of the bt709 color standard for digital TV. This was no +longer needed by GStreamer-1.20.4 and backports from it, but appears to +again be required in GStreamer-1.22 and later. + +**-srgb** A workaround for a failure to display full-range 8-bit color +\[0-255\], and instead restrict to limited range \[16-235\] "legal +BT709" HDTV format. The workaround works on x86_64 desktop systems, but +does not yet work on Raspberry Pi. The issue may be fixed in a future +GStreamer release: it only occurs in Linux and \*BSD. + +**-srbg no**. Disables the -srgb option, which is enabled by default in +Linux and \*BSD, but may be useless on Raspberry Pi, and may be +unwanted, as it adds extra processing load. **-rpi** Equivalent to "-v4l2" (Not valid for Raspberry Pi model 5, and removed in UxPlay 1.67) diff --git a/renderers/video_renderer.c b/renderers/video_renderer.c index 5188914f..bd7895c4 100644 --- a/renderers/video_renderer.c +++ b/renderers/video_renderer.c @@ -128,14 +128,14 @@ static void append_videoflip (GString *launch, const videoflip_t *flip, const vi } } -/* apple uses colorimetry=1:3:5:1 * +/* apple uses colorimetry that is detected as 1:3:7:1 * //previously 1:3:5:1 was seen * (not recognized by v4l2 plugin in Gstreamer < 1.20.4) * * See .../gst-libs/gst/video/video-color.h in gst-plugins-base * * range = 1 -> GST_VIDEO_COLOR_RANGE_0_255 ("full RGB") * * matrix = 3 -> GST_VIDEO_COLOR_MATRIX_BT709 * - * transfer = 5 -> GST_VIDEO_TRANSFER_BT709 * + * transfer = 7 -> GST_VIDEO_TRANSFER_SRGB * // previously GST_VIDEO_TRANSFER_BT709 * primaries = 1 -> GST_VIDEO_COLOR_PRIMARIES_BT709 * - * closest used by GStreamer < 1.20.4 is BT709, 2:3:5:1 with * * + * closest used by GStreamer < 1.20.4 is BT709, 2:3:5:1 with * // now use sRGB = 1:1:7:1 * range = 2 -> GST_VIDEO_COLOR_RANGE_16_235 ("limited RGB") */ static const char h264_caps[]="video/x-h264,stream-format=(string)byte-stream,alignment=(string)au"; diff --git a/uxplay.1 b/uxplay.1 index 8b799655..ee8d3f6c 100644 --- a/uxplay.1 +++ b/uxplay.1 @@ -87,6 +87,12 @@ UxPlay 1.71: An open\-source AirPlay mirroring (+ audio streaming) server: .TP \fB\-bt709\fR Sometimes needed for Raspberry Pi models using Video4Linux2. .TP +\fB\-srgb\fR Display "Full range" [0-255] color, not "Limited Range"[16-235] +.IP + This is a workaround for a GStreamer problem, until it is fixed. +.PP +\fB\-srgb\fR no Disable srgb option (use when enabled by default: Linux, *BSD) +.TP \fB\-as\fI sink\fR Choose the GStreamer audiosink; default "autoaudiosink" .IP choices:pulsesink,alsasink,pipewiresink,osssink,oss4sink, diff --git a/uxplay.cpp b/uxplay.cpp index f7a60746..b96053d3 100644 --- a/uxplay.cpp +++ b/uxplay.cpp @@ -72,6 +72,12 @@ #define HIGHEST_PORT 65535 #define NTP_TIMEOUT_LIMIT 5 #define BT709_FIX "capssetter caps=\"video/x-h264, colorimetry=bt709\"" +#define SRGB_FIX " ! video/x-raw,colorimetry=sRGB,format=RGB ! " +#ifdef FULL_RANGE_RGB_FIX + #define DEFAULT_SRGB_FIX true +#else + #define DEFAULT_SRGB_FIX false +#endif static std::string server_name = DEFAULT_NAME; static dnssd_t *dnssd = NULL; @@ -122,6 +128,7 @@ static unsigned short display[5] = {0}, tcp[3] = {0}, udp[3] = {0}; static bool debug_log = DEFAULT_DEBUG_LOG; static int log_level = LOGGER_INFO; static bool bt709_fix = false; +static bool srgb_fix = DEFAULT_SRGB_FIX; static int nohold = 0; static bool nofreeze = false; static unsigned short raop_port; @@ -640,7 +647,10 @@ static void print_info (char *name) { printf(" gtksink,waylandsink,osxvideosink,kmssink,d3d11videosink etc.\n"); printf("-vs 0 Streamed audio only, with no video display window\n"); printf("-v4l2 Use Video4Linux2 for GPU hardware h264 decoding\n"); - printf("-bt709 Sometimes needed for Raspberry Pi models using Video4Linux2 \n"); + printf("-bt709 Sometimes needed for Raspberry Pi models using Video4Linux2 \n"); + printf("-srgb Display \"Full range\" [0-255] color, not \"Limited Range\"[16-235]\n"); + printf(" This is a workaround for a GStreamer problem, until it is fixed\n"); + printf("-srgb no Disable srgb option (use when enabled by default: Linux, *BSD)\n"); printf("-as ... Choose the GStreamer audiosink; default \"autoaudiosink\"\n"); printf(" some choices:pulsesink,alsasink,pipewiresink,jackaudiosink,\n"); printf(" osssink,oss4sink,osxaudiosink,wasapisink,directsoundsink.\n"); @@ -1003,7 +1013,7 @@ static void parse_arguments (int argc, char *argv[]) { fprintf(stderr," -rpifb was equivalent to \"-v4l2 -vs kmssink\"\n"); fprintf(stderr," -rpigl was equivalent to \"-v4l2 -vs glimagesink\"\n"); fprintf(stderr," -rpiwl was equivalent to \"-v4l2 -vs waylandsink\"\n"); - fprintf(stderr," for GStreamer < 1.22, \"-bt709\" may also be needed\n"); + fprintf(stderr," Option \"-bt709\" may also be needed for R Pi model 4B and earlier\n"); exit(1); } else if (arg == "-fs" ) { fullscreen = true; @@ -1078,6 +1088,15 @@ static void parse_arguments (int argc, char *argv[]) { } } else if (arg == "-bt709") { bt709_fix = true; + } else if (arg == "-srgb") { + srgb_fix = true; + if (i < argc - 1) { + if (strlen(argv[i+1]) == 2 && strncmp(argv[i+1], "no", 2) == 0) { + srgb_fix = false; + i++; + continue; + } + } } else if (arg == "-nohold") { nohold = 1; } else if (arg == "-al") { @@ -2170,6 +2189,12 @@ int main (int argc, char *argv[]) { video_parser.append(BT709_FIX); } + if (srgb_fix && use_video) { + std::string option = video_converter; + video_converter.append(SRGB_FIX); + video_converter.append(option); + } + if (require_password && registration_list) { if (pairing_register == "") { const char * homedir = get_homedir();