spa: libcamera: source: allocBuffers(): restore on failure

Undo the allocation and clear the requests if a failure is encountered
in order to leave things in a known state.

(cherry picked from commit 348e703be0)
This commit is contained in:
Barnabás Pőcze 2025-08-08 09:48:47 +02:00 committed by Robert Mader
parent b28eb20c1f
commit 98842d50cf

View file

@ -278,18 +278,42 @@ int spa_libcamera_buffer_recycle(struct impl *impl, struct port *port, uint32_t
return 0; return 0;
} }
void freeBuffers(struct impl *impl, struct port *port)
{
impl->requestPool.clear();
std::ignore = impl->allocator->free(port->streamConfig.stream());
}
[[nodiscard]]
std::size_t count_unique_fds(libcamera::Span<const libcamera::FrameBuffer::Plane> planes)
{
std::size_t c = 0;
int fd = -1;
for (const auto& plane : planes) {
const int current_fd = plane.fd.get();
if (current_fd >= 0 && current_fd != fd) {
c += 1;
fd = current_fd;
}
}
return c;
}
int allocBuffers(struct impl *impl, struct port *port, unsigned int count) int allocBuffers(struct impl *impl, struct port *port, unsigned int count)
{ {
libcamera::Stream *stream = port->streamConfig.stream();
int res; int res;
if ((res = impl->allocator->allocate(port->streamConfig.stream())) < 0) if ((res = impl->allocator->allocate(stream)) < 0)
return res; return res;
for (unsigned int i = 0; i < count; i++) { for (unsigned int i = 0; i < count; i++) {
std::unique_ptr<Request> request = impl->camera->createRequest(i); std::unique_ptr<Request> request = impl->camera->createRequest(i);
if (!request) { if (!request) {
impl->requestPool.clear(); res = -ENOMEM;
return -ENOMEM; goto err;
} }
impl->requestPool.push_back(std::move(request)); impl->requestPool.push_back(std::move(request));
} }
@ -299,33 +323,20 @@ int allocBuffers(struct impl *impl, struct port *port, unsigned int count)
* video frame has to be addressed using more than one memory. * video frame has to be addressed using more than one memory.
* address. Therefore, need calculate the number of discontiguous * address. Therefore, need calculate the number of discontiguous
* memory and allocate the specified amount of memory */ * memory and allocate the specified amount of memory */
Stream *stream = impl->config->at(0).stream(); port->buffers_blocks = count_unique_fds(impl->allocator->buffers(stream).front()->planes());
const std::vector<std::unique_ptr<FrameBuffer>> &bufs = if (port->buffers_blocks <= 0) {
impl->allocator->buffers(stream); res = -ENOBUFS;
const std::vector<libcamera::FrameBuffer::Plane> &planes = bufs[0]->planes(); goto err;
int fd = -1;
uint32_t buffers_blocks = 0;
for (const FrameBuffer::Plane &plane : planes) {
const int current_fd = plane.fd.get();
if (current_fd >= 0 && current_fd != fd) {
buffers_blocks += 1;
fd = current_fd;
}
} }
if (buffers_blocks > 0) { return 0;
port->buffers_blocks = buffers_blocks;
} err:
freeBuffers(impl, port);
return res; return res;
} }
void freeBuffers(struct impl *impl, struct port *port)
{
impl->requestPool.clear();
impl->allocator->free(port->streamConfig.stream());
}
int spa_libcamera_clear_buffers(struct impl *impl, struct port *port) int spa_libcamera_clear_buffers(struct impl *impl, struct port *port)
{ {
uint32_t i; uint32_t i;