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>
+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,
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;
{
struct media_entity_pad *pad;
char *end;
return NULL;
for (p = end; isspace(*p); p++);
return NULL;
for (p = end; isspace(*p); p++);
ret = parse_crop(crop, p, &end);
if (ret < 0)
return NULL;
ret = parse_crop(crop, p, &end);
if (ret < 0)
return NULL;
for (p = end; isspace(*p); p++);
}
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;
if (*p != ']')
return NULL;
+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 };
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;
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;
if (pad == NULL) {
printf("Unable to parse format\n");
return -EINVAL;
+ 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.
*/
/* If the pad is an output pad, automatically set the same format on
* the remote subdev input pads, if any.
*/
printf("\n");
printf("Links and formats are defined as\n");
printf("\tlink = pad, '->', pad, '[', flags, ']' ;\n");
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("\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");
printf("where the fields are\n");
printf("\tentity number Entity numeric identifier\n");
printf("\tentity name Entify name (string) \n");
printf("\tfcc Format FourCC\n");
printf("\twidth Image width in pixels\n");
printf("\theight Image height in pixels\n");
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
}
#define OPT_PRINT_DOT 256
+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;
+}
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);
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);