Allow getting/querying/setting controls on non-sensor devices
This commit is contained in:

committed by
Martijn Braam

parent
a8e8d38018
commit
cd392d85cd
46
src/camera.c
46
src/camera.c
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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 {
|
||||
|
Reference in New Issue
Block a user