[libcamera-devel] libcamera: V4L2Device: Remove the controls order assumption in updateControls()
diff mbox series

Message ID 20210526064311.3767479-1-hiroh@chromium.org
State Superseded
Headers show
Series
  • [libcamera-devel] libcamera: V4L2Device: Remove the controls order assumption in updateControls()
Related show

Commit Message

Hirokazu Honda May 26, 2021, 6:43 a.m. UTC
The original updateControls() has the assumption that ctrls and
v4l2Ctrls lists are in the same order. It is dependent on the
caller implementation though. This changes updateControls()
implementation so that it works without the assumption.

Signed-off-by: Hirokazu Honda <hiroh@chromium.org>
---
 src/libcamera/v4l2_device.cpp | 25 ++++++++-----------------
 1 file changed, 8 insertions(+), 17 deletions(-)

Comments

Laurent Pinchart May 26, 2021, 11:36 p.m. UTC | #1
Hi Hiro,

Thank you for the patch.

On Wed, May 26, 2021 at 03:43:11PM +0900, Hirokazu Honda wrote:
> The original updateControls() has the assumption that ctrls and
> v4l2Ctrls lists are in the same order. It is dependent on the
> caller implementation though. This changes updateControls()
> implementation so that it works without the assumption.
> 
> Signed-off-by: Hirokazu Honda <hiroh@chromium.org>
> ---
>  src/libcamera/v4l2_device.cpp | 25 ++++++++-----------------
>  1 file changed, 8 insertions(+), 17 deletions(-)
> 
> diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp
> index caafbc2d..aaca7171 100644
> --- a/src/libcamera/v4l2_device.cpp
> +++ b/src/libcamera/v4l2_device.cpp
> @@ -244,12 +244,6 @@ ControlList V4L2Device::getControls(const std::vector<uint32_t> &ids)
>  
>  	ControlList ctrls{ controls_ };
>  
> -	/*
> -	 * Start by filling the ControlList. This can't be combined with filling
> -	 * v4l2Ctrls, as updateControls() relies on both containers having the
> -	 * same order, and the control list is based on a map, which is not
> -	 * sorted by insertion order.
> -	 */
>  	for (uint32_t id : ids) {
>  		const auto iter = controls_.find(id);
>  		if (iter == controls_.end()) {
> @@ -623,19 +617,16 @@ void V4L2Device::updateControlInfo()
>  void V4L2Device::updateControls(ControlList *ctrls,
>  				Span<const v4l2_ext_control> v4l2Ctrls)
>  {
> -	unsigned int i = 0;
> -	for (auto &ctrl : *ctrls) {
> -		if (i == v4l2Ctrls.size())
> -			break;
> +	for (const v4l2_ext_control &v4l2Ctrl : v4l2Ctrls) {
> +		const unsigned int id = v4l2Ctrl.id;
>  
> -		const struct v4l2_ext_control *v4l2Ctrl = &v4l2Ctrls[i];
> -		unsigned int id = ctrl.first;
> -		ControlValue &value = ctrl.second;
> +		ControlValue value = ctrls->get(id);
>  
> -		const auto iter = controls_.find(id);
> +		const auto &iter = controls_.find(id);

find() returns an iterator, not a reference to an iterator. Storing it
in a reference here will work as the lifetime of rvalues is extended
when a const lvalue reference is bound to them, but it's misleading, and
doesn't save any memory or CPU time. I think you should thus keep the
original code.

> +		ASSERT(iter != controls_.end());

I'd add a blank line here.

With these changes,

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

>  		switch (iter->first->type()) {
>  		case ControlTypeInteger64:
> -			value.set<int64_t>(v4l2Ctrl->value64);
> +			value.set<int64_t>(v4l2Ctrl.value64);
>  			break;
>  
>  		case ControlTypeByte:
> @@ -650,11 +641,11 @@ void V4L2Device::updateControls(ControlList *ctrls,
>  			 * \todo To be changed when support for string controls
>  			 * will be added.
>  			 */
> -			value.set<int32_t>(v4l2Ctrl->value);
> +			value.set<int32_t>(v4l2Ctrl.value);
>  			break;
>  		}
>  
> -		i++;
> +		ctrls->set(id, value);
>  	}
>  }
>

Patch
diff mbox series

diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp
index caafbc2d..aaca7171 100644
--- a/src/libcamera/v4l2_device.cpp
+++ b/src/libcamera/v4l2_device.cpp
@@ -244,12 +244,6 @@  ControlList V4L2Device::getControls(const std::vector<uint32_t> &ids)
 
 	ControlList ctrls{ controls_ };
 
-	/*
-	 * Start by filling the ControlList. This can't be combined with filling
-	 * v4l2Ctrls, as updateControls() relies on both containers having the
-	 * same order, and the control list is based on a map, which is not
-	 * sorted by insertion order.
-	 */
 	for (uint32_t id : ids) {
 		const auto iter = controls_.find(id);
 		if (iter == controls_.end()) {
@@ -623,19 +617,16 @@  void V4L2Device::updateControlInfo()
 void V4L2Device::updateControls(ControlList *ctrls,
 				Span<const v4l2_ext_control> v4l2Ctrls)
 {
-	unsigned int i = 0;
-	for (auto &ctrl : *ctrls) {
-		if (i == v4l2Ctrls.size())
-			break;
+	for (const v4l2_ext_control &v4l2Ctrl : v4l2Ctrls) {
+		const unsigned int id = v4l2Ctrl.id;
 
-		const struct v4l2_ext_control *v4l2Ctrl = &v4l2Ctrls[i];
-		unsigned int id = ctrl.first;
-		ControlValue &value = ctrl.second;
+		ControlValue value = ctrls->get(id);
 
-		const auto iter = controls_.find(id);
+		const auto &iter = controls_.find(id);
+		ASSERT(iter != controls_.end());
 		switch (iter->first->type()) {
 		case ControlTypeInteger64:
-			value.set<int64_t>(v4l2Ctrl->value64);
+			value.set<int64_t>(v4l2Ctrl.value64);
 			break;
 
 		case ControlTypeByte:
@@ -650,11 +641,11 @@  void V4L2Device::updateControls(ControlList *ctrls,
 			 * \todo To be changed when support for string controls
 			 * will be added.
 			 */
-			value.set<int32_t>(v4l2Ctrl->value);
+			value.set<int32_t>(v4l2Ctrl.value);
 			break;
 		}
 
-		i++;
+		ctrls->set(id, value);
 	}
 }