From 13af0eb587de630b3102ccf929b53726e34eb3c1 Mon Sep 17 00:00:00 2001 From: Brad Hards Date: Thu, 9 Nov 2023 20:53:33 +1100 Subject: [PATCH 01/11] uncompressed: fix component type validity check --- libheif/uncompressed_image.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libheif/uncompressed_image.cc b/libheif/uncompressed_image.cc index a0387b6c80..5218165b23 100644 --- a/libheif/uncompressed_image.cc +++ b/libheif/uncompressed_image.cc @@ -48,7 +48,8 @@ enum heif_uncompressed_component_type component_type_cyan = 13, component_type_magenta = 14, component_type_yellow = 15, - component_type_key_black = 16 + component_type_key_black = 16, + component_type_max_valid = component_type_key_black }; bool is_predefined_component_type(uint16_t type) @@ -467,8 +468,10 @@ static Error get_heif_chroma_uncompressed(std::shared_ptr& uncC, std:: uint16_t component_index = component.component_index; uint16_t component_type = cmpd->get_components()[component_index].component_type; - if (component_type >= 16) { - return { heif_error_Unsupported_feature, heif_suberror_Invalid_parameter_value, "a component_type >= 16 is not supported"}; + if (component_type > component_type_max_valid) { + std::stringstream sstr; + sstr << "a component_type > " << component_type_max_valid << " is not supported"; + return { heif_error_Unsupported_feature, heif_suberror_Invalid_parameter_value, sstr.str()}; } componentSet |= (1 << component_type); From b9aad15c6a9f06a5986728b1481549c452c3cc7e Mon Sep 17 00:00:00 2001 From: DarthSim Date: Tue, 14 Nov 2023 23:01:03 +0300 Subject: [PATCH 02/11] kvaazar: set chroma in kvazaar_query_input_colorspace2 --- libheif/plugins/encoder_kvazaar.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libheif/plugins/encoder_kvazaar.cc b/libheif/plugins/encoder_kvazaar.cc index 81173ec640..e12fdb57a5 100644 --- a/libheif/plugins/encoder_kvazaar.cc +++ b/libheif/plugins/encoder_kvazaar.cc @@ -302,7 +302,11 @@ static void kvazaar_query_input_colorspace2(void* encoder_raw, heif_colorspace* } else { *colorspace = heif_colorspace_YCbCr; - //*chroma = encoder->chroma; + if (*chroma != heif_chroma_420 && + *chroma != heif_chroma_422 && + *chroma != heif_chroma_444) { + *chroma = heif_chroma_420; + } } } From 0907279ea7f8b82d723b76421455d05660d0e71f Mon Sep 17 00:00:00 2001 From: Dirk Farin Date: Tue, 14 Nov 2023 22:12:19 +0100 Subject: [PATCH 03/11] fix kvazaar encoding with odd image sizes (see #1037) --- libheif/context.cc | 14 ++++++++ libheif/plugins/encoder_kvazaar.cc | 55 +++++++++++++++++++++++------- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/libheif/context.cc b/libheif/context.cc index 6140c92174..0033031259 100644 --- a/libheif/context.cc +++ b/libheif/context.cc @@ -2553,6 +2553,20 @@ Error HeifContext::encode_image_as_hevc(const std::shared_ptr& i heif_suberror_Invalid_image_size); } + if (encoder->plugin->plugin_api_version >= 3 && + encoder->plugin->query_encoded_size != nullptr) { + uint32_t check_encoded_width = input_width, check_encoded_height = input_height; + + encoder->plugin->query_encoded_size(encoder->encoder, + input_width, input_height, + &check_encoded_width, + &check_encoded_height); + + assert((int)check_encoded_width == encoded_width); + assert((int)check_encoded_height == encoded_height); + } + + // Note: 'ispe' must be before the transformation properties m_heif_file->add_ispe_property(image_id, encoded_width, encoded_height); diff --git a/libheif/plugins/encoder_kvazaar.cc b/libheif/plugins/encoder_kvazaar.cc index e12fdb57a5..344fd640bc 100644 --- a/libheif/plugins/encoder_kvazaar.cc +++ b/libheif/plugins/encoder_kvazaar.cc @@ -310,6 +310,14 @@ static void kvazaar_query_input_colorspace2(void* encoder_raw, heif_colorspace* } } +void kvazaar_query_encoded_size(void* encoder_raw, uint32_t input_width, uint32_t input_height, + uint32_t* encoded_width, uint32_t* encoded_height) +{ + *encoded_width = (input_width + 7) & ~0x7; + *encoded_height = (input_height + 7) & ~0x7; +} + + #if 0 static int rounded_size(int s) { @@ -339,10 +347,15 @@ static void append_chunk_data(kvz_data_chunk* data, std::vector& out) } -static void copy_plane(kvz_pixel* out_p, uint32_t out_stride, const uint8_t* in_p, uint32_t in_stride, int w, int h) +static void copy_plane(kvz_pixel* out_p, uint32_t out_stride, const uint8_t* in_p, uint32_t in_stride, int w, int h, int padded_width, int padded_height) { - for (int y = 0; y < h; y++) { - memcpy(out_p + y * out_stride, in_p + y * in_stride, w); + for (int y = 0; y < padded_height; y++) { + int sy = std::min(y, h - 1); // source y + memcpy(out_p + y * out_stride, in_p + sy * in_stride, w); + + if (padded_width > w) { + memset(out_p + y * out_stride + w, *(in_p + sy * in_stride + w - 1), padded_width - w); + } } } @@ -431,6 +444,14 @@ static struct heif_error kvazaar_encode_image(void* encoder_raw, const struct he (void) ctu; #endif + int input_width = heif_image_get_width(image, heif_channel_Y); + int input_height = heif_image_get_height(image, heif_channel_Y); + int input_chroma_width = 0; + int input_chroma_height = 0; + + uint32_t encoded_width, encoded_height; + kvazaar_query_encoded_size(encoder_raw, input_width, input_height, &encoded_width, &encoded_height); + kvz_chroma_format kvzChroma; int chroma_stride_shift = 0; int chroma_height_shift = 0; @@ -444,18 +465,24 @@ static struct heif_error kvazaar_encode_image(void* encoder_raw, const struct he kvzChroma = KVZ_CSP_420; chroma_stride_shift = 1; chroma_height_shift = 1; + input_chroma_width = (input_width + 1) / 2; + input_chroma_height = (input_height + 1) / 2; } else if (chroma == heif_chroma_422) { config->input_format = KVZ_FORMAT_P422; kvzChroma = KVZ_CSP_422; chroma_stride_shift = 1; chroma_height_shift = 0; + input_chroma_width = (input_width + 1) / 2; + input_chroma_height = input_height; } else if (chroma == heif_chroma_444) { config->input_format = KVZ_FORMAT_P444; kvzChroma = KVZ_CSP_444; chroma_stride_shift = 0; chroma_height_shift = 0; + input_chroma_width = input_width; + input_chroma_height = input_height; } if (chroma != heif_chroma_monochrome) { @@ -472,7 +499,6 @@ static struct heif_error kvazaar_encode_image(void* encoder_raw, const struct he (void) h; } - struct heif_color_profile_nclx* nclx = nullptr; heif_error err = heif_image_get_nclx_color_profile(image, &nclx); if (err.code != heif_error_Ok) { @@ -500,8 +526,8 @@ static struct heif_error kvazaar_encode_image(void* encoder_raw, const struct he config->qp = ((100 - encoder->quality) * 51 + 50) / 100; config->lossless = encoder->lossless ? 1 : 0; - config->width = heif_image_get_width(image, heif_channel_Y); - config->height = heif_image_get_height(image, heif_channel_Y); + config->width = encoded_width; + config->height = encoded_height; // Note: it is ok to cast away the const, as the image content is not changed. // However, we have to guarantee that there are no plane pointers or stride values kept over calling the svt_encode_image() function. @@ -514,7 +540,7 @@ static struct heif_error kvazaar_encode_image(void* encoder_raw, const struct he } */ - kvz_picture* pic = api->picture_alloc_csp(kvzChroma, config->width, config->height); + kvz_picture* pic = api->picture_alloc_csp(kvzChroma, encoded_width, encoded_height); if (!pic) { api->config_destroy(config); return heif_error{ @@ -528,20 +554,22 @@ static struct heif_error kvazaar_encode_image(void* encoder_raw, const struct he int stride; const uint8_t* data = heif_image_get_plane_readonly(image, heif_channel_Y, &stride); - copy_plane(pic->y, pic->stride, data, stride, config->width, config->height); + copy_plane(pic->y, pic->stride, data, stride, input_width, input_height, encoded_width, encoded_height); } else { int stride; const uint8_t* data; data = heif_image_get_plane_readonly(image, heif_channel_Y, &stride); - copy_plane(pic->y, pic->stride, data, stride, config->width, config->height); + copy_plane(pic->y, pic->stride, data, stride, input_width, input_height, encoded_width, encoded_height); data = heif_image_get_plane_readonly(image, heif_channel_Cb, &stride); - copy_plane(pic->u, pic->stride >> chroma_stride_shift, data, stride, config->width >> chroma_stride_shift, config->height >> chroma_height_shift); + copy_plane(pic->u, pic->stride >> chroma_stride_shift, data, stride, input_chroma_width, input_chroma_height, + encoded_width >> chroma_stride_shift, encoded_height >> chroma_height_shift); data = heif_image_get_plane_readonly(image, heif_channel_Cr, &stride); - copy_plane(pic->v, pic->stride >> chroma_stride_shift, data, stride, config->width >> chroma_stride_shift, config->height >> chroma_height_shift); + copy_plane(pic->v, pic->stride >> chroma_stride_shift, data, stride, input_chroma_width, input_chroma_height, + encoded_width >> chroma_stride_shift, encoded_height >> chroma_height_shift); } kvz_encoder* kvzencoder = api->encoder_open(config); @@ -675,7 +703,7 @@ static struct heif_error kvazaar_get_compressed_data(void* encoder_raw, uint8_t* static const struct heif_encoder_plugin encoder_plugin_kvazaar { - /* plugin_api_version */ 2, + /* plugin_api_version */ 3, /* compression_format */ heif_compression_HEVC, /* id_name */ "kvazaar", /* priority */ kvazaar_PLUGIN_PRIORITY, @@ -702,7 +730,8 @@ static const struct heif_encoder_plugin encoder_plugin_kvazaar /* query_input_colorspace */ kvazaar_query_input_colorspace, /* encode_image */ kvazaar_encode_image, /* get_compressed_data */ kvazaar_get_compressed_data, - /* query_input_colorspace (v2) */ kvazaar_query_input_colorspace2 + /* query_input_colorspace (v2) */ kvazaar_query_input_colorspace2, + /* query_encoded_size (v3) */ kvazaar_query_encoded_size }; const struct heif_encoder_plugin* get_encoder_plugin_kvazaar() From 45ca80fa615549477737250c632d05c0b2c1f46a Mon Sep 17 00:00:00 2001 From: Dirk Farin Date: Tue, 14 Nov 2023 22:14:38 +0100 Subject: [PATCH 04/11] add missing include and remove superfluous include --- libheif/plugins/encoder_kvazaar.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libheif/plugins/encoder_kvazaar.cc b/libheif/plugins/encoder_kvazaar.cc index 344fd640bc..1a39e2fb2e 100644 --- a/libheif/plugins/encoder_kvazaar.cc +++ b/libheif/plugins/encoder_kvazaar.cc @@ -22,10 +22,10 @@ #include "libheif/heif_plugin.h" #include "encoder_kvazaar.h" #include -#include #include #include #include +#include extern "C" { #include From 37ffc779354ceaa7c9be3c6ac730084744701278 Mon Sep 17 00:00:00 2001 From: Dirk Farin Date: Tue, 14 Nov 2023 22:16:26 +0100 Subject: [PATCH 05/11] fix cpplint false positive --- libheif/plugins/encoder_kvazaar.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/libheif/plugins/encoder_kvazaar.cc b/libheif/plugins/encoder_kvazaar.cc index 1a39e2fb2e..bda1c001b7 100644 --- a/libheif/plugins/encoder_kvazaar.cc +++ b/libheif/plugins/encoder_kvazaar.cc @@ -22,6 +22,7 @@ #include "libheif/heif_plugin.h" #include "encoder_kvazaar.h" #include +#include // apparently, this is a false positive of cpplint #include #include #include From 060b55c93ef2338998bf8bcc542421d9f5fd99fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milo=C5=A1=20Komar=C4=8Devi=C4=87?= <4973094+kmilos@users.noreply.github.com> Date: Wed, 15 Nov 2023 15:51:34 +0100 Subject: [PATCH 06/11] CMake: install thumbnailer only when binary is built --- gnome/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gnome/CMakeLists.txt b/gnome/CMakeLists.txt index fc38555df5..538c6f2ee7 100644 --- a/gnome/CMakeLists.txt +++ b/gnome/CMakeLists.txt @@ -1 +1,3 @@ -install(FILES heif.thumbnailer DESTINATION ${CMAKE_INSTALL_DATADIR}/thumbnailers) +if(WITH_EXAMPLES AND TARGET PNG::PNG) + install(FILES heif.thumbnailer DESTINATION ${CMAKE_INSTALL_DATADIR}/thumbnailers) +endif() From 0106add3fc858c9cf0dad5369de21be37e3cb684 Mon Sep 17 00:00:00 2001 From: Dirk Farin Date: Mon, 20 Nov 2023 19:11:31 +0100 Subject: [PATCH 07/11] increase version to v1.17.4 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 19ca2eb533..d2288dabe7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required (VERSION 3.16.3) # Oldest Ubuntu LTS (20.04 currently) -project(libheif LANGUAGES C CXX VERSION 1.17.3) +project(libheif LANGUAGES C CXX VERSION 1.17.4) # compatibility_version is never allowed to be decreased for any specific SONAME. # Libtool in the libheif-1.15.1 release had set it to 17.0.0, so we have to use this for the v1.x.y versions. From 907c8bd0e8621c4f81ebdd3c8f550cb6c1feee1c Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Tue, 21 Nov 2023 09:33:47 +0100 Subject: [PATCH 08/11] Fix installing Gnome files if examples are build. Regression was introduced in 060b55c93ef2338998bf8bcc542421d9f5fd99fd. --- gnome/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnome/CMakeLists.txt b/gnome/CMakeLists.txt index 538c6f2ee7..c1768cf2ee 100644 --- a/gnome/CMakeLists.txt +++ b/gnome/CMakeLists.txt @@ -1,3 +1,3 @@ -if(WITH_EXAMPLES AND TARGET PNG::PNG) +if(TARGET heif-thumbnailer) install(FILES heif.thumbnailer DESTINATION ${CMAKE_INSTALL_DATADIR}/thumbnailers) endif() From 82219b903001305fd916874a29dd372d92927d48 Mon Sep 17 00:00:00 2001 From: Dirk Farin Date: Tue, 21 Nov 2023 10:34:52 +0100 Subject: [PATCH 09/11] increase version to v1.17.5 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d2288dabe7..fbfd99e79a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required (VERSION 3.16.3) # Oldest Ubuntu LTS (20.04 currently) -project(libheif LANGUAGES C CXX VERSION 1.17.4) +project(libheif LANGUAGES C CXX VERSION 1.17.5) # compatibility_version is never allowed to be decreased for any specific SONAME. # Libtool in the libheif-1.15.1 release had set it to 17.0.0, so we have to use this for the v1.x.y versions. From bced6d0f185cce82a781286941e6b3897f36a506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Koci=C4=87?= Date: Tue, 21 Nov 2023 21:44:23 +0100 Subject: [PATCH 10/11] doc: fix ffmpeg codec name in README.md Commit 4a817ab changed the name of the plugin, but README was not updated accordingly. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b85bf7fa4a..faf4d9f387 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,7 @@ For each codec, there are two configuration variables: * `WITH_{codec}_PLUGIN`: when enabled, the codec is compiled as a separate plugin. In order to use dynamic plugins, also make sure that `ENABLE_PLUGIN_LOADING` is enabled. -The placeholder `{codec}` can have these values: `LIBDE265`, `X265`, `AOM_DECODER`, `AOM_ENCODER`, `SvtEnc`, `DAV1D`, `FFMPEG_HEVC_DECODER`, `JPEG_DECODER`, `JPEG_ENCODER`, `KVAZAAR`, `OpenJPEG_DECODER`, `OpenJPEG_ENCODER`. +The placeholder `{codec}` can have these values: `LIBDE265`, `X265`, `AOM_DECODER`, `AOM_ENCODER`, `SvtEnc`, `DAV1D`, `FFMPEG_DECODER`, `JPEG_DECODER`, `JPEG_ENCODER`, `KVAZAAR`, `OpenJPEG_DECODER`, `OpenJPEG_ENCODER`. Further options are: From 2bf226a300951e6897ee7267d0dd379ba5ad7287 Mon Sep 17 00:00:00 2001 From: Brad Hards Date: Thu, 30 Nov 2023 19:55:18 +1100 Subject: [PATCH 11/11] uncompressed: protect against broken uncC box component references --- libheif/uncompressed_image.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libheif/uncompressed_image.cc b/libheif/uncompressed_image.cc index 5218165b23..c91e5dba4f 100644 --- a/libheif/uncompressed_image.cc +++ b/libheif/uncompressed_image.cc @@ -534,6 +534,9 @@ int UncompressedImageCodec::get_luma_bits_per_pixel_from_configuration_unci(cons int alternate_channel_bits = 0; for (Box_uncC::Component component : uncC_box->get_components()) { uint16_t component_index = component.component_index; + if (component_index >= cmpd_box->get_components().size()) { + return -1; + } auto component_type = cmpd_box->get_components()[component_index].component_type; switch (component_type) { case component_type_monochrome: