Skip to content

Commit

Permalink
Merge branch 'master' into develop-v1.18.0
Browse files Browse the repository at this point in the history
  • Loading branch information
farindk committed Nov 30, 2023
2 parents 12d8b6b + 56ef61d commit 5e19d8b
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 21 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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.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.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
4 changes: 3 additions & 1 deletion gnome/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
install(FILES heif.thumbnailer DESTINATION ${CMAKE_INSTALL_DATADIR}/thumbnailers)
if(TARGET heif-thumbnailer)
install(FILES heif.thumbnailer DESTINATION ${CMAKE_INSTALL_DATADIR}/thumbnailers)
endif()
14 changes: 14 additions & 0 deletions libheif/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2553,6 +2553,20 @@ Error HeifContext::encode_image_as_hevc(const std::shared_ptr<HeifPixelImage>& 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);

Expand Down
64 changes: 49 additions & 15 deletions libheif/plugins/encoder_kvazaar.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@
#include "libheif/heif_plugin.h"
#include "encoder_kvazaar.h"
#include <memory>
#include <string>
#include <string> // apparently, this is a false positive of cpplint
#include <cstring>
#include <cassert>
#include <vector>
#include <algorithm>

extern "C" {
#include <kvazaar.h>
Expand Down Expand Up @@ -302,10 +303,22 @@ 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;
}
}
}

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)
{
Expand Down Expand Up @@ -335,10 +348,15 @@ static void append_chunk_data(kvz_data_chunk* data, std::vector<uint8_t>& 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);
}
}
}

Expand Down Expand Up @@ -427,6 +445,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;
Expand All @@ -440,18 +466,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) {
Expand All @@ -468,7 +500,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) {
Expand Down Expand Up @@ -496,8 +527,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.
Expand All @@ -510,7 +541,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{
Expand All @@ -524,20 +555,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);
Expand Down Expand Up @@ -671,7 +704,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,
Expand All @@ -698,7 +731,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()
Expand Down
9 changes: 6 additions & 3 deletions libheif/uncompressed_image.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -467,8 +468,10 @@ static Error get_heif_chroma_uncompressed(std::shared_ptr<Box_uncC>& 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);
Expand Down

0 comments on commit 5e19d8b

Please sign in to comment.