Documentation: guides: pipeline-handler: Refresh

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`. And update the code block languages where
appropriate.

[0]: https://git.libcamera.org/libcamera/vivid.git

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
Barnabás Pőcze
2025-12-17 16:21:25 +01:00
parent 5e59969dbb
commit 993496ba35

View File

@@ -154,7 +154,7 @@ In the *meson.build* file, add the *vivid.cpp* file as a build source for
libcamera by adding it to the global meson ``libcamera_internal_sources``
variable:
.. code-block:: none
.. code-block:: meson
# SPDX-License-Identifier: CC0-1.0
@@ -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.
@@ -180,7 +180,7 @@ configuring a build directory.
To add the new pipeline handler to this list of options, add its directory name
to the libcamera build options in the top level ``meson_options.txt``.
.. code-block:: none
.. code-block:: meson
option('pipelines',
type : 'array',
@@ -201,12 +201,12 @@ stub implementations for the overridden class members.
public:
PipelineHandlerVivid(CameraManager *manager);
CameraConfiguration *generateConfiguration(Camera *camera,
Span<const StreamRole> roles) override;
std::unique_ptr<CameraConfiguration>
generateConfiguration(Camera *camera, Span<const StreamRole> roles) override;
int configure(Camera *camera, CameraConfiguration *config) override;
int exportFrameBuffers(Camera *camera, Stream *stream,
std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
int start(Camera *camera, const ControlList *controls) override;
void stopDevice(Camera *camera) override;
@@ -221,8 +221,9 @@ stub implementations for the overridden class members.
{
}
CameraConfiguration *PipelineHandlerVivid::generateConfiguration(Camera *camera,
Span<const StreamRole> roles)
std::unique_ptr<CameraConfiguration>
PipelineHandlerVivid::generateConfiguration(Camera *camera,
Span<const StreamRole> roles)
{
return nullptr;
}
@@ -293,8 +294,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:
@@ -305,9 +305,9 @@ new pipeline handler by running:
And you should see output like the below:
.. code-block:: shell
.. code-block:: text
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 +352,7 @@ Add the following below ``dm.add("vivid-000-vid-cap");``:
.. code-block:: cpp
MediaDevice *media = acquireMediaDevice(enumerator, dm);
std::shared_ptr<MediaDevice> media = acquireMediaDevice(enumerator, dm);
if (!media)
return false;
@@ -382,7 +382,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 +423,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<V4L2VideoDevice> video_;
Stream stream_;
};
@@ -466,9 +460,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<V4L2VideoDevice>(media->getEntityByName("vivid-000-vid-cap"));
if (video_->open())
return -ENODEV;
@@ -487,9 +481,9 @@ handler.
.. code-block:: cpp
std::unique_ptr<VividCameraData> data = std::make_unique<VividCameraData>(this, media);
std::unique_ptr<VividCameraData> data = std::make_unique<VividCameraData>(this);
if (data->init())
if (data->init(media.get()))
return false;
@@ -506,7 +500,8 @@ PipelineHandler successfully matched and constructed a device.
.. code-block:: cpp
std::set<Stream *> streams{ &data->stream_ };
std::shared_ptr<Camera> camera = Camera::create(std::move(data), data->video_->deviceName(), streams);
const char *id = data->video_->deviceName();
std::shared_ptr<Camera> camera = Camera::create(std::move(data), id, streams);
registerCamera(std::move(camera));
return true;
@@ -521,19 +516,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<MediaDevice> media = acquireMediaDevice(enumerator, dm);
if (!media)
return false;
std::unique_ptr<VividCameraData> data = std::make_unique<VividCameraData>(this, media);
std::unique_ptr<VividCameraData> data = std::make_unique<VividCameraData>(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<Stream *> streams{ &data->stream_ };
std::shared_ptr<Camera> camera = Camera::create(std::move(data), data->video_->deviceName(), streams);
const char *id = data->video_->deviceName();
std::shared_ptr<Camera> camera = Camera::create(std::move(data), id, streams);
registerCamera(std::move(camera));
return true;
@@ -897,7 +893,7 @@ Add the following function implementation to your file:
const std::vector<libcamera::PixelFormat> &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,13 +908,13 @@ 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
handler, and showing that our configurations have been generated:
.. code-block:: shell
.. code-block:: text
Using camera vivid
0: 1280x720-BGR888
@@ -989,8 +985,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 +1004,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.
@@ -1130,7 +1126,7 @@ prepares the video device accordingly.
Implement the pipeline handler ``start()`` function by replacing the stub
version with the following code:
.. code-block:: c++
.. code-block:: cpp
VividCameraData *data = cameraData(camera);
unsigned int count = data->stream_.configuration().bufferCount;
@@ -1262,8 +1258,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 +1275,7 @@ before being set.
continue;
}
int32_t value = std::lround(it.second.get<float>() * 128 + offset);
int32_t value = std::lround(v.get<float>() * 128 + offset);
controls.set(cid, std::clamp(value, 0, 255));
}
@@ -1421,7 +1416,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.
@@ -1430,7 +1425,7 @@ Running the command above outputs (a lot of) information about pixel formats,
and then starts capturing frame data, and should provide an output such as the
following:
.. code-block:: none
.. code-block:: text
user@dev:/home/libcamera$ ./build/src/cam/cam -c vivid -C5
[42:34:08.573066847] [186470] INFO IPAManager ipa_manager.cpp:136 libcamera is not installed. Adding '/home/libcamera/build/src/ipa' to the IPA search path