Skip to content

Commit d5f15e5

Browse files
committed
Merge branch 'master' into next
2 parents 16e852d + 290d3f8 commit d5f15e5

File tree

89 files changed

+1537
-365
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+1537
-365
lines changed

Documentation/Doxyfile-common.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ GENERATE_LATEX = NO
5757
MACRO_EXPANSION = YES
5858
EXPAND_ONLY_PREDEF = YES
5959

60-
INCLUDE_PATH = "@TOP_SRCDIR@/include/libcamera"
60+
INCLUDE_PATH = "@TOP_BUILDDIR@/include" \
61+
"@TOP_SRCDIR@/include"
6162
INCLUDE_FILE_PATTERNS = *.h
6263

6364
IMAGE_PATH = "@TOP_SRCDIR@/Documentation/images"

Documentation/guides/application-developer.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@ accordingly. In this example, the application file has been named
618618
619619
simple_cam = executable('simple-cam',
620620
'simple-cam.cpp',
621-
dependencies: dependency('libcamera', required : true))
621+
dependencies: dependency('libcamera'))
622622
623623
The ``dependencies`` line instructs meson to ask ``pkgconfig`` (or ``cmake``) to
624624
locate the ``libcamera`` library, which the test application will be

Documentation/guides/pipeline-handler.rst

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ implementations for the overridden class members.
213213
std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
214214
215215
int start(Camera *camera, const ControlList *controls) override;
216-
void stop(Camera *camera) override;
216+
void stopDevice(Camera *camera) override;
217217
218218
int queueRequestDevice(Camera *camera, Request *request) override;
219219
@@ -247,7 +247,7 @@ implementations for the overridden class members.
247247
return -1;
248248
}
249249
250-
void PipelineHandlerVivid::stop(Camera *camera)
250+
void PipelineHandlerVivid::stopDevice(Camera *camera)
251251
{
252252
}
253253
@@ -521,14 +521,14 @@ handler and camera manager using `registerCamera`_.
521521
Finally with a successful construction, we return 'true' indicating that the
522522
PipelineHandler successfully matched and constructed a device.
523523

524-
.. _Camera::create: https://libcamera.org/api-html/classlibcamera_1_1Camera.html#a453740e0d2a2f495048ae307a85a2574
524+
.. _Camera::create: https://libcamera.org/internal-api-html/classlibcamera_1_1Camera.html#adf5e6c22411f953bfaa1ae21155d6c31
525525
.. _registerCamera: https://libcamera.org/api-html/classlibcamera_1_1PipelineHandler.html#adf02a7f1bbd87aca73c0e8d8e0e6c98b
526526

527527
.. code-block:: cpp
528528
529529
std::set<Stream *> streams{ &data->stream_ };
530-
std::shared_ptr<Camera> camera = Camera::create(this, data->video_->deviceName(), streams);
531-
registerCamera(std::move(camera), std::move(data));
530+
std::shared_ptr<Camera> camera = Camera::create(std::move(data), data->video_->deviceName(), streams);
531+
registerCamera(std::move(camera));
532532
533533
return true;
534534
@@ -554,8 +554,7 @@ Our match function should now look like the following:
554554
555555
/* Create and register the camera. */
556556
std::set<Stream *> streams{ &data->stream_ };
557-
const std::string &id = data->video_->deviceName();
558-
std::shared_ptr<Camera> camera = Camera::create(data.release(), id, streams);
557+
std::shared_ptr<Camera> camera = Camera::create(std::move(data), data->video_->deviceName(), streams);
559558
registerCamera(std::move(camera));
560559
561560
return true;
@@ -593,11 +592,11 @@ immutable properties of the ``Camera`` device.
593592
The libcamera controls and properties are defined in YAML form which is
594593
processed to automatically generate documentation and interfaces. Controls are
595594
defined by the src/libcamera/`control_ids_core.yaml`_ file and camera properties
596-
are defined by src/libcamera/`properties_ids_core.yaml`_.
595+
are defined by src/libcamera/`property_ids_core.yaml`_.
597596

598597
.. _controls framework: https://libcamera.org/api-html/controls_8h.html
599598
.. _control_ids_core.yaml: https://libcamera.org/api-html/control__ids_8h.html
600-
.. _properties_ids_core.yaml: https://libcamera.org/api-html/property__ids_8h.html
599+
.. _property_ids_core.yaml: https://libcamera.org/api-html/property__ids_8h.html
601600

602601
Pipeline handlers can optionally register the list of controls an application
603602
can set as well as a list of immutable camera properties. Being both
@@ -800,8 +799,7 @@ derived class, and assign it to a base class pointer.
800799

