-
-
Notifications
You must be signed in to change notification settings - Fork 308
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
extract stream decoding to Decoder classes #1321
Merged
Merged
Changes from 2 commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
0922977
extract stream decoding to Decoder classes (HEVC, J2K)
farindk 5f86fe3
move decode_single_frame_from_compressed_data() to Decoder
farindk 957093a
revert: cmake OpenJPEG version check
farindk 9d891b8
initialize Decoder in ImageItem::on_load_file()
farindk 9f1156a
decode HEVC through Decoder_HEVC
farindk d1e662f
default implementation of ImageItem::get_luma_bits_per_pixel() just f…
farindk 33d3870
move AVIF decoding into Decoder_AVIF
farindk 6a5b62c
(change struct to class)
farindk 1e64957
replace all get_item_type() with get_item_type_4cc()
farindk 1bb435c
replace all fourcc-type strings with uint32_t constants
farindk fa791d0
rename 'to_fourcc()' to 'fourcc_to_string()'
farindk 0eb4109
rename HeifFile::get_compressed_image_data() to HeifFile::get_uncompr…
farindk da93fdc
remove mutex from get_uncompressed_item_data() as it is not used for …
farindk e029ffc
add Decoder classes for VVC, AVC, JPEG
farindk ef58e35
(remove 'struct' forward declaration)
farindk 11cf60d
JPEG: parse SOF for chroma format
farindk 6295206
(minor edit)
farindk 73fb313
add Decoder_uncompressed class
farindk 497dc5b
uncompressed: separated codec from ImageItem
farindk 6190b58
uncompressed: pulled AbstractDecoder into its own file
farindk 77292c2
uncompressed: pulled ComponentInterleaveDecoder into its own file
farindk 8cae3b0
uncompressed: pulled PixelInterleaveDecoder into its own file
farindk 8b0dade
uncompressed: pulled MixedInterleaveDecoder into its own file
farindk b4a06be
uncompressed: pulled RowInterleaveDecoder into its own file
farindk ab2f694
uncompressed: pulled TileComponentInterleaveDecoder into its own file
farindk 5ae88f6
uncompressed: (cleanup)
farindk cba01e8
uncompressed: simplify nAlignmentSkipBytes()
farindk 901ce17
uncompressed: (cleanup includes)
farindk a1e388c
JPEG2000: use Decoder_JPEG2000 in ImageItem_JPEG2000
farindk 6882bd6
extract AVIF and AVC boxes into their own files
farindk a47b217
remove dead code
farindk 098da51
fix wrong AVIF chroma parsing
farindk c8715dd
extract HEVC boxes processing into its own file
farindk fd73fc3
extract JPEG boxes processing into its own file
farindk 3117743
extract JPEG2000 boxes processing into its own file
farindk 8e94574
extract VVC boxes processing into its own file
farindk 0a423e9
scale vvenc encoder quality from 0-100 and invert, so that 100 is max…
farindk e127d20
move all ImageItem classes into its own directory
farindk 562f826
add 'unci' to Decoder::alloc_for_infe_type()
farindk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
/* | ||
* HEIF codec. | ||
* Copyright (c) 2024 Dirk Farin <[email protected]> | ||
* | ||
* This file is part of libheif. | ||
* | ||
* libheif is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as | ||
* published by the Free Software Foundation, either version 3 of | ||
* the License, or (at your option) any later version. | ||
* | ||
* libheif is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with libheif. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#include "codecs/decoder.h" | ||
#include "error.h" | ||
#include "context.h" | ||
#include "plugin_registry.h" | ||
#include "libheif/api_structs.h" | ||
|
||
#include "codecs/hevc_dec.h" | ||
#include "codecs/jpeg2000_dec.h" | ||
|
||
#include <limits> | ||
|
||
|
||
void DataExtent::set_from_image_item(class HeifFile* file, heif_item_id item) | ||
{ | ||
m_iloc = file->get_property<Box_iloc>(item); | ||
m_item_id = item; | ||
} | ||
|
||
|
||
Result<std::vector<uint8_t>*> DataExtent::read_data() const | ||
{ | ||
if (!m_raw.empty()) { | ||
return &m_raw; | ||
} | ||
else if (m_iloc) { | ||
// image | ||
m_iloc->read_data(m_item_id, m_file->get_reader(), nullptr, &m_raw, 0, std::numeric_limits<uint64_t>::max()); | ||
} | ||
else { | ||
// sequence | ||
assert(false); // TODO | ||
} | ||
|
||
return &m_raw; | ||
} | ||
|
||
|
||
Result<std::vector<uint8_t>> DataExtent::read_data(uint64_t offset, uint64_t size) const | ||
{ | ||
std::vector<uint8_t> data; | ||
|
||
if (!m_raw.empty()) { | ||
data.insert(data.begin(), m_raw.begin() + offset, m_raw.begin() + offset + size); | ||
return data; | ||
} | ||
else if (m_iloc) { | ||
// TODO: cache data | ||
|
||
// image | ||
Error err = m_iloc->read_data(m_item_id, m_file->get_reader(), nullptr, &m_raw, 0, size); | ||
if (err) { | ||
return err; | ||
} | ||
return data; | ||
} | ||
else { | ||
// sequence | ||
assert(false); // TODO | ||
return Error::Ok; | ||
} | ||
} | ||
|
||
|
||
std::shared_ptr<Decoder> Decoder::alloc_for_compression_format(const HeifContext* ctx, heif_item_id id, uint32_t format_4cc) | ||
{ | ||
switch (format_4cc) { | ||
case fourcc("hvc1"): { | ||
auto hvcC = ctx->get_heif_file()->get_property<Box_hvcC>(id); | ||
return std::make_shared<Decoder_HEVC>(hvcC); | ||
} | ||
case fourcc("j2k1"): { | ||
auto j2kH = ctx->get_heif_file()->get_property<Box_j2kH>(id); | ||
return std::make_shared<Decoder_JPEG2000>(j2kH); | ||
} | ||
#if WITH_UNCOMPRESSED_CODEC | ||
#endif | ||
default: | ||
assert(false); | ||
return nullptr; | ||
} | ||
} | ||
|
||
|
||
Result<std::vector<uint8_t>> Decoder::get_compressed_data() const | ||
{ | ||
// --- get the compressed image data | ||
|
||
// data from configuration blocks | ||
|
||
Result<std::vector<uint8_t>> confData = read_bitstream_configuration_data(); | ||
if (confData.error) { | ||
return confData.error; | ||
} | ||
|
||
std::vector<uint8_t> data = confData.value; | ||
|
||
// image data, usually from 'mdat' | ||
|
||
Result dataResult = m_data_extent.read_data(); | ||
if (dataResult.error) { | ||
return dataResult.error; | ||
} | ||
|
||
data.insert(data.begin(), 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) | ||
{ | ||
const struct heif_decoder_plugin* decoder_plugin = get_decoder(compression_format, options.decoder_id); | ||
if (!decoder_plugin) { | ||
return Error(heif_error_Plugin_loading_error, heif_suberror_No_matching_decoder_installed); | ||
} | ||
|
||
|
||
// --- decode image with the plugin | ||
|
||
void* decoder; | ||
struct heif_error err = decoder_plugin->new_decoder(&decoder); | ||
if (err.code != heif_error_Ok) { | ||
return Error(err.code, err.subcode, err.message); | ||
} | ||
|
||
if (decoder_plugin->plugin_api_version >= 2) { | ||
if (decoder_plugin->set_strict_decoding) { | ||
decoder_plugin->set_strict_decoding(decoder, options.strict_decoding); | ||
} | ||
} | ||
|
||
err = decoder_plugin->push_data(decoder, data.data(), data.size()); | ||
if (err.code != heif_error_Ok) { | ||
decoder_plugin->free_decoder(decoder); | ||
return Error(err.code, err.subcode, err.message); | ||
} | ||
|
||
heif_image* decoded_img = nullptr; | ||
|
||
err = decoder_plugin->decode_image(decoder, &decoded_img); | ||
if (err.code != heif_error_Ok) { | ||
decoder_plugin->free_decoder(decoder); | ||
return Error(err.code, err.subcode, err.message); | ||
} | ||
|
||
if (!decoded_img) { | ||
// TODO(farindk): The plugin should return an error in this case. | ||
decoder_plugin->free_decoder(decoder); | ||
return Error(heif_error_Decoder_plugin_error, heif_suberror_Unspecified); | ||
} | ||
|
||
// -- cleanup | ||
|
||
std::shared_ptr<HeifPixelImage> img = std::move(decoded_img->image); | ||
heif_image_release(decoded_img); | ||
|
||
decoder_plugin->free_decoder(decoder); | ||
|
||
return img; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
* HEIF codec. | ||
* Copyright (c) 2024 Dirk Farin <[email protected]> | ||
* | ||
* This file is part of libheif. | ||
* | ||
* libheif is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as | ||
* published by the Free Software Foundation, either version 3 of | ||
* the License, or (at your option) any later version. | ||
* | ||
* libheif is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with libheif. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#ifndef HEIF_DECODER_H | ||
#define HEIF_DECODER_H | ||
|
||
#include "libheif/heif.h" | ||
#include "box.h" | ||
#include "error.h" | ||
#include "file.h" | ||
|
||
#include <memory> | ||
#include <string> | ||
#include <utility> | ||
#include <vector> | ||
#include <codecs/hevc.h> | ||
|
||
|
||
// Specifies the input data for decoding. | ||
// For images, this points to the iloc extents. | ||
// For sequences, this points to the track data. | ||
struct DataExtent | ||
{ | ||
std::shared_ptr<HeifFile> m_file; | ||
|
||
// --- 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); | ||
|
||
Result<std::vector<uint8_t>*> read_data() const; | ||
|
||
Result<std::vector<uint8_t>> read_data(uint64_t offset, uint64_t size) const; | ||
}; | ||
|
||
|
||
class Decoder | ||
{ | ||
public: | ||
virtual ~Decoder() = default; | ||
|
||
static std::shared_ptr<Decoder> alloc_for_compression_format(const HeifContext* ctx, heif_item_id, uint32_t format_4cc); | ||
|
||
void set_data_extent(DataExtent extent) { m_data_extent = std::move(extent); } | ||
|
||
[[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; | ||
|
||
[[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); | ||
|
||
private: | ||
DataExtent m_data_extent; | ||
}; | ||
|
||
|
||
#endif |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know why you do this (I do too), but probably not wanted in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'll have to put that on
.gitignore
. No matter how much care I take, sooner or later it slips through :-)