From a4c2c1ec1f93bba9a3c1ac9afac639d63a61a4cf Mon Sep 17 00:00:00 2001 From: Yassine Oudjana Date: Wed, 23 Feb 2022 10:23:02 +0400 Subject: [PATCH] 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. --- meson.build | 5 + src/camera.c | 320 ++++------------------------------------- src/camera.h | 64 ++------- src/camera_config.c | 2 +- src/camera_config.h | 6 +- src/io_pipeline.c | 4 +- src/main.c | 2 +- src/main.h | 2 +- src/mode.c | 263 +++++++++++++++++++++++++++++++++ src/mode.h | 55 +++++++ src/process_pipeline.c | 11 +- src/process_pipeline.h | 3 +- tools/camera_test.c | 8 +- 13 files changed, 381 insertions(+), 364 deletions(-) create mode 100644 src/mode.c create mode 100644 src/mode.h diff --git a/meson.build b/meson.build index 4e7d505..565a564 100644 --- a/meson.build +++ b/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', diff --git a/src/camera.c b/src/camera.c index 9e364b3..9f95de6 100644 --- a/src/camera.c +++ b/src/camera.c @@ -1,8 +1,10 @@ #include "camera.h" +#include "mode.h" #include #include #include +#include #include #include #include @@ -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); } diff --git a/src/camera.h b/src/camera.h index 62f15df..be3e071 100644 --- a/src/camera.h +++ b/src/camera.h @@ -1,53 +1,11 @@ #pragma once -#include +#include "mode.h" + #include #include #include -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; diff --git a/src/camera_config.c b/src/camera_config.c index 5cb93f7..6ff74d1 100644 --- a/src/camera_config.c +++ b/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) { diff --git a/src/camera_config.h b/src/camera_config.h index 4964685..d53d36f 100644 --- a/src/camera_config.h +++ b/src/camera_config.h @@ -1,6 +1,6 @@ #pragma once -#include "camera.h" +#include "mode.h" #include #include @@ -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; diff --git a/src/io_pipeline.c b/src/io_pipeline.c index 63adbbb..65e773c 100644 --- a/src/io_pipeline.c +++ b/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 diff --git a/src/main.c b/src/main.c index 8ab745d..68494c6 100644 --- a/src/main.c +++ b/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; diff --git a/src/main.h b/src/main.h index 6c8f4be..b2df652 100644 --- a/src/main.h +++ b/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; diff --git a/src/mode.c b/src/mode.c new file mode 100644 index 0000000..8db36e3 --- /dev/null +++ b/src/mode.c @@ -0,0 +1,263 @@ +#include "mode.h" + +#include +#include +#include +#include + +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; +} diff --git a/src/mode.h b/src/mode.h new file mode 100644 index 0000000..f3e5a5b --- /dev/null +++ b/src/mode.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include +#include + +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; +}; diff --git a/src/process_pipeline.c b/src/process_pipeline.c index 14f87b7..ceb0aff 100644 --- a/src/process_pipeline.c +++ b/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; diff --git a/src/process_pipeline.h b/src/process_pipeline.h index 10b4442..1225db9 100644 --- a/src/process_pipeline.h +++ b/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; diff --git a/tools/camera_test.c b/tools/camera_test.c index cf07791..11c0477 100644 --- a/tools/camera_test.c +++ b/tools/camera_test.c @@ -1,5 +1,6 @@ #include "camera.h" #include "device.h" +#include "mode.h" #include #include #include @@ -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,