From 453a55cba2c12b9e0d7b5bd41eb46ac8256ed6b0 Mon Sep 17 00:00:00 2001 From: Dirk Farin Date: Thu, 2 Nov 2023 17:57:10 +0100 Subject: [PATCH 1/6] fix returning version number parts (#1023) --- libheif/heif.cc | 11 +++-------- libheif/heif.h | 11 +++++------ 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/libheif/heif.cc b/libheif/heif.cc index 6f7f614989..373fd9971a 100644 --- a/libheif/heif.cc +++ b/libheif/heif.cc @@ -83,24 +83,19 @@ uint32_t heif_get_version_number(void) return (LIBHEIF_NUMERIC_VERSION); } -static uint8_t bcd2dec(uint8_t v) -{ - return uint8_t((v >> 4) * 10 + (v & 0x0F)); -} - int heif_get_version_number_major(void) { - return bcd2dec(((LIBHEIF_NUMERIC_VERSION) >> 24) & 0xFF); + return ((LIBHEIF_NUMERIC_VERSION) >> 24) & 0xFF; } int heif_get_version_number_minor(void) { - return bcd2dec(((LIBHEIF_NUMERIC_VERSION) >> 16) & 0xFF); + return ((LIBHEIF_NUMERIC_VERSION) >> 16) & 0xFF; } int heif_get_version_number_maintenance(void) { - return bcd2dec(((LIBHEIF_NUMERIC_VERSION) >> 8) & 0xFF); + return ((LIBHEIF_NUMERIC_VERSION) >> 8) & 0xFF; } diff --git a/libheif/heif.h b/libheif/heif.h index 0c25f5eada..71c325644f 100644 --- a/libheif/heif.h +++ b/libheif/heif.h @@ -77,19 +77,18 @@ extern "C" { // Version string of linked libheif library. LIBHEIF_API const char* heif_get_version(void); -// Numeric version of linked libheif library, encoded as BCD 0xHHMMLL00 = HH.MM.LL. -// For example: 0x02143000 is version 2.14.30 +// Numeric version of linked libheif library, encoded as 0xHHMMLL00 = hh.mm.ll, where hh, mm, ll is the decimal representation of HH, MM, LL. +// For example: 0x02150300 is version 2.21.3 LIBHEIF_API uint32_t heif_get_version_number(void); -// Numeric part "HH" from above. Returned as a decimal number (not BCD). +// Numeric part "HH" from above. Returned as a decimal number. LIBHEIF_API int heif_get_version_number_major(void); -// Numeric part "MM" from above. Returned as a decimal number (not BCD). +// Numeric part "MM" from above. Returned as a decimal number. LIBHEIF_API int heif_get_version_number_minor(void); -// Numeric part "LL" from above. Returned as a decimal number (not BCD). +// Numeric part "LL" from above. Returned as a decimal number. LIBHEIF_API int heif_get_version_number_maintenance(void); // Helper macros to check for given versions of libheif at compile time. -// Note: h, m, l should be 2-digit BCD numbers. I.e., decimal 17 = 0x17 (BCD) #define LIBHEIF_MAKE_VERSION(h, m, l) ((h) << 24 | (m) << 16 | (l) << 8) #define LIBHEIF_HAVE_VERSION(h, m, l) (LIBHEIF_NUMERIC_VERSION >= LIBHEIF_MAKE_VERSION(h, m, l)) From ec60415870d6cee6587f84d5bdcab27f98cab611 Mon Sep 17 00:00:00 2001 From: Dirk Farin Date: Fri, 3 Nov 2023 14:52:11 +0100 Subject: [PATCH 2/6] fix wrong orientation processing for 4 / 7 (#1026) --- libheif/file.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libheif/file.cc b/libheif/file.cc index 6de322bfdf..20ad689f8a 100644 --- a/libheif/file.cc +++ b/libheif/file.cc @@ -1013,7 +1013,7 @@ void HeifFile::add_orientation_properties(heif_item_id id, heif_orientation orie rotation_ccw = 180; break; case heif_orientation_flip_vertically: - mirror = heif_transform_mirror_direction_horizontal; + mirror = heif_transform_mirror_direction_vertical; has_mirror = true; break; case heif_orientation_rotate_90_cw_then_flip_horizontally: @@ -1026,7 +1026,7 @@ void HeifFile::add_orientation_properties(heif_item_id id, heif_orientation orie break; case heif_orientation_rotate_90_cw_then_flip_vertically: rotation_ccw = 270; - mirror = heif_transform_mirror_direction_horizontal; + mirror = heif_transform_mirror_direction_vertical; has_mirror = true; break; case heif_orientation_rotate_270_cw: From 2e59bafcbfad0aeb962cf1541f181f8f6c920050 Mon Sep 17 00:00:00 2001 From: Brad Hards Date: Fri, 3 Nov 2023 13:59:18 +1100 Subject: [PATCH 3/6] doc: minor api documentation cleanups --- libheif/Doxyfile.in | 5 +++-- libheif/heif.h | 46 ++++++++++++++++++++++++++---------------- libheif/heif_regions.h | 2 +- 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/libheif/Doxyfile.in b/libheif/Doxyfile.in index b56ab9b90d..0f98f68e1a 100644 --- a/libheif/Doxyfile.in +++ b/libheif/Doxyfile.in @@ -170,7 +170,7 @@ FULL_PATH_NAMES = YES # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. -STRIP_FROM_PATH = +STRIP_FROM_PATH = @CMAKE_CURRENT_SOURCE_DIR@ # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which @@ -864,7 +864,8 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = @CMAKE_CURRENT_SOURCE_DIR@/libheif/heif.h +INPUT = @CMAKE_CURRENT_SOURCE_DIR@/libheif/heif.h \ +@CMAKE_CURRENT_SOURCE_DIR@/libheif/heif_regions.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/libheif/heif.h b/libheif/heif.h index 71c325644f..eda62cd60a 100644 --- a/libheif/heif.h +++ b/libheif/heif.h @@ -391,7 +391,7 @@ enum heif_compression_format */ heif_compression_EVC = 6, /** - * JPEG 2000 compression. (Currently unused in libheif.) + * JPEG 2000 compression. * * The encapsulation of JPEG 2000 is specified in ISO/IEC 15444-16:2021. * The core encoding is defined in ISO/IEC 15444-1, or ITU-T T.800. @@ -400,7 +400,7 @@ enum heif_compression_format /** * Uncompressed encoding. * - * This is defined in ISO/IEC 23001-17:2023 (Draft International Standard). + * This is defined in ISO/IEC 23001-17:2023 (Final Draft International Standard). */ heif_compression_uncompressed = 8, /** @@ -478,24 +478,36 @@ struct heif_init_params }; -// You should call heif_init() when you start using libheif and heif_deinit() when you are finished. -// These calls are reference counted. Each call to heif_init() should be matched by one call to heif_deinit(). -// -// For backwards compatibility, it is not really necessary to call heif_init(), but some library memory objects -// will never be freed if you do not call heif_init()/heif_deinit(). -// -// heif_init() will load the external modules installed in the default plugin path. Thus, you need it when you -// want to load external plugins from the default path. -// Codec plugins that are compiled into the library directly (selected by the compile-time parameters of libheif) -// will be available even without heif_init(). -// -// Make sure that you don't have one part of your program use heif_init()/heif_deinit() and another part that doesn't -// use it as the latter may try to use an uninitialized library. If in doubt, enclose everything with init/deinit. - -// You may pass nullptr to get default parameters. Currently, no parameters are supported. +/** + * Initialise library. + * + * You should call heif_init() when you start using libheif and heif_deinit() when you are finished. + * These calls are reference counted. Each call to heif_init() should be matched by one call to heif_deinit(). + * + * For backwards compatibility, it is not really necessary to call heif_init(), but some library memory objects + * will never be freed if you do not call heif_init()/heif_deinit(). + * + * heif_init() will load the external modules installed in the default plugin path. Thus, you need it when you + * want to load external plugins from the default path. + * Codec plugins that are compiled into the library directly (selected by the compile-time parameters of libheif) + * will be available even without heif_init(). + * + * Make sure that you do not have one part of your program use heif_init()/heif_deinit() and another part that does + * not use it as the latter may try to use an uninitialized library. If in doubt, enclose everything with init/deinit. + * + * You may pass nullptr to get default parameters. Currently, no parameters are supported. + */ LIBHEIF_API struct heif_error heif_init(struct heif_init_params*); +/** + * Deinitialise and clean up library. + * + * You should call heif_init() when you start using libheif and heif_deinit() when you are finished. + * These calls are reference counted. Each call to heif_init() should be matched by one call to heif_deinit(). + * + * \sa heif_init() + */ LIBHEIF_API void heif_deinit(void); diff --git a/libheif/heif_regions.h b/libheif/heif_regions.h index 86733392b3..63083fba2a 100644 --- a/libheif/heif_regions.h +++ b/libheif/heif_regions.h @@ -506,7 +506,7 @@ struct heif_error heif_region_get_polyline_points(const struct heif_region* regi * The points are provided as pairs of X,Y coordinates, in the order X1, * Y1, X2, Y2, ..., Xn, Yn. * - * @param region the region to equery, which must be of type #heif_region_type_polyline + * @param region the region to query, which must be of type #heif_region_type_polyline * @param image_id the identifier for the image to transform / scale the region to * @param out_pts_array the array to return the points in, which must have twice as many entries as there are points * in the polyline. From 54074b7cac382a6f3af4a4c0eb452efc1b01c0c1 Mon Sep 17 00:00:00 2001 From: Dirk Farin Date: Fri, 3 Nov 2023 14:53:35 +0100 Subject: [PATCH 4/6] increase version to v1.17.3 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d7f2f4ae9..19ca2eb533 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.2) +project(libheif LANGUAGES C CXX VERSION 1.17.3) # 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 19865ce8a2d3abd4b1c929a7f4c0d7aec0cff5c9 Mon Sep 17 00:00:00 2001 From: Dirk Farin Date: Sat, 4 Nov 2023 10:46:17 +0100 Subject: [PATCH 5/6] check valid range of depth-representation SEI (ClusterFuzz 63848) --- libheif/error.h | 10 ++++++++++ libheif/hevc.cc | 29 ++++++++++++++++++++++------- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/libheif/error.h b/libheif/error.h index 75769b315e..af2af88f07 100644 --- a/libheif/error.h +++ b/libheif/error.h @@ -104,4 +104,14 @@ inline std::ostream& operator<<(std::ostream& ostr, const Error& err) return ostr; } + +template class Result +{ +public: + operator bool() const { return error.error_code == heif_error_Ok; } + + T value; + Error error; +}; + #endif diff --git a/libheif/hevc.cc b/libheif/hevc.cc index 4abbaa6c4e..4c23510a22 100644 --- a/libheif/hevc.cc +++ b/libheif/hevc.cc @@ -20,6 +20,7 @@ #include "hevc.h" #include "bitstream.h" +#include "error.h" #include #include @@ -346,8 +347,10 @@ static double read_depth_rep_info_element(BitReader& reader) } -static std::shared_ptr read_depth_representation_info(BitReader& reader) +static Result> read_depth_representation_info(BitReader& reader) { + Result> result; + auto msg = std::make_shared(); @@ -369,9 +372,15 @@ static std::shared_ptr read_depth_representation_info(BitReader& rea int rep_type; if (!reader.get_uvlc(&rep_type)) { - // TODO error + result.error = {heif_error_Invalid_input, heif_suberror_Invalid_parameter_value, "invalid depth representation type in input"}; + return result; + } + + if (rep_type < 0 || rep_type > 3) { + result.error = {heif_error_Invalid_input, heif_suberror_Invalid_parameter_value, "input depth representation type out of range"}; + return result; } - // TODO: check rep_type range + msg->depth_representation_type = (enum heif_depth_representation_type) rep_type; //printf("flags: %d %d %d %d\n",msg->has_z_near,msg->has_z_far,msg->has_d_min,msg->has_d_max); @@ -380,7 +389,8 @@ static std::shared_ptr read_depth_representation_info(BitReader& rea if (msg->has_d_min || msg->has_d_max) { int ref_view; if (!reader.get_uvlc(&ref_view)) { - // TODO error + result.error = {heif_error_Invalid_input, heif_suberror_Invalid_parameter_value, "invalid disparity_reference_view in input"}; + return result; } msg->disparity_reference_view = ref_view; @@ -403,7 +413,8 @@ static std::shared_ptr read_depth_representation_info(BitReader& rea // TODO: load non-uniform response curve } - return msg; + result.value = msg; + return result; } @@ -444,8 +455,12 @@ Error decode_hevc_aux_sei_messages(const std::vector& data, switch (payload_id) { case 177: // depth_representation_info - std::shared_ptr sei = read_depth_representation_info(sei_reader); - msgs.push_back(sei); + Result> seiResult = read_depth_representation_info(sei_reader); + if (seiResult.error) { + return seiResult.error; + } + + msgs.push_back(seiResult.value); break; } } From 6bc066bf067fce6ce209953515238f8c0b1b8ad2 Mon Sep 17 00:00:00 2001 From: dukesook Date: Tue, 7 Nov 2023 14:31:44 -0700 Subject: [PATCH 6/6] get and add uuid property --- libheif/box.cc | 6 ++- libheif/box.h | 8 +++- libheif/heif_properties.cc | 88 ++++++++++++++++++++++++++++++++++++++ libheif/heif_properties.h | 28 +++++++++++- 4 files changed, 127 insertions(+), 3 deletions(-) diff --git a/libheif/box.cc b/libheif/box.cc index e752ac4807..f35b602cd1 100644 --- a/libheif/box.cc +++ b/libheif/box.cc @@ -391,7 +391,11 @@ Error Box::parse(BitstreamRange& range) } else { uint64_t content_size = get_box_size() - get_header_size(); - if (range.prepare_read(content_size)) { + if (get_short_type() == fourcc("uuid")) { + m_uuid_data.resize(content_size); + range.read(m_uuid_data.data(), content_size); + } + else if (range.prepare_read(content_size)) { if (content_size > MAX_BOX_SIZE) { return Error(heif_error_Invalid_input, heif_suberror_Invalid_box_size); diff --git a/libheif/box.h b/libheif/box.h index 3a651f6ea9..ba96fdf981 100644 --- a/libheif/box.h +++ b/libheif/box.h @@ -125,8 +125,13 @@ class BoxHeader std::string get_type_string() const; + std::vector get_uuid_data() const { return m_uuid_data; } + void set_short_type(uint32_t type) { m_type = type; } + void set_uuid_type(const std::vector& uuid_type) { m_uuid_type = uuid_type; } + + void set_uuid_data(const std::vector& uuid_data) { m_uuid_data = uuid_data; } Error parse_header(BitstreamRange& range); @@ -140,9 +145,10 @@ class BoxHeader uint64_t m_size = 0; uint32_t m_type = 0; - std::vector m_uuid_type; protected: + std::vector m_uuid_type; + std::vector m_uuid_data; uint32_t m_header_size = 0; }; diff --git a/libheif/heif_properties.cc b/libheif/heif_properties.cc index d73cea41ca..c185de6725 100644 --- a/libheif/heif_properties.cc +++ b/libheif/heif_properties.cc @@ -300,3 +300,91 @@ void heif_property_user_description_release(struct heif_property_user_descriptio delete udes; } + +struct heif_error heif_item_add_property_uuid(const struct heif_context* context, + heif_item_id itemId, + uint8_t* uuid_type, + uint8_t* data, size_t size, + heif_property_id* out_propertyId) +{ + if (!context || !uuid_type || !data) { + return {heif_error_Usage_error, heif_suberror_Null_pointer_argument, "NULL argument passed in"}; + } + + std::vector data_vector(data, data + size); + std::vector uuid_type_vector(uuid_type, uuid_type + 16); + + auto uuid_box = std::make_shared(); + uuid_box->set_uuid_type(uuid_type_vector); + uuid_box->set_uuid_data(data_vector); + + heif_property_id id = context->context->add_property(itemId, uuid_box, false); + + if (out_propertyId) { + *out_propertyId = id; + } + + return heif_error_success; +} + + +struct heif_error heif_item_get_property_uuid_size(const struct heif_context* context, + heif_item_id itemId, + heif_property_id propertyId, + size_t* size_out) +{ + auto file = context->context->get_heif_file(); if (!context || !size_out) { + return {heif_error_Usage_error, heif_suberror_Null_pointer_argument, "NULL argument passed in"}; + } + + std::vector> properties; + Error err = file->get_properties(itemId, properties); + if (err) { + return err.error_struct(context->context.get()); + } + + if (propertyId - 1 < 0 || propertyId - 1 >= properties.size()) { + return {heif_error_Usage_error, heif_suberror_Invalid_property, "property index out of range"}; + } + + auto uuid_box = properties[propertyId - 1]; + auto data = uuid_box->get_uuid_data(); + + *size_out = data.size(); + + return heif_error_success; +} + + +struct heif_error heif_item_get_property_uuid(const struct heif_context* context, + heif_item_id itemId, + heif_property_id propertyId, + uint8_t* data_out) +{ + if (!context || !data_out) { + return {heif_error_Usage_error, heif_suberror_Null_pointer_argument, "NULL argument passed in"}; + } + + auto file = context->context->get_heif_file(); + + std::vector> properties; + Error err = file->get_properties(itemId, properties); + if (err) { + return err.error_struct(context->context.get()); + } + + if (propertyId - 1 < 0 || propertyId - 1 >= properties.size()) { + return {heif_error_Usage_error, heif_suberror_Invalid_property, "property index out of range"}; + } + + auto uuid_box = properties[propertyId - 1]; + auto data = uuid_box->get_uuid_data(); + + + + std::copy(data.begin(), data.end(), data_out); + + return heif_error_success; +} + + diff --git a/libheif/heif_properties.h b/libheif/heif_properties.h index 4ed15c8a90..d4d3429cef 100644 --- a/libheif/heif_properties.h +++ b/libheif/heif_properties.h @@ -37,7 +37,8 @@ enum heif_item_property_type heif_item_property_type_transform_mirror = heif_fourcc('i', 'm', 'i', 'r'), heif_item_property_type_transform_rotation = heif_fourcc('i', 'r', 'o', 't'), heif_item_property_type_transform_crop = heif_fourcc('c', 'l', 'a', 'p'), - heif_item_property_type_image_size = heif_fourcc('i', 's', 'p', 'e') + heif_item_property_type_image_size = heif_fourcc('i', 's', 'p', 'e'), + heif_item_property_type_uuid = heif_fourcc('u', 'u', 'i', 'd'), }; // Get the heif_property_id for a heif_item_id. @@ -131,6 +132,31 @@ void heif_item_get_property_transform_crop_borders(const struct heif_context* co int image_width, int image_height, int* left, int* top, int* right, int* bottom); + +LIBHEIF_API +struct heif_error heif_item_add_property_uuid(const struct heif_context* context, + heif_item_id itemId, + uint8_t* uuid_type, + uint8_t* data, size_t size, + heif_property_id* out_propertyId); + + +LIBHEIF_API +struct heif_error heif_item_get_property_uuid_size(const struct heif_context* context, + heif_item_id itemId, + heif_property_id propertyId, + size_t* size_out); + + +/** + * @param data_out User-supplied array. The size given by heif_item_get_property_uuid_size(). +*/ +LIBHEIF_API +struct heif_error heif_item_get_property_uuid(const struct heif_context* context, + heif_item_id itemId, + heif_property_id propertyId, + uint8_t* data_out); + #ifdef __cplusplus } #endif