From f8d44c6e6062af50257cd5dd74afdb835409628e Mon Sep 17 00:00:00 2001 From: twinaphex Date: Mon, 11 Nov 2013 14:26:57 +0100 Subject: [PATCH] (Camera) Add camera driver init/deinit when HAVE_CAMERA is defined --- camera/video4linux2.c | 19 ++++++--- config.def.h | 11 ++++- driver.c | 97 +++++++++++++++++++++++++++++++++++++++++-- driver.h | 9 +++- driver_funcs.h | 2 + general.h | 16 +++++++ settings.c | 20 +++++++++ 7 files changed, 163 insertions(+), 11 deletions(-) diff --git a/camera/video4linux2.c b/camera/video4linux2.c index 21a6696be0..82673fd254 100644 --- a/camera/video4linux2.c +++ b/camera/video4linux2.c @@ -29,6 +29,7 @@ #include #include #include +#include "../compat/strl.h" #include @@ -49,7 +50,7 @@ struct buffer typedef struct video4linux { - char *dev_name; + char dev_name[256]; int fd; bool ready; io_method io; @@ -537,17 +538,23 @@ static int v4l_start(void *data) return 0; } -static void *v4l_init(void) +static void *v4l_init(const char *device, unsigned width, unsigned height) { + (void)width; + (void)height; + struct stat st; video4linux_t *v4l = (video4linux_t*)calloc(1, sizeof(video4linux_t)); if (!v4l) return NULL; - // FIXME - /dev/video0 assumed for now - should allow for selecting which device - v4l->dev_name = "/dev/video0"; - v4l->width = 640; - v4l->height = 480; + if (device == NULL) + strlcpy(v4l->dev_name, "/dev/video0", sizeof(v4l->dev_name)); + else + strlcpy(v4l->dev_name, device, sizeof(v4l->dev_name)); + + v4l->width = 640; //FIXME - use width param + v4l->height = 480; //FIXME - use height param v4l->ready = false; if (stat(v4l->dev_name, &st) == -1) diff --git a/config.def.h b/config.def.h index 410a223f50..4d731e481a 100644 --- a/config.def.h +++ b/config.def.h @@ -79,7 +79,10 @@ enum INPUT_APPLE, INPUT_QNX, INPUT_RWEBINPUT, - INPUT_NULL + INPUT_NULL, + + CAMERA_V4L2, + CAMERA_NULL, }; #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) || defined(__CELLOS_LV2__) @@ -178,6 +181,12 @@ enum #define INPUT_DEFAULT_DRIVER INPUT_NULL #endif +#if defined(HAVE_V4L2) +#define CAMERA_DEFAULT_DRIVER CAMERA_V4L2 +#else +#define CAMERA_DEFAULT_DRIVER CAMERA_NULL +#endif + #if defined(XENON) || defined(_XBOX360) || defined(__CELLOS_LV2__) #define DEFAULT_ASPECT_RATIO 1.7778f #elif defined(_XBOX1) || defined(GEKKO) || defined(ANDROID) || defined(__BLACKBERRY_QNX__) diff --git a/driver.c b/driver.c index 3921de7196..6f852d67b5 100644 --- a/driver.c +++ b/driver.c @@ -179,6 +179,41 @@ static const input_driver_t *input_drivers[] = { NULL, }; +#ifdef HAVE_CAMERA +static const camera_driver_t *camera_drivers[] = { +#ifdef HAVE_V4L2 + &camera_v4l2, +#endif + NULL, +}; + +static int find_camera_driver_index(const char *driver) +{ + unsigned i; + for (i = 0; camera_drivers[i]; i++) + if (strcasecmp(driver, camera_drivers[i]->ident) == 0) + return i; + return -1; +} + +static void find_camera_driver(void) +{ + int i = find_camera_driver_index(g_settings.camera.driver); + if (i >= 0) + driver.camera = camera_drivers[i]; + else + { + unsigned d; + RARCH_ERR("Couldn't find any camera driver named \"%s\"\n", g_settings.camera.driver); + RARCH_LOG_OUTPUT("Available camera drivers are:\n"); + for (d = 0; camera_drivers[d]; d++) + RARCH_LOG_OUTPUT("\t%s\n", camera_drivers[d]->ident); + + rarch_fail(1, "find_camera_driver()"); + } +} +#endif + static int find_audio_driver_index(const char *driver) { unsigned i; @@ -327,6 +362,9 @@ void init_drivers_pre(void) find_audio_driver(); find_video_driver(); find_input_driver(); +#ifdef HAVE_CAMERA + find_camera_driver(); +#endif } static void adjust_system_rates(void) @@ -468,13 +506,44 @@ void global_uninit_drivers(void) driver.input->free(driver.input_data); driver.input_data = NULL; } + +#ifdef HAVE_CAMERA + if (driver.camera && driver.camera_data) + { + driver.camera->free(driver.camera_data); + driver.camera_data = NULL; + } +#endif } +#ifdef HAVE_CAMERA +void init_camera(void) +{ + // Resource leaks will follow if camera is initialized twice. + if (driver.camera_data) + return; + + find_camera_driver(); + + driver.camera_data = camera_init_func(*g_settings.camera.device ? g_settings.camera.device : NULL, + g_settings.camera.width, g_settings.camera.height); + + if (!driver.camera_data) + { + RARCH_ERR("Failed to initialize camera driver. Will continue without camera.\n"); + g_extern.camera_active = false; + } +} +#endif + void init_drivers(void) { driver.video_data_own = !driver.video_data; driver.audio_data_own = !driver.audio_data; driver.input_data_own = !driver.input_data; +#ifdef HAVE_CAMERA + driver.camera_data_own = !driver.camera_data_own; +#endif adjust_system_rates(); @@ -487,6 +556,10 @@ void init_drivers(void) init_audio(); +#ifdef HAVE_CAMERA + init_camera(); +#endif + // Keep non-throttled state as good as possible. if (driver.nonblock_state) driver_set_nonblock_state(driver.nonblock_state); @@ -494,6 +567,14 @@ void init_drivers(void) g_extern.system.frame_time_last = 0; } +#ifdef HAVE_CAMERA +void uninit_camera(void) +{ + if (driver.camera_data && driver.camera) + driver.camera->free(driver.camera_data); +} +#endif + void uninit_drivers(void) { uninit_audio(); @@ -503,6 +584,12 @@ void uninit_drivers(void) uninit_video_input(); +#ifdef HAVE_CAMERA + uninit_camera(); + + if (driver.camera_data_own) + driver.camera_data = NULL; +#endif if (driver.video_data_own) driver.video_data = NULL; if (driver.audio_data_own) @@ -510,9 +597,12 @@ void uninit_drivers(void) if (driver.input_data_own) driver.input_data = NULL; - driver.video_data_own = false; - driver.audio_data_own = false; - driver.input_data_own = false; +#ifdef HAVE_CAMERA + driver.camera_data_own = false; +#endif + driver.video_data_own = false; + driver.audio_data_own = false; + driver.input_data_own = false; } #ifdef HAVE_DYLIB @@ -692,6 +782,7 @@ void init_audio(void) audio_start_func(); } + static void compute_audio_buffer_statistics(void) { unsigned i, samples; diff --git a/driver.h b/driver.h index 111b8643a5..665264fd24 100644 --- a/driver.h +++ b/driver.h @@ -335,7 +335,7 @@ typedef struct camera_driver { //FIXME - params for init - queries for resolution, framerate, color format //which might or might not be honored - void *(*init)(void); + void *(*init)(const char *device, unsigned width, unsigned height); void (*free)(void *data); int (*start)(void *data); int (*stop)(void *data); @@ -430,6 +430,10 @@ typedef struct driver const audio_driver_t *audio; const video_driver_t *video; const input_driver_t *input; +#ifdef HAVE_CAMERA + const camera_driver_t *camera; + void *camera_data; +#endif void *audio_data; void *video_data; void *input_data; @@ -451,6 +455,9 @@ typedef struct driver bool video_data_own; bool audio_data_own; bool input_data_own; +#ifdef HAVE_CAMERA + bool camera_data_own; +#endif #ifdef HAVE_COMMAND rarch_cmd_t *command; diff --git a/driver_funcs.h b/driver_funcs.h index 56237a9cd6..995b94b0f1 100644 --- a/driver_funcs.h +++ b/driver_funcs.h @@ -18,6 +18,8 @@ #ifndef _RARCH_DRIVER_FUNCS_H #define _RARCH_DRIVER_FUNCS_H +#define camera_init_func(device, width, height) driver.camera->init(device, width, height) + #define audio_init_func(device, rate, latency) driver.audio->init(device, rate, latency) #define audio_write_func(buf, size) driver.audio->write(driver.audio_data, buf, size) #define audio_stop_func() driver.audio->stop(driver.audio_data) diff --git a/general.h b/general.h index c081b9f80c..02ba94b2c2 100644 --- a/general.h +++ b/general.h @@ -185,6 +185,16 @@ struct settings bool allow_rotate; } video; +#ifdef HAVE_CAMERA + struct + { + char driver[32]; + char device[PATH_MAX]; + unsigned width; + unsigned height; + } camera; +#endif + struct { char driver[32]; @@ -309,6 +319,9 @@ struct global bool verbose; bool audio_active; bool video_active; +#ifdef HAVE_CAMERA + bool camera_active; +#endif bool force_fullscreen; bool rom_file_temporary; @@ -621,6 +634,9 @@ struct rarch_main_wrap // Public functions void config_load(void); void config_set_defaults(void); +#ifdef HAVE_CAMERA +const char *config_get_default_camera(void); +#endif const char *config_get_default_video(void); const char *config_get_default_audio(void); const char *config_get_default_input(void); diff --git a/settings.c b/settings.c index 6ffd96c75f..ced3899fe0 100644 --- a/settings.c +++ b/settings.c @@ -148,13 +148,33 @@ const char *config_get_default_input(void) } } +#ifdef HAVE_CAMERA +const char *config_get_default_camera(void) +{ + switch (CAMERA_DEFAULT_DRIVER) + { + case CAMERA_V4L2: + return "video4linux2"; + case CAMERA_NULL: + return "null"; + default: + return NULL; + } +} +#endif + void config_set_defaults(void) { unsigned i, j; const char *def_video = config_get_default_video(); const char *def_audio = config_get_default_audio(); const char *def_input = config_get_default_input(); +#ifdef HAVE_CAMERA + const char *def_camera = config_get_default_camera(); + if (def_camera) + strlcpy(g_settings.camera.driver, def_camera, sizeof(g_settings.camera.driver)); +#endif if (def_video) strlcpy(g_settings.video.driver, def_video, sizeof(g_settings.video.driver)); if (def_audio)