summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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