Simple Directmedia Layer
at main 220 lines 8.5 kB view raw
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../SDL_internal.h" 22 23#ifndef SDL_syscamera_h_ 24#define SDL_syscamera_h_ 25 26#include "../video/SDL_surface_c.h" 27 28#define DEBUG_CAMERA 0 29 30/* Backends should call this as devices are added to the system (such as 31 a USB camera being plugged in), and should also be called for 32 for every device found during DetectDevices(). */ 33extern SDL_Camera *SDL_AddCamera(const char *name, SDL_CameraPosition position, int num_specs, const SDL_CameraSpec *specs, void *handle); 34 35/* Backends should call this if an opened camera device is lost. 36 This can happen due to i/o errors, or a device being unplugged, etc. */ 37extern void SDL_CameraDisconnected(SDL_Camera *device); 38 39// Find an SDL_Camera, selected by a callback. NULL if not found. DOES NOT LOCK THE DEVICE. 40extern SDL_Camera *SDL_FindPhysicalCameraByCallback(bool (*callback)(SDL_Camera *device, void *userdata), void *userdata); 41 42// Backends should call this when the user has approved/denied access to a camera. 43extern void SDL_CameraPermissionOutcome(SDL_Camera *device, bool approved); 44 45// Backends can call this to get a standardized name for a thread to power a specific camera device. 46extern char *SDL_GetCameraThreadName(SDL_Camera *device, char *buf, size_t buflen); 47 48// Backends can call these to change a device's refcount. 49extern void RefPhysicalCamera(SDL_Camera *device); 50extern void UnrefPhysicalCamera(SDL_Camera *device); 51 52// These functions are the heart of the camera threads. Backends can call them directly if they aren't using the SDL-provided thread. 53extern void SDL_CameraThreadSetup(SDL_Camera *device); 54extern bool SDL_CameraThreadIterate(SDL_Camera *device); 55extern void SDL_CameraThreadShutdown(SDL_Camera *device); 56 57// common utility functionality to gather up camera specs. Not required! 58typedef struct CameraFormatAddData 59{ 60 SDL_CameraSpec *specs; 61 int num_specs; 62 int allocated_specs; 63} CameraFormatAddData; 64 65bool SDL_AddCameraFormat(CameraFormatAddData *data, SDL_PixelFormat format, SDL_Colorspace colorspace, int w, int h, int framerate_numerator, int framerate_denominator); 66 67typedef enum SDL_CameraFrameResult 68{ 69 SDL_CAMERA_FRAME_ERROR, 70 SDL_CAMERA_FRAME_SKIP, 71 SDL_CAMERA_FRAME_READY 72} SDL_CameraFrameResult; 73 74typedef struct SurfaceList 75{ 76 SDL_Surface *surface; 77 Uint64 timestampNS; 78 struct SurfaceList *next; 79} SurfaceList; 80 81// Define the SDL camera driver structure 82struct SDL_Camera 83{ 84 // A mutex for locking 85 SDL_Mutex *lock; 86 87 // Human-readable device name. 88 char *name; 89 90 // Position of camera (front-facing, back-facing, etc). 91 SDL_CameraPosition position; 92 93 // When refcount hits zero, we destroy the device object. 94 SDL_AtomicInt refcount; 95 96 // These are, initially, set from camera_driver, but we might swap them out with Zombie versions on disconnect/failure. 97 bool (*WaitDevice)(SDL_Camera *device); 98 SDL_CameraFrameResult (*AcquireFrame)(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS); 99 void (*ReleaseFrame)(SDL_Camera *device, SDL_Surface *frame); 100 101 // All supported formats/dimensions for this device. 102 SDL_CameraSpec *all_specs; 103 104 // Elements in all_specs. 105 int num_specs; 106 107 // The device's actual specification that the camera is outputting, before conversion. 108 SDL_CameraSpec actual_spec; 109 110 // The device's current camera specification, after conversions. 111 SDL_CameraSpec spec; 112 113 // Unique value assigned at creation time. 114 SDL_CameraID instance_id; 115 116 // Driver-specific hardware data on how to open device (`hidden` is driver-specific data _when opened_). 117 void *handle; 118 119 // Dropping the first frame(s) after open seems to help timing on some platforms. 120 int drop_frames; 121 122 // Backend timestamp of first acquired frame, so we can keep these meaningful regardless of epoch. 123 Uint64 base_timestamp; 124 125 // SDL timestamp of first acquired frame, so we can roughly convert to SDL ticks. 126 Uint64 adjust_timestamp; 127 128 // Pixel data flows from the driver into these, then gets converted for the app if necessary. 129 SDL_Surface *acquire_surface; 130 131 // acquire_surface converts or scales to this surface before landing in output_surfaces, if necessary. 132 SDL_Surface *conversion_surface; 133 134 // A queue of surfaces that buffer converted/scaled frames of video until the app claims them. 135 SurfaceList output_surfaces[8]; 136 SurfaceList filled_output_surfaces; // this is FIFO 137 SurfaceList empty_output_surfaces; // this is LIFO 138 SurfaceList app_held_output_surfaces; 139 140 // A fake video frame we allocate if the camera fails/disconnects. 141 Uint8 *zombie_pixels; 142 143 // non-zero if acquire_surface needs to be scaled for final output. 144 int needs_scaling; // -1: downscale, 0: no scaling, 1: upscale 145 146 // true if acquire_surface needs to be converted for final output. 147 bool needs_conversion; 148 149 // Current state flags 150 SDL_AtomicInt shutdown; 151 SDL_AtomicInt zombie; 152 153 // A thread to feed the camera device 154 SDL_Thread *thread; 155 156 // Optional properties. 157 SDL_PropertiesID props; 158 159 // -1: user denied permission, 0: waiting for user response, 1: user approved permission. 160 int permission; 161 162 // Data private to this driver, used when device is opened and running. 163 struct SDL_PrivateCameraData *hidden; 164}; 165 166typedef struct SDL_CameraDriverImpl 167{ 168 void (*DetectDevices)(void); 169 bool (*OpenDevice)(SDL_Camera *device, const SDL_CameraSpec *spec); 170 void (*CloseDevice)(SDL_Camera *device); 171 bool (*WaitDevice)(SDL_Camera *device); 172 SDL_CameraFrameResult (*AcquireFrame)(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS); // set frame->pixels, frame->pitch, and *timestampNS! 173 void (*ReleaseFrame)(SDL_Camera *device, SDL_Surface *frame); // Reclaim frame->pixels and frame->pitch! 174 void (*FreeDeviceHandle)(SDL_Camera *device); // SDL is done with this device; free the handle from SDL_AddCamera() 175 void (*Deinitialize)(void); 176 177 bool ProvidesOwnCallbackThread; 178} SDL_CameraDriverImpl; 179 180typedef struct SDL_PendingCameraEvent 181{ 182 Uint32 type; 183 SDL_CameraID devid; 184 struct SDL_PendingCameraEvent *next; 185} SDL_PendingCameraEvent; 186 187typedef struct SDL_CameraDriver 188{ 189 const char *name; // The name of this camera driver 190 const char *desc; // The description of this camera driver 191 SDL_CameraDriverImpl impl; // the backend's interface 192 193 SDL_RWLock *device_hash_lock; // A rwlock that protects `device_hash` 194 SDL_HashTable *device_hash; // the collection of currently-available camera devices 195 SDL_PendingCameraEvent pending_events; 196 SDL_PendingCameraEvent *pending_events_tail; 197 198 SDL_AtomicInt device_count; 199 SDL_AtomicInt shutting_down; // non-zero during SDL_Quit, so we known not to accept any last-minute device hotplugs. 200} SDL_CameraDriver; 201 202typedef struct CameraBootStrap 203{ 204 const char *name; 205 const char *desc; 206 bool (*init)(SDL_CameraDriverImpl *impl); 207 bool demand_only; // if true: request explicitly, or it won't be available. 208} CameraBootStrap; 209 210// Not all of these are available in a given build. Use #ifdefs, etc. 211extern CameraBootStrap DUMMYCAMERA_bootstrap; 212extern CameraBootStrap PIPEWIRECAMERA_bootstrap; 213extern CameraBootStrap V4L2_bootstrap; 214extern CameraBootStrap COREMEDIA_bootstrap; 215extern CameraBootStrap ANDROIDCAMERA_bootstrap; 216extern CameraBootStrap EMSCRIPTENCAMERA_bootstrap; 217extern CameraBootStrap MEDIAFOUNDATION_bootstrap; 218extern CameraBootStrap VITACAMERA_bootstrap; 219 220#endif // SDL_syscamera_h_