Commit 1e93ba24 authored by Jakob Bornecrantz's avatar Jakob Bornecrantz
Browse files

xrt: Refactor frame interface

parent b9c3ac79
Pipeline #59056 passed with stages
in 3 minutes and 6 seconds
......@@ -36,12 +36,15 @@ set(UTIL_SOURCE_FILES
util/u_documentation.h
util/u_format.c
util/u_format.h
util/u_frame.c
util/u_frame.h
util/u_hashmap.cpp
util/u_hashmap.h
util/u_hashset.cpp
util/u_hashset.h
util/u_sink.c
util/u_sink.h
util/u_sink_converter.c
util/u_sink_queue.c
util/u_time.cpp
util/u_time.h
)
......
......@@ -225,7 +225,8 @@ t_calibration_frame(struct xrt_frame_sink *xsink, struct xrt_frame *xf)
*/
extern "C" int
t_calibration_create(struct xrt_frame_sink *gui,
t_calibration_create(struct xrt_frame_context *xfctx,
struct xrt_frame_sink *gui,
struct xrt_frame_sink **out_sink)
{
......@@ -242,19 +243,19 @@ t_calibration_create(struct xrt_frame_sink *gui,
int ret = 0;
if (debug_get_bool_option_hsv_filter()) {
ret = t_debug_hsv_filter_create(*out_sink, out_sink);
ret = t_debug_hsv_filter_create(xfctx, *out_sink, out_sink);
}
if (debug_get_bool_option_hsv_picker()) {
ret = t_debug_hsv_picker_create(*out_sink, out_sink);
ret = t_debug_hsv_picker_create(xfctx, *out_sink, out_sink);
}
if (debug_get_bool_option_hsv_viewer()) {
ret = t_debug_hsv_viewer_create(*out_sink, out_sink);
ret = t_debug_hsv_viewer_create(xfctx, *out_sink, out_sink);
}
// Ensure we only get yuv or yuyv frames.
u_sink_create_to_yuv_or_yuyv(*out_sink, out_sink);
u_sink_create_to_yuv_or_yuyv(xfctx, *out_sink, out_sink);
return ret;
}
......@@ -29,6 +29,7 @@ class DebugHSV
{
public:
struct xrt_frame_sink base = {};
struct xrt_frame_node node = {};
struct xrt_frame_sink sinks[4] = {};
struct xrt_frame_sink *sink;
......@@ -83,8 +84,20 @@ t_debug_hsv_filter_frame(struct xrt_frame_sink *xsink, struct xrt_frame *xf)
d.passthrough->push_frame(d.passthrough, xf);
}
extern "C" void
t_debug_hsv_filter_break_apart(struct xrt_frame_node *node)
{}
extern "C" void
t_debug_hsv_filter_destroy(struct xrt_frame_node *node)
{
auto d = container_of(node, DebugHSV, node);
delete d;
}
extern "C" int
t_debug_hsv_filter_create(struct xrt_frame_sink *passthrough,
t_debug_hsv_filter_create(struct xrt_frame_context *xfctx,
struct xrt_frame_sink *passthrough,
struct xrt_frame_sink **out_sink)
{
auto &d = *(new DebugHSV());
......@@ -96,12 +109,14 @@ t_debug_hsv_filter_create(struct xrt_frame_sink *passthrough,
cv::startWindowThread();
d.base.push_frame = t_debug_hsv_filter_frame;
d.node.break_apart = t_debug_hsv_filter_break_apart;
d.node.destroy = t_debug_hsv_filter_destroy;
d.passthrough = passthrough;
d.sinks[0].push_frame = t_debug_hsv_filter_frame0;
d.sinks[1].push_frame = t_debug_hsv_filter_frame1;
d.sinks[2].push_frame = t_debug_hsv_filter_frame2;
d.sinks[3].push_frame = t_debug_hsv_filter_frame3;
d.base.push_frame = t_debug_hsv_filter_frame;
struct xrt_frame_sink *sinks[4] = {
&d.sinks[0],
......@@ -110,10 +125,12 @@ t_debug_hsv_filter_create(struct xrt_frame_sink *passthrough,
&d.sinks[3],
};
*out_sink = &d.base;
t_hsv_filter_params params = T_HSV_DEFAULT_PARAMS();
t_hsv_filter_create(&params, sinks, &d.sink);
t_hsv_filter_create(xfctx, &params, sinks, &d.sink);
xrt_frame_context_add(xfctx, &d.node);
*out_sink = &d.base;
return 0;
}
......@@ -31,6 +31,7 @@ class DebugHSVPicker
{
public:
struct xrt_frame_sink base = {};
struct xrt_frame_node node = {};
struct
{
......@@ -199,14 +200,31 @@ t_debug_hsv_picker_frame(struct xrt_frame_sink *xsink, struct xrt_frame *xf)
d.passthrough->push_frame(d.passthrough, xf);
}
extern "C" void
t_debug_hsv_picker_break_apart(struct xrt_frame_node *node)
{}
extern "C" void
t_debug_hsv_picker_destroy(struct xrt_frame_node *node)
{
auto d = container_of(node, DebugHSVPicker, node);
delete d;
}
extern "C" int
t_debug_hsv_picker_create(struct xrt_frame_sink *passthrough,
t_debug_hsv_picker_create(struct xrt_frame_context *xfctx,
struct xrt_frame_sink *passthrough,
struct xrt_frame_sink **out_sink)
{
auto &d = *(new DebugHSVPicker());
cv::namedWindow(PICK_WIN);
d.base.push_frame = t_debug_hsv_picker_frame;
d.node.break_apart = t_debug_hsv_picker_break_apart;
d.node.destroy = t_debug_hsv_picker_destroy;
d.passthrough = passthrough;
// Trackbars to set thresholds for HSV values
cv::createTrackbar("Low H", PICK_WIN, &low_H, max_value_H,
on_low_H_thresh_trackbar);
......@@ -225,9 +243,7 @@ t_debug_hsv_picker_create(struct xrt_frame_sink *passthrough,
t_convert_make_y8u8v8_to_h8s8v8(&d.yuv_to_hsv);
d.passthrough = passthrough;
d.base.push_frame = t_debug_hsv_picker_frame;
xrt_frame_context_add(xfctx, &d.node);
*out_sink = &d.base;
......
......@@ -26,6 +26,7 @@ class DebugHSV
{
public:
struct xrt_frame_sink base = {};
struct xrt_frame_node node = {};
struct xrt_frame_sink *passthrough;
......@@ -155,8 +156,20 @@ t_debug_hsv_viewer_frame(struct xrt_frame_sink *xsink, struct xrt_frame *xf)
d.passthrough->push_frame(d.passthrough, xf);
}
extern "C" void
t_debug_hsv_viewer_break_apart(struct xrt_frame_node *node)
{}
extern "C" void
t_debug_hsv_viewer_destroy(struct xrt_frame_node *node)
{
auto d = container_of(node, DebugHSV, node);
delete d;
}
extern "C" int
t_debug_hsv_viewer_create(struct xrt_frame_sink *passthrough,
t_debug_hsv_viewer_create(struct xrt_frame_context *xfctx,
struct xrt_frame_sink *passthrough,
struct xrt_frame_sink **out_sink)
{
auto &d = *(new DebugHSV());
......@@ -167,15 +180,18 @@ t_debug_hsv_viewer_create(struct xrt_frame_sink *passthrough,
cv::startWindowThread();
d.passthrough = passthrough;
d.base.push_frame = t_debug_hsv_viewer_frame;
d.node.break_apart = t_debug_hsv_viewer_break_apart;
d.node.destroy = t_debug_hsv_viewer_destroy;
d.passthrough = passthrough;
t_convert_make_y8u8v8_to_r8g8b8(&d.yuv_to_rgb_table);
struct t_hsv_filter_params params = T_HSV_DEFAULT_PARAMS();
t_hsv_build_large_table(&params, &d.hsv_large);
t_hsv_build_optimized_table(&params, &d.hsv_opt);
xrt_frame_context_add(xfctx, &d.node);
*out_sink = &d.base;
return 0;
......
......@@ -8,11 +8,13 @@
#include "util/u_misc.h"
#include "util/u_debug.h"
#include "util/u_frame.h"
#include "util/u_format.h"
#include "tracking/t_tracking.h"
#include <stdio.h>
#include <assert.h>
#define MOD_180(v) ((uint32_t)(v) % 180)
......@@ -130,19 +132,16 @@ t_hsv_build_optimized_table(struct t_hsv_filter_params *params,
struct t_hsv_filter
{
struct xrt_frame_sink base;
struct xrt_frame_node node;
struct xrt_frame_sink *sinks[NUM_CHANNELS];
struct t_hsv_filter_params params;
uint8_t *buf0;
uint8_t *buf1;
uint8_t *buf2;
uint8_t *buf3;
size_t buf_stride;
size_t buf_size;
uint32_t buf_width;
uint32_t buf_height;
struct xrt_frame *frame0;
struct xrt_frame *frame1;
struct xrt_frame *frame2;
struct xrt_frame *frame3;
struct t_hsv_filter_optimized_table table;
};
......@@ -168,12 +167,17 @@ process_sample(struct t_hsv_filter *f,
static void
process_frame_yuv(struct t_hsv_filter *f, struct xrt_frame *xf)
{
struct xrt_frame *f0 = f->frame0;
struct xrt_frame *f1 = f->frame1;
struct xrt_frame *f2 = f->frame2;
struct xrt_frame *f3 = f->frame3;
for (uint32_t y = 0; y < xf->height; y++) {
uint8_t *src = (uint8_t *)xf->data + y * xf->stride;
uint8_t *dst0 = f->buf0 + y * f->buf_stride;
uint8_t *dst1 = f->buf1 + y * f->buf_stride;
uint8_t *dst2 = f->buf2 + y * f->buf_stride;
uint8_t *dst3 = f->buf3 + y * f->buf_stride;
uint8_t *dst0 = f0->data + y * f0->stride;
uint8_t *dst1 = f1->data + y * f1->stride;
uint8_t *dst2 = f2->data + y * f2->stride;
uint8_t *dst3 = f3->data + y * f3->stride;
for (uint32_t x = 0; x < xf->width; x += 1) {
uint8_t y = src[0];
......@@ -193,12 +197,17 @@ process_frame_yuv(struct t_hsv_filter *f, struct xrt_frame *xf)
static void
process_frame_yuyv(struct t_hsv_filter *f, struct xrt_frame *xf)
{
struct xrt_frame *f0 = f->frame0;
struct xrt_frame *f1 = f->frame1;
struct xrt_frame *f2 = f->frame2;
struct xrt_frame *f3 = f->frame3;
for (uint32_t y = 0; y < xf->height; y++) {
uint8_t *src = (uint8_t *)xf->data + y * xf->stride;
uint8_t *dst0 = f->buf0 + y * f->buf_stride;
uint8_t *dst1 = f->buf1 + y * f->buf_stride;
uint8_t *dst2 = f->buf2 + y * f->buf_stride;
uint8_t *dst3 = f->buf3 + y * f->buf_stride;
uint8_t *dst0 = f0->data + y * f0->stride;
uint8_t *dst1 = f1->data + y * f1->stride;
uint8_t *dst2 = f2->data + y * f2->stride;
uint8_t *dst3 = f3->data + y * f3->stride;
for (uint32_t x = 0; x < xf->width; x += 2) {
uint8_t y1 = src[0];
......@@ -225,43 +234,34 @@ process_frame_yuyv(struct t_hsv_filter *f, struct xrt_frame *xf)
static void
ensure_buf_allocated(struct t_hsv_filter *f, struct xrt_frame *xf)
{
if (xf->width == f->buf_width && xf->width == f->buf_height) {
return;
}
uint32_t w = xf->width;
uint32_t h = xf->height;
free(f->buf0);
free(f->buf1);
free(f->buf2);
free(f->buf3);
f->buf_width = xf->width;
f->buf_height = xf->height;
f->buf_stride = f->buf_width;
f->buf_size = f->buf_stride * f->buf_height;
f->buf0 = U_TYPED_ARRAY_CALLOC(uint8_t, f->buf_size);
f->buf1 = U_TYPED_ARRAY_CALLOC(uint8_t, f->buf_size);
f->buf2 = U_TYPED_ARRAY_CALLOC(uint8_t, f->buf_size);
f->buf3 = U_TYPED_ARRAY_CALLOC(uint8_t, f->buf_size);
u_frame_create_one_off(XRT_FORMAT_L8, w, h, &f->frame0);
u_frame_create_one_off(XRT_FORMAT_L8, w, h, &f->frame1);
u_frame_create_one_off(XRT_FORMAT_L8, w, h, &f->frame2);
u_frame_create_one_off(XRT_FORMAT_L8, w, h, &f->frame3);
}
static void
push_buf(struct t_hsv_filter *f, struct xrt_frame_sink *xsink, uint8_t *buf)
push_buf(struct t_hsv_filter *f,
struct xrt_frame *xf,
struct xrt_frame_sink *xsink,
struct xrt_frame **frame)
{
if (xsink == NULL) {
xrt_frame_reference(frame, NULL);
return;
}
struct xrt_frame xf = {0};
(*frame)->timestamp = xf->timestamp;
(*frame)->source_id = xf->source_id;
(*frame)->source_sequence = xf->source_sequence;
(*frame)->source_timestamp = xf->source_timestamp;
xf.format = XRT_FORMAT_L8;
xf.width = f->buf_width;
xf.height = f->buf_height;
xf.stride = f->buf_stride;
xf.size = f->buf_size;
xf.data = buf;
xsink->push_frame(xsink, *frame);
xsink->push_frame(xsink, &xf);
xrt_frame_reference(frame, NULL);
}
static void
......@@ -269,31 +269,55 @@ push_frame(struct xrt_frame_sink *xsink, struct xrt_frame *xf)
{
struct t_hsv_filter *f = (struct t_hsv_filter *)xsink;
ensure_buf_allocated(f, xf);
switch (xf->format) {
case XRT_FORMAT_YUV888: process_frame_yuv(f, xf); break;
case XRT_FORMAT_YUV422: process_frame_yuyv(f, xf); break;
case XRT_FORMAT_YUV888:
ensure_buf_allocated(f, xf);
process_frame_yuv(f, xf);
break;
case XRT_FORMAT_YUV422:
ensure_buf_allocated(f, xf);
process_frame_yuyv(f, xf);
break;
default:
fprintf(stderr, "ERROR: Bad format '%s'",
u_format_str(xf->format));
return;
}
push_buf(f, f->sinks[0], f->buf0);
push_buf(f, f->sinks[1], f->buf1);
push_buf(f, f->sinks[2], f->buf2);
push_buf(f, f->sinks[3], f->buf3);
push_buf(f, xf, f->sinks[0], &f->frame0);
push_buf(f, xf, f->sinks[1], &f->frame1);
push_buf(f, xf, f->sinks[2], &f->frame2);
push_buf(f, xf, f->sinks[3], &f->frame3);
assert(f->frame0 == NULL);
assert(f->frame1 == NULL);
assert(f->frame2 == NULL);
assert(f->frame3 == NULL);
}
static void
break_apart(struct xrt_frame_node *node)
{}
static void
destroy(struct xrt_frame_node *node)
{
struct t_hsv_filter *f = container_of(node, struct t_hsv_filter, node);
free(f);
}
int
t_hsv_filter_create(struct t_hsv_filter_params *params,
t_hsv_filter_create(struct xrt_frame_context *xfctx,
struct t_hsv_filter_params *params,
struct xrt_frame_sink *sinks[4],
struct xrt_frame_sink **out_sink)
{
struct t_hsv_filter *f = U_TYPED_CALLOC(struct t_hsv_filter);
f->params = *params;
f->base.push_frame = push_frame;
f->node.break_apart = break_apart;
f->node.destroy = destroy;
f->params = *params;
f->sinks[0] = sinks[0];
f->sinks[1] = sinks[1];
f->sinks[2] = sinks[2];
......@@ -301,6 +325,8 @@ t_hsv_filter_create(struct t_hsv_filter_params *params,
t_hsv_build_optimized_table(&f->params, &f->table);
xrt_frame_context_add(xfctx, &f->node);
*out_sink = &f->base;
return 0;
......
......@@ -130,7 +130,8 @@ t_hsv_filter_sample(struct t_hsv_filter_optimized_table *t,
}
int
t_hsv_filter_create(struct t_hsv_filter_params *params,
t_hsv_filter_create(struct xrt_frame_context *xfctx,
struct t_hsv_filter_params *params,
struct xrt_frame_sink *sinks[4],
struct xrt_frame_sink **out_sink);
......@@ -146,19 +147,23 @@ t_convert_yuv_or_yuyv_create(struct xrt_frame_sink *next,
struct xrt_frame_sink **out_sink);
int
t_calibration_create(struct xrt_frame_sink *gui,
t_calibration_create(struct xrt_frame_context *xfctx,
struct xrt_frame_sink *gui,
struct xrt_frame_sink **out_sink);
int
t_debug_hsv_picker_create(struct xrt_frame_sink *passthrough,
t_debug_hsv_picker_create(struct xrt_frame_context *xfctx,
struct xrt_frame_sink *passthrough,
struct xrt_frame_sink **out_sink);
int
t_debug_hsv_viewer_create(struct xrt_frame_sink *passthrough,
t_debug_hsv_viewer_create(struct xrt_frame_context *xfctx,
struct xrt_frame_sink *passthrough,
struct xrt_frame_sink **out_sink);
int
t_debug_hsv_filter_create(struct xrt_frame_sink *passthrough,
t_debug_hsv_filter_create(struct xrt_frame_context *xfctx,
struct xrt_frame_sink *passthrough,
struct xrt_frame_sink **out_sink);
......
// Copyright 2019, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief @ref xrt_frame helpers.
* @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup aux_util
*/
#include "util/u_misc.h"
#include "util/u_frame.h"
#include "util/u_format.h"
#include <assert.h>
static void
free_one_off(struct xrt_frame *xf)
{
assert(xf->reference.count == 0);
free(xf->data);
free(xf);
}
void
u_frame_create_one_off(enum xrt_format f,
uint32_t width,
uint32_t height,
struct xrt_frame **out_frame)
{
assert(width > 0);
assert(height > 0);
assert(u_format_is_blocks(f));
struct xrt_frame *xf = U_TYPED_CALLOC(struct xrt_frame);
xf->format = f;
xf->width = width;
xf->height = height;
xf->destroy = free_one_off;
u_format_size_for_dimensions(f, width, height, &xf->stride, &xf->size);
xf->data = (uint8_t *)realloc(xf->data, xf->size);
xrt_frame_reference(out_frame, xf);
}
// Copyright 2019, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief @ref xrt_frame helpers.
* @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup aux_util
*/
#pragma once
#include "xrt/xrt_frame.h"
#ifdef __cplusplus
extern "C" {
#endif
/*!
* Creates a single non-pooled frame, when the reference reaches zero it is
* freed.
*/
void
u_frame_create_one_off(enum xrt_format f,
uint32_t width,
uint32_t height,
struct xrt_frame **out_frame);
#ifdef __cplusplus
}
#endif
......@@ -17,14 +17,21 @@ extern "C" {
void
u_sink_create_format_converter(enum xrt_format f,
u_sink_create_format_converter(struct xrt_frame_context *xfctx,
enum xrt_format f,
struct xrt_frame_sink *downstream,
struct xrt_frame_sink **out_xfs);
void
u_sink_create_to_yuv_or_yuyv(struct xrt_frame_sink *downstream,
u_sink_create_to_yuv_or_yuyv(struct xrt_frame_context *xfctx,
struct xrt_frame_sink *downstream,
struct xrt_frame_sink **out_xfs);
bool
u_sink_queue_create(struct xrt_frame_context *xfctx,
struct xrt_frame_sink *downstream,
struct xrt_frame_sink **out_xfs);
#ifdef __cplusplus
}
......
......@@ -9,6 +9,7 @@
#include "util/u_misc.h"
#include "util/u_sink.h"
#include "util/u_frame.h"
#include "util/u_format.h"
#include <stdio.h>
......@@ -27,15 +28,12 @@
struct u_sink_converter
{
struct xrt_frame_sink base;
struct xrt_frame_node node;
struct xrt_frame_sink *downstream;
uint8_t *data;
struct xrt_frame *frame;
size_t size;
size_t stride;
uint32_t width;
uint32_t height;
enum xrt_format format;