1 /*
2     DSDL
3     Copyright (C) 2025 Inochi2D Project <luna@foxgirls.gay>
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     ==========================================================================
22 
23     Simple DirectMedia Layer
24     Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
25 
26     This software is provided 'as-is', without any express or implied
27     warranty.  In no event will the authors be held liable for any damages
28     arising from the use of this software.
29 
30     Permission is granted to anyone to use this software for any purpose,
31     including commercial applications, and to alter it and redistribute it
32     freely, subject to the following restrictions:
33 
34     1. The origin of this software must not be misrepresented; you must not
35         claim that you wrote the original software. If you use this software
36         in a product, an acknowledgment in the product documentation would be
37         appreciated but is not required.
38     2. Altered source versions must be plainly marked as such, and must not be
39         misrepresented as being the original software.
40     3. This notice may not be removed or altered from any source distribution.
41 */
42 
43 /**
44     SDL Camera Handling
45 
46     See_Also:
47         $(LINK2 https://wiki.libsdl.org/SDL3/CategoryCamera, SDL3 Camera Documentation)
48     
49     Copyright: © 2025 Inochi2D Project, © 1997-2025 Sam Lantinga
50     License: Subject to the terms of the Zlib License, as written in the LICENSE file.
51     Authors: 
52         Luna Nielsen
53 */
54 module sdl.camera;
55 import sdl.pixels;
56 import sdl.surface;
57 import sdl.properties;
58 import sdl.stdc;
59 
60 extern(C) nothrow @nogc:
61 
62 /**
63     This is a unique ID for a camera device for the time it is connected to the
64     system, and is never reused for the lifetime of the application.
65 
66     If the device is disconnected and reconnected, it will get a new ID.
67 
68     The value 0 is an invalid ID.
69 
70     See_Also:
71         $(D SDL_GetCameras)
72 */
73 alias SDL_CameraID = Uint32;
74 
75 /**
76     The opaque structure used to identify an opened SDL camera.
77 */
78 struct SDL_Camera;
79 
80 /**
81     The details of an output format for a camera device.
82 
83     Cameras often support multiple formats; each one will be encapsulated in
84     this struct.
85 
86     \since This struct is available since SDL 3.2.0.
87 
88     See_Also:
89         $(D SDL_GetCameraSupportedFormats)
90         $(D SDL_GetCameraFormat)
91 */
92 struct SDL_CameraSpec {
93     
94     /**
95         Frame format
96     */
97     SDL_PixelFormat format;
98     
99     /**
100         Frame colorspace
101     */
102     SDL_Colorspace colorspace;
103     
104     /**
105         Frame width
106     */
107     int width;
108     
109     /**
110         Frame height
111     */
112     int height;
113     
114     /**
115         Frame rate numerator ((num / denom) == FPS, (denom / num) == duration in seconds)
116     */
117     int framerate_numerator;
118     
119     /**
120         Frame rate demoninator ((num / denom) == FPS, (denom / num) == duration in seconds)
121     */
122     int framerate_denominator;
123 }
124 
125 /**
126     The position of camera in relation to system device.
127 
128     See_Also:
129         $(D SDL_GetCameraPosition)
130 */
131 enum SDL_CameraPosition {
132     SDL_CAMERA_POSITION_UNKNOWN,
133     SDL_CAMERA_POSITION_FRONT_FACING,
134     SDL_CAMERA_POSITION_BACK_FACING
135 }
136 
137 
138 /**
139     Use this function to get the number of built-in camera drivers.
140 
141     This function returns a hardcoded number. This never returns a negative
142     value; if there are no drivers compiled into this build of SDL, this
143     function returns zero. The presence of a driver in this list does not mean
144     it will function, it just means SDL is capable of interacting with that
145     interface. For example, a build of SDL might have v4l2 support, but if
146     there's no kernel support available, SDL's v4l2 driver would fail if used.
147 
148     By default, SDL tries all drivers, in its preferred order, until one is
149     found to be usable.
150 
151     Returns:
152         the number of built-in camera drivers.
153 
154     Threadsafety:
155         It is safe to call this function from any thread.
156 
157     See_Also:
158         $(D SDL_GetCameraDriver)
159 */
160 extern int SDL_GetNumCameraDrivers();
161 
162 /**
163     Use this function to get the name of a built in camera driver.
164 
165     The list of camera drivers is given in the order that they are normally
166     initialized by default; the drivers that seem more reasonable to choose
167     first (as far as the SDL developers believe) are earlier in the list.
168 
169     The names of drivers are all simple, low-ASCII identifiers, like "v4l2",
170     "coremedia" or "android". These never have Unicode characters, and are not
171     meant to be proper names.
172 
173     Params:
174         index = the index of the camera driver; the value ranges from 0 to
175                 SDL_GetNumCameraDrivers() - 1.
176     
177     Returns:
178         the name of the camera driver at the requested index, or NULL if
179         an invalid index was specified.
180 
181     Threadsafety:
182         It is safe to call this function from any thread.
183 
184     See_Also:
185         $(D SDL_GetNumCameraDrivers)
186 */
187 extern const(char)* SDL_GetCameraDriver(int index);
188 
189 /**
190     Get the name of the current camera driver.
191 
192     The names of drivers are all simple, low-ASCII identifiers, like "v4l2",
193     "coremedia" or "android". These never have Unicode characters, and are not
194     meant to be proper names.
195 
196     Returns:
197         the name of the current camera driver or NULL if no driver has
198         been initialized.
199 
200     Threadsafety:
201         It is safe to call this function from any thread.
202 */
203 extern const(char)* SDL_GetCurrentCameraDriver();
204 
205 /**
206     Get a list of currently connected camera devices.
207 
208     Params:
209         count = a pointer filled in with the number of cameras returned, may
210                 be NULL.
211 
212     Returns:
213         a 0 terminated array of camera instance IDs or NULL on failure;
214         call SDL_GetError() for more information. This should be freed
215         with SDL_free() when it is no longer needed.
216 
217     Threadsafety:
218         It is safe to call this function from any thread.
219 
220     See_Also:
221         $(D SDL_OpenCamera)
222 */
223 extern SDL_CameraID* SDL_GetCameras(int *count);
224 
225 /**
226     Get the list of native formats/sizes a camera supports.
227 
228     This returns a list of all formats and frame sizes that a specific camera
229     can offer. This is useful if your app can accept a variety of image formats
230     and sizes and so want to find the optimal spec that doesn't require
231     conversion.
232 
233     This function isn't strictly required; if you call SDL_OpenCamera with a
234     NULL spec, SDL will choose a native format for you, and if you instead
235     specify a desired format, it will transparently convert to the requested
236     format on your behalf.
237 
238     If `count` is not NULL, it will be filled with the number of elements in
239     the returned array.
240 
241     Note that it's legal for a camera to supply an empty list. This is what
242     will happen on Emscripten builds, since that platform won't tell _anything_
243     about available cameras until you've opened one, and won't even tell if
244     there _is_ a camera until the user has given you permission to check
245     through a scary warning popup.
246 
247     Params:
248         instance_id =   the camera device instance ID.
249         count =         a pointer filled in with the number of elements in the list,
250                         may be NULL.
251     
252     Returns:
253         a NULL terminated array of pointers to SDL_CameraSpec or NULL on
254         failure; call SDL_GetError() for more information. This is a
255         single allocation that should be freed with SDL_free() when it is
256         no longer needed.
257 
258     Threadsafety:
259         It is safe to call this function from any thread.
260 
261     See_Also:
262         $(D SDL_GetCameras)
263         $(D SDL_OpenCamera)
264 */
265 extern SDL_CameraSpec** SDL_GetCameraSupportedFormats(SDL_CameraID instance_id, int* count);
266 
267 /**
268     Get the human-readable device name for a camera.
269 
270     Params:
271         instance_id = the camera device instance ID.
272     
273     Returns:
274         a human-readable device name or NULL on failure; call
275         SDL_GetError() for more information.
276 
277     Threadsafety:
278         It is safe to call this function from any thread.
279 
280     See_Also:
281         $(D SDL_GetCameras)
282 */
283 extern const(char)* SDL_GetCameraName(SDL_CameraID instance_id);
284 
285 /**
286     Get the position of the camera in relation to the system.
287 
288     Most platforms will report UNKNOWN, but mobile devices, like phones, can
289     often make a distinction between cameras on the front of the device (that
290     points towards the user, for taking "selfies") and cameras on the back (for
291     filming in the direction the user is facing).
292 
293     Params:
294         instance_id = the camera device instance ID.
295     
296     Returns:
297         The position of the camera on the system hardware.
298 
299     Threadsafety:
300         It is safe to call this function from any thread.
301 
302     See_Also:
303         $(D SDL_GetCameras)
304 */
305 extern SDL_CameraPosition SDL_GetCameraPosition(SDL_CameraID instance_id);
306 
307 /**
308     Open a video recording device (a "camera").
309 
310     You can open the device with any reasonable spec, and if the hardware can't
311     directly support it, it will convert data seamlessly to the requested
312     format. This might incur overhead, including scaling of image data.
313 
314     If you would rather accept whatever format the device offers, you can pass
315     a NULL spec here and it will choose one for you (and you can use
316     SDL_Surface's conversion/scaling functions directly if necessary).
317 
318     You can call SDL_GetCameraFormat() to get the actual data format if passing
319     a NULL spec here. You can see the exact specs a device can support without
320     conversion with SDL_GetCameraSupportedFormats().
321 
322     SDL will not attempt to emulate framerate; it will try to set the hardware
323     to the rate closest to the requested speed, but it won't attempt to limit
324     or duplicate frames artificially; call SDL_GetCameraFormat() to see the
325     actual framerate of the opened the device, and check your timestamps if
326     this is crucial to your app!
327 
328     Note that the camera is not usable until the user approves its use! On some
329     platforms, the operating system will prompt the user to permit access to
330     the camera, and they can choose Yes or No at that point. Until they do, the
331     camera will not be usable. The app should either wait for an
332     SDL_EVENT_CAMERA_DEVICE_APPROVED (or SDL_EVENT_CAMERA_DEVICE_DENIED) event,
333     or poll SDL_GetCameraPermissionState() occasionally until it returns
334     non-zero. On platforms that don't require explicit user approval (and
335     perhaps in places where the user previously permitted access), the approval
336     event might come immediately, but it might come seconds, minutes, or hours
337     later!
338 
339     Params:
340         instance_id =   the camera device instance ID.
341         spec =          the desired format for data the device will provide. Can be
342                         NULL.
343     
344     Returns:
345         an SDL_Camera object or NULL on failure; call SDL_GetError() for
346         more information.
347 
348     Threadsafety:
349         It is safe to call this function from any thread.
350 
351     See_Also:
352         $(D SDL_GetCameras)
353         $(D SDL_GetCameraFormat)
354 */
355 extern SDL_Camera* SDL_OpenCamera(SDL_CameraID instance_id, const SDL_CameraSpec *spec);
356 
357 /**
358     Query if camera access has been approved by the user.
359 
360     Cameras will not function between when the device is opened by the app and
361     when the user permits access to the hardware. On some platforms, this
362     presents as a popup dialog where the user has to explicitly approve access;
363     on others the approval might be implicit and not alert the user at all.
364 
365     This function can be used to check the status of that approval. It will
366     return 0 if still waiting for user response, 1 if the camera is approved
367     for use, and -1 if the user denied access.
368 
369     Instead of polling with this function, you can wait for a
370     SDL_EVENT_CAMERA_DEVICE_APPROVED (or SDL_EVENT_CAMERA_DEVICE_DENIED) event
371     in the standard SDL event loop, which is guaranteed to be sent once when
372     permission to use the camera is decided.
373 
374     If a camera is declined, there's nothing to be done but call
375     SDL_CloseCamera() to dispose of it.
376 
377     Params:
378         camera = the opened camera device to query.
379 
380     Returns:
381         -1 if user denied access to the camera, 1 if user approved access,
382         0 if no decision has been made yet.
383 
384     Threadsafety:
385         It is safe to call this function from any thread.
386 
387     See_Also:
388         $(D SDL_OpenCamera)
389         $(D SDL_CloseCamera)
390 */
391 extern int SDL_GetCameraPermissionState(SDL_Camera* camera);
392 
393 /**
394     Get the instance ID of an opened camera.
395 
396     Params:
397         camera = an SDL_Camera to query.
398 
399     Returns:
400         the instance ID of the specified camera on success or 0 on
401         failure; call SDL_GetError() for more information.
402 
403     Threadsafety:
404     It is safe to call this function from any thread.
405 
406     See_Also:
407         $(D SDL_OpenCamera)
408 */
409 extern SDL_CameraID SDL_GetCameraID(SDL_Camera* camera);
410 
411 /**
412     Get the properties associated with an opened camera.
413 
414     Params:
415         camera = the SDL_Camera obtained from SDL_OpenCamera().
416     
417     Returns:
418         a valid property ID on success or 0 on failure; call
419         SDL_GetError() for more information.
420 
421     Threadsafety:
422         It is safe to call this function from any thread.
423 */
424 extern SDL_PropertiesID SDL_GetCameraProperties(SDL_Camera* camera);
425 
426 /**
427     Get the spec that a camera is using when generating images.
428 
429     Note that this might not be the native format of the hardware, as SDL might
430     be converting to this format behind the scenes.
431 
432     If the system is waiting for the user to approve access to the camera, as
433     some platforms require, this will return false, but this isn't necessarily
434     a fatal error; you should either wait for an
435     SDL_EVENT_CAMERA_DEVICE_APPROVED (or SDL_EVENT_CAMERA_DEVICE_DENIED) event,
436     or poll SDL_GetCameraPermissionState() occasionally until it returns
437     non-zero.
438 
439     Params:
440         camera =    opened camera device.
441         spec =      the SDL_CameraSpec to be initialized by this function.
442     
443     Returns:
444         true on success or false on failure; call SDL_GetError() for more
445         information.
446 
447     Threadsafety:
448         It is safe to call this function from any thread.
449 
450     See_Also:
451         $(D SDL_OpenCamera)
452 */
453 extern bool SDL_GetCameraFormat(SDL_Camera* camera, SDL_CameraSpec* spec);
454 
455 /**
456     Acquire a frame.
457 
458     The frame is a memory pointer to the image data, whose size and format are
459     given by the spec requested when opening the device.
460 
461     This is a non blocking API. If there is a frame available, a non-NULL
462     surface is returned, and timestampNS will be filled with a non-zero value.
463 
464     Note that an error case can also return NULL, but a NULL by itself is
465     normal and just signifies that a new frame is not yet available. Note that
466     even if a camera device fails outright (a USB camera is unplugged while in
467     use, etc), SDL will send an event separately to notify the app, but
468     continue to provide blank frames at ongoing intervals until
469     SDL_CloseCamera() is called, so real failure here is almost always an out
470     of memory condition.
471 
472     After use, the frame should be released with SDL_ReleaseCameraFrame(). If
473     you don't do this, the system may stop providing more video!
474 
475     Do not call SDL_DestroySurface() on the returned surface! It must be given
476     back to the camera subsystem with SDL_ReleaseCameraFrame!
477 
478     If the system is waiting for the user to approve access to the camera, as
479     some platforms require, this will return NULL (no frames available); you
480     should either wait for an SDL_EVENT_CAMERA_DEVICE_APPROVED (or
481     SDL_EVENT_CAMERA_DEVICE_DENIED) event, or poll
482     SDL_GetCameraPermissionState() occasionally until it returns non-zero.
483 
484     Params:
485         camera =        opened camera device.
486         timestampNS =   a pointer filled in with the frame's timestamp, or 0 on
487                         error. Can be NULL.
488     
489     Returns:
490         a new frame of video on success, NULL if none is currently
491         available.
492 
493     Threadsafety:
494         It is safe to call this function from any thread.
495 
496     See_Also:
497         $(D SDL_ReleaseCameraFrame)
498 */
499 extern SDL_Surface* SDL_AcquireCameraFrame(SDL_Camera* camera, Uint64* timestampNS);
500 
501 /**
502     Release a frame of video acquired from a camera.
503 
504     Let the back-end re-use the internal buffer for camera.
505 
506     This function _must_ be called only on surface objects returned by
507     SDL_AcquireCameraFrame(). This function should be called as quickly as
508     possible after acquisition, as SDL keeps a small FIFO queue of surfaces for
509     video frames; if surfaces aren't released in a timely manner, SDL may drop
510     upcoming video frames from the camera.
511 
512     If the app needs to keep the surface for a significant time, they should
513     make a copy of it and release the original.
514 
515     The app should not use the surface again after calling this function;
516     assume the surface is freed and the pointer is invalid.
517 
518     Params:
519         camera =    opened camera device.
520         frame =     the video frame surface to release.
521 
522     Threadsafety:
523         It is safe to call this function from any thread.
524 
525     See_Also:
526         $(D SDL_AcquireCameraFrame)
527 */
528 extern void SDL_ReleaseCameraFrame(SDL_Camera* camera, SDL_Surface* frame);
529 
530 /**
531     Use this function to shut down camera processing and close the camera
532     device.
533 
534     Params:
535         camera = opened camera device.
536 
537     Threadsafety:
538         It is safe to call this function from any thread, but no
539         thread may reference `device` once this function is called.
540 
541     See_Also:
542         $(D SDL_OpenCamera)
543 */
544 extern void SDL_CloseCamera(SDL_Camera* camera);