From 4d7c81bd906273a14ff884418f10eeeb9c2a75de Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 7 Jun 2024 10:52:39 +0200 Subject: [PATCH] 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 --- spa/plugins/v4l2/v4l2-source.c | 29 ++++++++++++++++++++++------- spa/plugins/v4l2/v4l2-utils.c | 5 +++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index f101ed7cf..e003fe07d 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -26,6 +26,7 @@ #include #include #include +#include #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; } diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index 4c583355c..cf48bfb8b 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -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;