[{"id":31337,"web_url":"https://patchwork.libcamera.org/comment/31337/","msgid":"<62zqg3qbct6xz5kni3soqeulbgitfiw3hl6rexbikpil4msux7@ulkxq3lwwsvq>","date":"2024-09-24T13:02:11","subject":"Re: [PATCH v7 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 Tue, Sep 24, 2024 at 11:02: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       | 73 ++++++++++++++++++++++++++++-\n>  2 files changed, 112 insertions(+), 6 deletions(-)\n>\n> diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp\n> index 71043e12..d52d58ed 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::android::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::android::FaceDetectModeOff:\n> +\t\t\t\tandroidMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> +\t\t\t\tbreak;\n> +\t\t\tcase controls::android::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..1982509d 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::android::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,67 @@ 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::android::FaceDetectFaceRectangles);\n> +\tif (faceDetectRectangles) {\n> +\t\tconst Span<const Rectangle> rectangles = *faceDetectRectangles;\n\nYou can spare all these temporary Span<>, but the rest of the code\ngoes through temporaries too\n\nReviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n\nThanks\n  j\n\n\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::android::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> +\t\t}\n> +\t\tresultMetadata->addEntry(ANDROID_STATISTICS_FACE_SCORES, scores);\n> +\t}\n> +\n> +\tconst auto &faceDetectFaceLandmarks =\n> +\t\tmetadata.get(controls::android::FaceDetectFaceLandmarks);\n> +\tif (faceDetectRectangles && faceDetectFaceLandmarks) {\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::android::FaceDetectFaceIds);\n> +\tif (faceDetectRectangles && 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> +\t\t}\n> +\t\tresultMetadata->addEntry(ANDROID_STATISTICS_FACE_IDS, ids);\n> +\t}\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 D3A03C3257\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 24 Sep 2024 13:02:17 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 2296363502;\n\tTue, 24 Sep 2024 15:02:17 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 171F863500\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 24 Sep 2024 15:02:15 +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 9D8C8A8F;\n\tTue, 24 Sep 2024 15:00: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=\"KA7rQ5j4\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1727182847;\n\tbh=oXR53iHjMm/UI/EGMf68/3rebA+KQNVRpNalku2DND0=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=KA7rQ5j4Oimdq0E70M7MPO4djR2Sl7iYgx/eD4yRmc+bt/1+Uel4XZBifDgEaODZT\n\ttnyJSTQqYqjxXNANUK6bW+zCYTZBzVJZiAVz4CgMzqs8k6fLx9s16Of57P/TObvxRv\n\t10gvxPkCbdN9EYHRwnajHGscE9boRbUeUbrAKK6k=","Date":"Tue, 24 Sep 2024 15:02:11 +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 v7 3/3] libcamera: android: Add face detection control\n\tsupport","Message-ID":"<62zqg3qbct6xz5kni3soqeulbgitfiw3hl6rexbikpil4msux7@ulkxq3lwwsvq>","References":"<20240924110353.2025397-1-chenghaoyang@google.com>\n\t<20240924110353.2025397-4-chenghaoyang@google.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20240924110353.2025397-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":31352,"web_url":"https://patchwork.libcamera.org/comment/31352/","msgid":"<CAC=wSGXMLrQJuxycEtwWmui4h_evQ4F0yTjrdr7ZJR+BUA3OHA@mail.gmail.com>","date":"2024-09-25T08:16:13","subject":"Re: [PATCH v7 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":"Hi Jacopo,\n\nOn Tue, Sep 24, 2024 at 9:02 PM Jacopo Mondi\n<jacopo.mondi@ideasonboard.com> wrote:\n>\n> Hi Harvey\n>\n> On Tue, Sep 24, 2024 at 11:02: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       | 73 ++++++++++++++++++++++++++++-\n> >  2 files changed, 112 insertions(+), 6 deletions(-)\n> >\n> > diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp\n> > index 71043e12..d52d58ed 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> >                                 maxFrameDuration_);\n> >\n> >       /* Statistics static metadata. */\n> > -     uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> > -     staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> > -                               faceDetectMode);\n> > -\n> >       int32_t maxFaceCount = 0;\n> > +     auto iter = camera_->controls().find(controls::android::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::android::FaceDetectModeOff:\n> > +                             androidMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> > +                             break;\n> > +                     case controls::android::FaceDetectModeSimple:\n> > +                             androidMode = ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE;\n> > +                             hasFaceDetection = true;\n> > +                             break;\n> > +                     default:\n> > +                             LOG(HAL, Fatal) << \"Received invalid face 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> > +                             ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> > +                             faceDetectModes.data(), faceDetectModes.size());\n> > +             }\n> > +     } else {\n> > +             uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\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 b/src/android/camera_device.cpp\n> > index 493f66e7..1982509d 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> >               controls.set(controls::ScalerCrop, cropRegion);\n> >       }\n> >\n> > +     if (settings.getEntry(ANDROID_STATISTICS_FACE_DETECT_MODE, &entry)) {\n> > +             const uint8_t *data = entry.data.u8;\n> > +             controls.set(controls::android::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 = controls::draft::TestPatternModeOff;\n> > @@ -1540,8 +1547,9 @@ CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) cons\n> >       value32 = ANDROID_SENSOR_TEST_PATTERN_MODE_OFF;\n> >       resultMetadata->addEntry(ANDROID_SENSOR_TEST_PATTERN_MODE, value32);\n> >\n> > -     value = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> > -     resultMetadata->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE, 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,67 @@ CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) cons\n> >               resultMetadata->addEntry(ANDROID_SENSOR_FRAME_DURATION,\n> >                                        *frameDuration * 1000);\n> >\n> > +     const auto &faceDetectRectangles =\n> > +             metadata.get(controls::android::FaceDetectFaceRectangles);\n> > +     if (faceDetectRectangles) {\n> > +             const Span<const Rectangle> rectangles = *faceDetectRectangles;\n>\n> You can spare all these temporary Span<>, but the rest of the code\n> goes through temporaries too\n\nSure, removed the temporary variables.\n\n\n>\n> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n>\n> Thanks\n>   j\n>\n>\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, flatRectangles);\n> > +     }\n> > +\n> > +     const auto &faceDetectFaceScores =\n> > +             metadata.get(controls::android::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 of face scores; \"\n> > +                                     << \"Expected: \"\n> > +                                     << faceDetectRectangles->size()\n> > +                                     << \", got: \" << scores.size();\n> > +             }\n> > +             resultMetadata->addEntry(ANDROID_STATISTICS_FACE_SCORES, scores);\n> > +     }\n> > +\n> > +     const auto &faceDetectFaceLandmarks =\n> > +             metadata.get(controls::android::FaceDetectFaceLandmarks);\n> > +     if (faceDetectRectangles && faceDetectFaceLandmarks) {\n> > +             const auto &landmarks = *faceDetectFaceLandmarks;\n> > +             size_t expectedLandmarks = faceDetectRectangles->size() * 3;\n> > +             if (landmarks.size() != expectedLandmarks) {\n> > +                     LOG(HAL, Error) << \"Pipeline returned wrong number of face landmarks; \"\n> > +                                     << \"Expected: \" << 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, androidLandmarks);\n> > +     }\n> > +\n> > +     const auto &faceDetectFaceIds =\n> > +             metadata.get(controls::android::FaceDetectFaceIds);\n> > +     if (faceDetectRectangles && faceDetectFaceIds) {\n> > +             const Span<const int32_t> &ids = *faceDetectFaceIds;\n> > +             if (ids.size() != faceDetectRectangles->size()) {\n> > +                     LOG(HAL, Error) << \"Pipeline returned wrong number of face ids; \"\n> > +                                     << \"Expected: \"\n> > +                                     << faceDetectRectangles->size()\n> > +                                     << \", got: \" << ids.size();\n> > +             }\n> > +             resultMetadata->addEntry(ANDROID_STATISTICS_FACE_IDS, ids);\n> > +     }\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\n\n\n--\nBR,\nHarvey Yang","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 9E06AC0F1B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 25 Sep 2024 08:16:51 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 494FF6350F;\n\tWed, 25 Sep 2024 10:16:51 +0200 (CEST)","from mail-ed1-x530.google.com (mail-ed1-x530.google.com\n\t[IPv6:2a00:1450:4864:20::530])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 65448634F4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 25 Sep 2024 10:16:50 +0200 (CEST)","by mail-ed1-x530.google.com with SMTP id\n\t4fb4d7f45d1cf-5c247dd0899so15250a12.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 25 Sep 2024 01:16:50 -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=\"XgzYq3nu\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=google.com; s=20230601; t=1727252210; x=1727857010;\n\tdarn=lists.libcamera.org; \n\th=content-transfer-encoding:cc:to:subject:message-id:date:from\n\t:in-reply-to:references:mime-version:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=ApRTVmDEkU9l4Z/sSjzveisC5qG2kNb00zq4jvuvEq4=;\n\tb=XgzYq3nuCHSQJR+EolVfHW1mJZG1yZr2B6zG2fidCk9psCC9nP8M19WOE39LOKvnD/\n\tQRDvW1xcLiezzfhqzOFmloVR0iBf0W87G1xbBnXlxownvbTZM5JDjFj3h3y7+gruRHAj\n\tvHKuGrC4Uc7yz3xKH3H3JRhnFexPogLVQmW0mFBRop7J69Bs+QICERlczEmVLFdnblzb\n\tIeyyKr3aKwjsyf7lJju6IB+O0pdUM0+1rEXbieK1pqMRI2UJnZSSDmPmfiDcPYNQ7xuZ\n\tR/tTTjHC9huwxgPVN/TrbRK+a8Ai0ab0VwspxmltpC0ZWC0oUYXYooTeJ/nwKrqQTjN9\n\tiiWQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1727252210; x=1727857010;\n\th=content-transfer-encoding:cc:to:subject:message-id:date:from\n\t:in-reply-to:references:mime-version:x-gm-message-state:from:to:cc\n\t:subject:date:message-id:reply-to;\n\tbh=ApRTVmDEkU9l4Z/sSjzveisC5qG2kNb00zq4jvuvEq4=;\n\tb=c3B4HOhRsxfL0H1h41kKfj6PnhB1xmQaF5l2zXIuFmEWHB/NRCv/OTeQhkeHlrI8qr\n\t6OdnjZGwMQs1WT/RsjJN7+n/4ZMIM2ylmmvLXmrruLOLqINp1CRBNXPOuLbdXZJNzfU/\n\tPdnTgIEEqrVdoCXigQaRULJNF490/RDP+wy+f58A5vdghFCTIGxVyRotuDAZ5tQgIAEO\n\tSQ/i3/R1+pJj4sSHo/nUqwTb122lKW5XPzV5Pqj1DjBGSabm9+tCOqv58GzTkV5QlFpU\n\tdRsGZlsag2v3copYBKTqngIaxgc66S3UfUuUG5hNjFEmn/ZiD/nsKv29UQouIpmFmlC/\n\tTrJA==","X-Forwarded-Encrypted":"i=1;\n\tAJvYcCXgoL4iCc6FwOKRYPBLAng81H2J+g7/RXuuODPm3eSA/NgmJGNoHPdQavzxfTsoi3eElD2of8CUzLzIy1aAy9c=@lists.libcamera.org","X-Gm-Message-State":"AOJu0Yx6IleLBCpzO2eLslo/whIYsm2+gk4fOXOs42fcmqq3+CUj+hMz\n\tV0ow6f25QJbkaj0VEeG9T0BDUJ9XUbSEIziJjJfqVlM8sjU92M8piRYr9y8llyINhz/zRwDl4qw\n\ti+iUlCHaoXdInIWAyKUmiP85sO8+WIQxyrGIz","X-Google-Smtp-Source":"AGHT+IE4MpEf3ZcYKa6FYIHDKTJgj1rZkBzSpBhDYjbcmmZT33PIwyQtrwOzU9jCGheg/oV6FV/QJQsirDc3GcAGJjc=","X-Received":"by 2002:a05:6402:5112:b0:5be:9bb0:1189 with SMTP id\n\t4fb4d7f45d1cf-5c720f8e26fmr270994a12.2.1727252209516; Wed, 25 Sep 2024\n\t01:16:49 -0700 (PDT)","MIME-Version":"1.0","References":"<20240924110353.2025397-1-chenghaoyang@google.com>\n\t<20240924110353.2025397-4-chenghaoyang@google.com>\n\t<62zqg3qbct6xz5kni3soqeulbgitfiw3hl6rexbikpil4msux7@ulkxq3lwwsvq>","In-Reply-To":"<62zqg3qbct6xz5kni3soqeulbgitfiw3hl6rexbikpil4msux7@ulkxq3lwwsvq>","From":"Cheng-Hao Yang <chenghaoyang@google.com>","Date":"Wed, 25 Sep 2024 16:16:13 +0800","Message-ID":"<CAC=wSGXMLrQJuxycEtwWmui4h_evQ4F0yTjrdr7ZJR+BUA3OHA@mail.gmail.com>","Subject":"Re: [PATCH v7 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":"text/plain; charset=\"UTF-8\"","Content-Transfer-Encoding":"quoted-printable","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>"}}]