Browse Source

Move mode types and functions to a new object (MR 13)

Rename MPCameraMode to a more generic MPMode and move it along
with related functions to a new object in preparation for using
it in the device object.
Yassine Oudjana 3 years ago
parent
commit
a4c2c1ec1f
13 changed files with 381 additions and 364 deletions
  1. 5 0
      meson.build
  2. 29 291
      src/camera.c
  3. 10 54
      src/camera.h
  4. 1 1
      src/camera_config.c
  5. 3 3
      src/camera_config.h
  6. 2 2
      src/io_pipeline.c
  7. 1 1
      src/main.c
  8. 1 1
      src/main.h
  9. 263 0
      src/mode.c
  10. 55 0
      src/mode.h
  11. 5 6
      src/process_pipeline.c
  12. 2 1
      src/process_pipeline.h
  13. 4 4
      tools/camera_test.c

+ 5 - 0
meson.build

@@ -44,6 +44,7 @@ executable('megapixels',
   'src/io_pipeline.c',
   'src/main.c',
   'src/matrix.c',
+  'src/mode.c',
   'src/pipeline.c',
   'src/process_pipeline.c',
   'src/zbar_pipeline.c',
@@ -66,6 +67,7 @@ install_data(
 executable('megapixels-list-devices',
   'tools/list_devices.c',
   'src/device.c',
+  'src/mode.c',
   include_directories: 'src/',
   dependencies: [gtkdep],
   install: true)
@@ -74,6 +76,7 @@ executable('megapixels-camera-test',
   'tools/camera_test.c',
   'src/camera.c',
   'src/device.c',
+  'src/mode.c',
   include_directories: 'src/',
   dependencies: [gtkdep],
   install: true)
@@ -106,6 +109,8 @@ if clang_format.found()
     'src/main.h',
     'src/matrix.c',
     'src/matrix.h',
+    'src/mode.c',
+    'src/mode.h',
     'src/pipeline.c',
     'src/pipeline.h',
     'src/process_pipeline.c',

+ 29 - 291
src/camera.c

@@ -1,8 +1,10 @@
 #include "camera.h"
+#include "mode.h"
 
 #include <assert.h>
 #include <errno.h>
 #include <glib.h>
+#include <linux/v4l2-subdev.h>
 #include <stdio.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
@@ -12,263 +14,6 @@
 #define MAX_VIDEO_BUFFERS 20
 #define MAX_BG_TASKS 8
 
-static const char *pixel_format_names[MP_PIXEL_FMT_MAX] = {
-        "unsupported", "BGGR8",   "GBRG8",   "GRBG8", "RGGB8", "BGGR10P",
-        "GBRG10P",     "GRBG10P", "RGGB10P", "UYVY",  "YUYV",
-};
-
-const char *
-mp_pixel_format_to_str(uint32_t pixel_format)
-{
-        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, "INVALID");
-        return pixel_format_names[pixel_format];
-}
-
-MPPixelFormat
-mp_pixel_format_from_str(const char *name)
-{
-        for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) {
-                if (strcasecmp(pixel_format_names[i], name) == 0) {
-                        return i;
-                }
-        }
-        g_return_val_if_reached(MP_PIXEL_FMT_UNSUPPORTED);
-}
-
-static const uint32_t pixel_format_v4l_pixel_formats[MP_PIXEL_FMT_MAX] = {
-        0,
-        V4L2_PIX_FMT_SBGGR8,
-        V4L2_PIX_FMT_SGBRG8,
-        V4L2_PIX_FMT_SGRBG8,
-        V4L2_PIX_FMT_SRGGB8,
-        V4L2_PIX_FMT_SBGGR10P,
-        V4L2_PIX_FMT_SGBRG10P,
-        V4L2_PIX_FMT_SGRBG10P,
-        V4L2_PIX_FMT_SRGGB10P,
-        V4L2_PIX_FMT_UYVY,
-        V4L2_PIX_FMT_YUYV,
-};
-
-uint32_t
-mp_pixel_format_to_v4l_pixel_format(MPPixelFormat pixel_format)
-{
-        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
-        return pixel_format_v4l_pixel_formats[pixel_format];
-}
-
-MPPixelFormat
-mp_pixel_format_from_v4l_pixel_format(uint32_t v4l_pixel_format)
-{
-        for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) {
-                if (pixel_format_v4l_pixel_formats[i] == v4l_pixel_format) {
-                        return i;
-                }
-        }
-        return MP_PIXEL_FMT_UNSUPPORTED;
-}
-
-static const uint32_t pixel_format_v4l_bus_codes[MP_PIXEL_FMT_MAX] = {
-        0,
-        MEDIA_BUS_FMT_SBGGR8_1X8,
-        MEDIA_BUS_FMT_SGBRG8_1X8,
-        MEDIA_BUS_FMT_SGRBG8_1X8,
-        MEDIA_BUS_FMT_SRGGB8_1X8,
-        MEDIA_BUS_FMT_SBGGR10_1X10,
-        MEDIA_BUS_FMT_SGBRG10_1X10,
-        MEDIA_BUS_FMT_SGRBG10_1X10,
-        MEDIA_BUS_FMT_SRGGB10_1X10,
-        MEDIA_BUS_FMT_UYVY8_2X8,
-        MEDIA_BUS_FMT_YUYV8_2X8,
-};
-
-uint32_t
-mp_pixel_format_to_v4l_bus_code(MPPixelFormat pixel_format)
-{
-        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
-        return pixel_format_v4l_bus_codes[pixel_format];
-}
-
-MPPixelFormat
-mp_pixel_format_from_v4l_bus_code(uint32_t v4l_bus_code)
-{
-        for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) {
-                if (pixel_format_v4l_bus_codes[i] == v4l_bus_code) {
-                        return i;
-                }
-        }
-        return MP_PIXEL_FMT_UNSUPPORTED;
-}
-
-uint32_t
-mp_pixel_format_bits_per_pixel(MPPixelFormat pixel_format)
-{
-        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
-        switch (pixel_format) {
-        case MP_PIXEL_FMT_BGGR8:
-        case MP_PIXEL_FMT_GBRG8:
-        case MP_PIXEL_FMT_GRBG8:
-        case MP_PIXEL_FMT_RGGB8:
-                return 8;
-        case MP_PIXEL_FMT_BGGR10P:
-        case MP_PIXEL_FMT_GBRG10P:
-        case MP_PIXEL_FMT_GRBG10P:
-        case MP_PIXEL_FMT_RGGB10P:
-                return 10;
-        case MP_PIXEL_FMT_UYVY:
-        case MP_PIXEL_FMT_YUYV:
-                return 16;
-        default:
-                return 0;
-        }
-}
-
-uint32_t
-mp_pixel_format_pixel_depth(MPPixelFormat pixel_format)
-{
-        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
-        switch (pixel_format) {
-        case MP_PIXEL_FMT_BGGR8:
-        case MP_PIXEL_FMT_GBRG8:
-        case MP_PIXEL_FMT_GRBG8:
-        case MP_PIXEL_FMT_RGGB8:
-        case MP_PIXEL_FMT_UYVY:
-        case MP_PIXEL_FMT_YUYV:
-                return 8;
-        case MP_PIXEL_FMT_GBRG10P:
-        case MP_PIXEL_FMT_GRBG10P:
-        case MP_PIXEL_FMT_RGGB10P:
-        case MP_PIXEL_FMT_BGGR10P:
-                return 10;
-        default:
-                return 0;
-        }
-}
-
-const char *
-mp_pixel_format_cfa(MPPixelFormat pixel_format)
-{
-        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
-        switch (pixel_format) {
-        case MP_PIXEL_FMT_BGGR8:
-        case MP_PIXEL_FMT_BGGR10P:
-                return "BGGR";
-                break;
-        case MP_PIXEL_FMT_GBRG8:
-        case MP_PIXEL_FMT_GBRG10P:
-                return "GBRG";
-                break;
-        case MP_PIXEL_FMT_GRBG8:
-        case MP_PIXEL_FMT_GRBG10P:
-                return "GRBG";
-                break;
-        case MP_PIXEL_FMT_RGGB8:
-        case MP_PIXEL_FMT_RGGB10P:
-                return "RGGB";
-                break;
-        case MP_PIXEL_FMT_UYVY:
-                return "UYUV";
-                break;
-        case MP_PIXEL_FMT_YUYV:
-                return "YUYV";
-                break;
-        default:
-                return "unsupported";
-        }
-}
-
-const char *
-mp_pixel_format_cfa_pattern(MPPixelFormat pixel_format)
-{
-        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
-        switch (pixel_format) {
-        case MP_PIXEL_FMT_BGGR8:
-        case MP_PIXEL_FMT_BGGR10P:
-                return "\002\001\001\000";
-                break;
-        case MP_PIXEL_FMT_GBRG8:
-        case MP_PIXEL_FMT_GBRG10P:
-                return "\001\002\000\001";
-                break;
-        case MP_PIXEL_FMT_GRBG8:
-        case MP_PIXEL_FMT_GRBG10P:
-                return "\001\000\002\001";
-                break;
-        case MP_PIXEL_FMT_RGGB8:
-        case MP_PIXEL_FMT_RGGB10P:
-                return "\000\001\001\002";
-                break;
-        default:
-                return NULL;
-        }
-}
-
-uint32_t
-mp_pixel_format_width_to_bytes(MPPixelFormat pixel_format, uint32_t width)
-{
-        uint32_t bits_per_pixel = mp_pixel_format_bits_per_pixel(pixel_format);
-        uint64_t bits_per_width = width * (uint64_t)bits_per_pixel;
-
-        uint64_t remainder = bits_per_width % 8;
-        if (remainder == 0)
-                return bits_per_width / 8;
-
-        return (bits_per_width + 8 - remainder) / 8;
-}
-
-uint32_t
-mp_pixel_format_width_to_colors(MPPixelFormat pixel_format, uint32_t width)
-{
-        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
-        switch (pixel_format) {
-        case MP_PIXEL_FMT_BGGR8:
-        case MP_PIXEL_FMT_GBRG8:
-        case MP_PIXEL_FMT_GRBG8:
-        case MP_PIXEL_FMT_RGGB8:
-                return width / 2;
-        case MP_PIXEL_FMT_BGGR10P:
-        case MP_PIXEL_FMT_GBRG10P:
-        case MP_PIXEL_FMT_GRBG10P:
-        case MP_PIXEL_FMT_RGGB10P:
-                return width / 2 * 5;
-        case MP_PIXEL_FMT_UYVY:
-        case MP_PIXEL_FMT_YUYV:
-                return width;
-        default:
-                return 0;
-        }
-}
-
-uint32_t
-mp_pixel_format_height_to_colors(MPPixelFormat pixel_format, uint32_t height)
-{
-        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
-        switch (pixel_format) {
-        case MP_PIXEL_FMT_BGGR8:
-        case MP_PIXEL_FMT_GBRG8:
-        case MP_PIXEL_FMT_GRBG8:
-        case MP_PIXEL_FMT_RGGB8:
-        case MP_PIXEL_FMT_BGGR10P:
-        case MP_PIXEL_FMT_GBRG10P:
-        case MP_PIXEL_FMT_GRBG10P:
-        case MP_PIXEL_FMT_RGGB10P:
-                return height / 2;
-        case MP_PIXEL_FMT_UYVY:
-        case MP_PIXEL_FMT_YUYV:
-                return height;
-        default:
-                return 0;
-        }
-}
-
-bool
-mp_camera_mode_is_equivalent(const MPCameraMode *m1, const MPCameraMode *m2)
-{
-        return m1->pixel_format == m2->pixel_format &&
-               m1->frame_interval.numerator == m2->frame_interval.numerator &&
-               m1->frame_interval.denominator == m2->frame_interval.denominator &&
-               m1->width == m2->width && m1->height == m2->height;
-}
-
 static void
 errno_printerr(const char *s)
 {
@@ -296,7 +41,7 @@ struct _MPCamera {
         int subdev_fd;
 
         bool has_set_mode;
-        MPCameraMode current_mode;
+        MPMode current_mode;
 
         struct video_buffer buffers[MAX_VIDEO_BUFFERS];
         uint32_t num_buffers;
@@ -461,7 +206,7 @@ get_buf_type(MPCamera *camera)
 }
 
 static bool
-camera_mode_impl(MPCamera *camera, int request, MPCameraMode *mode)
+camera_mode_impl(MPCamera *camera, int request, MPMode *mode)
 {
         uint32_t pixfmt = mp_pixel_format_to_v4l_pixel_format(mode->pixel_format);
         struct v4l2_format fmt = {};
@@ -499,7 +244,7 @@ camera_mode_impl(MPCamera *camera, int request, MPCameraMode *mode)
 }
 
 bool
-mp_camera_try_mode(MPCamera *camera, MPCameraMode *mode)
+mp_camera_try_mode(MPCamera *camera, MPMode *mode)
 {
         if (!camera_mode_impl(camera, VIDIOC_TRY_FMT, mode)) {
                 errno_printerr("VIDIOC_S_FMT");
@@ -508,14 +253,14 @@ mp_camera_try_mode(MPCamera *camera, MPCameraMode *mode)
         return true;
 }
 
-const MPCameraMode *
+const MPMode *
 mp_camera_get_mode(const MPCamera *camera)
 {
         return &camera->current_mode;
 }
 
 bool
-mp_camera_set_mode(MPCamera *camera, MPCameraMode *mode)
+mp_camera_set_mode(MPCamera *camera, MPMode *mode)
 {
         // Set the mode in the subdev the camera is one
         if (mp_camera_is_subdev(camera)) {
@@ -843,15 +588,10 @@ mp_camera_release_buffer(MPCamera *camera, uint32_t buffer_index)
         return true;
 }
 
-struct _MPCameraModeList {
-        MPCameraMode mode;
-        MPCameraModeList *next;
-};
-
-static MPCameraModeList *
-get_subdev_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
+static MPModeList *
+get_subdev_modes(MPCamera *camera, bool (*check)(MPCamera *, MPMode *))
 {
-        MPCameraModeList *item = NULL;
+        MPModeList *item = NULL;
 
         for (uint32_t fmt_index = 0;; ++fmt_index) {
                 struct v4l2_subdev_mbus_code_enum fmt = {};
@@ -912,7 +652,7 @@ get_subdev_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
                                         break;
                                 }
 
-                                MPCameraMode mode = {
+                                MPMode mode = {
                                         .pixel_format = format,
                                         .frame_interval = interval.interval,
                                         .width = frame.max_width,
@@ -923,8 +663,7 @@ get_subdev_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
                                         continue;
                                 }
 
-                                MPCameraModeList *new_item =
-                                        malloc(sizeof(MPCameraModeList));
+                                MPModeList *new_item = malloc(sizeof(MPModeList));
                                 new_item->mode = mode;
                                 new_item->next = item;
                                 item = new_item;
@@ -935,12 +674,12 @@ get_subdev_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
         return item;
 }
 
-static MPCameraModeList *
-get_video_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
+static MPModeList *
+get_video_modes(MPCamera *camera, bool (*check)(MPCamera *, MPMode *))
 {
         const enum v4l2_buf_type buftype = get_buf_type(camera);
 
-        MPCameraModeList *item = NULL;
+        MPModeList *item = NULL;
 
         for (uint32_t fmt_index = 0;; ++fmt_index) {
                 struct v4l2_fmtdesc fmt = {};
@@ -999,7 +738,7 @@ get_video_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
                                         break;
                                 }
 
-                                MPCameraMode mode = {
+                                MPMode mode = {
                                         .pixel_format = format,
                                         .frame_interval = interval.discrete,
                                         .width = frame.discrete.width,
@@ -1010,8 +749,7 @@ get_video_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
                                         continue;
                                 }
 
-                                MPCameraModeList *new_item =
-                                        malloc(sizeof(MPCameraModeList));
+                                MPModeList *new_item = malloc(sizeof(MPModeList));
                                 new_item->mode = mode;
                                 new_item->next = item;
                                 item = new_item;
@@ -1023,20 +761,20 @@ get_video_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
 }
 
 static bool
-all_modes(MPCamera *camera, MPCameraMode *mode)
+all_modes(MPCamera *camera, MPMode *mode)
 {
         return true;
 }
 
 static bool
-available_modes(MPCamera *camera, MPCameraMode *mode)
+available_modes(MPCamera *camera, MPMode *mode)
 {
-        MPCameraMode attempt = *mode;
+        MPMode attempt = *mode;
         return mp_camera_try_mode(camera, &attempt) &&
-               mp_camera_mode_is_equivalent(mode, &attempt);
+               mp_mode_is_equivalent(mode, &attempt);
 }
 
-MPCameraModeList *
+MPModeList *
 mp_camera_list_supported_modes(MPCamera *camera)
 {
         if (mp_camera_is_subdev(camera)) {
@@ -1046,7 +784,7 @@ mp_camera_list_supported_modes(MPCamera *camera)
         }
 }
 
-MPCameraModeList *
+MPModeList *
 mp_camera_list_available_modes(MPCamera *camera)
 {
         if (mp_camera_is_subdev(camera)) {
@@ -1056,25 +794,25 @@ mp_camera_list_available_modes(MPCamera *camera)
         }
 }
 
-MPCameraMode *
-mp_camera_mode_list_get(MPCameraModeList *list)
+MPMode *
+mp_camera_mode_list_get(MPModeList *list)
 {
         g_return_val_if_fail(list, NULL);
         return &list->mode;
 }
 
-MPCameraModeList *
-mp_camera_mode_list_next(MPCameraModeList *list)
+MPModeList *
+mp_camera_mode_list_next(MPModeList *list)
 {
         g_return_val_if_fail(list, NULL);
         return list->next;
 }
 
 void
-mp_camera_mode_list_free(MPCameraModeList *list)
+mp_camera_mode_list_free(MPModeList *list)
 {
         while (list) {
-                MPCameraModeList *tmp = list;
+                MPModeList *tmp = list;
                 list = tmp->next;
                 free(tmp);
         }

+ 10 - 54
src/camera.h

@@ -1,53 +1,11 @@
 #pragma once
 
-#include <linux/v4l2-subdev.h>
+#include "mode.h"
+
 #include <stdbool.h>
 #include <stdint.h>
 #include <sys/wait.h>
 
-typedef enum {
-        MP_PIXEL_FMT_UNSUPPORTED,
-        MP_PIXEL_FMT_BGGR8,
-        MP_PIXEL_FMT_GBRG8,
-        MP_PIXEL_FMT_GRBG8,
-        MP_PIXEL_FMT_RGGB8,
-        MP_PIXEL_FMT_BGGR10P,
-        MP_PIXEL_FMT_GBRG10P,
-        MP_PIXEL_FMT_GRBG10P,
-        MP_PIXEL_FMT_RGGB10P,
-        MP_PIXEL_FMT_UYVY,
-        MP_PIXEL_FMT_YUYV,
-
-        MP_PIXEL_FMT_MAX,
-} MPPixelFormat;
-
-const char *mp_pixel_format_to_str(MPPixelFormat pixel_format);
-MPPixelFormat mp_pixel_format_from_str(const char *str);
-
-MPPixelFormat mp_pixel_format_from_v4l_pixel_format(uint32_t v4l_pixel_format);
-MPPixelFormat mp_pixel_format_from_v4l_bus_code(uint32_t v4l_bus_code);
-uint32_t mp_pixel_format_to_v4l_pixel_format(MPPixelFormat pixel_format);
-uint32_t mp_pixel_format_to_v4l_bus_code(MPPixelFormat pixel_format);
-
-uint32_t mp_pixel_format_bits_per_pixel(MPPixelFormat pixel_format);
-uint32_t mp_pixel_format_pixel_depth(MPPixelFormat pixel_format);
-const char *mp_pixel_format_cfa(MPPixelFormat pixel_format);
-const char *mp_pixel_format_cfa_pattern(MPPixelFormat pixel_format);
-uint32_t mp_pixel_format_width_to_bytes(MPPixelFormat pixel_format, uint32_t width);
-uint32_t mp_pixel_format_width_to_colors(MPPixelFormat pixel_format, uint32_t width);
-uint32_t mp_pixel_format_height_to_colors(MPPixelFormat pixel_format,
-                                          uint32_t height);
-
-typedef struct {
-        MPPixelFormat pixel_format;
-
-        struct v4l2_fract frame_interval;
-        uint32_t width;
-        uint32_t height;
-} MPCameraMode;
-
-bool mp_camera_mode_is_equivalent(const MPCameraMode *m1, const MPCameraMode *m2);
-
 typedef struct {
         uint32_t index;
 
@@ -68,23 +26,21 @@ bool mp_camera_is_subdev(MPCamera *camera);
 int mp_camera_get_video_fd(MPCamera *camera);
 int mp_camera_get_subdev_fd(MPCamera *camera);
 
-const MPCameraMode *mp_camera_get_mode(const MPCamera *camera);
-bool mp_camera_try_mode(MPCamera *camera, MPCameraMode *mode);
+const MPMode *mp_camera_get_mode(const MPCamera *camera);
+bool mp_camera_try_mode(MPCamera *camera, MPMode *mode);
 
-bool mp_camera_set_mode(MPCamera *camera, MPCameraMode *mode);
+bool mp_camera_set_mode(MPCamera *camera, MPMode *mode);
 bool mp_camera_start_capture(MPCamera *camera);
 bool mp_camera_stop_capture(MPCamera *camera);
 bool mp_camera_is_capturing(MPCamera *camera);
 bool mp_camera_capture_buffer(MPCamera *camera, MPBuffer *buffer);
 bool mp_camera_release_buffer(MPCamera *camera, uint32_t buffer_index);
 
-typedef struct _MPCameraModeList MPCameraModeList;
-
-MPCameraModeList *mp_camera_list_supported_modes(MPCamera *camera);
-MPCameraModeList *mp_camera_list_available_modes(MPCamera *camera);
-MPCameraMode *mp_camera_mode_list_get(MPCameraModeList *list);
-MPCameraModeList *mp_camera_mode_list_next(MPCameraModeList *list);
-void mp_camera_mode_list_free(MPCameraModeList *list);
+MPModeList *mp_camera_list_supported_modes(MPCamera *camera);
+MPModeList *mp_camera_list_available_modes(MPCamera *camera);
+MPMode *mp_camera_mode_list_get(MPModeList *list);
+MPModeList *mp_camera_mode_list_next(MPModeList *list);
+void mp_camera_mode_list_free(MPModeList *list);
 
 typedef struct {
         uint32_t id;

+ 1 - 1
src/camera_config.c

@@ -83,7 +83,7 @@ strtoint(const char *nptr, char **endptr, int base)
 
 static bool
 config_handle_camera_mode(const char *prefix,
-                          MPCameraMode *mode,
+                          MPMode *mode,
                           const char *name,
                           const char *value)
 {

+ 3 - 3
src/camera_config.h

@@ -1,6 +1,6 @@
 #pragma once
 
-#include "camera.h"
+#include "mode.h"
 
 #include <stdbool.h>
 #include <stddef.h>
@@ -22,8 +22,8 @@ struct mp_camera_config {
         char dev_name[260];
         char media_dev_name[260];
 
-        MPCameraMode capture_mode;
-        MPCameraMode preview_mode;
+        MPMode capture_mode;
+        MPMode preview_mode;
         int rotate;
         bool mirrored;
 

+ 2 - 2
src/io_pipeline.c

@@ -68,7 +68,7 @@ static struct device_info devices[MP_MAX_CAMERAS];
 static size_t num_devices = 0;
 
 static const struct mp_camera_config *camera = NULL;
-static MPCameraMode mode;
+static MPMode mode;
 
 static bool just_switched_mode = false;
 static int blank_frame_count = 0;
@@ -204,7 +204,7 @@ setup_camera(MPDeviceList **device_list, const struct mp_camera_config *config)
                 // Start with the capture format, this works around a bug with
                 // the ov5640 driver where it won't allow setting the preview
                 // format initially.
-                MPCameraMode mode = config->capture_mode;
+                MPMode mode = config->capture_mode;
                 mp_camera_set_mode(info->camera, &mode);
 
                 // Trigger continuous auto focus if the sensor supports it

+ 1 - 1
src/main.c

@@ -36,7 +36,7 @@ enum user_control { USER_CONTROL_ISO, USER_CONTROL_SHUTTER };
 
 static bool camera_is_initialized = false;
 static const struct mp_camera_config *camera = NULL;
-static MPCameraMode mode;
+static MPMode mode;
 
 static int preview_width = -1;
 static int preview_height = -1;

+ 1 - 1
src/main.h

@@ -7,7 +7,7 @@
 
 struct mp_main_state {
         const struct mp_camera_config *camera;
-        MPCameraMode mode;
+        MPMode mode;
 
         int image_width;
         int image_height;

+ 263 - 0
src/mode.c

@@ -0,0 +1,263 @@
+#include "mode.h"
+
+#include <glib.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+static const char *pixel_format_names[MP_PIXEL_FMT_MAX] = {
+        "unsupported", "BGGR8",   "GBRG8",   "GRBG8", "RGGB8", "BGGR10P",
+        "GBRG10P",     "GRBG10P", "RGGB10P", "UYVY",  "YUYV",
+};
+
+const char *
+mp_pixel_format_to_str(uint32_t pixel_format)
+{
+        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, "INVALID");
+        return pixel_format_names[pixel_format];
+}
+
+MPPixelFormat
+mp_pixel_format_from_str(const char *name)
+{
+        for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) {
+                if (strcasecmp(pixel_format_names[i], name) == 0) {
+                        return i;
+                }
+        }
+        g_return_val_if_reached(MP_PIXEL_FMT_UNSUPPORTED);
+}
+
+static const uint32_t pixel_format_v4l_pixel_formats[MP_PIXEL_FMT_MAX] = {
+        0,
+        V4L2_PIX_FMT_SBGGR8,
+        V4L2_PIX_FMT_SGBRG8,
+        V4L2_PIX_FMT_SGRBG8,
+        V4L2_PIX_FMT_SRGGB8,
+        V4L2_PIX_FMT_SBGGR10P,
+        V4L2_PIX_FMT_SGBRG10P,
+        V4L2_PIX_FMT_SGRBG10P,
+        V4L2_PIX_FMT_SRGGB10P,
+        V4L2_PIX_FMT_UYVY,
+        V4L2_PIX_FMT_YUYV,
+};
+
+uint32_t
+mp_pixel_format_to_v4l_pixel_format(MPPixelFormat pixel_format)
+{
+        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
+        return pixel_format_v4l_pixel_formats[pixel_format];
+}
+
+MPPixelFormat
+mp_pixel_format_from_v4l_pixel_format(uint32_t v4l_pixel_format)
+{
+        for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) {
+                if (pixel_format_v4l_pixel_formats[i] == v4l_pixel_format) {
+                        return i;
+                }
+        }
+        return MP_PIXEL_FMT_UNSUPPORTED;
+}
+
+static const uint32_t pixel_format_v4l_bus_codes[MP_PIXEL_FMT_MAX] = {
+        0,
+        MEDIA_BUS_FMT_SBGGR8_1X8,
+        MEDIA_BUS_FMT_SGBRG8_1X8,
+        MEDIA_BUS_FMT_SGRBG8_1X8,
+        MEDIA_BUS_FMT_SRGGB8_1X8,
+        MEDIA_BUS_FMT_SBGGR10_1X10,
+        MEDIA_BUS_FMT_SGBRG10_1X10,
+        MEDIA_BUS_FMT_SGRBG10_1X10,
+        MEDIA_BUS_FMT_SRGGB10_1X10,
+        MEDIA_BUS_FMT_UYVY8_2X8,
+        MEDIA_BUS_FMT_YUYV8_2X8,
+};
+
+uint32_t
+mp_pixel_format_to_v4l_bus_code(MPPixelFormat pixel_format)
+{
+        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
+        return pixel_format_v4l_bus_codes[pixel_format];
+}
+
+MPPixelFormat
+mp_pixel_format_from_v4l_bus_code(uint32_t v4l_bus_code)
+{
+        for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) {
+                if (pixel_format_v4l_bus_codes[i] == v4l_bus_code) {
+                        return i;
+                }
+        }
+        return MP_PIXEL_FMT_UNSUPPORTED;
+}
+
+uint32_t
+mp_pixel_format_bits_per_pixel(MPPixelFormat pixel_format)
+{
+        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
+        switch (pixel_format) {
+        case MP_PIXEL_FMT_BGGR8:
+        case MP_PIXEL_FMT_GBRG8:
+        case MP_PIXEL_FMT_GRBG8:
+        case MP_PIXEL_FMT_RGGB8:
+                return 8;
+        case MP_PIXEL_FMT_BGGR10P:
+        case MP_PIXEL_FMT_GBRG10P:
+        case MP_PIXEL_FMT_GRBG10P:
+        case MP_PIXEL_FMT_RGGB10P:
+                return 10;
+        case MP_PIXEL_FMT_UYVY:
+        case MP_PIXEL_FMT_YUYV:
+                return 16;
+        default:
+                return 0;
+        }
+}
+
+uint32_t
+mp_pixel_format_pixel_depth(MPPixelFormat pixel_format)
+{
+        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
+        switch (pixel_format) {
+        case MP_PIXEL_FMT_BGGR8:
+        case MP_PIXEL_FMT_GBRG8:
+        case MP_PIXEL_FMT_GRBG8:
+        case MP_PIXEL_FMT_RGGB8:
+        case MP_PIXEL_FMT_UYVY:
+        case MP_PIXEL_FMT_YUYV:
+                return 8;
+        case MP_PIXEL_FMT_GBRG10P:
+        case MP_PIXEL_FMT_GRBG10P:
+        case MP_PIXEL_FMT_RGGB10P:
+        case MP_PIXEL_FMT_BGGR10P:
+                return 10;
+        default:
+                return 0;
+        }
+}
+
+const char *
+mp_pixel_format_cfa(MPPixelFormat pixel_format)
+{
+        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
+        switch (pixel_format) {
+        case MP_PIXEL_FMT_BGGR8:
+        case MP_PIXEL_FMT_BGGR10P:
+                return "BGGR";
+                break;
+        case MP_PIXEL_FMT_GBRG8:
+        case MP_PIXEL_FMT_GBRG10P:
+                return "GBRG";
+                break;
+        case MP_PIXEL_FMT_GRBG8:
+        case MP_PIXEL_FMT_GRBG10P:
+                return "GRBG";
+                break;
+        case MP_PIXEL_FMT_RGGB8:
+        case MP_PIXEL_FMT_RGGB10P:
+                return "RGGB";
+                break;
+        case MP_PIXEL_FMT_UYVY:
+                return "UYUV";
+                break;
+        case MP_PIXEL_FMT_YUYV:
+                return "YUYV";
+                break;
+        default:
+                return "unsupported";
+        }
+}
+
+const char *
+mp_pixel_format_cfa_pattern(MPPixelFormat pixel_format)
+{
+        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
+        switch (pixel_format) {
+        case MP_PIXEL_FMT_BGGR8:
+        case MP_PIXEL_FMT_BGGR10P:
+                return "\002\001\001\000";
+                break;
+        case MP_PIXEL_FMT_GBRG8:
+        case MP_PIXEL_FMT_GBRG10P:
+                return "\001\002\000\001";
+                break;
+        case MP_PIXEL_FMT_GRBG8:
+        case MP_PIXEL_FMT_GRBG10P:
+                return "\001\000\002\001";
+                break;
+        case MP_PIXEL_FMT_RGGB8:
+        case MP_PIXEL_FMT_RGGB10P:
+                return "\000\001\001\002";
+                break;
+        default:
+                return NULL;
+        }
+}
+
+uint32_t
+mp_pixel_format_width_to_bytes(MPPixelFormat pixel_format, uint32_t width)
+{
+        uint32_t bits_per_pixel = mp_pixel_format_bits_per_pixel(pixel_format);
+        uint64_t bits_per_width = width * (uint64_t)bits_per_pixel;
+
+        uint64_t remainder = bits_per_width % 8;
+        if (remainder == 0)
+                return bits_per_width / 8;
+
+        return (bits_per_width + 8 - remainder) / 8;
+}
+
+uint32_t
+mp_pixel_format_width_to_colors(MPPixelFormat pixel_format, uint32_t width)
+{
+        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
+        switch (pixel_format) {
+        case MP_PIXEL_FMT_BGGR8:
+        case MP_PIXEL_FMT_GBRG8:
+        case MP_PIXEL_FMT_GRBG8:
+        case MP_PIXEL_FMT_RGGB8:
+                return width / 2;
+        case MP_PIXEL_FMT_BGGR10P:
+        case MP_PIXEL_FMT_GBRG10P:
+        case MP_PIXEL_FMT_GRBG10P:
+        case MP_PIXEL_FMT_RGGB10P:
+                return width / 2 * 5;
+        case MP_PIXEL_FMT_UYVY:
+        case MP_PIXEL_FMT_YUYV:
+                return width;
+        default:
+                return 0;
+        }
+}
+
+uint32_t
+mp_pixel_format_height_to_colors(MPPixelFormat pixel_format, uint32_t height)
+{
+        g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
+        switch (pixel_format) {
+        case MP_PIXEL_FMT_BGGR8:
+        case MP_PIXEL_FMT_GBRG8:
+        case MP_PIXEL_FMT_GRBG8:
+        case MP_PIXEL_FMT_RGGB8:
+        case MP_PIXEL_FMT_BGGR10P:
+        case MP_PIXEL_FMT_GBRG10P:
+        case MP_PIXEL_FMT_GRBG10P:
+        case MP_PIXEL_FMT_RGGB10P:
+                return height / 2;
+        case MP_PIXEL_FMT_UYVY:
+        case MP_PIXEL_FMT_YUYV:
+                return height;
+        default:
+                return 0;
+        }
+}
+
+bool
+mp_mode_is_equivalent(const MPMode *m1, const MPMode *m2)
+{
+        return m1->pixel_format == m2->pixel_format &&
+               m1->frame_interval.numerator == m2->frame_interval.numerator &&
+               m1->frame_interval.denominator == m2->frame_interval.denominator &&
+               m1->width == m2->width && m1->height == m2->height;
+}

+ 55 - 0
src/mode.h

@@ -0,0 +1,55 @@
+#pragma once
+
+#include <linux/v4l2-subdev.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+typedef enum {
+        MP_PIXEL_FMT_UNSUPPORTED,
+        MP_PIXEL_FMT_BGGR8,
+        MP_PIXEL_FMT_GBRG8,
+        MP_PIXEL_FMT_GRBG8,
+        MP_PIXEL_FMT_RGGB8,
+        MP_PIXEL_FMT_BGGR10P,
+        MP_PIXEL_FMT_GBRG10P,
+        MP_PIXEL_FMT_GRBG10P,
+        MP_PIXEL_FMT_RGGB10P,
+        MP_PIXEL_FMT_UYVY,
+        MP_PIXEL_FMT_YUYV,
+
+        MP_PIXEL_FMT_MAX,
+} MPPixelFormat;
+
+const char *mp_pixel_format_to_str(MPPixelFormat pixel_format);
+MPPixelFormat mp_pixel_format_from_str(const char *str);
+
+MPPixelFormat mp_pixel_format_from_v4l_pixel_format(uint32_t v4l_pixel_format);
+MPPixelFormat mp_pixel_format_from_v4l_bus_code(uint32_t v4l_bus_code);
+uint32_t mp_pixel_format_to_v4l_pixel_format(MPPixelFormat pixel_format);
+uint32_t mp_pixel_format_to_v4l_bus_code(MPPixelFormat pixel_format);
+
+uint32_t mp_pixel_format_bits_per_pixel(MPPixelFormat pixel_format);
+uint32_t mp_pixel_format_pixel_depth(MPPixelFormat pixel_format);
+const char *mp_pixel_format_cfa(MPPixelFormat pixel_format);
+const char *mp_pixel_format_cfa_pattern(MPPixelFormat pixel_format);
+uint32_t mp_pixel_format_width_to_bytes(MPPixelFormat pixel_format, uint32_t width);
+uint32_t mp_pixel_format_width_to_colors(MPPixelFormat pixel_format, uint32_t width);
+uint32_t mp_pixel_format_height_to_colors(MPPixelFormat pixel_format,
+                                          uint32_t height);
+
+typedef struct {
+        MPPixelFormat pixel_format;
+
+        struct v4l2_fract frame_interval;
+        uint32_t width;
+        uint32_t height;
+} MPMode;
+
+bool mp_mode_is_equivalent(const MPMode *m1, const MPMode *m2);
+
+typedef struct _MPModeList MPModeList;
+
+struct _MPModeList {
+        MPMode mode;
+        MPModeList *next;
+};

+ 5 - 6
src/process_pipeline.c

@@ -31,7 +31,7 @@ static volatile int frames_received = 0;
 static const struct mp_camera_config *camera;
 static int camera_rotation;
 
-static MPCameraMode mode;
+static MPMode mode;
 
 static int burst_length;
 static int captures_remaining = 0;
@@ -834,11 +834,10 @@ mod(int a, int b)
 static void
 update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state)
 {
-        const bool output_changed =
-                !mp_camera_mode_is_equivalent(&mode, &state->mode) ||
-                preview_width != state->preview_width ||
-                preview_height != state->preview_height ||
-                device_rotation != state->device_rotation;
+        const bool output_changed = !mp_mode_is_equivalent(&mode, &state->mode) ||
+                                    preview_width != state->preview_width ||
+                                    preview_height != state->preview_height ||
+                                    device_rotation != state->device_rotation;
 
         const bool format_changed = mode.pixel_format != state->mode.pixel_format;
 

+ 2 - 1
src/process_pipeline.h

@@ -1,12 +1,13 @@
 #pragma once
 
+#include "camera.h"
 #include "camera_config.h"
 
 typedef struct _GdkSurface GdkSurface;
 
 struct mp_process_pipeline_state {
         const struct mp_camera_config *camera;
-        MPCameraMode mode;
+        MPMode mode;
 
         int burst_length;
 

+ 4 - 4
tools/camera_test.c

@@ -1,5 +1,6 @@
 #include "camera.h"
 #include "device.h"
+#include "mode.h"
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -143,15 +144,14 @@ main(int argc, char *argv[])
 
         double mode_list_begin = get_time();
 
-        MPCameraModeList *modes = mp_camera_list_available_modes(camera);
+        MPModeList *modes = mp_camera_list_available_modes(camera);
 
         double mode_list_end = get_time();
 
         printf("Available modes: (took %fms)\n",
                (mode_list_end - mode_list_begin) * 1000);
-        for (MPCameraModeList *list = modes; list;
-             list = mp_camera_mode_list_next(list)) {
-                MPCameraMode *m = mp_camera_mode_list_get(list);
+        for (MPModeList *list = modes; list; list = mp_camera_mode_list_next(list)) {
+                MPMode *m = mp_camera_mode_list_get(list);
                 printf("  %dx%d interval:%d/%d fmt:%s\n",
                        m->width,
                        m->height,