fix Full vs Restricted color issue by conversion to sRGB

thanks to @PancakeTAS for this discovery
This commit is contained in:
F. Duncanh
2024-12-19 21:04:51 -05:00
parent 47783de5de
commit b1fb510333
7 changed files with 77 additions and 12 deletions

View File

@@ -32,7 +32,9 @@ if ( ( UNIX AND NOT APPLE ) OR USE_X11 )
endif() endif()
if( UNIX AND NOT APPLE ) 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() else()
set( CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE ) set( CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE )
endif() endif()

View File

@@ -1107,8 +1107,18 @@ decoding in the GPU by Video4Linux2. Equivalent to
<p><strong>-bt709</strong> A workaround for the failure of the older <p><strong>-bt709</strong> A workaround for the failure of the older
Video4Linux2 plugin to recognize Apples use of an uncommon (but Video4Linux2 plugin to recognize Apples use of an uncommon (but
permitted) “full-range color” variant of the bt709 color standard for 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 digital TV. This was no longer needed by GStreamer-1.20.4 and backports
from it.</p> from it, but appears to again be required in GStreamer-1.22 and
later.</p>
<p><strong>-srgb</strong> 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.</p>
<p><strong>-srbg no</strong>. 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.</p>
<p><strong>-rpi</strong> Equivalent to “-v4l2” (Not valid for Raspberry <p><strong>-rpi</strong> Equivalent to “-v4l2” (Not valid for Raspberry
Pi model 5, and removed in UxPlay 1.67)</p> Pi model 5, and removed in UxPlay 1.67)</p>
<p><strong>-rpigl</strong> Equivalent to “-rpi -vs glimagesink”. <p><strong>-rpigl</strong> Equivalent to “-rpi -vs glimagesink”.

View File

@@ -1121,8 +1121,19 @@ Video4Linux2. Equivalent to `-vd v4l2h264dec -vc v4l2convert`.
**-bt709** A workaround for the failure of the older Video4Linux2 plugin **-bt709** A workaround for the failure of the older Video4Linux2 plugin
to recognize Apple's use of an uncommon (but permitted) "full-range 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 color" variant of the bt709 color standard for digital TV. This was no
longer needed by GStreamer-1.20.4 and backports from it. 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 **-rpi** Equivalent to "-v4l2" (Not valid for Raspberry Pi model 5, and
removed in UxPlay 1.67) removed in UxPlay 1.67)

View File

@@ -1122,8 +1122,19 @@ Video4Linux2. Equivalent to `-vd v4l2h264dec -vc v4l2convert`.
**-bt709** A workaround for the failure of the older Video4Linux2 plugin **-bt709** A workaround for the failure of the older Video4Linux2 plugin
to recognize Apple's use of an uncommon (but permitted) "full-range 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 color" variant of the bt709 color standard for digital TV. This was no
longer needed by GStreamer-1.20.4 and backports from it. 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 **-rpi** Equivalent to "-v4l2" (Not valid for Raspberry Pi model 5, and
removed in UxPlay 1.67) removed in UxPlay 1.67)

View File

@@ -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) * * (not recognized by v4l2 plugin in Gstreamer < 1.20.4) *
* See .../gst-libs/gst/video/video-color.h in gst-plugins-base * * See .../gst-libs/gst/video/video-color.h in gst-plugins-base *
* range = 1 -> GST_VIDEO_COLOR_RANGE_0_255 ("full RGB") * * range = 1 -> GST_VIDEO_COLOR_RANGE_0_255 ("full RGB") *
* matrix = 3 -> GST_VIDEO_COLOR_MATRIX_BT709 * * 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 * * 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") */ * 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"; static const char h264_caps[]="video/x-h264,stream-format=(string)byte-stream,alignment=(string)au";

View File

@@ -87,6 +87,12 @@ UxPlay 1.71: An open\-source AirPlay mirroring (+ audio streaming) server:
.TP .TP
\fB\-bt709\fR Sometimes needed for Raspberry Pi models using Video4Linux2. \fB\-bt709\fR Sometimes needed for Raspberry Pi models using Video4Linux2.
.TP .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" \fB\-as\fI sink\fR Choose the GStreamer audiosink; default "autoaudiosink"
.IP .IP
choices:pulsesink,alsasink,pipewiresink,osssink,oss4sink, choices:pulsesink,alsasink,pipewiresink,osssink,oss4sink,

View File

@@ -72,6 +72,12 @@
#define HIGHEST_PORT 65535 #define HIGHEST_PORT 65535
#define NTP_TIMEOUT_LIMIT 5 #define NTP_TIMEOUT_LIMIT 5
#define BT709_FIX "capssetter caps=\"video/x-h264, colorimetry=bt709\"" #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 std::string server_name = DEFAULT_NAME;
static dnssd_t *dnssd = NULL; 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 bool debug_log = DEFAULT_DEBUG_LOG;
static int log_level = LOGGER_INFO; static int log_level = LOGGER_INFO;
static bool bt709_fix = false; static bool bt709_fix = false;
static bool srgb_fix = DEFAULT_SRGB_FIX;
static int nohold = 0; static int nohold = 0;
static bool nofreeze = false; static bool nofreeze = false;
static unsigned short raop_port; static unsigned short raop_port;
@@ -640,7 +647,10 @@ static void print_info (char *name) {
printf(" gtksink,waylandsink,osxvideosink,kmssink,d3d11videosink etc.\n"); printf(" gtksink,waylandsink,osxvideosink,kmssink,d3d11videosink etc.\n");
printf("-vs 0 Streamed audio only, with no video display window\n"); printf("-vs 0 Streamed audio only, with no video display window\n");
printf("-v4l2 Use Video4Linux2 for GPU hardware h264 decoding\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("-as ... Choose the GStreamer audiosink; default \"autoaudiosink\"\n");
printf(" some choices:pulsesink,alsasink,pipewiresink,jackaudiosink,\n"); printf(" some choices:pulsesink,alsasink,pipewiresink,jackaudiosink,\n");
printf(" osssink,oss4sink,osxaudiosink,wasapisink,directsoundsink.\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," -rpifb was equivalent to \"-v4l2 -vs kmssink\"\n");
fprintf(stderr," -rpigl was equivalent to \"-v4l2 -vs glimagesink\"\n"); fprintf(stderr," -rpigl was equivalent to \"-v4l2 -vs glimagesink\"\n");
fprintf(stderr," -rpiwl was equivalent to \"-v4l2 -vs waylandsink\"\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); exit(1);
} else if (arg == "-fs" ) { } else if (arg == "-fs" ) {
fullscreen = true; fullscreen = true;
@@ -1078,6 +1088,15 @@ static void parse_arguments (int argc, char *argv[]) {
} }
} else if (arg == "-bt709") { } else if (arg == "-bt709") {
bt709_fix = true; 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") { } else if (arg == "-nohold") {
nohold = 1; nohold = 1;
} else if (arg == "-al") { } else if (arg == "-al") {
@@ -2170,6 +2189,12 @@ int main (int argc, char *argv[]) {
video_parser.append(BT709_FIX); 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 (require_password && registration_list) {
if (pairing_register == "") { if (pairing_register == "") {
const char * homedir = get_homedir(); const char * homedir = get_homedir();