Allow getting/querying/setting controls on non-sensor devices

This commit is contained in:
Kristian Vos
2024-08-03 11:52:01 +02:00
committed by Martijn Braam
parent a8e8d38018
commit cd392d85cd
3 changed files with 62 additions and 38 deletions

View File

@@ -27,6 +27,20 @@ xioctl(int fd, int request, void *arg)
return r;
}
int
get_fd_from_type(libmegapixels_camera *camera, int fd_type)
{
switch (fd_type) {
case FD_TYPE_SENSOR:
return camera->sensor_fd;
case FD_TYPE_LENS:
return camera->lens_fd;
default:
fprintf(stderr, "Unknown fd type %d\n", fd_type);
return -1;
}
}
struct video_buffer {
uint32_t length;
uint8_t *data;
@@ -674,11 +688,13 @@ mp_control_list_free(MPControlList *list)
bool
mp_camera_query_control(libmegapixels_camera *camera,
uint32_t id,
MPControl *control)
MPControl *control,
int fd_type)
{
struct v4l2_query_ext_ctrl ctrl = {};
ctrl.id = id;
if (xioctl(camera->sensor_fd, VIDIOC_QUERY_EXT_CTRL, &ctrl) == -1) {
int fd = get_fd_from_type(camera, fd_type);
if (xioctl(fd, VIDIOC_QUERY_EXT_CTRL, &ctrl) == -1) {
if (errno != EINVAL) {
errno_printerr("VIDIOC_QUERY_EXT_CTRL");
}
@@ -708,7 +724,8 @@ static bool
control_impl_int32(libmegapixels_camera *camera,
uint32_t id,
int request,
int32_t *value)
int32_t *value,
int fd_type)
{
struct v4l2_ext_control ctrl = {};
ctrl.id = id;
@@ -720,7 +737,8 @@ control_impl_int32(libmegapixels_camera *camera,
.count = 1,
.controls = &ctrl,
};
if (xioctl(camera->sensor_fd, request, &ctrls) == -1) {
int fd = get_fd_from_type(camera, fd_type);
if (xioctl(fd, request, &ctrls) == -1) {
return false;
}
@@ -729,7 +747,7 @@ control_impl_int32(libmegapixels_camera *camera,
}
pid_t
mp_camera_control_set_int32_bg(MPCamera *camera, uint32_t id, int32_t v)
mp_camera_control_set_int32_bg(MPCamera *camera, uint32_t id, int32_t v, int fd_type)
{
struct v4l2_ext_control ctrl = {};
ctrl.id = id;
@@ -742,7 +760,7 @@ mp_camera_control_set_int32_bg(MPCamera *camera, uint32_t id, int32_t v)
.controls = &ctrl,
};
int fd = camera->camera->sensor_fd;
int fd = get_fd_from_type(camera->camera, fd_type);
// fork only after all the memory has been read
pid_t pid = fork();
@@ -763,20 +781,20 @@ mp_camera_control_set_int32_bg(MPCamera *camera, uint32_t id, int32_t v)
bool
mp_camera_control_try_int32(libmegapixels_camera *camera, uint32_t id, int32_t *v)
{
return control_impl_int32(camera, id, VIDIOC_TRY_EXT_CTRLS, v);
return control_impl_int32(camera, id, VIDIOC_TRY_EXT_CTRLS, v, FD_TYPE_SENSOR);
}
bool
mp_camera_control_set_int32(libmegapixels_camera *camera, uint32_t id, int32_t v)
{
return control_impl_int32(camera, id, VIDIOC_S_EXT_CTRLS, &v);
return control_impl_int32(camera, id, VIDIOC_S_EXT_CTRLS, &v, FD_TYPE_SENSOR);
}
int32_t
mp_camera_control_get_int32(libmegapixels_camera *camera, uint32_t id)
mp_camera_control_get_int32(libmegapixels_camera *camera, uint32_t id, int fd_type)
{
int32_t v = 0;
control_impl_int32(camera, id, VIDIOC_G_EXT_CTRLS, &v);
control_impl_int32(camera, id, VIDIOC_G_EXT_CTRLS, &v, fd_type);
return v;
}
@@ -784,7 +802,7 @@ bool
mp_camera_control_try_boolean(libmegapixels_camera *camera, uint32_t id, bool *v)
{
int32_t value = *v;
bool s = control_impl_int32(camera, id, VIDIOC_TRY_EXT_CTRLS, &value);
bool s = control_impl_int32(camera, id, VIDIOC_TRY_EXT_CTRLS, &value, FD_TYPE_SENSOR);
*v = value;
return s;
}
@@ -793,14 +811,14 @@ bool
mp_camera_control_set_bool(libmegapixels_camera *camera, uint32_t id, bool v)
{
int32_t value = v;
return control_impl_int32(camera, id, VIDIOC_S_EXT_CTRLS, &value);
return control_impl_int32(camera, id, VIDIOC_S_EXT_CTRLS, &value, FD_TYPE_SENSOR);
}
bool
mp_camera_control_get_bool(libmegapixels_camera *camera, uint32_t id)
{
int32_t v = false;
control_impl_int32(camera, id, VIDIOC_G_EXT_CTRLS, &v);
control_impl_int32(camera, id, VIDIOC_G_EXT_CTRLS, &v, FD_TYPE_SENSOR);
return v;
}
@@ -808,5 +826,5 @@ pid_t
mp_camera_control_set_bool_bg(MPCamera *camera, uint32_t id, bool v)
{
int32_t value = v;
return mp_camera_control_set_int32_bg(camera, id, value);
return mp_camera_control_set_int32_bg(camera, id, value, FD_TYPE_SENSOR);
}

View File

@@ -9,6 +9,9 @@
#define MAX_VIDEO_BUFFERS 20
#define MAX_BG_TASKS 8
#define FD_TYPE_SENSOR 0
#define FD_TYPE_LENS 1
typedef struct {
uint32_t index;
@@ -60,13 +63,13 @@ MPControl *mp_control_list_get(MPControlList *list);
MPControlList *mp_control_list_next(MPControlList *list);
void mp_control_list_free(MPControlList *list);
bool mp_camera_query_control(libmegapixels_camera *camera, uint32_t id, MPControl *control);
bool mp_camera_query_control(libmegapixels_camera *camera, uint32_t id, MPControl *control, int fd_type);
bool mp_camera_control_try_int32(libmegapixels_camera *camera, uint32_t id, int32_t *v);
bool mp_camera_control_set_int32(libmegapixels_camera *camera, uint32_t id, int32_t v);
int32_t mp_camera_control_get_int32(libmegapixels_camera *camera, uint32_t id);
int32_t mp_camera_control_get_int32(libmegapixels_camera *camera, uint32_t id, int fd_type);
// set the value in the background, discards result
pid_t mp_camera_control_set_int32_bg(MPCamera *camera, uint32_t id, int32_t v);
pid_t mp_camera_control_set_int32_bg(MPCamera *camera, uint32_t id, int32_t v, int fd_type);
bool mp_camera_control_try_bool(libmegapixels_camera *camera, uint32_t id, bool *v);
bool mp_camera_control_set_bool(libmegapixels_camera *camera, uint32_t id, bool v);

View File

@@ -67,21 +67,21 @@ update_process_pipeline()
// Grab the latest control values
if (!state_io.gain.manual && state_io.gain.control) {
state_io.gain.value = mp_camera_control_get_int32(
state_io.camera, state_io.gain.control);
state_io.camera, state_io.gain.control, FD_TYPE_SENSOR);
}
if (!state_io.exposure.manual && state_io.exposure.control) {
state_io.exposure.value = mp_camera_control_get_int32(
state_io.camera, state_io.exposure.control);
state_io.camera, state_io.exposure.control, FD_TYPE_SENSOR);
}
float balance_red = 1.0f;
float balance_blue = 1.0f;
if (state_io.red.control && state_io.blue.control) {
int red = mp_camera_control_get_int32(state_io.camera,
state_io.red.control);
state_io.red.control, FD_TYPE_SENSOR);
int blue = mp_camera_control_get_int32(state_io.camera,
state_io.blue.control);
state_io.blue.control, FD_TYPE_SENSOR);
balance_red = (float)red / (float)state_io.red.max;
balance_blue = (float)blue / (float)state_io.blue.max;
}
@@ -165,7 +165,7 @@ capture(MPPipeline *pipeline, const void *data)
// the value seems to be 248 which creates a 5 frame burst
// for manual gain you can go up to 11 frames
state_io.gain.value =
mp_camera_control_get_int32(state_io.camera, V4L2_CID_GAIN);
mp_camera_control_get_int32(state_io.camera, V4L2_CID_GAIN, FD_TYPE_SENSOR);
gain_norm = (float)state_io.gain.value / (float)state_io.gain.max;
state_io.burst_length = (int)fmax(sqrtf(gain_norm) * 10, 2) + 1;
state_io.burst_length = MAX(1, state_io.burst_length);
@@ -257,7 +257,8 @@ update_controls()
state_io.gain.value != state_io.gain.value_req) {
mp_camera_control_set_int32_bg(mpcamera,
state_io.gain.control,
state_io.gain.value_req);
state_io.gain.value_req,
FD_TYPE_SENSOR);
state_io.gain.value = state_io.gain.value_req;
state_changed = true;
}
@@ -276,7 +277,8 @@ update_controls()
state_io.exposure.value != state_io.exposure.value_req) {
mp_camera_control_set_int32_bg(mpcamera,
state_io.exposure.control,
state_io.exposure.value_req);
state_io.exposure.value_req,
FD_TYPE_SENSOR);
state_io.exposure.value = state_io.exposure.value_req;
state_changed = true;
}
@@ -387,7 +389,8 @@ on_frame(MPBuffer buffer, void *_data)
mp_camera_control_set_int32_bg(
mpcamera,
V4L2_CID_EXPOSURE_AUTO,
V4L2_EXPOSURE_AUTO);
V4L2_EXPOSURE_AUTO,
FD_TYPE_SENSOR);
}
if (!state_io.gain.manual) {
@@ -419,14 +422,14 @@ static void
init_controls()
{
if (mp_camera_query_control(
state_io.camera, V4L2_CID_FOCUS_ABSOLUTE, NULL)) {
state_io.camera, V4L2_CID_FOCUS_ABSOLUTE, NULL, FD_TYPE_SENSOR)) {
// TODO: Set focus state
state_io.focus.control = V4L2_CID_FOCUS_ABSOLUTE;
} else {
state_io.focus.control = 0;
}
if (mp_camera_query_control(state_io.camera, V4L2_CID_FOCUS_AUTO, NULL)) {
if (mp_camera_query_control(state_io.camera, V4L2_CID_FOCUS_AUTO, NULL, FD_TYPE_SENSOR)) {
mp_camera_control_set_bool_bg(
mpcamera, V4L2_CID_FOCUS_AUTO, true);
state_io.focus.auto_control = V4L2_CID_FOCUS_AUTO;
@@ -435,14 +438,14 @@ init_controls()
}
state_io.can_af_trigger = mp_camera_query_control(
state_io.camera, V4L2_CID_AUTO_FOCUS_START, NULL);
state_io.camera, V4L2_CID_AUTO_FOCUS_START, NULL, FD_TYPE_SENSOR);
MPControl control;
if (mp_camera_query_control(state_io.camera, V4L2_CID_GAIN, &control)) {
if (mp_camera_query_control(state_io.camera, V4L2_CID_GAIN, &control, FD_TYPE_SENSOR)) {
state_io.gain.control = V4L2_CID_GAIN;
state_io.gain.max = control.max;
} else if (mp_camera_query_control(
state_io.camera, V4L2_CID_ANALOGUE_GAIN, &control)) {
state_io.camera, V4L2_CID_ANALOGUE_GAIN, &control, FD_TYPE_SENSOR)) {
state_io.gain.control = V4L2_CID_ANALOGUE_GAIN;
state_io.gain.max = control.max;
} else {
@@ -451,12 +454,12 @@ init_controls()
}
if (state_io.gain.control) {
state_io.gain.value = mp_camera_control_get_int32(
state_io.camera, state_io.gain.control);
state_io.camera, state_io.gain.control, FD_TYPE_SENSOR);
} else {
state_io.gain.value = 0;
}
if (mp_camera_query_control(state_io.camera, V4L2_CID_AUTOGAIN, &control)) {
if (mp_camera_query_control(state_io.camera, V4L2_CID_AUTOGAIN, &control, FD_TYPE_SENSOR)) {
state_io.gain.auto_control = V4L2_CID_AUTOGAIN;
state_io.gain.manual =
mp_camera_control_get_bool(state_io.camera,
@@ -465,29 +468,29 @@ init_controls()
state_io.gain.auto_control = 0;
}
if (mp_camera_query_control(state_io.camera, V4L2_CID_EXPOSURE, &control)) {
if (mp_camera_query_control(state_io.camera, V4L2_CID_EXPOSURE, &control, FD_TYPE_SENSOR)) {
state_io.exposure.control = V4L2_CID_EXPOSURE;
state_io.exposure.max = control.max;
state_io.exposure.value = mp_camera_control_get_int32(
state_io.camera, V4L2_CID_EXPOSURE);
state_io.camera, V4L2_CID_EXPOSURE, FD_TYPE_SENSOR);
} else {
state_io.exposure.control = 0;
}
if (mp_camera_query_control(
state_io.camera, V4L2_CID_EXPOSURE_AUTO, &control)) {
state_io.camera, V4L2_CID_EXPOSURE_AUTO, &control, FD_TYPE_SENSOR)) {
state_io.exposure.auto_control = V4L2_CID_EXPOSURE_AUTO;
state_io.exposure.manual =
mp_camera_control_get_int32(state_io.camera,
V4L2_CID_EXPOSURE_AUTO) ==
V4L2_CID_EXPOSURE_AUTO, FD_TYPE_SENSOR) ==
V4L2_EXPOSURE_MANUAL;
} else {
state_io.exposure.auto_control = 0;
}
if (mp_camera_query_control(
state_io.camera, V4L2_CID_RED_BALANCE, &control)) {
state_io.camera, V4L2_CID_RED_BALANCE, &control, FD_TYPE_SENSOR)) {
state_io.red.control = V4L2_CID_RED_BALANCE;
state_io.red.max = control.max;
} else {
@@ -495,7 +498,7 @@ init_controls()
}
if (mp_camera_query_control(
state_io.camera, V4L2_CID_BLUE_BALANCE, &control)) {
state_io.camera, V4L2_CID_BLUE_BALANCE, &control, FD_TYPE_SENSOR)) {
state_io.blue.control = V4L2_CID_BLUE_BALANCE;
state_io.blue.max = control.max;
} else {