[{"id":31306,"web_url":"https://patchwork.libcamera.org/comment/31306/","msgid":"<7cmdoizlomgmtx5upthpcox66hwro2amc6fxvarg464b3wl524@vxkb7opyfvdm>","date":"2024-09-23T10:21:19","subject":"Re: [PATCH v5 3/3] libcamera: android: Add face detection control\n\tsupport","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Harvey\n\nOn Mon, Sep 23, 2024 at 09:30:46AM GMT, Harvey Yang wrote:\n> From: Harvey Yang <chenghaoyang@chromium.org>\n>\n> Allow Android HAL adapter to pass the face detection metadata control to\n> the pipeline and also send face detection metadata to the camera client\n> if the pipeline generates it.\n>\n> Signed-off-by: Yudhistira Erlandinata <yerlandinata@chromium.org>\n> Co-developed-by: Harvey Yang <chenghaoyang@chromium.org>\n> ---\n>  src/android/camera_capabilities.cpp | 45 +++++++++++++++--\n>  src/android/camera_device.cpp       | 75 ++++++++++++++++++++++++++++-\n>  2 files changed, 114 insertions(+), 6 deletions(-)\n>\n> diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp\n> index 71043e12..a89a3115 100644\n> --- a/src/android/camera_capabilities.cpp\n> +++ b/src/android/camera_capabilities.cpp\n> @@ -7,6 +7,8 @@\n>\n>  #include \"camera_capabilities.h\"\n>\n> +#include <stdint.h>\n> +\n>  #include <algorithm>\n>  #include <array>\n>  #include <cmath>\n> @@ -1176,11 +1178,46 @@ int CameraCapabilities::initializeStaticMetadata()\n>  \t\t\t\t  maxFrameDuration_);\n>\n>  \t/* Statistics static metadata. */\n> -\tuint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> -\tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> -\t\t\t\t  faceDetectMode);\n> -\n>  \tint32_t maxFaceCount = 0;\n> +\tauto iter = camera_->controls().find(controls::draft::FaceDetectMode.id());\n> +\tif (iter != camera_->controls().end()) {\n> +\t\tconst ControlInfo &faceDetectCtrlInfo = iter->second;\n> +\t\tstd::vector<uint8_t> faceDetectModes;\n> +\t\tbool hasFaceDetection = false;\n> +\n> +\t\tfor (const auto &value : faceDetectCtrlInfo.values()) {\n> +\t\t\tuint8_t mode = value.get<uint8_t>();\n> +\t\t\tuint8_t androidMode = 0;\n> +\n> +\t\t\tswitch (mode) {\n> +\t\t\tcase controls::draft::FaceDetectModeOff:\n> +\t\t\t\tandroidMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> +\t\t\t\tbreak;\n> +\t\t\tcase controls::draft::FaceDetectModeSimple:\n> +\t\t\t\tandroidMode = ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE;\n> +\t\t\t\thasFaceDetection = true;\n> +\t\t\t\tbreak;\n> +\t\t\tdefault:\n> +\t\t\t\tLOG(HAL, Fatal) << \"Received invalid face detect mode: \" << mode;\n> +\t\t\t}\n> +\t\t\tfaceDetectModes.push_back(androidMode);\n> +\t\t}\n> +\t\tif (hasFaceDetection) {\n> +\t\t\t/*\n> +\t\t\t * \\todo Create new libcamera controls to query max\n> +\t\t\t * possible faces detected.\n> +\t\t\t */\n> +\t\t\tmaxFaceCount = 10;\n> +\t\t\tstaticMetadata_->addEntry(\n> +\t\t\t\tANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> +\t\t\t\tfaceDetectModes.data(), faceDetectModes.size());\n> +\t\t}\n> +\t} else {\n> +\t\tuint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> +\t\tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> +\t\t\t\t\t  faceDetectMode);\n> +\t}\n> +\n>  \tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,\n>  \t\t\t\t  maxFaceCount);\n>\n> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\n> index 493f66e7..50caa14a 100644\n> --- a/src/android/camera_device.cpp\n> +++ b/src/android/camera_device.cpp\n> @@ -15,6 +15,7 @@\n>  #include <vector>\n>\n>  #include <libcamera/base/log.h>\n> +#include <libcamera/base/span.h>\n>  #include <libcamera/base/unique_fd.h>\n>  #include <libcamera/base/utils.h>\n>\n> @@ -22,6 +23,7 @@\n>  #include <libcamera/controls.h>\n>  #include <libcamera/fence.h>\n>  #include <libcamera/formats.h>\n> +#include <libcamera/geometry.h>\n>  #include <libcamera/property_ids.h>\n>\n>  #include \"system/graphics.h\"\n> @@ -813,6 +815,11 @@ int CameraDevice::processControls(Camera3RequestDescriptor *descriptor)\n>  \t\tcontrols.set(controls::ScalerCrop, cropRegion);\n>  \t}\n>\n> +\tif (settings.getEntry(ANDROID_STATISTICS_FACE_DETECT_MODE, &entry)) {\n> +\t\tconst uint8_t *data = entry.data.u8;\n> +\t\tcontrols.set(controls::draft::FaceDetectMode, data[0]);\n> +\t}\n> +\n>  \tif (settings.getEntry(ANDROID_SENSOR_TEST_PATTERN_MODE, &entry)) {\n>  \t\tconst int32_t data = *entry.data.i32;\n>  \t\tint32_t testPatternMode = controls::draft::TestPatternModeOff;\n> @@ -1540,8 +1547,9 @@ CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) cons\n>  \tvalue32 = ANDROID_SENSOR_TEST_PATTERN_MODE_OFF;\n>  \tresultMetadata->addEntry(ANDROID_SENSOR_TEST_PATTERN_MODE, value32);\n>\n> -\tvalue = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> -\tresultMetadata->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE, value);\n> +\tsettings.getEntry(ANDROID_STATISTICS_FACE_DETECT_MODE, &entry);\n> +\tresultMetadata->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE,\n> +\t\t\t\t entry.data.u8, 1);\n>\n>  \tvalue = ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;\n>  \tresultMetadata->addEntry(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,\n> @@ -1580,6 +1588,69 @@ CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) cons\n>  \t\tresultMetadata->addEntry(ANDROID_SENSOR_FRAME_DURATION,\n>  \t\t\t\t\t *frameDuration * 1000);\n>\n> +\tconst auto &faceDetectRectangles =\n> +\t\tmetadata.get(controls::draft::FaceDetectFaceRectangles);\n> +\tif (faceDetectRectangles) {\n> +\t\tconst Span<const Rectangle> rectangles = *faceDetectRectangles;\n> +\t\tstd::vector<int32_t> flatRectangles;\n> +\t\tfor (const Rectangle &rect : rectangles) {\n> +\t\t\tflatRectangles.push_back(rect.x);\n> +\t\t\tflatRectangles.push_back(rect.y);\n> +\t\t\tflatRectangles.push_back(rect.x + rect.width);\n> +\t\t\tflatRectangles.push_back(rect.y + rect.height);\n> +\t\t}\n> +\t\tresultMetadata->addEntry(\n> +\t\t\tANDROID_STATISTICS_FACE_RECTANGLES, flatRectangles);\n> +\t}\n> +\n> +\tconst auto &faceDetectFaceScores =\n> +\t\tmetadata.get(controls::draft::FaceDetectFaceScores);\n> +\tif (faceDetectRectangles && faceDetectFaceScores) {\n> +\t\tconst Span<const uint8_t> &scores = *faceDetectFaceScores;\n> +\t\tif (scores.size() != faceDetectRectangles->size()) {\n> +\t\t\tLOG(HAL, Error) << \"Pipeline returned wrong number of face scores; \"\n> +\t\t\t\t\t<< \"Expected: \"\n> +\t\t\t\t\t<< faceDetectRectangles->size()\n> +\t\t\t\t\t<< \", got:\" << scores.size();\n\nmissing space after \", got:\"\n\n> +\t\t}\n> +\t\tresultMetadata->addEntry(ANDROID_STATISTICS_FACE_SCORES, scores);\n> +\t}\n> +\n> +\tconst auto &faceDetectFaceLandmarks =\n> +\t\tmetadata.get(controls::draft::FaceDetectFaceLandmarks);\n> +\tif (faceDetectRectangles && faceDetectFaceScores &&\n> +\t    faceDetectFaceLandmarks) {\n\nDo you need to accomulate the checks ? can't you just prefix only it\nwith\n        if (faceDetectRectangles && ...) ?\n\n> +\t\tconst auto &landmarks = *faceDetectFaceLandmarks;\n> +\t\tsize_t expectedLandmarks = faceDetectRectangles->size() * 3;\n> +\t\tif (landmarks.size() != expectedLandmarks) {\n> +\t\t\tLOG(HAL, Error) << \"Pipeline returned wrong number of face landmarks; \"\n> +\t\t\t\t\t<< \"Expected: \" << expectedLandmarks\n> +\t\t\t\t\t<< \", got: \" << landmarks.size();\n> +\t\t}\n> +\n> +\t\tstd::vector<int32_t> androidLandmarks;\n> +\t\tfor (const auto &landmark : landmarks) {\n> +\t\t\tandroidLandmarks.push_back(landmark.x);\n> +\t\t\tandroidLandmarks.push_back(landmark.y);\n> +\t\t}\n> +\t\tresultMetadata->addEntry(\n> +\t\t\tANDROID_STATISTICS_FACE_LANDMARKS, androidLandmarks);\n> +\t}\n> +\n> +\tconst auto &faceDetectFaceIds =\n> +\t\tmetadata.get(controls::draft::FaceDetectFaceIds);\n> +\tif (faceDetectRectangles && faceDetectFaceScores &&\n> +\t    faceDetectFaceLandmarks && faceDetectFaceIds) {\n> +\t\tconst Span<const int32_t> &ids = *faceDetectFaceIds;\n> +\t\tif (ids.size() != faceDetectRectangles->size()) {\n> +\t\t\tLOG(HAL, Error) << \"Pipeline returned wrong number of face ids; \"\n> +\t\t\t\t\t<< \"Expected: \"\n> +\t\t\t\t\t<< faceDetectRectangles->size()\n> +\t\t\t\t\t<< \", got:\" << ids.size();\n\nmissing space after \", got:\"\n\n> +\t\t}\n> +\t\tresultMetadata->addEntry(ANDROID_STATISTICS_FACE_IDS, ids);\n> +\t}\n> +\n\nI can fix the above comments when applying if it's fine with you\n\nReviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n\nThanks\n  j\n\n>  \tconst auto &scalerCrop = metadata.get(controls::ScalerCrop);\n>  \tif (scalerCrop) {\n>  \t\tconst Rectangle &crop = *scalerCrop;\n> --\n> 2.46.0.792.g87dc391469-goog\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 8FF74C0F1B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 23 Sep 2024 10:21:26 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6F0216037E;\n\tMon, 23 Sep 2024 12:21:25 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 676CD6037E\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 23 Sep 2024 12:21:23 +0200 (CEST)","from ideasonboard.com (93-61-96-190.ip145.fastwebnet.it\n\t[93.61.96.190])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 42C302E0;\n\tMon, 23 Sep 2024 12:19:57 +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=\"sCt6agdL\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1727086797;\n\tbh=ApEINiWcDbCCBnjsBVFIRc/9B2w8mSYxIpU9Z/NviEs=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=sCt6agdLtN8SN94SEp76BmSIjfhPdL/7uAZmnERdvR7y34mb++72YDy3zRm4SJ//d\n\tL82yepGekDdONihBYgHKWJeG+Bsw+5fcFUCXpKwODJKhGg1W8YZi/9emrrKNCzD4L+\n\t6Us4yeY6psVlBIhnDMpOUX89VH1qw+8oNCc+v8hw=","Date":"Mon, 23 Sep 2024 12:21:19 +0200","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"Harvey Yang <chenghaoyang@chromium.org>","Cc":"libcamera-devel@lists.libcamera.org, \n\tYudhistira Erlandinata <yerlandinata@chromium.org>","Subject":"Re: [PATCH v5 3/3] libcamera: android: Add face detection control\n\tsupport","Message-ID":"<7cmdoizlomgmtx5upthpcox66hwro2amc6fxvarg464b3wl524@vxkb7opyfvdm>","References":"<20240923093317.3500444-1-chenghaoyang@google.com>\n\t<20240923093317.3500444-4-chenghaoyang@google.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20240923093317.3500444-4-chenghaoyang@google.com>","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":31313,"web_url":"https://patchwork.libcamera.org/comment/31313/","msgid":"<CAC=wSGWV65Azaqy6on5-+goEHXnE-xKyphmzympNB_f=UCKLVg@mail.gmail.com>","date":"2024-09-23T14:51:00","subject":"Re: [PATCH v5 3/3] libcamera: android: Add face detection control\n\tsupport","submitter":{"id":148,"url":"https://patchwork.libcamera.org/api/people/148/","name":"Cheng-Hao Yang","email":"chenghaoyang@google.com"},"content":"Thanks Jacopo!\n\nv6 will be uploaded.\n\nOn Mon, Sep 23, 2024 at 6:21 PM Jacopo Mondi <jacopo.mondi@ideasonboard.com>\nwrote:\n\n> Hi Harvey\n>\n> On Mon, Sep 23, 2024 at 09:30:46AM GMT, Harvey Yang wrote:\n> > From: Harvey Yang <chenghaoyang@chromium.org>\n> >\n> > Allow Android HAL adapter to pass the face detection metadata control to\n> > the pipeline and also send face detection metadata to the camera client\n> > if the pipeline generates it.\n> >\n> > Signed-off-by: Yudhistira Erlandinata <yerlandinata@chromium.org>\n> > Co-developed-by: Harvey Yang <chenghaoyang@chromium.org>\n> > ---\n> >  src/android/camera_capabilities.cpp | 45 +++++++++++++++--\n> >  src/android/camera_device.cpp       | 75 ++++++++++++++++++++++++++++-\n> >  2 files changed, 114 insertions(+), 6 deletions(-)\n> >\n> > diff --git a/src/android/camera_capabilities.cpp\n> b/src/android/camera_capabilities.cpp\n> > index 71043e12..a89a3115 100644\n> > --- a/src/android/camera_capabilities.cpp\n> > +++ b/src/android/camera_capabilities.cpp\n> > @@ -7,6 +7,8 @@\n> >\n> >  #include \"camera_capabilities.h\"\n> >\n> > +#include <stdint.h>\n> > +\n> >  #include <algorithm>\n> >  #include <array>\n> >  #include <cmath>\n> > @@ -1176,11 +1178,46 @@ int\n> CameraCapabilities::initializeStaticMetadata()\n> >                                 maxFrameDuration_);\n> >\n> >       /* Statistics static metadata. */\n> > -     uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> > -\n>  staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> > -                               faceDetectMode);\n> > -\n> >       int32_t maxFaceCount = 0;\n> > +     auto iter =\n> camera_->controls().find(controls::draft::FaceDetectMode.id());\n> > +     if (iter != camera_->controls().end()) {\n> > +             const ControlInfo &faceDetectCtrlInfo = iter->second;\n> > +             std::vector<uint8_t> faceDetectModes;\n> > +             bool hasFaceDetection = false;\n> > +\n> > +             for (const auto &value : faceDetectCtrlInfo.values()) {\n> > +                     uint8_t mode = value.get<uint8_t>();\n> > +                     uint8_t androidMode = 0;\n> > +\n> > +                     switch (mode) {\n> > +                     case controls::draft::FaceDetectModeOff:\n> > +                             androidMode =\n> ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> > +                             break;\n> > +                     case controls::draft::FaceDetectModeSimple:\n> > +                             androidMode =\n> ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE;\n> > +                             hasFaceDetection = true;\n> > +                             break;\n> > +                     default:\n> > +                             LOG(HAL, Fatal) << \"Received invalid face\n> detect mode: \" << mode;\n> > +                     }\n> > +                     faceDetectModes.push_back(androidMode);\n> > +             }\n> > +             if (hasFaceDetection) {\n> > +                     /*\n> > +                      * \\todo Create new libcamera controls to query max\n> > +                      * possible faces detected.\n> > +                      */\n> > +                     maxFaceCount = 10;\n> > +                     staticMetadata_->addEntry(\n> > +\n>  ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> > +                             faceDetectModes.data(),\n> faceDetectModes.size());\n> > +             }\n> > +     } else {\n> > +             uint8_t faceDetectMode =\n> ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> > +\n>  staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> > +                                       faceDetectMode);\n> > +     }\n> > +\n> >       staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,\n> >                                 maxFaceCount);\n> >\n> > diff --git a/src/android/camera_device.cpp\n> b/src/android/camera_device.cpp\n> > index 493f66e7..50caa14a 100644\n> > --- a/src/android/camera_device.cpp\n> > +++ b/src/android/camera_device.cpp\n> > @@ -15,6 +15,7 @@\n> >  #include <vector>\n> >\n> >  #include <libcamera/base/log.h>\n> > +#include <libcamera/base/span.h>\n> >  #include <libcamera/base/unique_fd.h>\n> >  #include <libcamera/base/utils.h>\n> >\n> > @@ -22,6 +23,7 @@\n> >  #include <libcamera/controls.h>\n> >  #include <libcamera/fence.h>\n> >  #include <libcamera/formats.h>\n> > +#include <libcamera/geometry.h>\n> >  #include <libcamera/property_ids.h>\n> >\n> >  #include \"system/graphics.h\"\n> > @@ -813,6 +815,11 @@ int\n> CameraDevice::processControls(Camera3RequestDescriptor *descriptor)\n> >               controls.set(controls::ScalerCrop, cropRegion);\n> >       }\n> >\n> > +     if (settings.getEntry(ANDROID_STATISTICS_FACE_DETECT_MODE,\n> &entry)) {\n> > +             const uint8_t *data = entry.data.u8;\n> > +             controls.set(controls::draft::FaceDetectMode, data[0]);\n> > +     }\n> > +\n> >       if (settings.getEntry(ANDROID_SENSOR_TEST_PATTERN_MODE, &entry)) {\n> >               const int32_t data = *entry.data.i32;\n> >               int32_t testPatternMode =\n> controls::draft::TestPatternModeOff;\n> > @@ -1540,8 +1547,9 @@ CameraDevice::getResultMetadata(const\n> Camera3RequestDescriptor &descriptor) cons\n> >       value32 = ANDROID_SENSOR_TEST_PATTERN_MODE_OFF;\n> >       resultMetadata->addEntry(ANDROID_SENSOR_TEST_PATTERN_MODE,\n> value32);\n> >\n> > -     value = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> > -     resultMetadata->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE,\n> value);\n> > +     settings.getEntry(ANDROID_STATISTICS_FACE_DETECT_MODE, &entry);\n> > +     resultMetadata->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE,\n> > +                              entry.data.u8, 1);\n> >\n> >       value = ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;\n> >       resultMetadata->addEntry(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,\n> > @@ -1580,6 +1588,69 @@ CameraDevice::getResultMetadata(const\n> Camera3RequestDescriptor &descriptor) cons\n> >               resultMetadata->addEntry(ANDROID_SENSOR_FRAME_DURATION,\n> >                                        *frameDuration * 1000);\n> >\n> > +     const auto &faceDetectRectangles =\n> > +             metadata.get(controls::draft::FaceDetectFaceRectangles);\n> > +     if (faceDetectRectangles) {\n> > +             const Span<const Rectangle> rectangles =\n> *faceDetectRectangles;\n> > +             std::vector<int32_t> flatRectangles;\n> > +             for (const Rectangle &rect : rectangles) {\n> > +                     flatRectangles.push_back(rect.x);\n> > +                     flatRectangles.push_back(rect.y);\n> > +                     flatRectangles.push_back(rect.x + rect.width);\n> > +                     flatRectangles.push_back(rect.y + rect.height);\n> > +             }\n> > +             resultMetadata->addEntry(\n> > +                     ANDROID_STATISTICS_FACE_RECTANGLES,\n> flatRectangles);\n> > +     }\n> > +\n> > +     const auto &faceDetectFaceScores =\n> > +             metadata.get(controls::draft::FaceDetectFaceScores);\n> > +     if (faceDetectRectangles && faceDetectFaceScores) {\n> > +             const Span<const uint8_t> &scores = *faceDetectFaceScores;\n> > +             if (scores.size() != faceDetectRectangles->size()) {\n> > +                     LOG(HAL, Error) << \"Pipeline returned wrong number\n> of face scores; \"\n> > +                                     << \"Expected: \"\n> > +                                     << faceDetectRectangles->size()\n> > +                                     << \", got:\" << scores.size();\n>\n> missing space after \", got:\"\n>\n\nRight, sorry. Fixed.\n\n\n>\n> > +             }\n> > +             resultMetadata->addEntry(ANDROID_STATISTICS_FACE_SCORES,\n> scores);\n> > +     }\n> > +\n> > +     const auto &faceDetectFaceLandmarks =\n> > +             metadata.get(controls::draft::FaceDetectFaceLandmarks);\n> > +     if (faceDetectRectangles && faceDetectFaceScores &&\n> > +         faceDetectFaceLandmarks) {\n>\n> Do you need to accomulate the checks ? can't you just prefix only it\n> with\n>         if (faceDetectRectangles && ...) ?\n>\n\nAh good point. Fixed.\n\n\n>\n> > +             const auto &landmarks = *faceDetectFaceLandmarks;\n> > +             size_t expectedLandmarks = faceDetectRectangles->size() *\n> 3;\n> > +             if (landmarks.size() != expectedLandmarks) {\n> > +                     LOG(HAL, Error) << \"Pipeline returned wrong number\n> of face landmarks; \"\n> > +                                     << \"Expected: \" <<\n> expectedLandmarks\n> > +                                     << \", got: \" << landmarks.size();\n> > +             }\n> > +\n> > +             std::vector<int32_t> androidLandmarks;\n> > +             for (const auto &landmark : landmarks) {\n> > +                     androidLandmarks.push_back(landmark.x);\n> > +                     androidLandmarks.push_back(landmark.y);\n> > +             }\n> > +             resultMetadata->addEntry(\n> > +                     ANDROID_STATISTICS_FACE_LANDMARKS,\n> androidLandmarks);\n> > +     }\n> > +\n> > +     const auto &faceDetectFaceIds =\n> > +             metadata.get(controls::draft::FaceDetectFaceIds);\n> > +     if (faceDetectRectangles && faceDetectFaceScores &&\n> > +         faceDetectFaceLandmarks && faceDetectFaceIds) {\n> > +             const Span<const int32_t> &ids = *faceDetectFaceIds;\n> > +             if (ids.size() != faceDetectRectangles->size()) {\n> > +                     LOG(HAL, Error) << \"Pipeline returned wrong number\n> of face ids; \"\n> > +                                     << \"Expected: \"\n> > +                                     << faceDetectRectangles->size()\n> > +                                     << \", got:\" << ids.size();\n>\n> missing space after \", got:\"\n>\n\nFixed.\n\n\n>\n> > +             }\n> > +             resultMetadata->addEntry(ANDROID_STATISTICS_FACE_IDS, ids);\n> > +     }\n> > +\n>\n> I can fix the above comments when applying if it's fine with you\n>\n> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n>\n> Thanks\n>   j\n>\n> >       const auto &scalerCrop = metadata.get(controls::ScalerCrop);\n> >       if (scalerCrop) {\n> >               const Rectangle &crop = *scalerCrop;\n> > --\n> > 2.46.0.792.g87dc391469-goog\n> >\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 DFD8BC0F1B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 23 Sep 2024 14:51:39 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 79CC463513;\n\tMon, 23 Sep 2024 16:51:39 +0200 (CEST)","from mail-ed1-x532.google.com (mail-ed1-x532.google.com\n\t[IPv6:2a00:1450:4864:20::532])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D77C36037E\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 23 Sep 2024 16:51:37 +0200 (CEST)","by mail-ed1-x532.google.com with SMTP id\n\t4fb4d7f45d1cf-5c247dd0899so18665a12.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 23 Sep 2024 07:51:37 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=google.com header.i=@google.com\n\theader.b=\"UOdnqsUS\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=google.com; s=20230601; t=1727103097; x=1727707897;\n\tdarn=lists.libcamera.org; \n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:from:to:cc:subject:date:message-id:reply-to;\n\tbh=Y/NvxRwfUKFQXaCTIC530BsJZXiGGeI15QLUz4DCOBE=;\n\tb=UOdnqsUSbAWPvgt2ixq/H+qxoKZHkV26rQt5WyJPBt7gm2dfDRLfDTrSHHksIFfL4/\n\t98dPsK6qOSrkLScQR72QhdLwX55pWtPyLmHa+HUFM0rW9kzGc3OLKh1LDCtUcgqK9KGq\n\tNpX0oIFx4Uo8M77yIF4h+oCSs2Wo8eiInnqbxzn0IcExkRPcFbCeKEnZ+rLetPdowNuf\n\t0XzdxXbMdtH9O2jsxkte73AkIcgRbzKzm+1BkfSoxSAcGH9wSp+nCDbt9FaRd2tADZBy\n\tcIryQrlEzNNo8m3+ifK26D5YrlBEHU1bjgmLQlsBPqku3BKRVbP8QxPeIrcPfAG+ZQpF\n\tAknw==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1727103097; x=1727707897;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:x-gm-message-state:from:to:cc:subject:date:message-id\n\t:reply-to;\n\tbh=Y/NvxRwfUKFQXaCTIC530BsJZXiGGeI15QLUz4DCOBE=;\n\tb=qKxbGs/VQLJVmYiaalNZd+Yp7RiByvbaY6sSFghcQ3bFJuMPFY1WyliAoCu/ZG674s\n\tl8KTal7T40fQD8YAuP/ipCximBfs33besUvO+0Uvjhzz2R2aCtN+tn3BsFP2Gvqqk+I+\n\t9cF6k0N1iZ118M8bFrx/GQWFgrU+D5IQO0OR29Bc18K1stFNhy94+RLH7EgWj5FyCZ3w\n\tfoDbdgZa+jG7LDJHgKJLl3Z7nGe9BOrgFsIgjFaIBZlvJRdkMJiP9apsHH1MshK/3fAj\n\tAgAdNloTggM3zI8pz2Fmf1cJDpOJqS542ChahjZKEPWkFXcifU0RPdmGu2eEM+3ES4pn\n\tQgSw==","X-Forwarded-Encrypted":"i=1;\n\tAJvYcCW6KUGa7T+DDL4PPnj2f4iaTJHmy20s5skfXGZZLFug/TARgWY7U6uCS2zTWIJhCGJOrKYWTSwP89zbmfFRWp0=@lists.libcamera.org","X-Gm-Message-State":"AOJu0YwLBqijDlSqLxpnF7aO/NN0FOAxSPrtmjjov0jAs7x4hgebCXsC\n\tVMC9xLvR7QKxfvvYIeyLV4UHo2QmDxBbmJUousN0BGW6f9s0iW60KHxBuiHIjy5n5eZh2MGeb7+\n\tvO/iS5HqhEDD2uNCPpNEVZLXX1A5x/7xA/NasFe+WWnSEVylb9Ou9","X-Google-Smtp-Source":"AGHT+IESi+5hHUl7NoY1808oLlVteAv76yZyUyJ0yc0lLFz2WLRh8i+I/TH8MWyf/CKrA9eHHPEd4ETu/W26MYBq0BM=","X-Received":"by 2002:a05:6402:270b:b0:5c2:5251:ba5c with SMTP id\n\t4fb4d7f45d1cf-5c5b769d783mr365158a12.0.1727103096934; Mon, 23 Sep 2024\n\t07:51:36 -0700 (PDT)","MIME-Version":"1.0","References":"<20240923093317.3500444-1-chenghaoyang@google.com>\n\t<20240923093317.3500444-4-chenghaoyang@google.com>\n\t<7cmdoizlomgmtx5upthpcox66hwro2amc6fxvarg464b3wl524@vxkb7opyfvdm>","In-Reply-To":"<7cmdoizlomgmtx5upthpcox66hwro2amc6fxvarg464b3wl524@vxkb7opyfvdm>","From":"Cheng-Hao Yang <chenghaoyang@google.com>","Date":"Mon, 23 Sep 2024 22:51:00 +0800","Message-ID":"<CAC=wSGWV65Azaqy6on5-+goEHXnE-xKyphmzympNB_f=UCKLVg@mail.gmail.com>","Subject":"Re: [PATCH v5 3/3] libcamera: android: Add face detection control\n\tsupport","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Cc":"Harvey Yang <chenghaoyang@chromium.org>,\n\tlibcamera-devel@lists.libcamera.org, \n\tYudhistira Erlandinata <yerlandinata@chromium.org>","Content-Type":"multipart/alternative; boundary=\"00000000000095ef920622ca8674\"","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]