From patchwork Fri Jan 25 15:33:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 380 X-Patchwork-Delegate: niklas.soderlund@ragnatech.se Return-Path: Received: from bin-mail-out-06.binero.net (bin-mail-out-06.binero.net [195.74.38.229]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B909E60B1B for ; Fri, 25 Jan 2019 16:33:52 +0100 (CET) X-Halon-ID: 9cda1972-20b6-11e9-874f-005056917f90 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-02.atm.binero.net (Halon) with ESMTPA id 9cda1972-20b6-11e9-874f-005056917f90; Fri, 25 Jan 2019 16:33:50 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Fri, 25 Jan 2019 16:33:34 +0100 Message-Id: <20190125153340.2744-2-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190125153340.2744-1-niklas.soderlund@ragnatech.se> References: <20190125153340.2744-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 1/7] libcamera: stream: add basic Stream class X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 25 Jan 2019 15:33:53 -0000 Add a extremely simple Stream implementation. The idea is that once capability support is added to the library each stream would describe it's capabilities using this class. A application would then select one or more streams based on these capabilities and using them to configure and capture. At this stage all the Stream class provides is a way for a Camera object to communicate which stream ID it to operates on. This basically limits the usefulness of the object to cameras which only provides one stream per camera. Signed-off-by: Niklas Söderlund --- include/libcamera/libcamera.h | 1 + include/libcamera/meson.build | 1 + include/libcamera/stream.h | 25 +++++++++++++ src/libcamera/meson.build | 1 + src/libcamera/stream.cpp | 66 +++++++++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+) create mode 100644 include/libcamera/stream.h create mode 100644 src/libcamera/stream.cpp diff --git a/include/libcamera/libcamera.h b/include/libcamera/libcamera.h index c0511cf6d662b63f..272dfd5e4a67d5de 100644 --- a/include/libcamera/libcamera.h +++ b/include/libcamera/libcamera.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #endif /* __LIBCAMERA_LIBCAMERA_H__ */ diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index d7cb55ba4a49e1e8..54a680787e5c17aa 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -5,6 +5,7 @@ libcamera_api = files([ 'event_notifier.h', 'libcamera.h', 'signal.h', + 'stream.h', 'timer.h', ]) diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h new file mode 100644 index 0000000000000000..415815ba12c65e47 --- /dev/null +++ b/include/libcamera/stream.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * stream.h - Stream object interface + */ +#ifndef __LIBCAMERA_STREAM_H__ +#define __LIBCAMERA_STREAM_H__ + +namespace libcamera { + +class Stream final +{ +public: + Stream(unsigned int id); + + unsigned int id() const { return id_; }; + +private: + unsigned int id_; +}; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_STREAM_H__ */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index f9f25c0ecf1564cc..9f6ff99eebe2f5bc 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -10,6 +10,7 @@ libcamera_sources = files([ 'media_object.cpp', 'pipeline_handler.cpp', 'signal.cpp', + 'stream.cpp', 'timer.cpp', 'v4l2_device.cpp', ]) diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp new file mode 100644 index 0000000000000000..3b44e834ee02b35a --- /dev/null +++ b/src/libcamera/stream.cpp @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * stream.cpp - Stream information handeling + */ + +#include + +/** + * \file stream.h + * \brief Stream information + * + * A camera device can provide frames in different resolutions and formats + * concurrently from a single image source. The Stream class represents + * one of the multiple concurrent streams format. + * + * All streams exposed by a camera device share the same image source and are + * thus not fully independent. Parameters related to the image source, such as + * the exposure time or flash control, are common to all streams. Other + * parameters, such as format or resolution, may be specified per-stream, + * depending on the capabilities of the camera device. + * + * Camera devices expose at least one stream, and may expose additional streams + * based on the device capabilities. This can be used, for instance, to + * implement concurrent viewfinder and video capture, or concurrent viewfinder, + * video capture and still image capture. + */ + +namespace libcamera { + +/** + * \class Stream + * \brief Stream information carrier + * + * The Stream class is a model of all static information which are associated + * with a single video stream. A application should acquire Stream objects from + * the camera. + * + * Some cameras are capable of supplying more then one stream from the same + * video source. In such cases a application will receive a array of streams to + * inspect and select from to best fit its use-case. + * + * \todo Add capabilities to the Stream API. Without this the Stream class + * only serves to reveal how many streams of unknown capabilities a camera + * supports. This in it self is productive as it allows applications to + * configure and capture from one or more streams even if it won't be able + * to select the optimal stream for the task. + */ + +/** + * \brief Create a new stream with a ID + * \param[in] id Numerical ID which should be unique for the camera device the stream belongs to + */ +Stream::Stream(unsigned int id) + : id_(id) +{ +} + +/** + * \fn Stream::id() + * \brief Retrieve the streams ID + * \return The stream ID + */ + +} /* namespace libcamera */ From patchwork Fri Jan 25 15:33:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 381 X-Patchwork-Delegate: niklas.soderlund@ragnatech.se Return-Path: Received: from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net [195.74.38.228]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C87C260C6A for ; Fri, 25 Jan 2019 16:33:52 +0100 (CET) X-Halon-ID: 9d3d18f7-20b6-11e9-874f-005056917f90 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-02.atm.binero.net (Halon) with ESMTPA id 9d3d18f7-20b6-11e9-874f-005056917f90; Fri, 25 Jan 2019 16:33:50 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Fri, 25 Jan 2019 16:33:35 +0100 Message-Id: <20190125153340.2744-3-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190125153340.2744-1-niklas.soderlund@ragnatech.se> References: <20190125153340.2744-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 2/7] libcamera: stream: add basic StreamConfiguration class X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 25 Jan 2019 15:33:53 -0000 Add a simple StreamConfiguration class to hold configuration data for a single stream of a Camera. In its current form not many configuration parameters are supported but it's expected the number of options will grow over time. At this stage the pixel format is represented as a unsigned int to allow for a easy mapping to the V4L2 API. This might be subject to change in the future as we finalize how libcamera shall represent pixelformats. A StreamConfiguration objected needs to be created from the Stream object it should configure. As the two objects are so closely related I have at this stage opted to implement them in the same stream.{h,cpp} as the Stream class. Signed-off-by: Niklas Söderlund --- include/libcamera/stream.h | 20 ++++++++++++ src/libcamera/stream.cpp | 64 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h index 415815ba12c65e47..8750797c36dd9b42 100644 --- a/include/libcamera/stream.h +++ b/include/libcamera/stream.h @@ -20,6 +20,26 @@ private: unsigned int id_; }; +class StreamConfiguration final +{ +public: + StreamConfiguration(class Stream &stream); + + unsigned int id() const { return id_; }; + unsigned int width() const { return width_; }; + unsigned int height() const { return height_; }; + unsigned int pixelformat() const { return pixelformat_; }; + + void setDimension(unsigned int width, unsigned int height); + void setPixelFormat(unsigned int pixelformat); + +private: + unsigned int id_; + unsigned int width_; + unsigned int height_; + unsigned int pixelformat_; +}; + } /* namespace libcamera */ #endif /* __LIBCAMERA_STREAM_H__ */ diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp index 3b44e834ee02b35a..e40756260c5768f3 100644 --- a/src/libcamera/stream.cpp +++ b/src/libcamera/stream.cpp @@ -63,4 +63,68 @@ Stream::Stream(unsigned int id) * \return The stream ID */ +/** + * \class StreamConfiguration + * \brief Stream configuration object + * + * The StreamConfiguration class is a model of all information which can be + * configured for a single video stream. A application should acquire a all + * Stream object from a camera, select the ones it wish to use, create a + * StreamConfiguration for each of those streams, set the desired parameter on + * the objects and feed them back to the camera object to configure the camera. + */ + +/** + * \fn StreamConfiguration::id() + * \brief Retrieve the streams ID + * \return The stream ID + */ + +/** + * \fn StreamConfiguration::width() + * \brief Retrieve the Stream width + * \return The stream width + */ + +/** + * \fn StreamConfiguration::height() + * \brief Retrieve the Stream height + * \return The stream height + */ + +/** + * \fn StreamConfiguration::pixelformat() + * \brief Retrieve the Stream pixelformat + * \return The stream pixelformat + */ + +/** + * \brief Set desired width and height for the stream + * \param[in] width The desired width of the stream + * \param[in] height The desired height of the stream + */ +void StreamConfiguration::setDimension(unsigned int width, unsigned int height) +{ + width_ = width; + height_ = height; +} + +/** + * \brief Set desired pixelformat for the stream + * \param[in] pixelformat The desired pixelformat of the stream + */ +void StreamConfiguration::setPixelFormat(unsigned int pixelformat) +{ + pixelformat_ = pixelformat; +} + +/** + * \brief Create a new configuration container for a stream + * \param[in] stream The stream object the configuration object should act on + */ +StreamConfiguration::StreamConfiguration(class Stream &stream) + : id_(stream.id()), width_(0), height_(0), pixelformat_(0) +{ +} + } /* namespace libcamera */ From patchwork Fri Jan 25 15:33:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 382 X-Patchwork-Delegate: niklas.soderlund@ragnatech.se Return-Path: Received: from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net [195.74.38.228]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 03D4F60C83 for ; Fri, 25 Jan 2019 16:33:52 +0100 (CET) X-Halon-ID: 9d929c62-20b6-11e9-874f-005056917f90 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-02.atm.binero.net (Halon) with ESMTPA id 9d929c62-20b6-11e9-874f-005056917f90; Fri, 25 Jan 2019 16:33:51 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Fri, 25 Jan 2019 16:33:36 +0100 Message-Id: <20190125153340.2744-4-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190125153340.2744-1-niklas.soderlund@ragnatech.se> References: <20190125153340.2744-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 3/7] libcamera: pipelines: add method to retrieve streams X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 25 Jan 2019 15:33:53 -0000 A Camera object needs to be able to inquire its responsible PipelineHandler for which streams it supports. Add and implement such an interface to the PipelineHandler base class and all pipeline handler implementations. Signed-off-by: Niklas Söderlund --- src/libcamera/include/pipeline_handler.h | 3 +++ src/libcamera/pipeline/ipu3/ipu3.cpp | 12 ++++++++++++ src/libcamera/pipeline/uvcvideo.cpp | 12 ++++++++++++ src/libcamera/pipeline/vimc.cpp | 12 ++++++++++++ src/libcamera/pipeline_handler.cpp | 12 ++++++++++++ 5 files changed, 51 insertions(+) diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h index 0db84217089e692a..f92cc5b5fa5e777b 100644 --- a/src/libcamera/include/pipeline_handler.h +++ b/src/libcamera/include/pipeline_handler.h @@ -17,6 +17,7 @@ namespace libcamera { class CameraManager; class DeviceEnumerator; class MediaDevice; +class Stream; class Camera; class CameraData @@ -38,6 +39,8 @@ public: PipelineHandler(CameraManager *manager); virtual ~PipelineHandler(); + virtual std::vector streams(const Camera *camera) const = 0; + virtual bool match(DeviceEnumerator *enumerator) = 0; protected: diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index d74655d037728feb..5c35c7a53b9347a3 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -9,6 +9,7 @@ #include #include +#include #include "device_enumerator.h" #include "log.h" @@ -27,6 +28,8 @@ public: PipelineHandlerIPU3(CameraManager *manager); ~PipelineHandlerIPU3(); + std::vector streams(const Camera *camera) const; + bool match(DeviceEnumerator *enumerator); private: @@ -60,6 +63,15 @@ PipelineHandlerIPU3::~PipelineHandlerIPU3() imgu_->release(); } +std::vector PipelineHandlerIPU3::streams(const Camera *camera) const +{ + std::vector streams; + + streams.push_back(Stream(0)); + + return streams; +} + bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator) { DeviceMatch cio2_dm("ipu3-cio2"); diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp index c51e8bc1f2c2bf25..e1f023245b8e63dd 100644 --- a/src/libcamera/pipeline/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo.cpp @@ -6,6 +6,7 @@ */ #include +#include #include "device_enumerator.h" #include "media_device.h" @@ -20,6 +21,8 @@ public: PipelineHandlerUVC(CameraManager *manager); ~PipelineHandlerUVC(); + std::vector streams(const Camera *camera) const; + bool match(DeviceEnumerator *enumerator); private: @@ -41,6 +44,15 @@ PipelineHandlerUVC::~PipelineHandlerUVC() media_->release(); } +std::vector PipelineHandlerUVC::streams(const Camera *camera) const +{ + std::vector streams; + + streams.push_back(Stream(0)); + + return streams; +} + bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator) { DeviceMatch dm("uvcvideo"); diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp index f58a97d51619515d..a96ec9f431361a32 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -6,6 +6,7 @@ */ #include +#include #include "device_enumerator.h" #include "media_device.h" @@ -19,6 +20,8 @@ public: PipeHandlerVimc(CameraManager *manager); ~PipeHandlerVimc(); + std::vector streams(const Camera *camera) const; + bool match(DeviceEnumerator *enumerator); private: @@ -36,6 +39,15 @@ PipeHandlerVimc::~PipeHandlerVimc() media_->release(); } +std::vector PipeHandlerVimc::streams(const Camera *camera) const +{ + std::vector streams; + + streams.push_back(Stream(0)); + + return streams; +} + bool PipeHandlerVimc::match(DeviceEnumerator *enumerator) { DeviceMatch dm("vimc"); diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index 4d5344988cfe8aa2..a825e7bf882d23c2 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -84,6 +84,18 @@ PipelineHandler::~PipelineHandler() cameraData_.clear(); }; +/** + * \fn PipelineHandler::streams(const Camera *camera) + * \brief Retrive a array of all streams the camera provides + * \param[in] camera The camera to retrieve streams from + * + * This function is the interface to extract information about streams from a + * PipelineHandler. + * + * \return A array of streams from the camera or a empty list if \a camera + * is not part of the PipelineHandler. + */ + /** * \fn PipelineHandler::match(DeviceEnumerator *enumerator) * \brief Match media devices and create camera instances From patchwork Fri Jan 25 15:33:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 383 X-Patchwork-Delegate: niklas.soderlund@ragnatech.se Return-Path: Received: from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net [195.74.38.228]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D60EF60B21 for ; Fri, 25 Jan 2019 16:33:53 +0100 (CET) X-Halon-ID: 9debc261-20b6-11e9-874f-005056917f90 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-02.atm.binero.net (Halon) with ESMTPA id 9debc261-20b6-11e9-874f-005056917f90; Fri, 25 Jan 2019 16:33:51 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Fri, 25 Jan 2019 16:33:37 +0100 Message-Id: <20190125153340.2744-5-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190125153340.2744-1-niklas.soderlund@ragnatech.se> References: <20190125153340.2744-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 4/7] libcamera: pipelines: add method to configure streams X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 25 Jan 2019 15:33:55 -0000 All the streams which are to be used needs to be configured at the same time, that is passed from the application to the pipeline handler in a single call. This would allow the pipeline handler to take any dependences between the different streams and there configuration into account when setting up the hardware. This implementation do not interact with any hardware, instead it extends all pipeline handlers with the argument validation needed to make sure the configuration request is sound. It then proceeds to print the requested frame dimensions to the log. Future work based on more components are needed to make the pipeline specific implementations truly useful. Signed-off-by: Niklas Söderlund --- src/libcamera/include/pipeline_handler.h | 3 +++ src/libcamera/pipeline/ipu3/ipu3.cpp | 21 +++++++++++++++++++++ src/libcamera/pipeline/uvcvideo.cpp | 24 ++++++++++++++++++++++++ src/libcamera/pipeline/vimc.cpp | 24 ++++++++++++++++++++++++ src/libcamera/pipeline_handler.cpp | 18 ++++++++++++++++++ 5 files changed, 90 insertions(+) diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h index f92cc5b5fa5e777b..5813e00aec068356 100644 --- a/src/libcamera/include/pipeline_handler.h +++ b/src/libcamera/include/pipeline_handler.h @@ -18,6 +18,7 @@ class CameraManager; class DeviceEnumerator; class MediaDevice; class Stream; +class StreamConfiguration; class Camera; class CameraData @@ -41,6 +42,8 @@ public: virtual std::vector streams(const Camera *camera) const = 0; + virtual int configure(const Camera *camera, std::vector &config) = 0; + virtual bool match(DeviceEnumerator *enumerator) = 0; protected: diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 5c35c7a53b9347a3..2d790f72dc63c31b 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -30,6 +30,8 @@ public: std::vector streams(const Camera *camera) const; + int configure(const Camera *camera, std::vector &config); + bool match(DeviceEnumerator *enumerator); private: @@ -72,6 +74,25 @@ std::vector PipelineHandlerIPU3::streams(const Camera *camera) const return streams; } +int PipelineHandlerIPU3::configure(const Camera *camera, + std::vector &config) +{ + StreamConfiguration *cfg; + + if (config.size() != 1) + return -EINVAL; + + cfg = config.front(); + + if (!cfg || cfg->id() != 0) + return -EINVAL; + + LOG(IPU3, Info) << "TODO: Configure the camera for resolution " << + cfg->width() << "x" << cfg->height(); + + return 0; +} + bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator) { DeviceMatch cio2_dm("ipu3-cio2"); diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp index e1f023245b8e63dd..477a9fe7f56d9a75 100644 --- a/src/libcamera/pipeline/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo.cpp @@ -9,12 +9,15 @@ #include #include "device_enumerator.h" +#include "log.h" #include "media_device.h" #include "pipeline_handler.h" #include "v4l2_device.h" namespace libcamera { +LOG_DEFINE_CATEGORY(UVC) + class PipelineHandlerUVC : public PipelineHandler { public: @@ -23,6 +26,8 @@ public: std::vector streams(const Camera *camera) const; + int configure(const Camera *camera, std::vector &config); + bool match(DeviceEnumerator *enumerator); private: @@ -53,6 +58,25 @@ std::vector PipelineHandlerUVC::streams(const Camera *camera) const return streams; } +int PipelineHandlerUVC::configure(const Camera *camera, + std::vector &config) +{ + StreamConfiguration *cfg; + + if (config.size() != 1) + return -EINVAL; + + cfg = config.front(); + + if (!cfg || cfg->id() != 0) + return -EINVAL; + + LOG(UVC, Info) << "TODO: Configure the camera for resolution " << + cfg->width() << "x" << cfg->height(); + + return 0; +} + bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator) { DeviceMatch dm("uvcvideo"); diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp index a96ec9f431361a32..f9d3b3a604805baa 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -9,11 +9,14 @@ #include #include "device_enumerator.h" +#include "log.h" #include "media_device.h" #include "pipeline_handler.h" namespace libcamera { +LOG_DEFINE_CATEGORY(VIMC) + class PipeHandlerVimc : public PipelineHandler { public: @@ -22,6 +25,8 @@ public: std::vector streams(const Camera *camera) const; + int configure(const Camera *camera, std::vector &config); + bool match(DeviceEnumerator *enumerator); private: @@ -48,6 +53,25 @@ std::vector PipeHandlerVimc::streams(const Camera *camera) const return streams; } +int PipeHandlerVimc::configure(const Camera *camera, + std::vector &config) +{ + StreamConfiguration *cfg; + + if (config.size() != 1) + return -EINVAL; + + cfg = config.front(); + + if (!cfg || cfg->id() != 0) + return -EINVAL; + + LOG(VIMC, Info) << "TODO: Configure the camera for resolution " << + cfg->width() << "x" << cfg->height(); + + return 0; +} + bool PipeHandlerVimc::match(DeviceEnumerator *enumerator) { DeviceMatch dm("vimc"); diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index a825e7bf882d23c2..dc3535f105e3a992 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -96,6 +96,24 @@ PipelineHandler::~PipelineHandler() * is not part of the PipelineHandler. */ +/** + * \fn PipelineHandler::configure(const Camera *camera, std::vector &config) + * \brief Configure a set of streams for a camera + * \param[in] camera The camera to configure streams for + * \param[in] config A array of stream configurations to try and setup + * + * This function is the interface to configure one or more streams of a camera + * for capture. The intended user for this interface is the Camera class which + * will receive the array of configurations to apply from the application. + * + * The caller needs to verify the StreamConfiguration objects in the passed + * array after the call as it might remove one or more to satisfy hardware + * limitations. The call might also alter any or all of the configuration + * parameters of any stream to fit within valid operational conditions. + * + * \return 0 on success or a negative error code on error. + */ + /** * \fn PipelineHandler::match(DeviceEnumerator *enumerator) * \brief Match media devices and create camera instances From patchwork Fri Jan 25 15:33:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 384 Return-Path: Received: from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net [195.74.38.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 55A8860C6A for ; Fri, 25 Jan 2019 16:33:54 +0100 (CET) X-Halon-ID: 9e4c4d8f-20b6-11e9-874f-005056917f90 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-02.atm.binero.net (Halon) with ESMTPA id 9e4c4d8f-20b6-11e9-874f-005056917f90; Fri, 25 Jan 2019 16:33:52 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Fri, 25 Jan 2019 16:33:38 +0100 Message-Id: <20190125153340.2744-6-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190125153340.2744-1-niklas.soderlund@ragnatech.se> References: <20190125153340.2744-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 5/7] libcamera: camera: Add acquire() and release() X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 25 Jan 2019 15:33:55 -0000 From: Laurent Pinchart Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Niklas Söderlund --- include/libcamera/camera.h | 5 +++++ src/libcamera/camera.cpp | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h index a2ded62de94814c4..7e358f8c0aa093cf 100644 --- a/include/libcamera/camera.h +++ b/include/libcamera/camera.h @@ -29,6 +29,9 @@ public: Signal disconnected; + int acquire(); + void release(); + private: Camera(PipelineHandler *pipe, const std::string &name); ~Camera(); @@ -38,6 +41,8 @@ private: std::shared_ptr pipe_; std::string name_; + + bool acquired_; }; } /* namespace libcamera */ diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index 9cec289282e4797b..fd19e8cf6694cc1b 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -102,7 +102,7 @@ const std::string &Camera::name() const */ Camera::Camera(PipelineHandler *pipe, const std::string &name) - : pipe_(pipe->shared_from_this()), name_(name) + : pipe_(pipe->shared_from_this()), name_(name), acquired_(false) { } @@ -127,4 +127,37 @@ void Camera::disconnect() disconnected.emit(this); } +/** + * \brief Acquire the camera device for exclusive access + * + * After opening the device with open(), exclusive access must be obtained + * before performing operations that change the device state. This function is + * not blocking, if the device has already been acquired (by the same or another + * process) the -EBUSY error code is returned. + * + * Once exclusive access isn't needed anymore, the device should be released + * with a call to the release() function. + * + * \return 0 on success or a negative error code on error. + */ +int Camera::acquire() +{ + if (acquired_) + return -EBUSY; + + acquired_ = true; + return 0; +} + +/** + * \brief Release exclusive access to the camera device + * + * Releasing the camera device allows other users to acquire exclusive access + * with the acquire() function. + */ +void Camera::release() +{ + acquired_ = false; +} + } /* namespace libcamera */ From patchwork Fri Jan 25 15:33:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 385 X-Patchwork-Delegate: niklas.soderlund@ragnatech.se Return-Path: Received: from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net [195.74.38.228]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C897E60C80 for ; Fri, 25 Jan 2019 16:33:54 +0100 (CET) X-Halon-ID: 9e9fa57f-20b6-11e9-874f-005056917f90 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-02.atm.binero.net (Halon) with ESMTPA id 9e9fa57f-20b6-11e9-874f-005056917f90; Fri, 25 Jan 2019 16:33:53 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Fri, 25 Jan 2019 16:33:39 +0100 Message-Id: <20190125153340.2744-7-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190125153340.2744-1-niklas.soderlund@ragnatech.se> References: <20190125153340.2744-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 6/7] libcamera: camera: integrate streams and configuration X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 25 Jan 2019 15:33:55 -0000 Add retrieval and configuration of streams information and configuration. The implementation in the Camera are minimalistic as the heavily lifting are done by the pipeline handler implementations. The single most important thing for the helpers in the Camera object is to perform access control and making sure no request is forwarded to a pipeline handler if the camera have been disconnected. Signed-off-by: Niklas Söderlund --- include/libcamera/camera.h | 7 ++++++ src/libcamera/camera.cpp | 48 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h index 7e358f8c0aa093cf..c6342ed81598921c 100644 --- a/include/libcamera/camera.h +++ b/include/libcamera/camera.h @@ -9,12 +9,15 @@ #include #include +#include #include namespace libcamera { class PipelineHandler; +class Stream; +class StreamConfiguration; class Camera final { @@ -32,6 +35,10 @@ public: int acquire(); void release(); + std::vector streams() const; + + int configure(std::vector &config); + private: Camera(PipelineHandler *pipe, const std::string &name); ~Camera(); diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index fd19e8cf6694cc1b..f90abfecd4e6bb48 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -6,6 +6,9 @@ */ #include +#include + +#include "pipeline_handler.h" #include "log.h" #include "pipeline_handler.h" @@ -160,4 +163,49 @@ void Camera::release() acquired_ = false; } +/** + * \brief Retrieve the supported streams of the camera + * + * \return An array of streams supported by the camera device + */ +std::vector Camera::streams() const +{ + std::vector streams; + + if (pipe_) + streams = pipe_->streams(this); + + return streams; +} + +/** + * \brief Configure the camera device prior to capture + * + * Prior to starting capture, the camera device must be configured to select a + * set of streams. + * + * The requested configuration \a config shall contain at least one stream and + * may contain multiple streams. For each stream an associated StreamFormat + * shall be supplied. Streams supported by the camera device not part of the + * \a config will be disabled. + * + * Exclusive access to the camera device shall be ensured by a call to + * Camera::acquire() before calling this function, otherwise an -EACCES error + * will be returned. + * + * \param[in] config Array of stream configurations to setup + * + * \return 0 on success or a negative error code on error. + */ +int Camera::configure(std::vector &config) +{ + if (!pipe_) + return -ENODEV; + + if (!acquired_) + return -EACCES; + + return pipe_->configure(this, config); +} + } /* namespace libcamera */ From patchwork Fri Jan 25 15:33:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 386 X-Patchwork-Delegate: niklas.soderlund@ragnatech.se Return-Path: Received: from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net [195.74.38.228]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 218CF60C9D for ; Fri, 25 Jan 2019 16:33:55 +0100 (CET) X-Halon-ID: 9ee6f09a-20b6-11e9-874f-005056917f90 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-02.atm.binero.net (Halon) with ESMTPA id 9ee6f09a-20b6-11e9-874f-005056917f90; Fri, 25 Jan 2019 16:33:53 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Fri, 25 Jan 2019 16:33:40 +0100 Message-Id: <20190125153340.2744-8-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190125153340.2744-1-niklas.soderlund@ragnatech.se> References: <20190125153340.2744-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 7/7] cam: add option to statically configure a pipeline X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 25 Jan 2019 15:33:56 -0000 Add a option to statically configure the first stream of a camera to a fixed resolution. This should obviously be improved in the future but for now serves as a good exercise for the Camera API towards an application. Signed-off-by: Niklas Söderlund --- src/cam/main.cpp | 62 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/src/cam/main.cpp b/src/cam/main.cpp index cb98d302dcf30331..b8c05d9079be3cb3 100644 --- a/src/cam/main.cpp +++ b/src/cam/main.cpp @@ -20,7 +20,8 @@ using namespace libcamera; OptionsParser::Options options; enum { - OptCamera = 'c', + OptCamera = 'C', + OptFormat = 'f', OptHelp = 'h', OptList = 'l', }; @@ -40,6 +41,7 @@ static int parseOptions(int argc, char *argv[]) parser.addOption(OptCamera, "Specify which camera to operate on", "camera", OptionsParser::ArgumentRequired, "camera"); + parser.addOption(OptFormat, "Configure the first stream to 640x480", "format"); parser.addOption(OptHelp, "Display this help message", "help"); parser.addOption(OptList, "List all cameras", "list"); @@ -64,6 +66,8 @@ int main(int argc, char **argv) return EXIT_FAILURE; CameraManager *cm = CameraManager::instance(); + std::shared_ptr camera; + std::vector streams; ret = cm->start(); if (ret) { @@ -72,31 +76,65 @@ int main(int argc, char **argv) return EXIT_FAILURE; } + loop = new EventLoop(cm->eventDispatcher()); + + struct sigaction sa = {}; + sa.sa_handler = &signalHandler; + sigaction(SIGINT, &sa, nullptr); + if (options.isSet(OptList)) { std::cout << "Available cameras:" << std::endl; - for (const std::shared_ptr &camera : cm->cameras()) - std::cout << "- " << camera->name() << std::endl; + for (const std::shared_ptr &cam : cm->cameras()) + std::cout << "- " << cam->name() << std::endl; } if (options.isSet(OptCamera)) { - std::shared_ptr cam = cm->get(options[OptCamera]); - - if (cam) { - std::cout << "Using camera " << cam->name() << std::endl; - } else { + camera = cm->get(options[OptCamera]); + if (!camera) { std::cout << "Camera " << options[OptCamera] << " not found" << std::endl; + goto out; + } + + streams = camera->streams(); + if (streams.size() != 1) { + std::cout << "Camera have " << streams.size() << + " streams, I only know how to work with 1" << std::endl; + goto out; + } + + if (camera->acquire()) { + std::cout << "Failed to acquire camera" << std::endl; + goto out; } + + std::cout << "Using camera " << camera->name() << std::endl; } - loop = new EventLoop(cm->eventDispatcher()); + if (options.isSet(OptFormat)) { + if (!camera) { + std::cout << "Can't configure stream, no camera selected" << std::endl; + goto out_camera; + } - struct sigaction sa = {}; - sa.sa_handler = &signalHandler; - sigaction(SIGINT, &sa, nullptr); + StreamConfiguration config = StreamConfiguration(streams.front()); + config.setDimension(640, 480); + + std::vector configs; + configs.push_back(&config); + + if (camera->configure(configs)) + std::cout << "Failed to configure camera" << std::endl; + } ret = loop->exec(); +out_camera: + if (camera) { + camera->release(); + camera.reset(); + } +out: delete loop; cm->stop();