"setTargetFrameRate" doesn't find closest FPS

40 views
Skip to first unread message
Assigned to leoh...@google.com by scot...@google.com

Tobias Tharaldsen

unread,
Jul 1, 2025, 4:05:38 AMJul 1
to Android CameraX Discussion Group
Hi.
I'm not sure if it's a bug or if it's expected, but I see that setTargetFrameRate don't work as well as as using setCaptureRequestOption from Camera2CameraControl.

I'm trying set FPS on video capture, and was hoping I could just set the desired value (range) and then getClosestSupportedDeviceFrameRate from SupportedSurfaceCombination would be used to find the closes value, however that is unfortunately not the case.

Device and library info:
  • I am using Samsung S22, Android 15.
  • Running camera.cameraInfo.supportedFrameRateRanges I get these values:
    Frame rates: [[15, 30], [15, 15], [20, 20], [24, 24], [30, 30], [10, 30], [15, 20], [8, 30]]
  • The CameraX version I use is 1.5.0-beta01

What I see is this:

When using:
            videoCapture = VideoCapture.Builder(recorder)
                .apply { setTargetFrameRate(Range(14, 14)) }
                .build()
The output video is 30 FPS

When using:
            Camera2CameraControl.from(camera.cameraControl)
                .setCaptureRequestOptions(
                    CaptureRequestOptions.Builder()
                        .setCaptureRequestOption(
                            CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,
                            Range(14, 14)
                        ).build()
                )
The output video is 15 FPS.

So the second works, and is what I ended up using, because only that gives me what I need. 

As mentioned at top, I'm not sure if it's a bug or just a missing feature, I see that it was mentioned a bug fix on setTargetFrameRate here: 1.5.0-alpha02 and just wanted to mention it.

Leo Huang

unread,
Jul 1, 2025, 10:55:13 PMJul 1
to Android CameraX Discussion Group, tobb...@gmail.com
Hi,

Thank you for your question. I think you found an interesting problem.

This is the case with the current design. If you dig into the code of getClosestSupportedDeviceFrameRate, you'll see that it prioritizes the range that intersects with the target fps [14, 14]. Therefore, only [10, 30] and [8, 30] are considered, and [10, 30] is ultimately chosen. This results in a final video of 30fps. This is indeed controversial and can be improved. But honestly, even if CameraX modifies the logic for this case, the automatic selection mechanism is still unreliable. There will always be ambiguous situations, such as the target is [14, 14], and the device supports both [12, 12] and [16, 16]. Unless CameraX provide more advanced APIs to meet FPS requirements (if needed, please file a feature request here). So for now, it is still recommended that applications use their own logic to select one from cameraInfo.supportedFrameRateRanges and then set to the frame rate API.

Regarding the Camera2Interop method, although you can bypass the CameraX logic and directly set FPS, if you set a fps range that are not in the available FPS list, it may not be guaranteed to work properly on all devices. It depends on the devices.
The document of CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE states:
Range of valid values: Any of the entries in android.control.aeAvailableTargetFpsRanges

By the way, I am a little curious why such a special fps is set. [15, 15] seems to be more common? 

tobb...@gmail.com 在 2025年7月1日 星期二下午4:05:38 [UTC+8] 的信中寫道:

Tobias Tharaldsen

unread,
Jul 2, 2025, 5:58:55 AMJul 2
to Android CameraX Discussion Group, leoh...@google.com, Tobias Tharaldsen
Thank you for the reply and detailed explanation :)
I have now concluded to do as you suggest and pick an actual value from the cameraInfo.supportedFrameRateRanges and use the setTargetFrameRate from CameraX directly. I discovered the issue you mentioned when setting a range that is not among the available fps ranges (at all), and got some issues when doing that with Camera2Interop while the setTargetFrameRate now worked better instead (it defaulted to the closest highest in my case).

The reason for using Range(14, 14) was just for testing, and because I couldn't find much documentation about what values will be used and set when setting supported/unsupported ranges using setTargetFrameRate, but as I have understood it quickly becomes a complex challenge to find 1 correct range based on 1 desired range, and therefore just creating a custom function and picking manually from the supported list is the best.
Reply all
Reply to author
Forward
0 new messages