Pipeline improvements
This commit is contained in:
parent
0ba1a6844e
commit
d2f72a9150
79
camera.c
79
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 = {
|
||||
|
|
11
camera.h
11
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;
|
||||
|
|
32
device.c
32
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
device.h
1
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);
|
||||
|
|
67
pipeline.c
67
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;
|
||||
}
|
||||
|
|
10
pipeline.h
10
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);
|
||||
|
|
Loading…
Reference in New Issue