v4l2: support meta_videotransform on buffers

Advertise support for the videotransform metadata.
Make a new meta.videotransform.transform property to configure the
desired video transformation in the metadata.

This makes it possible for a session manager or other rules to set
a custom transformation on the source.

See #4034
This commit is contained in:
Wim Taymans 2024-06-07 10:52:39 +02:00
parent 6bb1d0476d
commit 4d7c81bd90
2 changed files with 27 additions and 7 deletions

View file

@ -26,6 +26,7 @@
#include <spa/param/latency-utils.h>
#include <spa/pod/filter.h>
#include <spa/control/control.h>
#include <spa/debug/types.h>
#include "v4l2.h"
@ -54,6 +55,7 @@ struct buffer {
struct spa_list link;
struct spa_buffer *outbuf;
struct spa_meta_header *h;
struct spa_meta_videotransform *vt;
struct v4l2_buffer v4l2_buffer;
void *ptr;
};
@ -121,6 +123,8 @@ struct impl {
struct spa_log *log;
struct spa_loop *data_loop;
enum spa_meta_videotransform_value transform;
uint64_t info_all;
struct spa_node_info info;
#define NODE_PropInfo 0
@ -580,6 +584,12 @@ static int impl_node_port_enum_params(void *object, int seq,
SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header),
SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header)));
break;
case 1:
param = spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_ParamMeta, id,
SPA_PARAM_META_type, SPA_POD_Id(SPA_META_VideoTransform),
SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_videotransform)));
break;
default:
return 0;
}
@ -965,8 +975,8 @@ impl_init(const struct spa_handle_factory *factory,
uint32_t n_support)
{
struct impl *this;
const char *str;
struct port *port;
uint32_t i;
int res;
spa_return_val_if_fail(factory != NULL, -EINVAL);
@ -1033,13 +1043,18 @@ impl_init(const struct spa_handle_factory *factory,
port->dev.log = this->log;
port->dev.fd = -1;
if (info && (str = spa_dict_lookup(info, SPA_KEY_API_V4L2_PATH))) {
strncpy(this->props.device, str, 63);
if ((res = spa_v4l2_open(&port->dev, this->props.device)) < 0)
return res;
spa_v4l2_close(&port->dev);
for (i = 0; info && i < info->n_items; i++) {
const char *k = info->items[i].key;
const char *s = info->items[i].value;
if (spa_streq(k, SPA_KEY_API_V4L2_PATH)) {
strncpy(this->props.device, s, 63);
if ((res = spa_v4l2_open(&port->dev, this->props.device)) < 0)
return res;
spa_v4l2_close(&port->dev);
} else if (spa_streq(k, "meta.videotransform.transform")) {
this->transform = spa_debug_type_find_type_short(spa_type_meta_videotransform_type, s);
}
}
return 0;
}

View file

@ -1400,6 +1400,9 @@ static int mmap_read(struct impl *this)
b->h->pts = pts;
b->h->dts_offset = 0;
}
if (b->vt) {
b->vt->transform = this->transform;
}
d = b->outbuf->datas;
d[0].chunk->offset = 0;
@ -1507,6 +1510,7 @@ static int spa_v4l2_use_buffers(struct impl *this, struct spa_buffer **buffers,
b->outbuf = buffers[i];
b->flags = BUFFER_FLAG_OUTSTANDING;
b->h = spa_buffer_find_meta_data(buffers[i], SPA_META_Header, sizeof(*b->h));
b->vt = spa_buffer_find_meta_data(buffers[i], SPA_META_VideoTransform, sizeof(*b->vt));
spa_log_debug(this->log, "import buffer %p", buffers[i]);
@ -1602,6 +1606,7 @@ mmap_init(struct impl *this,
b->outbuf = buffers[i];
b->flags = BUFFER_FLAG_OUTSTANDING;
b->h = spa_buffer_find_meta_data(buffers[i], SPA_META_Header, sizeof(*b->h));
b->vt = spa_buffer_find_meta_data(buffers[i], SPA_META_VideoTransform, sizeof(*b->vt));
spa_zero(b->v4l2_buffer);
b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;