diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index b06dda994..6b6dcff0d 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -90,6 +90,7 @@ struct port { struct v4l2_frmivalenum frmival; bool have_format; + bool have_modifier; struct spa_video_info current_format; struct spa_v4l2_device dev; @@ -219,6 +220,12 @@ static int port_get_format(struct port *port, case SPA_MEDIA_SUBTYPE_raw: spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_format, SPA_POD_Id(port->current_format.info.raw.format), + 0); + if (port->have_modifier) + spa_pod_builder_add(builder, + SPA_FORMAT_VIDEO_modifier, SPA_POD_Long(0), + 0); + spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&port->current_format.info.raw.size), SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&port->current_format.info.raw.framerate), 0); @@ -706,6 +713,7 @@ static int port_set_format(struct impl *this, struct port *port, spa_log_error(this->log, "can't parse video raw"); return -EINVAL; } + port->have_modifier = info.info.raw.flags & SPA_VIDEO_FLAG_MODIFIER; break; case SPA_MEDIA_SUBTYPE_mjpg: if (spa_format_video_mjpg_parse(format, &info.info.mjpg) < 0) diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index 58758f758..7e972dc6e 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -513,11 +513,12 @@ spa_v4l2_enum_format(struct impl *this, int seq, struct spa_pod_frame f[2]; struct spa_result_node_params result; uint32_t count = 0; + bool with_modifier; if ((res = spa_v4l2_open(dev, this->props.device)) < 0) return res; - spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 8192); spa_pod_builder_get_state(&b.b, &state); result.id = SPA_PARAM_EnumFormat; @@ -537,6 +538,7 @@ spa_v4l2_enum_format(struct impl *this, int seq, if ((res = spa_format_parse(filter, &filter_media_type, &filter_media_subtype)) < 0) return res; } + with_modifier = !filter || spa_pod_find_prop(filter, NULL, SPA_FORMAT_VIDEO_modifier); if (false) { next_fmtdesc: @@ -729,6 +731,10 @@ do_frmsize_filter: if (info->media_subtype == SPA_MEDIA_SUBTYPE_raw) { spa_pod_builder_prop(&b.b, SPA_FORMAT_VIDEO_format, 0); spa_pod_builder_id(&b.b, info->format); + if (with_modifier) { + spa_pod_builder_prop(&b.b, SPA_FORMAT_VIDEO_modifier, SPA_POD_PROP_FLAG_MANDATORY); + spa_pod_builder_long(&b.b, 0L); + } } spa_pod_builder_prop(&b.b, SPA_FORMAT_VIDEO_size, 0); @@ -899,6 +905,27 @@ do_frminterval_filter: spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + if (++count == num) + goto enum_end; + + if (with_modifier && info->media_subtype == SPA_MEDIA_SUBTYPE_raw) { + struct spa_pod_object *op = (struct spa_pod_object *) result.param; + const struct spa_pod_prop *p; + bool drop_next = false; + + spa_pod_builder_push_object(&b.b, &f[0], op->body.type, op->body.id); + + SPA_POD_OBJECT_FOREACH(op, p) { + if (p->key != SPA_FORMAT_VIDEO_modifier) + spa_pod_builder_raw_padded(&b.b, p, SPA_POD_PROP_SIZE(p)); + } + + result.index = result.next++; + result.param = spa_pod_builder_pop(&b.b, &f[0]); + + spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + } + if (++count != num) goto next;