From 98842d50cf2782c87990333da7669feea3694711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20P=C5=91cze?= Date: Fri, 8 Aug 2025 09:48:47 +0200 Subject: [PATCH] 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 348e703be0bee84371a0fe87df6b499987c1c508) --- spa/plugins/libcamera/libcamera-source.cpp | 61 +++++++++++++--------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/spa/plugins/libcamera/libcamera-source.cpp b/spa/plugins/libcamera/libcamera-source.cpp index 01fd77299..df4c8f181 100644 --- a/spa/plugins/libcamera/libcamera-source.cpp +++ b/spa/plugins/libcamera/libcamera-source.cpp @@ -278,18 +278,42 @@ int spa_libcamera_buffer_recycle(struct impl *impl, struct port *port, uint32_t 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 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) { + libcamera::Stream *stream = port->streamConfig.stream(); int res; - if ((res = impl->allocator->allocate(port->streamConfig.stream())) < 0) + if ((res = impl->allocator->allocate(stream)) < 0) return res; for (unsigned int i = 0; i < count; i++) { std::unique_ptr request = impl->camera->createRequest(i); if (!request) { - impl->requestPool.clear(); - return -ENOMEM; + res = -ENOMEM; + goto err; } 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. * address. Therefore, need calculate the number of discontiguous * memory and allocate the specified amount of memory */ - Stream *stream = impl->config->at(0).stream(); - const std::vector> &bufs = - impl->allocator->buffers(stream); - const std::vector &planes = bufs[0]->planes(); - 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; - } + port->buffers_blocks = count_unique_fds(impl->allocator->buffers(stream).front()->planes()); + if (port->buffers_blocks <= 0) { + res = -ENOBUFS; + goto err; } - if (buffers_blocks > 0) { - port->buffers_blocks = buffers_blocks; - } + return 0; + +err: + freeBuffers(impl, port); + 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) { uint32_t i;