summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSakari Ailus <sakari.ailus@iki.fi>2012-05-23 01:30:57 +0300
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-05-25 12:19:29 +0200
commit79fc1080b905dc3d61a93c31f68acaf3b4985c57 (patch)
tree5736f16181fb81ed10604485c54fd6ac644ba1ec
parent4aa40df9cfaf6f94b9207023d8ac9250847d2150 (diff)
New, more flexible syntax for format
More flexible and extensible syntax for format which allows better usage of the selection API. Continue supporting the old syntax but remove the documentation for it. It was not supported in an official release and its use is thus deprecated. Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-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 != ']')