[libcamera-devel] [PATCH 3/5] libcamera: Add MediaLink link setup function
Niklas Söderlund
niklas.soderlund at ragnatech.se
Fri Jan 4 17:45:09 CET 2019
Hi Jacopo,
Thanks for your patch.
On 2019-01-03 18:38:57 +0100, Jacopo Mondi wrote:
> Add a function to the MediaLink class to set the state of a link to
> enabled or disabled. The function makes use of an internal MediaDevice
> method, which is defined private and only accessible by the MediaLink
> setup() function itself.
>
> Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
> ---
> src/libcamera/include/media_device.h | 8 ++++++
> src/libcamera/include/media_object.h | 1 +
> src/libcamera/media_device.cpp | 30 +++++++++++++++++++++
> src/libcamera/media_object.cpp | 40 ++++++++++++++++++++++++++++
> 4 files changed, 79 insertions(+)
>
> diff --git a/src/libcamera/include/media_device.h b/src/libcamera/include/media_device.h
> index 3228ad5..d019639 100644
> --- a/src/libcamera/include/media_device.h
> +++ b/src/libcamera/include/media_device.h
> @@ -65,6 +65,14 @@ private:
> bool populateEntities(const struct media_v2_topology &topology);
> bool populatePads(const struct media_v2_topology &topology);
> bool populateLinks(const struct media_v2_topology &topology);
> +
> + /*
> + * The MediaLink enable method needs to access the private
> + * setLink() function.
> + */
> + friend int MediaLink::enable(bool enable);
I'm not saying we won't need this. But reading this makes me a bit
uncomfortable that the over all design is not sound. Would it not be OK
to make setLink() public instead? This interface will not be exposed to
applications so I don't feel there is a great need to protect us from us
self :-)
> + int setLink(const MediaPad *source, const MediaPad *sink,
> + unsigned int flags);
> };
>
> } /* namespace libcamera */
> diff --git a/src/libcamera/include/media_object.h b/src/libcamera/include/media_object.h
> index 0f0bb29..e00c639 100644
> --- a/src/libcamera/include/media_object.h
> +++ b/src/libcamera/include/media_object.h
> @@ -40,6 +40,7 @@ public:
> MediaPad *source() const { return source_; }
> MediaPad *sink() const { return sink_; }
> unsigned int flags() const { return flags_; }
> + int enable(bool enable);
>
> private:
> friend class MediaDevice;
> diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp
> index 6892300..b86d0c4 100644
> --- a/src/libcamera/media_device.cpp
> +++ b/src/libcamera/media_device.cpp
> @@ -641,4 +641,34 @@ bool MediaDevice::populateLinks(const struct media_v2_topology &topology)
> return true;
> }
>
> +int MediaDevice::setLink(const MediaPad *source, const MediaPad *sink,
> + unsigned int flags)
> +{
> + struct media_link_desc linkDesc = { };
> +
> + linkDesc.source.entity = source->entity()->id();
> + linkDesc.source.index = source->index();
> + linkDesc.source.flags = MEDIA_PAD_FL_SOURCE;
> +
> + linkDesc.sink.entity = sink->entity()->id();
> + linkDesc.sink.index = sink->index();
> + linkDesc.sink.flags = MEDIA_PAD_FL_SINK;
> +
> + linkDesc.flags = flags;
> +
> + int ret = ioctl(fd_, MEDIA_IOC_SETUP_LINK, &linkDesc);
> + if (ret) {
> + ret = -errno;
> + LOG(Error) << "Failed to setup link: " << strerror(-ret) << "\n";
> + return ret;
> + }
> +
> + LOG(Debug) << source->entity()->name() << "["
> + << source->index() << "] -> "
> + << sink->entity()->name() << "["
> + << sink->index() << "]: " << flags;
Should you not log linkDesc.flags here in case the IOCTL changed the
flags? Or maybe even compare flags to linkDesc.flags to make sure the
flags you want set is set. This is a open question and I'm fine with
this approach if MEDIA_IOC_SETUP_LINK can not modify the flags.
> +
> + return 0;
> +}
> +
> } /* namespace libcamera */
> diff --git a/src/libcamera/media_object.cpp b/src/libcamera/media_object.cpp
> index f1535e6..1ee8823 100644
> --- a/src/libcamera/media_object.cpp
> +++ b/src/libcamera/media_object.cpp
> @@ -16,6 +16,7 @@
>
> #include "log.h"
> #include "media_object.h"
> +#include "media_device.h"
>
> /**
> * \file media_object.h
> @@ -87,6 +88,45 @@ namespace libcamera {
> * Each link is referenced in the link array of both of the pads it connect.
> */
>
> +/**
> + * \brief Set a link state to enabled or disabled
Enable or disable a link in the media graph
> + * \param enable The enable flag, true enables the link, false disables it
> + *
> + * Set the status of a link, according to the value of \a enable.
> + * Links between two pads can be set to the enabled or disabled state freely,
> + * unless they're immutable links, whose status cannot be changed.
> + * Enabling an immutable link is not considered an error, while trying to
> + * disable it is. Caller should inspect the link flags before trying to
> + * disable an immutable link.
> + *
> + * Enabling a link establishes a data connection between two pads, while
> + * disabling it interrupts such a connections.
> + *
> + * \return 0 for success, negative error code otherwise
> + */
> +int MediaLink::enable(bool enable)
> +{
> + unsigned int flags = enable ? MEDIA_LNK_FL_ENABLED : 0;
> +
> + if ((flags_ & MEDIA_LNK_FL_IMMUTABLE) && !enable) {
> + LOG(Error) << "Immutable links cannot be disabled";
> + return -EINVAL;
> + }
Is it sound to relay on cached values here? What if the kernel have
changed the state of the link to once more be mutable (not sure any
drivers to this today)? I would drop this check and let the kernel deal
with this and relay on the return code from the MEDIA_IOC_SETUP_LINK
ioctl.
> +
> + /* Do not try to enable an already enabled link. */
> + if ((flags_ & MEDIA_LNK_FL_ENABLED) && enable)
> + return 0;
Same here, I would not trust the cached value. What if another process
have modified the media graph unknown to the library? Better let the
request happen and let the kernel deal with it.
> +
> + int ret = media_->setLink(source_, sink_, flags);
> + if (ret)
> + return ret;
> +
> + /* Only update flags if 'setLink()' didn't fail. */
> + flags_ = flags;
> +
> + return 0;
I think you can drop the comment and change this to:
int ret = media_->setLink(source_, sink_, flags);
if (!ret)
flags_ = flags;
return ret;
> +}
> +
> /**
> * \brief Construct a MediaLink
> * \param media The media device this entity belongs to
> --
> 2.20.1
>
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel
--
Regards,
Niklas Söderlund
More information about the libcamera-devel
mailing list