From patchwork Sun Jan 27 00:22:03 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: 411 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 74D8760B2D for ; Sun, 27 Jan 2019 01:22:51 +0100 (CET) X-Halon-ID: adbd82c0-21c9-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 adbd82c0-21c9-11e9-874f-005056917f90; Sun, 27 Jan 2019 01:22:49 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sun, 27 Jan 2019 01:22:03 +0100 Message-Id: <20190127002208.18913-2-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190127002208.18913-1-niklas.soderlund@ragnatech.se> References: <20190127002208.18913-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 1/6] libcamera: stream: add initial 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: Sun, 27 Jan 2019 00:22:52 -0000 Add an initial Stream implementation. The idea is that once capability support is added to the library each stream will describe its capabilities using this class. An application will then select one or more streams based on these capabilities and use them to configure the camera and capture. At this stage all the Stream class provides is a way for a Camera object to communicate which streams it provides. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart --- include/libcamera/libcamera.h | 1 + include/libcamera/meson.build | 1 + include/libcamera/stream.h | 25 +++++++++++++ src/libcamera/meson.build | 1 + src/libcamera/stream.cpp | 67 +++++++++++++++++++++++++++++++++++ 5 files changed, 95 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..580f2cc8d3a3ad59 --- /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 - Video stream for a Camera + */ +#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..307de3710d0ac6b1 --- /dev/null +++ b/src/libcamera/stream.cpp @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * stream.cpp - Video stream for a Camera + */ + +#include + +/** + * \file stream.h + * \brief Video stream for a Camera + * + * 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. + * + * 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 Video stream for a camera + * + * The Stream class models of all static information which are associated + * with a single video stream. Stream are exposed by the Camera object they + * belong to. + * + * Some cameras are capable of supplying more then one stream from the same + * video source. In such cases an application can inspect all available streams + * and select the ones that 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 itself is productive as it allows applications to configure and + * capture from one or more streams even if they 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 Sun Jan 27 00:22:04 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: 410 Return-Path: Received: from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net [195.74.38.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 77C4260C7D for ; Sun, 27 Jan 2019 01:22:51 +0100 (CET) X-Halon-ID: ae178ff2-21c9-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 ae178ff2-21c9-11e9-874f-005056917f90; Sun, 27 Jan 2019 01:22:50 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sun, 27 Jan 2019 01:22:04 +0100 Message-Id: <20190127002208.18913-3-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190127002208.18913-1-niklas.soderlund@ragnatech.se> References: <20190127002208.18913-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 2/6] libcamera: stream: add initial 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: Sun, 27 Jan 2019 00:22:52 -0000 Add an initial StreamConfiguration implementation 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 an unsigned int to allow for easy mapping to the V4L2 API. This might be subject to change in the future as we finalize how libcamera shall represent pixel formats. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart --- include/libcamera/stream.h | 10 ++++++++++ src/libcamera/stream.cpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h index 580f2cc8d3a3ad59..e7597dd5a9492c2a 100644 --- a/include/libcamera/stream.h +++ b/include/libcamera/stream.h @@ -20,6 +20,16 @@ private: unsigned int id_; }; +class StreamConfiguration final +{ +public: + StreamConfiguration(); + + 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 307de3710d0ac6b1..530668a478a79c94 100644 --- a/src/libcamera/stream.cpp +++ b/src/libcamera/stream.cpp @@ -64,4 +64,35 @@ Stream::Stream(unsigned int id) * \return The stream ID */ +/** + * \class StreamConfiguration + * \brief Configuration parameters for a stream + * + * The StreamConfiguration class is a model of all information which can be + * configured for a single video stream. + */ + +StreamConfiguration::StreamConfiguration() + : width(0), height(0), pixelFormat(0) +{ +} + +/** + * \var StreamConfiguration::width + * \brief Stream width in pixels + */ + +/** + * \var StreamConfiguration::height + * \brief Stream height in pixels + */ + +/** + * \var StreamConfiguration::pixelFormat + * \brief Stream pixel format or type of compression + * + * This is a little endian four character code representation of the pixel + * format described in V4L2 using the V4L2_PIX_FMT_* definitions. + */ + } /* namespace libcamera */ From patchwork Sun Jan 27 00:22:05 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: 413 Return-Path: Received: from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net [195.74.38.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F24C460C9B for ; Sun, 27 Jan 2019 01:22:52 +0100 (CET) X-Halon-ID: ae60dcd5-21c9-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 ae60dcd5-21c9-11e9-874f-005056917f90; Sun, 27 Jan 2019 01:22:51 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sun, 27 Jan 2019 01:22:05 +0100 Message-Id: <20190127002208.18913-4-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190127002208.18913-1-niklas.soderlund@ragnatech.se> References: <20190127002208.18913-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 3/6] 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: Sun, 27 Jan 2019 00:22:54 -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 | 39 +++++++++++++++++++++++++++++++++++++- 2 files changed, 43 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..500976b237bcbd2d 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -102,12 +102,14 @@ 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) { } Camera::~Camera() { + if (acquired_) + LOG(Camera, Error) << "Removing camera while still in use"; } /** @@ -127,4 +129,39 @@ 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. + * + * \todo Implement exclusive access across processes. + * + * \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 Sun Jan 27 00:22:06 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: 415 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 F0EF960C7D for ; Sun, 27 Jan 2019 01:22:57 +0100 (CET) X-Halon-ID: af5040c7-21c9-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 af5040c7-21c9-11e9-874f-005056917f90; Sun, 27 Jan 2019 01:22:54 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sun, 27 Jan 2019 01:22:06 +0100 Message-Id: <20190127002208.18913-5-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190127002208.18913-1-niklas.soderlund@ragnatech.se> References: <20190127002208.18913-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 4/6] libcamera: camera: extend camera object to support 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: Sun, 27 Jan 2019 00:22:58 -0000 A camera consist of one or more video streams origination from the same video source. The different streams could for example have access to different hardware blocks in the video pipeline and therefor be able to process the video source in different ways. All static information describing each streams needs to be recorded at camera creation. After a camera is created an application can retrieve the static information about its stream at any time. Update all pipeline handlers to register one stream per camera, this might be extended in the future for some of the pipelines. Signed-off-by: Niklas Söderlund --- include/libcamera/camera.h | 10 ++++- src/libcamera/camera.cpp | 55 ++++++++++++++++++++++++++-- src/libcamera/pipeline/ipu3/ipu3.cpp | 4 +- src/libcamera/pipeline/uvcvideo.cpp | 4 +- src/libcamera/pipeline/vimc.cpp | 4 +- 5 files changed, 69 insertions(+), 8 deletions(-) diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h index 7e358f8c0aa093cf..786d4d7d66bed5b2 100644 --- a/include/libcamera/camera.h +++ b/include/libcamera/camera.h @@ -15,12 +15,14 @@ namespace libcamera { class PipelineHandler; +class Stream; class Camera final { public: static std::shared_ptr create(PipelineHandler *pipe, - const std::string &name); + const std::string &name, + const std::vector &streams); Camera(const Camera &) = delete; void operator=(const Camera &) = delete; @@ -32,6 +34,8 @@ public: int acquire(); void release(); + std::vector streams() const; + private: Camera(PipelineHandler *pipe, const std::string &name); ~Camera(); @@ -39,10 +43,14 @@ private: friend class PipelineHandler; void disconnect(); + bool haveStreamID(unsigned int id) const; + std::shared_ptr pipe_; std::string name_; + std::vector streams_; bool acquired_; + bool disconnected_; }; } /* namespace libcamera */ diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index 500976b237bcbd2d..3b2c00d0a4bb45d1 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -6,6 +6,7 @@ */ #include +#include #include "log.h" #include "pipeline_handler.h" @@ -56,13 +57,15 @@ LOG_DECLARE_CATEGORY(Camera) * \brief Create a camera instance * \param[in] name The name of the camera device * \param[in] pipe The pipeline handler responsible for the camera device + * \param[in] streams Array of streams the camera shall provide * * The caller is responsible for guaranteeing unicity of the camera name. * * \return A shared pointer to the newly created camera object */ std::shared_ptr Camera::create(PipelineHandler *pipe, - const std::string &name) + const std::string &name, + const std::vector &streams) { struct Allocator : std::allocator { void construct(void *p, PipelineHandler *pipe, @@ -76,7 +79,19 @@ std::shared_ptr Camera::create(PipelineHandler *pipe, } }; - return std::allocate_shared(Allocator(), pipe, name); + std::shared_ptr camera = + std::allocate_shared(Allocator(), pipe, name); + + for (const Stream &stream : streams) { + if (camera->haveStreamID(stream.id())) { + LOG(Camera, Error) << "Duplication of stream ID"; + camera.reset(); + break; + } + camera->streams_.push_back(stream); + } + + return camera; } /** @@ -102,7 +117,8 @@ const std::string &Camera::name() const */ Camera::Camera(PipelineHandler *pipe, const std::string &name) - : pipe_(pipe->shared_from_this()), name_(name), acquired_(false) + : pipe_(pipe->shared_from_this()), name_(name), acquired_(false), + disconnected_(false) { } @@ -125,10 +141,24 @@ void Camera::disconnect() { LOG(Camera, Debug) << "Disconnecting camera " << name_; - /** \todo Block API calls when they will be implemented. */ + disconnected_ = true; disconnected.emit(this); } +/** + * \brief Check if camera have a stream ID + * \param[in] id Stream ID to check for + * \return ture if stream ID exists, else false + */ +bool Camera::haveStreamID(unsigned int id) const +{ + for (const Stream &stream : streams_) + if (stream.id() == id) + return true; + + return false; +} + /** * \brief Acquire the camera device for exclusive access * @@ -164,4 +194,21 @@ void Camera::release() acquired_ = false; } +/** + * \brief Retrieve all the camera's stream information + * + * Retrieve all of the camera's static stream information. The static + * information describes among other things how many streams the camera support + * and each streams capabilities. + * + * \return An array of all the camera's streams or an empty list on error. + */ +std::vector Camera::streams() const +{ + if (disconnected_) + return std::vector{}; + + return streams_; +} + } /* namespace libcamera */ diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index d74655d037728feb..dbb2a89163c36cbc 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" @@ -197,7 +198,8 @@ void PipelineHandlerIPU3::registerCameras() continue; std::string cameraName = sensor->name() + " " + std::to_string(id); - std::shared_ptr camera = Camera::create(this, cameraName); + std::vector streams{ Stream(0) }; + std::shared_ptr camera = Camera::create(this, cameraName, streams); /* * If V4L2 device creation fails, the Camera instance won't be diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp index c51e8bc1f2c2bf25..bc4a8d7236be589d 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" @@ -64,7 +65,8 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator) return false; } - std::shared_ptr camera = Camera::create(this, media_->model()); + std::vector streams{ Stream(0) }; + std::shared_ptr camera = Camera::create(this, media_->model(), streams); registerCamera(std::move(camera)); hotplugMediaDevice(media_.get()); diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp index f58a97d51619515d..c426a953aea1b3dd 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" @@ -56,7 +57,8 @@ bool PipeHandlerVimc::match(DeviceEnumerator *enumerator) media_->acquire(); - std::shared_ptr camera = Camera::create(this, "Dummy VIMC Camera"); + std::vector streams{ Stream(0) }; + std::shared_ptr camera = Camera::create(this, "Dummy VIMC Camera", streams); registerCamera(std::move(camera)); return true; From patchwork Sun Jan 27 00:22:07 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: 414 Return-Path: Received: from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net [195.74.38.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F1CDE60C7F for ; Sun, 27 Jan 2019 01:22:57 +0100 (CET) X-Halon-ID: b1e6aa96-21c9-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 b1e6aa96-21c9-11e9-874f-005056917f90; Sun, 27 Jan 2019 01:22:56 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sun, 27 Jan 2019 01:22:07 +0100 Message-Id: <20190127002208.18913-6-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190127002208.18913-1-niklas.soderlund@ragnatech.se> References: <20190127002208.18913-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 5/6] libcamera: pipeline: extend pipelines to support stream 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: Sun, 27 Jan 2019 00:22:58 -0000 All streams which are to be used for capture needs to be configured at the same time. This allows the pipeline handler to take any dependences between the different streams and there configuration into account when setting up the hardware. Extend the pipeline API and all pipeline implementations with two new functions, one to read the configuration and one to update it. Both functions operate on a group of streams which the pipeline handler should consider when performing the operations. In the current implemented pipelines this is rather easy as they only have one stream each per camera. Furthermore as there is yet no way for the pipeline handlers to interact with the hardware all they do is log that the format have been read or updated. Future work based on more components are needed to make the pipelines actually interact with the hardware. Signed-off-by: Niklas Söderlund --- src/libcamera/include/pipeline_handler.h | 8 ++++++ src/libcamera/pipeline/ipu3/ipu3.cpp | 32 ++++++++++++++++++++++ src/libcamera/pipeline/uvcvideo.cpp | 35 ++++++++++++++++++++++++ src/libcamera/pipeline/vimc.cpp | 35 ++++++++++++++++++++++++ src/libcamera/pipeline_handler.cpp | 34 +++++++++++++++++++++++ 5 files changed, 144 insertions(+) diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h index ca77a40b96e69b66..c19eb9b73ede8720 100644 --- a/src/libcamera/include/pipeline_handler.h +++ b/src/libcamera/include/pipeline_handler.h @@ -17,6 +17,8 @@ namespace libcamera { class CameraManager; class DeviceEnumerator; class MediaDevice; +class Stream; +class StreamConfiguration; class Camera; class CameraData @@ -38,6 +40,12 @@ public: PipelineHandler(CameraManager *manager); virtual ~PipelineHandler(); + virtual std::map + streamConfiguration(const Camera *camera, + const std::vector &streams) const = 0; + virtual int configureStreams(const Camera *camera, + std::map &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 dbb2a89163c36cbc..ff4d73f947a683ca 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -28,6 +28,12 @@ public: PipelineHandlerIPU3(CameraManager *manager); ~PipelineHandlerIPU3(); + std::map + streamConfiguration(const Camera *camera, + const std::vector &streams) const; + int configureStreams(const Camera *camera, + std::map &config); + bool match(DeviceEnumerator *enumerator); private: @@ -61,6 +67,32 @@ PipelineHandlerIPU3::~PipelineHandlerIPU3() imgu_->release(); } +std::map +PipelineHandlerIPU3::streamConfiguration(const Camera *camera, + const std::vector &streams) const +{ + std::map configs; + + StreamConfiguration config; + + LOG(IPU3, Info) << "TODO: Fetch stream configuration"; + + configs[0] = config; + + return configs; +} + +int PipelineHandlerIPU3::configureStreams(const Camera *camera, + std::map &config) +{ + StreamConfiguration *cfg = &config[0]; + + 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 bc4a8d7236be589d..bba4655a0a26b622 100644 --- a/src/libcamera/pipeline/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo.cpp @@ -9,18 +9,27 @@ #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: PipelineHandlerUVC(CameraManager *manager); ~PipelineHandlerUVC(); + std::map + streamConfiguration(const Camera *camera, + const std::vector &streams) const; + int configureStreams(const Camera *camera, + std::map &config); + bool match(DeviceEnumerator *enumerator); private: @@ -42,6 +51,32 @@ PipelineHandlerUVC::~PipelineHandlerUVC() media_->release(); } +std::map +PipelineHandlerUVC::streamConfiguration(const Camera *camera, + const std::vector &streams) const +{ + std::map configs; + + StreamConfiguration config; + + LOG(UVC, Info) << "TODO: Fetch stream configuration"; + + configs[0] = config; + + return configs; +} + +int PipelineHandlerUVC::configureStreams(const Camera *camera, + std::map &config) +{ + StreamConfiguration *cfg = &config[0]; + + 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 c426a953aea1b3dd..c9810a8e192ac68b 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -9,17 +9,26 @@ #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: PipeHandlerVimc(CameraManager *manager); ~PipeHandlerVimc(); + std::map + streamConfiguration(const Camera *camera, + const std::vector &streams) const; + int configureStreams(const Camera *camera, + std::map &config); + bool match(DeviceEnumerator *enumerator); private: @@ -37,6 +46,32 @@ PipeHandlerVimc::~PipeHandlerVimc() media_->release(); } +std::map +PipeHandlerVimc::streamConfiguration(const Camera *camera, + const std::vector &streams) const +{ + std::map configs; + + StreamConfiguration config; + + LOG(VIMC, Info) << "TODO: Fetch stream configuration"; + + configs[0] = config; + + return configs; +} + +int PipeHandlerVimc::configureStreams(const Camera *camera, + std::map &config) +{ + StreamConfiguration *cfg = &config[0]; + + 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 1c8640799f714686..ee6d80908f67d564 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -75,6 +75,40 @@ PipelineHandler::~PipelineHandler() { }; + +/** + * \fn PipelineHandler::streamConfiguration(const Camera *camera, * const std::vector &streams) + * \brief Retrieve a group of stream configurations for a specified camera + * \param[in] camera The camera to fetch the configuration from + * \param[in] streams An array of streams to fetch information about + * + * Retrieve the species camera's configuration for a specified group of streams. + * The caller shall populate the \a streams array with the streams it wish to + * fetch the configuration from. The map of stream IDs and configuration + * returned can then be examined by the caller to learn about the parameters for + * the specified streams. + * + * The intended companion to this is \a configureStreams() which can be used to + * change the group of streams parameters. + * + * \return A map of successfully retrieved stream IDs and configurations or an + * empty map on error. + */ + +/** + * \fn PipelineHandler::configureStreams(const Camera *camera, std::map &config) + * \brief Configure a group of streams for capture + * \param[in] camera The camera to apply the configuration to + * \param[in] config A map of stream configurations to apply + * + * Configure the specified group of streams for \a camera according to the + * configuration specified in \a configs. The intended caller of this interface + * is the Camera class which will receive configuration to apply from the + * application. + * + * \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 Sun Jan 27 00:22:08 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: 416 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 E58CE60C7F for ; Sun, 27 Jan 2019 01:22:58 +0100 (CET) X-Halon-ID: b265071f-21c9-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 b265071f-21c9-11e9-874f-005056917f90; Sun, 27 Jan 2019 01:22:58 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sun, 27 Jan 2019 01:22:08 +0100 Message-Id: <20190127002208.18913-7-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190127002208.18913-1-niklas.soderlund@ragnatech.se> References: <20190127002208.18913-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 6/6] libcamera: camera: extend camera object to support configuration of 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: Sun, 27 Jan 2019 00:22:59 -0000 Extend the camera to support reading and configuring of formats for groups of streams. The implementation in the Camera are minimalistic as the heavy lifting are done by the pipeline handler implementations. The most important functionality the camera provides in this context is validation of data structures passed to it from the application and access control to the pipeline handler. Signed-off-by: Niklas Söderlund --- include/libcamera/camera.h | 4 +++ src/libcamera/camera.cpp | 68 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h index 786d4d7d66bed5b2..798fee2487940208 100644 --- a/include/libcamera/camera.h +++ b/include/libcamera/camera.h @@ -7,6 +7,7 @@ #ifndef __LIBCAMERA_CAMERA_H__ #define __LIBCAMERA_CAMERA_H__ +#include #include #include @@ -16,6 +17,7 @@ namespace libcamera { class PipelineHandler; class Stream; +class StreamConfiguration; class Camera final { @@ -35,6 +37,8 @@ public: void release(); std::vector streams() const; + std::map streamConfiguration(const std::vector &streams) const; + int configureStreams(std::map &config); private: Camera(PipelineHandler *pipe, const std::string &name); diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index 3b2c00d0a4bb45d1..e41143972b0b537a 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -211,4 +211,72 @@ std::vector Camera::streams() const return streams_; } +/** + * \brief Retrieve a group of stream configurations + * \param[in] streams A map of stream IDs and configurations to setup + * + * Retrieve the camera's configuration for a specified group of streams. The + * caller can specify which of the camera's streams to retrieve configuration + * from by populating \a streams. + * + * The easiest way to populate the array of streams to fetch configuration from + * is to first retrieve the camera's full array of stream by with streams() and + * then potentially trim it down to only contain the streams the caller + * are interested in. + * + * \return A map of successfully retrieved stream IDs and configurations or an + * empty list on error. + */ +std::map +Camera::streamConfiguration(const std::vector &streams) const +{ + std::map config; + + if (disconnected_ || !streams.size()) + return config; + + for (const Stream &stream : streams) + if (!haveStreamID(stream.id())) + return config; + + return pipe_->streamConfiguration(this, streams); +} + +/** + * \brief Configure the camera's streams prior to capture + * \param[in] config A map of stream IDs and configurations to setup + * + * Prior to starting capture, the camera must be configured to select a + * group of streams to be involved in the capture and their configuration. + * The caller specify which streams are to be involved and their configuration + * by populating \a config. + * + * The easiest way to populate the array of config is to fetch an initial + * configuration from the camera with streamConfiguration() and then change the + * parameters to fit the callers need and once all the streams parameters are + * configured hand that over to configureStreams() to actually setup the camera. + * + * Exclusive access to the camera shall be ensured by a call to acquire() prior + * to calling this function, otherwise an -EACCES error is be returned. + * + * \return 0 on success or a negative error code on error. + */ +int Camera::configureStreams(std::map &config) +{ + if (disconnected_) + return -ENODEV; + + if (!acquired_) + return -EACCES; + + if (!config.size()) + return -EINVAL; + + for (const auto &pair : config) + if (!haveStreamID(pair.first)) + return -EINVAL; + + return pipe_->configureStreams(this, config); +} + } /* namespace libcamera */