[libcamera-devel] [PATCH v3 1/3] libcamera: Add MediaObject class hierarchy
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Mon Dec 31 01:39:54 CET 2018
Hi Jacopo,
Thank you for the patch.
On Sunday, 30 December 2018 16:23:12 EET Jacopo Mondi wrote:
> Add a class hierarcy to represent all media objects a media graph
> represents. Add a base MediaObject class, which retains the global unique
> object id, and define the derived MediaEntity, MediaLink and MediaPad
> classes.
>
> This hierarchy will be used by the MediaDevice objects which represents and
> handles the media graph.
>
> Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
> ---
> src/libcamera/include/media_object.h | 107 ++++++++++
> src/libcamera/media_object.cpp | 281 +++++++++++++++++++++++++++
> src/libcamera/meson.build | 2 +
> 3 files changed, 390 insertions(+)
> create mode 100644 src/libcamera/include/media_object.h
> create mode 100644 src/libcamera/media_object.cpp
>
> diff --git a/src/libcamera/include/media_object.h
> b/src/libcamera/include/media_object.h new file mode 100644
> index 0000000..118d0d8
> --- /dev/null
> +++ b/src/libcamera/include/media_object.h
> @@ -0,0 +1,107 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2018, Google Inc.
> + *
> + * media_object.h - Media Device objects: entities, pads and links.
> + */
> +#ifndef __LIBCAMERA_MEDIA_OBJECT_H__
> +#define __LIBCAMERA_MEDIA_OBJECT_H__
> +
> +#include <string>
> +#include <vector>
> +
> +#include <linux/media.h>
> +
> +namespace libcamera {
> +
> +class MediaDevice;
> +class MediaEntity;
> +
> +class MediaObject
> +{
> +public:
> + MediaObject(unsigned int id) : id_(id) { }
> + virtual ~MediaObject() { }
> +
> + unsigned int id() const { return id_; }
> +
> +protected:
> + unsigned int id_;
> +};
> +
> +class MediaPad;
> +class MediaLink : public MediaObject
> +{
> + friend class MediaDevice;
> +
> +public:
> + ~MediaLink() { }
> +
> + MediaPad *source() const { return source_; }
> + MediaPad *sink() const { return sink_; }
> + unsigned int flags() const { return flags_; }
> + void setFlags(unsigned int flags) { flags_ = flags; }
> +
> +private:
> + MediaLink(const struct media_v2_link *link,
> + MediaPad *source, MediaPad *sink);
> + MediaLink(const MediaLink &) = delete;
> +
> + MediaPad *source_;
> + MediaPad *sink_;
> + unsigned int flags_;
> +};
> +
> +class MediaEntity;
> +class MediaPad : public MediaObject
> +{
> + friend class MediaDevice;
> +
> +public:
> + ~MediaPad();
> +
> + unsigned int index() const { return index_; }
> + MediaEntity *entity() const { return entity_; }
> + unsigned int flags() const { return flags_; }
> + const std::vector<MediaLink *> &links() const { return links_; }
> +
> + void addLink(MediaLink *link);
> +
> +private:
> + MediaPad(const struct media_v2_pad *pad, MediaEntity *entity);
> + MediaPad(const MediaPad &) = delete;
> +
> + unsigned int index_;
> + MediaEntity *entity_;
> + unsigned int flags_;
> +
> + std::vector<MediaLink *> links_;
> +};
> +
> +class MediaEntity : public MediaObject
> +{
> + friend class MediaDevice;
> +
> +public:
> + const std::string &name() const { return name_; }
> +
> + const std::vector<MediaPad *> &pads() { return pads_; }
> +
> + const MediaPad *getPadByIndex(unsigned int index);
> + const MediaPad *getPadById(unsigned int id);
> +
> +private:
> + MediaEntity(const struct media_v2_entity *entity);
> + MediaEntity(const MediaEntity &) = delete;
> + ~MediaEntity();
> +
> + std::string name_;
> + std::string devnode_;
> +
> + std::vector<MediaPad *> pads_;
> +
> + void addPad(MediaPad *pad);
> +};
> +
> +} /* namespace libcamera */
> +#endif /* __LIBCAMERA_MEDIA_OBJECT_H__ */
> diff --git a/src/libcamera/media_object.cpp b/src/libcamera/media_object.cpp
> new file mode 100644
> index 0000000..f0906e8
> --- /dev/null
> +++ b/src/libcamera/media_object.cpp
> @@ -0,0 +1,281 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2018, Google Inc.
> + *
> + * media_object.cpp - Media device objects: entities, pads and links
> + */
> +
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <string.h>
> +#include <sys/stat.h>
> +
> +#include <string>
> +#include <vector>
> +
> +#include <linux/media.h>
> +
> +#include "log.h"
> +#include "media_object.h"
> +
> +/**
> + * \file media_object.h
> + *
> + * In the media object file is implemented a class hierarchy that
> + * represent the counterpart of media objects exposed by the kernel's
> + * media controller APIs.
> + *
> + * Media Objects here represented are media entities, media pads and
> + * media links, created with informations as obtained by the
> + * MEDIA_IOC_G_TOPOLOGY ioctl call.
> + *
> + * MediaLink, MediaPad and MediaEntity are derived classes of the virtual
> + * base class MediaObject, which maintains a globally unique id for each
> object. + *
> + * Media objects have private constructors to restrict the number of
> classes + * that can instantiate them only to the 'friend' MediaDevice one.
> Media + * objects are in facts created when a MediaDevice gets populated. +
> */
> +
> +namespace libcamera {
> +
> +/**
> + * \class MediaObject
> + * \brief Base class for all media object types
> + *
> + * MediaObject is the virtual base class for all media objects in the
> + * media graph. Each object has a globally unique id assigned, and this
> + * base class provides that.
> + *
> + * MediaEntities, MediaPads and MediaLink are MediaObject derived classes.
> + */
> +
> +/**
> + * \fn MediaObject::MediaObject()
> + * \brief Construct a MediaObject with \a id
> + * \param id The globally unique object id
> + */
> +
> +/**
> + * \fn MediaObject::id()
> + * \brief Return the object's globally unique id
> + */
> +
> +/**
> + * \var MediaObject::id_
> + * \brief The MediaObject unique id
> + */
> +
> +/**
> + * \class MediaLink
> + * \brief Media Link object
> + *
> + * A MediaLink represents a 'struct media_v2_link', with associated
> + * references to the MediaPad it connects and an internal status defined
> + * by the MEDIA_LNK_FL_* flags captured in flags_.
> + *
> + * MediaLink can be enabled enabled and disabled, with the exception of
> + * immutable links (see MEDIA_LNK_FL_IMMUTABLE).
> + *
> + * MediaLinks are created between MediaPads inspecting the media graph
> + * topology and are stored in both the source and sink MediaPad they
> + * connect.
> + */
> +
> +/**
> + * \brief Construct a MediaLink
> + * \param link The media link representation
> + * \param source The MediaPad source
> + * \param sink The MediaPad sink
> + */
> +MediaLink::MediaLink(const struct media_v2_link *link, MediaPad *source,
> + MediaPad *sink)
> + : MediaObject(link->id), source_(source),
> + sink_(sink), flags_(link->flags)
> +{
> +}
> +
> +/**
> + * \fn MediaLink::source()
> + * \brief Return the source MediaPad
> + */
> +
> +/**
> + * \fn MediaLink::sink()
> + * \brief Return the sink MediaPad
> + */
> +
> +/**
> + * \fn MediaLink::flags()
> + * \brief Return the link flags
> + */
> +
> +/**
> + * \fn MediaLink::setFlags()
> + * \brief Set the link flags to \a flags
> + * \param flags The flags to be applied to the link
> + */
> +
> +/**
> + * \class MediaPad
> + * \brief Media Pad object
> + *
> + * MediaPads represent a 'struct media_v2_pad', with associated a list of
> + * links and a reference to the entity they belong to.
> + *
> + * MediaPads are connected to other MediaPads by MediaLinks, created
> + * inspecting the media graph topology. Data connection between pads can be
> + * enabled or disabled operating on the link that connects the two. See +
> * MediaLink.
> + *
> + * MediaPads are either 'source' pads, or 'sink' pads. This information is
> + * captured by the MEDIA_PAD_FL_* flags as stored in the flags_ member
> + * variable.
> + *
> + * Each MediaPad has a list of MediaLinks it is associated to. All links
> + * in a source pad are outbound links, while all links in a sink pad are
> + * inbound ones.
> + *
> + * Each MediaPad has a reference to the MediaEntity it belongs to.
> + */
> +
> +/**
> + * \brief Create a MediaPad
> + * \param pad The media pad representation
> + * \param entity The MediaEntity this pad belongs to
> + */
> +MediaPad::MediaPad(const struct media_v2_pad *pad, MediaEntity *entity)
> + : MediaObject(pad->id), index_(pad->index), entity_(entity),
> + flags_(pad->flags)
> +{
> +}
> +
> +/**
> + * \brief Delete pad.
> + *
> + * Delete the pad by deleting its media links. As a reference to the same
> + * MediaLink gets stored in both the source and the sink pad, only source
> + * ones actually delete the MediaLink.
> + */
> +MediaPad::~MediaPad()
> +{
> + for (MediaLink *l : links_)
> + if (flags_ & MEDIA_PAD_FL_SOURCE)
> + delete l;
This is dangerous. Let's store all media objects in one vector in MediaDevice
and delete them all from there.
> +
> + links_.clear();
> +}
> +
> +/**
> + * \fn MediaPad::index()
> + * \brief Return the 0-indexed pad index
> + */
> +
> +/**
> + * \fn MediaPad::entity()
> + * \brief Return the MediaEntity this pad belongs to
> + */
> +
> +/**
> + * \fn MediaPad::flags()
> + * \brief Return the pad flags (MEDIA_PAD_FL_*)
> + */
> +
> +/**
> + * \fn MediaPad::links()
> + * \brief Return all links in this pad.
> + */
> +
> +/**
> + * \brief Add a new link to this pad.
> + * \param link The new link to add
> + */
> +void MediaPad::addLink(MediaLink *link)
> +{
> + links_.push_back(link);
> +}
> +
> +/**
> + * \class MediaEntity
> + * \brief Media entity
> + *
> + * A MediaEntity represents a 'struct media_v2_entity' with an associated
> + * list of MediaPads it contains.
> + *
> + * Entities are created inspecting the media graph topology, and MediaPads
> + * gets added as they are discovered.
> + *
> + * TODO: Add support for associating a devnode to the entity when
> integrating
> + * with DeviceEnumerator.
> + */
> +
> +/**
> + * \fn MediaEntity::name()
> + * \brief Return the entity name
> + */
> +
> +/**
> + * \fn MediaEntity::pads()
> + * \brief Return all pads in this entity
> + */
> +
> +/**
> + * \fn MediaEntity::getPadByIndex(unsigned int index)
> + * \brief Get a pad in this entity by its index
> + * \return The pad with index \a index
> + * \return nullptr if no pad is found at \index
> + */
> +const MediaPad *MediaEntity::getPadByIndex(unsigned int index)
> +{
> + for (MediaPad *p : pads_)
> + if (p->index() == index)
> + return p;
> +
> + return nullptr;
You can just return pads_[index] (checking whether index is valid first of
course).
> +}
> +
> +/**
> + * \brief Get a pad in this entity by its id
> + * \param id The pad globally unique id
> + * \return The pad with id \a id
> + * \return nullptr if not pad with \id is found
> + */
> +const MediaPad *MediaEntity::getPadById(unsigned int id)
> +{
> + for (MediaPad *p : pads_)
> + if (p->id() == id)
> + return p;
> +
> + return nullptr;
> +}
> +
> +/**
> + * \brief Construct a MediaEntity
> + * \param entity The media entity representation
> + */
> +MediaEntity::MediaEntity(const struct media_v2_entity *entity)
> + : MediaObject(entity->id), name_(entity->name)
> +{
> +}
> +
> +/**
> + * \fn MediaEntity::~MediaEntity()
> + * \brief Delete all pads in the entity
> + */
> +MediaEntity::~MediaEntity()
> +{
> + for (MediaPad *p : pads_)
> + delete p;
Same comment as for links.
Apart from that there's no blocking issue,
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> + pads_.clear();
> +}
> +
> +/**
> + * \brief Add \a pad to list of entity's pads
> + * \param pad The pad to add
> + */
> +void MediaEntity::addPad(MediaPad *pad)
> +{
> + pads_.push_back(pad);
> +}
> +
> +} /* namespace libcamera */
> diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
> index f632eb5..01d321c 100644
> --- a/src/libcamera/meson.build
> +++ b/src/libcamera/meson.build
> @@ -1,10 +1,12 @@
> libcamera_sources = files([
> 'log.cpp',
> 'main.cpp',
> + 'media_object.cpp',
> ])
>
> libcamera_headers = files([
> 'include/log.h',
> + 'include/media_object.h',
> 'include/utils.h',
> ])
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list