[PR] avdevice/avfoundation: keep format and frame rate range paired (PR #23995)

iSoldLeo via ffmpeg-devel <[email protected]> Mon, 03 Aug 2026 11:48:36 -0000
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <178575771758.59.7185294226129242854@29965ddac10e>
PR #23995 opened by iSoldLeo
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23995
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23995.patch

Fixes https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/22694.

## Summary

AVFoundation devices may expose multiple formats with identical dimensions but different frame-rate ranges. The old selection loop updated `selected_format` for every size match while retaining `selected_range` from an earlier format, so the final format and range could belong to different device modes.

Track a size-only match separately and update `selected_format` together with its matching range. This preserves the existing muxed-device size-only fallback and the current last-compatible-format selection behavior.

Related prior patch: https://ffmpeg.org/pipermail/ffmpeg-devel/2025-February/340414.html

## Testing

Tested on an Apple M4 Mac:

- full arm64 build and 2863/2863 local FATE tests
- direct `configure_video_device()` tests: 14 targeted cases plus 5000 randomized format/range matrices
- the same direct tests under ASan/UBSan and Rosetta x86_64
- Objective-C compile checks for macOS arm64/x86_64, iOS device/simulator, tvOS device/simulator, and Mac Catalyst arm64/x86_64
- `checkheaders`, `alltools`, `testprogs`, and `examples`

The Creative Live! Cam Sync 1080p from the issue was not available locally, so validation on that exact hardware is still requested.



>From 74b2140d1d7dc01eade9b811854de7bb6b261ac1 Mon Sep 17 00:00:00 2001
From: iSold Leo <[email protected]>
Date: Mon, 3 Aug 2026 19:43:47 +0800
Subject: [PATCH] avdevice/avfoundation: keep format and frame rate range
 paired

Formats with the same dimensions may expose different frame rates. The
selection loop previously updated selected_format for every size match but
kept selected_range from an earlier format. This could apply a range to a
format that does not support it and make device configuration fail.

Only update selected_format together with its matching range. Track a
size-only match separately so the muxed-device fallback remains unchanged.

Reported-by: MW-de <[email protected]>
Suggested-by: MW-de <[email protected]>
Fixes: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/22694
Signed-off-by: iSold Leo <[email protected]>
---
 libavdevice/avfoundation.m | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m
index 88b814ecf1..e57cd8581a 100644
--- a/libavdevice/avfoundation.m
+++ b/libavdevice/avfoundation.m
@@ -392,6 +392,7 @@ static int configure_video_device(AVFormatContext *s, AVCaptureDevice *video_dev
     double framerate = av_q2d(ctx->framerate);
     NSObject *range = nil;
     NSObject *format = nil;
+    NSObject *matching_size_format = nil;
     NSObject *selected_range = nil;
     NSObject *selected_format = nil;
 
@@ -409,13 +410,14 @@ static int configure_video_device(AVFormatContext *s, AVCaptureDevice *video_dev
             if ((ctx->width == 0 && ctx->height == 0) ||
                 (dimensions.width == ctx->width && dimensions.height == ctx->height)) {
 
-                selected_format = format;
+                matching_size_format = format;
 
                 for (range in [format valueForKey:@"videoSupportedFrameRateRanges"]) {
                     double max_framerate;
 
                     [[range valueForKey:@"maxFrameRate"] getValue:&max_framerate];
                     if (fabs (framerate - max_framerate) < 0.01) {
+                        selected_format = format;
                         selected_range = range;
                         break;
                     }
@@ -423,7 +425,7 @@ static int configure_video_device(AVFormatContext *s, AVCaptureDevice *video_dev
             }
         }
 
-        if (!selected_format) {
+        if (!matching_size_format) {
             av_log(s, AV_LOG_ERROR, "Selected video size (%dx%d) is not supported by the device.\n",
                 ctx->width, ctx->height);
             goto unsupported_format;
@@ -433,6 +435,7 @@ static int configure_video_device(AVFormatContext *s, AVCaptureDevice *video_dev
             av_log(s, AV_LOG_ERROR, "Selected framerate (%f) is not supported by the device.\n",
                 framerate);
             if (ctx->video_is_muxed) {
+                selected_format = matching_size_format;
                 av_log(s, AV_LOG_ERROR, "Falling back to default.\n");
             } else {
                 goto unsupported_format;
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]