New, more flexible syntax for format
authorSakari Ailus <sakari.ailus@iki.fi>
Tue, 22 May 2012 22:30:57 +0000 (01:30 +0300)
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Fri, 25 May 2012 10:19:29 +0000 (12:19 +0200)
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>
src/main.c
src/options.c
src/v4l2subdev.c

index 53964e49b47df950cd5f5672dd2e07b31a3a0483..ca633c809c95b20d98772e5086b4d3ca8224fee7 100644 (file)
@@ -59,16 +59,25 @@ static void v4l2_subdev_print_format(struct media_entity *entity,
        if (ret != 0)
                return;
 
        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);
 
               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)
        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);
                       rect.width, rect.height);
-       printf("]");
+
+       printf("]\n");
 }
 
 static const char *media_entity_type_to_string(unsigned type)
 }
 
 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];
 
                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);
 
 
                        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;
                        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);
 
                v4l2_subdev_print_format(pad->entity, pad->index,
                                         V4L2_SUBDEV_FORMAT_ACTIVE);
-               printf("\n");
        }
 
        if (media_opts.print || media_opts.print_dot) {
        }
 
        if (media_opts.print || media_opts.print_dot) {
index d71d11bef3403cfd5be4de5feb5a888a6c09098d..f367daf6a8195834327eeb34c57d45aa9cf37261 100644 (file)
@@ -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("%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");
        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("\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("\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("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");
        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'},
        {"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-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'},
        {"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 */
        }
 
        /* 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;
                switch (opt) {
                case 'd':
                        media_opts.devname = optarg;
@@ -108,7 +116,13 @@ int parse_cmdline(int argc, char **argv)
                        media_opts.entity = optarg;
                        break;
 
                        media_opts.entity = optarg;
                        break;
 
+               /* 'f' is supported for backward compatibility reasons and will
+                * be removed later.
+                */
                case 'f':
                case 'f':
+                       fprintf(stderr, "Warning: the -f option is deprecated "
+                               "and has been replaced by -V.\n");
+               case 'V':
                        media_opts.formats = optarg;
                        break;
 
                        media_opts.formats = optarg;
                        break;
 
index a2ab0c42e75ab48606dcb8e86ffc63661898422b..bc336104c7c112e10d4f43af3a1d1147dfeeb77e 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
 
 #include <errno.h>
 #include <fcntl.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.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;
 
        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 (; 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;
 
 
        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;
        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;
 }
 
        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;
 
 {
        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;
        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;
        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;
        if (*end != 'x')
                return -EINVAL;
 
        p = end + 1;
-       crop->height = strtoul(p, &end, 10);
+       r->height = strtoul(p, &end, 10);
        *endp = end;
 
        return 0;
        *endp = end;
 
        return 0;
@@ -307,12 +313,29 @@ static int v4l2_subdev_parse_frame_interval(struct v4l2_fract *interval,
        return 0;
 }
 
        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;
 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;
 
        char *end;
        int ret;
 
@@ -326,30 +349,45 @@ static struct media_pad *v4l2_subdev_parse_pad_format(
        if (*p++ != '[')
                return NULL;
 
        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 != ']')
        }
 
        if (*p != ']')