From patchwork Mon May 11 10:01:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 3749 Return-Path: Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 815EF603E2 for ; Mon, 11 May 2020 12:02:00 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="gSRRnrQ+"; dkim-atps=neutral Received: by mail-wr1-x42e.google.com with SMTP id 50so9603210wrc.11 for ; Mon, 11 May 2020 03:02:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=gSJF6QTfVRwWybx8gLeuO9JAxDrt1z6OOrCNObsnKRQ=; b=gSRRnrQ+DCJPiEMxXJziP8zOrgBho2vXZhWg+p1iQccmfYDDWRunMYa2MytSRKFCvK 9+IQglcr29djsGbtvIaNyw6RJY2CTBNS6ligkXeneTVmcnWjomu4FMRTGTb0ZNlb+qk5 LPX1SUKS1wNU3b7dawCGqW6fFwZeaoF+1DnmAWH6gwFxqmCbxbx2A7WoDq1vWXil2vCu VUcWNcGME/IxS1m6HokpyPhH02nuYawjYPcRz0W3sBHGia0JxkPqkl5sdy6dZD4XeJdt aG0YDjRruOiASOSFx3YRF0RJSyYfIcy5vrWs8m69W77s8ydmMQNg6Yws3C+cKce2wKZd CeIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=gSJF6QTfVRwWybx8gLeuO9JAxDrt1z6OOrCNObsnKRQ=; b=IzubujwZSgvT1va9MlDnP2Dk6ge1pK09JGpzJj0EQ/bcE/T6Bsf1ZkEW+kTIZDH+mO AdT7KQV1GBtcqBynTZFsoPLaLnZ2njFDmlu/SHDt6RNot4OTZ4b6YNJl1JIDpf/tgBSC VmNm3M7/ccH7pkTe+biMeaZITQWDqEJnPbGGcsR2Lgw2uqS31ADqnyD/vjJm1QxdGwz3 0HwlzgRQDfZnBLtgXxp5XSpmo7L0r7pWPQAg0RQ2ee7/bJbV6pdnMUNWi6gxRWO5B8ci mEx/ywMp+zxbv7i3RWEHUFphHpSUqquIbabfjsw3Rah3FcvHR6nsZQdLeVSXFIzsshSm 7sPA== X-Gm-Message-State: AGi0PuZNRFuSTTnbXDEQkv09n59ZVm57NI/PxL1y0R74mKgvmckJ8to7 Qqrj22Tfz7RtrINl4GOJ18bAkIJEmGFjEA== X-Google-Smtp-Source: APiQypLIzPwn1ER9DQ0ASAjhzqkVR88uTyUP09wAQkxKbaC6PqmvGzFFawDr3KRWOqmo+xPTeMGb1w== X-Received: by 2002:adf:e483:: with SMTP id i3mr17292506wrm.88.1589191319722; Mon, 11 May 2020 03:01:59 -0700 (PDT) Received: from naushir-VirtualBox.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id u74sm26391908wmu.13.2020.05.11.03.01.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 11 May 2020 03:01:58 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Mon, 11 May 2020 11:01:50 +0100 Message-Id: <20200511100150.5205-3-naush@raspberrypi.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200511100150.5205-1-naush@raspberrypi.com> References: <20200511100150.5205-1-naush@raspberrypi.com> Subject: [libcamera-devel] [PATCH 2/2] libcamera: raspberrypi: Limit the maximum framerate to 30.0fps 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-List-Received-Date: Mon, 11 May 2020 10:02:00 -0000 With the previous change to adapt framerate using VBLANK, the maximum framerate was limited by the sensor mode. This may not be entirely appropriate for what an application expects in the case where a mode can produce > 30.0fps. Provide a mechanism to limit the maximum framerate. This is currently a const set to 30.0fps. In future, this value could be passed in via a Request or stream configuration. Signed-off-by: Naushir Patuck --- src/ipa/raspberrypi/cam_helper.hpp | 2 +- src/ipa/raspberrypi/cam_helper_imx219.cpp | 18 ++++++++++++++---- src/ipa/raspberrypi/cam_helper_imx477.cpp | 18 ++++++++++++++---- src/ipa/raspberrypi/cam_helper_ov5647.cpp | 18 ++++++++++++++---- src/ipa/raspberrypi/raspberrypi.cpp | 8 +++++++- 5 files changed, 50 insertions(+), 14 deletions(-) diff --git a/src/ipa/raspberrypi/cam_helper.hpp b/src/ipa/raspberrypi/cam_helper.hpp index 37281c78..4f7a3897 100644 --- a/src/ipa/raspberrypi/cam_helper.hpp +++ b/src/ipa/raspberrypi/cam_helper.hpp @@ -74,7 +74,7 @@ public: MdParser &Parser() const { return *parser_; } uint32_t ExposureLines(double exposure_us) const; double Exposure(uint32_t exposure_lines) const; // in us - virtual uint32_t GetVBlanking(double exposure_us) const = 0; + virtual uint32_t GetVBlanking(double exposure_us, double maxFps) const = 0; virtual uint32_t GainCode(double gain) const = 0; virtual double Gain(uint32_t gain_code) const = 0; virtual void GetDelays(int &exposure_delay, int &gain_delay) const; diff --git a/src/ipa/raspberrypi/cam_helper_imx219.cpp b/src/ipa/raspberrypi/cam_helper_imx219.cpp index d34a1f1f..51a18aca 100644 --- a/src/ipa/raspberrypi/cam_helper_imx219.cpp +++ b/src/ipa/raspberrypi/cam_helper_imx219.cpp @@ -45,7 +45,7 @@ class CamHelperImx219 : public CamHelper { public: CamHelperImx219(); - uint32_t GetVBlanking(double exposure) const override; + uint32_t GetVBlanking(double exposure, double maxFps) const override; uint32_t GainCode(double gain) const override; double Gain(uint32_t gain_code) const override; unsigned int MistrustFramesModeSwitch() const override; @@ -55,6 +55,8 @@ public: private: /* Smallest difference between the frame length and integration time. */ static constexpr int frameIntegrationDiff = 4; + /* Largest possible frame length. */ + static constexpr int maxFrameLength = 0xffff; }; CamHelperImx219::CamHelperImx219() @@ -66,12 +68,20 @@ CamHelperImx219::CamHelperImx219() { } -uint32_t CamHelperImx219::GetVBlanking(double exposure) const +uint32_t CamHelperImx219::GetVBlanking(double exposure, double maxFps) const { + uint32_t frameLengthMin, vblank; uint32_t exposureLines = ExposureLines(exposure); - return std::max(mode_.height, exposureLines) - - mode_.height + frameIntegrationDiff; + vblank = std::max(mode_.height, exposureLines) - + mode_.height + frameIntegrationDiff; + + /* Limit the vblank to the maximum framerate requested. */ + frameLengthMin = std::min(1e9 / (mode_.line_length * maxFps), + maxFrameLength); + vblank = std::max(vblank, frameLengthMin - mode_.height); + + return vblank; } uint32_t CamHelperImx219::GainCode(double gain) const diff --git a/src/ipa/raspberrypi/cam_helper_imx477.cpp b/src/ipa/raspberrypi/cam_helper_imx477.cpp index 242d9689..ff815f9c 100644 --- a/src/ipa/raspberrypi/cam_helper_imx477.cpp +++ b/src/ipa/raspberrypi/cam_helper_imx477.cpp @@ -35,7 +35,7 @@ class CamHelperImx477 : public CamHelper { public: CamHelperImx477(); - uint32_t GetVBlanking(double exposure) const override; + uint32_t GetVBlanking(double exposure, double maxFps) const override; uint32_t GainCode(double gain) const override; double Gain(uint32_t gain_code) const override; bool SensorEmbeddedDataPresent() const override; @@ -44,6 +44,8 @@ public: private: /* Smallest difference between the frame length and integration time. */ static constexpr int frameIntegrationDiff = 22; + /* Largest possible frame length. */ + static constexpr int maxFrameLength = 0xffdc; }; CamHelperImx477::CamHelperImx477() @@ -51,12 +53,20 @@ CamHelperImx477::CamHelperImx477() { } -uint32_t CamHelperImx477::GetVBlanking(double exposure) const +uint32_t CamHelperImx477::GetVBlanking(double exposure, double maxFps) const { + uint32_t frameLengthMin, vblank; uint32_t exposureLines = ExposureLines(exposure); - return std::max(mode_.height, exposureLines) - - mode_.height + frameIntegrationDiff; + vblank = std::max(mode_.height, exposureLines) - + mode_.height + frameIntegrationDiff; + + /* Limit the vblank to the maximum framerate requested. */ + frameLengthMin = std::min(1e9 / (mode_.line_length * maxFps), + maxFrameLength); + vblank = std::max(vblank, frameLengthMin - mode_.height); + + return vblank; } uint32_t CamHelperImx477::GainCode(double gain) const diff --git a/src/ipa/raspberrypi/cam_helper_ov5647.cpp b/src/ipa/raspberrypi/cam_helper_ov5647.cpp index ff37779c..53ac3c3b 100644 --- a/src/ipa/raspberrypi/cam_helper_ov5647.cpp +++ b/src/ipa/raspberrypi/cam_helper_ov5647.cpp @@ -16,7 +16,7 @@ class CamHelperOv5647 : public CamHelper { public: CamHelperOv5647(); - uint32_t GetVBlanking(double exposure) const override; + uint32_t GetVBlanking(double exposure, double maxFps) const override; uint32_t GainCode(double gain) const override; double Gain(uint32_t gain_code) const override; void GetDelays(int &exposure_delay, int &gain_delay) const override; @@ -27,6 +27,8 @@ public: private: /* Smallest difference between the frame length and integration time. */ static constexpr int frameIntegrationDiff = 4; + /* Largest possible frame length. */ + static constexpr int maxFrameLength = 0xffff; }; /* @@ -39,12 +41,20 @@ CamHelperOv5647::CamHelperOv5647() { } -uint32_t CamHelperOv5647::GetVBlanking(double exposure) const +uint32_t CamHelperOv5647::GetVBlanking(double exposure, double maxFps) const { + uint32_t frameLengthMin, vblank; uint32_t exposureLines = ExposureLines(exposure); - return std::max(mode_.height, exposureLines) - - mode_.height + frameIntegrationDiff; + vblank = std::max(mode_.height, exposureLines) - + mode_.height + frameIntegrationDiff; + + /* Limit the vblank to the maximum framerate requested. */ + frameLengthMin = std::min(1e9 / (mode_.line_length * maxFps), + maxFrameLength); + vblank = std::max(vblank, frameLengthMin - mode_.height); + + return vblank; } uint32_t CamHelperOv5647::GainCode(double gain) const diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp index 104727ea..3a2cc16e 100644 --- a/src/ipa/raspberrypi/raspberrypi.cpp +++ b/src/ipa/raspberrypi/raspberrypi.cpp @@ -136,6 +136,12 @@ private: /* LS table allocation passed in from the pipeline handler. */ uint32_t lsTableHandle_; void *lsTable_; + + /* + * Have some defaults here, but eventually it should come from the + * application via a Request, or perhaps stream configuration. + */ + static constexpr double fpsMax = 30.0; }; int IPARPi::init(const IPASettings &settings) @@ -795,7 +801,7 @@ void IPARPi::applyAGC(const struct AgcStatus *agcStatus) int32_t gain_code = helper_->GainCode(agcStatus->analogue_gain); int32_t exposure_lines = helper_->ExposureLines(agcStatus->shutter_time); - int32_t vblanking = helper_->GetVBlanking(agcStatus->shutter_time); + int32_t vblanking = helper_->GetVBlanking(agcStatus->shutter_time, fpsMax); if (unicam_ctrls_.find(V4L2_CID_ANALOGUE_GAIN) == unicam_ctrls_.end()) { LOG(IPARPI, Error) << "Can't find analogue gain control";