[libcamera-devel] [RFC v1 3/7] py: Move ControlValue helpers to py_helpers.cpp

Laurent Pinchart laurent.pinchart at ideasonboard.com
Fri Jun 24 14:37:33 CEST 2022


On Fri, Jun 24, 2022 at 09:22:17AM +0100, Kieran Bingham wrote:
> Quoting Tomi Valkeinen (2022-06-23 15:47:32)
> > Clean up the py_main.cpp a bit by moving the ControlValue helpers to a
> > separate file.
> > 
> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen at ideasonboard.com>
> > ---
> >  src/py/libcamera/meson.build    |  1 +
> >  src/py/libcamera/py_helpers.cpp | 98 +++++++++++++++++++++++++++++++++
> >  src/py/libcamera/py_helpers.h   | 13 +++++
> >  src/py/libcamera/py_main.cpp    | 83 +---------------------------
> >  4 files changed, 114 insertions(+), 81 deletions(-)
> >  create mode 100644 src/py/libcamera/py_helpers.cpp
> >  create mode 100644 src/py/libcamera/py_helpers.h
> > 
> > diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build
> > index eb884538..04578bac 100644
> > --- a/src/py/libcamera/meson.build
> > +++ b/src/py/libcamera/meson.build
> > @@ -15,6 +15,7 @@ pybind11_dep = pybind11_proj.get_variable('pybind11_dep')
> >  pycamera_sources = files([
> >      'py_enums.cpp',
> >      'py_geometry.cpp',
> > +    'py_helpers.cpp',
> 
> Should this be called py_controls? Or do you expect other support code
> to go in here too. Or maybe it's more about types, 'py_types' ..
> 
> >      'py_main.cpp',
> >  ])
> >  
> > diff --git a/src/py/libcamera/py_helpers.cpp b/src/py/libcamera/py_helpers.cpp
> > new file mode 100644
> > index 00000000..d0a8b5c4
> > --- /dev/null
> > +++ b/src/py/libcamera/py_helpers.cpp
> > @@ -0,0 +1,98 @@
> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> > +/*
> > + * Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen at ideasonboard.com>
> > + */
> > +
> > +#include "py_helpers.h"
> > +
> > +#include <libcamera/libcamera.h>
> > +
> > +#include <pybind11/functional.h>
> > +#include <pybind11/smart_holder.h>
> 
> You have this in the py_helpers header too, so I don't think it needs to
> be duplicated here.
> 
> What's it used for? I thought it was just for the Camera destructor or
> something, I don't see Camera used here ?
> 
> Anyway, the code move to it's own component file makes sense to me.
> 
> 
> Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>

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

