Pipeline improvements

This commit is contained in:
Benjamin Schaaf 2020-11-26 00:31:52 +11:00
parent 0ba1a6844e
commit d2f72a9150
6 changed files with 131 additions and 69 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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