Pick the first format in the list of supported as something closest
to 640x480 instead of the lowest possible resolution.
Applications that don't suggest a default size will then get something
more sensible than a poster frame.
Previously, if "add_listener" was called on the monitor device, then it
did not necessarily emit events about all devices because it called
`enum_devices()` which does not emit events about already existing
devices. So the very first listener would get all existing devices,
but subsequent ones would not get events about the existence of devices
that have already been seen by the monitor. Fix that by simply emitting
events about all existing devices if the current listener is not the first.
libcamera's CameraManager runs the event handlers on its own thread,
thus synchronization is needed to ensure correct functionality.
Implement that by collecting hotplug events into a mutex protected queue
and signalling the main loop where they can be processed and the
"object_info" event can be safely emitted.
Using a shared_ptr removes the need for manually calling
`libcamera_manager_release()` to drop the reference as it is done
automatically whenever the shared_ptr is destroyed or reset.
Previously, the libcamera manager `impl` object was neither properly
constructed neither properly destructed. As a consequence, for example,
the shared pointers in the `devices` array weren't properly destructed,
although this has been somewhat mitigated by a previous change
that modifed `clear_devices()`.
Previously, the "impl" object was never properly constructed or
destructed, but it more or less worked out since the memory was initialized
to zero bytes and each member had trivial constructors. Except std::shared_ptr,
but an all zero storage happened to be equivalent to a default constructed
shared_ptr.
However, there was the still the problem that the shared_ptr was never
destructed, so it kept the referenced `Camera` object alive, which lead
to memory leaks.
An additional, somewhat unrelated change is that the "props" struct
is removed, and the device identifier is now stored in an `std::string`.
The reason is that `CameraManager::get()` already takes a const std::string reference,
so an std::string must be constructed in any case, so we might as well
take advantage of that and use `std::string` in the "impl" object as well.
Furthermore, wrap the `impl` struct in an anonymous namespace
to avoid name resolution problems.
Previously, in `remove_device()`, the last device would be copied into
the slot of the to-be-remove device. The problem with this is that it
left the shared_ptr untouched in the previously last slot, and hence
creating an extra reference. Fix this by moving instead of copying.
A similar problem is present in `clear_devices()` which also
did not properly dispose of the shared_ptrs. Fix that by
calling `reset()` on each device's camera pointer.
libcamera commit 1c4d4801850559d6f919eef5c2ffbaf7675dbc46
changed the return type of libcamera::ControlList::get()
to be std::optional<T>. Adapt the code to this change.
Fixes#2575
The PropInfo either has a registered id (and then also a name from the
type-info) or a custom name as a string.
In all cases, the description contains a free form text that clarifies
the property.
Use the description in the stream controls name.
Make the alignment parameter optional when negotiating buffers.
Default to a 16 bytes alignment and adjust for the max cpu
alignment.
Remove the useless align buffer parameter in plugins, we always
set it to 16 anyway.
Keep track of the negotiated parameters and use those to construct
the Buffers param.
Use the FrameAllocator to allocate buffer memory. Keep a request for
each buffer and queue them.
In requestComplete, put the request metadata info into the buffer and
header and write the finished buffer id to a ringbuffer. Then wake up
the data thread to pop the finished buffer_id and push it in the
graph.
Remove some old files.
The requests_ vector contains the requests created for a camera on start()
but the vector elements are not removed on camera stop(). This leads to a
segfault, when these requests that are no longer valid are queued again.
Also move the streamName_ map clear to LibCamera::stop() where it should
be, since its elements are added in the LibCamera::start() function.
The camera is connected in the spa_libcamera_stream_on() function but the
disconnect happen in LibCamera::stop(). It makes more sense to have this
two operations separated as it's done for the connection and start, since
the camera then can be stopped/started without needing to do a reconnect.
Move the camera disconnect to spa_libcamera_stream_off() for the reason
mentioned above but also to make the code more consistent and symmetric.
Camera is currently stopped and started in the spa_libcamera_set_format()
function, but this leads to a segfault due attempting to access a buffers
field of an already freed libcamera::FrameBufferAllocator instance.
The FrameBufferAllocator instance is freed in LibCamera::stop(), that is
called by spa_libcamera_stream_off() as handler of the node commands
SPA_NODE_COMMAND_Pause and SPA_NODE_COMMAND_Suspend.
Since the camera was already stopped, there's no need to attempt to stop
it again. In fact, the camera shouldn't be stopped/started at all in the
spa_libcamera_set_format() function but instead only as an action of the
SPA_NODE_COMMAND_{Pause,Suspend} and SPA_NODE_COMMAND_Start commands.
And same for the stop that's done in the LibCamera::close() function, it
shouldn't be needed because the camera is already stopped before closing.
Fixes#1513
There is no need to set and validate the configuration when the camera
is started, since this was already made when the camera was opened.
The configuration only needs to be set again if the port format changes
due a SPA_PARAM_Format parameter.
Upstream libcamera commit 32635054bc76e2ababd8ea2177fca1f88229541a
changed "planes" on `FrameMetadata` to be a function. Adapt
the plugin code accordingly.
To fix build warning about a variable being unused in LibCamera::stop():
[1/2] Compiling C++ object spa/plugins/libcamera/libspa-libcamera.so.p/libcamera_wrapper.cpp.o
../spa/plugins/libcamera/libcamera_wrapper.cpp: In member function ‘void LibCamera::stop()’:
../spa/plugins/libcamera/libcamera_wrapper.cpp:531:58: warning: unused variable ‘buffer’ [-Wunused-variable]
531 | for (const std::unique_ptr<FrameBuffer> &buffer : this->allocator_->buffers(stream)) {
| ^~~~~~
The SPA plugin is including a <libcamera/buffer.h> header file, but this
got renamed to <libcamera/framebuffer.h> to match the defined class name:
../spa/plugins/libcamera/libcamera_wrapper.cpp:52:10: fatal error: libcamera/buffer.h: No such file or directory
52 | #include <libcamera/buffer.h>
| ^~~~~~~~~~~~~~~~~~~~
Fixes#1435