Browse Source

SDL_GetCameraSupportedFormats() follows the SDL_GetStringRule

Also changed the function to return an array of pointers and added example usage to testcamera
Sam Lantinga 9 months ago
parent
commit
0fe6603747
4 changed files with 37 additions and 18 deletions
  1. 7 12
      include/SDL3/SDL_camera.h
  2. 13 5
      src/camera/SDL_camera.c
  3. 1 1
      src/dynapi/SDL_dynapi_procs.h
  4. 16 0
      test/testcamera.c

+ 7 - 12
include/SDL3/SDL_camera.h

@@ -198,24 +198,19 @@ extern SDL_DECLSPEC SDL_CameraID * SDLCALL SDL_GetCameras(int *count);
  * format on your behalf.
  *
  * If `count` is not NULL, it will be filled with the number of elements in
- * the returned array. Additionally, the last element of the array has all
- * fields set to zero (this element is not included in `count`).
+ * the returned array.
  *
- * The returned list is owned by the caller, and should be released with
- * SDL_free() when no longer needed.
- *
- * Note that it's legal for a camera to supply a list with only the zeroed
- * final element and `*count` set to zero; this is what will happen on
+ * Note that it's legal for a camera to supply an empty list. This is what will happen on
  * Emscripten builds, since that platform won't tell _anything_ about
  * available cameras until you've opened one, and won't even tell if there
  * _is_ a camera until the user has given you permission to check through a
  * scary warning popup.
  *
+ * The returned array follows the SDL_GetStringRule, and will be automatically freed later.
+ *
  * \param devid the camera device instance ID to query.
- * \param count a pointer filled in with the number of elements in the list.
- *              Can be NULL.
- * \returns a 0 terminated array of SDL_CameraSpecs, which should be freed
- *          with SDL_free(), or NULL on failure; call
+ * \param count a pointer filled in with the number of elements in the list, may be NULL.
+ * \returns a NULL terminated array of pointers to SDL_CameraSpec or NULL on failure; call
  *          SDL_GetError() for more information.
  *
  * \threadsafety It is safe to call this function from any thread.
@@ -225,7 +220,7 @@ extern SDL_DECLSPEC SDL_CameraID * SDLCALL SDL_GetCameras(int *count);
  * \sa SDL_GetCameras
  * \sa SDL_OpenCamera
  */
-extern SDL_DECLSPEC SDL_CameraSpec * SDLCALL SDL_GetCameraSupportedFormats(SDL_CameraID devid, int *count);
+extern SDL_DECLSPEC const SDL_CameraSpec * const * SDLCALL SDL_GetCameraSupportedFormats(SDL_CameraID devid, int *count);
 
 /**
  * Get the human-readable device name for a camera.

+ 13 - 5
src/camera/SDL_camera.c

@@ -734,7 +734,7 @@ SDL_CameraID *SDL_GetCameras(int *count)
     return retval;
 }
 
-SDL_CameraSpec *SDL_GetCameraSupportedFormats(SDL_CameraID instance_id, int *count)
+const SDL_CameraSpec * const *SDL_GetCameraSupportedFormats(SDL_CameraID instance_id, int *count)
 {
     if (count) {
         *count = 0;
@@ -745,17 +745,25 @@ SDL_CameraSpec *SDL_GetCameraSupportedFormats(SDL_CameraID instance_id, int *cou
         return NULL;
     }
 
-    SDL_CameraSpec *retval = (SDL_CameraSpec *) SDL_calloc(device->num_specs + 1, sizeof (SDL_CameraSpec));
+    int i;
+    int num_specs = device->num_specs;
+    const SDL_CameraSpec **retval = (const SDL_CameraSpec **) SDL_malloc(((num_specs + 1) * sizeof(SDL_CameraSpec *)) + (num_specs * sizeof (SDL_CameraSpec)));
     if (retval) {
-        SDL_memcpy(retval, device->all_specs, sizeof (SDL_CameraSpec) * device->num_specs);
+        SDL_CameraSpec *specs = (SDL_CameraSpec *)((Uint8 *)retval + ((num_specs + 1) * sizeof(SDL_CameraSpec *)));
+        SDL_memcpy(specs, device->all_specs, sizeof (SDL_CameraSpec) * num_specs);
+        for (i = 0; i < num_specs; ++i) {
+            retval[i] = specs++;
+        }
+        retval[i] = NULL;
+
         if (count) {
-            *count = device->num_specs;
+            *count = num_specs;
         }
     }
 
     ReleaseCamera(device);
 
-    return retval;
+    return SDL_FreeLater(retval);
 }
 
 

+ 1 - 1
src/dynapi/SDL_dynapi_procs.h

@@ -232,7 +232,7 @@ SDL_DYNAPI_PROC(const char*,SDL_GetCameraName,(SDL_CameraID a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_GetCameraPermissionState,(SDL_Camera *a),(a),return)
 SDL_DYNAPI_PROC(SDL_CameraPosition,SDL_GetCameraPosition,(SDL_CameraID a),(a),return)
 SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetCameraProperties,(SDL_Camera *a),(a),return)
-SDL_DYNAPI_PROC(SDL_CameraSpec*,SDL_GetCameraSupportedFormats,(SDL_CameraID a, int *b),(a,b),return)
+SDL_DYNAPI_PROC(const SDL_CameraSpec* const*,SDL_GetCameraSupportedFormats,(SDL_CameraID a, int *b),(a,b),return)
 SDL_DYNAPI_PROC(SDL_CameraID*,SDL_GetCameras,(int *a),(a),return)
 SDL_DYNAPI_PROC(void*,SDL_GetClipboardData,(const char *a, size_t *b),(a,b),return)
 SDL_DYNAPI_PROC(const char*,SDL_GetClipboardText,(void),(),return)

+ 16 - 0
test/testcamera.c

@@ -26,6 +26,20 @@ static SDL_Surface *frame_current = NULL;
 static SDL_CameraID front_camera = 0;
 static SDL_CameraID back_camera = 0;
 
+static void PrintCameraSpecs(SDL_CameraID camera_id)
+{
+    const SDL_CameraSpec *const *specs = SDL_GetCameraSupportedFormats(camera_id, NULL);
+    if (specs) {
+        int i;
+
+        SDL_Log("Available formats:\n");
+        for (i = 0; specs[i]; ++i) {
+            const SDL_CameraSpec *s = specs[i];
+            SDL_Log("    %dx%d %.2f FPS %s\n", s->width, s->height, (float)s->framerate_numerator / s->framerate_denominator, SDL_GetPixelFormatName(s->format));
+        }
+    }
+}
+
 int SDL_AppInit(void **appstate, int argc, char *argv[])
 {
     char window_title[128];
@@ -133,6 +147,8 @@ int SDL_AppInit(void **appstate, int argc, char *argv[])
         return SDL_APP_FAILURE;
     }
 
+    PrintCameraSpecs(camera_id);
+
     SDL_CameraSpec *pspec = &spec;
     spec.framerate_numerator = 1000;
     spec.framerate_denominator = 1;