summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacopo Mondi <jacopo@jmondi.org>2018-12-20 15:20:37 +0100
committerJacopo Mondi <jacopo@jmondi.org>2018-12-31 18:56:41 +0100
commitf0e16f0389eefef14cccf232ec79f3a296a959da (patch)
tree5c9d198be4cf8caed9801e080a85009d97c2c52d
parent20d15d9dc47fcfbf1f02689cc4c882115abe507f (diff)
libcamera: Add MediaObject class hierarchy
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: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
-rw-r--r--src/libcamera/include/media_object.h106
-rw-r--r--src/libcamera/media_object.cpp282
-rw-r--r--src/libcamera/meson.build2
3 files changed, 390 insertions, 0 deletions
diff --git a/src/libcamera/include/media_object.h b/src/libcamera/include/media_object.h
new file mode 100644
index 00000000..65b55085
--- /dev/null
+++ b/src/libcamera/include/media_object.h
@@ -0,0 +1,106 @@
+/* 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 MediaPad;
+
+class MediaObject
+{
+public:
+ unsigned int id() const { return id_; }
+
+protected:
+ friend class MediaDevice;
+
+ MediaObject(unsigned int id) : id_(id) { }
+ virtual ~MediaObject() { }
+
+ unsigned int id_;
+};
+
+class MediaLink : public MediaObject
+{
+public:
+ MediaPad *source() const { return source_; }
+ MediaPad *sink() const { return sink_; }
+ unsigned int flags() const { return flags_; }
+
+private:
+ friend class MediaDevice;
+
+ MediaLink(const struct media_v2_link *link,
+ MediaPad *source, MediaPad *sink);
+ MediaLink(const MediaLink &) = delete;
+ ~MediaLink() { }
+
+ MediaPad *source_;
+ MediaPad *sink_;
+ unsigned int flags_;
+};
+
+class MediaPad : public MediaObject
+{
+public:
+ 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:
+ friend class MediaDevice;
+
+ MediaPad(const struct media_v2_pad *pad, MediaEntity *entity);
+ MediaPad(const MediaPad &) = delete;
+ ~MediaPad();
+
+ unsigned int index_;
+ MediaEntity *entity_;
+ unsigned int flags_;
+
+ std::vector<MediaLink *> links_;
+};
+
+class MediaEntity : public MediaObject
+{
+public:
+ const std::string &name() const { return name_; }
+
+ const std::vector<MediaPad *> &pads() const { return pads_; }
+
+ const MediaPad *getPadByIndex(unsigned int index) const;
+ const MediaPad *getPadById(unsigned int id) const;
+
+private:
+ friend class MediaDevice;
+
+ 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 00000000..b64dcc3c
--- /dev/null
+++ b/src/libcamera/media_object.cpp
@@ -0,0 +1,282 @@
+/* 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
+ * \brief Provides a class hierarchy that represents the media objects exposed
+ * by the Linux kernel Media Controller APIs.
+ *
+ * The abstract MediaObject class represents any Media Controller graph object
+ * identified by an id unique in the media device context. It is subclassed by
+ * the MediaEntity, MediaPad and MediaLink classes that represent the entities,
+ * pads and links respectively. They are populated based on the media graph
+ * information exposed by the Linux kernel through the MEDIA_IOC_G_TOPOLOGY
+ * ioctl.
+ *
+ * As the media objects represent their kernel counterpart, information about
+ * the properties they expose can be found in the Linux kernel documentation.
+ *
+ * All media objects are meant to be created and destroyed solely by the
+ * MediaDevice and thus have private constructors and destructors.
+ */
+
+namespace libcamera {
+
+/**
+ * \class MediaObject
+ * \brief Base class for all media objects
+ *
+ * MediaObject is an abstract base class for all media objects in the media
+ * graph. Every media graph object is identified by an id unique in the media
+ * device context, and this base class provides that.
+ *
+ * \sa MediaEntity, MediaPad, MediaLink
+ */
+
+/**
+ * \fn MediaObject::MediaObject()
+ * \brief Construct a MediaObject with \a id
+ * \param id The media object id
+ *
+ * The caller shall ensure unicity of the object id in the media device context.
+ * This constraint is neither enforced nor checked by the MediaObject.
+ */
+
+/**
+ * \fn MediaObject::id()
+ * \brief Retrieve the media object id
+ * \return The media object id
+ */
+
+/**
+ * \var MediaObject::id_
+ * \brief The media object id
+ */
+
+/**
+ * \class MediaLink
+ * \brief The MediaLink represents a link between two pads in the media graph.
+ *
+ * Links are created from the information provided by the Media Controller API
+ * in the media_v2_link structure. They reference the source() and sink() pads
+ * they connect and track the link status through link flags().
+ *
+ * Each link is referenced in the link array of both of the pads it connect.
+ */
+
+/**
+ * \brief Construct a MediaLink
+ * \param link The media link kernel data
+ * \param source The source pad at the origin of the link
+ * \param sink The sink pad at the destination of the link
+ */
+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 Retrieve the link's source pad
+ * \return The source pad at the origin of the link
+ */
+
+/**
+ * \fn MediaLink::sink()
+ * \brief Retrieve the link's sink pad
+ * \return The sink pad at the destination of the link
+ */
+
+/**
+ * \fn MediaLink::flags()
+ * \brief Retrieve the link's flags
+ *
+ * Link flags are a bitmask of flags defined by the Media Controller API
+ * MEDIA_LNK_FL_* macros.
+ *
+ * \return The link flags
+ */
+
+/**
+ * \class MediaPad
+ * \brief The MediaPad represents a pad of an entity in the media graph
+ *
+ * Pads are created from the information provided by the Media Controller API
+ * in the media_v2_pad structure. They reference the entity() they belong to.
+ *
+ * In addition to its graph id, every media graph pad is identified by an index
+ * unique in the context of the entity the pad belongs to.
+ *
+ * A pad can be either a 'source' pad or a 'sink' pad. This information is
+ * captured in the pad flags().
+ *
+ * Pads are connected through links. Links originating from a source pad are
+ * outbound links, and links arriving at a sink pad are inbound links. Pads
+ * reference all the links() that are connected to them.
+ */
+
+/**
+ * \brief Construct a MediaPad
+ * \param pad The media pad kernel data
+ * \param entity The entity the pad belongs to
+ */
+MediaPad::MediaPad(const struct media_v2_pad *pad, MediaEntity *entity)
+ : MediaObject(pad->id), index_(pad->index), entity_(entity),
+ flags_(pad->flags)
+{
+}
+
+MediaPad::~MediaPad()
+{
+ /*
+ * Don't delete the links as we only borrow the reference owned by
+ * MediaDevice.
+ */
+ links_.clear();
+}
+
+/**
+ * \fn MediaPad::index()
+ * \brief Retrieve the pad index
+ * \return The 0-based pad index identifying the pad in the context of the
+ * entity it belongs to
+ */
+
+/**
+ * \fn MediaPad::entity()
+ * \brief Retrieve the entity the pad belongs to
+ * \return The MediaEntity the pad belongs to
+ */
+
+/**
+ * \fn MediaPad::flags()
+ * \brief Retrieve the pad flags
+ *
+ * Pad flags are a bitmask of flags defined by the Media Controller API
+ * MEDIA_PAD_FL_* macros.
+ *
+ * \return The pad flags
+ */
+
+/**
+ * \fn MediaPad::links()
+ * \brief Retrieve all links in the pad
+ * \return A list of links connected to the pad
+ */
+
+/**
+ * \brief Add a new link to this pad
+ * \param link The MediaLink to add
+ */
+void MediaPad::addLink(MediaLink *link)
+{
+ links_.push_back(link);
+}
+
+/**
+ * \class MediaEntity
+ * \brief The MediaEntity represents an entity in the media graph
+ *
+ * Entities are created from the information provided by the Media Controller
+ * API in the media_v2_entity structure. They reference the pads() they contain.
+ *
+ * In addition to its graph id, every media graph entity is identified by a
+ * name() unique in the media device context.
+ *
+ * \todo Add support for associating a devnode to the entity when integrating
+ * with DeviceEnumerator.
+ */
+
+/**
+ * \fn MediaEntity::name()
+ * \brief Retrieve the entity name
+ * \return The entity name
+ */
+
+/**
+ * \fn MediaEntity::pads()
+ * \brief Retrieve all pads of the entity
+ * \return The list of the entity's pads
+ */
+
+/**
+ * \brief Get a pad in this entity by its index
+ * \param index The 0-based pad index
+ * \return The pad identified by \a index, or nullptr if no such pad exist
+ */
+const MediaPad *MediaEntity::getPadByIndex(unsigned int index) const
+{
+ for (MediaPad *p : pads_) {
+ if (p->index() == index)
+ return p;
+ }
+
+ return nullptr;
+}
+
+/**
+ * \brief Get a pad in this entity by its object id
+ * \param id The pad id
+ * \return The pad identified by \a id, or nullptr if no such pad exist
+ */
+const MediaPad *MediaEntity::getPadById(unsigned int id) const
+{
+ for (MediaPad *p : pads_) {
+ if (p->id() == id)
+ return p;
+ }
+
+ return nullptr;
+}
+
+/**
+ * \brief Construct a MediaEntity
+ * \param entity The media entity kernel data
+ */
+MediaEntity::MediaEntity(const struct media_v2_entity *entity)
+ : MediaObject(entity->id), name_(entity->name)
+{
+}
+
+MediaEntity::~MediaEntity()
+{
+ /*
+ * Don't delete the pads as we only borrow the reference owned by
+ * MediaDevice.
+ */
+ pads_.clear();
+}
+
+/**
+ * \brief Add \a pad to the entity's list of pads
+ * \param pad The pad to add to the list
+ *
+ * This function is meant to add pads to the entity during parsing of the media
+ * graph, after the MediaPad objects are constructed and before the MediaDevice
+ * is made available externally.
+ */
+void MediaEntity::addPad(MediaPad *pad)
+{
+ pads_.push_back(pad);
+}
+
+} /* namespace libcamera */
diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
index ac5bba05..2985d40c 100644
--- a/src/libcamera/meson.build
+++ b/src/libcamera/meson.build
@@ -4,12 +4,14 @@ libcamera_sources = files([
'device_enumerator.cpp',
'log.cpp',
'main.cpp',
+ 'media_object.cpp',
'pipeline_handler.cpp',
])
libcamera_headers = files([
'include/device_enumerator.h',
'include/log.h',
+ 'include/media_object.h',
'include/pipeline_handler.h',
'include/utils.h',
])