[libcamera-devel] [PATCH 13/16] android: capabilties: Fix ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES

paul.elder at ideasonboard.com paul.elder at ideasonboard.com
Mon Sep 6 10:49:09 CEST 2021


Hi Jacopo,

On Fri, Sep 03, 2021 at 10:52:25AM +0200, Jacopo Mondi wrote:
> Hi Paul,
> 
> On Wed, Sep 01, 2021 at 06:31:42PM +0900, paul.elder at ideasonboard.com wrote:
> > Hi Jacopo,
> >
> > On Fri, Aug 27, 2021 at 02:07:54PM +0200, Jacopo Mondi wrote:
> > > 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 15 FPS as the
> > > minimum value, if the camera can go slower than that. Populate the
> >
> > If min is allowed to be less than 15, then why do you cap the minimum at
> > 15?
> 
> Good question! I would say 'because the Intel HAL does so' but I know
> it's a very fragile reasoning.
> 
> I'll try to use the max frame duration, after all our definition of
> the FrameDurationLimits control matches
> 
>         The maximum frame duration provides the absolute limit to the shutter
>         speed computed by the AE algorithm and it overrides any exposure mode
>         setting specified with controls::AeExposureMode.
> 
> So I think it's fair to report it as the AE algorithm FPS limit to
> Android.

Sounds good! \o/

With that fixed,

Reviewed-by: Paul Elder <paul.elder at ideasonboard.com>

> 
> -If- Android needs something different for reasons to be clarified,
> we'll have to adjust it in the HAL I guess.
> 
> Thanks
>    j
> 
> >
> >
> > Paul
> >
> > > ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES static metadata with the
> > > newly computed values.
> > >
> > > Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
> > > ---
> > >  src/android/camera_capabilities.cpp | 75 ++++++++++-------------------
> > >  1 file changed, 26 insertions(+), 49 deletions(-)
> > >
> > > diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp
> > > index 8bde06e824ef..01cdbcf1395d 100644
> > > --- a/src/android/camera_capabilities.cpp
> > > +++ b/src/android/camera_capabilities.cpp
> > > @@ -862,55 +862,6 @@ int CameraCapabilities::initializeStaticMetadata()
> > >  	staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,
> > >  				  aeAvailableModes);
> > >
> > > -	/* Initialize the AE frame duration limits. */
> > > -	int64_t minFrameDurationNsec = -1;
> > > -	int64_t maxFrameDurationNsec = -1;
> > > -	const auto frameDurationsInfo = controlsInfo.find(&controls::FrameDurationLimits);
> > > -	minFrameDurationNsec = frameDurationsInfo->second.min().get<int64_t>() * 1000;
> > > -	maxFrameDurationNsec = frameDurationsInfo->second.max().get<int64_t>() * 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<int32_t> aeCompensationRange = {
> > >  		0, 0,
> > >  	};
> > > @@ -1256,8 +1207,12 @@ int CameraCapabilities::initializeStaticMetadata()
> > >
> > >  	std::vector<uint32_t> availableStreamConfigurations;
> > >  	std::vector<int64_t> 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.
> > > @@ -1274,6 +1229,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);
> > > @@ -1301,6 +1266,18 @@ 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
> > > +	 * 15 if the camera can do less than that.
> > > +	 */
> > > +	int32_t minFps = std::max(1e9 / maxFrameDuration_, 15.0);
> > > +	int32_t availableAeFpsTarget[] = {
> > > +		minFps, maxYUVFps, maxYUVFps, maxYUVFps,
> > > +	};
> > > +	staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
> > > +				  availableAeFpsTarget);
> > > +
> > >  	std::vector<int64_t> availableStallDurations;
> > >  	for (const auto &entry : streamConfigurations_) {
> > >  		if (entry.androidFormat != HAL_PIXEL_FORMAT_BLOB)
> > > --
> > > 2.32.0
> > >


More information about the libcamera-devel mailing list