Skip to content

Commit

Permalink
decode HEVC through Decoder_HEVC
Browse files Browse the repository at this point in the history
  • Loading branch information
farindk committed Oct 2, 2024
1 parent 9d891b8 commit 9f1156a
Show file tree
Hide file tree
Showing 12 changed files with 85 additions and 55 deletions.
12 changes: 7 additions & 5 deletions libheif/box.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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();
}
}
Expand Down
14 changes: 7 additions & 7 deletions libheif/box.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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; }

Expand Down Expand Up @@ -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;
Expand Down
35 changes: 22 additions & 13 deletions libheif/codecs/decoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@
#include <limits>


void DataExtent::set_from_image_item(class HeifFile* file, heif_item_id item)
void DataExtent::set_from_image_item(std::shared_ptr<HeifFile> file, heif_item_id item)
{
m_iloc = file->get_property<Box_iloc>(item);
m_file = file;
m_item_id = item;
m_source = Source::Image;
}


Expand All @@ -42,9 +43,14 @@ Result<std::vector<uint8_t>*> 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<uint64_t>::max());
Error err = m_file->append_data_from_iloc(m_item_id, m_raw);
if (err) {
return err;
}
}
else {
// sequence
Expand All @@ -63,11 +69,11 @@ Result<std::vector<uint8_t>> 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;
}
Expand Down Expand Up @@ -114,25 +120,23 @@ Result<std::vector<uint8_t>> Decoder::get_compressed_data() const

std::vector<uint8_t> 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<std::shared_ptr<HeifPixelImage>>
Decoder::decode_single_frame_from_compressed_data(heif_compression_format compression_format,
const struct heif_decoding_options& options,
const std::vector<uint8_t>& 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);
}
Expand All @@ -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);
Expand Down
22 changes: 14 additions & 8 deletions libheif/codecs/decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,18 @@
struct DataExtent
{
std::shared_ptr<HeifFile> m_file;
enum class Source : uint8_t { Raw, Image, Sequence } m_source = Source::Raw;

// --- raw data
mutable std::vector<uint8_t> m_raw; // also for cached data

// --- image
std::shared_ptr<Box_iloc> 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<HeifFile> file, heif_item_id item);

Result<std::vector<uint8_t>*> read_data() const;

Expand All @@ -61,30 +61,36 @@ struct DataExtent
class Decoder
{
public:
static std::shared_ptr<Decoder> alloc_for_compression_format(const HeifContext* ctx, heif_item_id, uint32_t format_4cc);


virtual ~Decoder() = default;

static std::shared_ptr<Decoder> 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<std::vector<uint8_t>> read_bitstream_configuration_data() const = 0;

Result<std::vector<uint8_t>> get_compressed_data() const;

static Result<std::shared_ptr<HeifPixelImage>>
decode_single_frame_from_compressed_data(heif_compression_format compression_format,
const struct heif_decoding_options& options,
const std::vector<uint8_t>& data);
// --- decoding

virtual Result<std::shared_ptr<HeifPixelImage>>
decode_single_frame_from_compressed_data(const struct heif_decoding_options& options);

private:
DataExtent m_data_extent;
};


#endif
8 changes: 7 additions & 1 deletion libheif/codecs/hevc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@ Error ImageItem_HEVC::on_load_file()
m_decoder = std::make_shared<Decoder_HEVC>(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);

Expand Down Expand Up @@ -761,3 +761,9 @@ int ImageItem_HEVC::get_chroma_bits_per_pixel() const
{
return m_decoder->get_chroma_bits_per_pixel();
}


std::shared_ptr<class Decoder> ImageItem_HEVC::get_decoder() const
{
return m_decoder;
}
2 changes: 2 additions & 0 deletions libheif/codecs/hevc.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ class ImageItem_HEVC : public ImageItem
protected:
Result<std::vector<uint8_t>> read_bitstream_configuration_data(heif_item_id itemId) const override;

std::shared_ptr<class Decoder> get_decoder() const override;

private:
std::shared_ptr<class Decoder_HEVC> m_decoder;
};
Expand Down
2 changes: 2 additions & 0 deletions libheif/codecs/hevc_dec.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class Decoder_HEVC : public Decoder
public:
Decoder_HEVC(const std::shared_ptr<const Box_hvcC>& 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;
Expand Down
24 changes: 7 additions & 17 deletions libheif/codecs/image_item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,7 @@ bool HeifContext::is_image(heif_item_id ID) const
}


std::shared_ptr<HeifFile> ImageItem::get_file()
{
return m_heif_context->get_heif_file();
}


std::shared_ptr<const HeifFile> ImageItem::get_file() const
std::shared_ptr<HeifFile> ImageItem::get_file() const
{
return m_heif_context->get_heif_file();
}
Expand Down Expand Up @@ -1072,17 +1066,13 @@ Result<std::vector<uint8_t>> ImageItem::get_compressed_image_data() const
Result<std::shared_ptr<HeifPixelImage>> 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<std::vector<uint8_t>> 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);
}
6 changes: 3 additions & 3 deletions libheif/codecs/image_item.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,7 @@ class ImageItem : public ErrorBuffer

const HeifContext* get_context() const { return m_heif_context; }

std::shared_ptr<class HeifFile> get_file();

std::shared_ptr<const class HeifFile> get_file() const;
std::shared_ptr<class HeifFile> get_file() const;

Error check_resolution(uint32_t w, uint32_t h) const;

Expand Down Expand Up @@ -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<class Decoder> get_decoder() const { return nullptr; }
};


Expand Down
2 changes: 2 additions & 0 deletions libheif/codecs/jpeg2000_dec.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class Decoder_JPEG2000 : public Decoder
public:
Decoder_JPEG2000(const std::shared_ptr<const Box_j2kH>& 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;
Expand Down
7 changes: 6 additions & 1 deletion libheif/codecs/tild.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}


Expand Down
6 changes: 6 additions & 0 deletions libheif/common_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include <cinttypes>
#include "libheif/heif.h"
#include <string>

#ifdef _MSC_VER
#define MAYBE_UNUSED
Expand All @@ -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.

Expand Down

0 comments on commit 9f1156a

Please sign in to comment.