Message ID | 20210415044854.3348529-2-hiroh@chromium.org |
---|---|
State | Changes Requested |
Headers | show |
Series |
|
Related | show |
Hi Hiro, Thank you for the patch. On Thu, Apr 15, 2021 at 01:48:53PM +0900, Hirokazu Honda wrote: > The original code uses Variable-Length-Array, which is not > officially supported in C++. This replaces the array with > std::vector. > > Signed-off-by: Hirokazu Honda <hiroh@chromium.org> > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > --- > src/libcamera/v4l2_device.cpp | 32 +++++++++++++++----------------- > 1 file changed, 15 insertions(+), 17 deletions(-) > > diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp > index ee8c3fed..5ec1b10e 100644 > --- a/src/libcamera/v4l2_device.cpp > +++ b/src/libcamera/v4l2_device.cpp > @@ -279,12 +279,11 @@ ControlList V4L2Device::getControls(const std::vector<uint32_t> &ids) > */ > int V4L2Device::setControls(ControlList *ctrls) > { > - unsigned int count = ctrls->size(); > - if (count == 0) > + if (ctrls->empty()) > return 0; > > - struct v4l2_ext_control v4l2Ctrls[count]; > - memset(v4l2Ctrls, 0, sizeof(v4l2Ctrls)); > + std::vector<v4l2_ext_control> v4l2Ctrls(ctrls->size()); > + memset(v4l2Ctrls.data(), 0, v4l2Ctrls.size()); Is the memset() needed ? The std::vector constructor will default-insert the elements, which value-initializes them. If my interpretation of https://en.cppreference.com/w/cpp/language/value_initialization is correct, the elements will be zero-initialized. > > unsigned int i = 0; Should we replace i with v4l2_ext_control *v4l2Ctrl = v4l2Ctrls.data(); and do a v4l2Ctrl++; at the end of the loop ? That way we would ensure that i won't be used incorrectly (after being incremented) inside the loop. Apart from that, Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > for (auto &ctrl : *ctrls) { > @@ -295,14 +294,14 @@ int V4L2Device::setControls(ControlList *ctrls) > << "Control " << utils::hex(id) << " not found"; > return -EINVAL; > } > - > - v4l2Ctrls[i].id = id; > + v4l2_ext_control &v4l2Ctrl = v4l2Ctrls[i++]; > + v4l2Ctrl.id = id; > > /* Set the v4l2_ext_control value for the write operation. */ > ControlValue &value = ctrl.second; > switch (iter->first->type()) { > case ControlTypeInteger64: > - v4l2Ctrls[i].value64 = value.get<int64_t>(); > + v4l2Ctrl.value64 = value.get<int64_t>(); > break; > > case ControlTypeByte: { > @@ -314,32 +313,30 @@ int V4L2Device::setControls(ControlList *ctrls) > } > > Span<uint8_t> data = value.data(); > - v4l2Ctrls[i].p_u8 = data.data(); > - v4l2Ctrls[i].size = data.size(); > + v4l2Ctrl.p_u8 = data.data(); > + v4l2Ctrl.size = data.size(); > > break; > } > > default: > /* \todo To be changed to support strings. */ > - v4l2Ctrls[i].value = value.get<int32_t>(); > + v4l2Ctrl.value = value.get<int32_t>(); > break; > } > - > - i++; > } > > struct v4l2_ext_controls v4l2ExtCtrls = {}; > v4l2ExtCtrls.which = V4L2_CTRL_WHICH_CUR_VAL; > - v4l2ExtCtrls.controls = v4l2Ctrls; > - v4l2ExtCtrls.count = count; > + v4l2ExtCtrls.controls = v4l2Ctrls.data(); > + v4l2ExtCtrls.count = v4l2Ctrls.size(); > > int ret = ioctl(VIDIOC_S_EXT_CTRLS, &v4l2ExtCtrls); > if (ret) { > unsigned int errorIdx = v4l2ExtCtrls.error_idx; > > /* Generic validation error. */ > - if (errorIdx == 0 || errorIdx >= count) { > + if (errorIdx == 0 || errorIdx >= v4l2Ctrls.size()) { > LOG(V4L2, Error) << "Unable to set controls: " > << strerror(-ret); > return -EINVAL; > @@ -348,11 +345,12 @@ int V4L2Device::setControls(ControlList *ctrls) > /* A specific control failed. */ > LOG(V4L2, Error) << "Unable to set control " << errorIdx > << ": " << strerror(-ret); > - count = errorIdx - 1; > + > + v4l2Ctrls.resize(errorIdx); > ret = errorIdx; > } > > - updateControls(ctrls, v4l2Ctrls, count); > + updateControls(ctrls, v4l2Ctrls.data(), v4l2Ctrls.size()); > > return ret; > }
Hi Laurent, thanks for reviewing. On Tue, Apr 20, 2021 at 10:15 AM Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote: > > Hi Hiro, > > Thank you for the patch. > > On Thu, Apr 15, 2021 at 01:48:53PM +0900, Hirokazu Honda wrote: > > The original code uses Variable-Length-Array, which is not > > officially supported in C++. This replaces the array with > > std::vector. > > > > Signed-off-by: Hirokazu Honda <hiroh@chromium.org> > > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > > --- > > src/libcamera/v4l2_device.cpp | 32 +++++++++++++++----------------- > > 1 file changed, 15 insertions(+), 17 deletions(-) > > > > diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp > > index ee8c3fed..5ec1b10e 100644 > > --- a/src/libcamera/v4l2_device.cpp > > +++ b/src/libcamera/v4l2_device.cpp > > @@ -279,12 +279,11 @@ ControlList V4L2Device::getControls(const std::vector<uint32_t> &ids) > > */ > > int V4L2Device::setControls(ControlList *ctrls) > > { > > - unsigned int count = ctrls->size(); > > - if (count == 0) > > + if (ctrls->empty()) > > return 0; > > > > - struct v4l2_ext_control v4l2Ctrls[count]; > > - memset(v4l2Ctrls, 0, sizeof(v4l2Ctrls)); > > + std::vector<v4l2_ext_control> v4l2Ctrls(ctrls->size()); > > + memset(v4l2Ctrls.data(), 0, v4l2Ctrls.size()); > > Is the memset() needed ? The std::vector constructor will default-insert > the elements, which value-initializes them. If my interpretation of > https://en.cppreference.com/w/cpp/language/value_initialization is > correct, the elements will be zero-initialized. > value initialization in c++ fills zero to the first value in union. If the second or later values in the union is large than the first value, they are not zero-filled. So I would use memset for a structure with a union. > > > > unsigned int i = 0; > > Should we replace i with > > v4l2_ext_control *v4l2Ctrl = v4l2Ctrls.data(); > > and do a > > v4l2Ctrl++; > > at the end of the loop ? That way we would ensure that i won't be used > incorrectly (after being incremented) inside the loop. > > Apart from that, > > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > > for (auto &ctrl : *ctrls) { > > @@ -295,14 +294,14 @@ int V4L2Device::setControls(ControlList *ctrls) > > << "Control " << utils::hex(id) << " not found"; > > return -EINVAL; > > } > > - > > - v4l2Ctrls[i].id = id; > > + v4l2_ext_control &v4l2Ctrl = v4l2Ctrls[i++]; > > + v4l2Ctrl.id = id; > > > > /* Set the v4l2_ext_control value for the write operation. */ > > ControlValue &value = ctrl.second; > > switch (iter->first->type()) { > > case ControlTypeInteger64: > > - v4l2Ctrls[i].value64 = value.get<int64_t>(); > > + v4l2Ctrl.value64 = value.get<int64_t>(); > > break; > > > > case ControlTypeByte: { > > @@ -314,32 +313,30 @@ int V4L2Device::setControls(ControlList *ctrls) > > } > > > > Span<uint8_t> data = value.data(); > > - v4l2Ctrls[i].p_u8 = data.data(); > > - v4l2Ctrls[i].size = data.size(); > > + v4l2Ctrl.p_u8 = data.data(); > > + v4l2Ctrl.size = data.size(); > > > > break; > > } > > > > default: > > /* \todo To be changed to support strings. */ > > - v4l2Ctrls[i].value = value.get<int32_t>(); > > + v4l2Ctrl.value = value.get<int32_t>(); > > break; > > } > > - > > - i++; > > } > > > > struct v4l2_ext_controls v4l2ExtCtrls = {}; > > v4l2ExtCtrls.which = V4L2_CTRL_WHICH_CUR_VAL; > > - v4l2ExtCtrls.controls = v4l2Ctrls; > > - v4l2ExtCtrls.count = count; > > + v4l2ExtCtrls.controls = v4l2Ctrls.data(); > > + v4l2ExtCtrls.count = v4l2Ctrls.size(); > > > > int ret = ioctl(VIDIOC_S_EXT_CTRLS, &v4l2ExtCtrls); > > if (ret) { > > unsigned int errorIdx = v4l2ExtCtrls.error_idx; > > > > /* Generic validation error. */ > > - if (errorIdx == 0 || errorIdx >= count) { > > + if (errorIdx == 0 || errorIdx >= v4l2Ctrls.size()) { > > LOG(V4L2, Error) << "Unable to set controls: " > > << strerror(-ret); > > return -EINVAL; > > @@ -348,11 +345,12 @@ int V4L2Device::setControls(ControlList *ctrls) > > /* A specific control failed. */ > > LOG(V4L2, Error) << "Unable to set control " << errorIdx > > << ": " << strerror(-ret); > > - count = errorIdx - 1; > > + > > + v4l2Ctrls.resize(errorIdx); > > ret = errorIdx; > > } > > > > - updateControls(ctrls, v4l2Ctrls, count); > > + updateControls(ctrls, v4l2Ctrls.data(), v4l2Ctrls.size()); > > > > return ret; > > } > > -- > Regards, > > Laurent Pinchart
Hi Hiro, On Wed, Apr 21, 2021 at 06:30:50PM +0900, Hirokazu Honda wrote: > On Tue, Apr 20, 2021 at 10:15 AM Laurent Pinchart wrote: > > On Thu, Apr 15, 2021 at 01:48:53PM +0900, Hirokazu Honda wrote: > > > The original code uses Variable-Length-Array, which is not > > > officially supported in C++. This replaces the array with > > > std::vector. > > > > > > Signed-off-by: Hirokazu Honda <hiroh@chromium.org> > > > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > > > --- > > > src/libcamera/v4l2_device.cpp | 32 +++++++++++++++----------------- > > > 1 file changed, 15 insertions(+), 17 deletions(-) > > > > > > diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp > > > index ee8c3fed..5ec1b10e 100644 > > > --- a/src/libcamera/v4l2_device.cpp > > > +++ b/src/libcamera/v4l2_device.cpp > > > @@ -279,12 +279,11 @@ ControlList V4L2Device::getControls(const std::vector<uint32_t> &ids) > > > */ > > > int V4L2Device::setControls(ControlList *ctrls) > > > { > > > - unsigned int count = ctrls->size(); > > > - if (count == 0) > > > + if (ctrls->empty()) > > > return 0; > > > > > > - struct v4l2_ext_control v4l2Ctrls[count]; > > > - memset(v4l2Ctrls, 0, sizeof(v4l2Ctrls)); > > > + std::vector<v4l2_ext_control> v4l2Ctrls(ctrls->size()); > > > + memset(v4l2Ctrls.data(), 0, v4l2Ctrls.size()); > > > > Is the memset() needed ? The std::vector constructor will default-insert > > the elements, which value-initializes them. If my interpretation of > > https://en.cppreference.com/w/cpp/language/value_initialization is > > correct, the elements will be zero-initialized. > > value initialization in c++ fills zero to the first value in union. > If the second or later values in the union is large than the first > value, they are not zero-filled. > So I would use memset for a structure with a union. Good point, let's keep the memset() then. > > > > > > unsigned int i = 0; > > > > Should we replace i with > > > > v4l2_ext_control *v4l2Ctrl = v4l2Ctrls.data(); > > > > and do a > > > > v4l2Ctrl++; > > > > at the end of the loop ? That way we would ensure that i won't be used > > incorrectly (after being incremented) inside the loop. > > > > Apart from that, > > > > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > > > > for (auto &ctrl : *ctrls) { > > > @@ -295,14 +294,14 @@ int V4L2Device::setControls(ControlList *ctrls) > > > << "Control " << utils::hex(id) << " not found"; > > > return -EINVAL; > > > } > > > - > > > - v4l2Ctrls[i].id = id; > > > + v4l2_ext_control &v4l2Ctrl = v4l2Ctrls[i++]; > > > + v4l2Ctrl.id = id; > > > > > > /* Set the v4l2_ext_control value for the write operation. */ > > > ControlValue &value = ctrl.second; > > > switch (iter->first->type()) { > > > case ControlTypeInteger64: > > > - v4l2Ctrls[i].value64 = value.get<int64_t>(); > > > + v4l2Ctrl.value64 = value.get<int64_t>(); > > > break; > > > > > > case ControlTypeByte: { > > > @@ -314,32 +313,30 @@ int V4L2Device::setControls(ControlList *ctrls) > > > } > > > > > > Span<uint8_t> data = value.data(); > > > - v4l2Ctrls[i].p_u8 = data.data(); > > > - v4l2Ctrls[i].size = data.size(); > > > + v4l2Ctrl.p_u8 = data.data(); > > > + v4l2Ctrl.size = data.size(); > > > > > > break; > > > } > > > > > > default: > > > /* \todo To be changed to support strings. */ > > > - v4l2Ctrls[i].value = value.get<int32_t>(); > > > + v4l2Ctrl.value = value.get<int32_t>(); > > > break; > > > } > > > - > > > - i++; > > > } > > > > > > struct v4l2_ext_controls v4l2ExtCtrls = {}; > > > v4l2ExtCtrls.which = V4L2_CTRL_WHICH_CUR_VAL; > > > - v4l2ExtCtrls.controls = v4l2Ctrls; > > > - v4l2ExtCtrls.count = count; > > > + v4l2ExtCtrls.controls = v4l2Ctrls.data(); > > > + v4l2ExtCtrls.count = v4l2Ctrls.size(); > > > > > > int ret = ioctl(VIDIOC_S_EXT_CTRLS, &v4l2ExtCtrls); > > > if (ret) { > > > unsigned int errorIdx = v4l2ExtCtrls.error_idx; > > > > > > /* Generic validation error. */ > > > - if (errorIdx == 0 || errorIdx >= count) { > > > + if (errorIdx == 0 || errorIdx >= v4l2Ctrls.size()) { > > > LOG(V4L2, Error) << "Unable to set controls: " > > > << strerror(-ret); > > > return -EINVAL; > > > @@ -348,11 +345,12 @@ int V4L2Device::setControls(ControlList *ctrls) > > > /* A specific control failed. */ > > > LOG(V4L2, Error) << "Unable to set control " << errorIdx > > > << ": " << strerror(-ret); > > > - count = errorIdx - 1; > > > + > > > + v4l2Ctrls.resize(errorIdx); > > > ret = errorIdx; > > > } > > > > > > - updateControls(ctrls, v4l2Ctrls, count); > > > + updateControls(ctrls, v4l2Ctrls.data(), v4l2Ctrls.size()); > > > > > > return ret; > > > }
diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index ee8c3fed..5ec1b10e 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -279,12 +279,11 @@ ControlList V4L2Device::getControls(const std::vector<uint32_t> &ids) */ int V4L2Device::setControls(ControlList *ctrls) { - unsigned int count = ctrls->size(); - if (count == 0) + if (ctrls->empty()) return 0; - struct v4l2_ext_control v4l2Ctrls[count]; - memset(v4l2Ctrls, 0, sizeof(v4l2Ctrls)); + std::vector<v4l2_ext_control> v4l2Ctrls(ctrls->size()); + memset(v4l2Ctrls.data(), 0, v4l2Ctrls.size()); unsigned int i = 0; for (auto &ctrl : *ctrls) { @@ -295,14 +294,14 @@ int V4L2Device::setControls(ControlList *ctrls) << "Control " << utils::hex(id) << " not found"; return -EINVAL; } - - v4l2Ctrls[i].id = id; + v4l2_ext_control &v4l2Ctrl = v4l2Ctrls[i++]; + v4l2Ctrl.id = id; /* Set the v4l2_ext_control value for the write operation. */ ControlValue &value = ctrl.second; switch (iter->first->type()) { case ControlTypeInteger64: - v4l2Ctrls[i].value64 = value.get<int64_t>(); + v4l2Ctrl.value64 = value.get<int64_t>(); break; case ControlTypeByte: { @@ -314,32 +313,30 @@ int V4L2Device::setControls(ControlList *ctrls) } Span<uint8_t> data = value.data(); - v4l2Ctrls[i].p_u8 = data.data(); - v4l2Ctrls[i].size = data.size(); + v4l2Ctrl.p_u8 = data.data(); + v4l2Ctrl.size = data.size(); break; } default: /* \todo To be changed to support strings. */ - v4l2Ctrls[i].value = value.get<int32_t>(); + v4l2Ctrl.value = value.get<int32_t>(); break; } - - i++; } struct v4l2_ext_controls v4l2ExtCtrls = {}; v4l2ExtCtrls.which = V4L2_CTRL_WHICH_CUR_VAL; - v4l2ExtCtrls.controls = v4l2Ctrls; - v4l2ExtCtrls.count = count; + v4l2ExtCtrls.controls = v4l2Ctrls.data(); + v4l2ExtCtrls.count = v4l2Ctrls.size(); int ret = ioctl(VIDIOC_S_EXT_CTRLS, &v4l2ExtCtrls); if (ret) { unsigned int errorIdx = v4l2ExtCtrls.error_idx; /* Generic validation error. */ - if (errorIdx == 0 || errorIdx >= count) { + if (errorIdx == 0 || errorIdx >= v4l2Ctrls.size()) { LOG(V4L2, Error) << "Unable to set controls: " << strerror(-ret); return -EINVAL; @@ -348,11 +345,12 @@ int V4L2Device::setControls(ControlList *ctrls) /* A specific control failed. */ LOG(V4L2, Error) << "Unable to set control " << errorIdx << ": " << strerror(-ret); - count = errorIdx - 1; + + v4l2Ctrls.resize(errorIdx); ret = errorIdx; } - updateControls(ctrls, v4l2Ctrls, count); + updateControls(ctrls, v4l2Ctrls.data(), v4l2Ctrls.size()); return ret; }