From patchwork Mon Oct 24 00:03:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17664 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 CDF7CBDB16 for ; Mon, 24 Oct 2022 00:04:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A30C062ED4; Mon, 24 Oct 2022 02:04:24 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1666569864; bh=vgw+hsZqZ1Sox8PqtwxEJBX1S5VSzB6m7IptRVqtDbg=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=Er3RzuO99oPSDiTF2DMso8UVo/S9RGYHG8OHtJZn9AA579OBTl6nTqmIQ0AQM4Zp9 bW0EWLJ8rBGpaLfL2OcHgp4v3hJJzdu4SeKv0uJkZ6EHFIppNgH2GHQ2gmTqht+yJf 7RbkxFkPuZlMHGYqWiZQqp60weSODND13B/3gMK9rB5Za0WiLnM131SFt4zyuN9KWW mN7QrGpwMYkTUBiQPWSzxF6r0/fSkyUGkNGPBl25/mSMFJtcoTy6T/GHfUmDMjdF3/ PEmdQxu52JTjBzyvkWBAgCl4Vb2kb/zimwamHG4DOwMDu+62eHFIocD31L0culPO4T KGWxekRv1dkVQ== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2309D62EA6 for ; Mon, 24 Oct 2022 02:04:23 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Uv+st2HS"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 99E24471; Mon, 24 Oct 2022 02:04:22 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1666569862; bh=vgw+hsZqZ1Sox8PqtwxEJBX1S5VSzB6m7IptRVqtDbg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Uv+st2HSKwaPsQmKLQgex1lPXmkahm+h5sTUqlRUNFdLcGD0DGIAwYTV+jNAOExKu 9ctGo8x4pV4sAUrtQNXB2sJUnfaLHjJo3SCBd0k6+GShu4doxSLoEjyS+eonlXfycO CCJeBkiMKmOTORqK7I2BMlEabeJZARGuUJdKnCzw= To: libcamera-devel@lists.libcamera.org Date: Mon, 24 Oct 2022 03:03:44 +0300 Message-Id: <20221024000356.29521-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.37.4 In-Reply-To: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> References: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 01/13] ipa: Sort algorithm operations based on calling order 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: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Reorder functions in the base ipa::Algorithm and its derived classes to match the calling order: queueRequest(), prepare() and process(). This makes the code flow easier to read. No functional change intended. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Jacopo Mondi --- src/ipa/ipu3/algorithms/af.cpp | 32 +++--- src/ipa/ipu3/algorithms/awb.cpp | 166 +++++++++++++++--------------- src/ipa/libipa/algorithm.cpp | 34 +++--- src/ipa/libipa/algorithm.h | 14 +-- src/ipa/rkisp1/algorithms/agc.cpp | 80 +++++++------- src/ipa/rkisp1/algorithms/awb.cpp | 94 ++++++++--------- src/ipa/rkisp1/algorithms/awb.h | 6 +- 7 files changed, 213 insertions(+), 213 deletions(-) diff --git a/src/ipa/ipu3/algorithms/af.cpp b/src/ipa/ipu3/algorithms/af.cpp index 5a0452a5719b..12927eecf613 100644 --- a/src/ipa/ipu3/algorithms/af.cpp +++ b/src/ipa/ipu3/algorithms/af.cpp @@ -113,22 +113,6 @@ Af::Af() { } -/** - * \copydoc libcamera::ipa::Algorithm::prepare - */ -void Af::prepare(IPAContext &context, - [[maybe_unused]] const uint32_t frame, - [[maybe_unused]] IPAFrameContext &frameContext, - ipu3_uapi_params *params) -{ - const struct ipu3_uapi_grid_config &grid = context.configuration.af.afGrid; - params->acc_param.af.grid_cfg = grid; - params->acc_param.af.filter_config = afFilterConfigDefault; - - /* Enable AF processing block */ - params->use.acc_af = 1; -} - /** * \brief Configure the Af given a configInfo * \param[in] context The shared IPA context @@ -197,6 +181,22 @@ int Af::configure(IPAContext &context, const IPAConfigInfo &configInfo) return 0; } +/** + * \copydoc libcamera::ipa::Algorithm::prepare + */ +void Af::prepare(IPAContext &context, + [[maybe_unused]] const uint32_t frame, + [[maybe_unused]] IPAFrameContext &frameContext, + ipu3_uapi_params *params) +{ + const struct ipu3_uapi_grid_config &grid = context.configuration.af.afGrid; + params->acc_param.af.grid_cfg = grid; + params->acc_param.af.filter_config = afFilterConfigDefault; + + /* Enable AF processing block */ + params->use.acc_af = 1; +} + /** * \brief AF coarse scan * \param[in] context The shared IPA context diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp index dd7ebc07c534..5abd46215833 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -218,6 +218,89 @@ int Awb::configure(IPAContext &context, return 0; } +constexpr uint16_t Awb::threshold(float value) +{ + /* AWB thresholds are in the range [0, 8191] */ + return value * 8191; +} + +constexpr uint16_t Awb::gainValue(double gain) +{ + /* + * The colour gains applied by the BNR for the four channels (Gr, R, B + * and Gb) are expressed in the parameters structure as 16-bit integers + * that store a fixed-point U3.13 value in the range [0, 8[. + * + * The real gain value is equal to the gain parameter plus one, i.e. + * + * Pout = Pin * (1 + gain / 8192) + * + * where 'Pin' is the input pixel value, 'Pout' the output pixel value, + * and 'gain' the gain in the parameters structure as a 16-bit integer. + */ + return std::clamp((gain - 1.0) * 8192, 0.0, 65535.0); +} + +/** + * \copydoc libcamera::ipa::Algorithm::prepare + */ +void Awb::prepare(IPAContext &context, + [[maybe_unused]] const uint32_t frame, + [[maybe_unused]] IPAFrameContext &frameContext, + ipu3_uapi_params *params) +{ + /* + * Green saturation thresholds are reduced because we are using the + * green channel only in the exposure computation. + */ + params->acc_param.awb.config.rgbs_thr_r = threshold(1.0); + params->acc_param.awb.config.rgbs_thr_gr = threshold(0.9); + params->acc_param.awb.config.rgbs_thr_gb = threshold(0.9); + params->acc_param.awb.config.rgbs_thr_b = threshold(1.0); + + /* + * Enable saturation inclusion on thr_b for ImgU to update the + * ipu3_uapi_awb_set_item->sat_ratio field. + */ + params->acc_param.awb.config.rgbs_thr_b |= IPU3_UAPI_AWB_RGBS_THR_B_INCL_SAT | + IPU3_UAPI_AWB_RGBS_THR_B_EN; + + const ipu3_uapi_grid_config &grid = context.configuration.grid.bdsGrid; + + params->acc_param.awb.config.grid = context.configuration.grid.bdsGrid; + + /* + * Optical center is column start (respectively row start) of the + * cell of interest minus its X center (respectively Y center). + * + * For the moment use BDS as a first approximation, but it should + * be calculated based on Shading (SHD) parameters. + */ + params->acc_param.bnr = imguCssBnrDefaults; + Size &bdsOutputSize = context.configuration.grid.bdsOutputSize; + params->acc_param.bnr.column_size = bdsOutputSize.width; + params->acc_param.bnr.opt_center.x_reset = grid.x_start - (bdsOutputSize.width / 2); + params->acc_param.bnr.opt_center.y_reset = grid.y_start - (bdsOutputSize.height / 2); + params->acc_param.bnr.opt_center_sqr.x_sqr_reset = params->acc_param.bnr.opt_center.x_reset + * params->acc_param.bnr.opt_center.x_reset; + params->acc_param.bnr.opt_center_sqr.y_sqr_reset = params->acc_param.bnr.opt_center.y_reset + * params->acc_param.bnr.opt_center.y_reset; + + params->acc_param.bnr.wb_gains.gr = gainValue(context.activeState.awb.gains.green); + params->acc_param.bnr.wb_gains.r = gainValue(context.activeState.awb.gains.red); + params->acc_param.bnr.wb_gains.b = gainValue(context.activeState.awb.gains.blue); + params->acc_param.bnr.wb_gains.gb = gainValue(context.activeState.awb.gains.green); + + LOG(IPU3Awb, Debug) << "Color temperature estimated: " << asyncResults_.temperatureK; + + /* The CCM matrix may change when color temperature will be used */ + params->acc_param.ccm = imguCssCcmDefault; + + params->use.acc_awb = 1; + params->use.acc_bnr = 1; + params->use.acc_ccm = 1; +} + /** * The function estimates the correlated color temperature using * from RGB color space input. @@ -415,89 +498,6 @@ void Awb::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, context.activeState.awb.temperatureK); } -constexpr uint16_t Awb::threshold(float value) -{ - /* AWB thresholds are in the range [0, 8191] */ - return value * 8191; -} - -constexpr uint16_t Awb::gainValue(double gain) -{ - /* - * The colour gains applied by the BNR for the four channels (Gr, R, B - * and Gb) are expressed in the parameters structure as 16-bit integers - * that store a fixed-point U3.13 value in the range [0, 8[. - * - * The real gain value is equal to the gain parameter plus one, i.e. - * - * Pout = Pin * (1 + gain / 8192) - * - * where 'Pin' is the input pixel value, 'Pout' the output pixel value, - * and 'gain' the gain in the parameters structure as a 16-bit integer. - */ - return std::clamp((gain - 1.0) * 8192, 0.0, 65535.0); -} - -/** - * \copydoc libcamera::ipa::Algorithm::prepare - */ -void Awb::prepare(IPAContext &context, - [[maybe_unused]] const uint32_t frame, - [[maybe_unused]] IPAFrameContext &frameContext, - ipu3_uapi_params *params) -{ - /* - * Green saturation thresholds are reduced because we are using the - * green channel only in the exposure computation. - */ - params->acc_param.awb.config.rgbs_thr_r = threshold(1.0); - params->acc_param.awb.config.rgbs_thr_gr = threshold(0.9); - params->acc_param.awb.config.rgbs_thr_gb = threshold(0.9); - params->acc_param.awb.config.rgbs_thr_b = threshold(1.0); - - /* - * Enable saturation inclusion on thr_b for ImgU to update the - * ipu3_uapi_awb_set_item->sat_ratio field. - */ - params->acc_param.awb.config.rgbs_thr_b |= IPU3_UAPI_AWB_RGBS_THR_B_INCL_SAT | - IPU3_UAPI_AWB_RGBS_THR_B_EN; - - const ipu3_uapi_grid_config &grid = context.configuration.grid.bdsGrid; - - params->acc_param.awb.config.grid = context.configuration.grid.bdsGrid; - - /* - * Optical center is column start (respectively row start) of the - * cell of interest minus its X center (respectively Y center). - * - * For the moment use BDS as a first approximation, but it should - * be calculated based on Shading (SHD) parameters. - */ - params->acc_param.bnr = imguCssBnrDefaults; - Size &bdsOutputSize = context.configuration.grid.bdsOutputSize; - params->acc_param.bnr.column_size = bdsOutputSize.width; - params->acc_param.bnr.opt_center.x_reset = grid.x_start - (bdsOutputSize.width / 2); - params->acc_param.bnr.opt_center.y_reset = grid.y_start - (bdsOutputSize.height / 2); - params->acc_param.bnr.opt_center_sqr.x_sqr_reset = params->acc_param.bnr.opt_center.x_reset - * params->acc_param.bnr.opt_center.x_reset; - params->acc_param.bnr.opt_center_sqr.y_sqr_reset = params->acc_param.bnr.opt_center.y_reset - * params->acc_param.bnr.opt_center.y_reset; - - params->acc_param.bnr.wb_gains.gr = gainValue(context.activeState.awb.gains.green); - params->acc_param.bnr.wb_gains.r = gainValue(context.activeState.awb.gains.red); - params->acc_param.bnr.wb_gains.b = gainValue(context.activeState.awb.gains.blue); - params->acc_param.bnr.wb_gains.gb = gainValue(context.activeState.awb.gains.green); - - LOG(IPU3Awb, Debug) << "Color temperature estimated: " << asyncResults_.temperatureK; - - /* The CCM matrix may change when color temperature will be used */ - params->acc_param.ccm = imguCssCcmDefault; - - params->use.acc_awb = 1; - params->use.acc_bnr = 1; - params->use.acc_ccm = 1; -} - REGISTER_IPA_ALGORITHM(Awb, "Awb") } /* namespace ipa::ipu3::algorithms */ diff --git a/src/ipa/libipa/algorithm.cpp b/src/ipa/libipa/algorithm.cpp index 71f583840a5a..bc1c29a6dbcc 100644 --- a/src/ipa/libipa/algorithm.cpp +++ b/src/ipa/libipa/algorithm.cpp @@ -66,23 +66,6 @@ namespace ipa { * \return 0 if successful, an error code otherwise */ -/** - * \fn Algorithm::prepare() - * \brief Fill the \a params buffer with ISP processing parameters for a frame - * \param[in] context The shared IPA context - * \param[in] frame The frame context sequence number - * \param[in] frameContext The FrameContext for this frame - * \param[out] params The ISP specific parameters - * - * This function is called for every frame when the camera is running before it - * is processed by the ISP to prepare the ISP processing parameters for that - * frame. - * - * Algorithms shall fill in the parameter structure fields appropriately to - * configure the ISP processing blocks that they are responsible for. This - * includes setting fields and flags that enable those processing blocks. - */ - /** * \fn Algorithm::queueRequest() * \brief Provide control values to the algorithm @@ -100,6 +83,23 @@ namespace ipa { * use during frame processing. */ +/** + * \fn Algorithm::prepare() + * \brief Fill the \a params buffer with ISP processing parameters for a frame + * \param[in] context The shared IPA context + * \param[in] frame The frame context sequence number + * \param[in] frameContext The FrameContext for this frame + * \param[out] params The ISP specific parameters + * + * This function is called for every frame when the camera is running before it + * is processed by the ISP to prepare the ISP processing parameters for that + * frame. + * + * Algorithms shall fill in the parameter structure fields appropriately to + * configure the ISP processing blocks that they are responsible for. This + * includes setting fields and flags that enable those processing blocks. + */ + /** * \fn Algorithm::process() * \brief Process ISP statistics, and run algorithm operations diff --git a/src/ipa/libipa/algorithm.h b/src/ipa/libipa/algorithm.h index 38b3231c5d0e..987e3e4ce777 100644 --- a/src/ipa/libipa/algorithm.h +++ b/src/ipa/libipa/algorithm.h @@ -38,13 +38,6 @@ public: return 0; } - virtual void prepare([[maybe_unused]] typename Module::Context &context, - [[maybe_unused]] const uint32_t frame, - [[maybe_unused]] typename Module::FrameContext &frameContext, - [[maybe_unused]] typename Module::Params *params) - { - } - virtual void queueRequest([[maybe_unused]] typename Module::Context &context, [[maybe_unused]] const uint32_t frame, [[maybe_unused]] typename Module::FrameContext &frameContext, @@ -52,6 +45,13 @@ public: { } + virtual void prepare([[maybe_unused]] typename Module::Context &context, + [[maybe_unused]] const uint32_t frame, + [[maybe_unused]] typename Module::FrameContext &frameContext, + [[maybe_unused]] typename Module::Params *params) + { + } + virtual void process([[maybe_unused]] typename Module::Context &context, [[maybe_unused]] const uint32_t frame, [[maybe_unused]] typename Module::FrameContext &frameContext, diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index a06e9f732a8f..3fcbfa608467 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -107,6 +107,46 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) return 0; } +/** + * \copydoc libcamera::ipa::Algorithm::prepare + */ +void Agc::prepare(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, rkisp1_params_cfg *params) +{ + frameContext.agc.exposure = context.activeState.agc.exposure; + frameContext.agc.gain = context.activeState.agc.gain; + + if (frame > 0) + return; + + /* Configure the measurement window. */ + params->meas.aec_config.meas_window = context.configuration.agc.measureWindow; + /* Use a continuous method for measure. */ + params->meas.aec_config.autostop = RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP_0; + /* Estimate Y as (R + G + B) x (85/256). */ + params->meas.aec_config.mode = RKISP1_CIF_ISP_EXP_MEASURING_MODE_1; + + params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_AEC; + params->module_ens |= RKISP1_CIF_ISP_MODULE_AEC; + params->module_en_update |= RKISP1_CIF_ISP_MODULE_AEC; + + /* Configure histogram. */ + params->meas.hst_config.meas_window = context.configuration.agc.measureWindow; + /* Produce the luminance histogram. */ + params->meas.hst_config.mode = RKISP1_CIF_ISP_HISTOGRAM_MODE_Y_HISTOGRAM; + /* Set an average weighted histogram. */ + for (unsigned int histBin = 0; histBin < numHistBins_; histBin++) + params->meas.hst_config.hist_weight[histBin] = 1; + /* Step size can't be less than 3. */ + params->meas.hst_config.histogram_predivider = 4; + + /* Update the configuration for histogram. */ + params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_HST; + /* Enable the histogram measure unit. */ + params->module_ens |= RKISP1_CIF_ISP_MODULE_HST; + params->module_en_update |= RKISP1_CIF_ISP_MODULE_HST; +} + /** * \brief Apply a filter on the exposure value to limit the speed of changes * \param[in] exposureValue The target exposure from the AGC algorithm @@ -348,46 +388,6 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, metadata.set(controls::FrameDuration, frameDuration.get()); } -/** - * \copydoc libcamera::ipa::Algorithm::prepare - */ -void Agc::prepare(IPAContext &context, const uint32_t frame, - IPAFrameContext &frameContext, rkisp1_params_cfg *params) -{ - frameContext.agc.exposure = context.activeState.agc.exposure; - frameContext.agc.gain = context.activeState.agc.gain; - - if (frame > 0) - return; - - /* Configure the measurement window. */ - params->meas.aec_config.meas_window = context.configuration.agc.measureWindow; - /* Use a continuous method for measure. */ - params->meas.aec_config.autostop = RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP_0; - /* Estimate Y as (R + G + B) x (85/256). */ - params->meas.aec_config.mode = RKISP1_CIF_ISP_EXP_MEASURING_MODE_1; - - params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_AEC; - params->module_ens |= RKISP1_CIF_ISP_MODULE_AEC; - params->module_en_update |= RKISP1_CIF_ISP_MODULE_AEC; - - /* Configure histogram. */ - params->meas.hst_config.meas_window = context.configuration.agc.measureWindow; - /* Produce the luminance histogram. */ - params->meas.hst_config.mode = RKISP1_CIF_ISP_HISTOGRAM_MODE_Y_HISTOGRAM; - /* Set an average weighted histogram. */ - for (unsigned int histBin = 0; histBin < numHistBins_; histBin++) - params->meas.hst_config.hist_weight[histBin] = 1; - /* Step size can't be less than 3. */ - params->meas.hst_config.histogram_predivider = 4; - - /* Update the configuration for histogram. */ - params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_HST; - /* Enable the histogram measure unit. */ - params->module_ens |= RKISP1_CIF_ISP_MODULE_HST; - params->module_en_update |= RKISP1_CIF_ISP_MODULE_HST; -} - REGISTER_IPA_ALGORITHM(Agc, "Agc") } /* namespace ipa::rkisp1::algorithms */ diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp index 083c2d982c52..744f4a386c1a 100644 --- a/src/ipa/rkisp1/algorithms/awb.cpp +++ b/src/ipa/rkisp1/algorithms/awb.cpp @@ -67,20 +67,41 @@ int Awb::configure(IPAContext &context, return 0; } -uint32_t Awb::estimateCCT(double red, double green, double blue) +/** + * \copydoc libcamera::ipa::Algorithm::queueRequest + */ +void Awb::queueRequest(IPAContext &context, + [[maybe_unused]] const uint32_t frame, + IPAFrameContext &frameContext, + const ControlList &controls) { - /* Convert the RGB values to CIE tristimulus values (XYZ) */ - double X = (-0.14282) * (red) + (1.54924) * (green) + (-0.95641) * (blue); - double Y = (-0.32466) * (red) + (1.57837) * (green) + (-0.73191) * (blue); - double Z = (-0.68202) * (red) + (0.77073) * (green) + (0.56332) * (blue); - - /* Calculate the normalized chromaticity values */ - double x = X / (X + Y + Z); - double y = Y / (X + Y + Z); - - /* Calculate CCT */ - double n = (x - 0.3320) / (0.1858 - y); - return 449 * n * n * n + 3525 * n * n + 6823.3 * n + 5520.33; + auto &awb = context.activeState.awb; + + const auto &awbEnable = controls.get(controls::AwbEnable); + if (awbEnable && *awbEnable != awb.autoEnabled) { + awb.autoEnabled = *awbEnable; + + LOG(RkISP1Awb, Debug) + << (*awbEnable ? "Enabling" : "Disabling") << " AWB"; + } + + const auto &colourGains = controls.get(controls::ColourGains); + if (colourGains && !awb.autoEnabled) { + awb.gains.manual.red = (*colourGains)[0]; + awb.gains.manual.blue = (*colourGains)[1]; + + LOG(RkISP1Awb, Debug) + << "Set colour gains to red: " << awb.gains.manual.red + << ", blue: " << awb.gains.manual.blue; + } + + frameContext.awb.autoEnabled = awb.autoEnabled; + + if (!awb.autoEnabled) { + frameContext.awb.gains.red = awb.gains.manual.red; + frameContext.awb.gains.green = 1.0; + frameContext.awb.gains.blue = awb.gains.manual.blue; + } } /** @@ -165,41 +186,20 @@ void Awb::prepare(IPAContext &context, const uint32_t frame, params->module_ens |= RKISP1_CIF_ISP_MODULE_AWB; } -/** - * \copydoc libcamera::ipa::Algorithm::queueRequest - */ -void Awb::queueRequest(IPAContext &context, - [[maybe_unused]] const uint32_t frame, - IPAFrameContext &frameContext, - const ControlList &controls) +uint32_t Awb::estimateCCT(double red, double green, double blue) { - auto &awb = context.activeState.awb; - - const auto &awbEnable = controls.get(controls::AwbEnable); - if (awbEnable && *awbEnable != awb.autoEnabled) { - awb.autoEnabled = *awbEnable; - - LOG(RkISP1Awb, Debug) - << (*awbEnable ? "Enabling" : "Disabling") << " AWB"; - } - - const auto &colourGains = controls.get(controls::ColourGains); - if (colourGains && !awb.autoEnabled) { - awb.gains.manual.red = (*colourGains)[0]; - awb.gains.manual.blue = (*colourGains)[1]; - - LOG(RkISP1Awb, Debug) - << "Set colour gains to red: " << awb.gains.manual.red - << ", blue: " << awb.gains.manual.blue; - } - - frameContext.awb.autoEnabled = awb.autoEnabled; - - if (!awb.autoEnabled) { - frameContext.awb.gains.red = awb.gains.manual.red; - frameContext.awb.gains.green = 1.0; - frameContext.awb.gains.blue = awb.gains.manual.blue; - } + /* Convert the RGB values to CIE tristimulus values (XYZ) */ + double X = (-0.14282) * (red) + (1.54924) * (green) + (-0.95641) * (blue); + double Y = (-0.32466) * (red) + (1.57837) * (green) + (-0.73191) * (blue); + double Z = (-0.68202) * (red) + (0.77073) * (green) + (0.56332) * (blue); + + /* Calculate the normalized chromaticity values */ + double x = X / (X + Y + Z); + double y = Y / (X + Y + Z); + + /* Calculate CCT */ + double n = (x - 0.3320) / (0.1858 - y); + return 449 * n * n * n + 3525 * n * n + 6823.3 * n + 5520.33; } /** diff --git a/src/ipa/rkisp1/algorithms/awb.h b/src/ipa/rkisp1/algorithms/awb.h index f5633b1171a0..9d45a442339c 100644 --- a/src/ipa/rkisp1/algorithms/awb.h +++ b/src/ipa/rkisp1/algorithms/awb.h @@ -20,12 +20,12 @@ public: ~Awb() = default; int configure(IPAContext &context, const IPACameraSensorInfo &configInfo) override; - void prepare(IPAContext &context, const uint32_t frame, - IPAFrameContext &frameContext, - rkisp1_params_cfg *params) override; void queueRequest(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, const ControlList &controls) override; + void prepare(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + rkisp1_params_cfg *params) override; void process(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, const rkisp1_stat_buffer *stats, From patchwork Mon Oct 24 00:03:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17665 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 AEE6EC3285 for ; Mon, 24 Oct 2022 00:04:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 473C562EE1; Mon, 24 Oct 2022 02:04:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1666569868; bh=JE+NAC0fH+332zKjoX/apa/qS38zFdF3xFEWWL7kJDs=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=2PmovXopavjJhiUu7uKZx+vV9jhsgaFnRx+n6nBeb0WkwVqprZy3oLkmS5D9UL8V1 wYpTVctTgorRsDCTlaRrdfy/hxjILgfz2OPrkVt36yDbwwkpDtoCMhxOTzALgu58Pv yfC7wDRoxf9Qx/uB7iOyRhNeRy2IB5gdAQ2+K/BmCQ/pvedsniWRheA+5xRmnZfEov ptGmYEhBBc2Nln9dtPu05FhhrtxPUniQV/B6mhq1TxA1OiyNtEbcNkNeGokgU0kGaK DcvnT26pH3ls/H1jFFniEBPe3ZyVioIIdlrvYFlo0WoO4XU53Rt+iZF96tNwNs7TMB S3e3BxZOjeAgQ== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B5BD662EDA for ; Mon, 24 Oct 2022 02:04:24 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="bgaV2PqE"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id F19CF471; Mon, 24 Oct 2022 02:04:23 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1666569864; bh=JE+NAC0fH+332zKjoX/apa/qS38zFdF3xFEWWL7kJDs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bgaV2PqEHeCRq5Zl5fx/p7Wto3iZYZpZUGyGExVulTOuacXFNAe+vE0SnbIJ2A8SM NNJnNL6SiRXgDnWPBeFVzhSakEqTVEDMgdYzT/1f/DlalS3o9LesAWF78M5qXBBRaH +g334I0QEnp4OSmExopf3zLwKNmjOoiaXkHaGq5Y= To: libcamera-devel@lists.libcamera.org Date: Mon, 24 Oct 2022 03:03:45 +0300 Message-Id: <20221024000356.29521-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.37.4 In-Reply-To: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> References: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 02/13] ipa: rkisp1: Move shutter speed and analogue gain limits from agc to sensor 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: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The limits for the shutter speed and analogue gain are stored in IPASessionConfiguration::agc. While they're related to the AGC, they are properties of the sensor, and are stored in the session configuration by the IPA module, not the AGC algorithm. Move them to the IPASessionConfiguration::sensor structure where they belong. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Jacopo Mondi --- src/ipa/rkisp1/algorithms/agc.cpp | 11 ++++++----- src/ipa/rkisp1/ipa_context.cpp | 28 +++++++++++++++------------- src/ipa/rkisp1/ipa_context.h | 25 +++++++++++++------------ src/ipa/rkisp1/rkisp1.cpp | 10 ++++++---- 4 files changed, 40 insertions(+), 34 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 3fcbfa608467..169afe372803 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -74,7 +74,8 @@ Agc::Agc() int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) { /* Configure the default exposure and gain. */ - context.activeState.agc.gain = std::max(context.configuration.agc.minAnalogueGain, kMinAnalogueGain); + context.activeState.agc.gain = std::max(context.configuration.sensor.minAnalogueGain, + kMinAnalogueGain); context.activeState.agc.exposure = 10ms / context.configuration.sensor.lineDuration; /* @@ -202,13 +203,13 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext, /* Use the highest of the two gain estimates. */ double evGain = std::max(yGain, iqMeanGain); - utils::Duration minShutterSpeed = configuration.agc.minShutterSpeed; - utils::Duration maxShutterSpeed = std::min(configuration.agc.maxShutterSpeed, + utils::Duration minShutterSpeed = configuration.sensor.minShutterSpeed; + utils::Duration maxShutterSpeed = std::min(configuration.sensor.maxShutterSpeed, kMaxShutterSpeed); - double minAnalogueGain = std::max(configuration.agc.minAnalogueGain, + double minAnalogueGain = std::max(configuration.sensor.minAnalogueGain, kMinAnalogueGain); - double maxAnalogueGain = std::min(configuration.agc.maxAnalogueGain, + double maxAnalogueGain = std::min(configuration.sensor.maxAnalogueGain, kMaxAnalogueGain); /* Consider within 1% of the target as correctly exposed. */ diff --git a/src/ipa/rkisp1/ipa_context.cpp b/src/ipa/rkisp1/ipa_context.cpp index 3c14cf3476ce..7a987497bd03 100644 --- a/src/ipa/rkisp1/ipa_context.cpp +++ b/src/ipa/rkisp1/ipa_context.cpp @@ -28,21 +28,11 @@ namespace libcamera::ipa::rkisp1 { * \var IPASessionConfiguration::agc * \brief AGC parameters configuration of the IPA * - * \var IPASessionConfiguration::agc.minShutterSpeed - * \brief Minimum shutter speed supported with the configured sensor - * - * \var IPASessionConfiguration::agc.maxShutterSpeed - * \brief Maximum shutter speed supported with the configured sensor - * - * \var IPASessionConfiguration::agc.minAnalogueGain - * \brief Minimum analogue gain supported with the configured sensor - * - * \var IPASessionConfiguration::agc.maxAnalogueGain - * \brief Maximum analogue gain supported with the configured sensor - * * \var IPASessionConfiguration::agc.measureWindow * \brief AGC measure window - * + */ + +/** * \var IPASessionConfiguration::hw * \brief RkISP1-specific hardware information * @@ -77,6 +67,18 @@ namespace libcamera::ipa::rkisp1 { * \var IPASessionConfiguration::sensor * \brief Sensor-specific configuration of the IPA * + * \var IPASessionConfiguration::sensor.minShutterSpeed + * \brief Minimum shutter speed supported with the sensor + * + * \var IPASessionConfiguration::sensor.maxShutterSpeed + * \brief Maximum shutter speed supported with the sensor + * + * \var IPASessionConfiguration::sensor.minAnalogueGain + * \brief Minimum analogue gain supported with the sensor + * + * \var IPASessionConfiguration::sensor.maxAnalogueGain + * \brief Maximum analogue gain supported with the sensor + * * \var IPASessionConfiguration::sensor.defVBlank * \brief The default vblank value of the sensor * diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index 60e8a7e11196..bb60ab9eab72 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -21,24 +21,25 @@ namespace libcamera { namespace ipa::rkisp1 { struct IPASessionConfiguration { + struct { + struct rkisp1_cif_isp_window measureWindow; + } agc; + + struct { + struct rkisp1_cif_isp_window measureWindow; + bool enabled; + } awb; + + struct { + bool enabled; + } lsc; + struct { utils::Duration minShutterSpeed; utils::Duration maxShutterSpeed; double minAnalogueGain; double maxAnalogueGain; - struct rkisp1_cif_isp_window measureWindow; - } agc; - struct { - struct rkisp1_cif_isp_window measureWindow; - bool enabled; - } awb; - - struct { - bool enabled; - } lsc; - - struct { int32_t defVBlank; utils::Duration lineDuration; Size size; diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index 9061a189cbce..fcb9dacccc3c 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -257,10 +257,12 @@ int IPARkISP1::configure([[maybe_unused]] const IPACameraSensorInfo &info, * * \todo take VBLANK into account for maximum shutter speed */ - context_.configuration.agc.minShutterSpeed = minExposure * context_.configuration.sensor.lineDuration; - context_.configuration.agc.maxShutterSpeed = maxExposure * context_.configuration.sensor.lineDuration; - context_.configuration.agc.minAnalogueGain = camHelper_->gain(minGain); - context_.configuration.agc.maxAnalogueGain = camHelper_->gain(maxGain); + context_.configuration.sensor.minShutterSpeed = + minExposure * context_.configuration.sensor.lineDuration; + context_.configuration.sensor.maxShutterSpeed = + maxExposure * context_.configuration.sensor.lineDuration; + context_.configuration.sensor.minAnalogueGain = camHelper_->gain(minGain); + context_.configuration.sensor.maxAnalogueGain = camHelper_->gain(maxGain); for (auto const &algo : algorithms()) { int ret = algo->configure(context_, info); From patchwork Mon Oct 24 00:03:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17666 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 87A39C3286 for ; Mon, 24 Oct 2022 00:04:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1C75A62EEB; Mon, 24 Oct 2022 02:04:30 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1666569870; bh=9w8R/zt8f/eVuy3RQLJ41Y52KeXR/GuoRMAu99DWeQg=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=dkY8vi7FcVLrGjia+ZTFLeRT0fl9nVgXU48DKsi+3K45p6m6loRx1kIAoeLBtzPPK LmRrKoOk2Rf7aTrY2YRTvPD5EnNoibK31Dyq8MDH3xgfCmPbTooPZxON5AEtKbDUKN LOOROO4WuspwK+BF08+d8itbxbYGE1Ww0dxBTVCT0kjj05gxdE6/pVgf4xFuRBt1kl Ch/UWU1wGFa4L63pVKpvoWOyU/B+ma5PxPViV1BYIgte+nEGATvUfKuCySJ6bP5twt Mau6+LkQyQlyMCTi9EFaOF72u9Tx30QrMOva6xMFD/rBWAdSrqTQpB3EwgQDtRkZo2 hrfolpSHRqZOw== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EC23262ED9 for ; Mon, 24 Oct 2022 02:04:25 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="UBrNTRqs"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 74D6A88F; Mon, 24 Oct 2022 02:04:25 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1666569865; bh=9w8R/zt8f/eVuy3RQLJ41Y52KeXR/GuoRMAu99DWeQg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UBrNTRqsmfp9IxCQXAbCMCwKMByujcAogxeApJNddv/vgJlpJtOhUSfEyjL6D6VX8 t5UbGsm9pu+mMYNe80KejG7CzZZS+piyS89R31Fd0ZtYzaRvEg9lM1X3/JyjnctzrB i+/DP5eEm4txwAq/YVfLiQswIBWmJHXaCFwx9El0= To: libcamera-devel@lists.libcamera.org Date: Mon, 24 Oct 2022 03:03:46 +0300 Message-Id: <20221024000356.29521-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.37.4 In-Reply-To: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> References: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 03/13] ipa: rkisp1: Support raw capture in IPA operations 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: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The RkISP1 can capture raw frames by bypassing the ISP. In that mode, the ISP will not produce statistics nor consume parameters. Most algorithms will thus be unable to run, with one exception: the AGC will still be able to configure the sensor exposure time and analog gain in manual mode. To prepare for this, add the ability to disable algorithms for the duration of the capture session based on the camera configuration. Individual algorithms report whether they support raw formats at construction time, and the IPA module disables algorithms in configure() based on the stream configurations. Disabled algorithms are skipped during the capture session in the processStatsBuffer() operation. As the ISP doesn't produce statistics, don't try to access the stats buffer. There is no need for similar logic in fillParamsBuffer() as that operation won't be called for raw capture. All algorithms report not supporting raw capture by default. Raw support in AGC will be added separately. The feature is implemented in the RkISP1 module without any support from libipa at this point to avoid designing a generic API based on a single user. This may be changed in the future. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Jacopo Mondi --- src/ipa/rkisp1/algorithms/algorithm.h | 12 +++++++- src/ipa/rkisp1/ipa_context.cpp | 5 ++++ src/ipa/rkisp1/ipa_context.h | 2 ++ src/ipa/rkisp1/rkisp1.cpp | 42 +++++++++++++++++++++++---- 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/algorithm.h b/src/ipa/rkisp1/algorithms/algorithm.h index c3212cff76fe..9454c9a1fc06 100644 --- a/src/ipa/rkisp1/algorithms/algorithm.h +++ b/src/ipa/rkisp1/algorithms/algorithm.h @@ -15,7 +15,17 @@ namespace libcamera { namespace ipa::rkisp1 { -using Algorithm = libcamera::ipa::Algorithm; +class Algorithm : public libcamera::ipa::Algorithm +{ +public: + Algorithm() + : disabled_(false), supportsRaw_(false) + { + } + + bool disabled_; + bool supportsRaw_; +}; } /* namespace ipa::rkisp1 */ diff --git a/src/ipa/rkisp1/ipa_context.cpp b/src/ipa/rkisp1/ipa_context.cpp index 7a987497bd03..9bbf368432fa 100644 --- a/src/ipa/rkisp1/ipa_context.cpp +++ b/src/ipa/rkisp1/ipa_context.cpp @@ -89,6 +89,11 @@ namespace libcamera::ipa::rkisp1 { * \brief Sensor output resolution */ +/** + * \var IPASessionConfiguration::raw + * \brief Indicates if the camera is configured to capture raw frames + */ + /** * \struct IPAActiveState * \brief Active state for algorithms diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index bb60ab9eab72..3e47ac663c58 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -48,6 +48,8 @@ struct IPASessionConfiguration { struct { rkisp1_cif_isp_version revision; } hw; + + bool raw; }; struct IPAActiveState { diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index fcb9dacccc3c..538e42cb6f7f 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -24,6 +24,7 @@ #include #include +#include "libcamera/internal/formats.h" #include "libcamera/internal/mapped_framebuffer.h" #include "libcamera/internal/yaml_parser.h" @@ -207,7 +208,7 @@ void IPARkISP1::stop() * before accessing them. */ int IPARkISP1::configure([[maybe_unused]] const IPACameraSensorInfo &info, - [[maybe_unused]] const std::map &streamConfig, + const std::map &streamConfig, const std::map &entityControls) { if (entityControls.empty()) @@ -264,7 +265,21 @@ int IPARkISP1::configure([[maybe_unused]] const IPACameraSensorInfo &info, context_.configuration.sensor.minAnalogueGain = camHelper_->gain(minGain); context_.configuration.sensor.maxAnalogueGain = camHelper_->gain(maxGain); - for (auto const &algo : algorithms()) { + context_.configuration.raw = std::any_of(streamConfig.begin(), streamConfig.end(), + [](auto &cfg) -> bool { + PixelFormat pixelFormat{ cfg.second.pixelFormat }; + const PixelFormatInfo &format = PixelFormatInfo::info(pixelFormat); + return format.colourEncoding == PixelFormatInfo::ColourEncodingRAW; + }); + + for (auto const &a : algorithms()) { + Algorithm *algo = static_cast(a.get()); + + /* Disable algorithms that don't support raw formats. */ + algo->disabled_ = context_.configuration.raw && !algo->supportsRaw_; + if (algo->disabled_) + continue; + int ret = algo->configure(context_, info); if (ret) return ret; @@ -307,8 +322,12 @@ void IPARkISP1::queueRequest(const uint32_t frame, const ControlList &controls) { IPAFrameContext &frameContext = context_.frameContexts.alloc(frame); - for (auto const &algo : algorithms()) + for (auto const &a : algorithms()) { + Algorithm *algo = static_cast(a.get()); + if (algo->disabled_) + continue; algo->queueRequest(context_, frame, frameContext, controls); + } } void IPARkISP1::fillParamsBuffer(const uint32_t frame, const uint32_t bufferId) @@ -333,9 +352,16 @@ void IPARkISP1::processStatsBuffer(const uint32_t frame, const uint32_t bufferId { IPAFrameContext &frameContext = context_.frameContexts.get(frame); - const rkisp1_stat_buffer *stats = - reinterpret_cast( + /* + * In raw capture mode, the ISP is bypassed and no statistics buffer is + * provided. + */ + const rkisp1_stat_buffer *stats; + if (!context_.configuration.raw) + stats = reinterpret_cast( mappedBuffers_.at(bufferId).planes()[0].data()); + else + stats = nullptr; frameContext.sensor.exposure = sensorControls.get(V4L2_CID_EXPOSURE).get(); @@ -344,8 +370,12 @@ void IPARkISP1::processStatsBuffer(const uint32_t frame, const uint32_t bufferId ControlList metadata(controls::controls); - for (auto const &algo : algorithms()) + for (auto const &a : algorithms()) { + Algorithm *algo = static_cast(a.get()); + if (algo->disabled_) + continue; algo->process(context_, frame, frameContext, stats, metadata); + } setControls(frame); From patchwork Mon Oct 24 00:03:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17667 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 5DB09BD16B for ; Mon, 24 Oct 2022 00:04:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 96F6F62EEE; Mon, 24 Oct 2022 02:04:30 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1666569870; bh=SkFItuPc7oOntFA2TStR/Q7B3gL7P7w2oG2LpfBc+jU=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=xozh/ugKx+Q2Dxh7wMuKsws78fagUCpX1CusxptDPmdjw+Af600eDlT1ndZ6b0RD3 KjdOjEnYpy2B7z8ADH226t9RQSb9NlRr0e/SEf1kX0gY/37zvEvrLCBGp9krR6myhS Zq/qkGb3exkHsVPuyZM7WtAzhmtbHW+4tmzfJqRU9METKHYOhmzvcPHo34tWwHhp6T Afazw8cqAbPx1dgBPm2k2nRnJSamtDaYlQnLp+GodCra7mKEc+bKQATyy1PcHXdoy+ nKvA6yc2xpsx0a1M8kvWIz/495L7++Nm92clnM6G80HYfTgtOhv+HvRcL0E3lii+Eh Ga4Er9eWaOadQ== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 59A7562ED2 for ; Mon, 24 Oct 2022 02:04:27 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Wi+E5uNd"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D93F5471; Mon, 24 Oct 2022 02:04:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1666569867; bh=SkFItuPc7oOntFA2TStR/Q7B3gL7P7w2oG2LpfBc+jU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Wi+E5uNdkfoH4jSC20RF2cr1V/4UqSOCwJzyWw4Iq3F0QYFPos8fNTQQpuCNeIoIZ FmuKbglVAk6ha6UnXq/uJ1izMWv3SjLOb31/KVXriHa0EMMKa5SdApGSnnSHdRktpW 6MGGQwpi256jYUd5rLJq/8gQtnd1oZjPgzAqrwAw= To: libcamera-devel@lists.libcamera.org Date: Mon, 24 Oct 2022 03:03:47 +0300 Message-Id: <20221024000356.29521-5-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.37.4 In-Reply-To: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> References: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 04/13] ipa: rkisp1: Add support for manual gain and exposure 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: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Paul Elder Add support for manual gain and exposure in the rkisp1 IPA. Signed-off-by: Paul Elder --- include/libcamera/ipa/rkisp1.mojom | 2 +- src/ipa/rkisp1/algorithms/agc.cpp | 62 +++++++++++++++++++++--- src/ipa/rkisp1/algorithms/agc.h | 4 ++ src/ipa/rkisp1/ipa_context.h | 13 ++++- src/ipa/rkisp1/rkisp1.cpp | 17 +++++++ src/libcamera/pipeline/rkisp1/rkisp1.cpp | 2 +- 6 files changed, 89 insertions(+), 11 deletions(-) diff --git a/include/libcamera/ipa/rkisp1.mojom b/include/libcamera/ipa/rkisp1.mojom index eaf3955e4096..b526450d9949 100644 --- a/include/libcamera/ipa/rkisp1.mojom +++ b/include/libcamera/ipa/rkisp1.mojom @@ -10,7 +10,7 @@ import "include/libcamera/ipa/core.mojom"; interface IPARkISP1Interface { init(libcamera.IPASettings settings, - uint32 hwRevision) + uint32 hwRevision, libcamera.ControlInfoMap sensorControls) => (int32 ret, libcamera.ControlInfoMap ipaControls); start() => (int32 ret); stop(); diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 169afe372803..377a3e8a0efd 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -74,9 +74,14 @@ Agc::Agc() int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) { /* Configure the default exposure and gain. */ - context.activeState.agc.gain = std::max(context.configuration.sensor.minAnalogueGain, - kMinAnalogueGain); - context.activeState.agc.exposure = 10ms / context.configuration.sensor.lineDuration; + context.activeState.agc.automatic.gain = + std::max(context.configuration.sensor.minAnalogueGain, + kMinAnalogueGain); + context.activeState.agc.automatic.exposure = + 10ms / context.configuration.sensor.lineDuration; + context.activeState.agc.manual.gain = context.activeState.agc.automatic.gain; + context.activeState.agc.manual.exposure = context.activeState.agc.automatic.exposure; + context.activeState.agc.autoEnabled = true; /* * According to the RkISP1 documentation: @@ -108,14 +113,57 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) return 0; } +/** + * \copydoc libcamera::ipa::Algorithm::queueRequest + */ +void Agc::queueRequest(IPAContext &context, + [[maybe_unused]] const uint32_t frame, + IPAFrameContext &frameContext, + const ControlList &controls) +{ + auto &agc = context.activeState.agc; + + const auto &agcEnable = controls.get(controls::AeEnable); + if (agcEnable && *agcEnable != agc.autoEnabled) { + agc.autoEnabled = *agcEnable; + + LOG(RkISP1Agc, Debug) + << (*agcEnable ? "Enabling" : "Disabling") << " AGC"; + } + + const auto &exposure = controls.get(controls::ExposureTime); + if (exposure && !agc.autoEnabled) { + agc.manual.exposure = *exposure; + + LOG(RkISP1Agc, Debug) + << "Set exposure to: " << agc.manual.exposure; + } + + const auto &gain = controls.get(controls::AnalogueGain); + if (gain && !agc.autoEnabled) { + agc.manual.gain = *gain; + + LOG(RkISP1Agc, Debug) << "Set gain to: " << agc.manual.gain; + } + + frameContext.agc.autoEnabled = agc.autoEnabled; + + if (!frameContext.agc.autoEnabled) { + frameContext.agc.exposure = agc.manual.exposure; + frameContext.agc.gain = agc.manual.gain; + } +} + /** * \copydoc libcamera::ipa::Algorithm::prepare */ void Agc::prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, rkisp1_params_cfg *params) { - frameContext.agc.exposure = context.activeState.agc.exposure; - frameContext.agc.gain = context.activeState.agc.gain; + if (frameContext.agc.autoEnabled) { + frameContext.agc.exposure = context.activeState.agc.automatic.exposure; + frameContext.agc.gain = context.activeState.agc.automatic.gain; + } if (frame > 0) return; @@ -263,8 +311,8 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext, << stepGain; /* Update the estimated exposure and gain. */ - activeState.agc.exposure = shutterTime / configuration.sensor.lineDuration; - activeState.agc.gain = stepGain; + activeState.agc.automatic.exposure = shutterTime / configuration.sensor.lineDuration; + activeState.agc.automatic.gain = stepGain; } /** diff --git a/src/ipa/rkisp1/algorithms/agc.h b/src/ipa/rkisp1/algorithms/agc.h index da4d2d4e8359..a228d0c37768 100644 --- a/src/ipa/rkisp1/algorithms/agc.h +++ b/src/ipa/rkisp1/algorithms/agc.h @@ -26,6 +26,10 @@ public: ~Agc() = default; int configure(IPAContext &context, const IPACameraSensorInfo &configInfo) override; + void queueRequest(IPAContext &context, + const uint32_t frame, + IPAFrameContext &frameContext, + const ControlList &controls) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, rkisp1_params_cfg *params) override; diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index 3e47ac663c58..b9b2065328d6 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -54,8 +54,16 @@ struct IPASessionConfiguration { struct IPAActiveState { struct { - uint32_t exposure; - double gain; + struct { + uint32_t exposure; + double gain; + } manual; + struct { + uint32_t exposure; + double gain; + } automatic; + + bool autoEnabled; } agc; struct { @@ -96,6 +104,7 @@ struct IPAFrameContext : public FrameContext { struct { uint32_t exposure; double gain; + bool autoEnabled; } agc; struct { diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp index 538e42cb6f7f..5c041ded0db4 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -50,6 +50,7 @@ public: IPARkISP1(); int init(const IPASettings &settings, unsigned int hwRevision, + const ControlInfoMap &sensorControls, ControlInfoMap *ipaControls) override; int start() override; void stop() override; @@ -116,6 +117,7 @@ std::string IPARkISP1::logPrefix() const } int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision, + const ControlInfoMap &sensorControls, ControlInfoMap *ipaControls) { /* \todo Add support for other revisions */ @@ -184,6 +186,21 @@ int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision, /* Return the controls handled by the IPA. */ ControlInfoMap::Map ctrlMap = rkisp1Controls; + + auto exposureTimeInfo = sensorControls.find(V4L2_CID_EXPOSURE); + if (exposureTimeInfo != sensorControls.end()) { + ctrlMap.emplace(&controls::ExposureTime, + ControlInfo(exposureTimeInfo->second.min(), + exposureTimeInfo->second.max())); + } + + auto analogueGainInfo = sensorControls.find(V4L2_CID_ANALOGUE_GAIN); + if (analogueGainInfo != sensorControls.end()) { + ctrlMap.emplace(&controls::AnalogueGain, + ControlInfo(static_cast(analogueGainInfo->second.min().get()), + static_cast(analogueGainInfo->second.max().get()))); + } + *ipaControls = ControlInfoMap(std::move(ctrlMap), controls::controls); return 0; diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 455ee2a0a711..1418dc9a47fb 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -348,7 +348,7 @@ int RkISP1CameraData::loadIPA(unsigned int hwRevision) } int ret = ipa_->init({ ipaTuningFile, sensor_->model() }, hwRevision, - &controlInfo_); + sensor_->controls(), &controlInfo_); if (ret < 0) { LOG(RkISP1, Error) << "IPA initialization failure"; return ret; From patchwork Mon Oct 24 00:03:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17668 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 228DFBDB16 for ; Mon, 24 Oct 2022 00:04:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B28CD62EF6; Mon, 24 Oct 2022 02:04:33 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1666569873; bh=q4vlaDe9G9foCStqIT1WIl/viTRR4Z/iQiMqa/j9kDQ=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=rCfIUJsDQQmf1r+Rd1N97egH/R2zOqJuaa6H2XO+uyYr0ouMlPRU6RDEKxFZDZXI1 0oVSlq7yPtgKdnnbHSBiQUUdvkYdAKJZPewp3UZv5WN8usc0kbAzTSe+IsNwcsqpyc ZgGaGWqQ3ndDbu0qJDoNufXAUEsyWFg1fQ0GbtSvAnXaya5YsV48YAcEh9uaRxa4MC HU5cwgg7gkwklkUhccPALirJyilViGtdlyYwV9x8JgatkyHg7E58hYARP8Iz8hb5qr OVjXN1TO6v6OQu2q0yuQX3P0rwJMeA/8aGw2AzhVAUQnKFSBQkCdrkJOtnDALxILNS BSidV0fh7l+/Q== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9ED8562ED2 for ; Mon, 24 Oct 2022 02:04:28 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Frr44n+a"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 2AC1B471; Mon, 24 Oct 2022 02:04:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1666569868; bh=q4vlaDe9G9foCStqIT1WIl/viTRR4Z/iQiMqa/j9kDQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Frr44n+alCuPJx1WCYYRZgEbkOnfGPLzeQvwPjdY6PnHTht/klXuZ2r16w0QM7cCt UvaGDoK+q+TicV+jTBD3nm3g2JuycV3a0Me0W3Muu3pg0mndoDZxUblbK6taQwpixL rum17DgQ5+waLWGXfkRZ4H6FUIS4/AiWgqHP/Aro= To: libcamera-devel@lists.libcamera.org Date: Mon, 24 Oct 2022 03:03:48 +0300 Message-Id: <20221024000356.29521-6-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.37.4 In-Reply-To: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> References: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 05/13] ipa: rkisp1: agc: Support raw capture 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: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Support raw capture by allowing manual control of the exposure time and analogue gain. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder --- src/ipa/rkisp1/algorithms/agc.cpp | 51 ++++++++++++++++++++----------- src/ipa/rkisp1/algorithms/agc.h | 2 ++ 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 377a3e8a0efd..973965babed2 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -62,6 +62,7 @@ static constexpr double kRelativeLuminanceTarget = 0.4; Agc::Agc() : frameCount_(0), numCells_(0), numHistBins_(0), filteredExposure_(0s) { + supportsRaw_ = true; } /** @@ -81,7 +82,7 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) 10ms / context.configuration.sensor.lineDuration; context.activeState.agc.manual.gain = context.activeState.agc.automatic.gain; context.activeState.agc.manual.exposure = context.activeState.agc.automatic.exposure; - context.activeState.agc.autoEnabled = true; + context.activeState.agc.autoEnabled = !context.configuration.raw; /* * According to the RkISP1 documentation: @@ -123,12 +124,14 @@ void Agc::queueRequest(IPAContext &context, { auto &agc = context.activeState.agc; - const auto &agcEnable = controls.get(controls::AeEnable); - if (agcEnable && *agcEnable != agc.autoEnabled) { - agc.autoEnabled = *agcEnable; + if (!context.configuration.raw) { + const auto &agcEnable = controls.get(controls::AeEnable); + if (agcEnable && *agcEnable != agc.autoEnabled) { + agc.autoEnabled = *agcEnable; - LOG(RkISP1Agc, Debug) - << (*agcEnable ? "Enabling" : "Disabling") << " AGC"; + LOG(RkISP1Agc, Debug) + << (*agcEnable ? "Enabling" : "Disabling") << " AGC"; + } } const auto &exposure = controls.get(controls::ExposureTime); @@ -160,6 +163,9 @@ void Agc::queueRequest(IPAContext &context, void Agc::prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, rkisp1_params_cfg *params) { + if (!params) + return; + if (frameContext.agc.autoEnabled) { frameContext.agc.exposure = context.activeState.agc.automatic.exposure; frameContext.agc.gain = context.activeState.agc.automatic.gain; @@ -367,6 +373,22 @@ double Agc::measureBrightness(const rkisp1_cif_isp_hist_stat *hist) const return histogram.interQuantileMean(0.98, 1.0); } +void Agc::fillMetadata(IPAContext &context, IPAFrameContext &frameContext, + ControlList &metadata) +{ + utils::Duration exposureTime = context.configuration.sensor.lineDuration + * frameContext.sensor.exposure; + metadata.set(controls::AnalogueGain, frameContext.sensor.gain); + metadata.set(controls::ExposureTime, exposureTime.get()); + + /* \todo Use VBlank value calculated from each frame exposure. */ + uint32_t vTotal = context.configuration.sensor.size.height + + context.configuration.sensor.defVBlank; + utils::Duration frameDuration = context.configuration.sensor.lineDuration + * vTotal; + metadata.set(controls::FrameDuration, frameDuration.get()); +} + /** * \brief Process RkISP1 statistics, and run AGC operations * \param[in] context The shared IPA context @@ -382,6 +404,11 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, IPAFrameContext &frameContext, const rkisp1_stat_buffer *stats, ControlList &metadata) { + if (!stats) { + fillMetadata(context, frameContext, metadata); + return; + } + /* * \todo Verify that the exposure and gain applied by the sensor for * this frame match what has been requested. This isn't a hard @@ -424,17 +451,7 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, computeExposure(context, frameContext, yGain, iqMeanGain); frameCount_++; - utils::Duration exposureTime = context.configuration.sensor.lineDuration - * frameContext.sensor.exposure; - metadata.set(controls::AnalogueGain, frameContext.sensor.gain); - metadata.set(controls::ExposureTime, exposureTime.get()); - - /* \todo Use VBlank value calculated from each frame exposure. */ - uint32_t vTotal = context.configuration.sensor.size.height - + context.configuration.sensor.defVBlank; - utils::Duration frameDuration = context.configuration.sensor.lineDuration - * vTotal; - metadata.set(controls::FrameDuration, frameDuration.get()); + fillMetadata(context, frameContext, metadata); } REGISTER_IPA_ALGORITHM(Agc, "Agc") diff --git a/src/ipa/rkisp1/algorithms/agc.h b/src/ipa/rkisp1/algorithms/agc.h index a228d0c37768..8a22263741b6 100644 --- a/src/ipa/rkisp1/algorithms/agc.h +++ b/src/ipa/rkisp1/algorithms/agc.h @@ -44,6 +44,8 @@ private: utils::Duration filterExposure(utils::Duration exposureValue); double estimateLuminance(const rkisp1_cif_isp_ae_stat *ae, double gain); double measureBrightness(const rkisp1_cif_isp_hist_stat *hist) const; + void fillMetadata(IPAContext &context, IPAFrameContext &frameContext, + ControlList &metadata); uint64_t frameCount_; From patchwork Mon Oct 24 00:03:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17669 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 792B2C3285 for ; Mon, 24 Oct 2022 00:04:35 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 01A7E62EF8; Mon, 24 Oct 2022 02:04:34 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1666569875; bh=Yx96IqpktzpDHkyrxV43ILhbw+e0xY/upy+FAi8vPPA=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=aLTsEmw9PQnJQLOy+q2UYTVjPNJgR23a8g3rcmIiUYtwQtsfHBrRqG4AsxQ+0TPIg NVoKFv70WFY/q4TDDZqs7AoC4zv17JOD0HXM6bHMxQYF56ex6Eg/CRwmv6OT8tiLpI SS2cacFwEnPdSwDQ3vDSgZDo51ChuCXsaqxHQuBD0nkgYrBeNkZ5vIHn3tcRdt+9yG cREtQ2PMxDCKF+gSpYpNx6qRxYaD0LrXshW7rPEfKZftjfsByda9qllM1xVx6EQ0x+ pSEGRv2jAX5e7vQXhmcCQODMaAbWdtSwDpxp4hnsQH10u/sx0R1emhx0HwQDNKgVBe kDsemM+jGE4mA== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D598562ED2 for ; Mon, 24 Oct 2022 02:04:29 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="v4Gu6Ndn"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 68F01471; Mon, 24 Oct 2022 02:04:29 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1666569869; bh=Yx96IqpktzpDHkyrxV43ILhbw+e0xY/upy+FAi8vPPA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=v4Gu6NdnK58FB38utRDV0jYZXMXUnWwzuC6ktjDm+CB7DXzQnyRyKlVP4pJwVkAPo s1AMI8PSAwQOvWo8TreqCUMeXyApAlqFbYMy7BtYocmq+gRiK/Z2ak0hxEvRDKIKYP 96aWEA92UhlR6wAHYb9Iqq9Zu2cSSOXEAE/u02Qo= To: libcamera-devel@lists.libcamera.org Date: Mon, 24 Oct 2022 03:03:49 +0300 Message-Id: <20221024000356.29521-7-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.37.4 In-Reply-To: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> References: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 06/13] libcamera: stream: Add operator<<() to print StreamRole as a string 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: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" libcamera prints stream role values in log messages. To be more user-friendly, add a specialization of operator<<() to print the role name as a string instead of a numerical value. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder --- include/libcamera/stream.h | 3 +++ src/libcamera/stream.cpp | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h index f0ae7e62e0a3..efec695ad317 100644 --- a/include/libcamera/stream.h +++ b/include/libcamera/stream.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -70,6 +71,8 @@ enum StreamRole { using StreamRoles = std::vector; +std::ostream &operator<<(std::ostream &out, StreamRole role); + class Stream { public: diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp index 686e693bccba..67f308157fbf 100644 --- a/src/libcamera/stream.cpp +++ b/src/libcamera/stream.cpp @@ -417,6 +417,25 @@ std::string StreamConfiguration::toString() const * acceptable. */ +/** + * \brief Insert a text representation of a StreamRole into an output stream + * \param[in] out The output stream + * \param[in] role The StreamRole + * \return The output stream \a out + */ +std::ostream &operator<<(std::ostream &out, StreamRole role) +{ + static constexpr std::array names{ + "Raw", + "StillCapture", + "VideoRecording", + "Viewfinder", + }; + + out << names[static_cast>(role)]; + return out; +} + /** * \typedef StreamRoles * \brief A vector of StreamRole From patchwork Mon Oct 24 00:03:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17670 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 E51F1C3288 for ; Mon, 24 Oct 2022 00:04:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 428DF62EFB; Mon, 24 Oct 2022 02:04:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1666569876; bh=k92pDEMlNvueNxJ8zWmi/V9ZAkb7fwWyqiJALyBlU/A=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=P1GF471sa4HehrPlYudma2RPzxh11tSDZZKBOnjaPazFN7q6Qlm7T6lcii8odDe9L w3a8d4jKZIuR+F0eJqaDq3q4mfvQ5MUoQBONZbvJLMEZ+TR/sWDazKGFAgojp4GRTq Q8arz7lfTLAB1jI8NcVu2IGLJoN0oSXlsC2vHQUI11KDVDWpJPe6Hsn0pF83nZWYLa VAQRILkv0IhmQOvZBSgrUi2BHfFrb/r6KAwpyNhnCkLWOMWIh7Mru0xkNwwnbRSpGe jQhilTXRpxgXM6xoX6cQbmt83eXcPPqXArjL1rsNSoicSp8ZRItU9ySbzocpGgSRCn QDjCLi5fdc3TA== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2486862ED2 for ; Mon, 24 Oct 2022 02:04:31 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="fiFW0fhN"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id AD78688F; Mon, 24 Oct 2022 02:04:30 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1666569870; bh=k92pDEMlNvueNxJ8zWmi/V9ZAkb7fwWyqiJALyBlU/A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fiFW0fhNZEW+GFkfCITCNr/kiKOrAFin6i/h2mLJ1NfKnFnIhL3bE5byEyooWKGAE zlWh8Ya8v+F4QUGBDNRhUmZ8psmIOLZL4zuV8thQreMgWO4T8JPhx6UFTIxJlr67sl vp9/fgLQFhn1FJPJM03CiJyt1d82FIesJ7FNfg2k= To: libcamera-devel@lists.libcamera.org Date: Mon, 24 Oct 2022 03:03:50 +0300 Message-Id: <20221024000356.29521-8-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.37.4 In-Reply-To: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> References: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 07/13] libcamera: stream: Turn StreamRole into scoped enumeration 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: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The StreamRole enum has enumerators such as 'Raw' that are too generic to be in the global libcamera namespace. Turn it into a scoped enum to avoid namespace clashes, and update users accordingly. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Jacopo Mondi --- include/libcamera/stream.h | 2 +- src/apps/lc-compliance/capture_test.cpp | 17 ++++++++++++----- src/gstreamer/gstlibcamerapad.cpp | 20 +++++++++++++++----- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h index efec695ad317..29235ddf0d8a 100644 --- a/include/libcamera/stream.h +++ b/include/libcamera/stream.h @@ -62,7 +62,7 @@ private: StreamFormats formats_; }; -enum StreamRole { +enum class StreamRole { Raw, StillCapture, VideoRecording, diff --git a/src/apps/lc-compliance/capture_test.cpp b/src/apps/lc-compliance/capture_test.cpp index 52578207c11f..1dcfcf92fc8c 100644 --- a/src/apps/lc-compliance/capture_test.cpp +++ b/src/apps/lc-compliance/capture_test.cpp @@ -16,7 +16,12 @@ using namespace libcamera; const std::vector NUMREQUESTS = { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 }; -const std::vector ROLES = { Raw, StillCapture, VideoRecording, Viewfinder }; +const std::vector ROLES = { + StreamRole::Raw, + StreamRole::StillCapture, + StreamRole::VideoRecording, + StreamRole::Viewfinder +}; class SingleStream : public testing::TestWithParam> { @@ -54,10 +59,12 @@ void SingleStream::TearDown() std::string SingleStream::nameParameters(const testing::TestParamInfo &info) { - std::map rolesMap = { { Raw, "Raw" }, - { StillCapture, "StillCapture" }, - { VideoRecording, "VideoRecording" }, - { Viewfinder, "Viewfinder" } }; + std::map rolesMap = { + { StreamRole::Raw, "Raw" }, + { StreamRole::StillCapture, "StillCapture" }, + { StreamRole::VideoRecording, "VideoRecording" }, + { StreamRole::Viewfinder, "Viewfinder" } + }; std::string roleName = rolesMap[std::get<0>(info.param)]; std::string numRequestsName = std::to_string(std::get<1>(info.param)); diff --git a/src/gstreamer/gstlibcamerapad.cpp b/src/gstreamer/gstlibcamerapad.cpp index 87b4057ac101..9e710a479368 100644 --- a/src/gstreamer/gstlibcamerapad.cpp +++ b/src/gstreamer/gstlibcamerapad.cpp @@ -54,7 +54,7 @@ gst_libcamera_pad_get_property(GObject *object, guint prop_id, GValue *value, switch (prop_id) { case PROP_STREAM_ROLE: - g_value_set_enum(value, self->role); + g_value_set_enum(value, static_cast(self->role)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -87,9 +87,19 @@ gst_libcamera_stream_role_get_type() { static GType type = 0; static const GEnumValue values[] = { - { StillCapture, "libcamera::StillCapture", "still-capture" }, - { VideoRecording, "libcamera::VideoRecording", "video-recording" }, - { Viewfinder, "libcamera::Viewfinder", "view-finder" }, + { + static_cast(StreamRole::StillCapture), + "libcamera::StillCapture", + "still-capture", + }, { + static_cast(StreamRole::VideoRecording), + "libcamera::VideoRecording", + "video-recording", + }, { + static_cast(StreamRole::Viewfinder), + "libcamera::Viewfinder", + "view-finder", + }, { 0, NULL, NULL } }; @@ -110,7 +120,7 @@ gst_libcamera_pad_class_init(GstLibcameraPadClass *klass) auto *spec = g_param_spec_enum("stream-role", "Stream Role", "The selected stream role", gst_libcamera_stream_role_get_type(), - VideoRecording, + static_cast(StreamRole::VideoRecording), (GParamFlags)(GST_PARAM_MUTABLE_READY | G_PARAM_CONSTRUCT | G_PARAM_READWRITE From patchwork Mon Oct 24 00:03:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17671 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 946E7C3289 for ; Mon, 24 Oct 2022 00:04:37 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D33FB62EFD; Mon, 24 Oct 2022 02:04:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1666569876; bh=w3agMv/Il0W8IEOQXHr443qEB6P2AARPOi0AzE1asvM=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=ZzIITo4lv70RWso/P9nDz4lk826ywDDVLYCKOy1Sgel57Y818lWWWVlhJVWcWpvJ8 lKFgBo8c8dv+T0ouT1N4cAkEvIrafsQoTcFRtovE8oLDFtAupl9wJW+vuaINocPrQT 1qk+R7BN1i7+i4h1mrqVDTtXwQJE9Ow82gHlC/cENEUVqQM9tuBBYJeTV1hr/PEO7p gskHTqKsu/ZX3u9P5z9JCuiSqpe2BqqSPdgm6/04vcysRMR9YqoWOhp6OMx2I5GxDx EOzYL4V1qdCLeMaz025nOi+H4GFCnF1yAUuxzChaPK5B9IRUDnhhs8+aDwskmAqEs/ 26ts7lpoUr0EA== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 64C8F62ED2 for ; Mon, 24 Oct 2022 02:04:32 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="RqgHJXyh"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id EDB4088F; Mon, 24 Oct 2022 02:04:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1666569872; bh=w3agMv/Il0W8IEOQXHr443qEB6P2AARPOi0AzE1asvM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RqgHJXyhPldfMhE/CzxP5pc1BkTpPz+fhQL8nLFltmm1pwt82b4rfLWoo3wvEm1pY GrdxwC/qpQvoSifgyCpN6X0HMzFCoEqhY5hQ1w1Q4iobI3jbE7Xnlf7IlMvc0KZLlq 9zAB/YefuoKIsgCDVxRyT4pK5bTal5PEUJtAFupc= To: libcamera-devel@lists.libcamera.org Date: Mon, 24 Oct 2022 03:03:51 +0300 Message-Id: <20221024000356.29521-9-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.37.4 In-Reply-To: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> References: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 08/13] libcamera: pipeline_handler: Return unique_ptr from generateConfiguration() 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: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The PipelineHandler::generateConfiguration() function allocates a CameraConfiguration instance and returns it. The ownership of the instance is transferred to the caller. This is a perfect match for a std::unique_ptr<>, which the Camera::generateConfiguration() function already returns. Update PipelineHandler::generateConfiguration() to match it. This fixes a memory leak in one of the error return paths in the IPU3 pipeline handler. While at it, update the Camera::generateConfiguration() function documentation to drop the sentence that describes the ownership transfer, as that is implied by usage of std::unique_ptr<>. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- include/libcamera/internal/pipeline_handler.h | 2 +- src/libcamera/camera.cpp | 8 ++++---- src/libcamera/pipeline/ipu3/ipu3.cpp | 10 +++++----- src/libcamera/pipeline/raspberrypi/raspberrypi.cpp | 12 ++++++------ src/libcamera/pipeline/rkisp1/rkisp1.cpp | 9 +++++---- src/libcamera/pipeline/simple/simple.cpp | 12 ++++++------ src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 8 +++++--- src/libcamera/pipeline/vimc/vimc.cpp | 8 +++++--- src/libcamera/pipeline_handler.cpp | 3 +-- 9 files changed, 38 insertions(+), 34 deletions(-) diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h index b6139a88d421..96aab9d6459e 100644 --- a/include/libcamera/internal/pipeline_handler.h +++ b/include/libcamera/internal/pipeline_handler.h @@ -48,7 +48,7 @@ public: bool acquire(); void release(); - virtual CameraConfiguration *generateConfiguration(Camera *camera, + virtual std::unique_ptr generateConfiguration(Camera *camera, const StreamRoles &roles) = 0; virtual int configure(Camera *camera, CameraConfiguration *config) = 0; diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index 9fe29ca9dca5..daef77016971 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -934,8 +934,7 @@ const std::set &Camera::streams() const * \context This function is \threadsafe. * * \return A CameraConfiguration if the requested roles can be satisfied, or a - * null pointer otherwise. The ownership of the returned configuration is - * passed to the caller. + * null pointer otherwise. */ std::unique_ptr Camera::generateConfiguration(const StreamRoles &roles) { @@ -949,7 +948,8 @@ std::unique_ptr Camera::generateConfiguration(const StreamR if (roles.size() > streams().size()) return nullptr; - CameraConfiguration *config = d->pipe_->generateConfiguration(this, roles); + std::unique_ptr config = + d->pipe_->generateConfiguration(this, roles); if (!config) { LOG(Camera, Debug) << "Pipeline handler failed to generate configuration"; @@ -966,7 +966,7 @@ std::unique_ptr Camera::generateConfiguration(const StreamR LOG(Camera, Debug) << msg.str(); - return std::unique_ptr(config); + return config; } /** diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 3b892d9671c5..e4d79ea44aed 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -136,7 +136,7 @@ public: PipelineHandlerIPU3(CameraManager *manager); - CameraConfiguration *generateConfiguration(Camera *camera, + std::unique_ptr generateConfiguration(Camera *camera, const StreamRoles &roles) override; int configure(Camera *camera, CameraConfiguration *config) override; @@ -424,11 +424,12 @@ PipelineHandlerIPU3::PipelineHandlerIPU3(CameraManager *manager) { } -CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, - const StreamRoles &roles) +std::unique_ptr +PipelineHandlerIPU3::generateConfiguration(Camera *camera, const StreamRoles &roles) { IPU3CameraData *data = cameraData(camera); - IPU3CameraConfiguration *config = new IPU3CameraConfiguration(data); + std::unique_ptr config = + std::make_unique(data); if (roles.empty()) return config; @@ -494,7 +495,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, default: LOG(IPU3, Error) << "Requested stream role not supported: " << role; - delete config; return nullptr; } diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 343f8cb2c7ed..7c54550005fa 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -323,7 +323,8 @@ class PipelineHandlerRPi : public PipelineHandler public: PipelineHandlerRPi(CameraManager *manager); - CameraConfiguration *generateConfiguration(Camera *camera, const StreamRoles &roles) override; + std::unique_ptr generateConfiguration(Camera *camera, + const StreamRoles &roles) override; int configure(Camera *camera, CameraConfiguration *config) override; int exportFrameBuffers(Camera *camera, Stream *stream, @@ -561,11 +562,12 @@ PipelineHandlerRPi::PipelineHandlerRPi(CameraManager *manager) { } -CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera, - const StreamRoles &roles) +std::unique_ptr +PipelineHandlerRPi::generateConfiguration(Camera *camera, const StreamRoles &roles) { RPiCameraData *data = cameraData(camera); - CameraConfiguration *config = new RPiCameraConfiguration(data); + std::unique_ptr config = + std::make_unique(data); V4L2SubdeviceFormat sensorFormat; unsigned int bufferCount; PixelFormat pixelFormat; @@ -640,13 +642,11 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera, default: LOG(RPI, Error) << "Requested stream role not supported: " << role; - delete config; return nullptr; } if (rawCount > 1 || outCount > 2) { LOG(RPI, Error) << "Invalid stream roles requested"; - delete config; return nullptr; } diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 1418dc9a47fb..50da92d4d6f8 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -142,7 +142,7 @@ class PipelineHandlerRkISP1 : public PipelineHandler public: PipelineHandlerRkISP1(CameraManager *manager); - CameraConfiguration *generateConfiguration(Camera *camera, + std::unique_ptr generateConfiguration(Camera *camera, const StreamRoles &roles) override; int configure(Camera *camera, CameraConfiguration *config) override; @@ -539,7 +539,8 @@ PipelineHandlerRkISP1::PipelineHandlerRkISP1(CameraManager *manager) * Pipeline Operations */ -CameraConfiguration *PipelineHandlerRkISP1::generateConfiguration(Camera *camera, +std::unique_ptr +PipelineHandlerRkISP1::generateConfiguration(Camera *camera, const StreamRoles &roles) { RkISP1CameraData *data = cameraData(camera); @@ -550,7 +551,8 @@ CameraConfiguration *PipelineHandlerRkISP1::generateConfiguration(Camera *camera return nullptr; } - CameraConfiguration *config = new RkISP1CameraConfiguration(camera, data); + std::unique_ptr config = + std::make_unique(camera, data); if (roles.empty()) return config; @@ -595,7 +597,6 @@ CameraConfiguration *PipelineHandlerRkISP1::generateConfiguration(Camera *camera default: LOG(RkISP1, Warning) << "Requested stream role not supported: " << role; - delete config; return nullptr; } diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 37b3e7acd0a1..a32de7f36e13 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -311,8 +311,8 @@ class SimplePipelineHandler : public PipelineHandler public: SimplePipelineHandler(CameraManager *manager); - CameraConfiguration *generateConfiguration(Camera *camera, - const StreamRoles &roles) override; + std::unique_ptr generateConfiguration(Camera *camera, + const StreamRoles &roles) override; int configure(Camera *camera, CameraConfiguration *config) override; int exportFrameBuffers(Camera *camera, Stream *stream, @@ -1037,12 +1037,12 @@ SimplePipelineHandler::SimplePipelineHandler(CameraManager *manager) { } -CameraConfiguration *SimplePipelineHandler::generateConfiguration(Camera *camera, - const StreamRoles &roles) +std::unique_ptr +SimplePipelineHandler::generateConfiguration(Camera *camera, const StreamRoles &roles) { SimpleCameraData *data = cameraData(camera); - CameraConfiguration *config = - new SimpleCameraConfiguration(camera, data); + std::unique_ptr config = + std::make_unique(camera, data); if (roles.empty()) return config; diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index a28195450634..277465b72164 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -74,7 +74,7 @@ class PipelineHandlerUVC : public PipelineHandler public: PipelineHandlerUVC(CameraManager *manager); - CameraConfiguration *generateConfiguration(Camera *camera, + std::unique_ptr generateConfiguration(Camera *camera, const StreamRoles &roles) override; int configure(Camera *camera, CameraConfiguration *config) override; @@ -178,11 +178,13 @@ PipelineHandlerUVC::PipelineHandlerUVC(CameraManager *manager) { } -CameraConfiguration *PipelineHandlerUVC::generateConfiguration(Camera *camera, +std::unique_ptr +PipelineHandlerUVC::generateConfiguration(Camera *camera, const StreamRoles &roles) { UVCCameraData *data = cameraData(camera); - CameraConfiguration *config = new UVCCameraConfiguration(data); + std::unique_ptr config = + std::make_unique(data); if (roles.empty()) return config; diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp index f85d05f77a61..204f5ad73f6d 100644 --- a/src/libcamera/pipeline/vimc/vimc.cpp +++ b/src/libcamera/pipeline/vimc/vimc.cpp @@ -84,7 +84,7 @@ class PipelineHandlerVimc : public PipelineHandler public: PipelineHandlerVimc(CameraManager *manager); - CameraConfiguration *generateConfiguration(Camera *camera, + std::unique_ptr generateConfiguration(Camera *camera, const StreamRoles &roles) override; int configure(Camera *camera, CameraConfiguration *config) override; @@ -189,11 +189,13 @@ PipelineHandlerVimc::PipelineHandlerVimc(CameraManager *manager) { } -CameraConfiguration *PipelineHandlerVimc::generateConfiguration(Camera *camera, +std::unique_ptr +PipelineHandlerVimc::generateConfiguration(Camera *camera, const StreamRoles &roles) { VimcCameraData *data = cameraData(camera); - CameraConfiguration *config = new VimcCameraConfiguration(data); + std::unique_ptr config = + std::make_unique(data); if (roles.empty()) return config; diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index 588a3db30e82..825aff5ac20a 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -233,8 +233,7 @@ void PipelineHandler::unlockMediaDevices() * handler. * * \return A valid CameraConfiguration if the requested roles can be satisfied, - * or a null pointer otherwise. The ownership of the returned configuration is - * passed to the caller. + * or a null pointer otherwise. */ /** From patchwork Mon Oct 24 00:03:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17672 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 6AEF9C3286 for ; Mon, 24 Oct 2022 00:04:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F195B62F03; Mon, 24 Oct 2022 02:04:37 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1666569878; bh=yBe8pBqOPREEH/XvWbDIRYlizdhL1BOSbtQl4x1G/N0=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=vZ7b6gF5A8olhnNKr2OGS+/SQLLXKwFaB1g3SZshHyl5qCEDO6CHIGk+9FRQoS2Tr YRVfrbz99KOSbIVbDN6kcPrp0wK+SY0MAGcSTrbaUG8ePRRA53EXWDvembHUUh8MTH +DW0n+k6qq6DHmlsOibr7R2kVbMbpDtF4tv5eaEDqOtuJUa4D3s9LnP2w4ivoLsB67 /frTGF3mbzKPFFs2EOx9ZdxMRkVfzFLLmjvbia3gKTlJ8V7bNJMnEEZSoIT7c5q8x5 F3PtRWYNLBi74f0lA8a3THYG3rhO9sFdX4vpPspuAIFEpUVfby4cQDFFqk8FVl0hQx zC8FacUNcARhw== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A09DD62EE7 for ; Mon, 24 Oct 2022 02:04:33 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="kmOWe6VA"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 35660471; Mon, 24 Oct 2022 02:04:33 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1666569873; bh=yBe8pBqOPREEH/XvWbDIRYlizdhL1BOSbtQl4x1G/N0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kmOWe6VAQdVVTJzAt1Zbja14Zn/0H/nALXfpsBbs8f9j4JT3l0ud/gucD2SjuD/aC sSmZqJVeFhPCRc0BE20RcZ0IJu516w9+0qUrGuQy4zP/awGM6Qd+Zz7HQSfxAJ3Ohj z3QQ0y0NmoiNUgBxoVtPxq0UR13F01bqq3e0S7XY= To: libcamera-devel@lists.libcamera.org Date: Mon, 24 Oct 2022 03:03:52 +0300 Message-Id: <20221024000356.29521-10-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.37.4 In-Reply-To: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> References: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 09/13] pipeline: rkisp1: Pass info pointer to tryCompleteRequest() 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: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The tryCompleteRequest() function looks up the RkISP1FrameInfo that alls but one of its callers already look up. Remove the double look up by passing the info pointer to tryCompleteRequest(). Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Jacopo Mondi --- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 50da92d4d6f8..cca89cc13bff 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -168,7 +168,7 @@ private: int initLinks(Camera *camera, const CameraSensor *sensor, const RkISP1CameraConfiguration &config); int createCamera(MediaEntity *sensor); - void tryCompleteRequest(Request *request); + void tryCompleteRequest(RkISP1FrameInfo *info); void bufferReady(FrameBuffer *buffer); void paramReady(FrameBuffer *buffer); void statReady(FrameBuffer *buffer); @@ -391,7 +391,7 @@ void RkISP1CameraData::metadataReady(unsigned int frame, const ControlList &meta info->request->metadata().merge(metadata); info->metadataProcessed = true; - pipe()->tryCompleteRequest(info->request); + pipe()->tryCompleteRequest(info); } RkISP1CameraConfiguration::RkISP1CameraConfiguration(Camera *camera, @@ -1123,12 +1123,10 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) * Buffer Handling */ -void PipelineHandlerRkISP1::tryCompleteRequest(Request *request) +void PipelineHandlerRkISP1::tryCompleteRequest(RkISP1FrameInfo *info) { RkISP1CameraData *data = cameraData(activeCamera_); - RkISP1FrameInfo *info = data->frameInfo_.find(request); - if (!info) - return; + Request *request = info->request; if (request->hasPendingBuffers()) return; @@ -1146,6 +1144,13 @@ void PipelineHandlerRkISP1::tryCompleteRequest(Request *request) void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer) { + ASSERT(activeCamera_); + RkISP1CameraData *data = cameraData(activeCamera_); + + RkISP1FrameInfo *info = data->frameInfo_.find(buffer); + if (!info) + return; + Request *request = buffer->request(); /* @@ -1158,7 +1163,7 @@ void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer) buffer->metadata().timestamp); completeBuffer(request, buffer); - tryCompleteRequest(request); + tryCompleteRequest(info); } void PipelineHandlerRkISP1::paramReady(FrameBuffer *buffer) @@ -1171,7 +1176,7 @@ void PipelineHandlerRkISP1::paramReady(FrameBuffer *buffer) return; info->paramDequeued = true; - tryCompleteRequest(info->request); + tryCompleteRequest(info); } void PipelineHandlerRkISP1::statReady(FrameBuffer *buffer) @@ -1185,7 +1190,7 @@ void PipelineHandlerRkISP1::statReady(FrameBuffer *buffer) if (buffer->metadata().status == FrameMetadata::FrameCancelled) { info->metadataProcessed = true; - tryCompleteRequest(info->request); + tryCompleteRequest(info); return; } From patchwork Mon Oct 24 00:03:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17673 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 A9D66C328A for ; Mon, 24 Oct 2022 00:04:39 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3D5E362F00; Mon, 24 Oct 2022 02:04:39 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1666569879; bh=lXmxsGaajmMUMaQK4fbBRs1N2A8GSS2qalHjgA39cdw=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=lIz+4yZW0tsPIMrqdfbg+zt2+R7xawiNWCsiajpKjUGQqZzKEHpM4XYG8miBQdMmu 6+SFGAPRlIYqHUEziSm2fdwcJV14C0Ws9PQYotmElXA/IxPhRg2psdZ2wGTYsQeIX5 OHLTCh41+p4WShLToeUBpE6o0ZGRmwVz8SySmXq/9Ul3uL9ySKZQPNrk6aiM6sfOpR fhBjkMxyZmWtfY53iQPXiZCyoaIHz1sZPvwyZmFQJRA1UVd3K1QMgvyHZTWPXSj4gq NJXmC140vo8lwEVZQUTPTjZCfS4MsaY8RzqJKGbo1F4bNyaBUlshEZ6zmQuPgonva+ 0ZtEgPPQNwIhw== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0BA1262EF9 for ; Mon, 24 Oct 2022 02:04:35 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="UGl1L9GU"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8314C471; Mon, 24 Oct 2022 02:04:34 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1666569874; bh=lXmxsGaajmMUMaQK4fbBRs1N2A8GSS2qalHjgA39cdw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UGl1L9GU7v+i3QtK/Abb6dvvbXFh3oNrQD0JV1fqMp4A5TPmZt7zmZPgPHCNjXRMz sdsLw3Wy1ns02uWB7I1DsVpN1KOedgHw8A970woYijPZFrWOToW2bPV1sly5VnVlTB rYDXDkCzy7PdnRNgA57Ld/Ww+LLrCsDBz7rVP8b4= To: libcamera-devel@lists.libcamera.org Date: Mon, 24 Oct 2022 03:03:53 +0300 Message-Id: <20221024000356.29521-11-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.37.4 In-Reply-To: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> References: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 10/13] pipeline: rkisp1: Query the driver for formats 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: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Paul Elder Query the driver for the output formats and sizes that it supports, instead of hardcoding them. This allows future-proofing for formats that are supported by some but not all versions of the driver. As the rkisp1 driver currently does not support VIDIOC_ENUM_FRAMESIZES, fallback to the hardcoded list of supported formats and framesizes. This feature will be added to the driver in parallel, though we cannot guarantee that users will have a new enough kernel for it. Signed-off-by: Paul Elder Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- Changes since v2: - Don't pass V4L2VideoDevice to RkISP1Path::populateFormats() - Use structured binding in for range loop - Use std::set::count() to replace std::find_if() - Don't cache sizes, use std::set instead of std::map - Update min and max resolutions based on enumerated sizes - Drop comment about aspect ratio Changes since v1: - Enumerate and cache framesizes as well - Massage generateConfiguration accordingly - This lets us skip modifying V4L2VideoDevice::formats() to support lack of ENUM_FRAMESIZES - Also requires us to keep the list of hardcoded formats for backward compatibility --- src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 51 +++++++++++++++++-- src/libcamera/pipeline/rkisp1/rkisp1_path.h | 8 ++- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp index 2d38f0fb37ab..8077a54494a5 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp @@ -41,6 +41,8 @@ bool RkISP1Path::init(MediaDevice *media) if (video_->open() < 0) return false; + populateFormats(); + link_ = media->link("rkisp1_isp", 2, resizer, 0); if (!link_) return false; @@ -48,6 +50,41 @@ bool RkISP1Path::init(MediaDevice *media) return true; } +void RkISP1Path::populateFormats() +{ + V4L2VideoDevice::Formats v4l2Formats = video_->formats(); + if (v4l2Formats.empty()) { + LOG(RkISP1, Warning) + << "Failed to enumerate framesizes. Loading default framesizes"; + + for (const PixelFormat &format : formats_) + streamFormats_.insert(format); + return; + } + + minResolution_ = { 65535, 65535 }; + maxResolution_ = { 0, 0 }; + + std::vector formats; + for (const auto &[format, sizes] : v4l2Formats) { + const PixelFormat pixelFormat = format.toPixelFormat(); + const PixelFormatInfo &info = PixelFormatInfo::info(pixelFormat); + + /* \todo Add support for RAW formats. */ + if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) + continue; + + streamFormats_.insert(pixelFormat); + + for (const auto &size : sizes) { + if (minResolution_ > size.min) + minResolution_ = size.min; + if (maxResolution_ < size.max) + maxResolution_ = size.max; + } + } +} + StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution) { Size maxResolution = maxResolution_.boundedToAspectRatio(resolution) @@ -55,7 +92,7 @@ StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution) Size minResolution = minResolution_.expandedToAspectRatio(resolution); std::map> streamFormats; - for (const PixelFormat &format : formats_) + for (const auto &format : streamFormats_) streamFormats[format] = { { minResolution, maxResolution } }; StreamFormats formats(streamFormats); @@ -72,8 +109,12 @@ CameraConfiguration::Status RkISP1Path::validate(StreamConfiguration *cfg) const StreamConfiguration reqCfg = *cfg; CameraConfiguration::Status status = CameraConfiguration::Valid; - if (std::find(formats_.begin(), formats_.end(), cfg->pixelFormat) == - formats_.end()) + /* + * Default to NV12 if the requested format is not supported. All + * versions of the ISP are guaranteed to support NV12 on both the main + * and self paths. + */ + if (!streamFormats_.count(cfg->pixelFormat)) cfg->pixelFormat = formats::NV12; cfg->size.boundTo(maxResolution_); @@ -204,6 +245,10 @@ void RkISP1Path::stop() running_ = false; } +/* + * \todo Remove the hardcoded resolutions and formats once all users will have + * migrated to a recent enough kernel. + */ namespace { constexpr Size RKISP1_RSZ_MP_SRC_MIN{ 32, 16 }; constexpr Size RKISP1_RSZ_MP_SRC_MAX{ 4416, 3312 }; diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h index f3f1ae391d65..d88effbb6f56 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include #include @@ -57,14 +58,17 @@ public: Signal &bufferReady() { return video_->bufferReady; } private: + void populateFormats(); + static constexpr unsigned int RKISP1_BUFFER_COUNT = 4; const char *name_; bool running_; const Span formats_; - const Size minResolution_; - const Size maxResolution_; + std::set streamFormats_; + Size minResolution_; + Size maxResolution_; std::unique_ptr resizer_; std::unique_ptr video_; From patchwork Mon Oct 24 00:03:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17674 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 59BD7C328B for ; Mon, 24 Oct 2022 00:04:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D45B462F08; Mon, 24 Oct 2022 02:04:39 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1666569879; bh=4PooF5sHVc7qAJ/Kx6rffl96ItXM2SZY+ALQvtsoE2c=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=e3gVVW4q/s9pUnUeMpvRWEyTrHv5k848EAlCX16CxS+kgog67DQm92ppMX5EMKRzR 963RDm20CWURBjjGyak3WMA56hIW2EFPZdq3McNgi5Dc3E+WPfsbkdvWdI/F+ZY3T1 V72miDrL/lMAh+JnguvtWghuZW+rPemRbVDLIkW5DwK+hoD6eIvtLjVTzPXegJAFnz bG2pmI8WgLPN89R/hxWEp0Ec343L57tprcsJRU0FWuvksvuj3tBn/2sT7t04roUMu4 /ZmS0FMTO125Pjv5wp7NtekqbSqNPEjjtE+1+WZX/gTk4G6xGaXb+cu6C+5mV5aqHr XZ6AgC1QNvzLg== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4264962EDF for ; Mon, 24 Oct 2022 02:04:36 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="YqtqsQxr"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C9998471; Mon, 24 Oct 2022 02:04:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1666569876; bh=4PooF5sHVc7qAJ/Kx6rffl96ItXM2SZY+ALQvtsoE2c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YqtqsQxrSi7xk+g1sA0h3M460R6RphgeHbFNiBdowESsCnnwBrsjs7zo/MzPTJ+wF LGlne04DulguSNW9g1NQyE2RdOiTS1ybA0p9lazK/lISj2kjv2qcIptbVLmqgx7p3r AKRR1RkX7YQfw1IT/6Rz6+uwOOtc/v8I2rPmRzsI= To: libcamera-devel@lists.libcamera.org Date: Mon, 24 Oct 2022 03:03:54 +0300 Message-Id: <20221024000356.29521-12-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.37.4 In-Reply-To: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> References: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 11/13] pipeline: rkisp1: Fix stream size validation 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: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Unlike RkISP1Path::generateConfiguration(), the validate() function doesn't take the camera sensor resolution into account but only considers the absolute minimum and maximum sizes support by the ISP to validate the stream size. Fix it by using the same logic as when generating the configuration. Instead of passing the sensor resolution to the validate() function, pass the CameraSensor pointer to prepare for subsequent changes that will require access to more camera sensor data. While at it, update the generateConfiguration() function similarly for the same reason. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Jacopo Mondi --- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 17 +++++++------- src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 22 +++++++++++++++---- src/libcamera/pipeline/rkisp1/rkisp1_path.h | 6 +++-- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index cca89cc13bff..dcab5286aa56 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -404,14 +404,15 @@ RkISP1CameraConfiguration::RkISP1CameraConfiguration(Camera *camera, bool RkISP1CameraConfiguration::fitsAllPaths(const StreamConfiguration &cfg) { + const CameraSensor *sensor = data_->sensor_.get(); StreamConfiguration config; config = cfg; - if (data_->mainPath_->validate(&config) != Valid) + if (data_->mainPath_->validate(sensor, &config) != Valid) return false; config = cfg; - if (data_->selfPath_ && data_->selfPath_->validate(&config) != Valid) + if (data_->selfPath_ && data_->selfPath_->validate(sensor, &config) != Valid) return false; return true; @@ -459,7 +460,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() /* Try to match stream without adjusting configuration. */ if (mainPathAvailable) { StreamConfiguration tryCfg = cfg; - if (data_->mainPath_->validate(&tryCfg) == Valid) { + if (data_->mainPath_->validate(sensor, &tryCfg) == Valid) { mainPathAvailable = false; cfg = tryCfg; cfg.setStream(const_cast(&data_->mainPathStream_)); @@ -469,7 +470,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() if (selfPathAvailable) { StreamConfiguration tryCfg = cfg; - if (data_->selfPath_->validate(&tryCfg) == Valid) { + if (data_->selfPath_->validate(sensor, &tryCfg) == Valid) { selfPathAvailable = false; cfg = tryCfg; cfg.setStream(const_cast(&data_->selfPathStream_)); @@ -480,7 +481,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() /* Try to match stream allowing adjusting configuration. */ if (mainPathAvailable) { StreamConfiguration tryCfg = cfg; - if (data_->mainPath_->validate(&tryCfg) == Adjusted) { + if (data_->mainPath_->validate(sensor, &tryCfg) == Adjusted) { mainPathAvailable = false; cfg = tryCfg; cfg.setStream(const_cast(&data_->mainPathStream_)); @@ -491,7 +492,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() if (selfPathAvailable) { StreamConfiguration tryCfg = cfg; - if (data_->selfPath_->validate(&tryCfg) == Adjusted) { + if (data_->selfPath_->validate(sensor, &tryCfg) == Adjusted) { selfPathAvailable = false; cfg = tryCfg; cfg.setStream(const_cast(&data_->selfPathStream_)); @@ -603,11 +604,11 @@ PipelineHandlerRkISP1::generateConfiguration(Camera *camera, StreamConfiguration cfg; if (useMainPath) { cfg = data->mainPath_->generateConfiguration( - data->sensor_->resolution()); + data->sensor_.get()); mainPathAvailable = false; } else { cfg = data->selfPath_->generateConfiguration( - data->sensor_->resolution()); + data->sensor_.get()); selfPathAvailable = false; } diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp index 8077a54494a5..cc2ac66e6939 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp @@ -12,6 +12,7 @@ #include #include +#include "libcamera/internal/camera_sensor.h" #include "libcamera/internal/media_device.h" #include "libcamera/internal/v4l2_subdevice.h" #include "libcamera/internal/v4l2_videodevice.h" @@ -85,8 +86,10 @@ void RkISP1Path::populateFormats() } } -StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution) +StreamConfiguration RkISP1Path::generateConfiguration(const CameraSensor *sensor) { + const Size &resolution = sensor->resolution(); + Size maxResolution = maxResolution_.boundedToAspectRatio(resolution) .boundedTo(resolution); Size minResolution = minResolution_.expandedToAspectRatio(resolution); @@ -104,8 +107,11 @@ StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution) return cfg; } -CameraConfiguration::Status RkISP1Path::validate(StreamConfiguration *cfg) +CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor, + StreamConfiguration *cfg) { + const Size &resolution = sensor->resolution(); + const StreamConfiguration reqCfg = *cfg; CameraConfiguration::Status status = CameraConfiguration::Valid; @@ -117,8 +123,16 @@ CameraConfiguration::Status RkISP1Path::validate(StreamConfiguration *cfg) if (!streamFormats_.count(cfg->pixelFormat)) cfg->pixelFormat = formats::NV12; - cfg->size.boundTo(maxResolution_); - cfg->size.expandTo(minResolution_); + /* + * Adjust the size based on the sensor resolution and absolute limits + * of the ISP. + */ + Size maxResolution = maxResolution_.boundedToAspectRatio(resolution) + .boundedTo(resolution); + Size minResolution = minResolution_.expandedToAspectRatio(resolution); + + cfg->size.boundTo(maxResolution); + cfg->size.expandTo(minResolution); cfg->bufferCount = RKISP1_BUFFER_COUNT; V4L2DeviceFormat format; diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h index d88effbb6f56..bf4ad18fbbf2 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h @@ -23,6 +23,7 @@ namespace libcamera { +class CameraSensor; class MediaDevice; class V4L2Subdevice; struct StreamConfiguration; @@ -39,8 +40,9 @@ public: int setEnabled(bool enable) { return link_->setEnabled(enable); } bool isEnabled() const { return link_->flags() & MEDIA_LNK_FL_ENABLED; } - StreamConfiguration generateConfiguration(const Size &resolution); - CameraConfiguration::Status validate(StreamConfiguration *cfg); + StreamConfiguration generateConfiguration(const CameraSensor *sensor); + CameraConfiguration::Status validate(const CameraSensor *sensor, + StreamConfiguration *cfg); int configure(const StreamConfiguration &config, const V4L2SubdeviceFormat &inputFormat); From patchwork Mon Oct 24 00:03:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17675 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 49829BD16B for ; Mon, 24 Oct 2022 00:04:43 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 06D3562EDF; Mon, 24 Oct 2022 02:04:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1666569883; bh=YTaYpDITiY7M40evmlcVErHC0HbEYRpFebqm3O/T4pA=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=rwfQ557ZUj7eZjw4G87WeSUY2fggiAXtUZa5TuGUD/lAYmVD7mRABsRKH7wnROWiN 4rSqf4qRyiDmG8qGUcNEF+RB/Tw3tTeEeDDtp4yVuQetZs6OqSkgrZwe9Jb7nbmUin iWXKm3RWI0BOaIaEvX0P9m62YsL0R/gcQkFuplKHajhlvNmpIBv25YAbjgOOZxkS8O LU68ODltoePnQmN9jNgFW8eel0SDb4C7HKLycOwl9dtWR5TauZAfONZ2BFkVu4VQ0w T/0A8g9/7PhrGP46RnhbXMxaMs0qZSW1QpwT93e9Pt4EZZvVU1c9W+Sq7X+7Af++5c bMtx7CZUta4/g== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8757562F02 for ; Mon, 24 Oct 2022 02:04:37 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ZpXxCQeF"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 11B5588F; Mon, 24 Oct 2022 02:04:37 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1666569877; bh=YTaYpDITiY7M40evmlcVErHC0HbEYRpFebqm3O/T4pA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZpXxCQeFfA8KfdOxF3X7IxPrRRvrBjdctW9p0ItO+mAzQ5UKD+yStXwEaVhjpQrlF nWi71kzEKqvoewV5t1gZ25zV1VBpQMd/8aSIQPDW5F88YhuGL84jxjqJYF1qcxGkUK pNVbwGu/Tzr+z1kjdTcyoDPZDIY+GsNU8lscPmpI= To: libcamera-devel@lists.libcamera.org Date: Mon, 24 Oct 2022 03:03:55 +0300 Message-Id: <20221024000356.29521-13-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.37.4 In-Reply-To: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> References: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 12/13] pipeline: rkisp1: Support raw Bayer capture at runtime 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: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Florian Sylvestre Implement support for raw Bayer capture at runtime, from start() to stop(). Support of raw formats in the camera configuration is split to a subsequent change to ease review. In raw mode, the ISP is bypassed. There is no need to provide parameter buffers, and the ISP will not generate statistics. This requires multiple changes in the buffer handling: - The params and stats buffers don't need to be allocated, and the corresponding video nodes don't need to be started or stopped. - The IPA module fillParamsBuffer() operation must not be called in queueRequestDevice(). As a result, the IPA module thus doesn't emit the paramsBufferReady signal. The main and self path video buffers must thus be queued directly in queueRequestDevice(). - The tryCompleteRequest() function must not to wait until the params buffer has been dequeued. - When the frame buffer has been captured, the IPA module processStatsBuffer() operation must be called directly to fill request metadata. Signed-off-by: Florian Sylvestre Signed-off-by: Paul Elder Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Tested-by: Jacopo Mondi Reviewed-by: Jacopo Mondi --- Changes since v3: - Split from "pipeline: rkisp1: Support raw Bayer capture" - Drop new completeRaw() IPA operation - Don't queue params buffers in raw capture mode - Fix assertion failure when stopping capture --- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 148 ++++++++++++++--------- 1 file changed, 93 insertions(+), 55 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index dcab5286aa56..e57411544f7a 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -67,7 +67,8 @@ class RkISP1Frames public: RkISP1Frames(PipelineHandler *pipe); - RkISP1FrameInfo *create(const RkISP1CameraData *data, Request *request); + RkISP1FrameInfo *create(const RkISP1CameraData *data, Request *request, + bool isRaw); int destroy(unsigned int frame); void clear(); @@ -184,6 +185,7 @@ private: std::unique_ptr csi_; bool hasSelfPath_; + bool isRaw_; RkISP1MainPath mainPath_; RkISP1SelfPath selfPath_; @@ -203,28 +205,35 @@ RkISP1Frames::RkISP1Frames(PipelineHandler *pipe) { } -RkISP1FrameInfo *RkISP1Frames::create(const RkISP1CameraData *data, Request *request) +RkISP1FrameInfo *RkISP1Frames::create(const RkISP1CameraData *data, Request *request, + bool isRaw) { unsigned int frame = data->frame_; - if (pipe_->availableParamBuffers_.empty()) { - LOG(RkISP1, Error) << "Parameters buffer underrun"; - return nullptr; - } - FrameBuffer *paramBuffer = pipe_->availableParamBuffers_.front(); + FrameBuffer *paramBuffer = nullptr; + FrameBuffer *statBuffer = nullptr; + + if (!isRaw) { + if (pipe_->availableParamBuffers_.empty()) { + LOG(RkISP1, Error) << "Parameters buffer underrun"; + return nullptr; + } + + if (pipe_->availableStatBuffers_.empty()) { + LOG(RkISP1, Error) << "Statisitc buffer underrun"; + return nullptr; + } + + paramBuffer = pipe_->availableParamBuffers_.front(); + pipe_->availableParamBuffers_.pop(); - if (pipe_->availableStatBuffers_.empty()) { - LOG(RkISP1, Error) << "Statisitc buffer underrun"; - return nullptr; + statBuffer = pipe_->availableStatBuffers_.front(); + pipe_->availableStatBuffers_.pop(); } - FrameBuffer *statBuffer = pipe_->availableStatBuffers_.front(); FrameBuffer *mainPathBuffer = request->findBuffer(&data->mainPathStream_); FrameBuffer *selfPathBuffer = request->findBuffer(&data->selfPathStream_); - pipe_->availableParamBuffers_.pop(); - pipe_->availableStatBuffers_.pop(); - RkISP1FrameInfo *info = new RkISP1FrameInfo; info->frame = frame; @@ -665,6 +674,8 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c) << "ISP input pad configured with " << format << " crop " << rect; + isRaw_ = false; + /* YUYV8_2X8 is required on the ISP source path pad for YUV output. */ format.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8; LOG(RkISP1, Debug) @@ -760,13 +771,15 @@ int PipelineHandlerRkISP1::allocateBuffers(Camera *camera) data->selfPathStream_.configuration().bufferCount, }); - ret = param_->allocateBuffers(maxCount, ¶mBuffers_); - if (ret < 0) - goto error; + if (!isRaw_) { + ret = param_->allocateBuffers(maxCount, ¶mBuffers_); + if (ret < 0) + goto error; - ret = stat_->allocateBuffers(maxCount, &statBuffers_); - if (ret < 0) - goto error; + ret = stat_->allocateBuffers(maxCount, &statBuffers_); + if (ret < 0) + goto error; + } for (std::unique_ptr &buffer : paramBuffers_) { buffer->setCookie(ipaBufferId++); @@ -842,23 +855,25 @@ int PipelineHandlerRkISP1::start(Camera *camera, [[maybe_unused]] const ControlL data->frame_ = 0; - ret = param_->streamOn(); - if (ret) { - data->ipa_->stop(); - freeBuffers(camera); - LOG(RkISP1, Error) - << "Failed to start parameters " << camera->id(); - return ret; - } + if (!isRaw_) { + ret = param_->streamOn(); + if (ret) { + data->ipa_->stop(); + freeBuffers(camera); + LOG(RkISP1, Error) + << "Failed to start parameters " << camera->id(); + return ret; + } - ret = stat_->streamOn(); - if (ret) { - param_->streamOff(); - data->ipa_->stop(); - freeBuffers(camera); - LOG(RkISP1, Error) - << "Failed to start statistics " << camera->id(); - return ret; + ret = stat_->streamOn(); + if (ret) { + param_->streamOff(); + data->ipa_->stop(); + freeBuffers(camera); + LOG(RkISP1, Error) + << "Failed to start statistics " << camera->id(); + return ret; + } } if (data->mainPath_->isEnabled()) { @@ -903,15 +918,17 @@ void PipelineHandlerRkISP1::stopDevice(Camera *camera) selfPath_.stop(); mainPath_.stop(); - ret = stat_->streamOff(); - if (ret) - LOG(RkISP1, Warning) - << "Failed to stop statistics for " << camera->id(); + if (!isRaw_) { + ret = stat_->streamOff(); + if (ret) + LOG(RkISP1, Warning) + << "Failed to stop statistics for " << camera->id(); - ret = param_->streamOff(); - if (ret) - LOG(RkISP1, Warning) - << "Failed to stop parameters for " << camera->id(); + ret = param_->streamOff(); + if (ret) + LOG(RkISP1, Warning) + << "Failed to stop parameters for " << camera->id(); + } ASSERT(data->queuedRequests_.empty()); data->frameInfo_.clear(); @@ -925,12 +942,21 @@ int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request) { RkISP1CameraData *data = cameraData(camera); - RkISP1FrameInfo *info = data->frameInfo_.create(data, request); + RkISP1FrameInfo *info = data->frameInfo_.create(data, request, isRaw_); if (!info) return -ENOENT; data->ipa_->queueRequest(data->frame_, request->controls()); - data->ipa_->fillParamsBuffer(data->frame_, info->paramBuffer->cookie()); + if (isRaw_) { + if (info->mainPathBuffer) + data->mainPath_->queueBuffer(info->mainPathBuffer); + + if (data->selfPath_ && info->selfPathBuffer) + data->selfPath_->queueBuffer(info->selfPathBuffer); + } else { + data->ipa_->fillParamsBuffer(data->frame_, + info->paramBuffer->cookie()); + } data->frame_++; @@ -1135,7 +1161,7 @@ void PipelineHandlerRkISP1::tryCompleteRequest(RkISP1FrameInfo *info) if (!info->metadataProcessed) return; - if (!info->paramDequeued) + if (!isRaw_ && !info->paramDequeued) return; data->frameInfo_.destroy(info->frame); @@ -1152,16 +1178,28 @@ void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer) if (!info) return; + const FrameMetadata &metadata = buffer->metadata(); Request *request = buffer->request(); - /* - * Record the sensor's timestamp in the request metadata. - * - * \todo The sensor timestamp should be better estimated by connecting - * to the V4L2Device::frameStart signal. - */ - request->metadata().set(controls::SensorTimestamp, - buffer->metadata().timestamp); + if (metadata.status != FrameMetadata::FrameCancelled) { + /* + * Record the sensor's timestamp in the request metadata. + * + * \todo The sensor timestamp should be better estimated by connecting + * to the V4L2Device::frameStart signal. + */ + request->metadata().set(controls::SensorTimestamp, + metadata.timestamp); + + if (isRaw_) { + const ControlList &ctrls = + data->delayedCtrls_->get(metadata.sequence); + data->ipa_->processStatsBuffer(info->frame, 0, ctrls); + } + } else { + if (isRaw_) + info->metadataProcessed = true; + } completeBuffer(request, buffer); tryCompleteRequest(info); From patchwork Mon Oct 24 00:03:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17676 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 C5E81C328C for ; Mon, 24 Oct 2022 00:04:43 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 674AB62EDB; Mon, 24 Oct 2022 02:04:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1666569883; bh=nWH6bgiJFff13tvz948iLbgD+gVkWhWQtZXSjMKi/no=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=PXBpY87mdS5IHp+n7g9oyhco1Sgzbaj+rWxrmxZ6aG0Bl6ZcPkg8cAVy7TWoeFeWD 1CAQgG3ydfRnywsI+bTwa0kmHL1vEDfswjnW2jaaZvXkfsU8pE7YYRu9qN/pWPUz3e faUpTP9tfeoqszu5itLC+I8Riii3zMjFUueHC1Va5s7Hp8knifhaozwQIJVeMgfCNG jXlfRNv3G4K6wAdpqgm1vvAQvKm6c0WnUMTQHDtn2owBhJZ2ATfiaU608Q5DxXp18s niPV83vk9YJ531Yb0Gj5vb89iKVrNEg4pw+MRpa0keoSU6dZlPYNGxElWf/PF4BSPA oUMWWMJKshU/g== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D45D662F05 for ; Mon, 24 Oct 2022 02:04:38 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="HMCzZK2m"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 61665471; Mon, 24 Oct 2022 02:04:38 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1666569878; bh=nWH6bgiJFff13tvz948iLbgD+gVkWhWQtZXSjMKi/no=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HMCzZK2m50BX1xg6NI/NExWmkxPoEMe/CMz873ByNCXV73xEobIaIBIPFPrK0lkhS qlcSxZPGrQrkJWS97HoJLrRxxM7KFpy6hSbTc9nTPF5M36OFoorPgBQg0XMXPiqyZj UKLXC/Kg/3pmJvKt+cApyVKwTVdm3n/m0osiR0m0= To: libcamera-devel@lists.libcamera.org Date: Mon, 24 Oct 2022 03:03:56 +0300 Message-Id: <20221024000356.29521-14-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.37.4 In-Reply-To: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> References: <20221024000356.29521-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 13/13] pipeline: rkisp1: Support raw Bayer capture configuration 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: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Florian Sylvestre Implement support for raw Bayer capture during configuration generation, validation and camera configuration. While at it, fix a typo in a comment. Signed-off-by: Florian Sylvestre Signed-off-by: Paul Elder Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Jacopo Mondi --- Changes since v2: - Nearly complete rewrite --- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 116 +++++++--- src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 209 +++++++++++++++--- src/libcamera/pipeline/rkisp1/rkisp1_path.h | 3 +- 3 files changed, 273 insertions(+), 55 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index e57411544f7a..891fd2d50270 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -403,6 +403,30 @@ void RkISP1CameraData::metadataReady(unsigned int frame, const ControlList &meta pipe()->tryCompleteRequest(info); } +/* ----------------------------------------------------------------------------- + * Camera Configuration + */ + +namespace { + +/* Keep in sync with the supported raw formats in rkisp1_path.cpp. */ +const std::map rawFormats = { + { formats::SBGGR8, MEDIA_BUS_FMT_SBGGR8_1X8 }, + { formats::SGBRG8, MEDIA_BUS_FMT_SGBRG8_1X8 }, + { formats::SGRBG8, MEDIA_BUS_FMT_SGRBG8_1X8 }, + { formats::SRGGB8, MEDIA_BUS_FMT_SRGGB8_1X8 }, + { formats::SBGGR10, MEDIA_BUS_FMT_SBGGR10_1X10 }, + { formats::SGBRG10, MEDIA_BUS_FMT_SGBRG10_1X10 }, + { formats::SGRBG10, MEDIA_BUS_FMT_SGRBG10_1X10 }, + { formats::SRGGB10, MEDIA_BUS_FMT_SRGGB10_1X10 }, + { formats::SBGGR12, MEDIA_BUS_FMT_SBGGR12_1X12 }, + { formats::SGBRG12, MEDIA_BUS_FMT_SGBRG12_1X12 }, + { formats::SGRBG12, MEDIA_BUS_FMT_SGRBG12_1X12 }, + { formats::SRGGB12, MEDIA_BUS_FMT_SRGGB12_1X12 }, +}; + +} /* namespace */ + RkISP1CameraConfiguration::RkISP1CameraConfiguration(Camera *camera, RkISP1CameraData *data) : CameraConfiguration() @@ -449,6 +473,21 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() status = Adjusted; } + /* + * Simultaneous capture of raw and processed streams isn't possible. If + * there is any raw stream, cap the number of streams to one. + */ + if (config_.size() > 1) { + for (const auto &cfg : config_) { + if (PixelFormatInfo::info(cfg.pixelFormat).colourEncoding == + PixelFormatInfo::ColourEncodingRAW) { + config_.resize(1); + status = Adjusted; + } + break; + } + } + /* * If there are more than one stream in the configuration figure out the * order to evaluate the streams. The first stream has the highest @@ -510,45 +549,51 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() } } - /* All paths rejected configuraiton. */ + /* All paths rejected configuration. */ LOG(RkISP1, Debug) << "Camera configuration not supported " << cfg.toString(); return Invalid; } /* Select the sensor format. */ + PixelFormat rawFormat; Size maxSize; - for (const StreamConfiguration &cfg : config_) + + for (const StreamConfiguration &cfg : config_) { + const PixelFormatInfo &info = PixelFormatInfo::info(cfg.pixelFormat); + if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) + rawFormat = cfg.pixelFormat; + maxSize = std::max(maxSize, cfg.size); + } + + std::vector mbusCodes; + + if (rawFormat.isValid()) { + mbusCodes = { rawFormats.at(rawFormat) }; + } else { + std::transform(rawFormats.begin(), rawFormats.end(), + std::back_inserter(mbusCodes), + [](const auto &value) { return value.second; }); + } + + sensorFormat_ = sensor->getFormat(mbusCodes, maxSize); - sensorFormat_ = sensor->getFormat({ MEDIA_BUS_FMT_SBGGR12_1X12, - MEDIA_BUS_FMT_SGBRG12_1X12, - MEDIA_BUS_FMT_SGRBG12_1X12, - MEDIA_BUS_FMT_SRGGB12_1X12, - MEDIA_BUS_FMT_SBGGR10_1X10, - MEDIA_BUS_FMT_SGBRG10_1X10, - MEDIA_BUS_FMT_SGRBG10_1X10, - MEDIA_BUS_FMT_SRGGB10_1X10, - MEDIA_BUS_FMT_SBGGR8_1X8, - MEDIA_BUS_FMT_SGBRG8_1X8, - MEDIA_BUS_FMT_SGRBG8_1X8, - MEDIA_BUS_FMT_SRGGB8_1X8 }, - maxSize); if (sensorFormat_.size.isNull()) sensorFormat_.size = sensor->resolution(); return status; } +/* ----------------------------------------------------------------------------- + * Pipeline Operations + */ + PipelineHandlerRkISP1::PipelineHandlerRkISP1(CameraManager *manager) : PipelineHandler(manager), hasSelfPath_(true) { } -/* ----------------------------------------------------------------------------- - * Pipeline Operations - */ - std::unique_ptr PipelineHandlerRkISP1::generateConfiguration(Camera *camera, const StreamRoles &roles) @@ -604,23 +649,38 @@ PipelineHandlerRkISP1::generateConfiguration(Camera *camera, colorSpace = ColorSpace::Rec709; break; + case StreamRole::Raw: + if (roles.size() > 1) { + LOG(RkISP1, Error) + << "Can't capture both raw and processed streams"; + return nullptr; + } + + useMainPath = true; + colorSpace = ColorSpace::Raw; + break; + default: LOG(RkISP1, Warning) << "Requested stream role not supported: " << role; return nullptr; } - StreamConfiguration cfg; + RkISP1Path *path; + if (useMainPath) { - cfg = data->mainPath_->generateConfiguration( - data->sensor_.get()); + path = data->mainPath_; mainPathAvailable = false; } else { - cfg = data->selfPath_->generateConfiguration( - data->sensor_.get()); + path = data->selfPath_; selfPathAvailable = false; } + StreamConfiguration cfg = + path->generateConfiguration(data->sensor_.get(), role); + if (!cfg.pixelFormat.isValid()) + return nullptr; + cfg.colorSpace = colorSpace; config->addConfiguration(cfg); } @@ -674,10 +734,14 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c) << "ISP input pad configured with " << format << " crop " << rect; - isRaw_ = false; + const PixelFormat &streamFormat = config->at(0).pixelFormat; + const PixelFormatInfo &info = PixelFormatInfo::info(streamFormat); + isRaw_ = info.colourEncoding == PixelFormatInfo::ColourEncodingRAW; /* YUYV8_2X8 is required on the ISP source path pad for YUV output. */ - format.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8; + if (!isRaw_) + format.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8; + LOG(RkISP1, Debug) << "Configuring ISP output pad with " << format << " crop " << rect; diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp index cc2ac66e6939..2994bd665ebb 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp @@ -21,6 +21,39 @@ namespace libcamera { LOG_DECLARE_CATEGORY(RkISP1) +namespace { + +/* Keep in sync with the supported raw formats in rkisp1.cpp. */ +const std::map formatToMediaBus = { + { formats::UYVY, MEDIA_BUS_FMT_YUYV8_2X8 }, + { formats::YUYV, MEDIA_BUS_FMT_YUYV8_2X8 }, + { formats::NV12, MEDIA_BUS_FMT_YUYV8_1_5X8 }, + { formats::NV21, MEDIA_BUS_FMT_YUYV8_1_5X8 }, + { formats::NV16, MEDIA_BUS_FMT_YUYV8_2X8 }, + { formats::NV61, MEDIA_BUS_FMT_YUYV8_2X8 }, + { formats::YUV420, MEDIA_BUS_FMT_YUYV8_1_5X8 }, + { formats::YVU420, MEDIA_BUS_FMT_YUYV8_1_5X8 }, + { formats::YUV422, MEDIA_BUS_FMT_YUYV8_2X8 }, + { formats::YVU422, MEDIA_BUS_FMT_YUYV8_2X8 }, + { formats::R8, MEDIA_BUS_FMT_YUYV8_2X8 }, + { formats::RGB565, MEDIA_BUS_FMT_YUYV8_2X8 }, + { formats::XRGB8888, MEDIA_BUS_FMT_YUYV8_2X8 }, + { formats::SBGGR8, MEDIA_BUS_FMT_SBGGR8_1X8 }, + { formats::SGBRG8, MEDIA_BUS_FMT_SGBRG8_1X8 }, + { formats::SGRBG8, MEDIA_BUS_FMT_SGRBG8_1X8 }, + { formats::SRGGB8, MEDIA_BUS_FMT_SRGGB8_1X8 }, + { formats::SBGGR10, MEDIA_BUS_FMT_SBGGR10_1X10 }, + { formats::SGBRG10, MEDIA_BUS_FMT_SGBRG10_1X10 }, + { formats::SGRBG10, MEDIA_BUS_FMT_SGRBG10_1X10 }, + { formats::SRGGB10, MEDIA_BUS_FMT_SRGGB10_1X10 }, + { formats::SBGGR12, MEDIA_BUS_FMT_SBGGR12_1X12 }, + { formats::SGBRG12, MEDIA_BUS_FMT_SGBRG12_1X12 }, + { formats::SGRBG12, MEDIA_BUS_FMT_SGRBG12_1X12 }, + { formats::SRGGB12, MEDIA_BUS_FMT_SRGGB12_1X12 }, +}; + +} /* namespace */ + RkISP1Path::RkISP1Path(const char *name, const Span &formats, const Size &minResolution, const Size &maxResolution) : name_(name), running_(false), formats_(formats), @@ -69,11 +102,18 @@ void RkISP1Path::populateFormats() std::vector formats; for (const auto &[format, sizes] : v4l2Formats) { const PixelFormat pixelFormat = format.toPixelFormat(); - const PixelFormatInfo &info = PixelFormatInfo::info(pixelFormat); - /* \todo Add support for RAW formats. */ - if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) + /* + * As a defensive measure, skip any pixel format exposed by the + * driver that we don't know about. This ensures that looking up + * formats in formatToMediaBus using a key from streamFormats_ + * will never fail in any of the other functions. + */ + if (!formatToMediaBus.count(pixelFormat)) { + LOG(RkISP1, Warning) + << "Unsupported pixel format " << pixelFormat; continue; + } streamFormats_.insert(pixelFormat); @@ -86,21 +126,68 @@ void RkISP1Path::populateFormats() } } -StreamConfiguration RkISP1Path::generateConfiguration(const CameraSensor *sensor) +StreamConfiguration +RkISP1Path::generateConfiguration(const CameraSensor *sensor, StreamRole role) { + const std::vector &mbusCodes = sensor->mbusCodes(); const Size &resolution = sensor->resolution(); Size maxResolution = maxResolution_.boundedToAspectRatio(resolution) .boundedTo(resolution); Size minResolution = minResolution_.expandedToAspectRatio(resolution); + /* Create the list of supported stream formats. */ std::map> streamFormats; - for (const auto &format : streamFormats_) - streamFormats[format] = { { minResolution, maxResolution } }; + unsigned int rawBitsPerPixel = 0; + PixelFormat rawFormat; + + for (const auto &format : streamFormats_) { + const PixelFormatInfo &info = PixelFormatInfo::info(format); + + if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) { + /* Skip raw formats not supported by the sensor. */ + uint32_t mbusCode = formatToMediaBus.at(format); + if (std::find(mbusCodes.begin(), mbusCodes.end(), mbusCode) == + mbusCodes.end()) + continue; + + streamFormats[format] = { { resolution, resolution } }; + + /* + * Store the raw format with the higher bits per pixel + * for later usage. + */ + if (info.bitsPerPixel > rawBitsPerPixel) { + rawBitsPerPixel = info.bitsPerPixel; + rawFormat = format; + } + } else { + streamFormats[format] = { { minResolution, maxResolution } }; + } + } + + /* + * Pick a suitable pixel format for the role. Raw streams need to use a + * raw format, processed streams use NV12 by default. + */ + PixelFormat format; + + if (role == StreamRole::Raw) { + if (!rawFormat.isValid()) { + LOG(RkISP1, Error) + << "Sensor " << sensor->model() + << " doesn't support raw capture"; + return {}; + } + + format = rawFormat; + } else { + format = formats::NV12; + } StreamFormats formats(streamFormats); StreamConfiguration cfg(formats); - cfg.pixelFormat = formats::NV12; + cfg.pixelFormat = format; cfg.size = maxResolution; cfg.bufferCount = RKISP1_BUFFER_COUNT; @@ -110,26 +197,85 @@ StreamConfiguration RkISP1Path::generateConfiguration(const CameraSensor *sensor CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor, StreamConfiguration *cfg) { + const std::vector &mbusCodes = sensor->mbusCodes(); const Size &resolution = sensor->resolution(); const StreamConfiguration reqCfg = *cfg; CameraConfiguration::Status status = CameraConfiguration::Valid; /* - * Default to NV12 if the requested format is not supported. All - * versions of the ISP are guaranteed to support NV12 on both the main - * and self paths. + * Validate the pixel format. If the requested format isn't supported, + * default to either NV12 (all versions of the ISP are guaranteed to + * support NV12 on both the main and self paths) if the requested format + * is not a raw format, or to the supported raw format with the highest + * bits per pixel otherwise. */ - if (!streamFormats_.count(cfg->pixelFormat)) - cfg->pixelFormat = formats::NV12; + unsigned int rawBitsPerPixel = 0; + PixelFormat rawFormat; + bool found = false; + + for (const auto &format : streamFormats_) { + const PixelFormatInfo &info = PixelFormatInfo::info(format); + + if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) { + /* Skip raw formats not supported by the sensor. */ + uint32_t mbusCode = formatToMediaBus.at(format); + if (std::find(mbusCodes.begin(), mbusCodes.end(), mbusCode) == + mbusCodes.end()) + continue; + + /* + * Store the raw format with the higher bits per pixel + * for later usage. + */ + if (info.bitsPerPixel > rawBitsPerPixel) { + rawBitsPerPixel = info.bitsPerPixel; + rawFormat = format; + } + } + + if (cfg->pixelFormat == format) { + found = true; + break; + } + } + + bool isRaw = PixelFormatInfo::info(cfg->pixelFormat).colourEncoding == + PixelFormatInfo::ColourEncodingRAW; /* - * Adjust the size based on the sensor resolution and absolute limits - * of the ISP. + * If no raw format supported by the sensor has been found, use a + * processed format. */ - Size maxResolution = maxResolution_.boundedToAspectRatio(resolution) - .boundedTo(resolution); - Size minResolution = minResolution_.expandedToAspectRatio(resolution); + if (!rawFormat.isValid()) + isRaw = false; + + if (!found) + cfg->pixelFormat = isRaw ? rawFormat : formats::NV12; + + Size minResolution; + Size maxResolution; + + if (isRaw) { + /* + * Use the sensor output size closest to the requested stream + * size. + */ + uint32_t mbusCode = formatToMediaBus.at(cfg->pixelFormat); + V4L2SubdeviceFormat sensorFormat = + sensor->getFormat({ mbusCode }, cfg->size); + + minResolution = sensorFormat.size; + maxResolution = sensorFormat.size; + } else { + /* + * Adjust the size based on the sensor resolution and absolute + * limits of the ISP. + */ + minResolution = minResolution_.expandedToAspectRatio(resolution); + maxResolution = maxResolution_.boundedToAspectRatio(resolution) + .boundedTo(resolution); + } cfg->size.boundTo(maxResolution); cfg->size.expandTo(minResolution); @@ -182,15 +328,11 @@ int RkISP1Path::configure(const StreamConfiguration &config, << "Configuring " << name_ << " resizer output pad with " << ispFormat; - switch (config.pixelFormat) { - case formats::NV12: - case formats::NV21: - ispFormat.mbus_code = MEDIA_BUS_FMT_YUYV8_1_5X8; - break; - default: - ispFormat.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8; - break; - } + /* + * The configuration has been validated, the pixel format is guaranteed + * to be supported and thus found in formatToMediaBus. + */ + ispFormat.mbus_code = formatToMediaBus.at(config.pixelFormat); ret = resizer_->setFormat(1, &ispFormat); if (ret < 0) @@ -266,14 +408,25 @@ void RkISP1Path::stop() namespace { constexpr Size RKISP1_RSZ_MP_SRC_MIN{ 32, 16 }; constexpr Size RKISP1_RSZ_MP_SRC_MAX{ 4416, 3312 }; -constexpr std::array RKISP1_RSZ_MP_FORMATS{ +constexpr std::array RKISP1_RSZ_MP_FORMATS{ formats::YUYV, formats::NV16, formats::NV61, formats::NV21, formats::NV12, formats::R8, - /* \todo Add support for RAW formats. */ + formats::SBGGR8, + formats::SGBRG8, + formats::SGRBG8, + formats::SRGGB8, + formats::SBGGR10, + formats::SGBRG10, + formats::SGRBG10, + formats::SRGGB10, + formats::SBGGR12, + formats::SGBRG12, + formats::SGRBG12, + formats::SRGGB12, }; constexpr Size RKISP1_RSZ_SP_SRC_MIN{ 32, 16 }; diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h index bf4ad18fbbf2..bdf3f95b95e1 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h @@ -40,7 +40,8 @@ public: int setEnabled(bool enable) { return link_->setEnabled(enable); } bool isEnabled() const { return link_->flags() & MEDIA_LNK_FL_ENABLED; } - StreamConfiguration generateConfiguration(const CameraSensor *sensor); + StreamConfiguration generateConfiguration(const CameraSensor *sensor, + StreamRole role); CameraConfiguration::Status validate(const CameraSensor *sensor, StreamConfiguration *cfg);