diff --git a/include/SDL3/SDL_camera.h b/include/SDL3/SDL_camera.h index ca13689a0c..1114043d07 100644 --- a/include/SDL3/SDL_camera.h +++ b/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. diff --git a/src/camera/SDL_camera.c b/src/camera/SDL_camera.c index b17906ccfc..756f3f7983 100644 --- a/src/camera/SDL_camera.c +++ b/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); } diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 6380957353..54608dff34 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/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) diff --git a/test/testcamera.c b/test/testcamera.c index adf3100c74..17fc5d3acd 100644 --- a/test/testcamera.c +++ b/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;