summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2010-06-29 12:09:35 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2010-06-29 12:09:35 +0200
commitc13258a74fd7345828fce8fab117247e3f61e6e5 (patch)
treeb29a1420ce9648b283cc32fc35ff9504f93e229b /main.c
parent0c4da2bb2f4d7d3cd2cdea1369374d5b4f7e3b29 (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.c82
1 files changed, 74 insertions, 8 deletions
diff --git a/main.c b/main.c
index c59b633..9b8951a 100644
--- a/main.c
+++ b/main.c
@@ -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 == ',');