@@ -116,7 +116,7 @@ private:
void requestComplete(Request *request);
friend class FrameBufferAllocator;
- int exportFrameBuffers(Stream *stream,
+ int exportFrameBuffers(Stream *stream, unsigned int count,
std::vector<std::unique_ptr<FrameBuffer>> *buffers);
};
@@ -25,7 +25,7 @@ public:
FrameBufferAllocator(std::shared_ptr<Camera> camera);
~FrameBufferAllocator();
- int allocate(Stream *stream);
+ int allocate(Stream *stream, unsigned int count);
int free(Stream *stream);
bool allocated() const { return !buffers_.empty(); }
@@ -76,7 +76,7 @@ public:
const StreamRoles &roles) = 0;
virtual int configure(Camera *camera, CameraConfiguration *config) = 0;
- virtual int exportFrameBuffers(Camera *camera, Stream *stream,
+ virtual int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,
std::vector<std::unique_ptr<FrameBuffer>> *buffers) = 0;
virtual int start(Camera *camera, const ControlList *controls) = 0;
@@ -13,6 +13,7 @@
#include "jpeg/post_processor_jpeg.h"
#include <libcamera/formats.h>
+#include <libcamera/property_ids.h>
using namespace libcamera;
@@ -81,8 +82,10 @@ int CameraStream::configure()
return ret;
}
+ unsigned int bufferCount = cameraDevice_->camera()->properties().get(properties::MinNumRequests);
+
if (allocator_) {
- int ret = allocator_->allocate(stream());
+ int ret = allocator_->allocate(stream(), bufferCount);
if (ret < 0)
return ret;
@@ -11,6 +11,7 @@
#include <sstream>
#include <libcamera/control_ids.h>
+#include <libcamera/property_ids.h>
#include "capture.h"
#include "main.h"
@@ -81,17 +82,13 @@ int Capture::capture(FrameBufferAllocator *allocator)
{
int ret;
- /* Identify the stream with the least number of buffers. */
- unsigned int nbuffers = UINT_MAX;
+ unsigned int nbuffers = camera_->properties().get(properties::MinNumRequests);
for (StreamConfiguration &cfg : *config_) {
- ret = allocator->allocate(cfg.stream());
+ ret = allocator->allocate(cfg.stream(), nbuffers);
if (ret < 0) {
std::cerr << "Can't allocate buffers" << std::endl;
return -ENOMEM;
}
-
- unsigned int allocated = allocator->buffers(cfg.stream()).size();
- nbuffers = std::min(nbuffers, allocated);
}
/*
@@ -10,6 +10,7 @@
#include <libcamera/camera.h>
#include <libcamera/framebuffer_allocator.h>
+#include <libcamera/property_ids.h>
#include <libcamera/stream.h>
#include "gstlibcamera-utils.h"
@@ -188,13 +189,14 @@ gst_libcamera_allocator_new(std::shared_ptr<Camera> camera,
{
auto *self = GST_LIBCAMERA_ALLOCATOR(g_object_new(GST_TYPE_LIBCAMERA_ALLOCATOR,
nullptr));
+ unsigned int bufferCount = camera->properties().get(properties::MinNumRequests);
self->fb_allocator = new FrameBufferAllocator(camera);
for (StreamConfiguration &streamCfg : *config_) {
Stream *stream = streamCfg.stream();
gint ret;
- ret = self->fb_allocator->allocate(stream);
+ ret = self->fb_allocator->allocate(stream, bufferCount);
if (ret == 0)
return nullptr;
@@ -7,6 +7,8 @@
#include <gtest/gtest.h>
+#include <libcamera/property_ids.h>
+
#include "simple_capture.h"
using namespace libcamera;
@@ -44,11 +46,12 @@ void SimpleCapture::configure(StreamRole role)
void SimpleCapture::start()
{
+ unsigned int bufferCount = camera_->properties().get(properties::MinNumRequests);
Stream *stream = config_->at(0).stream();
- int count = allocator_->allocate(stream);
+ int count = allocator_->allocate(stream, bufferCount);
ASSERT_GE(count, 0) << "Failed to allocate buffers";
- EXPECT_EQ(count, config_->at(0).bufferCount) << "Allocated less buffers than expected";
+ EXPECT_EQ(count, static_cast<int>(bufferCount)) << "Allocated less buffers than expected";
camera_->requestCompleted.connect(this, &SimpleCapture::requestComplete);
@@ -663,7 +663,7 @@ void Camera::disconnect()
disconnected.emit(this);
}
-int Camera::exportFrameBuffers(Stream *stream,
+int Camera::exportFrameBuffers(Stream *stream, unsigned int count,
std::vector<std::unique_ptr<FrameBuffer>> *buffers)
{
Private *const d = LIBCAMERA_D_PTR();
@@ -680,7 +680,7 @@ int Camera::exportFrameBuffers(Stream *stream,
return d->pipe_->invokeMethod(&PipelineHandler::exportFrameBuffers,
ConnectionTypeBlocking, this, stream,
- buffers);
+ count, buffers);
}
/**
@@ -71,6 +71,7 @@ FrameBufferAllocator::~FrameBufferAllocator()
/**
* \brief Allocate buffers for a configured stream
* \param[in] stream The stream to allocate buffers for
+ * \param[in] count The number of buffers to allocate
*
* Allocate buffers suitable for capturing frames from the \a stream. The Camera
* shall have been previously configured with Camera::configure() and shall be
@@ -86,14 +87,14 @@ FrameBufferAllocator::~FrameBufferAllocator()
* not part of the active camera configuration
* \retval -EBUSY Buffers are already allocated for the \a stream
*/
-int FrameBufferAllocator::allocate(Stream *stream)
+int FrameBufferAllocator::allocate(Stream *stream, unsigned int count)
{
if (buffers_.count(stream)) {
LOG(Allocator, Error) << "Buffers already allocated for stream";
return -EBUSY;
}
- int ret = camera_->exportFrameBuffers(stream, &buffers_[stream]);
+ int ret = camera_->exportFrameBuffers(stream, count, &buffers_[stream]);
if (ret == -EINVAL)
LOG(Allocator, Error)
<< "Stream is not part of " << camera_->id()
@@ -134,7 +134,7 @@ public:
const StreamRoles &roles) override;
int configure(Camera *camera, CameraConfiguration *config) override;
- int exportFrameBuffers(Camera *camera, Stream *stream,
+ int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,
std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
int start(Camera *camera, const ControlList *controls) override;
@@ -654,10 +654,10 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c)
}
int PipelineHandlerIPU3::exportFrameBuffers(Camera *camera, Stream *stream,
+ unsigned int count,
std::vector<std::unique_ptr<FrameBuffer>> *buffers)
{
IPU3CameraData *data = cameraData(camera);
- unsigned int count = stream->configuration().bufferCount;
if (stream == &data->outStream_)
return data->imgu_->output_->exportBuffers(count, buffers);
@@ -250,7 +250,7 @@ public:
CameraConfiguration *generateConfiguration(Camera *camera, const StreamRoles &roles) override;
int configure(Camera *camera, CameraConfiguration *config) override;
- int exportFrameBuffers(Camera *camera, Stream *stream,
+ int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,
std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
int start(Camera *camera, const ControlList *controls) override;
@@ -794,10 +794,10 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)
}
int PipelineHandlerRPi::exportFrameBuffers([[maybe_unused]] Camera *camera, Stream *stream,
+ unsigned int count,
std::vector<std::unique_ptr<FrameBuffer>> *buffers)
{
RPi::Stream *s = static_cast<RPi::Stream *>(stream);
- unsigned int count = stream->configuration().bufferCount;
int ret = s->dev()->exportBuffers(count, buffers);
s->setExportedBuffers(buffers);
@@ -141,7 +141,7 @@ public:
const StreamRoles &roles) override;
int configure(Camera *camera, CameraConfiguration *config) override;
- int exportFrameBuffers(Camera *camera, Stream *stream,
+ int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,
std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
int start(Camera *camera, const ControlList *controls) override;
@@ -671,10 +671,10 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)
}
int PipelineHandlerRkISP1::exportFrameBuffers([[maybe_unused]] Camera *camera, Stream *stream,
+ unsigned int count,
std::vector<std::unique_ptr<FrameBuffer>> *buffers)
{
RkISP1CameraData *data = cameraData(camera);
- unsigned int count = stream->configuration().bufferCount;
if (stream == &data->mainPathStream_)
return mainPath_.exportBuffers(count, buffers);
@@ -228,7 +228,7 @@ public:
const StreamRoles &roles) override;
int configure(Camera *camera, CameraConfiguration *config) override;
- int exportFrameBuffers(Camera *camera, Stream *stream,
+ int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,
std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
int start(Camera *camera, const ControlList *controls) override;
@@ -776,10 +776,10 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)
}
int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,
+ unsigned int count,
std::vector<std::unique_ptr<FrameBuffer>> *buffers)
{
SimpleCameraData *data = cameraData(camera);
- unsigned int count = stream->configuration().bufferCount;
/*
* Export buffers on the converter or capture video node, depending on
@@ -69,7 +69,7 @@ public:
const StreamRoles &roles) override;
int configure(Camera *camera, CameraConfiguration *config) override;
- int exportFrameBuffers(Camera *camera, Stream *stream,
+ int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,
std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
int start(Camera *camera, const ControlList *controls) override;
@@ -223,11 +223,12 @@ int PipelineHandlerUVC::configure(Camera *camera, CameraConfiguration *config)
return 0;
}
-int PipelineHandlerUVC::exportFrameBuffers(Camera *camera, Stream *stream,
+int PipelineHandlerUVC::exportFrameBuffers(Camera *camera,
+ [[maybe_unused]] Stream *stream,
+ unsigned int count,
std::vector<std::unique_ptr<FrameBuffer>> *buffers)
{
UVCCameraData *data = cameraData(camera);
- unsigned int count = stream->configuration().bufferCount;
return data->video_->exportBuffers(count, buffers);
}
@@ -84,7 +84,7 @@ public:
const StreamRoles &roles) override;
int configure(Camera *camera, CameraConfiguration *config) override;
- int exportFrameBuffers(Camera *camera, Stream *stream,
+ int exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count,
std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
int start(Camera *camera, const ControlList *controls) override;
@@ -299,11 +299,12 @@ int PipelineHandlerVimc::configure(Camera *camera, CameraConfiguration *config)
return 0;
}
-int PipelineHandlerVimc::exportFrameBuffers(Camera *camera, Stream *stream,
+int PipelineHandlerVimc::exportFrameBuffers(Camera *camera,
+ [[maybe_unused]] Stream *stream,
+ unsigned int count,
std::vector<std::unique_ptr<FrameBuffer>> *buffers)
{
VimcCameraData *data = cameraData(camera);
- unsigned int count = stream->configuration().bufferCount;
return data->video_->exportBuffers(count, buffers);
}
@@ -323,6 +323,7 @@ const ControlList &PipelineHandler::properties(const Camera *camera) const
* \brief Allocate and export buffers for \a stream
* \param[in] camera The camera
* \param[in] stream The stream to allocate buffers for
+ * \param[in] count The number of buffers to allocate
* \param[out] buffers Array of buffers successfully allocated
*
* This method allocates buffers for the \a stream from the devices associated
@@ -25,6 +25,7 @@
#include <QtDebug>
#include <libcamera/camera_manager.h>
+#include <libcamera/property_ids.h>
#include <libcamera/version.h>
#include "dng_writer.h"
@@ -463,7 +464,15 @@ int MainWindow::startCapture()
for (StreamConfiguration &config : *config_) {
Stream *stream = config.stream();
- ret = allocator_->allocate(stream);
+ unsigned int bufferCount = camera_->properties().get(properties::MinNumRequests);
+
+ /*
+ * Need at least two buffers, one for capture and another for
+ * display
+ */
+ bufferCount = std::max(bufferCount, 2U);
+
+ ret = allocator_->allocate(stream, bufferCount);
if (ret < 0) {
qWarning() << "Failed to allocate capture buffers";
goto error;
@@ -161,7 +161,7 @@ int V4L2Camera::allocBuffers(unsigned int count)
{
Stream *stream = config_->at(0).stream();
- int ret = bufferAllocator_->allocate(stream);
+ int ret = bufferAllocator_->allocate(stream, count);
if (ret < 0)
return ret;
@@ -8,6 +8,7 @@
#include <iostream>
#include <libcamera/framebuffer_allocator.h>
+#include <libcamera/property_ids.h>
#include <libcamera/base/event_dispatcher.h>
#include <libcamera/base/thread.h>
@@ -96,7 +97,8 @@ protected:
Stream *stream = cfg.stream();
- int ret = allocator_->allocate(stream);
+ unsigned int bufferCount = camera_->properties().get(properties::MinNumRequests);
+ int ret = allocator_->allocate(stream, bufferCount);
if (ret < 0)
return TestFail;
@@ -8,6 +8,7 @@
#include <iostream>
#include <libcamera/framebuffer_allocator.h>
+#include <libcamera/property_ids.h>
#include "camera_test.h"
#include "test.h"
@@ -119,7 +120,8 @@ protected:
/* Use internally allocated buffers. */
allocator_ = new FrameBufferAllocator(camera_);
Stream *stream = *camera_->streams().begin();
- if (allocator_->allocate(stream) < 0)
+ unsigned int bufferCount = camera_->properties().get(properties::MinNumRequests);
+ if (allocator_->allocate(stream, bufferCount) < 0)
return TestFail;
if (camera_->start())
@@ -8,6 +8,7 @@
#include <iostream>
#include <libcamera/framebuffer_allocator.h>
+#include <libcamera/property_ids.h>
#include "libcamera/internal/buffer.h"
@@ -54,7 +55,8 @@ protected:
stream_ = cfg.stream();
- int ret = allocator_->allocate(stream_);
+ unsigned int bufferCount = camera_->properties().get(properties::MinNumRequests);
+ int ret = allocator_->allocate(stream_, bufferCount);
if (ret < 0)
return TestFail;
Make FrameBufferAllocator::allocate() require a 'count' argument for the number of buffers to be allocated. Signed-off-by: NĂcolas F. R. A. Prado <nfraprado@collabora.com> --- Changes in v5: - Made sure that qcam allocates at least 2 buffers include/libcamera/camera.h | 2 +- include/libcamera/framebuffer_allocator.h | 2 +- include/libcamera/internal/pipeline_handler.h | 2 +- src/android/camera_stream.cpp | 5 ++++- src/cam/capture.cpp | 9 +++------ src/gstreamer/gstlibcameraallocator.cpp | 4 +++- src/lc-compliance/simple_capture.cpp | 7 +++++-- src/libcamera/camera.cpp | 4 ++-- src/libcamera/framebuffer_allocator.cpp | 5 +++-- src/libcamera/pipeline/ipu3/ipu3.cpp | 4 ++-- src/libcamera/pipeline/raspberrypi/raspberrypi.cpp | 4 ++-- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 4 ++-- src/libcamera/pipeline/simple/simple.cpp | 4 ++-- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 7 ++++--- src/libcamera/pipeline/vimc/vimc.cpp | 7 ++++--- src/libcamera/pipeline_handler.cpp | 1 + src/qcam/main_window.cpp | 11 ++++++++++- src/v4l2/v4l2_camera.cpp | 2 +- test/camera/capture.cpp | 4 +++- test/camera/statemachine.cpp | 4 +++- test/mapped-buffer.cpp | 4 +++- 21 files changed, 60 insertions(+), 36 deletions(-)