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