v4l2: v4l2_camera_proxy: Fix VIDIOC_[GS]_PARM support
v4l2-compliance reports an error due to VIDIOC_S_PARM being supported
without VIDIOC_G_PARM. Fix it by implementing VIDIOC_G_PARM. To satisfy
all compliance tests, VIDIOC_S_PARM also needs to be updated to properly
zero reserved fields.
Fixes: 5456e02d3f
("v4l2: Support setting frame rate in the V4L2 Adaptation layer")
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
This commit is contained in:
parent
f326eb4bf2
commit
77438775b3
3 changed files with 64 additions and 2 deletions
|
@ -195,6 +195,29 @@ void V4L2CameraProxy::setFmtFromConfig(const StreamConfiguration &streamConfig)
|
|||
v4l2PixFormat_.xfer_func = V4L2_XFER_FUNC_DEFAULT;
|
||||
|
||||
sizeimage_ = streamConfig.frameSize;
|
||||
|
||||
const ControlInfoMap &controls = vcam_->controlInfo();
|
||||
const auto &it = controls.find(&controls::FrameDurationLimits);
|
||||
|
||||
if (it != controls.end()) {
|
||||
const int64_t duration = it->second.def().get<int64_t>();
|
||||
|
||||
v4l2TimePerFrame_.numerator = duration;
|
||||
v4l2TimePerFrame_.denominator = 1000000;
|
||||
} else {
|
||||
/*
|
||||
* Default to 30fps if the camera doesn't expose the
|
||||
* FrameDurationLimits control.
|
||||
*
|
||||
* \todo Remove this once all pipeline handlers implement the
|
||||
* control
|
||||
*/
|
||||
LOG(V4L2Compat, Warning)
|
||||
<< "Camera does not support FrameDurationLimits";
|
||||
|
||||
v4l2TimePerFrame_.numerator = 333333;
|
||||
v4l2TimePerFrame_.denominator = 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
void V4L2CameraProxy::querycap(std::shared_ptr<Camera> camera)
|
||||
|
@ -758,6 +781,22 @@ int V4L2CameraProxy::vidioc_streamoff(V4L2CameraFile *file, int *arg)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int V4L2CameraProxy::vidioc_g_parm(V4L2CameraFile *file, struct v4l2_streamparm *arg)
|
||||
{
|
||||
LOG(V4L2Compat, Debug)
|
||||
<< "[" << file->description() << "] " << __func__ << "()";
|
||||
|
||||
if (!validateBufferType(arg->type))
|
||||
return -EINVAL;
|
||||
|
||||
memset(&arg->parm, 0, sizeof(arg->parm));
|
||||
|
||||
arg->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
|
||||
arg->parm.capture.timeperframe = v4l2TimePerFrame_;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int V4L2CameraProxy::vidioc_s_parm(V4L2CameraFile *file, struct v4l2_streamparm *arg)
|
||||
{
|
||||
LOG(V4L2Compat, Debug)
|
||||
|
@ -766,9 +805,25 @@ int V4L2CameraProxy::vidioc_s_parm(V4L2CameraFile *file, struct v4l2_streamparm
|
|||
if (!validateBufferType(arg->type))
|
||||
return -EINVAL;
|
||||
|
||||
struct v4l2_fract *timeperframe = &arg->parm.capture.timeperframe;
|
||||
utils::Duration frameDuration = 1.0s * timeperframe->numerator / timeperframe->denominator;
|
||||
/*
|
||||
* Store the frame duration if it is valid, otherwise keep the current
|
||||
* value.
|
||||
*
|
||||
* \todo The provided value should be adjusted based on the camera
|
||||
* capabilities.
|
||||
*/
|
||||
if (arg->parm.capture.timeperframe.numerator &&
|
||||
arg->parm.capture.timeperframe.denominator)
|
||||
v4l2TimePerFrame_ = arg->parm.capture.timeperframe;
|
||||
|
||||
memset(&arg->parm, 0, sizeof(arg->parm));
|
||||
|
||||
arg->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
|
||||
arg->parm.capture.timeperframe = v4l2TimePerFrame_;
|
||||
|
||||
/* Apply the frame duration. */
|
||||
utils::Duration frameDuration = 1.0s * v4l2TimePerFrame_.numerator
|
||||
/ v4l2TimePerFrame_.denominator;
|
||||
int64_t uDuration = frameDuration.get<std::micro>();
|
||||
vcam_->controls().set(controls::FrameDurationLimits, { uDuration, uDuration });
|
||||
|
||||
|
@ -795,6 +850,7 @@ const std::set<unsigned long> V4L2CameraProxy::supportedIoctls_ = {
|
|||
VIDIOC_EXPBUF,
|
||||
VIDIOC_STREAMON,
|
||||
VIDIOC_STREAMOFF,
|
||||
VIDIOC_G_PARM,
|
||||
VIDIOC_S_PARM,
|
||||
};
|
||||
|
||||
|
@ -883,6 +939,9 @@ int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long longRequest, void
|
|||
case VIDIOC_STREAMOFF:
|
||||
ret = vidioc_streamoff(file, static_cast<int *>(arg));
|
||||
break;
|
||||
case VIDIOC_G_PARM:
|
||||
ret = vidioc_g_parm(file, static_cast<struct v4l2_streamparm *>(arg));
|
||||
break;
|
||||
case VIDIOC_S_PARM:
|
||||
ret = vidioc_s_parm(file, static_cast<struct v4l2_streamparm *>(arg));
|
||||
break;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue