Browse Source

Pipeline improvements

Benjamin Schaaf 4 years ago
parent
commit
d2f72a9150
6 changed files with 131 additions and 69 deletions
  1. 76 3
      camera.c
  2. 10 1
      camera.h
  3. 21 11
      device.c
  4. 1 0
      device.h
  5. 19 48
      pipeline.c
  6. 4 6
      pipeline.h

+ 76 - 3
camera.c

@@ -3,6 +3,7 @@
 #include <assert.h>
 #include <errno.h>
 #include <glib.h>
+#include <stdio.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 
@@ -14,6 +15,12 @@ static const char *pixel_format_names[MP_PIXEL_FMT_MAX] = {
     "GBRG8",
     "GRBG8",
     "RGGB8",
+    "BGGR10P",
+    "GBRG10P",
+    "GRBG10P",
+    "RGGB10P",
+    "UYVY",
+    "YUYV",
 };
 
 const char *mp_pixel_format_to_str(uint32_t pixel_format)
@@ -38,6 +45,12 @@ static const uint32_t pixel_format_v4l_pixel_formats[MP_PIXEL_FMT_MAX] = {
     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)
@@ -62,6 +75,12 @@ static const uint32_t pixel_format_v4l_bus_codes[MP_PIXEL_FMT_MAX] = {
     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)
@@ -80,14 +99,68 @@ MPPixelFormat mp_pixel_format_from_v4l_bus_code(uint32_t v4l_bus_code)
     return MP_PIXEL_FMT_UNSUPPORTED;
 }
 
-uint32_t mp_pixel_format_bytes_per_pixel(MPPixelFormat pixel_format)
+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 1;
+        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_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;
     }
 }
