diff options
-rw-r--r-- | main.c | 62 | ||||
-rw-r--r-- | options.c | 5 | ||||
-rw-r--r-- | subdev.c | 20 | ||||
-rw-r--r-- | subdev.h | 2 |
4 files changed, 85 insertions, 4 deletions
@@ -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. */ @@ -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 @@ -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; +} @@ -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 |