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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user