[{"id":19258,"web_url":"https://patchwork.libcamera.org/comment/19258/","msgid":"<20210901093142.GZ968527@pyrite.rasen.tech>","date":"2021-09-01T09:31:42","subject":"Re: [libcamera-devel] [PATCH 13/16] android: capabilties: Fix\n\tANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/people/17/","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"content":"Hi Jacopo,\n\nOn Fri, Aug 27, 2021 at 02:07:54PM +0200, Jacopo Mondi wrote:\n> As reported by the CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES documentation\n> in the Android developer reference:\n> \n> \"For devices advertising any color filter arrangement other than NIR, or\n> devices not advertising color filter arrangement, this list will always\n> include (min, max) and (max, max) where min <= 15 and max = the maximum\n> output frame rate of the maximum YUV_420_888 output size.\"\n> \n> Collect the higher FPS of the larger YUV stream and use 15 FPS as the\n> minimum value, if the camera can go slower than that. Populate the\n\nIf min is allowed to be less than 15, then why do you cap the minimum at\n15?\n\n\nPaul\n\n> ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES static metadata with the\n> newly computed values.\n> \n> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> ---\n>  src/android/camera_capabilities.cpp | 75 ++++++++++-------------------\n>  1 file changed, 26 insertions(+), 49 deletions(-)\n> \n> diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp\n> index 8bde06e824ef..01cdbcf1395d 100644\n> --- a/src/android/camera_capabilities.cpp\n> +++ b/src/android/camera_capabilities.cpp\n> @@ -862,55 +862,6 @@ int CameraCapabilities::initializeStaticMetadata()\n>  \tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,\n>  \t\t\t\t  aeAvailableModes);\n>  \n> -\t/* Initialize the AE frame duration limits. */\n> -\tint64_t minFrameDurationNsec = -1;\n> -\tint64_t maxFrameDurationNsec = -1;\n> -\tconst auto frameDurationsInfo = controlsInfo.find(&controls::FrameDurationLimits);\n> -\tminFrameDurationNsec = frameDurationsInfo->second.min().get<int64_t>() * 1000;\n> -\tmaxFrameDurationNsec = frameDurationsInfo->second.max().get<int64_t>() * 1000;\n> -\n> -\t/*\n> -\t * Adjust the minimum frame duration to comply with Android\n> -\t * requirements. The camera service mandates all preview/record\n> -\t * streams to have a minimum frame duration < 33,366 milliseconds\n> -\t * (see MAX_PREVIEW_RECORD_DURATION_NS in the camera service\n> -\t * implementation).\n> -\t *\n> -\t * If we're close enough (+ 500 useconds) to that value, round\n> -\t * the minimum frame duration of the camera to an accepted\n> -\t * value.\n> -\t */\n> -\tstatic constexpr int64_t MAX_PREVIEW_RECORD_DURATION_NS = 1e9 / 29.97;\n> -\tif (minFrameDurationNsec > MAX_PREVIEW_RECORD_DURATION_NS &&\n> -\t    minFrameDurationNsec < MAX_PREVIEW_RECORD_DURATION_NS + 500000)\n> -\t\tminFrameDurationNsec = MAX_PREVIEW_RECORD_DURATION_NS - 1000;\n> -\n> -\t/*\n> -\t * The AE routine frame rate limits are computed using the frame\n> -\t * duration limits, as libcamera clips the AE routine to the\n> -\t * frame durations.\n> -\t */\n> -\tint32_t maxFps = std::round(1e9 / minFrameDurationNsec);\n> -\tint32_t minFps = std::round(1e9 / maxFrameDurationNsec);\n> -\tminFps = std::max(1, minFps);\n> -\n> -\t/*\n> -\t * Force rounding errors so that we have the proper frame\n> -\t * durations for when we reuse these variables later\n> -\t */\n> -\tminFrameDurationNsec = 1e9 / maxFps;\n> -\tmaxFrameDurationNsec = 1e9 / minFps;\n> -\n> -\t/*\n> -\t * Register to the camera service {min, max} and {max, max}\n> -\t * intervals as requested by the metadata documentation.\n> -\t */\n> -\tint32_t availableAeFpsTarget[] = {\n> -\t\tminFps, maxFps, maxFps, maxFps\n> -\t};\n> -\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> -\t\t\t\t  availableAeFpsTarget);\n> -\n>  \tstd::vector<int32_t> aeCompensationRange = {\n>  \t\t0, 0,\n>  \t};\n> @@ -1256,8 +1207,12 @@ int CameraCapabilities::initializeStaticMetadata()\n>  \n>  \tstd::vector<uint32_t> availableStreamConfigurations;\n>  \tstd::vector<int64_t> minFrameDurations;\n> +\tint maxYUVFps = 0;\n> +\tSize maxYUVSize;\n> +\n>  \tavailableStreamConfigurations.reserve(streamConfigurations_.size() * 4);\n>  \tminFrameDurations.reserve(streamConfigurations_.size() * 4);\n> +\n>  \tfor (const auto &entry : streamConfigurations_) {\n>  \t\t/*\n>  \t\t * Filter out YUV streams not capable of running at 30 FPS.\n> @@ -1274,6 +1229,16 @@ int CameraCapabilities::initializeStaticMetadata()\n>  \t\tif (entry.androidFormat != HAL_PIXEL_FORMAT_BLOB && fps < 30)\n>  \t\t\tcontinue;\n>  \n> +\t\t/*\n> +\t\t * Collect the FPS of the maximum YUV output size to populate\n> +\t\t * AE_AVAILABLE_TARGET_FPS_RANGE\n> +\t\t */\n> +\t\tif (entry.androidFormat == HAL_PIXEL_FORMAT_YCbCr_420_888 &&\n> +\t\t    entry.resolution > maxYUVSize) {\n> +\t\t\tmaxYUVSize = entry.resolution;\n> +\t\t\tmaxYUVFps = fps;\n> +\t\t}\n> +\n>  \t\t/* Stream configuration map. */\n>  \t\tavailableStreamConfigurations.push_back(entry.androidFormat);\n>  \t\tavailableStreamConfigurations.push_back(entry.resolution.width);\n> @@ -1301,6 +1266,18 @@ int CameraCapabilities::initializeStaticMetadata()\n>  \tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n>  \t\t\t\t  minFrameDurations);\n>  \n> +\t/*\n> +\t * Register to the camera service {min, max} and {max, max} with\n> +\t * max being the larger YUV stream maximum frame rate and min being\n> +\t * 15 if the camera can do less than that.\n> +\t */\n> +\tint32_t minFps = std::max(1e9 / maxFrameDuration_, 15.0);\n> +\tint32_t availableAeFpsTarget[] = {\n> +\t\tminFps, maxYUVFps, maxYUVFps, maxYUVFps,\n> +\t};\n> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> +\t\t\t\t  availableAeFpsTarget);\n> +\n>  \tstd::vector<int64_t> availableStallDurations;\n>  \tfor (const auto &entry : streamConfigurations_) {\n>  \t\tif (entry.androidFormat != HAL_PIXEL_FORMAT_BLOB)\n> -- \n> 2.32.0\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id F0D93BDC71\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  1 Sep 2021 09:31:50 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6A5E160255;\n\tWed,  1 Sep 2021 11:31:50 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 0387E60253\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  1 Sep 2021 11:31:48 +0200 (CEST)","from pyrite.rasen.tech (unknown\n\t[IPv6:2400:4051:61:600:2c71:1b79:d06d:5032])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id A6A19559;\n\tWed,  1 Sep 2021 11:31:47 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"hdvUhktm\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1630488708;\n\tbh=vxxpH3csEwuMZDajPWGgir2LWYRhJlCXjXyWxx0EOCU=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=hdvUhktm/mtknyOm3/L961u1n8NUTE81Ft7KH6/xAPJWbQDAhBDftZCZztGlVaBhR\n\t6RnO3XiK1wSZlCWOG7DpBuGaPFK25ezk0eDazX6Wl9pWKffximyvS6PAsukTcGNP4r\n\tBuxo2v4vOhQ9P05UA0TRQZ0mhuTIAH8GB2ecaQ78=","Date":"Wed, 1 Sep 2021 18:31:42 +0900","From":"paul.elder@ideasonboard.com","To":"Jacopo Mondi <jacopo@jmondi.org>","Message-ID":"<20210901093142.GZ968527@pyrite.rasen.tech>","References":"<20210827120757.110615-1-jacopo@jmondi.org>\n\t<20210827120757.110615-14-jacopo@jmondi.org>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<20210827120757.110615-14-jacopo@jmondi.org>","Subject":"Re: [libcamera-devel] [PATCH 13/16] android: capabilties: Fix\n\tANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":19330,"web_url":"https://patchwork.libcamera.org/comment/19330/","msgid":"<20210903085225.zeqejfrs3atkgoh5@uno.localdomain>","date":"2021-09-03T08:52:25","subject":"Re: [libcamera-devel] [PATCH 13/16] android: capabilties: Fix\n\tANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Paul,\n\nOn Wed, Sep 01, 2021 at 06:31:42PM +0900, paul.elder@ideasonboard.com wrote:\n> Hi Jacopo,\n>\n> On Fri, Aug 27, 2021 at 02:07:54PM +0200, Jacopo Mondi wrote:\n> > As reported by the CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES documentation\n> > in the Android developer reference:\n> >\n> > \"For devices advertising any color filter arrangement other than NIR, or\n> > devices not advertising color filter arrangement, this list will always\n> > include (min, max) and (max, max) where min <= 15 and max = the maximum\n> > output frame rate of the maximum YUV_420_888 output size.\"\n> >\n> > Collect the higher FPS of the larger YUV stream and use 15 FPS as the\n> > minimum value, if the camera can go slower than that. Populate the\n>\n> If min is allowed to be less than 15, then why do you cap the minimum at\n> 15?\n\nGood question! I would say 'because the Intel HAL does so' but I know\nit's a very fragile reasoning.\n\nI'll try to use the max frame duration, after all our definition of\nthe FrameDurationLimits control matches\n\n        The maximum frame duration provides the absolute limit to the shutter\n        speed computed by the AE algorithm and it overrides any exposure mode\n        setting specified with controls::AeExposureMode.\n\nSo I think it's fair to report it as the AE algorithm FPS limit to\nAndroid.\n\n-If- Android needs something different for reasons to be clarified,\nwe'll have to adjust it in the HAL I guess.\n\nThanks\n   j\n\n>\n>\n> Paul\n>\n> > ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES static metadata with the\n> > newly computed values.\n> >\n> > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> > ---\n> >  src/android/camera_capabilities.cpp | 75 ++++++++++-------------------\n> >  1 file changed, 26 insertions(+), 49 deletions(-)\n> >\n> > diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp\n> > index 8bde06e824ef..01cdbcf1395d 100644\n> > --- a/src/android/camera_capabilities.cpp\n> > +++ b/src/android/camera_capabilities.cpp\n> > @@ -862,55 +862,6 @@ int CameraCapabilities::initializeStaticMetadata()\n> >  \tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,\n> >  \t\t\t\t  aeAvailableModes);\n> >\n> > -\t/* Initialize the AE frame duration limits. */\n> > -\tint64_t minFrameDurationNsec = -1;\n> > -\tint64_t maxFrameDurationNsec = -1;\n> > -\tconst auto frameDurationsInfo = controlsInfo.find(&controls::FrameDurationLimits);\n> > -\tminFrameDurationNsec = frameDurationsInfo->second.min().get<int64_t>() * 1000;\n> > -\tmaxFrameDurationNsec = frameDurationsInfo->second.max().get<int64_t>() * 1000;\n> > -\n> > -\t/*\n> > -\t * Adjust the minimum frame duration to comply with Android\n> > -\t * requirements. The camera service mandates all preview/record\n> > -\t * streams to have a minimum frame duration < 33,366 milliseconds\n> > -\t * (see MAX_PREVIEW_RECORD_DURATION_NS in the camera service\n> > -\t * implementation).\n> > -\t *\n> > -\t * If we're close enough (+ 500 useconds) to that value, round\n> > -\t * the minimum frame duration of the camera to an accepted\n> > -\t * value.\n> > -\t */\n> > -\tstatic constexpr int64_t MAX_PREVIEW_RECORD_DURATION_NS = 1e9 / 29.97;\n> > -\tif (minFrameDurationNsec > MAX_PREVIEW_RECORD_DURATION_NS &&\n> > -\t    minFrameDurationNsec < MAX_PREVIEW_RECORD_DURATION_NS + 500000)\n> > -\t\tminFrameDurationNsec = MAX_PREVIEW_RECORD_DURATION_NS - 1000;\n> > -\n> > -\t/*\n> > -\t * The AE routine frame rate limits are computed using the frame\n> > -\t * duration limits, as libcamera clips the AE routine to the\n> > -\t * frame durations.\n> > -\t */\n> > -\tint32_t maxFps = std::round(1e9 / minFrameDurationNsec);\n> > -\tint32_t minFps = std::round(1e9 / maxFrameDurationNsec);\n> > -\tminFps = std::max(1, minFps);\n> > -\n> > -\t/*\n> > -\t * Force rounding errors so that we have the proper frame\n> > -\t * durations for when we reuse these variables later\n> > -\t */\n> > -\tminFrameDurationNsec = 1e9 / maxFps;\n> > -\tmaxFrameDurationNsec = 1e9 / minFps;\n> > -\n> > -\t/*\n> > -\t * Register to the camera service {min, max} and {max, max}\n> > -\t * intervals as requested by the metadata documentation.\n> > -\t */\n> > -\tint32_t availableAeFpsTarget[] = {\n> > -\t\tminFps, maxFps, maxFps, maxFps\n> > -\t};\n> > -\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> > -\t\t\t\t  availableAeFpsTarget);\n> > -\n> >  \tstd::vector<int32_t> aeCompensationRange = {\n> >  \t\t0, 0,\n> >  \t};\n> > @@ -1256,8 +1207,12 @@ int CameraCapabilities::initializeStaticMetadata()\n> >\n> >  \tstd::vector<uint32_t> availableStreamConfigurations;\n> >  \tstd::vector<int64_t> minFrameDurations;\n> > +\tint maxYUVFps = 0;\n> > +\tSize maxYUVSize;\n> > +\n> >  \tavailableStreamConfigurations.reserve(streamConfigurations_.size() * 4);\n> >  \tminFrameDurations.reserve(streamConfigurations_.size() * 4);\n> > +\n> >  \tfor (const auto &entry : streamConfigurations_) {\n> >  \t\t/*\n> >  \t\t * Filter out YUV streams not capable of running at 30 FPS.\n> > @@ -1274,6 +1229,16 @@ int CameraCapabilities::initializeStaticMetadata()\n> >  \t\tif (entry.androidFormat != HAL_PIXEL_FORMAT_BLOB && fps < 30)\n> >  \t\t\tcontinue;\n> >\n> > +\t\t/*\n> > +\t\t * Collect the FPS of the maximum YUV output size to populate\n> > +\t\t * AE_AVAILABLE_TARGET_FPS_RANGE\n> > +\t\t */\n> > +\t\tif (entry.androidFormat == HAL_PIXEL_FORMAT_YCbCr_420_888 &&\n> > +\t\t    entry.resolution > maxYUVSize) {\n> > +\t\t\tmaxYUVSize = entry.resolution;\n> > +\t\t\tmaxYUVFps = fps;\n> > +\t\t}\n> > +\n> >  \t\t/* Stream configuration map. */\n> >  \t\tavailableStreamConfigurations.push_back(entry.androidFormat);\n> >  \t\tavailableStreamConfigurations.push_back(entry.resolution.width);\n> > @@ -1301,6 +1266,18 @@ int CameraCapabilities::initializeStaticMetadata()\n> >  \tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n> >  \t\t\t\t  minFrameDurations);\n> >\n> > +\t/*\n> > +\t * Register to the camera service {min, max} and {max, max} with\n> > +\t * max being the larger YUV stream maximum frame rate and min being\n> > +\t * 15 if the camera can do less than that.\n> > +\t */\n> > +\tint32_t minFps = std::max(1e9 / maxFrameDuration_, 15.0);\n> > +\tint32_t availableAeFpsTarget[] = {\n> > +\t\tminFps, maxYUVFps, maxYUVFps, maxYUVFps,\n> > +\t};\n> > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> > +\t\t\t\t  availableAeFpsTarget);\n> > +\n> >  \tstd::vector<int64_t> availableStallDurations;\n> >  \tfor (const auto &entry : streamConfigurations_) {\n> >  \t\tif (entry.androidFormat != HAL_PIXEL_FORMAT_BLOB)\n> > --\n> > 2.32.0\n> >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 95A36BD87D\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri,  3 Sep 2021 08:51:38 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 2B63E6916A;\n\tFri,  3 Sep 2021 10:51:38 +0200 (CEST)","from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net\n\t[217.70.183.194])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id B309369165\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri,  3 Sep 2021 10:51:36 +0200 (CEST)","(Authenticated sender: jacopo@jmondi.org)\n\tby relay2-d.mail.gandi.net (Postfix) with ESMTPSA id 49EE840006;\n\tFri,  3 Sep 2021 08:51:36 +0000 (UTC)"],"Date":"Fri, 3 Sep 2021 10:52:25 +0200","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"paul.elder@ideasonboard.com","Message-ID":"<20210903085225.zeqejfrs3atkgoh5@uno.localdomain>","References":"<20210827120757.110615-1-jacopo@jmondi.org>\n\t<20210827120757.110615-14-jacopo@jmondi.org>\n\t<20210901093142.GZ968527@pyrite.rasen.tech>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20210901093142.GZ968527@pyrite.rasen.tech>","Subject":"Re: [libcamera-devel] [PATCH 13/16] android: capabilties: Fix\n\tANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":19407,"web_url":"https://patchwork.libcamera.org/comment/19407/","msgid":"<20210906084909.GR968527@pyrite.rasen.tech>","date":"2021-09-06T08:49:09","subject":"Re: [libcamera-devel] [PATCH 13/16] android: capabilties: Fix\n\tANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/people/17/","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"content":"Hi Jacopo,\n\nOn Fri, Sep 03, 2021 at 10:52:25AM +0200, Jacopo Mondi wrote:\n> Hi Paul,\n> \n> On Wed, Sep 01, 2021 at 06:31:42PM +0900, paul.elder@ideasonboard.com wrote:\n> > Hi Jacopo,\n> >\n> > On Fri, Aug 27, 2021 at 02:07:54PM +0200, Jacopo Mondi wrote:\n> > > As reported by the CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES documentation\n> > > in the Android developer reference:\n> > >\n> > > \"For devices advertising any color filter arrangement other than NIR, or\n> > > devices not advertising color filter arrangement, this list will always\n> > > include (min, max) and (max, max) where min <= 15 and max = the maximum\n> > > output frame rate of the maximum YUV_420_888 output size.\"\n> > >\n> > > Collect the higher FPS of the larger YUV stream and use 15 FPS as the\n> > > minimum value, if the camera can go slower than that. Populate the\n> >\n> > If min is allowed to be less than 15, then why do you cap the minimum at\n> > 15?\n> \n> Good question! I would say 'because the Intel HAL does so' but I know\n> it's a very fragile reasoning.\n> \n> I'll try to use the max frame duration, after all our definition of\n> the FrameDurationLimits control matches\n> \n>         The maximum frame duration provides the absolute limit to the shutter\n>         speed computed by the AE algorithm and it overrides any exposure mode\n>         setting specified with controls::AeExposureMode.\n> \n> So I think it's fair to report it as the AE algorithm FPS limit to\n> Android.\n\nSounds good! \\o/\n\nWith that fixed,\n\nReviewed-by: Paul Elder <paul.elder@ideasonboard.com>\n\n> \n> -If- Android needs something different for reasons to be clarified,\n> we'll have to adjust it in the HAL I guess.\n> \n> Thanks\n>    j\n> \n> >\n> >\n> > Paul\n> >\n> > > ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES static metadata with the\n> > > newly computed values.\n> > >\n> > > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> > > ---\n> > >  src/android/camera_capabilities.cpp | 75 ++++++++++-------------------\n> > >  1 file changed, 26 insertions(+), 49 deletions(-)\n> > >\n> > > diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp\n> > > index 8bde06e824ef..01cdbcf1395d 100644\n> > > --- a/src/android/camera_capabilities.cpp\n> > > +++ b/src/android/camera_capabilities.cpp\n> > > @@ -862,55 +862,6 @@ int CameraCapabilities::initializeStaticMetadata()\n> > >  \tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,\n> > >  \t\t\t\t  aeAvailableModes);\n> > >\n> > > -\t/* Initialize the AE frame duration limits. */\n> > > -\tint64_t minFrameDurationNsec = -1;\n> > > -\tint64_t maxFrameDurationNsec = -1;\n> > > -\tconst auto frameDurationsInfo = controlsInfo.find(&controls::FrameDurationLimits);\n> > > -\tminFrameDurationNsec = frameDurationsInfo->second.min().get<int64_t>() * 1000;\n> > > -\tmaxFrameDurationNsec = frameDurationsInfo->second.max().get<int64_t>() * 1000;\n> > > -\n> > > -\t/*\n> > > -\t * Adjust the minimum frame duration to comply with Android\n> > > -\t * requirements. The camera service mandates all preview/record\n> > > -\t * streams to have a minimum frame duration < 33,366 milliseconds\n> > > -\t * (see MAX_PREVIEW_RECORD_DURATION_NS in the camera service\n> > > -\t * implementation).\n> > > -\t *\n> > > -\t * If we're close enough (+ 500 useconds) to that value, round\n> > > -\t * the minimum frame duration of the camera to an accepted\n> > > -\t * value.\n> > > -\t */\n> > > -\tstatic constexpr int64_t MAX_PREVIEW_RECORD_DURATION_NS = 1e9 / 29.97;\n> > > -\tif (minFrameDurationNsec > MAX_PREVIEW_RECORD_DURATION_NS &&\n> > > -\t    minFrameDurationNsec < MAX_PREVIEW_RECORD_DURATION_NS + 500000)\n> > > -\t\tminFrameDurationNsec = MAX_PREVIEW_RECORD_DURATION_NS - 1000;\n> > > -\n> > > -\t/*\n> > > -\t * The AE routine frame rate limits are computed using the frame\n> > > -\t * duration limits, as libcamera clips the AE routine to the\n> > > -\t * frame durations.\n> > > -\t */\n> > > -\tint32_t maxFps = std::round(1e9 / minFrameDurationNsec);\n> > > -\tint32_t minFps = std::round(1e9 / maxFrameDurationNsec);\n> > > -\tminFps = std::max(1, minFps);\n> > > -\n> > > -\t/*\n> > > -\t * Force rounding errors so that we have the proper frame\n> > > -\t * durations for when we reuse these variables later\n> > > -\t */\n> > > -\tminFrameDurationNsec = 1e9 / maxFps;\n> > > -\tmaxFrameDurationNsec = 1e9 / minFps;\n> > > -\n> > > -\t/*\n> > > -\t * Register to the camera service {min, max} and {max, max}\n> > > -\t * intervals as requested by the metadata documentation.\n> > > -\t */\n> > > -\tint32_t availableAeFpsTarget[] = {\n> > > -\t\tminFps, maxFps, maxFps, maxFps\n> > > -\t};\n> > > -\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> > > -\t\t\t\t  availableAeFpsTarget);\n> > > -\n> > >  \tstd::vector<int32_t> aeCompensationRange = {\n> > >  \t\t0, 0,\n> > >  \t};\n> > > @@ -1256,8 +1207,12 @@ int CameraCapabilities::initializeStaticMetadata()\n> > >\n> > >  \tstd::vector<uint32_t> availableStreamConfigurations;\n> > >  \tstd::vector<int64_t> minFrameDurations;\n> > > +\tint maxYUVFps = 0;\n> > > +\tSize maxYUVSize;\n> > > +\n> > >  \tavailableStreamConfigurations.reserve(streamConfigurations_.size() * 4);\n> > >  \tminFrameDurations.reserve(streamConfigurations_.size() * 4);\n> > > +\n> > >  \tfor (const auto &entry : streamConfigurations_) {\n> > >  \t\t/*\n> > >  \t\t * Filter out YUV streams not capable of running at 30 FPS.\n> > > @@ -1274,6 +1229,16 @@ int CameraCapabilities::initializeStaticMetadata()\n> > >  \t\tif (entry.androidFormat != HAL_PIXEL_FORMAT_BLOB && fps < 30)\n> > >  \t\t\tcontinue;\n> > >\n> > > +\t\t/*\n> > > +\t\t * Collect the FPS of the maximum YUV output size to populate\n> > > +\t\t * AE_AVAILABLE_TARGET_FPS_RANGE\n> > > +\t\t */\n> > > +\t\tif (entry.androidFormat == HAL_PIXEL_FORMAT_YCbCr_420_888 &&\n> > > +\t\t    entry.resolution > maxYUVSize) {\n> > > +\t\t\tmaxYUVSize = entry.resolution;\n> > > +\t\t\tmaxYUVFps = fps;\n> > > +\t\t}\n> > > +\n> > >  \t\t/* Stream configuration map. */\n> > >  \t\tavailableStreamConfigurations.push_back(entry.androidFormat);\n> > >  \t\tavailableStreamConfigurations.push_back(entry.resolution.width);\n> > > @@ -1301,6 +1266,18 @@ int CameraCapabilities::initializeStaticMetadata()\n> > >  \tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n> > >  \t\t\t\t  minFrameDurations);\n> > >\n> > > +\t/*\n> > > +\t * Register to the camera service {min, max} and {max, max} with\n> > > +\t * max being the larger YUV stream maximum frame rate and min being\n> > > +\t * 15 if the camera can do less than that.\n> > > +\t */\n> > > +\tint32_t minFps = std::max(1e9 / maxFrameDuration_, 15.0);\n> > > +\tint32_t availableAeFpsTarget[] = {\n> > > +\t\tminFps, maxYUVFps, maxYUVFps, maxYUVFps,\n> > > +\t};\n> > > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> > > +\t\t\t\t  availableAeFpsTarget);\n> > > +\n> > >  \tstd::vector<int64_t> availableStallDurations;\n> > >  \tfor (const auto &entry : streamConfigurations_) {\n> > >  \t\tif (entry.androidFormat != HAL_PIXEL_FORMAT_BLOB)\n> > > --\n> > > 2.32.0\n> > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 887FCBD87D\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  6 Sep 2021 08:49:17 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 10B646916A;\n\tMon,  6 Sep 2021 10:49:17 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4075E60503\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  6 Sep 2021 10:49:16 +0200 (CEST)","from pyrite.rasen.tech (unknown\n\t[IPv6:2400:4051:61:600:2c71:1b79:d06d:5032])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id D7DB5317;\n\tMon,  6 Sep 2021 10:49:14 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"MLufNU/5\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1630918155;\n\tbh=8xo5ZvAMLkgk3dZnsq448uVmIoenvwRNv7Eq9ea9h+0=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=MLufNU/5OF8HNDgT2KGT/Y+CQq7gO93FtgVv4zCxwDvBaPuSLT8uVEE+SyxRORHfg\n\tSvo+c9JU7z7uD1c+sukXbebvOr7p/JQybBNXYqpcSEBRYQoGqKckK6SwljNXEJsg9Z\n\teXXHNmXDYkKEayiLu01crpa08NNrADNrmwBqMWPk=","Date":"Mon, 6 Sep 2021 17:49:09 +0900","From":"paul.elder@ideasonboard.com","To":"Jacopo Mondi <jacopo@jmondi.org>","Message-ID":"<20210906084909.GR968527@pyrite.rasen.tech>","References":"<20210827120757.110615-1-jacopo@jmondi.org>\n\t<20210827120757.110615-14-jacopo@jmondi.org>\n\t<20210901093142.GZ968527@pyrite.rasen.tech>\n\t<20210903085225.zeqejfrs3atkgoh5@uno.localdomain>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<20210903085225.zeqejfrs3atkgoh5@uno.localdomain>","Subject":"Re: [libcamera-devel] [PATCH 13/16] android: capabilties: Fix\n\tANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]