From 85c0526fdb1147522911519126497bf27174fd5a Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Tue, 8 Oct 2024 12:51:56 +0200 Subject: [PATCH] decoder: added CS override opt for FF JPEGs FFmpeg encoded JPEGs with COM CS=ITU601 are limited-range BT.601. Allow override when the caller knows that it is actually limiee-range BT.709 as eg. UltraGrid does. --- CMakeLists.txt | 2 +- NEWS.md | 7 +++++-- libgpujpeg/gpujpeg_decoder.h | 2 ++ src/gpujpeg_decoder.c | 3 ++- src/gpujpeg_decoder_internal.h | 4 ++++ src/gpujpeg_reader.c | 22 ++++++++++++++-------- 6 files changed, 28 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c44b9419..b918699f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR) # change version also in configure.ac -project(gpujpeg VERSION 0.25.4 LANGUAGES C CUDA) +project(gpujpeg VERSION 0.25.5 LANGUAGES C CUDA) # options set(BUILD_OPENGL OFF CACHE STRING "Build with OpenGL support, options are: AUTO ON OFF") diff --git a/NEWS.md b/NEWS.md index b5081a08..c833be99 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,7 +1,10 @@ 2024-10-08 - 0.25.5 ---------- -- add gpujpeg_decoder_create_with_params() (+ struct +- added gpujpeg_decoder_create_with_params() (+ struct gpujpeg_decoder_init_parameters, gpujpeg_decoder_default_init_parameters()) +- added gpujpeg_decoder_init_parameters.ff_cs_itu601_is_709 flag to + override colorspace to limited 709 if FFmpeg-specific comment CS=ITU601 + is present (as 709 is used by UltraGrid) 2024-10-07 - 0.25.4 ---------- @@ -10,7 +13,7 @@ 2024-06-05 - 0.25.3 ---------- - added gpujpeg_color_space_by_name -- addeg gpujpeg_print_pixel_format +- added gpujpeg_print_pixel_format 2024-04-09 - 0.25.2 ---------- diff --git a/libgpujpeg/gpujpeg_decoder.h b/libgpujpeg/gpujpeg_decoder.h index d8d93d29..80072214 100644 --- a/libgpujpeg/gpujpeg_decoder.h +++ b/libgpujpeg/gpujpeg_decoder.h @@ -90,6 +90,8 @@ struct gpujpeg_decoder_init_parameters cudaStream_t stream; ///< stream CUDA stream to be used, cudaStreamDefault (0x00) is default int verbose; ///< verbosity level (-1 - quiet, 0 - normal, 1 - verbose) bool perf_stats; ///< print performance statistics on output + bool ff_cs_itu601_is_709; ///< if FFmpeg specific COM marker "CS=ITU601" present, interpret the data as + ///< limited-range BT.709 not BT.601 }; /** diff --git a/src/gpujpeg_decoder.c b/src/gpujpeg_decoder.c index d27c3fd3..f424eafc 100644 --- a/src/gpujpeg_decoder.c +++ b/src/gpujpeg_decoder.c @@ -157,7 +157,7 @@ gpujpeg_decoder_create(cudaStream_t stream) struct gpujpeg_decoder_init_parameters gpujpeg_decoder_default_init_parameters() { - return (struct gpujpeg_decoder_init_parameters){cudaStreamDefault, 0, false}; + return (struct gpujpeg_decoder_init_parameters){cudaStreamDefault, 0, false, false}; } /** * Create JPEG decoder @@ -174,6 +174,7 @@ gpujpeg_decoder_create_with_params(const struct gpujpeg_decoder_init_parameters } decoder->coder.param.verbose = params->verbose; decoder->coder.param.perf_stats = params->perf_stats; + decoder->ff_cs_itu601_is_709 = params->ff_cs_itu601_is_709; return decoder; } diff --git a/src/gpujpeg_decoder_internal.h b/src/gpujpeg_decoder_internal.h index 5f9bc6d4..693bdc7b 100644 --- a/src/gpujpeg_decoder_internal.h +++ b/src/gpujpeg_decoder_internal.h @@ -31,6 +31,8 @@ #ifndef GPUJPEG_DECODER_INTERNAL_H #define GPUJPEG_DECODER_INTERNAL_H +#include + #include "../libgpujpeg/gpujpeg_common.h" #include "gpujpeg_common_internal.h" #include "gpujpeg_table.h" @@ -68,6 +70,8 @@ struct gpujpeg_decoder enum gpujpeg_pixel_format req_pixel_format; enum gpujpeg_color_space req_color_space; + bool ff_cs_itu601_is_709; ///< if FFmpeg specific COM marker "CS=ITU601" present, interpret the data as + ///< limited-range BT.709 not BT.601 }; #endif // GPUJPEG_DECODER_INTERNAL_H diff --git a/src/gpujpeg_reader.c b/src/gpujpeg_reader.c index 877d2512..45383793 100644 --- a/src/gpujpeg_reader.c +++ b/src/gpujpeg_reader.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "../libgpujpeg/gpujpeg_decoder.h" #include "gpujpeg_decoder_internal.h" @@ -578,7 +579,8 @@ gpujpeg_reader_read_app14(uint8_t** image, const uint8_t* image_end, enum gpujpe } static int -gpujpeg_reader_read_com(uint8_t** image, const uint8_t* image_end, enum gpujpeg_color_space *color_space) +gpujpeg_reader_read_com(uint8_t** image, const uint8_t* image_end, bool ff_cs_itu601_is_709, + enum gpujpeg_color_space* color_space) { if(image_end - *image < 2) { fprintf(stderr, "[GPUJPEG] [Error] Could not read com length\n"); @@ -596,7 +598,7 @@ gpujpeg_reader_read_com(uint8_t** image, const uint8_t* image_end, enum gpujpeg_ const size_t com_length = length - 2; // check both with '\0' and without: if ( (com_length == sizeof cs_itu601 || com_length == sizeof cs_itu601 - 1) && strncmp((char*)*image, cs_itu601, com_length) == 0 ) { - *color_space = GPUJPEG_YCBCR_BT601; + *color_space = ff_cs_itu601_is_709 ? GPUJPEG_YCBCR_BT709 : GPUJPEG_YCBCR_BT601; } *image += length - 2; @@ -1232,7 +1234,9 @@ gpujpeg_reader_read_sos(struct gpujpeg_decoder* decoder, struct gpujpeg_reader* * @retval @ref Errors */ static int -gpujpeg_reader_read_common_markers(uint8_t **image, const uint8_t* image_end, int marker, int log_level, enum gpujpeg_color_space *color_space, int *restart_interval, _Bool *in_spiff) +gpujpeg_reader_read_common_markers(uint8_t** image, const uint8_t* image_end, int marker, int log_level, + bool ff_cs_itu601_is_709, enum gpujpeg_color_space* color_space, + int* restart_interval, bool* in_spiff) { int rc = 0; switch (marker) @@ -1310,7 +1314,7 @@ gpujpeg_reader_read_common_markers(uint8_t **image, const uint8_t* image_end, in return -1; case GPUJPEG_MARKER_COM: - if ( gpujpeg_reader_read_com(image, image_end, color_space) != 0 ) { + if ( gpujpeg_reader_read_com(image, image_end, ff_cs_itu601_is_709, color_space) != 0 ) { return -1; } break; @@ -1420,8 +1424,9 @@ gpujpeg_reader_read_image(struct gpujpeg_decoder* decoder, uint8_t* image, size_ } // Read more info according to the marker - int rc = gpujpeg_reader_read_common_markers(&image, image_end, marker, decoder->coder.param.verbose, &header_color_space, &reader.param.restart_interval, &in_spiff); - if (rc < 0) { + int rc = gpujpeg_reader_read_common_markers(&image, image_end, marker, decoder->coder.param.verbose, decoder->ff_cs_itu601_is_709, + &header_color_space, &reader.param.restart_interval, &in_spiff); + if ( rc < 0 ) { return rc; } if (rc == 0) { // already processed @@ -1547,8 +1552,9 @@ gpujpeg_reader_get_image_info(uint8_t *image, size_t image_size, struct gpujpeg_ } // Read more info according to the marker - int rc = gpujpeg_reader_read_common_markers(&image, image_end, marker, param->verbose, &header_color_space, ¶m->restart_interval, &in_spiff); - if (rc < 0) { + int rc = gpujpeg_reader_read_common_markers(&image, image_end, marker, param->verbose, false, + &header_color_space, ¶m->restart_interval, &in_spiff); + if ( rc < 0 ) { return rc; } if (rc == 0) { // already processed