diff --git a/CMakeLists.txt b/CMakeLists.txt index d3b09c6b3..b6eefb296 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -332,6 +332,7 @@ set_option(SDL_KMSDRM "Use KMS DRM video driver" ${UNIX_SYS}) dep_option(SDL_KMSDRM_SHARED "Dynamically load KMS DRM support" ON "SDL_KMSDRM" OFF) set_option(SDL_OFFSCREEN "Use offscreen video driver" ON) dep_option(SDL_CAMERA "Enable camera support" ON SDL_VIDEO OFF) +set_option(SDL_DUMMYCAMERA "Support the dummy camera driver" ON) option_string(SDL_BACKGROUNDING_SIGNAL "number to use for magic backgrounding signal or 'OFF'" OFF) option_string(SDL_FOREGROUNDING_SIGNAL "number to use for magic foregrounding signal or 'OFF'" OFF) dep_option(SDL_HIDAPI "Enable the HIDAPI subsystem" ON "NOT VISIONOS" OFF) @@ -1172,6 +1173,23 @@ if(SDL_AUDIO) endif() endif() +if(SDL_CAMERA) + # CheckDummyCamera/CheckDiskCamera - valid for all platforms + if(SDL_DUMMYCAMERA) + set(SDL_CAMERA_DRIVER_DUMMY 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/dummy/*.c") + set(HAVE_DUMMYCAMERA TRUE) + set(HAVE_SDL_CAMERA TRUE) + endif() + # !!! FIXME: for later. + #if(SDL_DISKCAMERA) + # set(SDL_CAMERA_DRIVER_DISK 1) + # sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/disk/*.c") + # set(HAVE_DISKCAMERA TRUE) + # set(HAVE_SDL_CAMERA TRUE) + #endif() +endif() + if(UNIX OR APPLE) # Relevant for Unix/Darwin only set(DYNAPI_NEEDS_DLOPEN 1) @@ -1290,7 +1308,7 @@ if(ANDROID) endif() if(SDL_CAMERA) - set(SDL_CAMERA_ANDROID 1) + set(SDL_CAMERA_DRIVER_ANDROID 1) set(HAVE_CAMERA TRUE) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/android/*.c") endif() @@ -1531,7 +1549,7 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) endif() if(SDL_CAMERA AND HAVE_LINUX_VIDEODEV2_H) - set(SDL_CAMERA_V4L2 1) + set(SDL_CAMERA_DRIVER_V4L2 1) set(HAVE_CAMERA TRUE) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/v4l2/*.c") endif() @@ -2035,9 +2053,9 @@ elseif(APPLE) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/file/cocoa/*.m") if(IOS OR TVOS OR MACOSX OR DARWIN) - set(SDL_CAMERA_APPLE TRUE) + set(SDL_CAMERA_DRIVER_COREMEDIA 1) set(HAVE_CAMERA TRUE) - sdl_sources("${SDL3_SOURCE_DIR}/src/camera/apple/SDL_camera_apple.m") + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/coremedia/*.m") endif() if(IOS OR TVOS OR VISIONOS) @@ -2739,7 +2757,7 @@ if(NOT HAVE_SDL_MISC) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/dummy/*.c") endif() if(NOT HAVE_CAMERA) - set(SDL_CAMERA_DUMMY 1) + set(SDL_CAMERA_DRIVER_DUMMY 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/dummy/*.c") endif() diff --git a/include/SDL3/SDL_camera.h b/include/SDL3/SDL_camera.h index c37499c54..e2b13cfe8 100644 --- a/include/SDL3/SDL_camera.h +++ b/include/SDL3/SDL_camera.h @@ -108,6 +108,71 @@ typedef struct SDL_CameraFrame } SDL_CameraFrame; +/** + * Use this function to get the number of built-in camera drivers. + * + * This function returns a hardcoded number. This never returns a negative + * value; if there are no drivers compiled into this build of SDL, this + * function returns zero. The presence of a driver in this list does not mean + * it will function, it just means SDL is capable of interacting with that + * interface. For example, a build of SDL might have v4l2 support, but if + * there's no kernel support available, SDL's v4l2 driver would fail if used. + * + * By default, SDL tries all drivers, in its preferred order, until one is + * found to be usable. + * + * \returns the number of built-in camera drivers. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetCameraDriver + */ +extern DECLSPEC int SDLCALL SDL_GetNumCameraDrivers(void); + +/** + * Use this function to get the name of a built in camera driver. + * + * The list of camera drivers is given in the order that they are normally + * initialized by default; the drivers that seem more reasonable to choose + * first (as far as the SDL developers believe) are earlier in the list. + * + * The names of drivers are all simple, low-ASCII identifiers, like "v4l2", + * "coremedia" or "android". These never have Unicode characters, and are not + * meant to be proper names. + * + * \param index the index of the camera driver; the value ranges from 0 to + * SDL_GetNumCameraDrivers() - 1 + * \returns the name of the camera driver at the requested index, or NULL if an + * invalid index was specified. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetNumCameraDrivers + */ +extern DECLSPEC const char *SDLCALL SDL_GetCameraDriver(int index); + +/** + * Get the name of the current camera driver. + * + * The returned string points to internal static memory and thus never becomes + * invalid, even if you quit the camera subsystem and initialize a new driver + * (although such a case would return a different static string from another + * call to this function, of course). As such, you should not modify or free + * the returned string. + * + * \returns the name of the current camera driver or NULL if no driver has been + * initialized. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC const char *SDLCALL SDL_GetCurrentCameraDriver(void); + /** * Get a list of currently connected camera devices. * diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index acbbd84ea..7c30a707d 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -355,6 +355,22 @@ extern "C" { */ #define SDL_HINT_BMP_SAVE_LEGACY_FORMAT "SDL_BMP_SAVE_LEGACY_FORMAT" +/** + * A variable that decides what camera backend to use. + * + * By default, SDL will try all available camera backends in a reasonable + * order until it finds one that can work, but this hint allows the app + * or user to force a specific target, such as "directshow" if, say, you are + * on Windows Media Foundations but want to try DirectShow instead. + * + * The default value is unset, in which case SDL will try to figure out + * the best camera backend on your behalf. This hint needs to be set + * before SDL_Init() is called to be useful. + * + * This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_CAMERA_DRIVER "SDL_CAMERA_DRIVER" + /** * A variable controlling whether DirectInput should be used for controllers * @@ -2478,7 +2494,6 @@ extern "C" { */ #define SDL_HINT_XINPUT_ENABLED "SDL_XINPUT_ENABLED" - /** * An enumeration of hint priorities */ diff --git a/include/SDL3/SDL_init.h b/include/SDL3/SDL_init.h index c208b5f7d..8459bf9eb 100644 --- a/include/SDL3/SDL_init.h +++ b/include/SDL3/SDL_init.h @@ -59,7 +59,8 @@ typedef enum SDL_INIT_HAPTIC = 0x00001000, SDL_INIT_GAMEPAD = 0x00002000, /**< `SDL_INIT_GAMEPAD` implies `SDL_INIT_JOYSTICK` */ SDL_INIT_EVENTS = 0x00004000, - SDL_INIT_SENSOR = 0x00008000 + SDL_INIT_SENSOR = 0x00008000, + SDL_INIT_CAMERA = 0x00010000 /**< `SDL_INIT_CAMERA` implies `SDL_INIT_EVENTS` */ } SDL_InitFlags; /** diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index 076d3120f..7985065dc 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -467,10 +467,11 @@ #cmakedefine SDL_FILESYSTEM_N3DS @SDL_FILESYSTEM_N3DS@ /* Enable camera subsystem */ -#cmakedefine SDL_CAMERA_DUMMY @SDL_CAMERA_DUMMY@ -#cmakedefine SDL_CAMERA_V4L2 @SDL_CAMERA_V4L2@ -#cmakedefine SDL_CAMERA_APPLE @SDL_CAMERA_APPLE@ -#cmakedefine SDL_CAMERA_ANDROID @SDL_CAMERA_ANDROID@ +#cmakedefine SDL_CAMERA_DRIVER_DUMMY @SDL_CAMERA_DRIVER_DUMMY@ +/* !!! FIXME: for later cmakedefine SDL_CAMERA_DRIVER_DISK @SDL_CAMERA_DRIVER_DISK@ */ +#cmakedefine SDL_CAMERA_DRIVER_V4L2 @SDL_CAMERA_DRIVER_V4L2@ +#cmakedefine SDL_CAMERA_DRIVER_COREMEDIA @SDL_CAMERA_DRIVER_COREMEDIA@ +#cmakedefine SDL_CAMERA_DRIVER_ANDROID @SDL_CAMERA_DRIVER_ANDROID@ /* Enable misc subsystem */ #cmakedefine SDL_MISC_DUMMY @SDL_MISC_DUMMY@ diff --git a/include/build_config/SDL_build_config_android.h b/include/build_config/SDL_build_config_android.h index c2eaf0985..9ae2ca4d9 100644 --- a/include/build_config/SDL_build_config_android.h +++ b/include/build_config/SDL_build_config_android.h @@ -191,6 +191,6 @@ #define SDL_FILESYSTEM_ANDROID 1 /* Enable the camera driver */ -#define SDL_CAMERA_ANDROID 1 +#define SDL_CAMERA_DRIVER_ANDROID 1 #endif /* SDL_build_config_android_h_ */ diff --git a/include/build_config/SDL_build_config_emscripten.h b/include/build_config/SDL_build_config_emscripten.h index 3d7836678..07a94d615 100644 --- a/include/build_config/SDL_build_config_emscripten.h +++ b/include/build_config/SDL_build_config_emscripten.h @@ -210,6 +210,6 @@ #define SDL_FILESYSTEM_EMSCRIPTEN 1 /* Enable the camera driver (src/camera/dummy/\*.c) */ /* !!! FIXME */ -#define SDL_CAMERA_DUMMY 1 +#define SDL_CAMERA_DRIVER_DUMMY 1 #endif /* SDL_build_config_emscripten_h */ diff --git a/include/build_config/SDL_build_config_ios.h b/include/build_config/SDL_build_config_ios.h index a356f8920..649ff4e86 100644 --- a/include/build_config/SDL_build_config_ios.h +++ b/include/build_config/SDL_build_config_ios.h @@ -213,6 +213,6 @@ #define SDL_FILESYSTEM_COCOA 1 /* enable camera support */ -#define SDL_CAMERA_APPLE 1 +#define SDL_CAMERA_DRIVER_COREMEDIA 1 #endif /* SDL_build_config_ios_h_ */ diff --git a/include/build_config/SDL_build_config_macos.h b/include/build_config/SDL_build_config_macos.h index d45a3980c..a8bed484d 100644 --- a/include/build_config/SDL_build_config_macos.h +++ b/include/build_config/SDL_build_config_macos.h @@ -270,7 +270,8 @@ #define SDL_FILESYSTEM_COCOA 1 /* enable camera support */ -#define SDL_CAMERA_APPLE 1 +#define SDL_CAMERA_DRIVER_COREMEDIA 1 +#define SDL_CAMERA_DRIVER_DUMMY 1 /* Enable assembly routines */ #ifdef __ppc__ diff --git a/include/build_config/SDL_build_config_minimal.h b/include/build_config/SDL_build_config_minimal.h index 38e870160..06d02557e 100644 --- a/include/build_config/SDL_build_config_minimal.h +++ b/include/build_config/SDL_build_config_minimal.h @@ -90,6 +90,6 @@ typedef unsigned int uintptr_t; #define SDL_FILESYSTEM_DUMMY 1 /* Enable the camera driver (src/camera/dummy/\*.c) */ -#define SDL_CAMERA_DUMMY 1 +#define SDL_CAMERA_DRIVER_DUMMY 1 #endif /* SDL_build_config_minimal_h_ */ diff --git a/include/build_config/SDL_build_config_ngage.h b/include/build_config/SDL_build_config_ngage.h index a8719bd90..3449627b0 100644 --- a/include/build_config/SDL_build_config_ngage.h +++ b/include/build_config/SDL_build_config_ngage.h @@ -87,6 +87,6 @@ typedef unsigned long uintptr_t; #define SDL_FILESYSTEM_DUMMY 1 /* Enable the camera driver (src/camera/dummy/\*.c) */ -#define SDL_CAMERA_DUMMY 1 +#define SDL_CAMERA_DRIVER_DUMMY 1 #endif /* SDL_build_config_ngage_h_ */ diff --git a/include/build_config/SDL_build_config_windows.h b/include/build_config/SDL_build_config_windows.h index 42682d8fc..066888fbd 100644 --- a/include/build_config/SDL_build_config_windows.h +++ b/include/build_config/SDL_build_config_windows.h @@ -312,6 +312,6 @@ typedef unsigned int uintptr_t; #define SDL_FILESYSTEM_WINDOWS 1 /* Enable the camera driver (src/camera/dummy/\*.c) */ /* !!! FIXME */ -#define SDL_CAMERA_DUMMY 1 +#define SDL_CAMERA_DRIVER_DUMMY 1 #endif /* SDL_build_config_windows_h_ */ diff --git a/include/build_config/SDL_build_config_wingdk.h b/include/build_config/SDL_build_config_wingdk.h index 0c60bea6f..a636694a0 100644 --- a/include/build_config/SDL_build_config_wingdk.h +++ b/include/build_config/SDL_build_config_wingdk.h @@ -248,7 +248,7 @@ #define SDL_FILESYSTEM_WINDOWS 1 /* Enable the camera driver (src/camera/dummy/\*.c) */ /* !!! FIXME */ -#define SDL_CAMERA_DUMMY 1 +#define SDL_CAMERA_DRIVER_DUMMY 1 /* Use the (inferior) GDK text input method for GDK platforms */ /*#define SDL_GDK_TEXTINPUT 1*/ diff --git a/include/build_config/SDL_build_config_winrt.h b/include/build_config/SDL_build_config_winrt.h index 4b3f865c4..07c656ef3 100644 --- a/include/build_config/SDL_build_config_winrt.h +++ b/include/build_config/SDL_build_config_winrt.h @@ -216,6 +216,6 @@ #define SDL_POWER_WINRT 1 /* Enable the camera driver (src/camera/dummy/\*.c) */ /* !!! FIXME */ -#define SDL_CAMERA_DUMMY 1 +#define SDL_CAMERA_DRIVER_DUMMY 1 #endif /* SDL_build_config_winrt_h_ */ diff --git a/include/build_config/SDL_build_config_xbox.h b/include/build_config/SDL_build_config_xbox.h index 11116f9a6..ea050da7d 100644 --- a/include/build_config/SDL_build_config_xbox.h +++ b/include/build_config/SDL_build_config_xbox.h @@ -237,6 +237,6 @@ #define SDL_GDK_TEXTINPUT 1 /* Enable the camera driver (src/camera/dummy/\*.c) */ -#define SDL_CAMERA_DUMMY 1 +#define SDL_CAMERA_DRIVER_DUMMY 1 #endif /* SDL_build_config_wingdk_h_ */ diff --git a/src/SDL.c b/src/SDL.c index e5c43fee1..1553f80bc 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -46,6 +46,7 @@ #include "joystick/SDL_gamepad_c.h" #include "joystick/SDL_joystick_c.h" #include "sensor/SDL_sensor_c.h" +#include "camera/SDL_camera_c.h" #define SDL_INIT_EVERYTHING ~0U @@ -365,6 +366,30 @@ int SDL_InitSubSystem(Uint32 flags) #endif } + /* Initialize the camera subsystem */ + if (flags & SDL_INIT_CAMERA) { +#ifndef SDL_CAMERA_DISABLED + if (SDL_ShouldInitSubsystem(SDL_INIT_CAMERA)) { + /* camera implies events */ + if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { + goto quit_and_error; + } + + SDL_IncrementSubsystemRefCount(SDL_INIT_CAMERA); + if (SDL_CameraInit(NULL) < 0) { + SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA); + goto quit_and_error; + } + } else { + SDL_IncrementSubsystemRefCount(SDL_INIT_CAMERA); + } + flags_initialized |= SDL_INIT_CAMERA; +#else + SDL_SetError("SDL not built with camera support"); + goto quit_and_error; +#endif + } + (void)flags_initialized; /* make static analysis happy, since this only gets used in error cases. */ return 0; @@ -382,6 +407,18 @@ int SDL_Init(Uint32 flags) void SDL_QuitSubSystem(Uint32 flags) { /* Shut down requested initialized subsystems */ + +#ifndef SDL_CAMERA_DISABLED + if (flags & SDL_INIT_CAMERA) { + if (SDL_ShouldQuitSubsystem(SDL_INIT_CAMERA)) { + SDL_QuitCamera(); + /* camera implies events */ + SDL_QuitSubSystem(SDL_INIT_EVENTS); + } + SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA); + } +#endif + #ifndef SDL_SENSOR_DISABLED if (flags & SDL_INIT_SENSOR) { if (SDL_ShouldQuitSubsystem(SDL_INIT_SENSOR)) { diff --git a/src/camera/SDL_camera.c b/src/camera/SDL_camera.c index d62854c9c..5a8c08f8c 100644 --- a/src/camera/SDL_camera.c +++ b/src/camera/SDL_camera.c @@ -25,7 +25,25 @@ #include "../video/SDL_pixels_c.h" #include "../thread/SDL_systhread.h" -#define DEBUG_CAMERA 1 +// Available camera drivers +static const CameraBootStrap *const bootstrap[] = { +#ifdef SDL_CAMERA_DRIVER_V4L2 + &V4L2_bootstrap, +#endif +#ifdef SDL_CAMERA_DRIVER_COREMEDIA + &COREMEDIA_bootstrap, +#endif +#ifdef SDL_CAMERA_DRIVER_ANDROID + &ANDROIDCAMERA_bootstrap, +#endif +#ifdef SDL_CAMERA_DRIVER_DUMMY + &DUMMYCAMERA_bootstrap, +#endif + NULL +}; + +static SDL_CameraDriver camera_driver; + // list node entries to share frames between SDL and user app // !!! FIXME: do we need this struct? @@ -36,6 +54,25 @@ typedef struct entry_t static SDL_CameraDevice *open_devices[16]; // !!! FIXME: remove limit +int SDL_GetNumCameraDrivers(void) +{ + return SDL_arraysize(bootstrap) - 1; +} + +const char *SDL_GetCameraDriver(int index) +{ + if (index >= 0 && index < SDL_GetNumCameraDrivers()) { + return bootstrap[index]->name; + } + return NULL; +} + +const char *SDL_GetCurrentCameraDriver(void) +{ + return camera_driver.name; +} + + static void CloseCameraDevice(SDL_CameraDevice *device) { if (!device) { @@ -69,46 +106,18 @@ static void CloseCameraDevice(SDL_CameraDevice *device) SDL_CameraFrame f = entry->frame; // Release frames not acquired, if any if (f.timestampNS) { - ReleaseFrame(device, &f); + camera_driver.impl.ReleaseFrame(device, &f); } SDL_free(entry); } } - CloseDevice(device); + camera_driver.impl.CloseDevice(device); SDL_free(device->dev_name); SDL_free(device); } -// Tell if all devices are closed -SDL_bool CheckAllDeviceClosed(void) -{ - const int n = SDL_arraysize(open_devices); - int all_closed = SDL_TRUE; - for (int i = 0; i < n; i++) { - if (open_devices[i]) { - all_closed = SDL_FALSE; - break; - } - } - return all_closed; -} - -// Tell if at least one device is in playing state -SDL_bool CheckDevicePlaying(void) -{ - const int n = SDL_arraysize(open_devices); - for (int i = 0; i < n; i++) { - if (open_devices[i]) { - if (SDL_GetCameraStatus(open_devices[i]) == SDL_CAMERA_PLAYING) { - return SDL_TRUE; - } - } - } - return SDL_FALSE; -} - void SDL_CloseCamera(SDL_CameraDevice *device) { if (!device) { @@ -128,7 +137,7 @@ int SDL_StartCamera(SDL_CameraDevice *device) return SDL_SetError("invalid state"); } - const int result = StartCamera(device); + const int result = camera_driver.impl.StartCamera(device); if (result < 0) { return result; } @@ -147,7 +156,7 @@ int SDL_GetCameraSpec(SDL_CameraDevice *device, SDL_CameraSpec *spec) } SDL_zerop(spec); - return GetDeviceSpec(device, spec); + return camera_driver.impl.GetDeviceSpec(device, spec); } int SDL_StopCamera(SDL_CameraDevice *device) @@ -162,7 +171,7 @@ int SDL_StopCamera(SDL_CameraDevice *device) SDL_AtomicSet(&device->shutdown, 1); SDL_LockMutex(device->acquiring_lock); - const int retval = StopCamera(device); + const int retval = camera_driver.impl.StopCamera(device); SDL_UnlockMutex(device->acquiring_lock); return (retval < 0) ? -1 : 0; @@ -254,14 +263,13 @@ const char *SDL_GetCameraDeviceName(SDL_CameraDeviceID instance_id) return NULL; } - if (GetCameraDeviceName(instance_id, buf, sizeof (buf)) < 0) { + if (camera_driver.impl.GetDeviceName(instance_id, buf, sizeof (buf)) < 0) { buf[0] = 0; } return buf; } - SDL_CameraDeviceID *SDL_GetCameraDevices(int *count) { int dummycount = 0; @@ -270,7 +278,7 @@ SDL_CameraDeviceID *SDL_GetCameraDevices(int *count) } int num = 0; - SDL_CameraDeviceID *retval = GetCameraDevices(&num); + SDL_CameraDeviceID *retval = camera_driver.impl.GetDevices(&num); if (retval) { *count = num; return retval; @@ -279,7 +287,6 @@ SDL_CameraDeviceID *SDL_GetCameraDevices(int *count) // return list of 0 ID, null terminated retval = (SDL_CameraDeviceID *)SDL_calloc(1, sizeof(*retval)); if (retval == NULL) { - SDL_OutOfMemory(); *count = 0; return NULL; } @@ -331,7 +338,7 @@ static int SDLCALL SDL_CameraThread(void *devicep) SDL_zero(f); SDL_LockMutex(device->acquiring_lock); - ret = AcquireFrame(device, &f); + ret = camera_driver.impl.AcquireFrame(device, &f); SDL_UnlockMutex(device->acquiring_lock); if (ret == 0) { @@ -376,7 +383,6 @@ error_mem: SDL_Log("dev[%p] End thread 'SDL_CameraThread' with error: %s", (void *)device, SDL_GetError()); #endif SDL_AtomicSet(&device->shutdown, 1); - SDL_OutOfMemory(); // !!! FIXME: this error isn't accessible since the thread is about to terminate return 0; } @@ -436,7 +442,6 @@ SDL_CameraDevice *SDL_OpenCamera(SDL_CameraDeviceID instance_id) device = (SDL_CameraDevice *) SDL_calloc(1, sizeof (SDL_CameraDevice)); if (device == NULL) { - SDL_OutOfMemory(); goto error; } device->dev_name = SDL_strdup(device_name); @@ -456,7 +461,7 @@ SDL_CameraDevice *SDL_OpenCamera(SDL_CameraDeviceID instance_id) goto error; } - if (OpenDevice(device) < 0) { + if (camera_driver.impl.OpenDevice(device) < 0) { goto error; } @@ -515,7 +520,7 @@ int SDL_SetCameraSpec(SDL_CameraDevice *device, const SDL_CameraSpec *desired, S device->spec = *obtained; - result = InitDevice(device); + result = camera_driver.impl.InitDevice(device); if (result < 0) { return result; } @@ -541,7 +546,7 @@ int SDL_AcquireCameraFrame(SDL_CameraDevice *device, SDL_CameraFrame *frame) int ret; // Wait for a frame - while ((ret = AcquireFrame(device, frame)) == 0) { + while ((ret = camera_driver.impl.AcquireFrame(device, frame)) == 0) { if (frame->num_planes) { return 0; } @@ -576,7 +581,7 @@ int SDL_ReleaseCameraFrame(SDL_CameraDevice *device, SDL_CameraFrame *frame) return SDL_InvalidParamError("device"); } else if (frame == NULL) { return SDL_InvalidParamError("frame"); - } else if (ReleaseFrame(device, frame) < 0) { + } else if (camera_driver.impl.ReleaseFrame(device, frame) < 0) { return -1; } @@ -589,7 +594,7 @@ int SDL_GetNumCameraFormats(SDL_CameraDevice *device) if (!device) { return SDL_InvalidParamError("device"); } - return GetNumFormats(device); + return camera_driver.impl.GetNumFormats(device); } int SDL_GetCameraFormat(SDL_CameraDevice *device, int index, Uint32 *format) @@ -600,7 +605,7 @@ int SDL_GetCameraFormat(SDL_CameraDevice *device, int index, Uint32 *format) return SDL_InvalidParamError("format"); } *format = 0; - return GetFormat(device, index, format); + return camera_driver.impl.GetFormat(device, index, format); } int SDL_GetNumCameraFrameSizes(SDL_CameraDevice *device, Uint32 format) @@ -608,7 +613,7 @@ int SDL_GetNumCameraFrameSizes(SDL_CameraDevice *device, Uint32 format) if (!device) { return SDL_InvalidParamError("device"); } - return GetNumFrameSizes(device, format); + return camera_driver.impl.GetNumFrameSizes(device, format); } int SDL_GetCameraFrameSize(SDL_CameraDevice *device, Uint32 format, int index, int *width, int *height) @@ -621,7 +626,7 @@ int SDL_GetCameraFrameSize(SDL_CameraDevice *device, Uint32 format, int index, i return SDL_InvalidParamError("height"); } *width = *height = 0; - return GetFrameSize(device, format, index, width, height); + return camera_driver.impl.GetFrameSize(device, format, index, width, height); } SDL_CameraDevice *SDL_OpenCameraWithSpec(SDL_CameraDeviceID instance_id, const SDL_CameraSpec *desired, SDL_CameraSpec *obtained, int allowed_changes) @@ -653,15 +658,35 @@ SDL_CameraStatus SDL_GetCameraStatus(SDL_CameraDevice *device) return SDL_CAMERA_INIT; } -int SDL_CameraInit(void) +static void CompleteCameraEntryPoints(void) { - SDL_zeroa(open_devices); - SDL_SYS_CameraInit(); - return 0; + // this doesn't currently fill in stub implementations, it just asserts the backend filled them all in. + #define FILL_STUB(x) SDL_assert(camera_driver.impl.x != NULL) + FILL_STUB(DetectDevices); + FILL_STUB(OpenDevice); + FILL_STUB(CloseDevice); + FILL_STUB(InitDevice); + FILL_STUB(GetDeviceSpec); + FILL_STUB(StartCamera); + FILL_STUB(StopCamera); + FILL_STUB(AcquireFrame); + FILL_STUB(ReleaseFrame); + FILL_STUB(GetNumFormats); + FILL_STUB(GetFormat); + FILL_STUB(GetNumFrameSizes); + FILL_STUB(GetFrameSize); + FILL_STUB(GetDeviceName); + FILL_STUB(GetDevices); + FILL_STUB(Deinitialize); + #undef FILL_STUB } void SDL_QuitCamera(void) { + if (!camera_driver.name) { // not initialized?! + return; + } + const int n = SDL_arraysize(open_devices); for (int i = 0; i < n; i++) { CloseCameraDevice(open_devices[i]); @@ -669,6 +694,112 @@ void SDL_QuitCamera(void) SDL_zeroa(open_devices); - SDL_SYS_CameraQuit(); +#if 0 // !!! FIXME + SDL_PendingCameraDeviceEvent *pending_events = camera_driver.pending_events.next; + camera_driver.pending_events.next = NULL; + + SDL_PendingCameraDeviceEvent *pending_next = NULL; + for (SDL_PendingCameraDeviceEvent *i = pending_events; i; i = pending_next) { + pending_next = i->next; + SDL_free(i); + } +#endif + + // Free the driver data + camera_driver.impl.Deinitialize(); + + SDL_zero(camera_driver); +} + +// this is 90% the same code as the audio subsystem uses. +int SDL_CameraInit(const char *driver_name) +{ + if (SDL_GetCurrentCameraDriver()) { + SDL_QuitCamera(); // shutdown driver if already running. + } + + SDL_zeroa(open_devices); + + // Select the proper camera driver + if (!driver_name) { + driver_name = SDL_GetHint(SDL_HINT_CAMERA_DRIVER); + } + + SDL_bool initialized = SDL_FALSE; + SDL_bool tried_to_init = SDL_FALSE; + + if (driver_name && (*driver_name != 0)) { + char *driver_name_copy = SDL_strdup(driver_name); + const char *driver_attempt = driver_name_copy; + + if (!driver_name_copy) { + return -1; + } + + while (driver_attempt && (*driver_attempt != 0) && !initialized) { + char *driver_attempt_end = SDL_strchr(driver_attempt, ','); + if (driver_attempt_end) { + *driver_attempt_end = '\0'; + } + + for (int i = 0; bootstrap[i]; i++) { + if (SDL_strcasecmp(bootstrap[i]->name, driver_attempt) == 0) { + tried_to_init = SDL_TRUE; + SDL_zero(camera_driver); + #if 0 // !!! FIXME + camera_driver.pending_events_tail = &camera_driver.pending_events; + #endif + if (bootstrap[i]->init(&camera_driver.impl)) { + camera_driver.name = bootstrap[i]->name; + camera_driver.desc = bootstrap[i]->desc; + initialized = SDL_TRUE; + } + break; + } + } + + driver_attempt = (driver_attempt_end) ? (driver_attempt_end + 1) : NULL; + } + + SDL_free(driver_name_copy); + } else { + for (int i = 0; !initialized && bootstrap[i]; i++) { + if (bootstrap[i]->demand_only) { + continue; + } + + tried_to_init = SDL_TRUE; + SDL_zero(camera_driver); + #if 0 // !!! FIXME + camera_driver.pending_events_tail = &camera_driver.pending_events; + #endif + if (bootstrap[i]->init(&camera_driver.impl)) { + camera_driver.name = bootstrap[i]->name; + camera_driver.desc = bootstrap[i]->desc; + initialized = SDL_TRUE; + } + } + } + + if (!initialized) { + // specific drivers will set the error message if they fail, but otherwise we do it here. + if (!tried_to_init) { + if (driver_name) { + SDL_SetError("Camera driver '%s' not available", driver_name); + } else { + SDL_SetError("No available camera driver"); + } + } + + SDL_zero(camera_driver); + return -1; // No driver was available, so fail. + } + + CompleteCameraEntryPoints(); + + // Make sure we have a list of devices available at startup... + camera_driver.impl.DetectDevices(); + + return 0; } diff --git a/src/camera/SDL_camera_c.h b/src/camera/SDL_camera_c.h index 787b5f2db..56921ab8a 100644 --- a/src/camera/SDL_camera_c.h +++ b/src/camera/SDL_camera_c.h @@ -24,7 +24,7 @@ #define SDL_camera_c_h_ // Initialize the camera subsystem -int SDL_CameraInit(void); +int SDL_CameraInit(const char *driver_name); // Shutdown the camera subsystem void SDL_QuitCamera(void); diff --git a/src/camera/SDL_syscamera.h b/src/camera/SDL_syscamera.h index 990272f8d..6a7c56356 100644 --- a/src/camera/SDL_syscamera.h +++ b/src/camera/SDL_syscamera.h @@ -25,6 +25,8 @@ #include "../SDL_list.h" +#define DEBUG_CAMERA 1 + // The SDL camera driver typedef struct SDL_CameraDevice SDL_CameraDevice; @@ -57,34 +59,45 @@ struct SDL_CameraDevice struct SDL_PrivateCameraData *hidden; }; -extern int SDL_SYS_CameraInit(void); -extern int SDL_SYS_CameraQuit(void); +typedef struct SDL_CameraDriverImpl +{ + void (*DetectDevices)(void); + int (*OpenDevice)(SDL_CameraDevice *_this); + void (*CloseDevice)(SDL_CameraDevice *_this); + int (*InitDevice)(SDL_CameraDevice *_this); + int (*GetDeviceSpec)(SDL_CameraDevice *_this, SDL_CameraSpec *spec); + int (*StartCamera)(SDL_CameraDevice *_this); + int (*StopCamera)(SDL_CameraDevice *_this); + int (*AcquireFrame)(SDL_CameraDevice *_this, SDL_CameraFrame *frame); + int (*ReleaseFrame)(SDL_CameraDevice *_this, SDL_CameraFrame *frame); + int (*GetNumFormats)(SDL_CameraDevice *_this); + int (*GetFormat)(SDL_CameraDevice *_this, int index, Uint32 *format); + int (*GetNumFrameSizes)(SDL_CameraDevice *_this, Uint32 format); + int (*GetFrameSize)(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int *height); + int (*GetDeviceName)(SDL_CameraDeviceID instance_id, char *buf, int size); + SDL_CameraDeviceID *(*GetDevices)(int *count); + void (*Deinitialize)(void); +} SDL_CameraDriverImpl; -// !!! FIXME: These names need to be made camera-specific. +typedef struct SDL_CameraDriver +{ + const char *name; // The name of this camera driver + const char *desc; // The description of this camera driver + SDL_CameraDriverImpl impl; // the backend's interface +} SDL_CameraDriver; -extern int OpenDevice(SDL_CameraDevice *_this); -extern void CloseDevice(SDL_CameraDevice *_this); +typedef struct CameraBootStrap +{ + const char *name; + const char *desc; + SDL_bool (*init)(SDL_CameraDriverImpl *impl); + SDL_bool demand_only; // if SDL_TRUE: request explicitly, or it won't be available. +} CameraBootStrap; -extern int InitDevice(SDL_CameraDevice *_this); - -extern int GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec); - -extern int StartCamera(SDL_CameraDevice *_this); -extern int StopCamera(SDL_CameraDevice *_this); - -extern int AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame); -extern int ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame); - -extern int GetNumFormats(SDL_CameraDevice *_this); -extern int GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format); - -extern int GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format); -extern int GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int *height); - -extern int GetCameraDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size); -extern SDL_CameraDeviceID *GetCameraDevices(int *count); - -extern SDL_bool CheckAllDeviceClosed(void); -extern SDL_bool CheckDevicePlaying(void); +// Not all of these are available in a given build. Use #ifdefs, etc. +extern CameraBootStrap DUMMYCAMERA_bootstrap; +extern CameraBootStrap V4L2_bootstrap; +extern CameraBootStrap COREMEDIA_bootstrap; +extern CameraBootStrap ANDROIDCAMERA_bootstrap; #endif // SDL_syscamera_h_ diff --git a/src/camera/android/SDL_camera_android.c b/src/camera/android/SDL_camera_android.c index 51d2446b6..20aeb06f1 100644 --- a/src/camera/android/SDL_camera_android.c +++ b/src/camera/android/SDL_camera_android.c @@ -25,9 +25,9 @@ #include "../../video/SDL_pixels_c.h" #include "../../thread/SDL_systhread.h" -#define DEBUG_CAMERA 1 +#if defined(SDL_CAMERA_DRIVER_ANDROID) -#if defined(SDL_CAMERA_ANDROID) && __ANDROID_API__ >= 24 +#if __ANDROID_API__ >= 24 /* * APP_PLATFORM=android-24 @@ -62,7 +62,7 @@ static ACameraManager *cameraMgr = NULL; static ACameraIdList *cameraIdList = NULL; -static void create_cameraMgr(void) +static int CreateCameraManager(void) { if (cameraMgr == NULL) { #if 0 // !!! FIXME: this is getting replaced in a different branch. @@ -78,9 +78,13 @@ static void create_cameraMgr(void) SDL_Log("Create ACameraManager"); } } + + cameraMgr = ACameraManager_create(); + + return cameraMgr ? 0 : SDL_SetError("Error creating ACameraManager"); } -static void delete_cameraMgr(void) +static void DestroyCameraManager(void) { if (cameraIdList) { ACameraManager_deleteCameraIdList(cameraIdList); @@ -215,7 +219,7 @@ static void onActive(void* context, ACameraCaptureSession *session) #endif } -int OpenDevice(SDL_CameraDevice *_this) +static int ANDROIDCAMERA_OpenDevice(SDL_CameraDevice *_this) { /* Cannot open a second camera, while the first one is opened. * If you want to play several camera, they must all be opened first, then played. @@ -231,10 +235,10 @@ int OpenDevice(SDL_CameraDevice *_this) _this->hidden = (struct SDL_PrivateCameraData *) SDL_calloc(1, sizeof (struct SDL_PrivateCameraData)); if (_this->hidden == NULL) { - return SDL_OutOfMemory(); + return -1; } - create_cameraMgr(); + CreateCameraManager(); _this->hidden->dev_callbacks.context = (void *) _this; _this->hidden->dev_callbacks.onDisconnected = onDisconnected; @@ -248,7 +252,7 @@ int OpenDevice(SDL_CameraDevice *_this) return 0; } -void CloseDevice(SDL_CameraDevice *_this) +static void ANDROIDCAMERA_CloseDevice(SDL_CameraDevice *_this) { if (_this && _this->hidden) { if (_this->hidden->session) { @@ -271,14 +275,9 @@ void CloseDevice(SDL_CameraDevice *_this) _this->hidden = NULL; } - - // !!! FIXME: just refcount this? - if (CheckAllDeviceClosed()) { - delete_cameraMgr(); - } } -int InitDevice(SDL_CameraDevice *_this) +static int ANDROIDCAMERA_InitDevice(SDL_CameraDevice *_this) { size_t size, pitch; SDL_CalculateSize(_this->spec.format, _this->spec.width, _this->spec.height, &size, &pitch, SDL_FALSE); @@ -286,7 +285,7 @@ int InitDevice(SDL_CameraDevice *_this) return 0; } -int GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec) +static int ANDROIDCAMERA_GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec) { // !!! FIXME: catch NULLs at higher level if (spec) { @@ -296,7 +295,7 @@ int GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec) return -1; } -int StartCamera(SDL_CameraDevice *_this) +static int ANDROIDCAMERA_StartCamera(SDL_CameraDevice *_this) { // !!! FIXME: maybe log the error code in SDL_SetError camera_status_t res; @@ -377,14 +376,14 @@ error: return -1; } -int StopCamera(SDL_CameraDevice *_this) +static int ANDROIDCAMERA_StopCamera(SDL_CameraDevice *_this) { ACameraCaptureSession_close(_this->hidden->session); _this->hidden->session = NULL; return 0; } -int AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) +static int ANDROIDCAMERA_AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) { media_status_t res; AImage *image; @@ -435,7 +434,7 @@ int AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) return 0; } -int ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) +static int ANDROIDCAMERA_ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) { if (frame->internal){ AImage_delete((AImage *)frame->internal); @@ -443,7 +442,7 @@ int ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) return 0; } -int GetNumFormats(SDL_CameraDevice *_this) +static int ANDROIDCAMERA_GetNumFormats(SDL_CameraDevice *_this) { camera_status_t res; SDL_bool unknown = SDL_FALSE; @@ -505,7 +504,7 @@ int GetNumFormats(SDL_CameraDevice *_this) return _this->hidden->num_formats; } -int GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) +static int ANDROIDCAMERA_GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) { int i2 = 0; @@ -533,7 +532,7 @@ int GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) return 0; } -int GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) +static int ANDROIDCAMERA_GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) { // !!! FIXME: call SDL_SetError()? if (_this->hidden->num_formats == 0) { @@ -559,7 +558,7 @@ int GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) return -1; } -int GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int *height) +static int ANDROIDCAMERA_GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int *height) { // !!! FIXME: call SDL_SetError()? camera_status_t res; @@ -608,10 +607,10 @@ int GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, return -1; } -static int GetNumDevices(void) +static int ANDROIDCAMERA_GetNumDevices(void) { camera_status_t res; - create_cameraMgr(); + CreateCameraManager(); if (cameraIdList) { ACameraManager_deleteCameraIdList(cameraIdList); @@ -628,11 +627,11 @@ static int GetNumDevices(void) return -1; } -int GetCameraDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size) +static int ANDROIDCAMERA_GetDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size) { // !!! FIXME: call SDL_SetError()? int index = instance_id - 1; - create_cameraMgr(); + CreateCameraManager(); if (cameraIdList == NULL) { GetNumDevices(); @@ -648,14 +647,13 @@ int GetCameraDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size) return -1; } -SDL_CameraDeviceID *GetCameraDevices(int *count) +static SDL_CameraDeviceID *ANDROIDCAMERA_GetDevices(int *count) { // hard-coded list of ID const int num = GetNumDevices(); SDL_CameraDeviceID *retval = (SDL_CameraDeviceID *)SDL_malloc((num + 1) * sizeof(*ret)); if (retval == NULL) { - SDL_OutOfMemory(); *count = 0; return NULL; } @@ -668,15 +666,47 @@ SDL_CameraDeviceID *GetCameraDevices(int *count) return retval; } -int SDL_SYS_CameraInit(void) +static void ANDROIDCAMERA_Deinitialize(void) { - return 0; + DestroyCameraManager(); } -int SDL_SYS_CameraQuit(void) +#endif // __ANDROID_API__ >= 24 + + +static SDL_bool ANDROIDCAMERA_Init(SDL_CameraDriverImpl *impl) { - return 0; +#if __ANDROID_API__ < 24 + return SDL_FALSE; +#else + if (CreateCameraManager() < 0) { + return SDL_FALSE; + } + + impl->DetectDevices = ANDROIDCAMERA_DetectDevices; + impl->OpenDevice = ANDROIDCAMERA_OpenDevice; + impl->CloseDevice = ANDROIDCAMERA_CloseDevice; + impl->InitDevice = ANDROIDCAMERA_InitDevice; + impl->GetDeviceSpec = ANDROIDCAMERA_GetDeviceSpec; + impl->StartCamera = ANDROIDCAMERA_StartCamera; + impl->StopCamera = ANDROIDCAMERA_StopCamera; + impl->AcquireFrame = ANDROIDCAMERA_AcquireFrame; + impl->ReleaseFrame = ANDROIDCAMERA_ReleaseFrame; + impl->GetNumFormats = ANDROIDCAMERA_GetNumFormats; + impl->GetFormat = ANDROIDCAMERA_GetFormat; + impl->GetNumFrameSizes = ANDROIDCAMERA_GetNumFrameSizes; + impl->GetFrameSize = ANDROIDCAMERA_GetFrameSize; + impl->GetDeviceName = ANDROIDCAMERA_GetDeviceName; + impl->GetDevices = ANDROIDCAMERA_GetDevices; + impl->Deinitialize = ANDROIDCAMERA_Deinitialize; + + return SDL_TRUE; +#endif } +CameraBootStrap ANDROIDCAMERA_bootstrap = { + "android", "SDL Android camera driver", ANDROIDCAMERA_Init, SDL_FALSE +}; + #endif diff --git a/src/camera/apple/SDL_camera_apple.m b/src/camera/coremedia/SDL_camera_coremedia.m similarity index 87% rename from src/camera/apple/SDL_camera_apple.m rename to src/camera/coremedia/SDL_camera_coremedia.m index ae44fe69c..f5ade8ca0 100644 --- a/src/camera/apple/SDL_camera_apple.m +++ b/src/camera/coremedia/SDL_camera_coremedia.m @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#ifdef SDL_CAMERA_APPLE +#ifdef SDL_CAMERA_DRIVER_COREMEDIA #include "../SDL_syscamera.h" #include "../SDL_camera_c.h" @@ -35,59 +35,7 @@ #undef HAVE_COREMEDIA #endif -// !!! FIXME: use the dummy driver -// !!! FIXME: actually, move everything over to backend callbacks instead. -#ifndef HAVE_COREMEDIA -int InitDevice(SDL_CameraDevice *_this) { - return -1; -} -int OpenDevice(SDL_CameraDevice *_this) { - return -1; -} -int AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) { - return -1; -} -void CloseDevice(SDL_CameraDevice *_this) { -} -int GetCameraDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size) { - return -1; -} -int GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec) { - return -1; -} -int GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) { - return -1; -} -int GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int *height) { - return -1; -} -SDL_CameraDeviceID *GetCameraDevices(int *count) { - return NULL; -} -int GetNumFormats(SDL_CameraDevice *_this) { - return 0; -} -int GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) { - return 0; -} -int ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) { - return 0; -} -int StartCapture(SDL_CameraDevice *_this) { - return 0; -} -int StopCapture(SDL_CameraDevice *_this) { - return 0; -} -int SDL_SYS_CameraInit(void) { - return 0; -} -int SDL_SYS_CameraQuit(void) { - return 0; -} - - -#else +#ifdef HAVE_COREMEDIA #import #import @@ -234,16 +182,16 @@ static NSString *sdlformat_to_nsfourcc(Uint32 fmt) } @end -int OpenDevice(SDL_CameraDevice *_this) +static int COREMEDIA_OpenDevice(SDL_CameraDevice *_this) { _this->hidden = (struct SDL_PrivateCameraData *) SDL_calloc(1, sizeof (struct SDL_PrivateCameraData)); if (_this->hidden == NULL) { - return SDL_OutOfMemory(); + return -1; } return 0; } -void CloseDevice(SDL_CameraDevice *_this) +static void COREMEDIA_CloseDevice(SDL_CameraDevice *_this) { if (!_this) { return; @@ -271,7 +219,7 @@ void CloseDevice(SDL_CameraDevice *_this) } } -int InitDevice(SDL_CameraDevice *_this) +static int COREMEDIA_InitDevice(SDL_CameraDevice *_this) { // !!! FIXME: autorelease pool? NSString *fmt = sdlformat_to_nsfourcc(_this->spec.format); @@ -381,7 +329,7 @@ int InitDevice(SDL_CameraDevice *_this) return 0; } -int GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec) +static int COREMEDIA_GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec) { // !!! FIXME: make sure higher level checks spec != NULL if (spec) { @@ -391,19 +339,19 @@ int GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec) return -1; } -int StartCamera(SDL_CameraDevice *_this) +static int COREMEDIA_StartCamera(SDL_CameraDevice *_this) { [_this->hidden->session startRunning]; return 0; } -int StopCamera(SDL_CameraDevice *_this) +static int COREMEDIA_StopCamera(SDL_CameraDevice *_this) { [_this->hidden->session stopRunning]; return 0; } -int AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) +static int COREMEDIA_AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) { if (CMSimpleQueueGetCount(_this->hidden->frame_queue) > 0) { CMSampleBufferRef sampleBuffer = (CMSampleBufferRef)CMSimpleQueueDequeue(_this->hidden->frame_queue); @@ -444,7 +392,7 @@ int AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) return 0; } -int ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) +static int COREMEDIA_ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) { if (frame->internal) { CMSampleBufferRef sampleBuffer = (CMSampleBufferRef) frame->internal; @@ -456,7 +404,7 @@ int ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) return 0; } -int GetNumFormats(SDL_CameraDevice *_this) +static int COREMEDIA_GetNumFormats(SDL_CameraDevice *_this) { AVCaptureDevice *device = GetCameraDeviceByName(_this->dev_name); if (device) { @@ -476,7 +424,7 @@ int GetNumFormats(SDL_CameraDevice *_this) return 0; } -int GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) +static int COREMEDIA_GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) { AVCaptureDevice *device = GetCameraDeviceByName(_this->dev_name); if (device) { @@ -503,7 +451,7 @@ int GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) return -1; } -int GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) +static int COREMEDIA_GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) { AVCaptureDevice *device = GetCameraDeviceByName(_this->dev_name); if (device) { @@ -525,8 +473,7 @@ int GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) return 0; } -int -GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int *height) +static int COREMEDIA_GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int *height) { AVCaptureDevice *device = GetCameraDeviceByName(_this->dev_name); if (device) { @@ -553,7 +500,7 @@ GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int return -1; } -int GetCameraDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size) +static int COREMEDIA_GetDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size) { int index = instance_id - 1; NSArray *devices = DiscoverCameraDevices(); @@ -567,20 +514,19 @@ int GetCameraDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size) return -1; } -static int GetNumDevices(void) +static int GetNumCameraDevices(void) { NSArray *devices = DiscoverCameraDevices(); return [devices count]; } -SDL_CameraDeviceID *GetCameraDevices(int *count) +static SDL_CameraDeviceID *COREMEDIA_GetDevices(int *count) { // hard-coded list of ID - const int num = GetNumDevices(); + const int num = GetNumCameraDevices(); SDL_CameraDeviceID *retval = (SDL_CameraDeviceID *)SDL_calloc((num + 1), sizeof(*ret)); if (retval == NULL) { - SDL_OutOfMemory(); *count = 0; return NULL; } @@ -593,17 +539,45 @@ SDL_CameraDeviceID *GetCameraDevices(int *count) return ret; } -int SDL_SYS_CameraInit(void) +static void COREMEDIA_DetectDevices(void) { - return 0; } -int SDL_SYS_CameraQuit(void) +static void COREMEDIA_Deinitialize(void) { - return 0; } +static SDL_bool COREMEDIA_Init(SDL_CameraDriverImpl *impl) +{ +#ifndef HAVE_COREMEDIA + return SDL_FALSE; +#else + impl->DetectDevices = COREMEDIA_DetectDevices; + impl->OpenDevice = COREMEDIA_OpenDevice; + impl->CloseDevice = COREMEDIA_CloseDevice; + impl->InitDevice = COREMEDIA_InitDevice; + impl->GetDeviceSpec = COREMEDIA_GetDeviceSpec; + impl->StartCamera = COREMEDIA_StartCamera; + impl->StopCamera = COREMEDIA_StopCamera; + impl->AcquireFrame = COREMEDIA_AcquireFrame; + impl->ReleaseFrame = COREMEDIA_ReleaseFrame; + impl->GetNumFormats = COREMEDIA_GetNumFormats; + impl->GetFormat = COREMEDIA_GetFormat; + impl->GetNumFrameSizes = COREMEDIA_GetNumFrameSizes; + impl->GetFrameSize = COREMEDIA_GetFrameSize; + impl->GetDeviceName = COREMEDIA_GetDeviceName; + impl->GetDevices = COREMEDIA_GetDevices; + impl->Deinitialize = COREMEDIA_Deinitialize; + + return SDL_TRUE; +#endif +} + +CameraBootStrap COREMEDIA_bootstrap = { + "coremedia", "SDL Apple CoreMedia camera driver", COREMEDIA_Init, SDL_FALSE +}; + #endif // HAVE_COREMEDIA -#endif // SDL_CAMERA_APPLE +#endif // SDL_CAMERA_COREMEDIA diff --git a/src/camera/v4l2/SDL_camera_v4l2.c b/src/camera/v4l2/SDL_camera_v4l2.c index 223d8a053..f4f484666 100644 --- a/src/camera/v4l2/SDL_camera_v4l2.c +++ b/src/camera/v4l2/SDL_camera_v4l2.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#ifdef SDL_CAMERA_V4L2 +#ifdef SDL_CAMERA_DRIVER_V4L2 #include "../SDL_syscamera.h" #include "../SDL_camera_c.h" @@ -30,8 +30,6 @@ #include "../../core/linux/SDL_udev.h" #include // INT_MAX -#define DEBUG_CAMERA 1 - #define MAX_CAMERA_DEVICES 128 // It's doubtful someone has more than that static int MaybeAddDevice(const char *path); @@ -206,7 +204,7 @@ static int acquire_frame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) } -int ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) +static int V4L2_ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) { struct v4l2_buffer buf; const int fd = _this->hidden->fd; @@ -259,8 +257,7 @@ int ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) return 0; } - -int AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) +static int V4L2_AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) { fd_set fds; struct timeval tv; @@ -310,7 +307,7 @@ int AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) } -int StopCamera(SDL_CameraDevice *_this) +static int V4L2_StopCamera(SDL_CameraDevice *_this) { enum v4l2_buf_type type; const int fd = _this->hidden->fd; @@ -428,7 +425,7 @@ static int PreEnqueueBuffers(SDL_CameraDevice *_this) return 0; } -int StartCamera(SDL_CameraDevice *_this) +static int V4L2_StartCamera(SDL_CameraDevice *_this) { enum v4l2_buf_type type; @@ -476,15 +473,10 @@ static int AllocBufferRead(SDL_CameraDevice *_this, size_t buffer_size) { _this->hidden->buffers[0].length = buffer_size; _this->hidden->buffers[0].start = SDL_calloc(1, buffer_size); - - if (!_this->hidden->buffers[0].start) { - return SDL_OutOfMemory(); - } - return 0; + return _this->hidden->buffers[0].start ? 0 : -1; } -static int -AllocBufferMmap(SDL_CameraDevice *_this) +static int AllocBufferMmap(SDL_CameraDevice *_this) { int fd = _this->hidden->fd; int i; @@ -516,8 +508,7 @@ AllocBufferMmap(SDL_CameraDevice *_this) return 0; } -static int -AllocBufferUserPtr(SDL_CameraDevice *_this, size_t buffer_size) +static int AllocBufferUserPtr(SDL_CameraDevice *_this, size_t buffer_size) { int i; for (i = 0; i < _this->hidden->nb_buffers; ++i) { @@ -525,41 +516,38 @@ AllocBufferUserPtr(SDL_CameraDevice *_this, size_t buffer_size) _this->hidden->buffers[i].start = SDL_calloc(1, buffer_size); if (!_this->hidden->buffers[i].start) { - return SDL_OutOfMemory(); + return -1; } } return 0; } -static Uint32 -format_v4l2_2_sdl(Uint32 fmt) +static Uint32 format_v4l2_to_sdl(Uint32 fmt) { switch (fmt) { -#define CASE(x, y) case x: return y + #define CASE(x, y) case x: return y CASE(V4L2_PIX_FMT_YUYV, SDL_PIXELFORMAT_YUY2); CASE(V4L2_PIX_FMT_MJPEG, SDL_PIXELFORMAT_UNKNOWN); -#undef CASE + #undef CASE default: SDL_Log("Unknown format V4L2_PIX_FORMAT '%d'", fmt); return SDL_PIXELFORMAT_UNKNOWN; } } -static Uint32 -format_sdl_2_v4l2(Uint32 fmt) +static Uint32 format_sdl_to_v4l2(Uint32 fmt) { switch (fmt) { -#define CASE(y, x) case x: return y + #define CASE(y, x) case x: return y CASE(V4L2_PIX_FMT_YUYV, SDL_PIXELFORMAT_YUY2); CASE(V4L2_PIX_FMT_MJPEG, SDL_PIXELFORMAT_UNKNOWN); -#undef CASE + #undef CASE default: return 0; } } -int -GetNumFormats(SDL_CameraDevice *_this) +static int V4L2_GetNumFormats(SDL_CameraDevice *_this) { int fd = _this->hidden->fd; int i = 0; @@ -574,8 +562,7 @@ GetNumFormats(SDL_CameraDevice *_this) return i; } -int -GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) +static int V4L2_GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) { int fd = _this->hidden->fd; struct v4l2_fmtdesc fmtdesc; @@ -584,7 +571,7 @@ GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) fmtdesc.index = index; fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc) == 0) { - *format = format_v4l2_2_sdl(fmtdesc.pixelformat); + *format = format_v4l2_to_sdl(fmtdesc.pixelformat); #if DEBUG_CAMERA if (fmtdesc.flags & V4L2_FMT_FLAG_EMULATED) { @@ -600,8 +587,7 @@ GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) return -1; } -int -GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) +static int V4L2_GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) { int fd = _this->hidden->fd; int i = 0; @@ -609,7 +595,7 @@ GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) SDL_zero(frmsizeenum); frmsizeenum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - frmsizeenum.pixel_format = format_sdl_2_v4l2(format); + frmsizeenum.pixel_format = format_sdl_to_v4l2(format); while (ioctl(fd,VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) == 0) { frmsizeenum.index++; if (frmsizeenum.type == V4L2_FRMSIZE_TYPE_DISCRETE) { @@ -624,8 +610,7 @@ GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) return i; } -int -GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int *height) +static int V4L2_GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int *height) { int fd = _this->hidden->fd; struct v4l2_frmsizeenum frmsizeenum; @@ -633,7 +618,7 @@ GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int SDL_zero(frmsizeenum); frmsizeenum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - frmsizeenum.pixel_format = format_sdl_2_v4l2(format); + frmsizeenum.pixel_format = format_sdl_to_v4l2(format); while (ioctl(fd,VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) == 0) { frmsizeenum.index++; @@ -663,12 +648,8 @@ GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int return -1; } - - - -#if DEBUG_VIDEO_CAPTURE_CAPTURE -static void -dbg_v4l2_pixelformat(const char *str, int f) { +static void dbg_v4l2_pixelformat(const char *str, int f) +{ SDL_Log("%s V4L2_format=%d %c%c%c%c", str, f, (f >> 0) & 0xff, (f >> 8) & 0xff, @@ -677,8 +658,7 @@ dbg_v4l2_pixelformat(const char *str, int f) { } #endif -int -GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec) +static int V4L2_GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec) { struct v4l2_format fmt; int fd = _this->hidden->fd; @@ -705,13 +685,12 @@ GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec) //spec->width = fmt.fmt.pix.width; //spec->height = fmt.fmt.pix.height; _this->hidden->driver_pitch = fmt.fmt.pix.bytesperline; - //spec->format = format_v4l2_2_sdl(fmt.fmt.pix.pixelformat); + //spec->format = format_v4l2_to_sdl(fmt.fmt.pix.pixelformat); return 0; } -int -InitDevice(SDL_CameraDevice *_this) +static int V4L2_InitDevice(SDL_CameraDevice *_this) { struct v4l2_cropcap cropcap; struct v4l2_crop crop; @@ -753,7 +732,7 @@ InitDevice(SDL_CameraDevice *_this) fmt.fmt.pix.height = _this->spec.height; - fmt.fmt.pix.pixelformat = format_sdl_2_v4l2(_this->spec.format); + fmt.fmt.pix.pixelformat = format_sdl_to_v4l2(_this->spec.format); // fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; fmt.fmt.pix.field = V4L2_FIELD_ANY; @@ -767,7 +746,7 @@ InitDevice(SDL_CameraDevice *_this) } } - GetDeviceSpec(_this, &_this->spec); + V4L2_GetDeviceSpec(_this, &_this->spec); if (PreEnqueueBuffers(_this) < 0) { return -1; @@ -776,7 +755,7 @@ InitDevice(SDL_CameraDevice *_this) { _this->hidden->buffers = SDL_calloc(_this->hidden->nb_buffers, sizeof(*_this->hidden->buffers)); if (!_this->hidden->buffers) { - return SDL_OutOfMemory(); + return -1; } } @@ -802,7 +781,7 @@ InitDevice(SDL_CameraDevice *_this) return (retval < 0) ? -1 : 0; } -void CloseDevice(SDL_CameraDevice *_this) +static void V4L2_CloseDevice(SDL_CameraDevice *_this) { if (!_this) { return; @@ -846,8 +825,7 @@ void CloseDevice(SDL_CameraDevice *_this) } } - -int OpenDevice(SDL_CameraDevice *_this) +static int V4L2_OpenDevice(SDL_CameraDevice *_this) { struct stat st; struct v4l2_capability cap; @@ -856,7 +834,6 @@ int OpenDevice(SDL_CameraDevice *_this) _this->hidden = (struct SDL_PrivateCameraData *) SDL_calloc(1, sizeof (struct SDL_PrivateCameraData)); if (_this->hidden == NULL) { - SDL_OutOfMemory(); return -1; } @@ -921,7 +898,7 @@ int OpenDevice(SDL_CameraDevice *_this) return 0; } -int GetCameraDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size) +static int V4L2_GetDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size) { SDL_cameralist_item *item; for (item = SDL_cameralist; item; item = item->next) { @@ -935,15 +912,13 @@ int GetCameraDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size) return -1; } - -SDL_CameraDeviceID *GetCameraDevices(int *count) +static SDL_CameraDeviceID *V4L2_GetDevices(int *count) { // real list of ID const int num = num_cameras; SDL_CameraDeviceID *retval = (SDL_CameraDeviceID *)SDL_malloc((num + 1) * sizeof(*retval)); if (retval == NULL) { - SDL_OutOfMemory(); *count = 0; return NULL; } @@ -959,55 +934,6 @@ SDL_CameraDeviceID *GetCameraDevices(int *count) } -// Initializes the subsystem by finding available devices. -int SDL_SYS_CameraInit(void) -{ - const char pattern[] = "/dev/video%d"; - char path[PATH_MAX]; - - /* - * Limit amount of checks to MAX_CAMERA_DEVICES since we may or may not have - * permission to some or all devices. - */ - for (int i = 0; i < MAX_CAMERA_DEVICES; i++) { - (void)SDL_snprintf(path, PATH_MAX, pattern, i); - if (MaybeAddDevice(path) == -2) { - break; - } - } - -#ifdef SDL_USE_LIBUDEV - if (SDL_UDEV_Init() < 0) { - return SDL_SetError("Could not initialize UDEV"); - } else if (SDL_UDEV_AddCallback(CameraUdevCallback) < 0) { - SDL_UDEV_Quit(); - return SDL_SetError("Could not setup Video Capture <-> udev callback"); - } - - // Force a scan to build the initial device list - SDL_UDEV_Scan(); -#endif // SDL_USE_LIBUDEV - - return num_cameras; -} - -int SDL_SYS_CameraQuit(void) -{ - for (SDL_cameralist_item *item = SDL_cameralist; item; ) { - SDL_cameralist_item *tmp = item->next; - SDL_free(item->fname); - SDL_free(item->bus_info); - SDL_free(item); - item = tmp; - } - - num_cameras = 0; - SDL_cameralist = NULL; - SDL_cameralist_tail = NULL; - - return SDL_FALSE; -} - #ifdef SDL_USE_LIBUDEV static void CameraUdevCallback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath) { @@ -1150,5 +1076,78 @@ static int MaybeRemoveDevice(const char *path) } #endif // SDL_USE_LIBUDEV + +static void V4L2_Deinitialize(void) +{ + for (SDL_cameralist_item *item = SDL_cameralist; item; ) { + SDL_cameralist_item *tmp = item->next; + SDL_free(item->fname); + SDL_free(item->bus_info); + SDL_free(item); + item = tmp; + } + + num_cameras = 0; + SDL_cameralist = NULL; + SDL_cameralist_tail = NULL; +} + +static void V4L2_DetectDevices(void) +{ +} + +static SDL_bool V4L2_Init(SDL_CameraDriverImpl *impl) +{ + // !!! FIXME: move to DetectDevices + const char pattern[] = "/dev/video%d"; + char path[PATH_MAX]; + + /* + * Limit amount of checks to MAX_CAMERA_DEVICES since we may or may not have + * permission to some or all devices. + */ + for (int i = 0; i < MAX_CAMERA_DEVICES; i++) { + (void)SDL_snprintf(path, PATH_MAX, pattern, i); + if (MaybeAddDevice(path) == -2) { + break; + } + } + +#ifdef SDL_USE_LIBUDEV + if (SDL_UDEV_Init() < 0) { + return SDL_SetError("Could not initialize UDEV"); + } else if (SDL_UDEV_AddCallback(CameraUdevCallback) < 0) { + SDL_UDEV_Quit(); + return SDL_SetError("Could not setup Video Capture <-> udev callback"); + } + + // Force a scan to build the initial device list + SDL_UDEV_Scan(); +#endif // SDL_USE_LIBUDEV + + impl->DetectDevices = V4L2_DetectDevices; + impl->OpenDevice = V4L2_OpenDevice; + impl->CloseDevice = V4L2_CloseDevice; + impl->InitDevice = V4L2_InitDevice; + impl->GetDeviceSpec = V4L2_GetDeviceSpec; + impl->StartCamera = V4L2_StartCamera; + impl->StopCamera = V4L2_StopCamera; + impl->AcquireFrame = V4L2_AcquireFrame; + impl->ReleaseFrame = V4L2_ReleaseFrame; + impl->GetNumFormats = V4L2_GetNumFormats; + impl->GetFormat = V4L2_GetFormat; + impl->GetNumFrameSizes = V4L2_GetNumFrameSizes; + impl->GetFrameSize = V4L2_GetFrameSize; + impl->GetDeviceName = V4L2_GetDeviceName; + impl->GetDevices = V4L2_GetDevices; + impl->Deinitialize = V4L2_Deinitialize; + + return SDL_TRUE; +} + +CameraBootStrap V4L2_bootstrap = { + "v4l2", "SDL Video4Linux2 camera driver", V4L2_Init, SDL_FALSE +}; + #endif // SDL_CAMERA_V4L2 diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index beb7e40f8..cedc7556b 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -458,7 +458,6 @@ int SDL_VideoInit(const char *driver_name) SDL_bool init_keyboard = SDL_FALSE; SDL_bool init_mouse = SDL_FALSE; SDL_bool init_touch = SDL_FALSE; - SDL_bool init_camera = SDL_FALSE; int i = 0; /* Check to make sure we don't overwrite '_this' */ @@ -485,10 +484,6 @@ int SDL_VideoInit(const char *driver_name) goto pre_driver_error; } init_touch = SDL_TRUE; - if (SDL_CameraInit() < 0) { - goto pre_driver_error; - } - init_camera = SDL_TRUE; /* Select the proper video driver */ video = NULL; @@ -590,9 +585,6 @@ int SDL_VideoInit(const char *driver_name) pre_driver_error: SDL_assert(_this == NULL); - if (init_camera) { - SDL_QuitCamera(); - } if (init_touch) { SDL_QuitTouch(); } @@ -3784,7 +3776,6 @@ void SDL_VideoQuit(void) SDL_ClearClipboardData(); /* Halt event processing before doing anything else */ - SDL_QuitCamera(); SDL_QuitTouch(); SDL_QuitMouse(); SDL_QuitKeyboard(); diff --git a/test/testcamera.c b/test/testcamera.c index 255dcf4ea..f96b72866 100644 --- a/test/testcamera.c +++ b/test/testcamera.c @@ -213,7 +213,7 @@ int main(int argc, char **argv) SDL_Log("%s", usage); /* Load the SDL library */ - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { /* FIXME: SDL_INIT_JOYSTICK needed for add/removing devices at runtime */ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_CAMERA) < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError()); return 1; } diff --git a/test/testcameraminimal.c b/test/testcameraminimal.c index 060b8ed50..ce2d3ec20 100644 --- a/test/testcameraminimal.c +++ b/test/testcameraminimal.c @@ -54,7 +54,7 @@ int main(int argc, char **argv) SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); /* Load the SDL library */ - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { /* FIXME: SDL_INIT_JOYSTICK needed for add/removing devices at runtime */ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_CAMERA) < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError()); return 1; }