Allow specifying only some SDL_CameraSpec fields when opening a camera

This allows setting the size without format, or FPS without size, etc.
This commit is contained in:
Sam Lantinga
2024-05-02 12:25:39 -07:00
parent 861815e51d
commit d4dc613559

View File

@@ -948,8 +948,9 @@ static void ChooseBestCameraSpec(SDL_CameraDevice *device, const SDL_CameraSpec
int wantw = spec->width; int wantw = spec->width;
int wanth = spec->height; int wanth = spec->height;
if (wantw > 0 && wanth > 0) {
// Find the sizes with the closest aspect ratio and then find the best fit of those. // Find the sizes with the closest aspect ratio and then find the best fit of those.
const float wantaspect = ((float)wantw) / ((float) wanth); const float wantaspect = ((float)wantw) / ((float)wanth);
const float epsilon = 1e-6f; const float epsilon = 1e-6f;
float closestaspect = -9999999.0f; float closestaspect = -9999999.0f;
float closestdiff = 999999.0f; float closestdiff = 999999.0f;
@@ -959,7 +960,7 @@ static void ChooseBestCameraSpec(SDL_CameraDevice *device, const SDL_CameraSpec
const SDL_CameraSpec *thisspec = &device->all_specs[i]; const SDL_CameraSpec *thisspec = &device->all_specs[i];
const int thisw = thisspec->width; const int thisw = thisspec->width;
const int thish = thisspec->height; const int thish = thisspec->height;
const float thisaspect = ((float)thisw) / ((float) thish); const float thisaspect = ((float)thisw) / ((float)thish);
const float aspectdiff = SDL_fabs(wantaspect - thisaspect); const float aspectdiff = SDL_fabs(wantaspect - thisaspect);
const float diff = SDL_fabs(closestaspect - thisaspect); const float diff = SDL_fabs(closestaspect - thisaspect);
const int diffw = SDL_abs(thisw - wantw); const int diffw = SDL_abs(thisw - wantw);
@@ -977,6 +978,9 @@ static void ChooseBestCameraSpec(SDL_CameraDevice *device, const SDL_CameraSpec
closest->height = thish; closest->height = thish;
} }
} }
} else {
SDL_copyp(closest, &device->all_specs[0]);
}
SDL_assert(closest->width > 0); SDL_assert(closest->width > 0);
SDL_assert(closest->height > 0); SDL_assert(closest->height > 0);
@@ -1030,16 +1034,6 @@ static void ChooseBestCameraSpec(SDL_CameraDevice *device, const SDL_CameraSpec
SDL_Camera *SDL_OpenCameraDevice(SDL_CameraDeviceID instance_id, const SDL_CameraSpec *spec) SDL_Camera *SDL_OpenCameraDevice(SDL_CameraDeviceID instance_id, const SDL_CameraSpec *spec)
{ {
if (spec) {
if ((spec->width <= 0) || (spec->height <= 0)) {
SDL_SetError("Requested spec frame size is invalid");
return NULL;
} else if (spec->format == SDL_PIXELFORMAT_UNKNOWN) {
SDL_SetError("Requested spec format is invalid");
return NULL;
}
}
SDL_CameraDevice *device = ObtainPhysicalCameraDevice(instance_id); SDL_CameraDevice *device = ObtainPhysicalCameraDevice(instance_id);
if (!device) { if (!device) {
return NULL; return NULL;
@@ -1073,10 +1067,21 @@ SDL_Camera *SDL_OpenCameraDevice(SDL_CameraDeviceID instance_id, const SDL_Camer
return NULL; return NULL;
} }
if (!spec) { if (spec) {
SDL_copyp(&device->spec, &closest);
} else {
SDL_copyp(&device->spec, spec); SDL_copyp(&device->spec, spec);
if (spec->width <= 0 || spec->height <= 0) {
device->spec.width = closest.width;
device->spec.height = closest.height;
}
if (spec->format == SDL_PIXELFORMAT_UNKNOWN) {
device->spec.format = closest.format;
}
if (spec->interval_denominator == 0) {
device->spec.interval_numerator = closest.interval_numerator;
device->spec.interval_denominator = closest.interval_denominator;
}
} else {
SDL_copyp(&device->spec, &closest);
} }
SDL_copyp(&device->actual_spec, &closest); SDL_copyp(&device->actual_spec, &closest);