mirror of
				https://github.com/libsdl-org/SDL.git
				synced 2025-10-26 12:27:44 +00:00 
			
		
		
		
	camera: Reworked to operate with a driver interface, like other subsystems.
This commit is contained in:
		| @@ -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) | dep_option(SDL_KMSDRM_SHARED       "Dynamically load KMS DRM support" ON "SDL_KMSDRM" OFF) | ||||||
| set_option(SDL_OFFSCREEN           "Use offscreen video driver" ON) | set_option(SDL_OFFSCREEN           "Use offscreen video driver" ON) | ||||||
| dep_option(SDL_CAMERA              "Enable camera support" ON SDL_VIDEO OFF) | 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_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) | 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) | dep_option(SDL_HIDAPI              "Enable the HIDAPI subsystem" ON "NOT VISIONOS" OFF) | ||||||
| @@ -1172,6 +1173,23 @@ if(SDL_AUDIO) | |||||||
|   endif() |   endif() | ||||||
| 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) | if(UNIX OR APPLE) | ||||||
|   # Relevant for Unix/Darwin only |   # Relevant for Unix/Darwin only | ||||||
|   set(DYNAPI_NEEDS_DLOPEN 1) |   set(DYNAPI_NEEDS_DLOPEN 1) | ||||||
| @@ -1290,7 +1308,7 @@ if(ANDROID) | |||||||
|   endif() |   endif() | ||||||
|  |  | ||||||
|   if(SDL_CAMERA) |   if(SDL_CAMERA) | ||||||
|     set(SDL_CAMERA_ANDROID 1) |     set(SDL_CAMERA_DRIVER_ANDROID 1) | ||||||
|     set(HAVE_CAMERA TRUE) |     set(HAVE_CAMERA TRUE) | ||||||
|     sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/android/*.c") |     sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/android/*.c") | ||||||
|   endif() |   endif() | ||||||
| @@ -1531,7 +1549,7 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) | |||||||
|     endif() |     endif() | ||||||
|  |  | ||||||
|     if(SDL_CAMERA AND HAVE_LINUX_VIDEODEV2_H) |     if(SDL_CAMERA AND HAVE_LINUX_VIDEODEV2_H) | ||||||
|       set(SDL_CAMERA_V4L2 1) |       set(SDL_CAMERA_DRIVER_V4L2 1) | ||||||
|       set(HAVE_CAMERA TRUE) |       set(HAVE_CAMERA TRUE) | ||||||
|       sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/v4l2/*.c") |       sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/v4l2/*.c") | ||||||
|     endif() |     endif() | ||||||
| @@ -2035,9 +2053,9 @@ elseif(APPLE) | |||||||
|   sdl_glob_sources("${SDL3_SOURCE_DIR}/src/file/cocoa/*.m") |   sdl_glob_sources("${SDL3_SOURCE_DIR}/src/file/cocoa/*.m") | ||||||
|  |  | ||||||
|   if(IOS OR TVOS OR MACOSX OR DARWIN) |   if(IOS OR TVOS OR MACOSX OR DARWIN) | ||||||
|     set(SDL_CAMERA_APPLE TRUE) |     set(SDL_CAMERA_DRIVER_COREMEDIA 1) | ||||||
|     set(HAVE_CAMERA TRUE) |     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() |   endif() | ||||||
|  |  | ||||||
|   if(IOS OR TVOS OR VISIONOS) |   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") |   sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/dummy/*.c") | ||||||
| endif() | endif() | ||||||
| if(NOT HAVE_CAMERA) | 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") |   sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/dummy/*.c") | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|   | |||||||
| @@ -108,6 +108,71 @@ typedef struct SDL_CameraFrame | |||||||
| } 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. |  * Get a list of currently connected camera devices. | ||||||
|  * |  * | ||||||
|   | |||||||
| @@ -355,6 +355,22 @@ extern "C" { | |||||||
|  */ |  */ | ||||||
| #define SDL_HINT_BMP_SAVE_LEGACY_FORMAT "SDL_BMP_SAVE_LEGACY_FORMAT" | #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 |  * A variable controlling whether DirectInput should be used for controllers | ||||||
|  * |  * | ||||||
| @@ -2478,7 +2494,6 @@ extern "C" { | |||||||
|  */ |  */ | ||||||
| #define SDL_HINT_XINPUT_ENABLED "SDL_XINPUT_ENABLED" | #define SDL_HINT_XINPUT_ENABLED "SDL_XINPUT_ENABLED" | ||||||
|  |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  *  An enumeration of hint priorities |  *  An enumeration of hint priorities | ||||||
|  */ |  */ | ||||||
|   | |||||||
| @@ -59,7 +59,8 @@ typedef enum | |||||||
|     SDL_INIT_HAPTIC       = 0x00001000, |     SDL_INIT_HAPTIC       = 0x00001000, | ||||||
|     SDL_INIT_GAMEPAD      = 0x00002000,  /**< `SDL_INIT_GAMEPAD` implies `SDL_INIT_JOYSTICK` */ |     SDL_INIT_GAMEPAD      = 0x00002000,  /**< `SDL_INIT_GAMEPAD` implies `SDL_INIT_JOYSTICK` */ | ||||||
|     SDL_INIT_EVENTS       = 0x00004000, |     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; | } SDL_InitFlags; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|   | |||||||
| @@ -467,10 +467,11 @@ | |||||||
| #cmakedefine SDL_FILESYSTEM_N3DS @SDL_FILESYSTEM_N3DS@ | #cmakedefine SDL_FILESYSTEM_N3DS @SDL_FILESYSTEM_N3DS@ | ||||||
|  |  | ||||||
| /* Enable camera subsystem */ | /* Enable camera subsystem */ | ||||||
| #cmakedefine SDL_CAMERA_DUMMY @SDL_CAMERA_DUMMY@ | #cmakedefine SDL_CAMERA_DRIVER_DUMMY @SDL_CAMERA_DRIVER_DUMMY@ | ||||||
| #cmakedefine SDL_CAMERA_V4L2 @SDL_CAMERA_V4L2@ | /* !!! FIXME: for later cmakedefine SDL_CAMERA_DRIVER_DISK @SDL_CAMERA_DRIVER_DISK@ */ | ||||||
| #cmakedefine SDL_CAMERA_APPLE @SDL_CAMERA_APPLE@ | #cmakedefine SDL_CAMERA_DRIVER_V4L2 @SDL_CAMERA_DRIVER_V4L2@ | ||||||
| #cmakedefine SDL_CAMERA_ANDROID @SDL_CAMERA_ANDROID@ | #cmakedefine SDL_CAMERA_DRIVER_COREMEDIA @SDL_CAMERA_DRIVER_COREMEDIA@ | ||||||
|  | #cmakedefine SDL_CAMERA_DRIVER_ANDROID @SDL_CAMERA_DRIVER_ANDROID@ | ||||||
|  |  | ||||||
| /* Enable misc subsystem */ | /* Enable misc subsystem */ | ||||||
| #cmakedefine SDL_MISC_DUMMY @SDL_MISC_DUMMY@ | #cmakedefine SDL_MISC_DUMMY @SDL_MISC_DUMMY@ | ||||||
|   | |||||||
| @@ -191,6 +191,6 @@ | |||||||
| #define SDL_FILESYSTEM_ANDROID   1 | #define SDL_FILESYSTEM_ANDROID   1 | ||||||
|  |  | ||||||
| /* Enable the camera driver */ | /* Enable the camera driver */ | ||||||
| #define SDL_CAMERA_ANDROID 1 | #define SDL_CAMERA_DRIVER_ANDROID 1 | ||||||
|  |  | ||||||
| #endif /* SDL_build_config_android_h_ */ | #endif /* SDL_build_config_android_h_ */ | ||||||
|   | |||||||
| @@ -210,6 +210,6 @@ | |||||||
| #define SDL_FILESYSTEM_EMSCRIPTEN 1 | #define SDL_FILESYSTEM_EMSCRIPTEN 1 | ||||||
|  |  | ||||||
| /* Enable the camera driver (src/camera/dummy/\*.c) */  /* !!! FIXME */ | /* 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 */ | #endif /* SDL_build_config_emscripten_h */ | ||||||
|   | |||||||
| @@ -213,6 +213,6 @@ | |||||||
| #define SDL_FILESYSTEM_COCOA   1 | #define SDL_FILESYSTEM_COCOA   1 | ||||||
|  |  | ||||||
| /* enable camera support */ | /* enable camera support */ | ||||||
| #define SDL_CAMERA_APPLE 1 | #define SDL_CAMERA_DRIVER_COREMEDIA 1 | ||||||
|  |  | ||||||
| #endif /* SDL_build_config_ios_h_ */ | #endif /* SDL_build_config_ios_h_ */ | ||||||
|   | |||||||
| @@ -270,7 +270,8 @@ | |||||||
| #define SDL_FILESYSTEM_COCOA   1 | #define SDL_FILESYSTEM_COCOA   1 | ||||||
|  |  | ||||||
| /* enable camera support */ | /* enable camera support */ | ||||||
| #define SDL_CAMERA_APPLE 1 | #define SDL_CAMERA_DRIVER_COREMEDIA 1 | ||||||
|  | #define SDL_CAMERA_DRIVER_DUMMY 1 | ||||||
|  |  | ||||||
| /* Enable assembly routines */ | /* Enable assembly routines */ | ||||||
| #ifdef __ppc__ | #ifdef __ppc__ | ||||||
|   | |||||||
| @@ -90,6 +90,6 @@ typedef unsigned int uintptr_t; | |||||||
| #define SDL_FILESYSTEM_DUMMY  1 | #define SDL_FILESYSTEM_DUMMY  1 | ||||||
|  |  | ||||||
| /* Enable the camera driver (src/camera/dummy/\*.c) */ | /* 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_ */ | #endif /* SDL_build_config_minimal_h_ */ | ||||||
|   | |||||||
| @@ -87,6 +87,6 @@ typedef unsigned long      uintptr_t; | |||||||
| #define SDL_FILESYSTEM_DUMMY 1 | #define SDL_FILESYSTEM_DUMMY 1 | ||||||
|  |  | ||||||
| /* Enable the camera driver (src/camera/dummy/\*.c) */ | /* 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_ */ | #endif /* SDL_build_config_ngage_h_ */ | ||||||
|   | |||||||
| @@ -312,6 +312,6 @@ typedef unsigned int uintptr_t; | |||||||
| #define SDL_FILESYSTEM_WINDOWS  1 | #define SDL_FILESYSTEM_WINDOWS  1 | ||||||
|  |  | ||||||
| /* Enable the camera driver (src/camera/dummy/\*.c) */  /* !!! FIXME */ | /* 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_ */ | #endif /* SDL_build_config_windows_h_ */ | ||||||
|   | |||||||
| @@ -248,7 +248,7 @@ | |||||||
| #define SDL_FILESYSTEM_WINDOWS  1 | #define SDL_FILESYSTEM_WINDOWS  1 | ||||||
|  |  | ||||||
| /* Enable the camera driver (src/camera/dummy/\*.c) */  /* !!! FIXME */ | /* 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 */ | /* Use the (inferior) GDK text input method for GDK platforms */ | ||||||
| /*#define SDL_GDK_TEXTINPUT 1*/ | /*#define SDL_GDK_TEXTINPUT 1*/ | ||||||
|   | |||||||
| @@ -216,6 +216,6 @@ | |||||||
| #define SDL_POWER_WINRT 1 | #define SDL_POWER_WINRT 1 | ||||||
|  |  | ||||||
| /* Enable the camera driver (src/camera/dummy/\*.c) */  /* !!! FIXME */ | /* 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_ */ | #endif /* SDL_build_config_winrt_h_ */ | ||||||
|   | |||||||
| @@ -237,6 +237,6 @@ | |||||||
| #define SDL_GDK_TEXTINPUT 1 | #define SDL_GDK_TEXTINPUT 1 | ||||||
|  |  | ||||||
| /* Enable the camera driver (src/camera/dummy/\*.c) */ | /* 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_ */ | #endif /* SDL_build_config_wingdk_h_ */ | ||||||
|   | |||||||
							
								
								
									
										37
									
								
								src/SDL.c
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								src/SDL.c
									
									
									
									
									
								
							| @@ -46,6 +46,7 @@ | |||||||