801800
.. code-block:: cpp
802801
803-
VividCameraData *data = cameraData(camera);
804-
CameraConfiguration *config = new VividCameraConfiguration();
802+
auto config = std::make_unique<VividCameraConfiguration>();
805803
806804
A ``CameraConfiguration`` is specific to each pipeline, so you can only create
807805
it from the pipeline handler code path. Applications can also generate an empty
@@ -829,9 +827,7 @@ To generate a ``StreamConfiguration``, you need a list of pixel formats and
829827
frame sizes which are supported as outputs of the stream. You can fetch a map of
830828
the ``V4LPixelFormat`` and ``SizeRange`` supported by the underlying output
831829
device, but the pipeline handler needs to convert this to a
832-
``libcamera::PixelFormat`` type to pass to applications. We do this here using
833-
``std::transform`` to convert the formats and populate a new ``PixelFormat`` map
834-
as shown below.
830+
``libcamera::PixelFormat`` type to pass to applications.
835831

836832
Continue adding the following code example to our ``generateConfiguration``
837833
implementation.
@@ -841,14 +837,12 @@ implementation.
841837
std::map<V4L2PixelFormat, std::vector<SizeRange>> v4l2Formats =
842838
data->video_->formats();
843839
std::map<PixelFormat, std::vector<SizeRange>> deviceFormats;
844-
std::transform(v4l2Formats.begin(), v4l2Formats.end(),
845-
std::inserter(deviceFormats, deviceFormats.begin()),
846-
[&](const decltype(v4l2Formats)::value_type &format) {
847-
return decltype(deviceFormats)::value_type{
848-
format.first.toPixelFormat(),
849-
format.second
850-
};
851-
});
840+
841+
for (auto &[v4l2PixelFormat, sizes] : v4l2Formats) {
842+
PixelFormat pixelFormat = v4l2PixelFormat.toPixelFormat();
843+
if (pixelFormat.isValid())
844+
deviceFormats.try_emplace(pixelFormat, std::move(sizes));
845+
}
852846
853847
The `StreamFormats`_ class holds information about the pixel formats and frame
854848
sizes that a stream can support. The class groups size information by the pixel
@@ -938,9 +932,9 @@ Add the following function implementation to your file:
938932
939933
StreamConfiguration &cfg = config_[0];
940934
941-
const std::vector<libcamera::PixelFormat> formats = cfg.formats().pixelformats();
935+
const std::vector<libcamera::PixelFormat> &formats = cfg.formats().pixelformats();
942936
if (std::find(formats.begin(), formats.end(), cfg.pixelFormat) == formats.end()) {
943-
cfg.pixelFormat = cfg.formats().pixelformats()[0];
937+
cfg.pixelFormat = formats[0];
944938
LOG(VIVID, Debug) << "Adjusting format to " << cfg.pixelFormat.toString();
945939
status = Adjusted;
946940
}
@@ -1158,7 +1152,7 @@ available to the devices which have to be started and ready to produce
11581152
images. At the end of a capture session the ``Camera`` device needs to be
11591153
stopped, to gracefully clean up any allocated memory and stop the hardware
11601154
devices. Pipeline handlers implement two functions for these purposes, the
1161-
``start()`` and ``stop()`` functions.
1155+
``start()`` and ``stopDevice()`` functions.
11621156

11631157
The memory initialization phase that happens at ``start()`` time serves to
11641158
configure video devices to be able to use memory buffers exported as dma-buf
@@ -1261,8 +1255,8 @@ algorithms, or other devices you should also stop them.
12611255
.. _releaseBuffers: https://libcamera.org/api-html/classlibcamera_1_1V4L2VideoDevice.html#a191619c152f764e03bc461611f3fcd35
12621256

12631257
Of course we also need to handle the corresponding actions to stop streaming on
1264-
a device, Add the following to the ``stop`` function, to stop the stream with
1265-
the `streamOff`_ function and release all buffers.
1258+
a device, Add the following to the ``stopDevice()`` function, to stop the
1259+
stream with the `streamOff`_ function and release all buffers.
12661260

12671261
.. _streamOff: https://libcamera.org/api-html/classlibcamera_1_1V4L2VideoDevice.html#a61998710615bdf7aa25a046c8565ed66
12681262

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ for cam: [optional]
118118
- libtiff-dev: Enables writing DNG
119119

120120
for qcam: [optional]
121-
libtiff-dev qt6-base-dev qt6-tools-dev-tools
121+
libtiff-dev qt6-base-dev
122122

