From patchwork Wed Dec 17 15:38:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 25600 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 828A1BD7D8 for ; Wed, 17 Dec 2025 15:38:14 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 56AD761A65; Wed, 17 Dec 2025 16:38:13 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="lr94zIYY"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AF58E61A35 for ; Wed, 17 Dec 2025 16:38:12 +0100 (CET) Received: from pb-laptop.local (185.221.143.114.nat.pool.zt.hu [185.221.143.114]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0A59C581 for ; Wed, 17 Dec 2025 16:38:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1765985886; bh=wBfzfruHS7uomyPeixrft2ySl3U4dQ3uvqh9dRzwPwU=; h=From:To:Subject:Date:From; b=lr94zIYYwPEjTZ7xm6OdaqQ/tmZDXqWjXgAPhZEbmCuVFCXVxylNQrEJTYcLlHRl9 b5/cw1nYTKdDFs7838/03pklhKvrJ6BQx1rD/FxQ6gFamK4zga7u6nUDZopNRgZOJ1 +ASZgvOYlg2RJWNKFke8yCzXtb2S205O3BFJqyOM= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Subject: [PATCH v1] Documentation: guides: pipeline-handler: Refresh Date: Wed, 17 Dec 2025 16:38:08 +0100 Message-ID: <20251217153808.3447066-1-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.52.0 MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Update the guide to be compatible with the current version of libcamera, as well as sync the code snippets with [0]. Apart from libcamera related changes, `meson build` is replaced with `meson setup build`, and direct `ninja` calls are replaced with `meson compile -C build`. [0]: https://git.libcamera.org/libcamera/vivid.git Signed-off-by: Barnabás Pőcze Reviewed-by: Kieran Bingham --- Documentation/guides/pipeline-handler.rst | 68 +++++++++++------------ 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/Documentation/guides/pipeline-handler.rst b/Documentation/guides/pipeline-handler.rst index 85d9cc870..deca75376 100644 --- a/Documentation/guides/pipeline-handler.rst +++ b/Documentation/guides/pipeline-handler.rst @@ -170,7 +170,7 @@ a comma separated list with ``-Dpipelines`` when generating a build directory: .. code-block:: shell - meson build -Dpipelines=ipu3,uvcvideo,vivid + meson setup build -Dpipelines=ipu3,uvcvideo,vivid Read the `Meson build configuration`_ documentation for more information on configuring a build directory. @@ -201,12 +201,12 @@ stub implementations for the overridden class members. public: PipelineHandlerVivid(CameraManager *manager); - CameraConfiguration *generateConfiguration(Camera *camera, - Span roles) override; + std::unique_ptr + generateConfiguration(Camera *camera, Span roles) override; int configure(Camera *camera, CameraConfiguration *config) override; int exportFrameBuffers(Camera *camera, Stream *stream, - std::vector> *buffers) override; + std::vector> *buffers) override; int start(Camera *camera, const ControlList *controls) override; void stopDevice(Camera *camera) override; @@ -293,8 +293,7 @@ Run the following commands: .. code-block:: shell - meson build - ninja -C build + meson compile -C build To build the libcamera code base, and confirm that the build system found the new pipeline handler by running: @@ -307,7 +306,7 @@ And you should see output like the below: .. code-block:: shell - DEBUG Camera camera_manager.cpp:148 Found registered pipeline handler 'PipelineHandlerVivid' + DEBUG Camera camera_manager.cpp:143 Found registered pipeline handler 'vivid Matching devices ~~~~~~~~~~~~~~~~ @@ -352,7 +351,7 @@ Add the following below ``dm.add("vivid-000-vid-cap");``: .. code-block:: cpp - MediaDevice *media = acquireMediaDevice(enumerator, dm); + std::shared_ptr media = acquireMediaDevice(enumerator, dm); if (!media) return false; @@ -382,7 +381,7 @@ running .. code-block:: shell - ninja -C build + meson compile -C build LIBCAMERA_LOG_LEVELS=Pipeline,VIVID:0 ./build/src/cam/cam -l And you should see output like the below: @@ -423,21 +422,15 @@ it will be used: class VividCameraData : public Camera::Private { public: - VividCameraData(PipelineHandler *pipe, MediaDevice *media) - : Camera::Private(pipe), media_(media), video_(nullptr) + VividCameraData(PipelineHandler *pipe) + : Camera::Private(pipe) { } - ~VividCameraData() - { - delete video_; - } - - int init(); + int init(const MediaDevice *media); void bufferReady(FrameBuffer *buffer); - MediaDevice *media_; - V4L2VideoDevice *video_; + std::unique_ptr video_; Stream stream_; }; @@ -466,9 +459,9 @@ open a single capture device named 'vivid-000-vid-cap' by the device. .. code-block:: cpp - int VividCameraData::init() + int VividCameraData::init(const MediaDevice *media) { - video_ = new V4L2VideoDevice(media_->getEntityByName("vivid-000-vid-cap")); + video_ = std::make_unique(media->getEntityByName("vivid-000-vid-cap")); if (video_->open()) return -ENODEV; @@ -487,9 +480,9 @@ handler. .. code-block:: cpp - std::unique_ptr data = std::make_unique(this, media); + std::unique_ptr data = std::make_unique(this); - if (data->init()) + if (data->init(media.get())) return false; @@ -506,7 +499,8 @@ PipelineHandler successfully matched and constructed a device. .. code-block:: cpp std::set streams{ &data->stream_ }; - std::shared_ptr camera = Camera::create(std::move(data), data->video_->deviceName(), streams); + const char *id = data->video_->deviceName(); + std::shared_ptr camera = Camera::create(std::move(data), id, streams); registerCamera(std::move(camera)); return true; @@ -521,19 +515,20 @@ Our match function should now look like the following: DeviceMatch dm("vivid"); dm.add("vivid-000-vid-cap"); - MediaDevice *media = acquireMediaDevice(enumerator, dm); + std::shared_ptr media = acquireMediaDevice(enumerator, dm); if (!media) return false; - std::unique_ptr data = std::make_unique(this, media); + std::unique_ptr data = std::make_unique(this); /* Locate and open the capture video node. */ - if (data->init()) + if (data->init(media.get())) return false; /* Create and register the camera. */ std::set streams{ &data->stream_ }; - std::shared_ptr camera = Camera::create(std::move(data), data->video_->deviceName(), streams); + const char *id = data->video_->deviceName(); + std::shared_ptr camera = Camera::create(std::move(data), id, streams); registerCamera(std::move(camera)); return true; @@ -897,7 +892,7 @@ Add the following function implementation to your file: const std::vector &formats = cfg.formats().pixelformats(); if (std::find(formats.begin(), formats.end(), cfg.pixelFormat) == formats.end()) { cfg.pixelFormat = formats[0]; - LOG(VIVID, Debug) << "Adjusting format to " << cfg.pixelFormat.toString(); + LOG(VIVID, Debug) << "Adjusting format to " << cfg.pixelFormat; status = Adjusted; } @@ -912,7 +907,7 @@ codebase, and test: .. code-block:: shell - ninja -C build + meson compile -C build LIBCAMERA_LOG_LEVELS=Pipeline,VIVID:0 ./build/src/cam/cam -c vivid -I You should see the following output showing the capabilites of our new pipeline @@ -989,8 +984,9 @@ Add the following code beneath the code from above: .. code-block:: cpp + const V4L2PixelFormat fourcc = data->video_->toV4L2PixelFormat(cfg.pixelFormat); V4L2DeviceFormat format = {}; - format.fourcc = data->video_->toV4L2PixelFormat(cfg.pixelFormat); + format.fourcc = fourcc; format.size = cfg.size; Set the video device format defined above using the @@ -1007,8 +1003,7 @@ Continue the implementation with the following code: if (ret) return ret; - if (format.size != cfg.size || - format.fourcc != data->video_->toV4L2PixelFormat(cfg.pixelFormat)) + if (format.size != cfg.size || format.fourcc != fourcc) return -EINVAL; Finally, store and set stream-specific data reflecting the state of the stream. @@ -1262,8 +1257,7 @@ before being set. { ControlList controls(data->video_->controls()); - for (auto it : request->controls()) { - unsigned int id = it.first; + for (const auto &[id, v] : request->controls()) { unsigned int offset; uint32_t cid; @@ -1280,7 +1274,7 @@ before being set. continue; } - int32_t value = std::lround(it.second.get() * 128 + offset); + int32_t value = std::lround(v.get() * 128 + offset); controls.set(cid, std::clamp(value, 0, 255)); } @@ -1421,7 +1415,7 @@ capture through the pipeline through both of the cam and qcam utilities. .. code-block:: shell - ninja -C build + meson compile -C build ./build/src/cam/cam -c vivid -C5 To test that the pipeline handler can detect a device, and capture input.