@@ -427,7 +500,7 @@ bool mp_camera_capture_image(MPCamera *camera, void (*callback)(MPImage, void *)
     uint32_t width = camera->current_mode.width;
     uint32_t height = camera->current_mode.height;
 
-    assert(buf.bytesused == mp_pixel_format_bytes_per_pixel(pixel_format) * width * height);
+    assert(buf.bytesused == mp_pixel_format_width_to_bytes(pixel_format, width) * height);
     assert(buf.bytesused == camera->buffers[buf.index].length);
 
     MPImage image = {

+ 10 - 1
camera.h

@@ -10,6 +10,12 @@ typedef enum {
     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;
@@ -22,7 +28,10 @@ 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_bytes_per_pixel(MPPixelFormat pixel_format);
+uint32_t mp_pixel_format_bits_per_pixel(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;

+ 21 - 11
device.c

@@ -67,20 +67,10 @@ static int xioctl(int fd, int request, void *arg)
 
 MPDevice *mp_device_find(const char *driver_name)
 {
-    MPDevice *found_device = NULL;
-
-    int length = strlen(driver_name);
     MPDeviceList *list = mp_device_list_new();
 
-    for (MPDeviceList *item = list; item; item = mp_device_list_next(item)) {
-        MPDevice *device = mp_device_list_get(item);
-        const struct media_device_info *info = mp_device_get_info(device);
+    MPDevice *found_device = mp_device_list_find_remove(&list, driver_name);
 
-        if (strncmp(info->driver, driver_name, length) == 0) {
-            found_device = mp_device_list_remove(&item);
-            break;
-        }
-    }
 
     mp_device_list_free(list);
 
@@ -375,6 +365,26 @@ void mp_device_list_free(MPDeviceList *device_list)
     }
 }
 
+MPDevice *mp_device_list_find_remove(MPDeviceList **list, const char *driver_name)
+{
+    MPDevice *found_device = NULL;
+    int length = strlen(driver_name);
+
+    while (*list) {
+        MPDevice *device = mp_device_list_get(*list);
+        const struct media_device_info *info = mp_device_get_info(device);
+
+        if (strncmp(info->driver, driver_name, length) == 0) {
+            found_device = mp_device_list_remove(list);
+            break;
+        }
+
+        list = &(*list)->next;
+    }
+
+    return found_device;
+}
+
 MPDevice *mp_device_list_remove(MPDeviceList **device_list)
 {
     MPDevice *device = (*device_list)->device;

+ 1 - 0
device.h

@@ -42,6 +42,7 @@ typedef struct _MPDeviceList MPDeviceList;
 MPDeviceList *mp_device_list_new();
 void mp_device_list_free(MPDeviceList *device_list);
 
+MPDevice *mp_device_list_find_remove(MPDeviceList **device_list, const char *driver_name);
 MPDevice *mp_device_list_remove(MPDeviceList **device_list);
 
 MPDevice *mp_device_list_get(const MPDeviceList *device_list);

+ 19 - 48
pipeline.c

@@ -32,7 +32,7 @@ MPPipeline *mp_pipeline_new()
 
 struct invoke_args {
     MPPipeline *pipeline;
-    void (*callback)(MPPipeline *, void *);
+    MPPipelineCallback callback;
 };
 
 static bool invoke_impl(struct invoke_args *args)
@@ -41,7 +41,7 @@ static bool invoke_impl(struct invoke_args *args)
     return false;
 }
 
-void mp_pipeline_invoke(MPPipeline *pipeline, MPPipelineCallback callback, void *data, size_t size)
+void mp_pipeline_invoke(MPPipeline *pipeline, MPPipelineCallback callback, const void *data, size_t size)
 {
     if (pthread_self() != pipeline->thread) {
         struct invoke_args *args = malloc(sizeof(struct invoke_args) + size);
@@ -75,63 +75,34 @@ void mp_pipeline_free(MPPipeline *pipeline)
     free(pipeline);
 }
 
-struct _MPPipelineCapture {
-    MPPipeline *pipeline;
+struct capture_source_args
+{
     MPCamera *camera;
-
     void (*callback)(MPImage, void *);
     void *user_data;
-    GSource *video_source;
 };
 
-static bool on_capture(int fd, GIOCondition condition, MPPipelineCapture *capture)
+static bool on_capture(int fd, GIOCondition condition, struct capture_source_args *args)
 {
-    mp_camera_capture_image(capture->camera, capture->callback, capture->user_data);
+    mp_camera_capture_image(args->camera, args->callback, args->user_data);
     return true;
 }
 
-static void capture_start_impl(MPPipeline *pipeline, MPPipelineCapture **_capture)
+// Not thread safe
+GSource *mp_pipeline_add_capture_source(MPPipeline *pipeline, MPCamera *camera, void (*callback)(MPImage, void *), void *user_data)
 {
-    MPPipelineCapture *capture = *_capture;
+    int video_fd = mp_camera_get_video_fd(camera);
+    GSource *video_source = g_unix_fd_source_new(video_fd, G_IO_IN);
 
-    mp_camera_start_capture(capture->camera);
-
-    // Start watching for new captures
-    int video_fd = mp_camera_get_video_fd(capture->camera);
-    capture->video_source = g_unix_fd_source_new(video_fd, G_IO_IN);
+    struct capture_source_args *args = malloc(sizeof(struct capture_source_args));
+    args->camera = camera;
+    args->callback = callback;
+    args->user_data = user_data;
     g_source_set_callback(
-        capture->video_source,
+        video_source,
         (GSourceFunc)on_capture,
-        capture,
-        NULL);
-    g_source_attach(capture->video_source, capture->pipeline->main_context);
-}
-
-MPPipelineCapture *mp_pipeline_capture_start(MPPipeline *pipeline, MPCamera *camera, void (*callback)(MPImage, void *), void *user_data)
-{
-    MPPipelineCapture *capture = malloc(sizeof(MPPipelineCapture));
-    capture->pipeline = pipeline;
-    capture->camera = camera;
-    capture->callback = callback;
-    capture->user_data = user_data;
-    capture->video_source = NULL;
-
-    mp_pipeline_invoke(pipeline, (MPPipelineCallback)capture_start_impl, &capture, sizeof(MPPipelineCapture *));
-
-    return capture;
-}
-
-static void capture_end_impl(MPPipeline *pipeline, MPPipelineCapture **_capture)
-{
-    MPPipelineCapture *capture = *_capture;
-
-    mp_camera_stop_capture(capture->camera);
-    g_source_destroy(capture->video_source);
-
-    free(capture);
-}
-
-void mp_pipeline_capture_end(MPPipelineCapture *capture)
-{
-    mp_pipeline_invoke(capture->pipeline, (MPPipelineCallback)capture_end_impl, &capture, sizeof(MPPipelineCapture *));
+        args,
+        free);
+    g_source_attach(video_source, pipeline->main_context);
+    return video_source;
 }

+ 4 - 6
pipeline.h

@@ -2,16 +2,14 @@
 
 #include "camera.h"
 #include "device.h"
+#include <glib.h>
 
 typedef struct _MPPipeline MPPipeline;
 
-typedef void (*MPPipelineCallback)(MPPipeline *, void *);
+typedef void (*MPPipelineCallback)(MPPipeline *, const void *);
 
 MPPipeline *mp_pipeline_new();
-void mp_pipeline_invoke(MPPipeline *pipeline, MPPipelineCallback callback, void *data, size_t size);
+void mp_pipeline_invoke(MPPipeline *pipeline, MPPipelineCallback callback, const void *data, size_t size);
 void mp_pipeline_free(MPPipeline *pipeline);
 
-typedef struct _MPPipelineCapture MPPipelineCapture;
-
-MPPipelineCapture *mp_pipeline_capture_start(MPPipeline *pipeline, MPCamera *camera, void (*capture)(MPImage, void *), void *data);
-void mp_pipeline_capture_end(MPPipelineCapture *capture);
+GSource *mp_pipeline_add_capture_source(MPPipeline *pipeline, MPCamera *camera, void (*callback)(MPImage, void *), void *user_data);