123123
for tracing with lttng: [optional]
124124
liblttng-ust-dev python3-jinja2 lttng-tools

include/libcamera/controls.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ struct control_type<Point> {
120120
};
121121

122122
template<typename T, std::size_t N>
123-
struct control_type<Span<T, N>> : public control_type<std::remove_cv_t<T>> {
123+
struct control_type<Span<T, N>, std::enable_if_t<control_type<std::remove_cv_t<T>>::size == 0>> : public control_type<std::remove_cv_t<T>> {
124124
static constexpr std::size_t size = N;
125125
};
126126

include/libcamera/internal/ipa_data_serializer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,6 @@ class IPADataSerializer<Flags<E>>
309309
serialize(const Flags<E> &data, [[maybe_unused]] ControlSerializer *cs = nullptr)
310310
{
311311
std::vector<uint8_t> dataVec;
312-
dataVec.reserve(sizeof(Flags<E>));
313312
appendPOD<uint32_t>(dataVec, static_cast<typename Flags<E>::Type>(data));
314313

315314
return { dataVec, {} };

include/libcamera/internal/ipa_module.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class IPAModule : public Loggable
2929
bool isValid() const;
3030

3131
const struct IPAModuleInfo &info() const;
32-
const std::vector<uint8_t> signature() const;
32+
const std::vector<uint8_t> &signature() const;
3333
const std::string &path() const;
3434

3535
bool load();

include/libcamera/internal/matrix.h

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <algorithm>
1010
#include <sstream>
11+
#include <type_traits>
1112
#include <vector>
1213

1314
#include <libcamera/base/log.h>
@@ -20,25 +21,32 @@ namespace libcamera {
2021
LOG_DECLARE_CATEGORY(Matrix)
2122

2223
#ifndef __DOXYGEN__
23-
template<typename T, unsigned int Rows, unsigned int Cols,
24-
std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
25-
#else
26-
template<typename T, unsigned int Rows, unsigned int Cols>
24+
template<typename T>
25+
bool matrixInvert(Span<const T> dataIn, Span<T> dataOut, unsigned int dim,
26+
Span<T> scratchBuffer, Span<unsigned int> swapBuffer);
2727
#endif /* __DOXYGEN__ */
28+
29+
template<typename T, unsigned int Rows, unsigned int Cols>
2830
class Matrix
2931
{
32+
static_assert(std::is_arithmetic_v<T>, "Matrix type must be arithmetic");
33+
3034
public:
31-
Matrix()
35+
constexpr Matrix()
3236
{
33-
data_.fill(static_cast<T>(0));
3437
}
3538

3639
Matrix(const std::array<T, Rows * Cols> &data)
3740
{
3841
std::copy(data.begin(), data.end(), data_.begin());
3942
}
4043

41-
static Matrix identity()
44+
Matrix(const Span<const T, Rows * Cols> data)
45+
{
46+
std::copy(data.begin(), data.end(), data_.begin());
47+
}
48+
49+
static constexpr Matrix identity()
4250
{
4351
Matrix ret;
4452
for (size_t i = 0; i < std::min(Rows, Cols); i++)
@@ -66,14 +74,14 @@ class Matrix
6674
return out.str();
6775
}
6876

69-
Span<const T, Rows * Cols> data() const { return data_; }
77+
constexpr Span<const T, Rows * Cols> data() const { return data_; }
7078

71-
Span<const T, Cols> operator[](size_t i) const
79+
constexpr Span<const T, Cols> operator[](size_t i) const
7280
{
7381
return Span<const T, Cols>{ &data_.data()[i * Cols], Cols };
7482
}
7583

76-
Span<T, Cols> operator[](size_t i)
84+
constexpr Span<T, Cols> operator[](size_t i)
7785
{
7886
return Span<T, Cols>{ &data_.data()[i * Cols], Cols };
7987
}
@@ -90,8 +98,30 @@ class Matrix
9098
return *this;
9199
}
92100

101+
Matrix<T, Rows, Cols> inverse(bool *ok = nullptr) const
102+
{
103+
static_assert(Rows == Cols, "Matrix must be square");
104+
105+
Matrix<T, Rows, Cols> inverse;
106+
std::array<T, Rows * Cols * 2> scratchBuffer;
107+
std::array<unsigned int, Rows> swapBuffer;
108+
bool res = matrixInvert(Span<const T>(data_),
109+
Span<T>(inverse.data_),
110+
Rows,
111+
Span<T>(scratchBuffer),
112+
Span<unsigned int>(swapBuffer));
113+
if (ok)
114+
*ok = res;
115+
return inverse;
116+
}
117+
93118
private:
94-
std::array<T, Rows * Cols> data_;
119+
/*
120+
* \todo The initializer is only necessary for the constructor to be
121+
* constexpr in C++17. Remove the initializer as soon as we are on
122+
* C++20.
123+
*/
124+
std::array<T, Rows * Cols> data_ = {};
95125
};
96126

97127
#ifndef __DOXYGEN__
@@ -123,21 +153,16 @@ Matrix<U, Rows, Cols> operator*(const Matrix<U, Rows, Cols> &m, T d)
123153
return d * m;
124154
}
125155

126-
#ifndef __DOXYGEN__
127-
template<typename T,
128-
unsigned int R1, unsigned int C1,
129-
unsigned int R2, unsigned int C2,
130-
std::enable_if_t<C1 == R2> * = nullptr>
131-
#else
132-
template<typename T, unsigned int R1, unsigned int C1, unsigned int R2, unsigned in C2>
133-
#endif /* __DOXYGEN__ */
134-
Matrix<T, R1, C2> operator*(const Matrix<T, R1, C1> &m1, const Matrix<T, R2, C2> &m2)
156+
template<typename T1, unsigned int R1, unsigned int C1, typename T2, unsigned int R2, unsigned int C2>
157+
constexpr Matrix<std::common_type_t<T1, T2>, R1, C2> operator*(const Matrix<T1, R1, C1> &m1,
158+
const Matrix<T2, R2, C2> &m2)
135159
{
136-
Matrix<T, R1, C2> result;
160+
static_assert(C1 == R2, "Matrix dimensions must match for multiplication");
161+
Matrix<std::common_type_t<T1, T2>, R1, C2> result;
137162

138163
for (unsigned int i = 0; i < R1; i++) {
139164
for (unsigned int j = 0; j < C2; j++) {
140-
T sum = 0;
165+
std::common_type_t<T1, T2> sum = 0;
141166

142167
for (unsigned int k = 0; k < C1; k++)
143168
sum += m1[i][k] * m2[k][j];
@@ -150,7 +175,7 @@ Matrix<T, R1, C2> operator*(const Matrix<T, R1, C1> &m1, const Matrix<T, R2, C2>
150175
}
151176

152177
template<typename T, unsigned int Rows, unsigned int Cols>
153-
Matrix<T, Rows, Cols> operator+(const Matrix<T, Rows, Cols> &m1, const Matrix<T, Rows, Cols> &m2)
178+
constexpr Matrix<T, Rows, Cols> operator+(const Matrix<T, Rows, Cols> &m1, const Matrix<T, Rows, Cols> &m2)
154179
{
155180
Matrix<T, Rows, Cols> result;
156181

include/libcamera/internal/media_device.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ class MediaDevice : protected Loggable
5555

5656
Signal<> disconnected;
5757

58+
std::vector<MediaEntity *> locateEntities(unsigned int function);
59+
5860
protected:
5961
std::string logPrefix() const override;
6062

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2+
/*
3+
* Copyright (C) 2024, Ideas on Board Oy
4+
*
5+
* Media pipeline support
6+
*/
7+
8+
#pragma once
9+
10+
#include <list>
11+
#include <string>
12+
13+
#include <libcamera/base/log.h>
14+
15+
namespace libcamera {
16+
17+
class CameraSensor;
18+
class MediaEntity;
19+
class MediaLink;
20+
class MediaPad;
21+
struct V4L2SubdeviceFormat;
22+
23+
class MediaPipeline
24+
{
25+
public:
26+
int init(MediaEntity *source, std::string_view sink);
27+
int initLinks();
28+
int configure(CameraSensor *sensor, V4L2SubdeviceFormat *);
29+
30+
private:
31+
struct Entity {
32+
/* The media entity, always valid. */
33+
MediaEntity *entity;
34+
/*
35+
* Whether or not the entity is a subdev that supports the
36+
* routing API.
37+
*/
38+
bool supportsRouting;
39+
/*
40+
* The local sink pad connected to the upstream entity, null for
41+
* the camera sensor at the beginning of the pipeline.
42+
*/
43+
const MediaPad *sink;
44+
/*
45+
* The local source pad connected to the downstream entity, null
46+
* for the video node at the end of the pipeline.
47+
*/
48+
const MediaPad *source;
49+
/*
50+
* The link on the source pad, to the downstream entity, null
51+
* for the video node at the end of the pipeline.
52+
*/
53+
MediaLink *sourceLink;
54+
};
55+
56+
std::list<Entity> entities_;
57+
};
58+
59+
} /* namespace libcamera */

0 commit comments

Comments
 (0)