summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libcamera/pipeline/raspberrypi/meson.build1
-rw-r--r--src/libcamera/pipeline/raspberrypi/raspberrypi.cpp193
-rw-r--r--src/libcamera/pipeline/raspberrypi/rpi_stream.cpp116
-rw-r--r--src/libcamera/pipeline/raspberrypi/rpi_stream.h107
4 files changed, 243 insertions, 174 deletions
diff --git a/src/libcamera/pipeline/raspberrypi/meson.build b/src/libcamera/pipeline/raspberrypi/meson.build
index ae0aed3b..7c5b6ff7 100644
--- a/src/libcamera/pipeline/raspberrypi/meson.build
+++ b/src/libcamera/pipeline/raspberrypi/meson.build
@@ -3,5 +3,6 @@
libcamera_sources += files([
'dma_heaps.cpp',
'raspberrypi.cpp',
+ 'rpi_stream.cpp',
'staggered_ctrl.cpp',
])
diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
index ce43af34..3d94b3ed 100644
--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
@@ -19,7 +19,6 @@
#include <libcamera/logging.h>
#include <libcamera/property_ids.h>
#include <libcamera/request.h>
-#include <libcamera/stream.h>
#include <linux/videodev2.h>
@@ -33,6 +32,7 @@
#include "libcamera/internal/v4l2_videodevice.h"
#include "dma_heaps.h"
+#include "rpi_stream.h"
#include "staggered_ctrl.h"
namespace libcamera {
@@ -122,165 +122,10 @@ V4L2DeviceFormat findBestMode(V4L2VideoDevice::Formats &formatsMap,
return bestMode;
}
-} /* namespace */
-
-/*
- * Device stream abstraction for either an internal or external stream.
- * Used for both Unicam and the ISP.
- */
-class RPiStream : public Stream
-{
-public:
- RPiStream()
- {
- }
-
- RPiStream(const char *name, MediaEntity *dev, bool importOnly = false)
- : external_(false), importOnly_(importOnly), name_(name),
- dev_(std::make_unique<V4L2VideoDevice>(dev))
- {
- }
-
- V4L2VideoDevice *dev() const
- {
- return dev_.get();
- }
-
- void setExternal(bool external)
- {
- external_ = external;
- }
-
- bool isExternal() const
- {
- /*
- * Import streams cannot be external.
- *
- * RAW capture is a special case where we simply copy the RAW
- * buffer out of the request. All other buffer handling happens
- * as if the stream is internal.
- */
- return external_ && !importOnly_;
- }
-
- bool isImporter() const
- {
- return importOnly_;
- }
-
- void reset()
- {
- external_ = false;
- internalBuffers_.clear();
- }
-
- std::string name() const
- {
- return name_;
- }
-
- void setExternalBuffers(std::vector<std::unique_ptr<FrameBuffer>> *buffers)
- {
- externalBuffers_ = buffers;
- }
-
- const std::vector<std::unique_ptr<FrameBuffer>> *getBuffers() const
- {
- return external_ ? externalBuffers_ : &internalBuffers_;
- }
-
- void releaseBuffers()
- {
- dev_->releaseBuffers();
- if (!external_ && !importOnly_)
- internalBuffers_.clear();
- }
-
- int importBuffers(unsigned int count)
- {
- return dev_->importBuffers(count);
- }
-
- int allocateBuffers(unsigned int count)
- {
- return dev_->allocateBuffers(count, &internalBuffers_);
- }
-
- int queueBuffers()
- {
- if (external_)
- return 0;
-
- for (auto &b : internalBuffers_) {
- int ret = dev_->queueBuffer(b.get());
- if (ret) {
- LOG(RPI, Error) << "Failed to queue buffers for "
- << name_;
- return ret;
- }
- }
-
- return 0;
- }
-
- bool findFrameBuffer(FrameBuffer *buffer) const
- {
- auto start = external_ ? externalBuffers_->begin() : internalBuffers_.begin();
- auto end = external_ ? externalBuffers_->end() : internalBuffers_.end();
-
- if (importOnly_)
- return false;
-
- if (std::find_if(start, end,
- [buffer](std::unique_ptr<FrameBuffer> const &ref) { return ref.get() == buffer; }) != end)
- return true;
-
- return false;
- }
-
-private:
- /*
- * Indicates that this stream is active externally, i.e. the buffers
- * are provided by the application.
- */
- bool external_;
- /* Indicates that this stream only imports buffers, e.g. ISP input. */
- bool importOnly_;
- /* Stream name identifier. */
- std::string name_;
- /* The actual device stream. */
- std::unique_ptr<V4L2VideoDevice> dev_;
- /* Internally allocated framebuffers associated with this device stream. */
- std::vector<std::unique_ptr<FrameBuffer>> internalBuffers_;
- /* Externally allocated framebuffers associated with this device stream. */
- std::vector<std::unique_ptr<FrameBuffer>> *externalBuffers_;
-};
-
-/*
- * The following class is just a convenient (and typesafe) array of device
- * streams indexed with an enum class.
- */
enum class Unicam : unsigned int { Image, Embedded };
enum class Isp : unsigned int { Input, Output0, Output1, Stats };
-template<typename E, std::size_t N>
-class RPiDevice : public std::array<class RPiStream, N>
-{
-private:
- constexpr auto index(E e) const noexcept
- {
- return static_cast<std::underlying_type_t<E>>(e);
- }
-public:
- RPiStream &operator[](E e)
- {
- return std::array<class RPiStream, N>::operator[](index(e));
- }
- const RPiStream &operator[](E e) const
- {
- return std::array<class RPiStream, N>::operator[](index(e));
- }
-};
+} /* namespace */
class RPiCameraData : public CameraData
{
@@ -304,15 +149,15 @@ public:
void ispOutputDequeue(FrameBuffer *buffer);
void clearIncompleteRequests();
- void handleStreamBuffer(FrameBuffer *buffer, const RPiStream *stream);
+ void handleStreamBuffer(FrameBuffer *buffer, const RPi::RPiStream *stream);
void handleState();
CameraSensor *sensor_;
/* Array of Unicam and ISP device streams and associated buffers/streams. */
- RPiDevice<Unicam, 2> unicam_;
- RPiDevice<Isp, 4> isp_;
+ RPi::RPiDevice<Unicam, 2> unicam_;
+ RPi::RPiDevice<Isp, 4> isp_;
/* The vector below is just for convenience when iterating over all streams. */
- std::vector<RPiStream *> streams_;
+ std::vector<RPi::RPiStream *> streams_;
/* Buffers passed to the IPA. */
std::vector<IPABuffer> ipaBuffers_;
@@ -761,7 +606,7 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)
int PipelineHandlerRPi::exportFrameBuffers([[maybe_unused]] Camera *camera, Stream *stream,
std::vector<std::unique_ptr<FrameBuffer>> *buffers)
{
- RPiStream *s = static_cast<RPiStream *>(stream);
+ RPi::RPiStream *s = static_cast<RPi::RPiStream *>(stream);
unsigned int count = stream->configuration().bufferCount;
int ret = s->dev()->exportBuffers(count, buffers);
@@ -908,14 +753,14 @@ bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator)
return false;
/* Locate and open the unicam video streams. */
- data->unicam_[Unicam::Embedded] = RPiStream("Unicam Embedded", unicam_->getEntityByName("unicam-embedded"));
- data->unicam_[Unicam::Image] = RPiStream("Unicam Image", unicam_->getEntityByName("unicam-image"));
+ data->unicam_[Unicam::Embedded] = RPi::RPiStream("Unicam Embedded", unicam_->getEntityByName("unicam-embedded"));
+ data->unicam_[Unicam::Image] = RPi::RPiStream("Unicam Image", unicam_->getEntityByName("unicam-image"));
/* Tag the ISP input stream as an import stream. */
- data->isp_[Isp::Input] = RPiStream("ISP Input", isp_->getEntityByName("bcm2835-isp0-output0"), true);
- data->isp_[Isp::Output0] = RPiStream("ISP Output0", isp_->getEntityByName("bcm2835-isp0-capture1"));
- data->isp_[Isp::Output1] = RPiStream("ISP Output1", isp_->getEntityByName("bcm2835-isp0-capture2"));
- data->isp_[Isp::Stats] = RPiStream("ISP Stats", isp_->getEntityByName("bcm2835-isp0-capture3"));
+ data->isp_[Isp::Input] = RPi::RPiStream("ISP Input", isp_->getEntityByName("bcm2835-isp0-output0"), true);
+ data->isp_[Isp::Output0] = RPi::RPiStream("ISP Output0", isp_->getEntityByName("bcm2835-isp0-capture1"));
+ data->isp_[Isp::Output1] = RPi::RPiStream("ISP Output1", isp_->getEntityByName("bcm2835-isp0-capture2"));
+ data->isp_[Isp::Stats] = RPi::RPiStream("ISP Stats", isp_->getEntityByName("bcm2835-isp0-capture3"));
/* This is just for convenience so that we can easily iterate over all streams. */
for (auto &stream : data->unicam_)
@@ -1013,7 +858,7 @@ int PipelineHandlerRPi::prepareBuffers(Camera *camera)
*/
unsigned int maxBuffers = 0;
for (const Stream *s : camera->streams())
- if (static_cast<const RPiStream *>(s)->isExternal())
+ if (static_cast<const RPi::RPiStream *>(s)->isExternal())
maxBuffers = std::max(maxBuffers, s->configuration().bufferCount);
for (auto const stream : data->streams_) {
@@ -1257,12 +1102,12 @@ done:
void RPiCameraData::unicamBufferDequeue(FrameBuffer *buffer)
{
- const RPiStream *stream = nullptr;
+ const RPi::RPiStream *stream = nullptr;
if (state_ == State::Stopped)
return;
- for (RPiStream const &s : unicam_) {
+ for (RPi::RPiStream const &s : unicam_) {
if (s.findFrameBuffer(buffer)) {
stream = &s;
break;
@@ -1318,12 +1163,12 @@ void RPiCameraData::ispInputDequeue(FrameBuffer *buffer)
void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer)
{
- const RPiStream *stream = nullptr;
+ const RPi::RPiStream *stream = nullptr;
if (state_ == State::Stopped)
return;
- for (RPiStream const &s : isp_) {
+ for (RPi::RPiStream const &s : isp_) {
if (s.findFrameBuffer(buffer)) {
stream = &s;
break;
@@ -1404,7 +1249,7 @@ void RPiCameraData::clearIncompleteRequests()
}
}
-void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, const RPiStream *stream)
+void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, const RPi::RPiStream *stream)
{
if (stream->isExternal()) {
if (!dropFrame_) {
diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp
new file mode 100644
index 00000000..2e52bd5c
--- /dev/null
+++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2020, Raspberry Pi (Trading) Ltd.
+ *
+ * rpi_stream.cpp - Raspberry Pi device stream abstraction class.
+ */
+#include "rpi_stream.h"
+
+#include "libcamera/internal/log.h"
+
+namespace libcamera {
+
+LOG_DEFINE_CATEGORY(RPISTREAM)
+
+namespace RPi {
+
+V4L2VideoDevice *RPiStream::dev() const
+{
+ return dev_.get();
+}
+
+std::string RPiStream::name() const
+{
+ return name_;
+}
+
+void RPiStream::reset()
+{
+ external_ = false;
+ internalBuffers_.clear();
+}
+
+bool RPiStream::isImporter() const
+{
+ return importOnly_;
+}
+
+void RPiStream::setExternal(bool external)
+{
+ external_ = external;
+}
+
+bool RPiStream::isExternal() const
+{
+ /*
+ * Import streams cannot be external.
+ *
+ * RAW capture is a special case where we simply copy the RAW
+ * buffer out of the request. All other buffer handling happens
+ * as if the stream is internal.
+ */
+ return external_ && !importOnly_;
+}
+
+void RPiStream::setExternalBuffers(std::vector<std::unique_ptr<FrameBuffer>> *buffers)
+{
+ externalBuffers_ = buffers;
+}
+
+const std::vector<std::unique_ptr<FrameBuffer>> *RPiStream::getBuffers() const
+{
+ return external_ ? externalBuffers_ : &internalBuffers_;
+}
+
+bool RPiStream::findFrameBuffer(FrameBuffer *buffer) const
+{
+ auto start = external_ ? externalBuffers_->begin() : internalBuffers_.begin();
+ auto end = external_ ? externalBuffers_->end() : internalBuffers_.end();
+
+ if (importOnly_)
+ return false;
+
+ if (std::find_if(start, end,
+ [buffer](std::unique_ptr<FrameBuffer> const &ref) { return ref.get() == buffer; }) != end)
+ return true;
+
+ return false;
+}
+
+int RPiStream::importBuffers(unsigned int count)
+{
+ return dev_->importBuffers(count);
+}
+
+int RPiStream::allocateBuffers(unsigned int count)
+{
+ return dev_->allocateBuffers(count, &internalBuffers_);
+}
+
+int RPiStream::queueBuffers()
+{
+ if (external_)
+ return 0;
+
+ for (auto &b : internalBuffers_) {
+ int ret = dev_->queueBuffer(b.get());
+ if (ret) {
+ LOG(RPISTREAM, Error) << "Failed to queue buffers for "
+ << name_;
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+void RPiStream::releaseBuffers()
+{
+ dev_->releaseBuffers();
+ if (!external_ && !importOnly_)
+ internalBuffers_.clear();
+}
+
+} /* namespace RPi */
+
+} /* namespace libcamera */
diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.h b/src/libcamera/pipeline/raspberrypi/rpi_stream.h
new file mode 100644
index 00000000..8fcf522b
--- /dev/null
+++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.h
@@ -0,0 +1,107 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2020, Raspberry Pi (Trading) Ltd.
+ *
+ * rpi_stream.h - Raspberry Pi device stream abstraction class.
+ */
+#ifndef __LIBCAMERA_PIPELINE_RPI_STREAM_H__
+#define __LIBCAMERA_PIPELINE_RPI_STREAM_H__
+
+#include <queue>
+#include <string>
+#include <vector>
+
+#include <libcamera/stream.h>
+
+#include "libcamera/internal/v4l2_videodevice.h"
+
+namespace libcamera {
+
+namespace RPi {
+
+/*
+ * Device stream abstraction for either an internal or external stream.
+ * Used for both Unicam and the ISP.
+ */
+class RPiStream : public Stream
+{
+public:
+ RPiStream()
+ {
+ }
+
+ RPiStream(const char *name, MediaEntity *dev, bool importOnly = false)
+ : external_(false), importOnly_(importOnly), name_(name),
+ dev_(std::make_unique<V4L2VideoDevice>(dev))
+ {
+ }
+
+ V4L2VideoDevice *dev() const;
+ std::string name() const;
+ bool isImporter() const;
+ void reset();
+
+ void setExternal(bool external);
+ bool isExternal() const;
+
+ void setExternalBuffers(std::vector<std::unique_ptr<FrameBuffer>> *buffers);
+ const std::vector<std::unique_ptr<FrameBuffer>> *getBuffers() const;
+ bool findFrameBuffer(FrameBuffer *buffer) const;
+
+ int importBuffers(unsigned int count);
+ int allocateBuffers(unsigned int count);
+
+ int queueBuffers();
+ void releaseBuffers();
+
+private:
+ /*
+ * Indicates that this stream is active externally, i.e. the buffers
+ * are provided by the application.
+ */
+ bool external_;
+
+ /* Indicates that this stream only imports buffers, e.g. ISP input. */
+ bool importOnly_;
+
+ /* Stream name identifier. */
+ std::string name_;
+
+ /* The actual device stream. */
+ std::unique_ptr<V4L2VideoDevice> dev_;
+
+ /* Internally allocated framebuffers associated with this device stream. */
+ std::vector<std::unique_ptr<FrameBuffer>> internalBuffers_;
+
+ /* Externally allocated framebuffers associated with this device stream. */
+ std::vector<std::unique_ptr<FrameBuffer>> *externalBuffers_;
+};
+
+/*
+ * The following class is just a convenient (and typesafe) array of device
+ * streams indexed with an enum class.
+ */
+template<typename E, std::size_t N>
+class RPiDevice : public std::array<class RPiStream, N>
+{
+private:
+ constexpr auto index(E e) const noexcept
+ {
+ return static_cast<std::underlying_type_t<E>>(e);
+ }
+public:
+ RPiStream &operator[](E e)
+ {
+ return std::array<class RPiStream, N>::operator[](index(e));
+ }
+ const RPiStream &operator[](E e) const
+ {
+ return std::array<class RPiStream, N>::operator[](index(e));
+ }
+};
+
+} /* namespace RPi */
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_PIPELINE_RPI_STREAM_H__ */