diff options
-rw-r--r-- | src/main.c | 20 | ||||
-rw-r--r-- | src/options.c | 36 | ||||
-rw-r--r-- | src/v4l2subdev.c | 90 |
3 files changed, 102 insertions, 44 deletions
@@ -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 != ']') |