summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.c20
-rw-r--r--src/options.c36
-rw-r--r--src/v4l2subdev.c90
3 files changed, 102 insertions, 44 deletions
diff --git a/src/main.c b/src/main.c
index 53964e4..ca633c8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -59,16 +59,25 @@ static void v4l2_subdev_print_format(struct media_entity *entity,
if (ret != 0)
return;
- printf("[%s %ux%u", v4l2_subdev_pixelcode_to_string(format.code),
+ printf("\t\t[fmt:%s/%ux%u",
+ v4l2_subdev_pixelcode_to_string(format.code),
format.width, format.height);
ret = v4l2_subdev_get_selection(entity, &rect, pad,
+ V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS,
+ which);
+ if (ret == 0)
+ printf("\n\t\t crop.bounds:(%u,%u)/%ux%u", rect.left, rect.top,
+ rect.width, rect.height);
+
+ ret = v4l2_subdev_get_selection(entity, &rect, pad,
V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL,
which);
if (ret == 0)
- printf(" (%u,%u)/%ux%u", rect.left, rect.top,
+ printf("\n\t\t crop:(%u,%u)/%ux%u", rect.left, rect.top,
rect.width, rect.height);
- printf("]");
+
+ printf("]\n");
}
static const char *media_entity_type_to_string(unsigned type)
@@ -252,13 +261,11 @@ static void media_print_topology_text(struct media_device *media)
for (j = 0; j < entity->info.pads; j++) {
struct media_pad *pad = &entity->pads[j];
- printf("\tpad%u: %s ", j, media_pad_type_to_string(pad->flags));
+ printf("\tpad%u: %s\n", j, media_pad_type_to_string(pad->flags));
if (media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV)
v4l2_subdev_print_format(entity, j, V4L2_SUBDEV_FORMAT_ACTIVE);
- printf("\n");
-
for (k = 0; k < entity->num_links; k++) {
struct media_link *link = &entity->links[k];
struct media_pad *source = link->source;
@@ -364,7 +371,6 @@ int main(int argc, char **argv)
v4l2_subdev_print_format(pad->entity, pad->index,
V4L2_SUBDEV_FORMAT_ACTIVE);
- printf("\n");
}
if (media_opts.print || media_opts.print_dot) {
diff --git a/src/options.c b/src/options.c
index d71d11b..f367daf 100644
--- a/src/options.c
+++ b/src/options.c
@@ -37,8 +37,8 @@ static void usage(const char *argv0, int verbose)
printf("%s [options] device\n", argv0);
printf("-d, --device dev Media device name (default: %s)\n", MEDIA_DEVNAME_DEFAULT);
printf("-e, --entity name Print the device name associated with the given entity\n");
- printf("-f, --set-format Comma-separated list of formats to setup\n");
- printf(" --get-format pad Print the active format on a given pad\n");
+ printf("-V, --set-v4l2 v4l2 Comma-separated list of formats to setup\n");
+ printf(" --get-v4l2 pad Print the active format on a given pad\n");
printf("-h, --help Show verbose help and exit\n");
printf("-i, --interactive Modify links interactively\n");
printf("-l, --links Comma-separated list of links descriptors to setup\n");
@@ -53,16 +53,22 @@ static void usage(const char *argv0, int verbose)
printf("\n");
printf("Links and formats are defined as\n");
printf("\tlink = pad '->' pad '[' flags ']' ;\n");
- printf("\tformat = pad '[' fcc ' ' size [ ' ' crop ] [ ' ' '@' frame interval ] ']' ;\n");
- printf("\tpad = entity ':' pad number ;\n");
- printf("\tentity = entity number | ( '\"' entity name '\"' ) ;\n");
+ printf("\tpad = entity ':' pad-number ;\n");
+ printf("\tentity = entity-number | ( '\"' entity-name '\"' ) ;\n");
+ printf("\n");
+ printf("\tv4l2 = pad '[' v4l2-properties ']' ;\n");
+ printf("\tv4l2-properties = v4l2-property { ',' v4l2-property } ;\n");
+ printf("\tv4l2-property = v4l2-mbusfmt | v4l2-crop | v4l2-interval ;\n");
+ printf("\tv4l2-mbusfmt = 'fmt:' fcc '/' size ;\n");
+ printf("\tv4l2-crop = 'crop:' '(' left ',' top ')' '/' size ;\n");
+ printf("\tv4l2-interval = '@' numerator '/' denominator ;\n");
+ printf("\n");
printf("\tsize = width 'x' height ;\n");
- printf("\tcrop = '(' left ',' top ')' '/' size ;\n");
- printf("\tframe interval = numerator '/' denominator ;\n");
+ printf("\n");
printf("where the fields are\n");
- printf("\tentity number Entity numeric identifier\n");
- printf("\tentity name Entity name (string) \n");
- printf("\tpad number Pad numeric identifier\n");
+ printf("\tentity-number Entity numeric identifier\n");
+ printf("\tentity-name Entity name (string) \n");
+ printf("\tpad-number Pad numeric identifier\n");
printf("\tflags Link flags (0: inactive, 1: active)\n");
printf("\tfcc Format FourCC\n");
printf("\twidth Image width in pixels\n");
@@ -78,7 +84,9 @@ static struct option opts[] = {
{"device", 1, 0, 'd'},
{"entity", 1, 0, 'e'},
{"set-format", 1, 0, 'f'},
+ {"set-v4l2", 1, 0, 'V'},
{"get-format", 1, 0, OPT_GET_FORMAT},
+ {"get-v4l2", 1, 0, OPT_GET_FORMAT},
{"help", 0, 0, 'h'},
{"interactive", 0, 0, 'i'},
{"links", 1, 0, 'l'},
@@ -98,7 +106,7 @@ int parse_cmdline(int argc, char **argv)
}
/* parse options */
- while ((opt = getopt_long(argc, argv, "d:e:f:hil:prv", opts, NULL)) != -1) {
+ while ((opt = getopt_long(argc, argv, "d:e:f:hil:prvV:", opts, NULL)) != -1) {
switch (opt) {
case 'd':
media_opts.devname = optarg;
@@ -108,7 +116,13 @@ int parse_cmdline(int argc, char **argv)
media_opts.entity = optarg;
break;
+ /* 'f' is supported for backward compatibility reasons and will
+ * be removed later.
+ */
case 'f':
+ fprintf(stderr, "Warning: the -f option is deprecated "
+ "and has been replaced by -V.\n");
+ case 'V':
media_opts.formats = optarg;
break;
diff --git a/src/v4l2subdev.c b/src/v4l2subdev.c
index a2ab0c4..bc33610 100644
--- a/src/v4l2subdev.c
+++ b/src/v4l2subdev.c
@@ -25,6 +25,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
@@ -232,14 +233,19 @@ static int v4l2_subdev_parse_format(struct v4l2_mbus_framefmt *format,
unsigned int width, height;
char *end;
+ /*
+ * Compatibility with the old syntax: consider space as valid
+ * separator between the media bus pixel code and the size.
+ */
for (; isspace(*p); ++p);
- for (end = (char *)p; !isspace(*end) && *end != '\0'; ++end);
+ for (end = (char *)p;
+ *end != '/' && *end != ' ' && *end != '\0'; ++end);
code = v4l2_subdev_string_to_pixelcode(p, end - p);
if (code == (enum v4l2_mbus_pixelcode)-1)
return -EINVAL;
- for (p = end; isspace(*p); ++p);
+ p = end + 1;
width = strtoul(p, &end, 10);
if (*end != 'x')
return -EINVAL;
@@ -256,32 +262,32 @@ static int v4l2_subdev_parse_format(struct v4l2_mbus_framefmt *format,
return 0;
}
-static int v4l2_subdev_parse_crop(
- struct v4l2_rect *crop, const char *p, char **endp)
+static int v4l2_subdev_parse_rectangle(
+ struct v4l2_rect *r, const char *p, char **endp)
{
char *end;
if (*p++ != '(')
return -EINVAL;
- crop->left = strtoul(p, &end, 10);
+ r->left = strtoul(p, &end, 10);
if (*end != ',')
return -EINVAL;
p = end + 1;
- crop->top = strtoul(p, &end, 10);
+ r->top = strtoul(p, &end, 10);
if (*end++ != ')')
return -EINVAL;
if (*end != '/')
return -EINVAL;
p = end + 1;
- crop->width = strtoul(p, &end, 10);
+ r->width = strtoul(p, &end, 10);
if (*end != 'x')
return -EINVAL;
p = end + 1;
- crop->height = strtoul(p, &end, 10);
+ r->height = strtoul(p, &end, 10);
*endp = end;
return 0;
@@ -307,12 +313,29 @@ static int v4l2_subdev_parse_frame_interval(struct v4l2_fract *interval,
return 0;
}
+/*
+ * The debate over whether this function should be named icanhasstr() instead
+ * has been strong and heated. If you feel like this would be an important
+ * change, patches are welcome (or not).
+ */
+static bool strhazit(const char *str, const char **p)
+{
+ int len = strlen(str);
+
+ if (strncmp(str, *p, len))
+ return false;
+
+ for (*p += len; isspace(**p); ++*p);
+ return true;
+}
+
static struct media_pad *v4l2_subdev_parse_pad_format(
struct media_device *media, struct v4l2_mbus_framefmt *format,
struct v4l2_rect *crop, struct v4l2_fract *interval, const char *p,
char **endp)
{
struct media_pad *pad;
+ bool first;
char *end;
int ret;
@@ -326,30 +349,45 @@ static struct media_pad *v4l2_subdev_parse_pad_format(
if (*p++ != '[')
return NULL;
- for (; isspace(*p); ++p);
+ for (first = true; ; first = false) {
+ for (; isspace(*p); p++);
- if (isalnum(*p)) {
- ret = v4l2_subdev_parse_format(format, p, &end);
- if (ret < 0)
- return NULL;
+ /*
+ * Backward compatibility: if the first property starts with an
+ * uppercase later, process it as a format description.
+ */
+ if (strhazit("fmt:", &p) || (first && isupper(*p))) {
+ ret = v4l2_subdev_parse_format(format, p, &end);
+ if (ret < 0)
+ return NULL;
- for (p = end; isspace(*p); p++);
- }
+ p = end;
+ continue;
+ }
- if (*p == '(') {
- ret = v4l2_subdev_parse_crop(crop, p, &end);
- if (ret < 0)
- return NULL;
+ /*
+ * Backward compatibility: crop rectangles can be specified
+ * implicitly without the 'crop:' property name.
+ */
+ if (strhazit("crop:", &p) || *p == '(') {
+ ret = v4l2_subdev_parse_rectangle(crop, p, &end);
+ if (ret < 0)
+ return NULL;
+
+ p = end;
+ continue;
+ }
- for (p = end; isspace(*p); p++);
- }
+ if (*p == '@') {
+ ret = v4l2_subdev_parse_frame_interval(interval, ++p, &end);
+ if (ret < 0)
+ return NULL;
- if (*p == '@') {
- ret = v4l2_subdev_parse_frame_interval(interval, ++p, &end);
- if (ret < 0)
- return NULL;
+ p = end;
+ continue;
+ }
- for (p = end; isspace(*p); p++);
+ break;
}
if (*p != ']')