From 9f1156a1e8ca62f2721ab08b118819b83e396366 Mon Sep 17 00:00:00 2001 From: Dirk Farin Date: Thu, 3 Oct 2024 00:09:49 +0200 Subject: [PATCH] decode HEVC through Decoder_HEVC --- libheif/box.cc | 12 +++++++----- libheif/box.h | 14 +++++++------- libheif/codecs/decoder.cc | 35 ++++++++++++++++++++++------------- libheif/codecs/decoder.h | 22 ++++++++++++++-------- libheif/codecs/hevc.cc | 8 +++++++- libheif/codecs/hevc.h | 2 ++ libheif/codecs/hevc_dec.h | 2 ++ libheif/codecs/image_item.cc | 24 +++++++----------------- libheif/codecs/image_item.h | 6 +++--- libheif/codecs/jpeg2000_dec.h | 2 ++ libheif/codecs/tild.cc | 7 ++++++- libheif/common_utils.h | 6 ++++++ 12 files changed, 85 insertions(+), 55 deletions(-) diff --git a/libheif/box.cc b/libheif/box.cc index f0b622cd1e..6a36380e8d 100644 --- a/libheif/box.cc +++ b/libheif/box.cc @@ -2075,6 +2075,8 @@ Error Box_infe::parse(BitstreamRange& range) m_content_encoding = range.read_string(); } + m_item_type_4cc = 0; + if (get_version() >= 2) { m_hidden_item = (get_flags() & 1); @@ -2086,17 +2088,17 @@ Error Box_infe::parse(BitstreamRange& range) } m_item_protection_index = range.read16(); - uint32_t item_type = range.read32(); - if (item_type != 0) { - m_item_type = to_fourcc(item_type); + m_item_type_4cc = range.read32(); + if (m_item_type_4cc != 0) { + m_item_type = to_fourcc(m_item_type_4cc); } m_item_name = range.read_string(); - if (item_type == fourcc("mime")) { + if (m_item_type_4cc == fourcc("mime")) { m_content_type = range.read_string(); m_content_encoding = range.read_string(); } - else if (item_type == fourcc("uri ")) { + else if (m_item_type_4cc == fourcc("uri ")) { m_item_uri_type = range.read_string(); } } diff --git a/libheif/box.h b/libheif/box.h index 73e7091c9c..6d07e0a219 100644 --- a/libheif/box.h +++ b/libheif/box.h @@ -45,11 +45,6 @@ #define HAS_BOOL_ARRAY 1 #endif -// abbreviation -constexpr inline uint32_t fourcc(const char* id) { return fourcc_to_uint32(id); } - -std::string to_fourcc(uint32_t code); - /* constexpr uint32_t fourcc(const char* string) { @@ -596,7 +591,11 @@ class Box_infe : public FullBox const std::string& get_item_type() const { return m_item_type; } - void set_item_type(const std::string& type) { m_item_type = type; } + uint32_t get_item_type_4cc() const { return m_item_type_4cc; } + + void set_item_type(const std::string& type) { m_item_type = type; m_item_type_4cc = fourcc_to_uint32(type.c_str()); } + + void set_item_type_4cc(uint32_t type) { m_item_type_4cc = type; m_item_type = to_fourcc(type); } void set_item_name(const std::string& name) { m_item_name = name; } @@ -625,7 +624,8 @@ class Box_infe : public FullBox heif_item_id m_item_ID = 0; uint16_t m_item_protection_index = 0; - std::string m_item_type; + uint32_t m_item_type_4cc = 0; + std::string m_item_type; // deprecated, prefer to use m_item_type_4cc std::string m_item_name; std::string m_content_type; std::string m_content_encoding; diff --git a/libheif/codecs/decoder.cc b/libheif/codecs/decoder.cc index b6e1c059cc..94d26d9778 100644 --- a/libheif/codecs/decoder.cc +++ b/libheif/codecs/decoder.cc @@ -30,10 +30,11 @@ #include -void DataExtent::set_from_image_item(class HeifFile* file, heif_item_id item) +void DataExtent::set_from_image_item(std::shared_ptr file, heif_item_id item) { - m_iloc = file->get_property(item); + m_file = file; m_item_id = item; + m_source = Source::Image; } @@ -42,9 +43,14 @@ Result*> DataExtent::read_data() const if (!m_raw.empty()) { return &m_raw; } - else if (m_iloc) { + else if (m_source == Source::Image) { + assert(m_file); + // image - m_iloc->read_data(m_item_id, m_file->get_reader(), nullptr, &m_raw, 0, std::numeric_limits::max()); + Error err = m_file->append_data_from_iloc(m_item_id, m_raw); + if (err) { + return err; + } } else { // sequence @@ -63,11 +69,11 @@ Result> DataExtent::read_data(uint64_t offset, uint64_t siz data.insert(data.begin(), m_raw.begin() + offset, m_raw.begin() + offset + size); return data; } - else if (m_iloc) { + else if (m_source == Source::Image) { // TODO: cache data // image - Error err = m_iloc->read_data(m_item_id, m_file->get_reader(), nullptr, &m_raw, 0, size); + Error err = m_file->append_data_from_iloc(m_item_id, m_raw, 0, size); if (err) { return err; } @@ -114,25 +120,23 @@ Result> Decoder::get_compressed_data() const std::vector data = confData.value; - // image data, usually from 'mdat' + // append image data Result dataResult = m_data_extent.read_data(); if (dataResult.error) { return dataResult.error; } - data.insert(data.begin(), dataResult.value->begin(), dataResult.value->end()); + data.insert(data.end(), dataResult.value->begin(), dataResult.value->end()); return data; } Result> -Decoder::decode_single_frame_from_compressed_data(heif_compression_format compression_format, - const struct heif_decoding_options& options, - const std::vector& data) +Decoder::decode_single_frame_from_compressed_data(const struct heif_decoding_options& options) { - const struct heif_decoder_plugin* decoder_plugin = get_decoder(compression_format, options.decoder_id); + const struct heif_decoder_plugin* decoder_plugin = get_decoder(get_compression_format(), options.decoder_id); if (!decoder_plugin) { return Error(heif_error_Plugin_loading_error, heif_suberror_No_matching_decoder_installed); } @@ -152,7 +156,12 @@ Decoder::decode_single_frame_from_compressed_data(heif_compression_format compre } } - err = decoder_plugin->push_data(decoder, data.data(), data.size()); + auto dataResult = get_compressed_data(); + if (dataResult.error) { + return dataResult.error; + } + + err = decoder_plugin->push_data(decoder, dataResult.value.data(), dataResult.value.size()); if (err.code != heif_error_Ok) { decoder_plugin->free_decoder(decoder); return Error(err.code, err.subcode, err.message); diff --git a/libheif/codecs/decoder.h b/libheif/codecs/decoder.h index 19c8750338..45a938c82d 100644 --- a/libheif/codecs/decoder.h +++ b/libheif/codecs/decoder.h @@ -39,18 +39,18 @@ struct DataExtent { std::shared_ptr m_file; + enum class Source : uint8_t { Raw, Image, Sequence } m_source = Source::Raw; // --- raw data mutable std::vector m_raw; // also for cached data // --- image - std::shared_ptr m_iloc; heif_item_id m_item_id = 0; // --- sequence // TODO - void set_from_image_item(class HeifFile* file, heif_item_id item); + void set_from_image_item(std::shared_ptr file, heif_item_id item); Result*> read_data() const; @@ -61,30 +61,36 @@ struct DataExtent class Decoder { public: + static std::shared_ptr alloc_for_compression_format(const HeifContext* ctx, heif_item_id, uint32_t format_4cc); + + virtual ~Decoder() = default; - static std::shared_ptr alloc_for_compression_format(const HeifContext* ctx, heif_item_id, uint32_t format_4cc); + virtual heif_compression_format get_compression_format() const = 0; void set_data_extent(DataExtent extent) { m_data_extent = std::move(extent); } + // --- information about the image format + [[nodiscard]] virtual int get_luma_bits_per_pixel() const = 0; [[nodiscard]] virtual int get_chroma_bits_per_pixel() const = 0; [[nodiscard]] virtual Error get_coded_image_colorspace(heif_colorspace*, heif_chroma*) const = 0; + // --- raw data access + [[nodiscard]] virtual Result> read_bitstream_configuration_data() const = 0; Result> get_compressed_data() const; - static Result> - decode_single_frame_from_compressed_data(heif_compression_format compression_format, - const struct heif_decoding_options& options, - const std::vector& data); + // --- decoding + + virtual Result> + decode_single_frame_from_compressed_data(const struct heif_decoding_options& options); private: DataExtent m_data_extent; }; - #endif diff --git a/libheif/codecs/hevc.cc b/libheif/codecs/hevc.cc index 3de4637cb6..bc4a00c750 100644 --- a/libheif/codecs/hevc.cc +++ b/libheif/codecs/hevc.cc @@ -651,7 +651,7 @@ Error ImageItem_HEVC::on_load_file() m_decoder = std::make_shared(hvcC_box); DataExtent extent; - extent.set_from_image_item(get_context()->get_heif_file().get(), get_id()); + extent.set_from_image_item(get_context()->get_heif_file(), get_id()); m_decoder->set_data_extent(extent); @@ -761,3 +761,9 @@ int ImageItem_HEVC::get_chroma_bits_per_pixel() const { return m_decoder->get_chroma_bits_per_pixel(); } + + +std::shared_ptr ImageItem_HEVC::get_decoder() const +{ + return m_decoder; +} diff --git a/libheif/codecs/hevc.h b/libheif/codecs/hevc.h index c389e13734..109f4a5a75 100644 --- a/libheif/codecs/hevc.h +++ b/libheif/codecs/hevc.h @@ -151,6 +151,8 @@ class ImageItem_HEVC : public ImageItem protected: Result> read_bitstream_configuration_data(heif_item_id itemId) const override; + std::shared_ptr get_decoder() const override; + private: std::shared_ptr m_decoder; }; diff --git a/libheif/codecs/hevc_dec.h b/libheif/codecs/hevc_dec.h index e978c60321..8d9030604f 100644 --- a/libheif/codecs/hevc_dec.h +++ b/libheif/codecs/hevc_dec.h @@ -39,6 +39,8 @@ class Decoder_HEVC : public Decoder public: Decoder_HEVC(const std::shared_ptr& hvcC) : m_hvcC(hvcC) {} + heif_compression_format get_compression_format() const override { return heif_compression_HEVC; } + int get_luma_bits_per_pixel() const override; int get_chroma_bits_per_pixel() const override; diff --git a/libheif/codecs/image_item.cc b/libheif/codecs/image_item.cc index 82decdd0e1..a91a03a491 100644 --- a/libheif/codecs/image_item.cc +++ b/libheif/codecs/image_item.cc @@ -64,13 +64,7 @@ bool HeifContext::is_image(heif_item_id ID) const } -std::shared_ptr ImageItem::get_file() -{ - return m_heif_context->get_heif_file(); -} - - -std::shared_ptr ImageItem::get_file() const +std::shared_ptr ImageItem::get_file() const { return m_heif_context->get_heif_file(); } @@ -1072,17 +1066,13 @@ Result> ImageItem::get_compressed_image_data() const Result> ImageItem::decode_compressed_image(const struct heif_decoding_options& options, bool decode_tile_only, uint32_t tile_x0, uint32_t tile_y0) const { - // --- find the decoder plugin with the correct compression format + DataExtent extent; + extent.set_from_image_item(get_file(), get_id()); - heif_compression_format compression_format = get_compression_format(); - if (compression_format == heif_compression_undefined) { - return Error{heif_error_Decoder_plugin_error, heif_suberror_Unsupported_codec, "Decoding not supported"}; - } + auto decoder = get_decoder(); + assert(decoder); - Result> dataResult = get_compressed_image_data(); - if (dataResult.error) { - return dataResult.error; - } + decoder->set_data_extent(std::move(extent)); - return Decoder::decode_single_frame_from_compressed_data(compression_format, options, *dataResult); + return decoder->decode_single_frame_from_compressed_data(options); } diff --git a/libheif/codecs/image_item.h b/libheif/codecs/image_item.h index dd7ebac6a5..3fe87ffd7e 100644 --- a/libheif/codecs/image_item.h +++ b/libheif/codecs/image_item.h @@ -91,9 +91,7 @@ class ImageItem : public ErrorBuffer const HeifContext* get_context() const { return m_heif_context; } - std::shared_ptr get_file(); - - std::shared_ptr get_file() const; + std::shared_ptr get_file() const; Error check_resolution(uint32_t w, uint32_t h) const; @@ -407,6 +405,8 @@ class ImageItem : public ErrorBuffer enum heif_image_input_class input_class, const heif_color_profile_nclx* target_heif_nclx, ImageItem::CodedImageData& inout_codedImage); + + virtual std::shared_ptr get_decoder() const { return nullptr; } }; diff --git a/libheif/codecs/jpeg2000_dec.h b/libheif/codecs/jpeg2000_dec.h index 578a07c2ac..f11e321b0b 100644 --- a/libheif/codecs/jpeg2000_dec.h +++ b/libheif/codecs/jpeg2000_dec.h @@ -39,6 +39,8 @@ class Decoder_JPEG2000 : public Decoder public: Decoder_JPEG2000(const std::shared_ptr& j2kH) : m_j2kH(j2kH) {} + heif_compression_format get_compression_format() const override { return heif_compression_JPEG2000; } + void set_data_extent(DataExtent extent) { m_data_extent = std::move(extent); } int get_luma_bits_per_pixel() const override; diff --git a/libheif/codecs/tild.cc b/libheif/codecs/tild.cc index 7e06b6a1ff..7ad936cefc 100644 --- a/libheif/codecs/tild.cc +++ b/libheif/codecs/tild.cc @@ -613,7 +613,12 @@ ImageItem_Tild::decode_grid_tile(const heif_decoding_options& options, uint32_t // --- decode - return Decoder::decode_single_frame_from_compressed_data(get_compression_format(), options, data); + DataExtent extent; + extent.m_raw = data; + + m_tile_decoder->set_data_extent(std::move(extent)); + + return m_tile_decoder->decode_single_frame_from_compressed_data(options); } diff --git a/libheif/common_utils.h b/libheif/common_utils.h index 07820070a1..c6f43c16aa 100644 --- a/libheif/common_utils.h +++ b/libheif/common_utils.h @@ -23,6 +23,7 @@ #include #include "libheif/heif.h" +#include #ifdef _MSC_VER #define MAYBE_UNUSED @@ -39,6 +40,11 @@ constexpr inline uint32_t fourcc_to_uint32(const char* id) ((((uint32_t) id[3])&0xFF) << 0)); } +// abbreviation +constexpr inline uint32_t fourcc(const char* id) { return fourcc_to_uint32(id); } + +std::string to_fourcc(uint32_t code); + // Functions for common use in libheif and the plugins.