summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c82
-rw-r--r--options.c28
-rw-r--r--subdev.c45
-rw-r--r--subdev.h4
4 files changed, 147 insertions, 12 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 == ',');
diff --git a/options.c b/options.c
index 5e4c9f7..69ff9d5 100644
--- a/options.c
+++ b/options.c
@@ -30,19 +30,39 @@ struct media_options media_opts = {
.devname = MEDIA_DEVNAME_DEFAULT,
};
-static void usage(const char *argv0)
+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, --formats Comma-separated list of formats to setup\n");
- printf("-h, --help Show this help screen\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("-p, --print-topology Print the device topology (implies -v)\n");
printf(" --print-dot Print the device topology as a dot graph (implies -v)\n");
printf("-r, --reset Reset all links to inactive\n");
printf("-v, --verbose Be verbose\n");
+
+ if (!verbose)
+ return;
+
+ printf("\n");
+ printf("Links and formats are defined as\n");
+ printf("\tlink = pad, '->', pad, '[', flags, ']' ;\n");
+ printf("\tformat = pad, '[', fcc, ' ', size, [ ' ', crop ], ']' ;\n");
+ printf("\tpad = entity, ':', pad number ;\n");
+ printf("\tentity = entity number | ( '\"', entity name, '\"' ) ;\n");
+ printf("\tsize = width, 'x', height ;\n");
+ printf("\tcrop = left, ',', top, '/', size ;\n");
+ printf("where the fields are\n");
+ printf("\tentity number Entity numeric identifier\n");
+ printf("\tentity name Entify 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("\theight Image height in pixels\n");
}
#define OPT_PRINT_DOT 256
@@ -65,7 +85,7 @@ int parse_cmdline(int argc, char **argv)
int opt;
if (argc == 1) {
- usage(argv[0]);
+ usage(argv[0], 0);
return 1;
}
@@ -85,7 +105,7 @@ int parse_cmdline(int argc, char **argv)
break;
case 'h':
- usage(argv[0]);
+ usage(argv[0], 1);
exit(0);
case 'i':
diff --git a/subdev.c b/subdev.c
index c35b5b4..ac14324 100644
--- a/subdev.c
+++ b/subdev.c
@@ -133,3 +133,48 @@ int v4l2_subdev_set_format(struct media_entity *entity,
return 0;
}
+int v4l2_subdev_get_crop(struct media_entity *entity, struct v4l2_rect *rect,
+ unsigned int pad, enum v4l2_subdev_format which)
+{
+ struct v4l2_subdev_pad_crop crop;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&crop, 0, sizeof(crop));
+ crop.pad = pad;
+ crop.which = which;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_CROP, &crop);
+ if (ret < 0)
+ return -errno;
+
+ *rect = crop.rect;
+ return 0;
+}
+
+int v4l2_subdev_set_crop(struct media_entity *entity, struct v4l2_rect *rect,
+ unsigned int pad, enum v4l2_subdev_format which)
+{
+ struct v4l2_subdev_pad_crop crop;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&crop, 0, sizeof(crop));
+ crop.pad = pad;
+ crop.which = which;
+ crop.rect = *rect;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_CROP, &crop);
+ if (ret < 0)
+ return -errno;
+
+ *rect = crop.rect;
+ return 0;
+}
+
diff --git a/subdev.h b/subdev.h
index c431271..e3106e6 100644
--- a/subdev.h
+++ b/subdev.h
@@ -34,6 +34,10 @@ int v4l2_subdev_get_format(struct media_entity *entity,
int v4l2_subdev_set_format(struct media_entity *entity,
struct v4l2_mbus_framefmt *format, unsigned int pad,
enum v4l2_subdev_format which);
+int v4l2_subdev_get_crop(struct media_entity *entity, struct v4l2_rect *rect,
+ unsigned int pad, enum v4l2_subdev_format which);
+int v4l2_subdev_set_crop(struct media_entity *entity, struct v4l2_rect *rect,
+ unsigned int pad, enum v4l2_subdev_format which);
#endif