> > +#include <pybind11/stl.h>
> > +#include <pybind11/stl_bind.h>
> > +
> > +namespace py = pybind11;
> > +
> > +using namespace libcamera;
> > +
> > +template<typename T>
> > +static py::object valueOrTuple(const ControlValue &cv)
> > +{
> > +       if (cv.isArray()) {
> > +               const T *v = reinterpret_cast<const T *>(cv.data().data());
> > +               auto t = py::tuple(cv.numElements());
> > +
> > +               for (size_t i = 0; i < cv.numElements(); ++i)
> > +                       t[i] = v[i];
> > +
> > +               return std::move(t);
> > +       }
> > +
> > +       return py::cast(cv.get<T>());
> > +}
> > +
> > +py::object controlValueToPy(const ControlValue &cv)
> > +{
> > +       switch (cv.type()) {
> > +       case ControlTypeBool:
> > +               return valueOrTuple<bool>(cv);
> > +       case ControlTypeByte:
> > +               return valueOrTuple<uint8_t>(cv);
> > +       case ControlTypeInteger32:
> > +               return valueOrTuple<int32_t>(cv);
> > +       case ControlTypeInteger64:
> > +               return valueOrTuple<int64_t>(cv);
> > +       case ControlTypeFloat:
> > +               return valueOrTuple<float>(cv);
> > +       case ControlTypeString:
> > +               return py::cast(cv.get<std::string>());
> > +       case ControlTypeRectangle: {
> > +               const Rectangle *v = reinterpret_cast<const Rectangle *>(cv.data().data());
> > +               return py::cast(v);
> > +       }
> > +       case ControlTypeSize: {
> > +               const Size *v = reinterpret_cast<const Size *>(cv.data().data());
> > +               return py::cast(v);
> > +       }
> > +       case ControlTypeNone:
> > +       default:
> > +               throw std::runtime_error("Unsupported ControlValue type");
> > +       }
> > +}
> > +
> > +template<typename T>
> > +static ControlValue controlValueMaybeArray(const py::object &ob)
> > +{
> > +       if (py::isinstance<py::list>(ob) || py::isinstance<py::tuple>(ob)) {
> > +               std::vector<T> vec = ob.cast<std::vector<T>>();
> > +               return ControlValue(Span<const T>(vec));
> > +       }
> > +
> > +       return ControlValue(ob.cast<T>());
> > +}
> > +
> > +ControlValue pyToControlValue(const py::object &ob, ControlType type)
> > +{
> > +       switch (type) {
> > +       case ControlTypeBool:
> > +               return ControlValue(ob.cast<bool>());
> > +       case ControlTypeByte:
> > +               return controlValueMaybeArray<uint8_t>(ob);
> > +       case ControlTypeInteger32:
> > +               return controlValueMaybeArray<int32_t>(ob);
> > +       case ControlTypeInteger64:
> > +               return controlValueMaybeArray<int64_t>(ob);
> > +       case ControlTypeFloat:
> > +               return controlValueMaybeArray<float>(ob);
> > +       case ControlTypeString:
> > +               return ControlValue(ob.cast<std::string>());
> > +       case ControlTypeRectangle:
> > +               return ControlValue(ob.cast<Rectangle>());
> > +       case ControlTypeSize:
> > +               return ControlValue(ob.cast<Size>());
> > +       case ControlTypeNone:
> > +       default:
> > +               throw std::runtime_error("Control type not implemented");
> > +       }
> > +}
> > diff --git a/src/py/libcamera/py_helpers.h b/src/py/libcamera/py_helpers.h
> > new file mode 100644
> > index 00000000..cd31e2cc
> > --- /dev/null
> > +++ b/src/py/libcamera/py_helpers.h
> > @@ -0,0 +1,13 @@
> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> > +/*
> > + * Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen at ideasonboard.com>
> > + */
> > +
> > +#pragma once
> > +
> > +#include <libcamera/libcamera.h>
> > +
> > +#include <pybind11/smart_holder.h>
> > +
> > +pybind11::object controlValueToPy(const libcamera::ControlValue &cv);
> > +libcamera::ControlValue pyToControlValue(const pybind11::object &ob, libcamera::ControlType type);
> > diff --git a/src/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp
> > index 17b17f60..5a423ece 100644
> > --- a/src/py/libcamera/py_main.cpp
> > +++ b/src/py/libcamera/py_main.cpp
> > @@ -21,93 +21,14 @@
> >  #include <pybind11/stl.h>
> >  #include <pybind11/stl_bind.h>
> >  
> > +#include "py_helpers.h"
> > +
> >  namespace py = pybind11;
> >  
> >  using namespace libcamera;
> >  
> >  LOG_DEFINE_CATEGORY(Python)
> >  
> > -template<typename T>
> > -static py::object valueOrTuple(const ControlValue &cv)
> > -{
> > -       if (cv.isArray()) {
> > -               const T *v = reinterpret_cast<const T *>(cv.data().data());
> > -               auto t = py::tuple(cv.numElements());
> > -
> > -               for (size_t i = 0; i < cv.numElements(); ++i)
> > -                       t[i] = v[i];
> > -
> > -               return std::move(t);
> > -       }
> > -
> > -       return py::cast(cv.get<T>());
> > -}
> > -
> > -static py::object controlValueToPy(const ControlValue &cv)
> > -{
> > -       switch (cv.type()) {
> > -       case ControlTypeBool:
> > -               return valueOrTuple<bool>(cv);
> > -       case ControlTypeByte:
> > -               return valueOrTuple<uint8_t>(cv);
> > -       case ControlTypeInteger32:
> > -               return valueOrTuple<int32_t>(cv);
> > -       case ControlTypeInteger64:
> > -               return valueOrTuple<int64_t>(cv);
> > -       case ControlTypeFloat:
> > -               return valueOrTuple<float>(cv);
> > -       case ControlTypeString:
> > -               return py::cast(cv.get<std::string>());
> > -       case ControlTypeRectangle: {
> > -               const Rectangle *v = reinterpret_cast<const Rectangle *>(cv.data().data());
> > -               return py::cast(v);
> > -       }
> > -       case ControlTypeSize: {
> > -               const Size *v = reinterpret_cast<const Size *>(cv.data().data());
> > -               return py::cast(v);
> > -       }
> > -       case ControlTypeNone:
> > -       default:
> > -               throw std::runtime_error("Unsupported ControlValue type");
> > -       }
> > -}
> > -
> > -template<typename T>
> > -static ControlValue controlValueMaybeArray(const py::object &ob)
> > -{
> > -       if (py::isinstance<py::list>(ob) || py::isinstance<py::tuple>(ob)) {
> > -               std::vector<T> vec = ob.cast<std::vector<T>>();
> > -               return ControlValue(Span<const T>(vec));
> > -       }
> > -
> > -       return ControlValue(ob.cast<T>());
> > -}
> > -
> > -static ControlValue pyToControlValue(const py::object &ob, ControlType type)
> > -{
> > -       switch (type) {
> > -       case ControlTypeBool:
> > -               return ControlValue(ob.cast<bool>());
> > -       case ControlTypeByte:
> > -               return controlValueMaybeArray<uint8_t>(ob);
> > -       case ControlTypeInteger32:
> > -               return controlValueMaybeArray<int32_t>(ob);
> > -       case ControlTypeInteger64:
> > -               return controlValueMaybeArray<int64_t>(ob);
> > -       case ControlTypeFloat:
> > -               return controlValueMaybeArray<float>(ob);
> > -       case ControlTypeString:
> > -               return ControlValue(ob.cast<std::string>());
> > -       case ControlTypeRectangle:
> > -               return ControlValue(ob.cast<Rectangle>());
> > -       case ControlTypeSize:
> > -               return ControlValue(ob.cast<Size>());
> > -       case ControlTypeNone:
> > -       default:
> > -               throw std::runtime_error("Control type not implemented");
> > -       }
> > -}
> > -
> >  static std::weak_ptr<CameraManager> gCameraManager;
> >  static int gEventfd;
> >  static std::mutex gReqlistMutex;

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list