Commit dfa3bcc3 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

v4l2: correct frame rate if enumeration fails

The streaming parameters depend on the format, so the format must be
set explicitly, then the streaming parameters queried every time.

This essentially reverts 1bb938e4.
parent f5b0ed55
...@@ -765,13 +765,12 @@ static const struct v4l2_fract infinity = { 1, 0 }; ...@@ -765,13 +765,12 @@ static const struct v4l2_fract infinity = { 1, 0 };
/** /**
* Finds the highest frame rate possible of a certain V4L2 format. * Finds the highest frame rate possible of a certain V4L2 format.
* @param fmt V4L2 capture format [IN] * @param fmt V4L2 capture format [IN]
* @param parm V4L2 capture streaming parameters [IN]
* @param it V4L2 frame interval [OUT] * @param it V4L2 frame interval [OUT]
* @return 0 on success, -1 on error.
*/ */
static void FindMaxRate (vlc_object_t *obj, int fd, static int FindMaxRate (vlc_object_t *obj, int fd,
const struct v4l2_format *restrict fmt, const struct v4l2_format *restrict fmt,
const struct v4l2_streamparm *restrict parm, struct v4l2_fract *restrict it)
struct v4l2_fract *restrict it)
{ {
struct v4l2_frmivalenum fie = { struct v4l2_frmivalenum fie = {
.pixel_format = fmt->fmt.pix.pixelformat, .pixel_format = fmt->fmt.pix.pixelformat,
...@@ -780,19 +779,26 @@ static void FindMaxRate (vlc_object_t *obj, int fd, ...@@ -780,19 +779,26 @@ static void FindMaxRate (vlc_object_t *obj, int fd,
}; };
/* Mind that maximum rate means minimum interval */ /* Mind that maximum rate means minimum interval */
if (!(parm->parm.capture.capability & V4L2_CAP_TIMEPERFRAME))
{
*it = parm->parm.capture.timeperframe;
msg_Dbg (obj, " constant frame interval: %"PRIu32"/%"PRIu32,
it->numerator, it->denominator);
}
else
if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &fie) < 0) if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &fie) < 0)
{ {
msg_Warn (obj, " unknown frame intervals: %m"); msg_Dbg (obj, " unknown frame intervals: %m");
*it = parm->parm.capture.timeperframe; /* Frame intervals cannot be enumerated. Set the format and then
msg_Dbg (obj, " default frame interval: %"PRIu32"/%"PRIu32, * get the streaming parameters to figure out the default frame
it->numerator, it->denominator); * interval. This is not necessarily the maximum though. */
struct v4l2_format dummy_fmt = *fmt;
struct v4l2_streamparm parm = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
if (v4l2_ioctl (fd, VIDIOC_S_FMT, &dummy_fmt) < 0
|| v4l2_ioctl (fd, VIDIOC_G_PARM, &parm) < 0)
{
*it = infinity;
return -1;
}
*it = parm.parm.capture.timeperframe;
msg_Dbg (obj, " %s frame interval: %"PRIu32"/%"PRIu32,
(parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)
? "default" : "constant", it->numerator, it->denominator);
} }
else else
switch (fie.type) switch (fie.type)
...@@ -803,14 +809,12 @@ static void FindMaxRate (vlc_object_t *obj, int fd, ...@@ -803,14 +809,12 @@ static void FindMaxRate (vlc_object_t *obj, int fd,
{ {
if (fcmp (&fie.discrete, it) < 0) if (fcmp (&fie.discrete, it) < 0)
*it = fie.discrete; *it = fie.discrete;
msg_Dbg (obj, " discrete frame interval: %"PRIu32"/%"PRIu32,
fie.discrete.numerator, fie.discrete.denominator);
fie.index++; fie.index++;
} }
while (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &fie) >= 0); while (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &fie) >= 0);
msg_Dbg (obj, " best discrete frame interval: %"PRIu32"/%"PRIu32, msg_Dbg (obj, " %s frame interval: %"PRIu32"/%"PRIu32,
it->numerator, it->denominator); "discrete", it->numerator, it->denominator);
break; break;
case V4L2_FRMIVAL_TYPE_STEPWISE: case V4L2_FRMIVAL_TYPE_STEPWISE:
...@@ -826,6 +830,7 @@ static void FindMaxRate (vlc_object_t *obj, int fd, ...@@ -826,6 +830,7 @@ static void FindMaxRate (vlc_object_t *obj, int fd,
*it = fie.stepwise.min; *it = fie.stepwise.min;
break; break;
} }
return 0;
} }
#undef SetupFormat #undef SetupFormat
...@@ -850,15 +855,7 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc, ...@@ -850,15 +855,7 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc,
msg_Err (obj, "cannot get default format: %m"); msg_Err (obj, "cannot get default format: %m");
return -1; return -1;
} }
if (v4l2_ioctl (fd, VIDIOC_G_PARM, parm) < 0)
{
msg_Err (obj, "cannot get streaming parameters: %m");
return -1;
}
fmt->fmt.pix.pixelformat = fourcc; fmt->fmt.pix.pixelformat = fourcc;
parm->parm.capture.capturemode = 0; /* normal video mode */
parm->parm.capture.extendedmode = 0;
struct v4l2_frmsizeenum fse = { struct v4l2_frmsizeenum fse = {
.pixel_format = fourcc, .pixel_format = fourcc,
...@@ -874,7 +871,7 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc, ...@@ -874,7 +871,7 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc,
fmt->fmt.pix.height = height; fmt->fmt.pix.height = height;
msg_Dbg (obj, " requested frame size: %"PRIu32"x%"PRIu32, msg_Dbg (obj, " requested frame size: %"PRIu32"x%"PRIu32,
width, height); width, height);
FindMaxRate (obj, fd, fmt, parm, &best_it); FindMaxRate (obj, fd, fmt, &best_it);
} }
else else
if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &fse) < 0) if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &fse) < 0)
...@@ -883,7 +880,7 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc, ...@@ -883,7 +880,7 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc,
msg_Dbg (obj, " unknown frame sizes: %m"); msg_Dbg (obj, " unknown frame sizes: %m");
msg_Dbg (obj, " current frame size: %"PRIu32"x%"PRIu32, msg_Dbg (obj, " current frame size: %"PRIu32"x%"PRIu32,
fmt->fmt.pix.width, fmt->fmt.pix.height); fmt->fmt.pix.width, fmt->fmt.pix.height);
FindMaxRate (obj, fd, fmt, parm, &best_it); FindMaxRate (obj, fd, fmt, &best_it);
} }
else else
switch (fse.type) switch (fse.type)
...@@ -895,7 +892,7 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc, ...@@ -895,7 +892,7 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc,
msg_Dbg (obj, " frame size %"PRIu32"x%"PRIu32, msg_Dbg (obj, " frame size %"PRIu32"x%"PRIu32,
fse.discrete.width, fse.discrete.height); fse.discrete.width, fse.discrete.height);
FindMaxRate (obj, fd, fmt, parm, &cur_it); FindMaxRate (obj, fd, fmt, &cur_it);
int64_t c = fcmp (&cur_it, &best_it); int64_t c = fcmp (&cur_it, &best_it);
uint64_t area = fse.discrete.width * fse.discrete.height; uint64_t area = fse.discrete.width * fse.discrete.height;
...@@ -925,12 +922,6 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc, ...@@ -925,12 +922,6 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc,
msg_Dbg (obj, " with %"PRIu32"x%"PRIu32" steps", msg_Dbg (obj, " with %"PRIu32"x%"PRIu32" steps",
fse.stepwise.step_width, fse.stepwise.step_height); fse.stepwise.step_width, fse.stepwise.step_height);
if (!(parm->parm.capture.capability & V4L2_CAP_TIMEPERFRAME))
{ /* Frame rate is constant, lets maximize resolution */
fmt->fmt.pix.width = fse.stepwise.max_width;
fmt->fmt.pix.height = fse.stepwise.max_height;
}
else
/* FIXME: slow and dumb */ /* FIXME: slow and dumb */
for (uint32_t width = fse.stepwise.min_width; for (uint32_t width = fse.stepwise.min_width;
width <= fse.stepwise.max_width; width <= fse.stepwise.max_width;
...@@ -941,7 +932,7 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc, ...@@ -941,7 +932,7 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc,
{ {
struct v4l2_fract cur_it; struct v4l2_fract cur_it;
FindMaxRate (obj, fd, fmt, parm, &cur_it); FindMaxRate (obj, fd, fmt, &cur_it);
int64_t c = fcmp (&cur_it, &best_it); int64_t c = fcmp (&cur_it, &best_it);
uint64_t area = width * height; uint64_t area = width * height;
...@@ -960,15 +951,26 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc, ...@@ -960,15 +951,26 @@ int SetupFormat (vlc_object_t *obj, int fd, uint32_t fourcc,
break; break;
} }
parm->parm.capture.timeperframe = best_it; /* Set the final format */
if (v4l2_ioctl (fd, VIDIOC_S_FMT, fmt) < 0) if (v4l2_ioctl (fd, VIDIOC_S_FMT, fmt) < 0)
{ {
msg_Err (obj, "cannot set format: %m"); msg_Err (obj, "cannot set format: %m");
return -1; return -1;
} }
/* Now that the final format is set, fetch and override parameters */
if (v4l2_ioctl (fd, VIDIOC_G_PARM, parm) < 0)
{
msg_Err (obj, "cannot get streaming parameters: %m");
return -1;
}
parm->parm.capture.capturemode = 0; /* normal video mode */
parm->parm.capture.extendedmode = 0;
if (best_it.denominator != 0)
parm->parm.capture.timeperframe = best_it;
if (v4l2_ioctl (fd, VIDIOC_S_PARM, parm) < 0) if (v4l2_ioctl (fd, VIDIOC_S_PARM, parm) < 0)
msg_Warn (obj, "cannot set streaming parameters: %m"); msg_Warn (obj, "cannot set streaming parameters: %m");
ResetCrop (obj, fd); /* crop depends on frame size */ ResetCrop (obj, fd); /* crop depends on frame size */
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment