From patchwork Wed Jan 30 11:56:10 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: 447 Return-Path: Received: from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net [195.74.38.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 261B860DB9 for ; Wed, 30 Jan 2019 12:56:44 +0100 (CET) X-Halon-ID: 18e2fe71-2486-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from wyvern.c.hoisthospitality.com (unknown [217.64.245.162]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id 18e2fe71-2486-11e9-911a-0050569116f7; Wed, 30 Jan 2019 12:56:41 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Wed, 30 Jan 2019 12:56:10 +0100 Message-Id: <20190130115615.17362-2-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190130115615.17362-1-niklas.soderlund@ragnatech.se> References: <20190130115615.17362-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 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: Wed, 30 Jan 2019 11:56:44 -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 the Stream class is empty as capabilities are yet to be added. The class is still useful as it will be used to communicate how many streams a Camera object provides. Signed-off-by: Niklas Söderlund Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- include/libcamera/libcamera.h | 1 + include/libcamera/meson.build | 1 + include/libcamera/stream.h | 18 +++++++++++++ src/libcamera/meson.build | 1 + src/libcamera/stream.cpp | 51 +++++++++++++++++++++++++++++++++++ 5 files changed, 72 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 6619e556ebbd20e4..8167e8099ac061d2 100644 --- a/include/libcamera/libcamera.h +++ b/include/libcamera/libcamera.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #endif /* __LIBCAMERA_LIBCAMERA_H__ */ diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index 8fcbbf7892ea9280..8c14423bc444ef51 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -6,6 +6,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..4f47d85ed6382b36 --- /dev/null +++ b/include/libcamera/stream.h @@ -0,0 +1,18 @@ +/* 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 +{ +}; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_STREAM_H__ */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index b5b25965fd123350..a4e9cc8f936c47a7 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -11,6 +11,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..f82b05a2bcfa14e9 --- /dev/null +++ b/src/libcamera/stream.cpp @@ -0,0 +1,51 @@ +/* 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. Streams are exposed by the Camera object they + * belong to. + * + * 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. + */ + +} /* namespace libcamera */ From patchwork Wed Jan 30 11:56:11 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: 448 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 52E5C60DB9 for ; Wed, 30 Jan 2019 12:56:46 +0100 (CET) X-Halon-ID: 1bdfdf0c-2486-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from wyvern.c.hoisthospitality.com (unknown [217.64.245.162]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id 1bdfdf0c-2486-11e9-911a-0050569116f7; Wed, 30 Jan 2019 12:56:44 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Wed, 30 Jan 2019 12:56:11 +0100 Message-Id: <20190130115615.17362-3-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190130115615.17362-1-niklas.soderlund@ragnatech.se> References: <20190130115615.17362-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 2/6] libcamera: stream: add initial StreamConfiguration structure 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: Wed, 30 Jan 2019 11:56:46 -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 | 6 ++++++ src/libcamera/stream.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h index 4f47d85ed6382b36..4b24dd841dd64b64 100644 --- a/include/libcamera/stream.h +++ b/include/libcamera/stream.h @@ -13,6 +13,12 @@ class Stream final { }; +struct 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 f82b05a2bcfa14e9..4819cd94c1850efb 100644 --- a/src/libcamera/stream.cpp +++ b/src/libcamera/stream.cpp @@ -48,4 +48,30 @@ namespace libcamera { * optimal stream for the task. */ +/** + * \struct StreamConfiguration + * \brief Configuration parameters for a stream + * + * The StreamConfiguration structure models all information which can be + * configured for a single video stream. + */ + +/** + * \var StreamConfiguration::width + * \brief Stream width in pixels + */ + +/** + * \var StreamConfiguration::height + * \brief Stream height in pixels + */ + +/** + * \var StreamConfiguration::pixelFormat + * \brief Stream pixel format + * + * 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 Wed Jan 30 11:56:12 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: 449 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 7F6C860DB5 for ; Wed, 30 Jan 2019 12:56:51 +0100 (CET) X-Halon-ID: 1db5cf01-2486-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from wyvern.c.hoisthospitality.com (unknown [217.64.245.162]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id 1db5cf01-2486-11e9-911a-0050569116f7; Wed, 30 Jan 2019 12:56:49 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Wed, 30 Jan 2019 12:56:12 +0100 Message-Id: <20190130115615.17362-4-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190130115615.17362-1-niklas.soderlund@ragnatech.se> References: <20190130115615.17362-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 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: Wed, 30 Jan 2019 11:56:51 -0000 From: Laurent Pinchart Exclusive access must be obtained before performing operations that change the device state. Define an internal flag to track ownership and provide a means of protecting functions that change device configuration. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Niklas Söderlund Reviewed-by: Kieran Bingham --- 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 Wed Jan 30 11:56:13 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: 450 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 88D7060B2D for ; Wed, 30 Jan 2019 12:56:57 +0100 (CET) X-Halon-ID: 20d14117-2486-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from wyvern.c.hoisthospitality.com (unknown [217.64.245.162]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id 20d14117-2486-11e9-911a-0050569116f7; Wed, 30 Jan 2019 12:56:55 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Wed, 30 Jan 2019 12:56:13 +0100 Message-Id: <20190130115615.17362-5-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190130115615.17362-1-niklas.soderlund@ragnatech.se> References: <20190130115615.17362-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 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: Wed, 30 Jan 2019 11:56:57 -0000 A camera consists of one or more video streams originating from the same video source. The different streams could for example have access to different hardware blocks in the video pipeline and therefore be able to process the video source in different ways. All static information describing each stream need 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 will be extended in the future for some of the pipelines. Signed-off-by: Niklas Söderlund Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- include/libcamera/camera.h | 8 ++++++- src/libcamera/camera.cpp | 34 ++++++++++++++++++++++++---- src/libcamera/pipeline/ipu3/ipu3.cpp | 8 +++++-- src/libcamera/pipeline/uvcvideo.cpp | 5 +++- src/libcamera/pipeline/vimc.cpp | 5 +++- 5 files changed, 51 insertions(+), 9 deletions(-) diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h index 7e358f8c0aa093cf..01498935ae4aab58 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(); + const std::vector streams() const; + private: Camera(PipelineHandler *pipe, const std::string &name); ~Camera(); @@ -41,8 +45,10 @@ private: 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..986b74407aed6bd2 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 provides * * 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,12 @@ std::shared_ptr Camera::create(PipelineHandler *pipe, } }; - return std::allocate_shared(Allocator(), pipe, name); + std::shared_ptr camera = + std::allocate_shared(Allocator(), pipe, name); + + camera->streams_ = streams; + + return camera; } /** @@ -102,7 +110,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,7 +134,7 @@ void Camera::disconnect() { LOG(Camera, Debug) << "Disconnecting camera " << name_; - /** \todo Block API calls when they will be implemented. */ + disconnected_ = true; disconnected.emit(this); } @@ -164,4 +173,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 valid streams. + */ +const 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 80f4a7bffee52948..52844da78419943d 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" @@ -37,6 +38,7 @@ private: : dev_(nullptr) {} ~IPU3CameraData() { delete dev_; } V4L2Device *dev_; + Stream stream_; }; std::shared_ptr cio2_; @@ -202,15 +204,17 @@ void PipelineHandlerIPU3::registerCameras() if (link->setEnabled(true)) continue; + std::unique_ptr data = utils::make_unique(); + std::string cameraName = sensor->name() + " " + std::to_string(id); - std::shared_ptr camera = Camera::create(this, cameraName); + std::vector streams{ &data->stream_ }; + std::shared_ptr camera = Camera::create(this, cameraName, streams); /* * If V4L2 device creation fails, the Camera instance won't be * registered. The 'camera' shared pointer goes out of scope * and deletes the Camera it manages. */ - std::unique_ptr data = utils::make_unique(); data->dev_ = createVideoDevice(id); if (!data->dev_) { LOG(IPU3, Error) diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp index c51e8bc1f2c2bf25..8ea7ac74d2a5395d 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" @@ -25,6 +26,7 @@ public: private: std::shared_ptr media_; V4L2Device *video_; + Stream stream_; }; PipelineHandlerUVC::PipelineHandlerUVC(CameraManager *manager) @@ -64,7 +66,8 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator) return false; } - std::shared_ptr camera = Camera::create(this, media_->model()); + std::vector streams{ &stream_ }; + 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..9e1cf11a20c7a7e3 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" @@ -23,6 +24,7 @@ public: private: std::shared_ptr media_; + Stream stream_; }; PipeHandlerVimc::PipeHandlerVimc(CameraManager *manager) @@ -56,7 +58,8 @@ bool PipeHandlerVimc::match(DeviceEnumerator *enumerator) media_->acquire(); - std::shared_ptr camera = Camera::create(this, "Dummy VIMC Camera"); + std::vector streams{ &stream_ }; + std::shared_ptr camera = Camera::create(this, "Dummy VIMC Camera", streams); registerCamera(std::move(camera)); return true; From patchwork Wed Jan 30 11:56:14 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: 451 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 51DE560B2D for ; Wed, 30 Jan 2019 12:57:01 +0100 (CET) X-Halon-ID: 241ddefd-2486-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from wyvern.c.hoisthospitality.com (unknown [217.64.245.162]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id 241ddefd-2486-11e9-911a-0050569116f7; Wed, 30 Jan 2019 12:56:58 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Wed, 30 Jan 2019 12:56:14 +0100 Message-Id: <20190130115615.17362-6-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190130115615.17362-1-niklas.soderlund@ragnatech.se> References: <20190130115615.17362-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 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: Wed, 30 Jan 2019 11:57:01 -0000 All streams which are to be used for capture need to be configured at the same time. This allows the pipeline handler to take any dependencies between the different streams and their configuration into account when setting up the hardware. Extend the pipeline API and all pipeline implementations with two new functions, one to read a default configuration and one to set a new configuration. 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 return a null format and logs that a default configuration have been requested and log that a new configuration have been requested. Future work based on more components are needed to make the pipelines return a good default format and actually interact with the hardware. Signed-off-by: Niklas Söderlund --- src/libcamera/include/pipeline_handler.h | 7 +++++ src/libcamera/pipeline/ipu3/ipu3.cpp | 36 ++++++++++++++++++++++++ src/libcamera/pipeline/uvcvideo.cpp | 35 +++++++++++++++++++++++ src/libcamera/pipeline/vimc.cpp | 35 +++++++++++++++++++++++ src/libcamera/pipeline_handler.cpp | 34 ++++++++++++++++++++++ 5 files changed, 147 insertions(+) diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h index 080997e22e545e01..b4321f0fa0f765be 100644 --- a/src/libcamera/include/pipeline_handler.h +++ b/src/libcamera/include/pipeline_handler.h @@ -18,6 +18,8 @@ class Camera; class CameraManager; class DeviceEnumerator; class MediaDevice; +class Stream; +class StreamConfiguration; class CameraData { @@ -38,6 +40,11 @@ public: PipelineHandler(CameraManager *manager); virtual ~PipelineHandler(); + virtual std::map + streamConfiguration(Camera *camera, std::vector &streams) = 0; + virtual int configureStreams(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 52844da78419943d..39553b7c19823a52 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(Camera *camera, + std::vector &streams); + int configureStreams(Camera *camera, + std::map &config); + bool match(DeviceEnumerator *enumerator); private: @@ -68,6 +74,36 @@ PipelineHandlerIPU3::~PipelineHandlerIPU3() imgu_->release(); } +std::map +PipelineHandlerIPU3::streamConfiguration(Camera *camera, + std::vector &streams) +{ + IPU3CameraData *data = dynamic_cast(cameraData(camera)); + + std::map configs; + + StreamConfiguration config{}; + + LOG(IPU3, Info) << "TODO: Return a good default format"; + + configs[&data->stream_] = config; + + return configs; +} + +int PipelineHandlerIPU3::configureStreams(Camera *camera, + std::map &config) +{ + IPU3CameraData *data = dynamic_cast(cameraData(camera)); + + StreamConfiguration *cfg = &config[&data->stream_]; + + 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 8ea7ac74d2a5395d..4647ed95e929940a 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(Camera *camera, + std::vector &streams); + int configureStreams(Camera *camera, + std::map &config); + bool match(DeviceEnumerator *enumerator); private: @@ -43,6 +52,32 @@ PipelineHandlerUVC::~PipelineHandlerUVC() media_->release(); } +std::map +PipelineHandlerUVC::streamConfiguration(Camera *camera, + std::vector &streams) +{ + std::map configs; + + StreamConfiguration config{}; + + LOG(UVC, Info) << "TODO: Return a good default format"; + + configs[&stream_] = config; + + return configs; +} + +int PipelineHandlerUVC::configureStreams(Camera *camera, + std::map &config) +{ + StreamConfiguration *cfg = &config[&stream_]; + + 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 9e1cf11a20c7a7e3..835f8f512c4ac53a 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(Camera *camera, + std::vector &streams); + int configureStreams(Camera *camera, + std::map &config); + bool match(DeviceEnumerator *enumerator); private: @@ -38,6 +47,32 @@ PipeHandlerVimc::~PipeHandlerVimc() media_->release(); } +std::map +PipeHandlerVimc::streamConfiguration(Camera *camera, + std::vector &streams) +{ + std::map configs; + + StreamConfiguration config{}; + + LOG(VIMC, Info) << "TODO: Return a good default format"; + + configs[&stream_] = config; + + return configs; +} + +int PipeHandlerVimc::configureStreams(Camera *camera, + std::map &config) +{ + StreamConfiguration *cfg = &config[&stream_]; + + 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..3a560e10c442717f 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -75,6 +75,40 @@ PipelineHandler::~PipelineHandler() { }; + +/** + * \fn PipelineHandler::streamConfiguration() + * \brief Retrieve a group of stream configurations for a specified camera + * \param[in] camera The camera to fetch default configuration from + * \param[in] streams An array of streams to fetch information about + * + * Retrieve the species camera's default 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 streams and configuration + * returned can then be examined by the caller to learn about the defualt + * 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 streams and configurations or an + * empty map on error. + */ + +/** + * \fn PipelineHandler::configureStreams() + * \brief Configure a group of streams for capture + * \param[in] camera The camera to configure + * \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 Wed Jan 30 11:56:15 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: 452 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 4E45560B2D for ; Wed, 30 Jan 2019 12:57:05 +0100 (CET) X-Halon-ID: 26407874-2486-11e9-911a-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from wyvern.c.hoisthospitality.com (unknown [217.64.245.162]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id 26407874-2486-11e9-911a-0050569116f7; Wed, 30 Jan 2019 12:57:03 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Wed, 30 Jan 2019 12:56:15 +0100 Message-Id: <20190130115615.17362-7-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190130115615.17362-1-niklas.soderlund@ragnatech.se> References: <20190130115615.17362-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 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: Wed, 30 Jan 2019 11:57:05 -0000 Extend the camera to support reading and configuring 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 | 61 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h index 01498935ae4aab58..b21d116edc0f3a57 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(); const std::vector streams() const; + std::map streamConfiguration(std::vector &streams); + 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 986b74407aed6bd2..a293350f731e18df 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -190,4 +190,65 @@ const 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 specifies 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(std::vector &streams) +{ + if (disconnected_ || !streams.size()) + std::map{}; + + 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 specifies 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 caller's 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. + * \retval -ENODEV The camera is not connected to any hardware + * \retval -EACCES The user have not acquired exclusive access to the camera + * \retval -EINVAL The configuration is not valid + */ +int Camera::configureStreams(std::map &config) +{ + if (disconnected_) + return -ENODEV; + + if (!acquired_) + return -EACCES; + + if (!config.size()) + return -EINVAL; + + return pipe_->configureStreams(this, config); +} + } /* namespace libcamera */