summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodor Tomov <ttomov@mm-sol.com>2010-06-30 10:55:43 +0300
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2010-07-01 10:34:32 +0200
commita04e11ca5bbf2a44539ee14e3077358a21262ba2 (patch)
tree8ea3e86da132a77ab8ccee3b909e727620db29ec
parentc13258a74fd7345828fce8fab117247e3f61e6e5 (diff)
V4L2 subdev frame interval support
Extend the V4L2 media bus format syntax to support an optional frame interval value. If specified, the frame interval is set on the subdev. Signed-off-by: Todor Tomov <ttomov@mm-sol.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--main.c62
-rw-r--r--options.c5
-rw-r--r--subdev.c20
-rw-r--r--subdev.h2
4 files changed, 85 insertions, 4 deletions
diff --git a/main.c b/main.c
index 9b8951a..96b7ca1 100644
--- a/main.c
+++ b/main.c
@@ -230,9 +230,28 @@ static int parse_crop(struct v4l2_rect *crop, const char *p, char **endp)
return 0;
}
+static int parse_frame_interval(struct v4l2_fract *interval, const char *p, char **endp)
+{
+ char *end;
+
+ for (; isspace(*p); ++p);
+
+ interval->numerator = strtoul(p, &end, 10);
+
+ for (p = end; isspace(*p); ++p);
+ if (*p++ != '/')
+ return -EINVAL;
+
+ for (; isspace(*p); ++p);
+ interval->denominator = 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, struct v4l2_rect *crop,
- const char *p, char **endp)
+ struct v4l2_fract *interval, const char *p, char **endp)
{
struct media_entity_pad *pad;
char *end;
@@ -253,7 +272,7 @@ static struct media_entity_pad *parse_pad_format(struct media_device *media,
return NULL;
for (p = end; isspace(*p); p++);
- if (*p != ']') {
+ if (isdigit(*p)) {
ret = parse_crop(crop, p, &end);
if (ret < 0)
return NULL;
@@ -261,6 +280,14 @@ static struct media_entity_pad *parse_pad_format(struct media_device *media,
for (p = end; isspace(*p); p++);
}
+ if (*p == '@') {
+ ret = parse_frame_interval(interval, ++p, &end);
+ if (ret < 0)
+ return NULL;
+
+ for (p = end; isspace(*p); p++);
+ }
+
if (*p != ']')
return NULL;
@@ -310,16 +337,37 @@ static int set_crop(struct media_entity_pad *pad, struct v4l2_rect *crop)
return 0;
}
+static int set_frame_interval(struct media_entity *entity, struct v4l2_fract *interval)
+{
+ int ret;
+
+ printf("Setting up frame interval %u/%u on entity %s\n",
+ interval->numerator, interval->denominator, entity->info.name);
+
+ ret = v4l2_subdev_set_frame_interval(entity, interval);
+ if (ret < 0) {
+ printf("Unable to set frame interval: %s (%d)", strerror(-ret), ret);
+ return ret;
+ }
+
+ printf("Frame interval set: %u/%u\n",
+ interval->numerator, interval->denominator);
+
+ 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 };
+ struct v4l2_fract interval = { 0, 0 };
unsigned int i;
char *end;
int ret;
- pad = parse_pad_format(media, &format, &crop, p, &end);
+ pad = parse_pad_format(media, &format, &crop, &interval, p, &end);
if (pad == NULL) {
printf("Unable to parse format\n");
return -EINVAL;
@@ -339,6 +387,14 @@ static int setup_format(struct media_device *media, const char *p, char **endp)
}
}
+ if (interval.numerator != 0) {
+ ret = set_frame_interval(pad->entity, &interval);
+ if (ret < 0) {
+ printf("Unable to set frame interval\n");
+ return ret;
+ }
+ }
+
/* If the pad is an output pad, automatically set the same format on
* the remote subdev input pads, if any.
*/
diff --git a/options.c b/options.c
index 69ff9d5..6fd2daf 100644
--- a/options.c
+++ b/options.c
@@ -50,11 +50,12 @@ 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 ], ']' ;\n");
+ printf("\tformat = pad, '[', fcc, ' ', size, [ ' ', crop ], [ ' ', '@', frame interval ], ']' ;\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("\tframe interval = numerator, '/', denominator ;\n");
printf("where the fields are\n");
printf("\tentity number Entity numeric identifier\n");
printf("\tentity name Entify name (string) \n");
@@ -63,6 +64,8 @@ static void usage(const char *argv0, int verbose)
printf("\tfcc Format FourCC\n");
printf("\twidth Image width in pixels\n");
printf("\theight Image height in pixels\n");
+ printf("\tnumerator Frame interval numerator\n");
+ printf("\tdenominator Frame interval denominator\n");
}
#define OPT_PRINT_DOT 256
diff --git a/subdev.c b/subdev.c
index ac14324..40b2506 100644
--- a/subdev.c
+++ b/subdev.c
@@ -178,3 +178,23 @@ int v4l2_subdev_set_crop(struct media_entity *entity, struct v4l2_rect *rect,
return 0;
}
+int v4l2_subdev_set_frame_interval(struct media_entity *entity,
+ struct v4l2_fract *interval)
+{
+ struct v4l2_subdev_frame_interval ival;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&ival, 0, sizeof(ival));
+ ival.interval = *interval;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &ival);
+ if (ret < 0)
+ return -errno;
+
+ *interval = ival.interval;
+ return 0;
+}
diff --git a/subdev.h b/subdev.h
index e3106e6..7b65411 100644
--- a/subdev.h
+++ b/subdev.h
@@ -38,6 +38,8 @@ 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);
+int v4l2_subdev_set_frame_interval(struct media_entity *entity,
+ struct v4l2_fract *interval);
#endif