diff --git a/src/camera.c b/src/camera.c index e621c34..ad32215 100644 --- a/src/camera.c +++ b/src/camera.c @@ -27,20 +27,6 @@ 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; @@ -686,14 +672,12 @@ mp_control_list_free(MPControlList *list) } bool -mp_camera_query_control(libmegapixels_camera *camera, +mp_camera_query_control(int fd, uint32_t id, - MPControl *control, - int fd_type) + MPControl *control) { struct v4l2_query_ext_ctrl ctrl = {}; ctrl.id = id; - 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"); @@ -702,6 +686,7 @@ mp_camera_query_control(libmegapixels_camera *camera, } if (control) { + control->fd = fd; control->id = ctrl.id; control->type = ctrl.type; strcpy(control->name, ctrl.name); @@ -721,14 +706,12 @@ mp_camera_query_control(libmegapixels_camera *camera, } static bool -control_impl_int32(libmegapixels_camera *camera, - uint32_t id, +control_impl_int32(MPControl *control, int request, - int32_t *value, - int fd_type) + int32_t *value) { struct v4l2_ext_control ctrl = {}; - ctrl.id = id; + ctrl.id = control->id; ctrl.value = *value; struct v4l2_ext_controls ctrls = { @@ -737,8 +720,7 @@ control_impl_int32(libmegapixels_camera *camera, .count = 1, .controls = &ctrl, }; - int fd = get_fd_from_type(camera, fd_type); - if (xioctl(fd, request, &ctrls) == -1) { + if (xioctl(control->fd, request, &ctrls) == -1) { return false; } @@ -747,10 +729,10 @@ control_impl_int32(libmegapixels_camera *camera, } pid_t -mp_camera_control_set_int32_bg(MPCamera *camera, uint32_t id, int32_t v, int fd_type) +mp_camera_control_set_int32_bg(MPCamera *camera, MPControl *control, int32_t v) { struct v4l2_ext_control ctrl = {}; - ctrl.id = id; + ctrl.id = control->id; ctrl.value = v; struct v4l2_ext_controls ctrls = { @@ -760,8 +742,6 @@ mp_camera_control_set_int32_bg(MPCamera *camera, uint32_t id, int32_t v, int fd_ .controls = &ctrl, }; - int fd = get_fd_from_type(camera->camera, fd_type); - // fork only after all the memory has been read pid_t pid = fork(); if (pid == -1) { @@ -773,58 +753,58 @@ mp_camera_control_set_int32_bg(MPCamera *camera, uint32_t id, int32_t v, int fd_ } // ignore errors - xioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls); + xioctl(control->fd, VIDIOC_S_EXT_CTRLS, &ctrls); // exit without calling exit handlers _exit(0); } bool -mp_camera_control_try_int32(libmegapixels_camera *camera, uint32_t id, int32_t *v) +mp_camera_control_try_int32(MPControl *control, int32_t *v) { - return control_impl_int32(camera, id, VIDIOC_TRY_EXT_CTRLS, v, FD_TYPE_SENSOR); + return control_impl_int32(control, VIDIOC_TRY_EXT_CTRLS, v); } bool -mp_camera_control_set_int32(libmegapixels_camera *camera, uint32_t id, int32_t v) +mp_camera_control_set_int32(MPControl *control, int32_t v) { - return control_impl_int32(camera, id, VIDIOC_S_EXT_CTRLS, &v, FD_TYPE_SENSOR); + return control_impl_int32(control, VIDIOC_S_EXT_CTRLS, &v); } int32_t -mp_camera_control_get_int32(libmegapixels_camera *camera, uint32_t id, int fd_type) +mp_camera_control_get_int32(MPControl *control) { int32_t v = 0; - control_impl_int32(camera, id, VIDIOC_G_EXT_CTRLS, &v, fd_type); + control_impl_int32(control, VIDIOC_G_EXT_CTRLS, &v); return v; } bool -mp_camera_control_try_boolean(libmegapixels_camera *camera, uint32_t id, bool *v) +mp_camera_control_try_boolean(MPControl *control, bool *v) { int32_t value = *v; - bool s = control_impl_int32(camera, id, VIDIOC_TRY_EXT_CTRLS, &value, FD_TYPE_SENSOR); + bool s = control_impl_int32(control, VIDIOC_TRY_EXT_CTRLS, &value); *v = value; return s; } bool -mp_camera_control_set_bool(libmegapixels_camera *camera, uint32_t id, bool v) +mp_camera_control_set_bool(MPControl *control, bool v) { int32_t value = v; - return control_impl_int32(camera, id, VIDIOC_S_EXT_CTRLS, &value, FD_TYPE_SENSOR); + return control_impl_int32(control, VIDIOC_S_EXT_CTRLS, &value); } bool -mp_camera_control_get_bool(libmegapixels_camera *camera, uint32_t id) +mp_camera_control_get_bool(MPControl *control) { int32_t v = false; - control_impl_int32(camera, id, VIDIOC_G_EXT_CTRLS, &v, FD_TYPE_SENSOR); + control_impl_int32(control, VIDIOC_G_EXT_CTRLS, &v); return v; } pid_t -mp_camera_control_set_bool_bg(MPCamera *camera, uint32_t id, bool v) +mp_camera_control_set_bool_bg(MPCamera *camera, MPControl *control, bool v) { int32_t value = v; - return mp_camera_control_set_int32_bg(camera, id, value, FD_TYPE_SENSOR); + return mp_camera_control_set_int32_bg(camera, control, value); } diff --git a/src/camera.h b/src/camera.h index f0b9ddc..542058e 100644 --- a/src/camera.h +++ b/src/camera.h @@ -8,10 +8,6 @@ #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; @@ -36,6 +32,7 @@ bool mp_camera_capture_buffer(MPCamera *camera, MPBuffer *buffer); bool mp_camera_release_buffer(MPCamera *camera, uint32_t buffer_index); typedef struct { + int fd; uint32_t id; uint32_t type; char name[32]; @@ -63,16 +60,16 @@ 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, int fd_type); +bool mp_camera_query_control(int fd, uint32_t id, MPControl *control); -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, int fd_type); +bool mp_camera_control_try_int32(MPControl *control, int32_t *v); +bool mp_camera_control_set_int32(MPControl *control, int32_t v); +int32_t mp_camera_control_get_int32(MPControl *control); // set the value in the background, discards result -pid_t mp_camera_control_set_int32_bg(MPCamera *camera, uint32_t id, int32_t v, int fd_type); +pid_t mp_camera_control_set_int32_bg(MPCamera *camera, MPControl *control, int32_t v); -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); -bool mp_camera_control_get_bool(libmegapixels_camera *camera, uint32_t id); +bool mp_camera_control_try_bool(MPControl *control, bool *v); +bool mp_camera_control_set_bool(MPControl *control, bool v); +bool mp_camera_control_get_bool(MPControl *control); // set the value in the background, discards result -pid_t mp_camera_control_set_bool_bg(MPCamera *camera, uint32_t id, bool v); +pid_t mp_camera_control_set_bool_bg(MPCamera *camera, MPControl *control, bool v); diff --git a/src/io_pipeline.c b/src/io_pipeline.c index 9a13391..78fea58 100644 --- a/src/io_pipeline.c +++ b/src/io_pipeline.c @@ -25,7 +25,7 @@ static GSource *capture_source; static bool pipeline_changed = true; typedef struct invoke_set_control { - uint32_t control; + MPControl *control; int32_t int_value; bool bool_value; } invoke_set_control; @@ -65,23 +65,19 @@ update_process_pipeline() } pipeline_changed = false; // 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, FD_TYPE_SENSOR); + if (!state_io.gain.manual && state_io.gain.control.id) { + state_io.gain.value = mp_camera_control_get_int32(&state_io.gain.control); } - 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, FD_TYPE_SENSOR); + if (!state_io.exposure.manual && state_io.exposure.control.id) { + state_io.exposure.value = mp_camera_control_get_int32(&state_io.exposure.control); } 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, FD_TYPE_SENSOR); - int blue = mp_camera_control_get_int32(state_io.camera, - state_io.blue.control, FD_TYPE_SENSOR); + if (state_io.red.control.id && state_io.blue.control.id) { + int red = mp_camera_control_get_int32(&state_io.red.control); + int blue = mp_camera_control_get_int32(&state_io.blue.control); balance_red = (float)red / (float)state_io.red.max; balance_blue = (float)blue / (float)state_io.blue.max; } @@ -136,11 +132,11 @@ static void set_control_int32(MPPipeline *pipeline, const void *data) { const invoke_set_control *control_data = (const invoke_set_control *)data; - mp_camera_control_set_int32(state_io.camera, control_data->control, control_data->int_value); + mp_camera_control_set_int32(control_data->control, control_data->int_value); } void -mp_io_pipeline_set_control_int32(uint32_t control, uint32_t value) +mp_io_pipeline_set_control_int32(MPControl *control, uint32_t value) { invoke_set_control data = { 0 }; data.control = control; @@ -156,16 +152,15 @@ capture(MPPipeline *pipeline, const void *data) float gain_norm; // Disable the autogain/exposure while taking the burst - mp_camera_control_set_int32(state_io.camera, V4L2_CID_AUTOGAIN, 0); - mp_camera_control_set_int32( - state_io.camera, V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL); + mp_camera_control_set_int32(&state_io.gain.auto_control, 0); + mp_camera_control_set_int32(&state_io.exposure.auto_control, V4L2_EXPOSURE_MANUAL); // Get current gain to calculate a burst length; // with low gain there's 3, with the max automatic gain of the ov5640 // 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, FD_TYPE_SENSOR); + mp_camera_control_get_int32(&state_io.gain.control); 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); @@ -221,12 +216,16 @@ start_focus() !mp_camera_check_task_complete(mpcamera, focus_continuous_task)) return; - if (state_io.focus.control) { + if (state_io.focus.control.id) { focus_continuous_task = mp_camera_control_set_bool_bg( - mpcamera, state_io.focus.control, 1); + mpcamera, &state_io.focus.control, 1); } else if (state_io.can_af_trigger) { + // TODO improve + MPControl auto_focus_start_control; + auto_focus_start_control.id = V4L2_CID_AUTO_FOCUS_START; + auto_focus_start_control.fd = state_io.camera->sensor_fd; start_focus_task = mp_camera_control_set_bool_bg( - mpcamera, V4L2_CID_AUTO_FOCUS_START, 1); + mpcamera, &auto_focus_start_control, 1); } } @@ -246,26 +245,25 @@ update_controls() if (state_io.gain.manual != state_io.gain.manual_req) { mp_camera_control_set_bool_bg(mpcamera, - V4L2_CID_AUTOGAIN, + &state_io.gain.auto_control, !state_io.gain.manual_req); state_io.gain.manual = state_io.gain.manual_req; state_changed = true; } if ((state_io.gain.manual || - (!state_io.gain.manual && state_io.gain.auto_control == 0)) && + (!state_io.gain.manual && state_io.gain.auto_control.id == 0)) && 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, - FD_TYPE_SENSOR); + &state_io.gain.control, + state_io.gain.value_req); state_io.gain.value = state_io.gain.value_req; state_changed = true; } if (state_io.exposure.manual != state_io.exposure.manual_req) { mp_camera_control_set_bool_bg(mpcamera, - V4L2_CID_EXPOSURE_AUTO, + &state_io.exposure.auto_control, state_io.exposure.manual_req ? V4L2_EXPOSURE_MANUAL : V4L2_EXPOSURE_AUTO); @@ -276,9 +274,8 @@ update_controls() if (state_io.exposure.manual && 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, - FD_TYPE_SENSOR); + &state_io.exposure.control, + state_io.exposure.value_req); state_io.exposure.value = state_io.exposure.value_req; state_changed = true; } @@ -293,7 +290,7 @@ static void do_aaa() { bool auto_exposure = - !state_io.exposure.manual && state_io.exposure.auto_control == 0; + !state_io.exposure.manual && state_io.exposure.auto_control.id == 0; if (auto_exposure) { int direction = state_io.stats.exposure; @@ -388,14 +385,13 @@ on_frame(MPBuffer buffer, void *_data) if (!state_io.exposure.manual) { mp_camera_control_set_int32_bg( mpcamera, - V4L2_CID_EXPOSURE_AUTO, - V4L2_EXPOSURE_AUTO, - FD_TYPE_SENSOR); + &state_io.exposure.auto_control, + V4L2_EXPOSURE_AUTO); } if (!state_io.gain.manual) { mp_camera_control_set_bool_bg( - mpcamera, V4L2_CID_AUTOGAIN, true); + mpcamera, &state_io.gain.auto_control, true); } // Go back to preview mode @@ -421,88 +417,88 @@ on_frame(MPBuffer buffer, void *_data) static void init_controls() { + MPControl focus_control; if (mp_camera_query_control( - state_io.camera, V4L2_CID_FOCUS_ABSOLUTE, NULL, FD_TYPE_SENSOR)) { - // TODO: Set focus state - state_io.focus.control = V4L2_CID_FOCUS_ABSOLUTE; + state_io.camera->sensor_fd, V4L2_CID_FOCUS_ABSOLUTE, &focus_control)) { + state_io.focus.control = focus_control; } else { - state_io.focus.control = 0; + state_io.focus.control.id = 0; } - if (mp_camera_query_control(state_io.camera, V4L2_CID_FOCUS_AUTO, NULL, FD_TYPE_SENSOR)) { + MPControl auto_focus_control; + if (mp_camera_query_control(state_io.camera->sensor_fd, V4L2_CID_FOCUS_AUTO, &auto_focus_control)) { mp_camera_control_set_bool_bg( - mpcamera, V4L2_CID_FOCUS_AUTO, true); - state_io.focus.auto_control = V4L2_CID_FOCUS_AUTO; + mpcamera, &auto_focus_control, true); + state_io.focus.auto_control = auto_focus_control; } else { - state_io.focus.auto_control = 0; + state_io.focus.auto_control.id = 0; } state_io.can_af_trigger = mp_camera_query_control( - state_io.camera, V4L2_CID_AUTO_FOCUS_START, NULL, FD_TYPE_SENSOR); + state_io.camera->sensor_fd, V4L2_CID_AUTO_FOCUS_START, NULL); - MPControl 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; + MPControl gain_control; + if (mp_camera_query_control(state_io.camera->sensor_fd, V4L2_CID_GAIN, &gain_control)) { + state_io.gain.control = gain_control; + state_io.gain.max = gain_control.max; } else if (mp_camera_query_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; + state_io.camera->sensor_fd, V4L2_CID_ANALOGUE_GAIN, &gain_control)) { + state_io.gain.control = gain_control; + state_io.gain.max = gain_control.max; } else { state_io.gain.max = 0; - state_io.gain.control = 0; + state_io.gain.control.id = 0; } - if (state_io.gain.control) { - state_io.gain.value = mp_camera_control_get_int32( - state_io.camera, state_io.gain.control, FD_TYPE_SENSOR); + if (state_io.gain.control.id) { + state_io.gain.value = mp_camera_control_get_int32(&state_io.gain.control); } else { state_io.gain.value = 0; } - if (mp_camera_query_control(state_io.camera, V4L2_CID_AUTOGAIN, &control, FD_TYPE_SENSOR)) { - state_io.gain.auto_control = V4L2_CID_AUTOGAIN; + MPControl auto_gain_control; + if (mp_camera_query_control(state_io.camera->sensor_fd, V4L2_CID_AUTOGAIN, &auto_gain_control)) { + state_io.gain.auto_control = auto_gain_control; state_io.gain.manual = - mp_camera_control_get_bool(state_io.camera, - V4L2_CID_AUTOGAIN) == 0; + mp_camera_control_get_bool(&auto_gain_control) == 0; } else { - state_io.gain.auto_control = 0; + state_io.gain.auto_control.id = 0; } - 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, FD_TYPE_SENSOR); - + MPControl exposure_control; + if (mp_camera_query_control(state_io.camera->sensor_fd, V4L2_CID_EXPOSURE, &exposure_control)) { + state_io.exposure.control = exposure_control; + state_io.exposure.max = exposure_control.max; + state_io.exposure.value = mp_camera_control_get_int32(&exposure_control); } else { - state_io.exposure.control = 0; + state_io.exposure.control.id = 0; } + MPControl auto_exposure_control; if (mp_camera_query_control( - state_io.camera, V4L2_CID_EXPOSURE_AUTO, &control, FD_TYPE_SENSOR)) { - state_io.exposure.auto_control = V4L2_CID_EXPOSURE_AUTO; + state_io.camera->sensor_fd, V4L2_CID_EXPOSURE_AUTO, &auto_exposure_control)) { + state_io.exposure.auto_control = auto_exposure_control; state_io.exposure.manual = - mp_camera_control_get_int32(state_io.camera, - V4L2_CID_EXPOSURE_AUTO, FD_TYPE_SENSOR) == - V4L2_EXPOSURE_MANUAL; + mp_camera_control_get_int32(&auto_exposure_control) == V4L2_EXPOSURE_MANUAL; } else { - state_io.exposure.auto_control = 0; + state_io.exposure.auto_control.id = 0; } + MPControl red_control; if (mp_camera_query_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; + state_io.camera->sensor_fd, V4L2_CID_RED_BALANCE, &red_control)) { + state_io.red.control = red_control; + state_io.red.max = red_control.max; } else { - state_io.red.control = 0; + state_io.red.control.id = 0; } + MPControl blue_control; if (mp_camera_query_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; + state_io.camera->sensor_fd, V4L2_CID_BLUE_BALANCE, &blue_control)) { + state_io.blue.control = blue_control; + state_io.blue.max = blue_control.max; } else { - state_io.blue.control = 0; + state_io.blue.control.id = 0; } pipeline_changed = true; diff --git a/src/io_pipeline.h b/src/io_pipeline.h index 21ca6d8..a108250 100644 --- a/src/io_pipeline.h +++ b/src/io_pipeline.h @@ -10,7 +10,7 @@ void mp_io_pipeline_stop(); void mp_io_pipeline_focus(); void mp_io_pipeline_capture(); -void mp_io_pipeline_set_control_int32(uint32_t control, uint32_t value); +void mp_io_pipeline_set_control_int32(MPControl *control, uint32_t value); void mp_io_pipeline_release_buffer(uint32_t buffer_index); diff --git a/src/main.c b/src/main.c index 83838d7..cdf9ec4 100644 --- a/src/main.c +++ b/src/main.c @@ -199,10 +199,10 @@ update_state(const mp_state_main *new_state) state.stats.focus = new_state->stats.focus; // Make the right settings available for the camera + gtk_widget_set_visible(iso_button, state.gain.control.id != 0); + gtk_widget_set_visible(shutter_button, state.exposure.control.id != 0); // Even if there's no flash led/v4l, it'll just default to using the screen as flash, so always enable this button gtk_widget_set_visible(flash_button, true); - gtk_widget_set_visible(iso_button, state.gain.control != 0); - gtk_widget_set_visible(shutter_button, state.exposure.control != 0); return false; } diff --git a/src/process_pipeline.c b/src/process_pipeline.c index bd6d059..77dcdc7 100644 --- a/src/process_pipeline.c +++ b/src/process_pipeline.c @@ -378,9 +378,9 @@ static void process_aaa() { bool auto_exposure = - !state_proc.exposure.manual && state_proc.exposure.auto_control == 0; + !state_proc.exposure.manual && state_proc.exposure.auto_control.id == 0; bool auto_focus = - !state_proc.focus.manual && state_proc.focus.auto_control == 0; + !state_proc.focus.manual && state_proc.focus.auto_control.id == 0; bool auto_balance = TRUE; if (!auto_exposure && !auto_focus && !auto_balance) { return; @@ -445,9 +445,9 @@ process_aaa() clamp_control(&state_proc.gain); clamp_control(&state_proc.exposure); - mp_io_pipeline_set_control_int32(state_proc.gain.control, + mp_io_pipeline_set_control_int32(&state_proc.gain.control, state_proc.gain.value_req); - mp_io_pipeline_set_control_int32(state_proc.exposure.control, + mp_io_pipeline_set_control_int32(&state_proc.exposure.control, state_proc.exposure.value_req); state_proc.gain.value = state_proc.gain.value_req; state_proc.exposure.value = state_proc.exposure.value_req; diff --git a/src/state.h b/src/state.h index 89e5e50..7823e32 100644 --- a/src/state.h +++ b/src/state.h @@ -1,16 +1,17 @@ #pragma once +#include "camera.h" #include "dcp.h" #include #include typedef struct cstate { - uint32_t control; + MPControl control; int32_t value; int32_t value_req; int32_t max; bool manual; bool manual_req; - uint32_t auto_control; + MPControl auto_control; } controlstate; typedef struct state_main {