diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2010-06-29 12:09:35 +0200 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2010-06-29 12:09:35 +0200 |
commit | c13258a74fd7345828fce8fab117247e3f61e6e5 (patch) | |
tree | b29a1420ce9648b283cc32fc35ff9504f93e229b /main.c | |
parent | 0c4da2bb2f4d7d3cd2cdea1369374d5b4f7e3b29 (diff) |
V4L2 subdev crop support
Extend the V4L2 media bus format syntax to support an optional crop
rectangle. If specified, the crop rectangle is set on the subdev pad.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 82 |
1 files changed, 74 insertions, 8 deletions
@@ -203,8 +203,36 @@ static int parse_format(struct v4l2_mbus_framefmt *format, const char *p, char * return 0; } +static int parse_crop(struct v4l2_rect *crop, const char *p, char **endp) +{ + char *end; + + for (; isspace(*p); ++p); + + crop->left = strtoul(p, &end, 10); + if (*end != ',') + return -EINVAL; + + p = end + 1; + crop->top = strtoul(p, &end, 10); + if (*end != '/') + return -EINVAL; + + p = end + 1; + crop->width = strtoul(p, &end, 10); + if (*end != 'x') + return -EINVAL; + + p = end + 1; + crop->height = strtoul(p, &end, 10); + *endp = end; + + return 0; +} + static struct media_entity_pad *parse_pad_format(struct media_device *media, - struct v4l2_mbus_framefmt *format, const char *p, char **endp) + struct v4l2_mbus_framefmt *format, struct v4l2_rect *crop, + const char *p, char **endp) { struct media_entity_pad *pad; char *end; @@ -225,10 +253,18 @@ static struct media_entity_pad *parse_pad_format(struct media_device *media, return NULL; for (p = end; isspace(*p); p++); - if (*p++ != ']') + if (*p != ']') { + ret = parse_crop(crop, p, &end); + if (ret < 0) + return NULL; + + for (p = end; isspace(*p); p++); + } + + if (*p != ']') return NULL; - *endp = (char *)p; + *endp = (char *)p + 1; return pad; } @@ -253,23 +289,55 @@ static int set_format(struct media_entity_pad *pad, struct v4l2_mbus_framefmt *f return 0; } +static int set_crop(struct media_entity_pad *pad, struct v4l2_rect *crop) +{ + int ret; + + printf("Setting up crop rectangle %u,%u/%ux%u on pad %s/%u\n", + crop->left, crop->top, crop->width, crop->height, + pad->entity->info.name, pad->index); + + ret = v4l2_subdev_set_crop(pad->entity, crop, pad->index, + V4L2_SUBDEV_FORMAT_ACTIVE); + if (ret < 0) { + printf("Unable to set crop rectangle: %s (%d)", strerror(-ret), ret); + return ret; + } + + printf("Crop rectangle set: %u,%u/%ux%u\n", + crop->left, crop->top, crop->width, crop->height); + + return 0; +} + static int setup_format(struct media_device *media, const char *p, char **endp) { struct v4l2_mbus_framefmt format; struct media_entity_pad *pad; + struct v4l2_rect crop = { -1, -1, -1, -1 }; unsigned int i; char *end; int ret; - pad = parse_pad_format(media, &format, p, &end); + pad = parse_pad_format(media, &format, &crop, p, &end); if (pad == NULL) { printf("Unable to parse format\n"); return -EINVAL; } ret = set_format(pad, &format); - if (ret < 0) + if (ret < 0) { + printf("Unable to set format\n"); return ret; + } + + if (crop.left != -1 && crop.top != -1) { + ret = set_crop(pad, &crop); + if (ret < 0) { + printf("Unable to set crop rectangle\n"); + return ret; + } + } /* If the pad is an output pad, automatically set the same format on * the remote subdev input pads, if any. @@ -301,10 +369,8 @@ static int setup_formats(struct media_device *media, const char *p) do { ret = setup_format(media, p, &end); - if (ret < 0) { - printf("Unable to parse format\n"); + if (ret < 0) return ret; - } p = end + 1; } while (*end == ','); |