@@ -18,35 +18,26 @@
#include <libcamera/base/signal.h>
#include <libcamera/base/unique_fd.h>
+#include "libcamera/internal/media_device_base.h"
#include "libcamera/internal/media_object.h"
namespace libcamera {
-class MediaDevice : protected Loggable
+class MediaDevice : public MediaDeviceBase
{
public:
MediaDevice(const std::string &deviceNode);
~MediaDevice();
- bool acquire();
- void release();
- bool busy() const { return acquired_; }
+ bool lock() override;
+ void unlock() override;
- bool lock();
- void unlock();
+ int populate() override;
- int populate();
- bool isValid() const { return valid_; }
-
- const std::string &driver() const { return driver_; }
- const std::string &deviceNode() const { return deviceNode_; }
const std::string &model() const { return model_; }
unsigned int version() const { return version_; }
unsigned int hwRevision() const { return hwRevision_; }
- const std::vector<MediaEntity *> &entities() const { return entities_; }
- MediaEntity *getEntityByName(const std::string &name) const;
-
MediaLink *link(const std::string &sourceName, unsigned int sourceIdx,
const std::string &sinkName, unsigned int sinkIdx);
MediaLink *link(const MediaEntity *source, unsigned int sourceIdx,
@@ -54,18 +45,13 @@ public:
MediaLink *link(const MediaPad *source, const MediaPad *sink);
int disableLinks();
- Signal<> disconnected;
-
-protected:
- std::string logPrefix() const override;
-
private:
- int open();
- void close();
+ int open() override;
+ void close() override;
MediaObject *object(unsigned int id);
bool addObject(MediaObject *object);
- void clear();
+ void clear() override;
struct media_v2_interface *findInterface(const struct media_v2_topology &topology,
unsigned int entityId);
@@ -77,18 +63,13 @@ private:
friend int MediaLink::setEnabled(bool enable);
int setupLink(const MediaLink *link, unsigned int flags);
- std::string driver_;
- std::string deviceNode_;
std::string model_;
unsigned int version_;
unsigned int hwRevision_;
UniqueFD fd_;
- bool valid_;
- bool acquired_;
std::map<unsigned int, MediaObject *> objects_;
- std::vector<MediaEntity *> entities_;
};
} /* namespace libcamera */
new file mode 100644
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022, Google Inc.
+ *
+ * media_device.h - The base class of media device handler
+ */
+
+#pragma once
+
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <linux/media.h>
+
+#include <libcamera/base/log.h>
+#include <libcamera/base/signal.h>
+#include <libcamera/base/unique_fd.h>
+
+#include "libcamera/internal/media_object.h"
+
+namespace libcamera {
+
+class MediaDeviceBase : protected Loggable
+{
+public:
+ MediaDeviceBase(const std::string &deviceNode);
+ ~MediaDeviceBase();
+
+ bool acquire();
+ void release();
+ bool busy() const { return acquired_; }
+
+ virtual bool lock();
+ virtual void unlock();
+
+ virtual int populate();
+ bool isValid() const { return valid_; }
+
+ const std::string &driver() const { return driver_; }
+ const std::string &deviceNode() const { return deviceNode_; }
+
+ const std::vector<MediaEntity *> &entities() const { return entities_; }
+ MediaEntity *getEntityByName(const std::string &name) const;
+
+ Signal<> disconnected;
+
+protected:
+ std::string logPrefix() const override;
+
+ virtual int open() { return 0; }
+ virtual void close() {}
+ virtual void clear();
+
+ std::string driver_;
+ std::string deviceNode_;
+
+ bool valid_;
+ bool acquired_;
+
+ std::vector<MediaEntity *> entities_;
+
+private:
+ bool lock_;
+};
+
+} /* namespace libcamera */
@@ -31,6 +31,7 @@ libcamera_internal_headers = files([
'ipc_unixsocket.h',
'mapped_framebuffer.h',
'media_device.h',
+ 'media_device_base.h',
'media_object.h',
'pipeline_handler.h',
'process.h',
@@ -63,63 +63,13 @@ LOG_DEFINE_CATEGORY(MediaDevice)
* populate() before the media graph can be queried.
*/
MediaDevice::MediaDevice(const std::string &deviceNode)
- : deviceNode_(deviceNode), valid_(false), acquired_(false)
+ : MediaDeviceBase(deviceNode)
{
}
MediaDevice::~MediaDevice()
{
fd_.reset();
- clear();
-}
-
-std::string MediaDevice::logPrefix() const
-{
- return deviceNode() + "[" + driver() + "]";
-}
-
-/**
- * \brief Claim a device for exclusive use
- *
- * The device claiming mechanism offers simple media device access arbitration
- * between multiple users. When the media device is created, it is available to
- * all users. Users can query the media graph to determine whether they can
- * support the device and, if they do, claim the device for exclusive use. Other
- * users are then expected to skip over media devices in use as reported by the
- * busy() function.
- *
- * Once claimed the device shall be released by its user when not needed anymore
- * by calling the release() function. Acquiring the media device opens a file
- * descriptor to the device which is kept open until release() is called.
- *
- * Exclusive access is only guaranteed if all users of the media device abide by
- * the device claiming mechanism, as it isn't enforced by the media device
- * itself.
- *
- * \return true if the device was successfully claimed, or false if it was
- * already in use
- * \sa release(), busy()
- */
-bool MediaDevice::acquire()
-{
- if (acquired_)
- return false;
-
- if (open())
- return false;
-
- acquired_ = true;
- return true;
-}
-
-/**
- * \brief Release a device previously claimed for exclusive use
- * \sa acquire(), busy()
- */
-void MediaDevice::release()
-{
- close();
- acquired_ = false;
}
/**
@@ -290,12 +240,6 @@ done:
* \return The name of the kernel driver that handles the MediaDevice
*/
-/**
- * \fn MediaDevice::deviceNode()
- * \brief Retrieve the media device node path
- * \return The MediaDevice deviceNode path
- */
-
/**
* \fn MediaDevice::model()
* \brief Retrieve the media device model name
@@ -320,26 +264,6 @@ done:
* \return The MediaDevice hardware revision
*/
-/**
- * \fn MediaDevice::entities()
- * \brief Retrieve the list of entities in the media graph
- * \return The list of MediaEntities registered in the MediaDevice
- */
-
-/**
- * \brief Return the MediaEntity with name \a name
- * \param[in] name The entity name
- * \return The entity with \a name, or nullptr if no such entity is found
- */
-MediaEntity *MediaDevice::getEntityByName(const std::string &name) const
-{
- for (MediaEntity *e : entities_)
- if (e->name() == name)
- return e;
-
- return nullptr;
-}
-
/**
* \brief Retrieve the MediaLink connecting two pads, identified by entity
* names and pad indexes
@@ -453,16 +377,6 @@ int MediaDevice::disableLinks()
return 0;
}
-/**
- * \var MediaDevice::disconnected
- * \brief Signal emitted when the media device is disconnected from the system
- *
- * This signal is emitted when the device enumerator detects that the media
- * device has been removed from the system. For hot-pluggable devices this is
- * usually caused by physical device disconnection, but can also result from
- * driver unloading for most devices. The media device is passed as a parameter.
- */
-
/**
* \brief Open the media device
*
@@ -565,14 +479,9 @@ void MediaDevice::clear()
delete o.second;
objects_.clear();
- entities_.clear();
- valid_ = false;
-}
-/**
- * \var MediaDevice::entities_
- * \brief Global list of media entities in the media graph
- */
+ MediaDeviceBase::clear();
+}
/**
* \brief Find the interface associated with an entity
new file mode 100644
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022, Google Inc.
+ *
+ * media_device_base.cpp - The base class of media device handler
+ */
+
+#include "libcamera/internal/media_device_base.h"
+
+namespace libcamera {
+
+LOG_DEFINE_CATEGORY(MediaDeviceBase)
+
+MediaDeviceBase::MediaDeviceBase(const std::string &deviceNode)
+ : deviceNode_(deviceNode), valid_(false), acquired_(false), lock_(false)
+{
+}
+
+MediaDeviceBase::~MediaDeviceBase()
+{
+ clear();
+}
+
+/**
+ * \brief Claim a device for exclusive use
+ *
+ * The device claiming mechanism offers simple media device access arbitration
+ * between multiple users. When the media device is created, it is available to
+ * all users. Users can query the media graph to determine whether they can
+ * support the device and, if they do, claim the device for exclusive use. Other
+ * users are then expected to skip over media devices in use as reported by the
+ * busy() function.
+ *
+ * Once claimed the device shall be released by its user when not needed anymore
+ * by calling the release() function. Acquiring the media device opens a file
+ * descriptor to the device which is kept open until release() is called.
+ *
+ * Exclusive access is only guaranteed if all users of the media device abide by
+ * the device claiming mechanism, as it isn't enforced by the media device
+ * itself.
+ *
+ * \return true if the device was successfully claimed, or false if it was
+ * already in use
+ * \sa release(), busy()
+ */
+bool MediaDeviceBase::acquire()
+{
+ if (acquired_)
+ return false;
+
+ if (open())
+ return false;
+
+ acquired_ = true;
+ return true;
+}
+
+/**
+ * \brief Release a device previously claimed for exclusive use
+ * \sa acquire(), busy()
+ */
+void MediaDeviceBase::release()
+{
+ close();
+ acquired_ = false;
+}
+
+bool MediaDeviceBase::lock()
+{
+ if (lock_)
+ return false;
+
+ lock_ = true;
+ return true;
+}
+
+void MediaDeviceBase::unlock()
+{
+ lock_ = false;
+}
+
+int MediaDeviceBase::populate()
+{
+ valid_ = true;
+ return 0;
+}
+
+/**
+ * \fn MediaDeviceBase::deviceNode()
+ * \brief Retrieve the media device node path
+ * \return The MediaDeviceBase deviceNode path
+ */
+
+/**
+ * \fn MediaDeviceBase::entities()
+ * \brief Retrieve the list of entities in the media graph
+ * \return The list of MediaEntities registered in the MediaDeviceBase
+ */
+
+/**
+ * \brief Return the MediaEntity with name \a name
+ * \param[in] name The entity name
+ * \return The entity with \a name, or nullptr if no such entity is found
+ */
+MediaEntity *MediaDeviceBase::getEntityByName(const std::string &name) const
+{
+ for (MediaEntity *e : entities_)
+ if (e->name() == name)
+ return e;
+
+ return nullptr;
+}
+
+/**
+ * \var MediaDeviceBase::disconnected
+ * \brief Signal emitted when the media device is disconnected from the system
+ *
+ * This signal is emitted when the device enumerator detects that the media
+ * device has been removed from the system. For hot-pluggable devices this is
+ * usually caused by physical device disconnection, but can also result from
+ * driver unloading for most devices. The media device is passed as a parameter.
+ */
+
+std::string MediaDeviceBase::logPrefix() const
+{
+ return deviceNode() + "[" + driver() + "]";
+}
+
+void MediaDeviceBase::clear()
+{
+ entities_.clear();
+ valid_ = false;
+}
+
+/**
+ * \var MediaDeviceBase::entities_
+ * \brief Global list of media entities in the media graph
+ */
+
+} /* namespace libcamera */
@@ -32,6 +32,7 @@ libcamera_sources = files([
'ipc_unixsocket.cpp',
'mapped_framebuffer.cpp',
'media_device.cpp',
+ 'media_device_base.cpp',
'media_object.cpp',
'pipeline_handler.cpp',
'pixel_format.cpp',
To introduce a virtual MediaDevice class in the following patches, adds a base class of MediaDevice, to be used in other base classes. Signed-off-by: Harvey Yang <chenghaoyang@chromium.org> --- include/libcamera/internal/media_device.h | 35 +---- .../libcamera/internal/media_device_base.h | 68 +++++++++ include/libcamera/internal/meson.build | 1 + src/libcamera/media_device.cpp | 97 +----------- src/libcamera/media_device_base.cpp | 140 ++++++++++++++++++ src/libcamera/meson.build | 1 + 6 files changed, 221 insertions(+), 121 deletions(-) create mode 100644 include/libcamera/internal/media_device_base.h create mode 100644 src/libcamera/media_device_base.cpp