SDL: Allow for floating point error in matching framerates

From 4f71218e170ad75d7d43fb74cf299d982966257f Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 5 Jul 2024 09:23:06 -0700
Subject: [PATCH] Allow for floating point error in matching framerates

Fixes https://github.com/libsdl-org/SDL/issues/10053
---
 src/camera/coremedia/SDL_camera_coremedia.m | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/src/camera/coremedia/SDL_camera_coremedia.m b/src/camera/coremedia/SDL_camera_coremedia.m
index 5b4bbaaf485e6..6e407ea4cdf12 100644
--- a/src/camera/coremedia/SDL_camera_coremedia.m
+++ b/src/camera/coremedia/SDL_camera_coremedia.m
@@ -268,12 +268,14 @@ static int COREMEDIA_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec *
         }
 
         const CMVideoDimensions dim = CMVideoFormatDescriptionGetDimensions(formatDescription);
-        if ( ((int) dim.width != w) || (((int) dim.height) != h) ) {
+        if ((int)dim.width != w || (int)dim.height != h) {
             continue;
         }
 
+        const float FRAMERATE_EPSILON = 0.01f;
         for (AVFrameRateRange *framerate in format.videoSupportedFrameRateRanges) {
-            if (rate >= framerate.minFrameRate && rate <= framerate.maxFrameRate) {
+            if (rate > (framerate.minFrameRate - FRAMERATE_EPSILON) &&
+                rate < (framerate.maxFrameRate + FRAMERATE_EPSILON)) {
                 spec_format = format;
                 break;
             }
@@ -393,12 +395,15 @@ static void GatherCameraSpecs(AVCaptureDevice *device, CameraFormatAddData *add_
         const int w = (int) dims.width;
         const int h = (int) dims.height;
         for (AVFrameRateRange *framerate in fmt.videoSupportedFrameRateRanges) {
-            int numerator = 0, denominator = 1;
-
-            SDL_CalculateFraction(framerate.minFrameRate, &numerator, &denominator);
-            SDL_AddCameraFormat(add_data, device_format, device_colorspace, w, h, numerator, denominator);
-            SDL_CalculateFraction(framerate.maxFrameRate, &numerator, &denominator);
-            SDL_AddCameraFormat(add_data, device_format, device_colorspace, w, h, numerator, denominator);
+            int min_numerator = 0, min_denominator = 1;
+            int max_numerator = 0, max_denominator = 1;
+
+            SDL_CalculateFraction(framerate.minFrameRate, &min_numerator, &min_denominator);
+            SDL_AddCameraFormat(add_data, device_format, device_colorspace, w, h, min_numerator, min_denominator);
+            SDL_CalculateFraction(framerate.maxFrameRate, &max_numerator, &max_denominator);
+            if (max_numerator != min_numerator || max_denominator != min_denominator) {
+                SDL_AddCameraFormat(add_data, device_format, device_colorspace, w, h, max_numerator, max_denominator);
+            }
         }
     }
 }