[libcamera-devel,v4,2/5] libcamera: controls: Updates to gain and exposure controls

Message ID 20200424104700.26819-3-naush@raspberrypi.com
State Accepted
Headers show
Series
  • Patchset for libcamera controls
Related show

Commit Message

Naushir Patuck April 24, 2020, 10:46 a.m. UTC
Rename:
ManualExposure -> ExposureTime
ManualGain -> AnalogueGain

Use micro-seconds units for ExposureTime. This is changed from milli-
seconds. The latter would not allow very low exposure times.
AnalogueGain switch to use a float to allow fractional gain adjustments.

Update the uvcvideo pipeline handler to use the new exposure and gain
units. For ExposureTime, UVC uses units of 100 micro-seconds, so map
the values before setting V4L2_CID_EXPOSURE_ABSOLUTE. For AnalogueGain,
UVC has no explicit gain units, so map the default gain value to 1.0
and linearly scale to the requested value.

Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 src/libcamera/control_ids.yaml               | 22 +++++++-----
 src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 37 ++++++++++++++++----
 2 files changed, 44 insertions(+), 15 deletions(-)

Patch

diff --git a/src/libcamera/control_ids.yaml b/src/libcamera/control_ids.yaml
index bcbab195..d8bdb382 100644
--- a/src/libcamera/control_ids.yaml
+++ b/src/libcamera/control_ids.yaml
@@ -12,7 +12,7 @@  controls:
       description: |
         Enable or disable the AE.
 
-        \sa ManualExposure
+        \sa ExposureTime AnalogueGain
 
   - AeLocked:
       type: bool
@@ -30,8 +30,6 @@  controls:
       description: |
         Enable or disable the AWB.
 
-        \sa ManualGain
-
   - Brightness:
       type: int32_t
       description: Specify a fixed brightness parameter
@@ -44,12 +42,20 @@  controls:
       type: int32_t
       description: Specify a fixed saturation parameter
 
-  - ManualExposure:
+  - ExposureTime:
       type: int32_t
-      description: Specify a fixed exposure time in milli-seconds
+      description: |
+        Exposure time (shutter speed) for the frame applied in the sensor
+        device. This value is specified in micro-seconds.
 
-  - ManualGain:
-      type: int32_t
-      description: Specify a fixed gain parameter
+        \sa AnalogueGain AeEnable
+
+  - AnalogueGain:
+      type: float
+      description: |
+        Analogue gain value applied in the sensor device.
+        The value of the control specifies the gain multiplier applied to all
+        colour channels. This value cannot be lower than 1.0.
 
+        \sa ExposureTime AeEnable
 ...
diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
index ffbddf27..b518ad16 100644
--- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
+++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
@@ -7,6 +7,7 @@ 
 
 #include <algorithm>
 #include <iomanip>
+#include <math.h>
 #include <sys/sysmacros.h>
 #include <tuple>
 
@@ -251,11 +252,24 @@  int PipelineHandlerUVC::processControls(UVCCameraData *data, Request *request)
 			controls.set(V4L2_CID_CONTRAST, value);
 		} else if (id == controls::Saturation) {
 			controls.set(V4L2_CID_SATURATION, value);
-		} else if (id == controls::ManualExposure) {
+		} else if (id == controls::ExposureTime) {
 			controls.set(V4L2_CID_EXPOSURE_AUTO, static_cast<int32_t>(1));
-			controls.set(V4L2_CID_EXPOSURE_ABSOLUTE, value);
-		} else if (id == controls::ManualGain) {
-			controls.set(V4L2_CID_GAIN, value);
+			/*
+			 * controls::ExposureTime is in units of 1 us, and UVC
+			 * expects V4L2_CID_EXPOSURE_ABSOLUTE in units of 100 us.
+			 */
+			controls.set(V4L2_CID_EXPOSURE_ABSOLUTE,
+				     value.get<int32_t>() / 100);
+		} else if (id == controls::AnalogueGain) {
+			/*
+			 * controls::AnalogueGain is specified as an absolute
+			 * multiplier for all RGB samples. Map this multiplier
+			 * in a linear way such that 1.0 -> default gain
+			 * of the V4L2_CID_GAIN control on the uvcvideo device.
+			 */
+			const ControlInfo &gainInfo = controls.infoMap()->at(V4L2_CID_GAIN);
+			int32_t gain = lroundf(value.get<float>() * gainInfo.def().get<int32_t>());
+			controls.set(V4L2_CID_GAIN, gain);
 		}
 	}
 
@@ -350,7 +364,7 @@  int UVCCameraData::init(MediaEntity *entity)
 	ControlInfoMap::Map ctrls;
 
 	for (const auto &ctrl : controls) {
-		const ControlInfo &info = ctrl.second;
+		ControlInfo info = ctrl.second;
 		const ControlId *id;
 
 		switch (ctrl.first->id()) {
@@ -364,10 +378,19 @@  int UVCCameraData::init(MediaEntity *entity)
 			id = &controls::Saturation;
 			break;
 		case V4L2_CID_EXPOSURE_ABSOLUTE:
-			id = &controls::ManualExposure;
+			id = &controls::ExposureTime;
 			break;
 		case V4L2_CID_GAIN:
-			id = &controls::ManualGain;
+			id = &controls::AnalogueGain;
+			/*
+			 * AnalogueGain is a float control, convert the type of
+			 * the range.
+			 */
+			info = ControlInfo{
+				{ static_cast<float>(info.min().get<int32_t>()) },
+				{ static_cast<float>(info.max().get<int32_t>()) },
+				{ static_cast<float>(info.def().get<int32_t>()) }
+			};
 			break;
 		default:
 			continue;