ソースを参照

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

Kristian Vos 4 ヶ月 前
コミット
04570c0ee1
3 ファイル変更62 行追加38 行削除
  1. 32 14
      src/camera.c
  2. 6 3
      src/camera.h
  3. 24 21
      src/io_pipeline.c

+ 32 - 14
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);
 }

+ 6 - 3
src/camera.h

@@ -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);

+ 24 - 21
src/io_pipeline.c

@@ -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 {