Skip to content
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

Adding a new emscripten js method to parse depth images #1029

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ third-party/SVT-AV1/
third-party/dav1d/
third-party/libwebp/
third-party/rav1e/
buildjs/
5 changes: 3 additions & 2 deletions build-emscripten.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash
set -e
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
DIR=$PWD

if [[ $# -ne 1 ]] ; then
echo "Usage: $0 SRCDIR"
Expand All @@ -27,7 +27,7 @@ STANDALONE="${STANDALONE:-0}"
DEBUG="${DEBUG:-0}"
USE_WASM="${USE_WASM:-1}"

echo "Build using ${CORES} CPU cores"
echo "Build using ${CORES} CPU cores in dir ${DIR}"

LIBRARY_LINKER_FLAGS=""
LIBRARY_INCLUDE_FLAGS=""
Expand All @@ -50,6 +50,7 @@ if [ "$ENABLE_LIBDE265" = "1" ]; then
LIBRARY_LINKER_FLAGS="$LIBRARY_LINKER_FLAGS -lde265"
LIBRARY_INCLUDE_FLAGS="$LIBRARY_INCLUDE_FLAGS -L${DIR}/libde265-${LIBDE265_VERSION}/libde265/.libs"
fi
echo "libde265: $CONFIGURE_ARGS_LIBDE265"

CONFIGURE_ARGS_AOM=""
if [ "$ENABLE_AOM" = "1" ]; then
Expand Down
10 changes: 0 additions & 10 deletions libheif/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,4 @@ inline std::ostream& operator<<(std::ostream& ostr, const Error& err)
return ostr;
}


template <typename T> class Result
{
public:
operator bool() const { return error.error_code == heif_error_Ok; }

T value;
Error error;
};

#endif
99 changes: 98 additions & 1 deletion libheif/heif_emscripten.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,95 @@ static emscripten::val heif_js_decode_image2(struct heif_image_handle* handle,
return result;
}

static emscripten::val heif_js_depth_img_decode(struct heif_image_handle *handle, heif_item_id depth_image_id)
{
emscripten::val depth_result = emscripten::val::object();
struct heif_image_handle *depth_handle;
heif_image_handle_get_depth_image_handle(handle, depth_image_id, &depth_handle);
if (!depth_handle)
{
depth_result.set("err", "could not get handle of depth image");
depth_result.set("id", depth_image_id);
return depth_result;
}
Comment on lines +268 to +272
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to return an heif_error here since heif_error is registered as an value object see here, that way it won't be necessary to manually delete the object on the JS side see here


int width = heif_image_handle_get_width(depth_handle);
depth_result.set("width", width);

int height = heif_image_handle_get_height(depth_handle);
depth_result.set("height", height);

struct heif_image *depth_image;
struct heif_error err = heif_decode_image(depth_handle, &depth_image, heif_colorspace_monochrome, heif_chroma_monochrome, nullptr);
if (err.code)
{
depth_result.set("err", "could not get image of depth image");
depth_result.set("msg", err.message);
depth_result.set("id", depth_image_id);
return depth_result;
Comment on lines +284 to +287
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same issue as above

}

depth_result.set("testdata", emscripten::val(emscripten::typed_memory_view(10, "123456890")));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like this is a leftover from testing

return depth_result;
std::vector<heif_channel> channels{
heif_channel_Y,
heif_channel_Cb,
heif_channel_Cr,
heif_channel_R,
heif_channel_G,
heif_channel_B,
heif_channel_Alpha,
heif_channel_interleaved};

for (auto &&channel : channels)
{
if (heif_image_has_channel(depth_image, channel))
{
depth_result.set("c_width", heif_image_get_width(depth_image, channel));
depth_result.set("c_height", heif_image_get_height(depth_image, channel));

int stride;
const uint8_t *plane = heif_image_get_plane_readonly(depth_image, channel, &stride);
if (plane)
{
depth_result.set("stride", stride);
depth_result.set("data", emscripten::val(emscripten::typed_memory_view(stride * height, plane)));
depth_result.set("buffersize", stride * height);
depth_result.set("channel", channel);
depth_result.set("testdata", emscripten::val(emscripten::typed_memory_view(10, "123456890")));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another leftover

return depth_result;
}
}
}

depth_result.set("err", "could get no plane of depth image");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be a little bit pedantic but I'd rephrase this error message to "could not get plane of depth image"

depth_result.set("id", depth_image_id);
return depth_result;
}
static emscripten::val heif_js_get_depth_imgs_decoded(struct heif_image_handle *handle)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

based on what this function does a better name might be heif_js_image_handle_get_depth_img_handle, since it doesn't actually do any image decoding

{
// similar to https://github.com/bigcat88/pillow_heif/blob/b2bf2744d0e4203088481b938af91974b3a2006f/pillow_heif/_pillow_heif.c#L1094
emscripten::val results = emscripten::val::array();
if (!handle)
{
return results;
}
int n_images = heif_image_handle_get_number_of_depth_images(handle);
if (n_images == 0)
return results;
heif_item_id *ids = (heif_item_id *)malloc(n_images * sizeof(heif_item_id));

Comment on lines +338 to +339
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also here there should be a check to make sure the malloc didn't return a null pointer, similar to here

n_images = heif_image_handle_get_list_of_depth_image_IDs(handle, ids, n_images);
for (int i = 0; i < n_images; i++)
{

struct heif_image_handle *depth_handle;
heif_image_handle_get_depth_image_handle(handle, ids[i], &depth_handle);
results.call<void>("push", emscripten::val(depth_handle));
}
free(ids);
return results;
}

#define EXPORT_HEIF_FUNCTION(name) \
emscripten::function(#name, &name, emscripten::allow_raw_pointers())
Expand All @@ -280,10 +369,18 @@ EMSCRIPTEN_BINDINGS(libheif) {
//emscripten::function("heif_js_decode_image",
//&heif_js_decode_image, emscripten::allow_raw_pointers());
emscripten::function("heif_js_decode_image2",
&heif_js_decode_image2, emscripten::allow_raw_pointers());
&heif_js_decode_image2, emscripten::allow_raw_pointers());
emscripten::function("heif_js_depth_img_decode",
&heif_js_depth_img_decode, emscripten::allow_raw_pointers());
emscripten::function("heif_js_get_depth_imgs_decoded",
&heif_js_get_depth_imgs_decoded, emscripten::allow_raw_pointers());
EXPORT_HEIF_FUNCTION(heif_image_handle_release);
EXPORT_HEIF_FUNCTION(heif_image_handle_get_width);
EXPORT_HEIF_FUNCTION(heif_image_handle_get_height);
EXPORT_HEIF_FUNCTION(heif_image_handle_get_number_of_depth_images);
EXPORT_HEIF_FUNCTION(heif_image_handle_get_list_of_depth_image_IDs);
EXPORT_HEIF_FUNCTION(heif_image_handle_get_depth_image_handle);
EXPORT_HEIF_FUNCTION(heif_image_handle_is_primary_image);
EXPORT_HEIF_FUNCTION(heif_image_handle_is_primary_image);
EXPORT_HEIF_FUNCTION(heif_image_release);

Expand Down
29 changes: 7 additions & 22 deletions libheif/hevc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

#include "hevc.h"
#include "bitstream.h"
#include "error.h"

#include <cassert>
#include <cmath>
Expand Down Expand Up @@ -347,10 +346,8 @@ static double read_depth_rep_info_element(BitReader& reader)
}


static Result<std::shared_ptr<SEIMessage>> read_depth_representation_info(BitReader& reader)
static std::shared_ptr<SEIMessage> read_depth_representation_info(BitReader& reader)
{
Result<std::shared_ptr<SEIMessage>> result;

auto msg = std::make_shared<SEIMessage_depth_representation_info>();


Expand All @@ -372,15 +369,9 @@ static Result<std::shared_ptr<SEIMessage>> read_depth_representation_info(BitRea

int rep_type;
if (!reader.get_uvlc(&rep_type)) {
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 error
}

// 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);
Expand All @@ -389,8 +380,7 @@ static Result<std::shared_ptr<SEIMessage>> read_depth_representation_info(BitRea
if (msg->has_d_min || msg->has_d_max) {
int ref_view;
if (!reader.get_uvlc(&ref_view)) {
result.error = {heif_error_Invalid_input, heif_suberror_Invalid_parameter_value, "invalid disparity_reference_view in input"};
return result;
// TODO error
}
msg->disparity_reference_view = ref_view;

Expand All @@ -413,8 +403,7 @@ static Result<std::shared_ptr<SEIMessage>> read_depth_representation_info(BitRea
// TODO: load non-uniform response curve
}

result.value = msg;
return result;
return msg;
}


Expand Down Expand Up @@ -455,12 +444,8 @@ Error decode_hevc_aux_sei_messages(const std::vector<uint8_t>& data,

switch (payload_id) {
case 177: // depth_representation_info
Result<std::shared_ptr<SEIMessage>> seiResult = read_depth_representation_info(sei_reader);
if (seiResult.error) {
return seiResult.error;
}

msgs.push_back(seiResult.value);
std::shared_ptr<SEIMessage> sei = read_depth_representation_info(sei_reader);
msgs.push_back(sei);
break;
}
}
Expand Down