libyuv: add support to overwrite default allocator

Internally libyuv uses malloc & free for short time dynamic memory
allocation during image transformation. The converted images are
such large, that the Libc allocator will create and destroy new Genode
dataspace per image.  In time sensitive code paths, the overhead can be
noticeable by the caller of the image transformation.
The patch adds the option to register callbacks in the libyuv library to
implement the image allocation by users of the library. They may implement
caching strategies to avoid the overhead, e.g. as seen with qemu-usb and
the webcam model.
This commit is contained in:
Alexander Boettcher 2023-09-15 13:44:26 +02:00 committed by Christian Helmuth
parent 63c5ec7390
commit 0d868515a5
10 changed files with 226 additions and 6 deletions

View File

@ -0,0 +1,26 @@
/*
* \brief Libyuv initialization to overwrite default libc memory/free allocator
* \author Alexander Boettcher
* \date 2023-09-15
*/
/*
* Copyright (C) 2023 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _INCLUDE__LIBYUV__LIBYUV_H_
#define _INCLUDE__LIBYUV__LIBYUV_H_
/* use same namespace as used in contrib libyuv sources */
namespace libyuv
{
typedef void * (*type_malloc)(unsigned long);
typedef void (*type_free )(void *);
extern "C" void libyuv_init(type_malloc os_malloc, type_free os_free);
}
#endif /* _INCLUDE__LIBYUV_LIBYUV_H_ */

View File