| #include "joystick/SDL_gamepad_c.h" | #include "joystick/SDL_gamepad_c.h" | ||||||
| #include "joystick/SDL_joystick_c.h" | #include "joystick/SDL_joystick_c.h" | ||||||
| #include "sensor/SDL_sensor_c.h" | #include "sensor/SDL_sensor_c.h" | ||||||
|  | #include "camera/SDL_camera_c.h" | ||||||
|  |  | ||||||
| #define SDL_INIT_EVERYTHING ~0U | #define SDL_INIT_EVERYTHING ~0U | ||||||
|  |  | ||||||
| @@ -365,6 +366,30 @@ int SDL_InitSubSystem(Uint32 flags) | |||||||
| #endif | #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. */ |     (void)flags_initialized; /* make static analysis happy, since this only gets used in error cases. */ | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| @@ -382,6 +407,18 @@ int SDL_Init(Uint32 flags) | |||||||
| void SDL_QuitSubSystem(Uint32 flags) | void SDL_QuitSubSystem(Uint32 flags) | ||||||
| { | { | ||||||
|     /* Shut down requested initialized subsystems */ |     /* 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 | #ifndef SDL_SENSOR_DISABLED | ||||||
|     if (flags & SDL_INIT_SENSOR) { |     if (flags & SDL_INIT_SENSOR) { | ||||||
|         if (SDL_ShouldQuitSubsystem(SDL_INIT_SENSOR)) { |         if (SDL_ShouldQuitSubsystem(SDL_INIT_SENSOR)) { | ||||||
|   | |||||||
| @@ -25,7 +25,25 @@ | |||||||
| #include "../video/SDL_pixels_c.h" | #include "../video/SDL_pixels_c.h" | ||||||
| #include "../thread/SDL_systhread.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 | // list node entries to share frames between SDL and user app | ||||||
| // !!! FIXME: do we need this struct? | // !!! FIXME: do we need this struct? | ||||||
| @@ -36,6 +54,25 @@ typedef struct entry_t | |||||||
|  |  | ||||||
| static SDL_CameraDevice *open_devices[16];  // !!! FIXME: remove limit | 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) | static void CloseCameraDevice(SDL_CameraDevice *device) | ||||||
| { | { | ||||||
|     if (!device) { |     if (!device) { | ||||||
| @@ -69,46 +106,18 @@ static void CloseCameraDevice(SDL_CameraDevice *device) | |||||||
|             SDL_CameraFrame f = entry->frame; |             SDL_CameraFrame f = entry->frame; | ||||||
|             // Release frames not acquired, if any |             // Release frames not acquired, if any | ||||||
|             if (f.timestampNS) { |             if (f.timestampNS) { | ||||||
|                 ReleaseFrame(device, &f); |                 camera_driver.impl.ReleaseFrame(device, &f); | ||||||
|             } |             } | ||||||
|             SDL_free(entry); |             SDL_free(entry); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     CloseDevice(device); |     camera_driver.impl.CloseDevice(device); | ||||||
|  |  | ||||||
|     SDL_free(device->dev_name); |     SDL_free(device->dev_name); | ||||||
|     SDL_free(device); |     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) | void SDL_CloseCamera(SDL_CameraDevice *device) | ||||||
| { | { | ||||||
|     if (!device) { |     if (!device) { | ||||||
| @@ -128,7 +137,7 @@ int SDL_StartCamera(SDL_CameraDevice *device) | |||||||
|         return SDL_SetError("invalid state"); |         return SDL_SetError("invalid state"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const int result = StartCamera(device); |     const int result = camera_driver.impl.StartCamera(device); | ||||||
|     if (result < 0) { |     if (result < 0) { | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
| @@ -147,7 +156,7 @@ int SDL_GetCameraSpec(SDL_CameraDevice *device, SDL_CameraSpec *spec) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     SDL_zerop(spec); |     SDL_zerop(spec); | ||||||
|     return GetDeviceSpec(device, spec); |     return camera_driver.impl.GetDeviceSpec(device, spec); | ||||||
| } | } | ||||||
|  |  | ||||||
| int SDL_StopCamera(SDL_CameraDevice *device) | int SDL_StopCamera(SDL_CameraDevice *device) | ||||||
| @@ -162,7 +171,7 @@ int SDL_StopCamera(SDL_CameraDevice *device) | |||||||
|     SDL_AtomicSet(&device->shutdown, 1); |     SDL_AtomicSet(&device->shutdown, 1); | ||||||
|  |  | ||||||
|     SDL_LockMutex(device->acquiring_lock); |     SDL_LockMutex(device->acquiring_lock); | ||||||
|     const int retval = StopCamera(device); |     const int retval = camera_driver.impl.StopCamera(device); | ||||||
|     SDL_UnlockMutex(device->acquiring_lock); |     SDL_UnlockMutex(device->acquiring_lock); | ||||||
|  |  | ||||||
|     return (retval < 0) ? -1 : 0; |     return (retval < 0) ? -1 : 0; | ||||||
| @@ -254,14 +263,13 @@ const char *SDL_GetCameraDeviceName(SDL_CameraDeviceID instance_id) | |||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (GetCameraDeviceName(instance_id, buf, sizeof (buf)) < 0) { |     if (camera_driver.impl.GetDeviceName(instance_id, buf, sizeof (buf)) < 0) { | ||||||
|         buf[0] = 0; |         buf[0] = 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return buf; |     return buf; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| SDL_CameraDeviceID *SDL_GetCameraDevices(int *count) | SDL_CameraDeviceID *SDL_GetCameraDevices(int *count) | ||||||
| { | { | ||||||
|     int dummycount = 0; |     int dummycount = 0; | ||||||
| @@ -270,7 +278,7 @@ SDL_CameraDeviceID *SDL_GetCameraDevices(int *count) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     int num = 0; |     int num = 0; | ||||||
|     SDL_CameraDeviceID *retval = GetCameraDevices(&num); |     SDL_CameraDeviceID *retval = camera_driver.impl.GetDevices(&num); | ||||||
|     if (retval) { |     if (retval) { | ||||||
|         *count = num; |         *count = num; | ||||||
|         return retval; |         return retval; | ||||||
| @@ -279,7 +287,6 @@ SDL_CameraDeviceID *SDL_GetCameraDevices(int *count) | |||||||
|     // return list of 0 ID, null terminated |     // return list of 0 ID, null terminated | ||||||
|     retval = (SDL_CameraDeviceID *)SDL_calloc(1, sizeof(*retval)); |     retval = (SDL_CameraDeviceID *)SDL_calloc(1, sizeof(*retval)); | ||||||
|     if (retval == NULL) { |     if (retval == NULL) { | ||||||
|         SDL_OutOfMemory(); |  | ||||||
|         *count = 0; |         *count = 0; | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
| @@ -331,7 +338,7 @@ static int SDLCALL SDL_CameraThread(void *devicep) | |||||||
|         SDL_zero(f); |         SDL_zero(f); | ||||||
|  |  | ||||||
|         SDL_LockMutex(device->acquiring_lock); |         SDL_LockMutex(device->acquiring_lock); | ||||||
|         ret = AcquireFrame(device, &f); |         ret = camera_driver.impl.AcquireFrame(device, &f); | ||||||
|         SDL_UnlockMutex(device->acquiring_lock); |         SDL_UnlockMutex(device->acquiring_lock); | ||||||
|  |  | ||||||
|         if (ret == 0) { |         if (ret == 0) { | ||||||
| @@ -376,7 +383,6 @@ error_mem: | |||||||
|     SDL_Log("dev[%p] End thread 'SDL_CameraThread' with error: %s", (void *)device, SDL_GetError()); |     SDL_Log("dev[%p] End thread 'SDL_CameraThread' with error: %s", (void *)device, SDL_GetError()); | ||||||
| #endif | #endif | ||||||
|     SDL_AtomicSet(&device->shutdown, 1); |     SDL_AtomicSet(&device->shutdown, 1); | ||||||
|     SDL_OutOfMemory();  // !!! FIXME: this error isn't accessible since the thread is about to terminate |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -436,7 +442,6 @@ SDL_CameraDevice *SDL_OpenCamera(SDL_CameraDeviceID instance_id) | |||||||
|  |  | ||||||
|     device = (SDL_CameraDevice *) SDL_calloc(1, sizeof (SDL_CameraDevice)); |     device = (SDL_CameraDevice *) SDL_calloc(1, sizeof (SDL_CameraDevice)); | ||||||
|     if (device == NULL) { |     if (device == NULL) { | ||||||
|         SDL_OutOfMemory(); |  | ||||||
|         goto error; |         goto error; | ||||||
|     } |     } | ||||||
|     device->dev_name = SDL_strdup(device_name); |     device->dev_name = SDL_strdup(device_name); | ||||||
| @@ -456,7 +461,7 @@ SDL_CameraDevice *SDL_OpenCamera(SDL_CameraDeviceID instance_id) | |||||||
|         goto error; |         goto error; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (OpenDevice(device) < 0) { |     if (camera_driver.impl.OpenDevice(device) < 0) { | ||||||
|         goto error; |         goto error; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -515,7 +520,7 @@ int SDL_SetCameraSpec(SDL_CameraDevice *device, const SDL_CameraSpec *desired, S | |||||||
|  |  | ||||||
|     device->spec = *obtained; |     device->spec = *obtained; | ||||||
|  |  | ||||||
|     result = InitDevice(device); |     result = camera_driver.impl.InitDevice(device); | ||||||
|     if (result < 0) { |     if (result < 0) { | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
| @@ -541,7 +546,7 @@ int SDL_AcquireCameraFrame(SDL_CameraDevice *device, SDL_CameraFrame *frame) | |||||||
|         int ret; |         int ret; | ||||||
|  |  | ||||||
|         // Wait for a frame |         // Wait for a frame | ||||||
|         while ((ret = AcquireFrame(device, frame)) == 0) { |         while ((ret = camera_driver.impl.AcquireFrame(device, frame)) == 0) { | ||||||
|             if (frame->num_planes) { |             if (frame->num_planes) { | ||||||
|                 return 0; |                 return 0; | ||||||
|             } |             } | ||||||
| @@ -576,7 +581,7 @@ int SDL_ReleaseCameraFrame(SDL_CameraDevice *device, SDL_CameraFrame *frame) | |||||||
|         return SDL_InvalidParamError("device"); |         return SDL_InvalidParamError("device"); | ||||||
|     } else if (frame == NULL) { |     } else if (frame == NULL) { | ||||||
|         return SDL_InvalidParamError("frame"); |         return SDL_InvalidParamError("frame"); | ||||||
|     } else if (ReleaseFrame(device, frame) < 0) { |     } else if (camera_driver.impl.ReleaseFrame(device, frame) < 0) { | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -589,7 +594,7 @@ int SDL_GetNumCameraFormats(SDL_CameraDevice *device) | |||||||
|     if (!device) { |     if (!device) { | ||||||
|         return SDL_InvalidParamError("device"); |         return SDL_InvalidParamError("device"); | ||||||
|     } |     } | ||||||
|     return GetNumFormats(device); |     return camera_driver.impl.GetNumFormats(device); | ||||||
| } | } | ||||||
|  |  | ||||||
| int SDL_GetCameraFormat(SDL_CameraDevice *device, int index, Uint32 *format) | 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"); |         return SDL_InvalidParamError("format"); | ||||||
|     } |     } | ||||||
|     *format = 0; |     *format = 0; | ||||||
|     return GetFormat(device, index, format); |     return camera_driver.impl.GetFormat(device, index, format); | ||||||
| } | } | ||||||
|  |  | ||||||
| int SDL_GetNumCameraFrameSizes(SDL_CameraDevice *device, Uint32 format) | int SDL_GetNumCameraFrameSizes(SDL_CameraDevice *device, Uint32 format) | ||||||
| @@ -608,7 +613,7 @@ int SDL_GetNumCameraFrameSizes(SDL_CameraDevice *device, Uint32 format) | |||||||
|     if (!device) { |     if (!device) { | ||||||
|         return SDL_InvalidParamError("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) | 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"); |         return SDL_InvalidParamError("height"); | ||||||
|     } |     } | ||||||
|     *width = *height = 0; |     *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) | 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; |     return SDL_CAMERA_INIT; | ||||||
| } | } | ||||||
|  |  | ||||||
| int SDL_CameraInit(void) | static void CompleteCameraEntryPoints(void) | ||||||
| { | { | ||||||
|     SDL_zeroa(open_devices); |     // this doesn't currently fill in stub implementations, it just asserts the backend filled them all in. | ||||||
|     SDL_SYS_CameraInit(); |     #define FILL_STUB(x) SDL_assert(camera_driver.impl.x != NULL) | ||||||
|     return 0; |     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) | void SDL_QuitCamera(void) | ||||||
| { | { | ||||||
|  |     if (!camera_driver.name) {  // not initialized?! | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     const int n = SDL_arraysize(open_devices); |     const int n = SDL_arraysize(open_devices); | ||||||
|     for (int i = 0; i < n; i++) { |     for (int i = 0; i < n; i++) { | ||||||
|         CloseCameraDevice(open_devices[i]); |         CloseCameraDevice(open_devices[i]); | ||||||
| @@ -669,6 +694,112 @@ void SDL_QuitCamera(void) | |||||||
|  |  | ||||||
|     SDL_zeroa(open_devices); |     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; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ | |||||||
| #define SDL_camera_c_h_ | #define SDL_camera_c_h_ | ||||||
|  |  | ||||||
| // Initialize the camera subsystem | // Initialize the camera subsystem | ||||||
| int SDL_CameraInit(void); | int SDL_CameraInit(const char *driver_name); | ||||||
|  |  | ||||||
| // Shutdown the camera subsystem | // Shutdown the camera subsystem | ||||||
| void SDL_QuitCamera(void); | void SDL_QuitCamera(void); | ||||||
|   | |||||||
| @@ -25,6 +25,8 @@ | |||||||
|  |  | ||||||
| #include "../SDL_list.h" | #include "../SDL_list.h" | ||||||
|  |  | ||||||
|  | #define DEBUG_CAMERA 1 | ||||||
|  |  | ||||||
| // The SDL camera driver | // The SDL camera driver | ||||||
| typedef struct SDL_CameraDevice SDL_CameraDevice; | typedef struct SDL_CameraDevice SDL_CameraDevice; | ||||||
|  |  | ||||||
| @@ -57,34 +59,45 @@ struct SDL_CameraDevice | |||||||
|     struct SDL_PrivateCameraData *hidden; |     struct SDL_PrivateCameraData *hidden; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| extern int SDL_SYS_CameraInit(void); | typedef struct SDL_CameraDriverImpl | ||||||
| extern int SDL_SYS_CameraQuit(void); | { | ||||||
|  |     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); | typedef struct CameraBootStrap | ||||||
| extern void CloseDevice(SDL_CameraDevice *_this); | { | ||||||
|  |     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); | // Not all of these are available in a given build. Use #ifdefs, etc. | ||||||
|  | extern CameraBootStrap DUMMYCAMERA_bootstrap; | ||||||
| extern int GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec); | extern CameraBootStrap V4L2_bootstrap; | ||||||
|  | extern CameraBootStrap COREMEDIA_bootstrap; | ||||||
| extern int StartCamera(SDL_CameraDevice *_this); | extern CameraBootStrap ANDROIDCAMERA_bootstrap; | ||||||
| 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); |  | ||||||
|  |  | ||||||
| #endif // SDL_syscamera_h_ | #endif // SDL_syscamera_h_ | ||||||
|   | |||||||
| @@ -25,9 +25,9 @@ | |||||||
| #include "../../video/SDL_pixels_c.h" | #include "../../video/SDL_pixels_c.h" | ||||||
| #include "../../thread/SDL_systhread.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 |  * APP_PLATFORM=android-24 | ||||||
| @@ -62,7 +62,7 @@ | |||||||
| static ACameraManager *cameraMgr = NULL; | static ACameraManager *cameraMgr = NULL; | ||||||
| static ACameraIdList *cameraIdList = NULL; | static ACameraIdList *cameraIdList = NULL; | ||||||
|  |  | ||||||
| static void create_cameraMgr(void) | static int CreateCameraManager(void) | ||||||
| { | { | ||||||
|     if (cameraMgr == NULL) { |     if (cameraMgr == NULL) { | ||||||
|         #if 0  // !!! FIXME: this is getting replaced in a different branch. |         #if 0  // !!! FIXME: this is getting replaced in a different branch. | ||||||
| @@ -78,9 +78,13 @@ static void create_cameraMgr(void) | |||||||
|             SDL_Log("Create ACameraManager"); |             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) { |     if (cameraIdList) { | ||||||
|         ACameraManager_deleteCameraIdList(cameraIdList); |         ACameraManager_deleteCameraIdList(cameraIdList); | ||||||
| @@ -215,7 +219,7 @@ static void onActive(void* context, ACameraCaptureSession *session) | |||||||
|     #endif |     #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| int OpenDevice(SDL_CameraDevice *_this) | static int ANDROIDCAMERA_OpenDevice(SDL_CameraDevice *_this) | ||||||
| { | { | ||||||
|     /* Cannot open a second camera, while the first one is opened. |     /* 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. |      * 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)); |     _this->hidden = (struct SDL_PrivateCameraData *) SDL_calloc(1, sizeof (struct SDL_PrivateCameraData)); | ||||||
|     if (_this->hidden == NULL) { |     if (_this->hidden == NULL) { | ||||||
|         return SDL_OutOfMemory(); |         return -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     create_cameraMgr(); |     CreateCameraManager(); | ||||||
|  |  | ||||||
|     _this->hidden->dev_callbacks.context = (void *) _this; |     _this->hidden->dev_callbacks.context = (void *) _this; | ||||||
|     _this->hidden->dev_callbacks.onDisconnected = onDisconnected; |     _this->hidden->dev_callbacks.onDisconnected = onDisconnected; | ||||||
| @@ -248,7 +252,7 @@ int OpenDevice(SDL_CameraDevice *_this) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| void CloseDevice(SDL_CameraDevice *_this) | static void ANDROIDCAMERA_CloseDevice(SDL_CameraDevice *_this) | ||||||
| { | { | ||||||
|     if (_this && _this->hidden) { |     if (_this && _this->hidden) { | ||||||
|         if (_this->hidden->session) { |         if (_this->hidden->session) { | ||||||
| @@ -271,14 +275,9 @@ void CloseDevice(SDL_CameraDevice *_this) | |||||||
|  |  | ||||||
|         _this->hidden = NULL; |         _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; |     size_t size, pitch; | ||||||
|     SDL_CalculateSize(_this->spec.format, _this->spec.width, _this->spec.height, &size, &pitch, SDL_FALSE); |     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; |     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 |     // !!! FIXME: catch NULLs at higher level | ||||||
|     if (spec) { |     if (spec) { | ||||||
| @@ -296,7 +295,7 @@ int GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec) | |||||||
|     return -1; |     return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| int StartCamera(SDL_CameraDevice *_this) | static int ANDROIDCAMERA_StartCamera(SDL_CameraDevice *_this) | ||||||
| { | { | ||||||
|     // !!! FIXME: maybe log the error code in SDL_SetError |     // !!! FIXME: maybe log the error code in SDL_SetError | ||||||
|     camera_status_t res; |     camera_status_t res; | ||||||
| @@ -377,14 +376,14 @@ error: | |||||||
|     return -1; |     return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| int StopCamera(SDL_CameraDevice *_this) | static int ANDROIDCAMERA_StopCamera(SDL_CameraDevice *_this) | ||||||
| { | { | ||||||
|     ACameraCaptureSession_close(_this->hidden->session); |     ACameraCaptureSession_close(_this->hidden->session); | ||||||
|     _this->hidden->session = NULL; |     _this->hidden->session = NULL; | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) | static int ANDROIDCAMERA_AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) | ||||||
| { | { | ||||||
|     media_status_t res; |     media_status_t res; | ||||||
|     AImage *image; |     AImage *image; | ||||||
| @@ -435,7 +434,7 @@ int AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) | static int ANDROIDCAMERA_ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) | ||||||
| { | { | ||||||
|     if (frame->internal){ |     if (frame->internal){ | ||||||
|         AImage_delete((AImage *)frame->internal); |         AImage_delete((AImage *)frame->internal); | ||||||
| @@ -443,7 +442,7 @@ int ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int GetNumFormats(SDL_CameraDevice *_this) | static int ANDROIDCAMERA_GetNumFormats(SDL_CameraDevice *_this) | ||||||
| { | { | ||||||
|     camera_status_t res; |     camera_status_t res; | ||||||
|     SDL_bool unknown = SDL_FALSE; |     SDL_bool unknown = SDL_FALSE; | ||||||
| @@ -505,7 +504,7 @@ int GetNumFormats(SDL_CameraDevice *_this) | |||||||
|     return _this->hidden->num_formats; |     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; |     int i2 = 0; | ||||||
|  |  | ||||||
| @@ -533,7 +532,7 @@ int GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) | static int ANDROIDCAMERA_GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) | ||||||
| { | { | ||||||
|     // !!! FIXME: call SDL_SetError()? |     // !!! FIXME: call SDL_SetError()? | ||||||
|     if (_this->hidden->num_formats == 0) { |     if (_this->hidden->num_formats == 0) { | ||||||
| @@ -559,7 +558,7 @@ int GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) | |||||||
|     return -1; |     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()? |     // !!! FIXME: call SDL_SetError()? | ||||||
|     camera_status_t res; |     camera_status_t res; | ||||||
| @@ -608,10 +607,10 @@ int GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, | |||||||
|     return -1; |     return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int GetNumDevices(void) | static int ANDROIDCAMERA_GetNumDevices(void) | ||||||
| { | { | ||||||
|     camera_status_t res; |     camera_status_t res; | ||||||
|     create_cameraMgr(); |     CreateCameraManager(); | ||||||
|  |  | ||||||
|     if (cameraIdList) { |     if (cameraIdList) { | ||||||
|         ACameraManager_deleteCameraIdList(cameraIdList); |         ACameraManager_deleteCameraIdList(cameraIdList); | ||||||
| @@ -628,11 +627,11 @@ static int GetNumDevices(void) | |||||||
|     return -1; |     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()? |     // !!! FIXME: call SDL_SetError()? | ||||||
|     int index = instance_id - 1; |     int index = instance_id - 1; | ||||||
|     create_cameraMgr(); |     CreateCameraManager(); | ||||||
|  |  | ||||||
|     if (cameraIdList == NULL) { |     if (cameraIdList == NULL) { | ||||||
|         GetNumDevices(); |         GetNumDevices(); | ||||||
| @@ -648,14 +647,13 @@ int GetCameraDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size) | |||||||
|     return -1; |     return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| SDL_CameraDeviceID *GetCameraDevices(int *count) | static SDL_CameraDeviceID *ANDROIDCAMERA_GetDevices(int *count) | ||||||
| { | { | ||||||
|     // hard-coded list of ID |     // hard-coded list of ID | ||||||
|     const int num = GetNumDevices(); |     const int num = GetNumDevices(); | ||||||
|     SDL_CameraDeviceID *retval = (SDL_CameraDeviceID *)SDL_malloc((num + 1) * sizeof(*ret)); |     SDL_CameraDeviceID *retval = (SDL_CameraDeviceID *)SDL_malloc((num + 1) * sizeof(*ret)); | ||||||
|  |  | ||||||
|     if (retval == NULL) { |     if (retval == NULL) { | ||||||
|         SDL_OutOfMemory(); |  | ||||||
|         *count = 0; |         *count = 0; | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
| @@ -668,15 +666,47 @@ SDL_CameraDeviceID *GetCameraDevices(int *count) | |||||||
|     return retval; |     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 | #endif | ||||||
|  |  | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ | |||||||
| */ | */ | ||||||
| #include "SDL_internal.h" | #include "SDL_internal.h" | ||||||
| 
 | 
 | ||||||
| #ifdef SDL_CAMERA_APPLE | #ifdef SDL_CAMERA_DRIVER_COREMEDIA | ||||||
| 
 | 
 | ||||||
| #include "../SDL_syscamera.h" | #include "../SDL_syscamera.h" | ||||||
| #include "../SDL_camera_c.h" | #include "../SDL_camera_c.h" | ||||||
| @@ -35,59 +35,7 @@ | |||||||
| #undef HAVE_COREMEDIA | #undef HAVE_COREMEDIA | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| // !!! FIXME: use the dummy driver | #ifdef HAVE_COREMEDIA | ||||||
| // !!! 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 |  | ||||||
| 
 | 
 | ||||||
| #import <AVFoundation/AVFoundation.h> | #import <AVFoundation/AVFoundation.h> | ||||||
| #import <CoreMedia/CoreMedia.h> | #import <CoreMedia/CoreMedia.h> | ||||||
| @@ -234,16 +182,16 @@ static NSString *sdlformat_to_nsfourcc(Uint32 fmt) | |||||||
|         } |         } | ||||||
| @end | @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)); |     _this->hidden = (struct SDL_PrivateCameraData *) SDL_calloc(1, sizeof (struct SDL_PrivateCameraData)); | ||||||
|     if (_this->hidden == NULL) { |     if (_this->hidden == NULL) { | ||||||
|         return SDL_OutOfMemory(); |         return -1; | ||||||
|     } |     } | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CloseDevice(SDL_CameraDevice *_this) | static void COREMEDIA_CloseDevice(SDL_CameraDevice *_this) | ||||||
| { | { | ||||||
|     if (!_this) { |     if (!_this) { | ||||||
|         return; |         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? |     // !!! FIXME: autorelease pool? | ||||||
|     NSString *fmt = sdlformat_to_nsfourcc(_this->spec.format); |     NSString *fmt = sdlformat_to_nsfourcc(_this->spec.format); | ||||||
| @@ -381,7 +329,7 @@ int InitDevice(SDL_CameraDevice *_this) | |||||||
|     return 0; |     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 |     // !!! FIXME: make sure higher level checks spec != NULL | ||||||
|     if (spec) { |     if (spec) { | ||||||
| @@ -391,19 +339,19 @@ int GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec) | |||||||
|     return -1; |     return -1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int StartCamera(SDL_CameraDevice *_this) | static int COREMEDIA_StartCamera(SDL_CameraDevice *_this) | ||||||
| { | { | ||||||
|     [_this->hidden->session startRunning]; |     [_this->hidden->session startRunning]; | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int StopCamera(SDL_CameraDevice *_this) | static int COREMEDIA_StopCamera(SDL_CameraDevice *_this) | ||||||
| { | { | ||||||
|     [_this->hidden->session stopRunning]; |     [_this->hidden->session stopRunning]; | ||||||
|     return 0; |     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) { |     if (CMSimpleQueueGetCount(_this->hidden->frame_queue) > 0) { | ||||||
|         CMSampleBufferRef sampleBuffer = (CMSampleBufferRef)CMSimpleQueueDequeue(_this->hidden->frame_queue); |         CMSampleBufferRef sampleBuffer = (CMSampleBufferRef)CMSimpleQueueDequeue(_this->hidden->frame_queue); | ||||||
| @@ -444,7 +392,7 @@ int AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) | static int COREMEDIA_ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) | ||||||
| { | { | ||||||
|     if (frame->internal) { |     if (frame->internal) { | ||||||
|         CMSampleBufferRef sampleBuffer = (CMSampleBufferRef) frame->internal; |         CMSampleBufferRef sampleBuffer = (CMSampleBufferRef) frame->internal; | ||||||
| @@ -456,7 +404,7 @@ int ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int GetNumFormats(SDL_CameraDevice *_this) | static int COREMEDIA_GetNumFormats(SDL_CameraDevice *_this) | ||||||
| { | { | ||||||
|     AVCaptureDevice *device = GetCameraDeviceByName(_this->dev_name); |     AVCaptureDevice *device = GetCameraDeviceByName(_this->dev_name); | ||||||
|     if (device) { |     if (device) { | ||||||
| @@ -476,7 +424,7 @@ int GetNumFormats(SDL_CameraDevice *_this) | |||||||
|     return 0; |     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); |     AVCaptureDevice *device = GetCameraDeviceByName(_this->dev_name); | ||||||
|     if (device) { |     if (device) { | ||||||
| @@ -503,7 +451,7 @@ int GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) | |||||||
|     return -1; |     return -1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) | static int COREMEDIA_GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) | ||||||
| { | { | ||||||
|     AVCaptureDevice *device = GetCameraDeviceByName(_this->dev_name); |     AVCaptureDevice *device = GetCameraDeviceByName(_this->dev_name); | ||||||
|     if (device) { |     if (device) { | ||||||
| @@ -525,8 +473,7 @@ int GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | static int COREMEDIA_GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int *height) | ||||||
| GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int *height) |  | ||||||
| { | { | ||||||
|     AVCaptureDevice *device = GetCameraDeviceByName(_this->dev_name); |     AVCaptureDevice *device = GetCameraDeviceByName(_this->dev_name); | ||||||
|     if (device) { |     if (device) { | ||||||
| @@ -553,7 +500,7 @@ GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int | |||||||
|     return -1; |     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; |     int index = instance_id - 1; | ||||||
|     NSArray<AVCaptureDevice *> *devices = DiscoverCameraDevices(); |     NSArray<AVCaptureDevice *> *devices = DiscoverCameraDevices(); | ||||||
| @@ -567,20 +514,19 @@ int GetCameraDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size) | |||||||
|     return -1; |     return -1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int GetNumDevices(void) | static int GetNumCameraDevices(void) | ||||||
| { | { | ||||||
|     NSArray<AVCaptureDevice *> *devices = DiscoverCameraDevices(); |     NSArray<AVCaptureDevice *> *devices = DiscoverCameraDevices(); | ||||||
|     return [devices count]; |     return [devices count]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| SDL_CameraDeviceID *GetCameraDevices(int *count) | static SDL_CameraDeviceID *COREMEDIA_GetDevices(int *count) | ||||||
| { | { | ||||||
|     // hard-coded list of ID |     // hard-coded list of ID | ||||||
|     const int num = GetNumDevices(); |     const int num = GetNumCameraDevices(); | ||||||
|     SDL_CameraDeviceID *retval = (SDL_CameraDeviceID *)SDL_calloc((num + 1), sizeof(*ret)); |     SDL_CameraDeviceID *retval = (SDL_CameraDeviceID *)SDL_calloc((num + 1), sizeof(*ret)); | ||||||
| 
 | 
 | ||||||
|     if (retval == NULL) { |     if (retval == NULL) { | ||||||
|         SDL_OutOfMemory(); |  | ||||||
|         *count = 0; |         *count = 0; | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
| @@ -593,17 +539,45 @@ SDL_CameraDeviceID *GetCameraDevices(int *count) | |||||||
|     return ret; |     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 // HAVE_COREMEDIA | ||||||
| 
 | 
 | ||||||
| #endif // SDL_CAMERA_APPLE | #endif // SDL_CAMERA_COREMEDIA | ||||||
| 
 | 
 | ||||||
| @@ -20,7 +20,7 @@ | |||||||
| */ | */ | ||||||
| #include "SDL_internal.h" | #include "SDL_internal.h" | ||||||
|  |  | ||||||
| #ifdef SDL_CAMERA_V4L2 | #ifdef SDL_CAMERA_DRIVER_V4L2 | ||||||
|  |  | ||||||
| #include "../SDL_syscamera.h" | #include "../SDL_syscamera.h" | ||||||
| #include "../SDL_camera_c.h" | #include "../SDL_camera_c.h" | ||||||
| @@ -30,8 +30,6 @@ | |||||||
| #include "../../core/linux/SDL_udev.h" | #include "../../core/linux/SDL_udev.h" | ||||||
| #include <limits.h>      // INT_MAX | #include <limits.h>      // INT_MAX | ||||||
|  |  | ||||||
| #define DEBUG_CAMERA 1 |  | ||||||
|  |  | ||||||
| #define MAX_CAMERA_DEVICES 128 // It's doubtful someone has more than that | #define MAX_CAMERA_DEVICES 128 // It's doubtful someone has more than that | ||||||
|  |  | ||||||
| static int MaybeAddDevice(const char *path); | 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; |     struct v4l2_buffer buf; | ||||||
|     const int fd = _this->hidden->fd; |     const int fd = _this->hidden->fd; | ||||||
| @@ -259,8 +257,7 @@ int ReleaseFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int V4L2_AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) | ||||||
| int AcquireFrame(SDL_CameraDevice *_this, SDL_CameraFrame *frame) |  | ||||||
| { | { | ||||||
|     fd_set fds; |     fd_set fds; | ||||||
|     struct timeval tv; |     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; |     enum v4l2_buf_type type; | ||||||
|     const int fd = _this->hidden->fd; |     const int fd = _this->hidden->fd; | ||||||
| @@ -428,7 +425,7 @@ static int PreEnqueueBuffers(SDL_CameraDevice *_this) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int StartCamera(SDL_CameraDevice *_this) | static int V4L2_StartCamera(SDL_CameraDevice *_this) | ||||||
| { | { | ||||||
|     enum v4l2_buf_type type; |     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].length = buffer_size; | ||||||
|     _this->hidden->buffers[0].start = SDL_calloc(1, buffer_size); |     _this->hidden->buffers[0].start = SDL_calloc(1, buffer_size); | ||||||
|  |     return _this->hidden->buffers[0].start ? 0 : -1; | ||||||
|     if (!_this->hidden->buffers[0].start) { |  | ||||||
|         return SDL_OutOfMemory(); |  | ||||||
|     } |  | ||||||
|     return 0; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static int | static int AllocBufferMmap(SDL_CameraDevice *_this) | ||||||
| AllocBufferMmap(SDL_CameraDevice *_this) |  | ||||||
| { | { | ||||||
|     int fd = _this->hidden->fd; |     int fd = _this->hidden->fd; | ||||||
|     int i; |     int i; | ||||||
| @@ -516,8 +508,7 @@ AllocBufferMmap(SDL_CameraDevice *_this) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int | static int AllocBufferUserPtr(SDL_CameraDevice *_this, size_t buffer_size) | ||||||
| AllocBufferUserPtr(SDL_CameraDevice *_this, size_t buffer_size) |  | ||||||
| { | { | ||||||
|     int i; |     int i; | ||||||
|     for (i = 0; i < _this->hidden->nb_buffers; ++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); |         _this->hidden->buffers[i].start = SDL_calloc(1, buffer_size); | ||||||
|  |  | ||||||
|         if (!_this->hidden->buffers[i].start) { |         if (!_this->hidden->buffers[i].start) { | ||||||
|             return SDL_OutOfMemory(); |             return -1; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static Uint32 | static Uint32 format_v4l2_to_sdl(Uint32 fmt) | ||||||
| format_v4l2_2_sdl(Uint32 fmt) |  | ||||||
| { | { | ||||||
|     switch (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_YUYV, SDL_PIXELFORMAT_YUY2); | ||||||
|         CASE(V4L2_PIX_FMT_MJPEG, SDL_PIXELFORMAT_UNKNOWN); |         CASE(V4L2_PIX_FMT_MJPEG, SDL_PIXELFORMAT_UNKNOWN); | ||||||
| #undef CASE |         #undef CASE | ||||||
|         default: |         default: | ||||||
|             SDL_Log("Unknown format V4L2_PIX_FORMAT '%d'", fmt); |             SDL_Log("Unknown format V4L2_PIX_FORMAT '%d'", fmt); | ||||||
|             return SDL_PIXELFORMAT_UNKNOWN; |             return SDL_PIXELFORMAT_UNKNOWN; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static Uint32 | static Uint32 format_sdl_to_v4l2(Uint32 fmt) | ||||||
| format_sdl_2_v4l2(Uint32 fmt) |  | ||||||
| { | { | ||||||
|     switch (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_YUYV, SDL_PIXELFORMAT_YUY2); | ||||||
|         CASE(V4L2_PIX_FMT_MJPEG, SDL_PIXELFORMAT_UNKNOWN); |         CASE(V4L2_PIX_FMT_MJPEG, SDL_PIXELFORMAT_UNKNOWN); | ||||||
| #undef CASE |         #undef CASE | ||||||
|         default: |         default: | ||||||
|             return 0; |             return 0; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| int | static int V4L2_GetNumFormats(SDL_CameraDevice *_this) | ||||||
| GetNumFormats(SDL_CameraDevice *_this) |  | ||||||
| { | { | ||||||
|     int fd = _this->hidden->fd; |     int fd = _this->hidden->fd; | ||||||
|     int i = 0; |     int i = 0; | ||||||
| @@ -574,8 +562,7 @@ GetNumFormats(SDL_CameraDevice *_this) | |||||||
|     return i; |     return i; | ||||||
| } | } | ||||||
|  |  | ||||||
| int | static int V4L2_GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) | ||||||
| GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) |  | ||||||
| { | { | ||||||
|     int fd = _this->hidden->fd; |     int fd = _this->hidden->fd; | ||||||
|     struct v4l2_fmtdesc fmtdesc; |     struct v4l2_fmtdesc fmtdesc; | ||||||
| @@ -584,7 +571,7 @@ GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) | |||||||
|     fmtdesc.index = index; |     fmtdesc.index = index; | ||||||
|     fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |     fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||||
|     if (ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc) == 0) { |     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 DEBUG_CAMERA | ||||||
|         if (fmtdesc.flags & V4L2_FMT_FLAG_EMULATED) { |         if (fmtdesc.flags & V4L2_FMT_FLAG_EMULATED) { | ||||||
| @@ -600,8 +587,7 @@ GetFormat(SDL_CameraDevice *_this, int index, Uint32 *format) | |||||||
|     return -1; |     return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| int | static int V4L2_GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) | ||||||
| GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) |  | ||||||
| { | { | ||||||
|     int fd = _this->hidden->fd; |     int fd = _this->hidden->fd; | ||||||
|     int i = 0; |     int i = 0; | ||||||
| @@ -609,7 +595,7 @@ GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) | |||||||
|  |  | ||||||
|     SDL_zero(frmsizeenum); |     SDL_zero(frmsizeenum); | ||||||
|     frmsizeenum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |     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) { |     while (ioctl(fd,VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) == 0) { | ||||||
|         frmsizeenum.index++; |         frmsizeenum.index++; | ||||||
|         if (frmsizeenum.type == V4L2_FRMSIZE_TYPE_DISCRETE) { |         if (frmsizeenum.type == V4L2_FRMSIZE_TYPE_DISCRETE) { | ||||||
| @@ -624,8 +610,7 @@ GetNumFrameSizes(SDL_CameraDevice *_this, Uint32 format) | |||||||
|     return i; |     return i; | ||||||
| } | } | ||||||
|  |  | ||||||
| int | static int V4L2_GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int *height) | ||||||
| GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int *height) |  | ||||||
| { | { | ||||||
|     int fd = _this->hidden->fd; |     int fd = _this->hidden->fd; | ||||||
|     struct v4l2_frmsizeenum frmsizeenum; |     struct v4l2_frmsizeenum frmsizeenum; | ||||||
| @@ -633,7 +618,7 @@ GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int | |||||||
|  |  | ||||||
|     SDL_zero(frmsizeenum); |     SDL_zero(frmsizeenum); | ||||||
|     frmsizeenum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |     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) { |     while (ioctl(fd,VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) == 0) { | ||||||
|         frmsizeenum.index++; |         frmsizeenum.index++; | ||||||
|  |  | ||||||
| @@ -663,12 +648,8 @@ GetFrameSize(SDL_CameraDevice *_this, Uint32 format, int index, int *width, int | |||||||
|  |  | ||||||
|     return -1; |     return -1; | ||||||
| } | } | ||||||
|  | static void dbg_v4l2_pixelformat(const char *str, int f) | ||||||
|  | { | ||||||
|  |  | ||||||
| #if DEBUG_VIDEO_CAPTURE_CAPTURE |  | ||||||
| static void |  | ||||||
| dbg_v4l2_pixelformat(const char *str, int f) { |  | ||||||
|     SDL_Log("%s  V4L2_format=%d  %c%c%c%c", str, f, |     SDL_Log("%s  V4L2_format=%d  %c%c%c%c", str, f, | ||||||
|                 (f >> 0) & 0xff, |                 (f >> 0) & 0xff, | ||||||
|                 (f >> 8) & 0xff, |                 (f >> 8) & 0xff, | ||||||
| @@ -677,8 +658,7 @@ dbg_v4l2_pixelformat(const char *str, int f) { | |||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| int | static int V4L2_GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec) | ||||||
| GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec) |  | ||||||
| { | { | ||||||
|     struct v4l2_format fmt; |     struct v4l2_format fmt; | ||||||
|     int fd = _this->hidden->fd; |     int fd = _this->hidden->fd; | ||||||
| @@ -705,13 +685,12 @@ GetDeviceSpec(SDL_CameraDevice *_this, SDL_CameraSpec *spec) | |||||||
|     //spec->width = fmt.fmt.pix.width; |     //spec->width = fmt.fmt.pix.width; | ||||||
|     //spec->height = fmt.fmt.pix.height; |     //spec->height = fmt.fmt.pix.height; | ||||||
|     _this->hidden->driver_pitch = fmt.fmt.pix.bytesperline; |     _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; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int | static int V4L2_InitDevice(SDL_CameraDevice *_this) | ||||||
| InitDevice(SDL_CameraDevice *_this) |  | ||||||
| { | { | ||||||
|     struct v4l2_cropcap cropcap; |     struct v4l2_cropcap cropcap; | ||||||
|     struct v4l2_crop crop; |     struct v4l2_crop crop; | ||||||
| @@ -753,7 +732,7 @@ InitDevice(SDL_CameraDevice *_this) | |||||||
|         fmt.fmt.pix.height      = _this->spec.height; |         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_INTERLACED; | ||||||
|         fmt.fmt.pix.field       = V4L2_FIELD_ANY; |         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) { |     if (PreEnqueueBuffers(_this) < 0) { | ||||||
|         return -1; |         return -1; | ||||||
| @@ -776,7 +755,7 @@ InitDevice(SDL_CameraDevice *_this) | |||||||
|     { |     { | ||||||
|         _this->hidden->buffers = SDL_calloc(_this->hidden->nb_buffers, sizeof(*_this->hidden->buffers)); |         _this->hidden->buffers = SDL_calloc(_this->hidden->nb_buffers, sizeof(*_this->hidden->buffers)); | ||||||
|         if (!_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; |     return (retval < 0) ? -1 : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| void CloseDevice(SDL_CameraDevice *_this) | static void V4L2_CloseDevice(SDL_CameraDevice *_this) | ||||||
| { | { | ||||||
|     if (!_this) { |     if (!_this) { | ||||||
|         return; |         return; | ||||||
| @@ -846,8 +825,7 @@ void CloseDevice(SDL_CameraDevice *_this) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int V4L2_OpenDevice(SDL_CameraDevice *_this) | ||||||
| int OpenDevice(SDL_CameraDevice *_this) |  | ||||||
| { | { | ||||||
|     struct stat st; |     struct stat st; | ||||||
|     struct v4l2_capability cap; |     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)); |     _this->hidden = (struct SDL_PrivateCameraData *) SDL_calloc(1, sizeof (struct SDL_PrivateCameraData)); | ||||||
|     if (_this->hidden == NULL) { |     if (_this->hidden == NULL) { | ||||||
|         SDL_OutOfMemory(); |  | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -921,7 +898,7 @@ int OpenDevice(SDL_CameraDevice *_this) | |||||||
|     return 0; |     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; |     SDL_cameralist_item *item; | ||||||
|     for (item = SDL_cameralist; item; item = item->next) { |     for (item = SDL_cameralist; item; item = item->next) { | ||||||
| @@ -935,15 +912,13 @@ int GetCameraDeviceName(SDL_CameraDeviceID instance_id, char *buf, int size) | |||||||
|     return -1; |     return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static SDL_CameraDeviceID *V4L2_GetDevices(int *count) | ||||||
| SDL_CameraDeviceID *GetCameraDevices(int *count) |  | ||||||
| { | { | ||||||
|     // real list of ID |     // real list of ID | ||||||
|     const int num = num_cameras; |     const int num = num_cameras; | ||||||
|     SDL_CameraDeviceID *retval = (SDL_CameraDeviceID *)SDL_malloc((num + 1) * sizeof(*retval)); |     SDL_CameraDeviceID *retval = (SDL_CameraDeviceID *)SDL_malloc((num + 1) * sizeof(*retval)); | ||||||
|  |  | ||||||
|     if (retval == NULL) { |     if (retval == NULL) { | ||||||
|         SDL_OutOfMemory(); |  | ||||||
|         *count = 0; |         *count = 0; | ||||||
|         return NULL; |         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 | #ifdef SDL_USE_LIBUDEV | ||||||
| static void CameraUdevCallback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath) | 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 | #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 | #endif // SDL_CAMERA_V4L2 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -458,7 +458,6 @@ int SDL_VideoInit(const char *driver_name) | |||||||
|     SDL_bool init_keyboard = SDL_FALSE; |     SDL_bool init_keyboard = SDL_FALSE; | ||||||
|     SDL_bool init_mouse = SDL_FALSE; |     SDL_bool init_mouse = SDL_FALSE; | ||||||
|     SDL_bool init_touch = SDL_FALSE; |     SDL_bool init_touch = SDL_FALSE; | ||||||
|     SDL_bool init_camera = SDL_FALSE; |  | ||||||
|     int i = 0; |     int i = 0; | ||||||
|  |  | ||||||
|     /* Check to make sure we don't overwrite '_this' */ |     /* Check to make sure we don't overwrite '_this' */ | ||||||
| @@ -485,10 +484,6 @@ int SDL_VideoInit(const char *driver_name) | |||||||
|         goto pre_driver_error; |         goto pre_driver_error; | ||||||
|     } |     } | ||||||
|     init_touch = SDL_TRUE; |     init_touch = SDL_TRUE; | ||||||
|     if (SDL_CameraInit() < 0) { |  | ||||||
|         goto pre_driver_error; |  | ||||||
|     } |  | ||||||
|     init_camera = SDL_TRUE; |  | ||||||
|  |  | ||||||
|     /* Select the proper video driver */ |     /* Select the proper video driver */ | ||||||
|     video = NULL; |     video = NULL; | ||||||
| @@ -590,9 +585,6 @@ int SDL_VideoInit(const char *driver_name) | |||||||
|  |  | ||||||
| pre_driver_error: | pre_driver_error: | ||||||
|     SDL_assert(_this == NULL); |     SDL_assert(_this == NULL); | ||||||
|     if (init_camera) { |  | ||||||
|         SDL_QuitCamera(); |  | ||||||
|     } |  | ||||||
|     if (init_touch) { |     if (init_touch) { | ||||||
|         SDL_QuitTouch(); |         SDL_QuitTouch(); | ||||||
|     } |     } | ||||||
| @@ -3784,7 +3776,6 @@ void SDL_VideoQuit(void) | |||||||
|     SDL_ClearClipboardData(); |     SDL_ClearClipboardData(); | ||||||
|  |  | ||||||
|     /* Halt event processing before doing anything else */ |     /* Halt event processing before doing anything else */ | ||||||
|     SDL_QuitCamera(); |  | ||||||
|     SDL_QuitTouch(); |     SDL_QuitTouch(); | ||||||
|     SDL_QuitMouse(); |     SDL_QuitMouse(); | ||||||
|     SDL_QuitKeyboard(); |     SDL_QuitKeyboard(); | ||||||
|   | |||||||
| @@ -213,7 +213,7 @@ int main(int argc, char **argv) | |||||||
|     SDL_Log("%s", usage); |     SDL_Log("%s", usage); | ||||||
|  |  | ||||||
|     /* Load the SDL library */ |     /* 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()); |         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError()); | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -54,7 +54,7 @@ int main(int argc, char **argv) | |||||||
|     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); |     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); | ||||||
|  |  | ||||||
|     /* Load the SDL library */ |     /* 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()); |         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError()); | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Ryan C. Gordon
					Ryan C. Gordon