From d810227c487c545b3a57ecbb77cdae72ca4f121a Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Wed, 30 Jun 2021 17:24:39 +0200 Subject: android: capabilties: Fix ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES As reported by the CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES documentation in the Android developer reference: "For devices advertising any color filter arrangement other than NIR, or devices not advertising color filter arrangement, this list will always include (min, max) and (max, max) where min <= 15 and max = the maximum output frame rate of the maximum YUV_420_888 output size." Collect the higher FPS of the larger YUV stream and use it with the minimum FPS rate the camera can produce to populate the ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES static metadata. Signed-off-by: Jacopo Mondi Reviewed-by: Paul Elder Reviewed-by: Laurent Pinchart --- src/android/camera_capabilities.cpp | 75 ++++++++++++++----------------------- 1 file changed, 28 insertions(+), 47 deletions(-) diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp index b7c3fdbd..f2f984c5 100644 --- a/src/android/camera_capabilities.cpp +++ b/src/android/camera_capabilities.cpp @@ -886,53 +886,6 @@ int CameraCapabilities::initializeStaticMetadata() staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES, aeAvailableModes); - /* Initialize the AE frame duration limits. */ - const auto frameDurationsInfo = controlsInfo.find(&controls::FrameDurationLimits); - int64_t minFrameDurationNsec = frameDurationsInfo->second.min().get() * 1000; - int64_t maxFrameDurationNsec = frameDurationsInfo->second.max().get() * 1000; - - /* - * Adjust the minimum frame duration to comply with Android - * requirements. The camera service mandates all preview/record - * streams to have a minimum frame duration < 33,366 milliseconds - * (see MAX_PREVIEW_RECORD_DURATION_NS in the camera service - * implementation). - * - * If we're close enough (+ 500 useconds) to that value, round - * the minimum frame duration of the camera to an accepted - * value. - */ - static constexpr int64_t MAX_PREVIEW_RECORD_DURATION_NS = 1e9 / 29.97; - if (minFrameDurationNsec > MAX_PREVIEW_RECORD_DURATION_NS && - minFrameDurationNsec < MAX_PREVIEW_RECORD_DURATION_NS + 500000) - minFrameDurationNsec = MAX_PREVIEW_RECORD_DURATION_NS - 1000; - - /* - * The AE routine frame rate limits are computed using the frame - * duration limits, as libcamera clips the AE routine to the - * frame durations. - */ - int32_t maxFps = std::round(1e9 / minFrameDurationNsec); - int32_t minFps = std::round(1e9 / maxFrameDurationNsec); - minFps = std::max(1, minFps); - - /* - * Force rounding errors so that we have the proper frame - * durations for when we reuse these variables later - */ - minFrameDurationNsec = 1e9 / maxFps; - maxFrameDurationNsec = 1e9 / minFps; - - /* - * Register to the camera service {min, max} and {max, max} - * intervals as requested by the metadata documentation. - */ - int32_t availableAeFpsTarget[] = { - minFps, maxFps, maxFps, maxFps - }; - staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, - availableAeFpsTarget); - std::vector aeCompensationRange = { 0, 0, }; @@ -1278,8 +1231,12 @@ int CameraCapabilities::initializeStaticMetadata() std::vector availableStreamConfigurations; std::vector minFrameDurations; + int maxYUVFps = 0; + Size maxYUVSize; + availableStreamConfigurations.reserve(streamConfigurations_.size() * 4); minFrameDurations.reserve(streamConfigurations_.size() * 4); + for (const auto &entry : streamConfigurations_) { /* * Filter out YUV streams not capable of running at 30 FPS. @@ -1298,6 +1255,16 @@ int CameraCapabilities::initializeStaticMetadata() if (entry.androidFormat != HAL_PIXEL_FORMAT_BLOB && fps < 30) continue; + /* + * Collect the FPS of the maximum YUV output size to populate + * AE_AVAILABLE_TARGET_FPS_RANGE + */ + if (entry.androidFormat == HAL_PIXEL_FORMAT_YCbCr_420_888 && + entry.resolution > maxYUVSize) { + maxYUVSize = entry.resolution; + maxYUVFps = fps; + } + /* Stream configuration map. */ availableStreamConfigurations.push_back(entry.androidFormat); availableStreamConfigurations.push_back(entry.resolution.width); @@ -1323,6 +1290,20 @@ int CameraCapabilities::initializeStaticMetadata() staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS, minFrameDurations); + /* + * Register to the camera service {min, max} and {max, max} with + * 'max' being the larger YUV stream maximum frame rate and 'min' being + * the globally minimum frame rate rounded to the next largest integer + * as the camera service expects the camera maximum frame duration to be + * smaller than 10^9 / minFps. + */ + int32_t minFps = std::ceil(1e9 / maxFrameDuration_); + int32_t availableAeFpsTarget[] = { + minFps, maxYUVFps, maxYUVFps, maxYUVFps, + }; + staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, + availableAeFpsTarget); + std::vector availableStallDurations; for (const auto &entry : streamConfigurations_) { if (entry.androidFormat != HAL_PIXEL_FORMAT_BLOB) -- cgit v1.2.1