From patchwork Thu Nov 11 10:49:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hanlin Chen X-Patchwork-Id: 14547 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id CE8C2BDB1C for ; Thu, 11 Nov 2021 10:49:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7CCB06035D; Thu, 11 Nov 2021 11:49:34 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="KHjzFO1+"; dkim-atps=neutral Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3A0DB60369 for ; Thu, 11 Nov 2021 11:49:33 +0100 (CET) Received: by mail-pj1-x1032.google.com with SMTP id x7so3832805pjn.0 for ; Thu, 11 Nov 2021 02:49:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=79aUadBtYlR09ShcgbybPJ7j1L4UXmL3pC0j4+AsB4Y=; b=KHjzFO1+egAxmxcSOEtxT0fTrNxgi6FgwvH72GxZAenZVAp9GiUv/KCYmnOX7Cw2Eo VjiAeYSYM2uT7RWCsQJbqeLlNKDL6ziUXwOXNzRlo1Ejpdw0dJxUp3rO9K3Qo9X3DBGl dboZuyVttsqwFn/4vzCF/foF5OQIU3B4h1kiw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=79aUadBtYlR09ShcgbybPJ7j1L4UXmL3pC0j4+AsB4Y=; b=SjK9np4wbQJClDlwUpvgZM25W2w+tsGjIBV3ZRlXvygMlYgk1pjdBp0fQ7CVhEDzRB p0+v7F71FqZwQ9dWZOkaE2wMzt7r7keRAJI2V1RJlJrunW/yXrEgph34PaBFiQTaQpgJ yUzCxfkS+1dcxj8GakzU9+2/8w0NRyOLm28xL8Nra6T45uOmIlfeP+UE0k5ghgE0umrI dcxRpCCEq9mYJjrW2flW7mwFFx3dleGjJdpiDNMLBeGt3WYpVLQWTQktOTTetzy8QZlN pKFNDIknOZJ/9s1+PkGO+rDQszLXcWYbDpcNwPTJI4Nqx64IWGt0dy2jGLuA5JcOcbkh 2tbg== X-Gm-Message-State: AOAM5333O7iC07j1ThIpCt4iI50pikjsOKEesMvuhfLisFDjOPpgSguz 1Y+rQE0GVbI0G/5dVZn6afolpovQvjuZlg== X-Google-Smtp-Source: ABdhPJycg9H7J2aNpa7+OLnfSdMx8AgtACW+juCDqshGpCxyaAbE/WHYAV8nFNMDCVWV9OGfzWbQ7g== X-Received: by 2002:a17:90b:4f86:: with SMTP id qe6mr7225147pjb.198.1636627771348; Thu, 11 Nov 2021 02:49:31 -0800 (PST) Received: from localhost ([2401:fa00:1:10:3925:da9c:3049:be7a]) by smtp.gmail.com with UTF8SMTPSA id x14sm2217514pjl.27.2021.11.11.02.49.30 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 11 Nov 2021 02:49:31 -0800 (PST) From: Han-Lin Chen To: libcamera-devel@lists.libcamera.org Date: Thu, 11 Nov 2021 18:49:04 +0800 Message-Id: <20211111104908.295992-3-hanlinchen@chromium.org> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog In-Reply-To: <20211111104908.295992-1-hanlinchen@chromium.org> References: <20211111104908.295992-1-hanlinchen@chromium.org> MIME-Version: 1.0 Subject: [libcamera-devel] [IPU3-IPA PATCH v3 2/6] ipu3: Add a class AiqResultsRingBuffer to reserve AiqResults history X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The AIQ algorithm expects the statstistics comes with the effective AiqResults applied on the sensor, which may not always be the latest AiqResults, since pipeline handler may delay setting the controls based on SOF. Add a class to reserve the history of the AiqResults generated for previous frames, so IPA can have a chance to look for the suitable one backwards. In details, the patch adds following to AiqResult Class. - Make the parameters to setXXX() functions const. - Implement copy constructors - Implement a RingBuffer to maintain AiqResults History Signed-off-by: Han-Lin Chen Reviewed-by: Kieran Bingham --- aiq/aiq_results.cpp | 90 +++++++++++++++++++++++++++++++++++++++++---- aiq/aiq_results.h | 43 ++++++++++++++++++---- 2 files changed, 117 insertions(+), 16 deletions(-) diff --git a/aiq/aiq_results.cpp b/aiq/aiq_results.cpp index f727f36..befcf7a 100644 --- a/aiq/aiq_results.cpp +++ b/aiq/aiq_results.cpp @@ -63,7 +63,34 @@ AiqResults::AiqResults() sa_.channel_b = channelB_.data(); } -void AiqResults::setAe(ia_aiq_ae_results *ae) +AiqResults::AiqResults(const AiqResults &other) + :AiqResults() +{ + setAe(&other.ae_); + setAf(&other.af_); + setAfBracket(&other.afBracket_); + setAwb(&other.awb_); + setGbce(&other.gbce_); + setDetectedSceneMode(other.detectedSceneMode_); + setPa(&other.pa_); + setSa(&other.sa_); +} + +AiqResults& AiqResults::operator=(const AiqResults &other) +{ + setAe(&other.ae_); + setAf(&other.af_); + setAfBracket(&other.afBracket_); + setAwb(&other.awb_); + setGbce(&other.gbce_); + setDetectedSceneMode(other.detectedSceneMode_); + setPa(&other.pa_); + setSa(&other.sa_); + + return *this; +} + +void AiqResults::setAe(const ia_aiq_ae_results *ae) { /* Todo: Potentially Requires copying * ia_aiq_aperture_control *aperture_control; @@ -121,7 +148,7 @@ void AiqResults::setAe(ia_aiq_ae_results *ae) } } -void AiqResults::setAf(ia_aiq_af_results *af) +void AiqResults::setAf(const ia_aiq_af_results *af) { ASSERT(af); @@ -133,7 +160,7 @@ void AiqResults::setAf(ia_aiq_af_results *af) af_.final_lens_position_reached = af->final_lens_position_reached; } -void AiqResults::setAfBracket(ia_aiq_af_bracket_results *afBracket) +void AiqResults::setAfBracket(const ia_aiq_af_bracket_results *afBracket) { ASSERT(afBracket); @@ -145,7 +172,7 @@ void AiqResults::setAfBracket(ia_aiq_af_bracket_results *afBracket) afBracket_.lens_positions_bracketing = afBracket->lens_positions_bracketing; } -void AiqResults::setAwb(ia_aiq_awb_results *awb) +void AiqResults::setAwb(const ia_aiq_awb_results *awb) { ASSERT(awb); @@ -157,7 +184,7 @@ void AiqResults::setAwb(ia_aiq_awb_results *awb) awb_.distance_from_convergence = awb->distance_from_convergence; } -void AiqResults::setGbce(ia_aiq_gbce_results *gbce) +void AiqResults::setGbce(const ia_aiq_gbce_results *gbce) { ASSERT(gbce); @@ -181,12 +208,12 @@ void AiqResults::setGbce(ia_aiq_gbce_results *gbce) } } -void AiqResults::setDetectedSceneMode(ia_aiq_scene_mode dsm) +void AiqResults::setDetectedSceneMode(const ia_aiq_scene_mode dsm) { detectedSceneMode_ = dsm; } -void AiqResults::setPa(ia_aiq_pa_results *pa) +void AiqResults::setPa(const ia_aiq_pa_results *pa) { ASSERT(pa); @@ -234,7 +261,7 @@ void AiqResults::setPa(ia_aiq_pa_results *pa) pa_.brightness_level = pa->brightness_level; } -void AiqResults::setSa(ia_aiq_sa_results *sa) +void AiqResults::setSa(const ia_aiq_sa_results *sa) { ASSERT(sa && sa->channel_r && sa->channel_gr && sa->channel_gb && sa->channel_b); @@ -275,6 +302,53 @@ void AiqResults::setSa(ia_aiq_sa_results *sa) sa_.frame_params = sa->frame_params; } +AiqResults& AiqResultsRingBuffer::operator[](unsigned int index) +{ + return std::array::operator[](index % bufferSize); +} + +const AiqResults& AiqResultsRingBuffer::operator[](unsigned int index) const +{ + return std::array::operator[](index % bufferSize); +} + +void AiqResultsRingBuffer::reset() +{ + start_ = end_ = size_ = 0; +} + +void AiqResultsRingBuffer::extendOne() +{ + end_ = (end_ + 1) % bufferSize; + size_ = std::min(size_ + 1, bufferSize); + if (size_ == bufferSize) { + start_ = end_; + } +} + +AiqResults& AiqResultsRingBuffer::latest() +{ + unsigned int i = (end_ + bufferSize - 1) % bufferSize; + return operator[](i); +} + +AiqResults& AiqResultsRingBuffer::searchBackward( + const std::function pred, AiqResults& def) +{ + if (size_ == 0) + return def; + + unsigned int i = (end_ + bufferSize - 1) % bufferSize; + while (i != start_) { + if (pred(operator[](i))) { + return operator[](i); + } + i = (i + bufferSize - 1) % bufferSize; + } + + return def; +} + } /* namespace ipa::ipu3::aiq */ } /* namespace libcamera */ diff --git a/aiq/aiq_results.h b/aiq/aiq_results.h index ae19a6c..8c95852 100644 --- a/aiq/aiq_results.h +++ b/aiq/aiq_results.h @@ -8,6 +8,8 @@ * of the aiq result structures. */ +#include +#include #include #include @@ -37,6 +39,10 @@ class AiqResults { public: AiqResults(); + AiqResults(const AiqResults &other); + AiqResults &operator=(const AiqResults &other); + AiqResults(const AiqResults &&other) = delete; + AiqResults &operator=(const AiqResults &&other) = delete; const ia_aiq_ae_results *ae() { return &ae_; } ia_aiq_af_results *af() { return &af_; } @@ -46,14 +52,14 @@ public: const ia_aiq_pa_results *pa() { return &pa_; } const ia_aiq_sa_results *sa() { return &sa_; } - void setAe(ia_aiq_ae_results *ae); - void setAf(ia_aiq_af_results *af); - void setAfBracket(ia_aiq_af_bracket_results *afBracket); - void setAwb(ia_aiq_awb_results *awb); - void setGbce(ia_aiq_gbce_results *gbce); - void setDetectedSceneMode(ia_aiq_scene_mode dsm); - void setPa(ia_aiq_pa_results *pa); - void setSa(ia_aiq_sa_results *sa); + void setAe(const ia_aiq_ae_results *ae); + void setAf(const ia_aiq_af_results *af); + void setAfBracket(const ia_aiq_af_bracket_results *afBracket); + void setAwb(const ia_aiq_awb_results *awb); + void setGbce(const ia_aiq_gbce_results *gbce); + void setDetectedSceneMode(const ia_aiq_scene_mode dsm); + void setPa(const ia_aiq_pa_results *pa); + void setSa(const ia_aiq_sa_results *sa); private: ia_aiq_ae_results ae_; @@ -109,6 +115,27 @@ private: std::vector channelGb_; }; +static constexpr unsigned int bufferSize = 16; +class AiqResultsRingBuffer: public std::array +{ +public: + AiqResults &operator[](unsigned int index); + const AiqResults &operator[](unsigned int index) const; + void reset(); + void extendOne(); + AiqResults& latest(); + unsigned int size() { return size_; } + AiqResults& searchBackward(const std::function pred, + AiqResults& def); + +private: + void incrementSize(); + + unsigned int start_ = 0; + unsigned int end_ = 0; + unsigned int size_ = 0; +}; + } /* namespace libcamera::ipa::ipu3::aiq */ #endif /* IPA_IPU3_AIQ_RESULTS_H */