@ -3,13 +3,18 @@ SHARED_LIB = yes
YUV_PORT := $(call select_from_ports,libyuv)
YUV_DIR = $(YUV_PORT)/src/lib/libyuv
LIB_DIR = $(REP_DIR)/src/lib/libyuv
LIBS = libc stdcxx jpeg
INC_DIR += $(REP_DIR)/include
INC_DIR += $(YUV_PORT)/include
SRC_CC = $(notdir $(wildcard $(YUV_DIR)/source/*.cc))
SRC_CC = $(notdir $(wildcard $(YUV_DIR)/source/*.cc))
SRC_CC += memory.cc
CC_CXX_WARN_STRICT = -Wextra -Werror
CC_OPT += -Wno-unused-parameter -DHAVE_JPEG
vpath %.cc $(YUV_DIR)/source
vpath memory.cc $(LIB_DIR)
vpath %.cc $(YUV_DIR)/source

View File

@ -351,3 +351,4 @@ YUY2ToI420 T
YUY2ToI422 T
YUY2ToNV12 T
YUY2ToY T
libyuv_init T

View File

@ -1 +1 @@
01cdd9be97364d27b8d6aa7aafc18ba0f2eb4c3f
d53528820b90c03e8b8d23ef6bae7ad4337a3cf3

View File

@ -10,6 +10,6 @@ DIRS := include include/libyuv
DIR_CONTENT(include) := src/lib/libyuv/include/libyuv.h
DIR_CONTENT(include/libyuv) := src/lib/libyuv/include/libyuv/*.h
PATCHES := src/lib/libyuv/constraints.patch
PATCHES := src/lib/libyuv/constraints.patch src/lib/libyuv/memory.patch
PATCH_OPT := -d src/lib/libyuv -p1

View File

@ -5,6 +5,7 @@ PORT_DIR := $(call port_dir,$(REP_DIR)/ports/libyuv)
include:
mkdir $@
cp -r $(PORT_DIR)/include/* $@/
cp -r $(REP_DIR)/include/libyuv $@/
lib/symbols/libyuv:
$(mirror_from_rep_dir)

View File

@ -2,7 +2,8 @@ MIRROR_FROM_REP_DIR := lib/mk/libyuv.inc \
lib/mk/spec/arm_v8/libyuv.mk \
lib/mk/spec/x86_32/libyuv.mk \
lib/mk/spec/x86_64/libyuv.mk \
lib/import/import-libyuv.mk
lib/import/import-libyuv.mk \
include/libyuv
content: src/lib/libyuv include LICENSE $(MIRROR_FROM_REP_DIR)
@ -11,6 +12,7 @@ PORT_DIR := $(call port_dir,$(REP_DIR)/ports/libyuv)
src/lib/libyuv:
mkdir -p $@
cp -r $(PORT_DIR)/src/lib/libyuv/source $@
cp -r $(REP_DIR)/src/lib/libyuv/* $@
include:
mkdir -p $@

View File

@ -1,4 +1,4 @@
base
libc
stdcxx
jpeg

View File

@ -0,0 +1,57 @@
/*
* \brief Support to overwrite default memory allocator of libyuv
* \author Alexander Boettcher
*/
/*
* Copyright (C) 2023 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 2.
*/
#include <base/log.h>
#include <stdlib.h>
typedef void * (*type_malloc)(unsigned long);
typedef void (*type_free )(void *);
static type_malloc use_malloc(type_malloc m = malloc)
{
static auto defined_malloc = m;
return defined_malloc;
}
static type_free use_free(type_free f = free)
{
static auto defined_free = f;
return defined_free;
}
extern "C" void libyuv_init(type_malloc os_malloc, type_free os_free)
{
if (!os_malloc || !os_free) {
Genode::error("invalid libyuv allocator specified");
return;
}
use_malloc(os_malloc);
use_free (os_free);
}
extern "C" void *libyuv_malloc(unsigned long size)
{
return use_malloc()(size);
}
extern "C" void libyuv_free(void *ptr)
{
use_free()(ptr);
}

View File

@ -0,0 +1,128 @@
--- libyuv/include/libyuv/row.h
+++ libyuv/include/libyuv/row.h
@@ -20,6 +20,9 @@
extern "C" {
#endif
+extern void *libyuv_malloc(unsigned long size);
+extern void libyuv_free(void *ptr);
+
// TODO: Fix Win32 build
// https://bugs.chromium.org/p/libyuv/issues/detail?id=900
#if defined(__pnacl__) || defined(__CLR_VER) || defined(_M_IX86) || \
@@ -785,11 +788,11 @@
#define IS_ALIGNED(p, a) (!((uintptr_t)(p) & ((a)-1)))
#define align_buffer_64(var, size) \
- uint8_t* var##_mem = (uint8_t*)(malloc((size) + 63)); /* NOLINT */ \
+ uint8_t* var##_mem = (uint8_t*)(libyuv_malloc((size) + 63)); /* NOLINT */ \
uint8_t* var = (uint8_t*)(((intptr_t)(var##_mem) + 63) & ~63) /* NOLINT */
#define free_aligned_buffer_64(var) \
- free(var##_mem); \
+ libyuv_free(var##_mem); \
var = 0
#if defined(__APPLE__) || defined(__x86_64__) || defined(__llvm__)
--- libyuv/source/convert_jpeg.cc
+++ libyuv/source/convert_jpeg.cc
@@ -32,6 +32,10 @@
int h;
};
+extern void *libyuv_malloc(unsigned long size);
+extern void libyuv_free(void *ptr);
+
+
static void JpegCopyI420(void* opaque,
const uint8_t* const* data,
const int* strides,
--- libyuv/source/convert_to_argb.cc
+++ libyuv/source/convert_to_argb.cc
@@ -23,6 +23,9 @@
extern "C" {
#endif
+extern void *libyuv_malloc(unsigned long size);
+extern void libyuv_free(void *ptr);
+
// Convert camera sample to ARGB with cropping, rotation and vertical flip.
// src_width is used for source stride computation
// src_height is used to compute location of planes, and indicate inversion
@@ -76,7 +79,7 @@
if (need_buf) {
int argb_size = crop_width * 4 * abs_crop_height;
- rotate_buffer = (uint8_t*)malloc(argb_size); /* NOLINT */
+ rotate_buffer = (uint8_t*)libyuv_malloc(argb_size); /* NOLINT */
if (!rotate_buffer) {
return 1; // Out of memory runtime error.
}
@@ -366,7 +369,7 @@
r = ARGBRotate(dst_argb, dst_stride_argb, dest_argb, dest_dst_stride_argb,
crop_width, abs_crop_height, rotation);
}
- free(rotate_buffer);
+ libyuv_free(rotate_buffer);
} else if (rotation) {
src = sample + (src_width * crop_y + crop_x) * 4;
r = ARGBRotate(src, src_width * 4, dst_argb, dst_stride_argb, crop_width,
--- libyuv/source/convert_to_i420.cc
+++ libyuv/source/convert_to_i420.cc
@@ -19,6 +19,9 @@
extern "C" {
#endif
+extern void *libyuv_malloc(unsigned long size);
+extern void libyuv_free(void *ptr);
+
// Convert camera sample to I420 with cropping, rotation and vertical flip.
// src_width is used for source stride computation
// src_height is used to compute location of planes, and indicate inversion
@@ -76,7 +79,7 @@
if (need_buf) {
int y_size = crop_width * abs_crop_height;
int uv_size = ((crop_width + 1) / 2) * ((abs_crop_height + 1) / 2);
- rotate_buffer = (uint8_t*)malloc(y_size + uv_size * 2); /* NOLINT */
+ rotate_buffer = (uint8_t*)libyuv_malloc(y_size + uv_size * 2); /* NOLINT */
if (!rotate_buffer) {
return 1; // Out of memory runtime error.
}
@@ -260,7 +263,7 @@
tmp_v, tmp_v_stride, crop_width, abs_crop_height,
rotation);
}
- free(rotate_buffer);
+ libyuv_free(rotate_buffer);
}
return r;
--- libyuv/source/scale_argb.cc
+++ libyuv/source/scale_argb.cc
@@ -23,6 +23,9 @@
extern "C" {
#endif
+extern void *libyuv_malloc(unsigned long size);
+extern void libyuv_free(void *ptr);
+
static __inline int Abs(int v) {
return v >= 0 ? v : -v;
}
@@ -1071,7 +1074,7 @@
int clip_width,
int clip_height,
enum FilterMode filtering) {
- uint8_t* argb_buffer = (uint8_t*)malloc(src_width * src_height * 4);
+ uint8_t* argb_buffer = (uint8_t*)libyuv_malloc(src_width * src_height * 4);
int r;
(void)src_fourcc; // TODO(fbarchard): implement and/or assert.
(void)dst_fourcc;
@@ -1081,7 +1084,7 @@
r = ARGBScaleClip(argb_buffer, src_width * 4, src_width, src_height, dst_argb,
dst_stride_argb, dst_width, dst_height, clip_x, clip_y,
clip_width, clip_height, filtering);
- free(argb_buffer);
+ libyuv_free(argb_buffer);
return r;
}