From patchwork Wed Apr 21 16:51:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= X-Patchwork-Id: 12050 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id E18C7BDB15 for ; Wed, 21 Apr 2021 16:52:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A16D16884C; Wed, 21 Apr 2021 18:52:25 +0200 (CEST) Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DA00B68846 for ; Wed, 21 Apr 2021 18:52:22 +0200 (CEST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: nfraprado) with ESMTPSA id D859C1F423EB From: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= To: libcamera-devel@lists.libcamera.org Date: Wed, 21 Apr 2021 13:51:36 -0300 Message-Id: <20210421165139.318432-2-nfraprado@collabora.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210421165139.318432-1-nfraprado@collabora.com> References: <20210421165139.318432-1-nfraprado@collabora.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 1/4] libcamera: property: Add QueueDepth property X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Andr=C3=A9_Almeida?= , kernel@collabora.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The QueueDepth property reports the minimum amount of requests needed in the camera pipeline. Signed-off-by: Nícolas F. R. A. Prado --- src/libcamera/pipeline/ipu3/ipu3.cpp | 4 ++++ src/libcamera/pipeline/raspberrypi/raspberrypi.cpp | 4 ++++ src/libcamera/pipeline/rkisp1/rkisp1.cpp | 2 ++ src/libcamera/pipeline/rkisp1/rkisp1_path.h | 4 ++-- src/libcamera/pipeline/simple/simple.cpp | 6 ++++-- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 2 ++ src/libcamera/pipeline/vimc/vimc.cpp | 3 +++ src/libcamera/property_ids.yaml | 5 +++++ 8 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 51446fcf5bc1..6067db2f37a3 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -1049,6 +1049,10 @@ int PipelineHandlerIPU3::registerCameras() /* Initialize the camera properties. */ data->properties_ = cio2->sensor()->properties(); + /* TODO This can be changed to CIO2 after configuration, but + * both are 4 currently */ + data->properties_.set(properties::QueueDepth, 4); + ret = initControls(data.get()); if (ret) continue; diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 2a917455500f..8d1ade3a4352 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -1035,6 +1035,10 @@ bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator) /* Initialize the camera properties. */ data->properties_ = data->sensor_->properties(); + /* TODO Can be 1, 2 or 4 depending on configuration, for now use the max + * which is 4 */ + data->properties_.set(properties::QueueDepth, 4); + /* * Set a default value for the ScalerCropMaximum property to show * that we support its use, however, initialise it to zero because diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 549f4a4e61a8..7d876e9387d7 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -940,6 +941,7 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor) /* Initialize the camera properties. */ data->properties_ = data->sensor_->properties(); + data->properties_.set(properties::QueueDepth, RKISP1_BUFFER_COUNT); /* * \todo Read dealy values from the sensor itself or from a diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h index 3b3e37d258d0..7540dd41ad84 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h @@ -26,6 +26,8 @@ class V4L2Subdevice; struct StreamConfiguration; struct V4L2SubdeviceFormat; +static constexpr unsigned int RKISP1_BUFFER_COUNT = 4; + class RkISP1Path { public: @@ -56,8 +58,6 @@ public: Signal &bufferReady() { return video_->bufferReady; } private: - static constexpr unsigned int RKISP1_BUFFER_COUNT = 4; - const char *name_; bool running_; diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index f6095d38e97a..6ee24f2f14e8 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -141,6 +142,8 @@ static const SimplePipelineInfo supportedDevices[] = { } /* namespace */ +static constexpr unsigned int kNumInternalBuffers = 3; + class SimpleCameraData : public CameraData { public: @@ -238,8 +241,6 @@ protected: int queueRequestDevice(Camera *camera, Request *request) override; private: - static constexpr unsigned int kNumInternalBuffers = 3; - SimpleCameraData *cameraData(const Camera *camera) { return static_cast( @@ -424,6 +425,7 @@ int SimpleCameraData::init() } properties_ = sensor_->properties(); + properties_.set(properties::QueueDepth, kNumInternalBuffers); return 0; } diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index b6c6ade5ebaf..591f46b60d23 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -525,6 +525,8 @@ int UVCCameraData::init(MediaDevice *media) properties_.set(properties::PixelArraySize, resolution); properties_.set(properties::PixelArrayActiveAreas, { Rectangle(resolution) }); + properties_.set(properties::QueueDepth, 4); + /* Initialise the supported controls. */ ControlInfoMap::Map ctrls; diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp index 8f5f4ba30953..605b3fe89152 100644 --- a/src/libcamera/pipeline/vimc/vimc.cpp +++ b/src/libcamera/pipeline/vimc/vimc.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -516,6 +517,8 @@ int VimcCameraData::init() /* Initialize the camera properties. */ properties_ = sensor_->properties(); + properties_.set(properties::QueueDepth, 4); + return 0; } diff --git a/src/libcamera/property_ids.yaml b/src/libcamera/property_ids.yaml index 104e9aaf4fa3..0b7d1271a26b 100644 --- a/src/libcamera/property_ids.yaml +++ b/src/libcamera/property_ids.yaml @@ -678,6 +678,11 @@ controls: \todo Turn this property into a "maximum control value" for the ScalerCrop control once "dynamic" controls have been implemented. + - QueueDepth: + type: int32_t + description: | + Minimum amount of requests needed in the camera pipeline. + # ---------------------------------------------------------------------------- # Draft properties section From patchwork Wed Apr 21 16:51:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= X-Patchwork-Id: 12051 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 26F77BDB15 for ; Wed, 21 Apr 2021 16:52:27 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E696A68857; Wed, 21 Apr 2021 18:52:26 +0200 (CEST) Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7643368835 for ; Wed, 21 Apr 2021 18:52:25 +0200 (CEST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: nfraprado) with ESMTPSA id 38CB31F423EC From: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= To: libcamera-devel@lists.libcamera.org Date: Wed, 21 Apr 2021 13:51:37 -0300 Message-Id: <20210421165139.318432-3-nfraprado@collabora.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210421165139.318432-1-nfraprado@collabora.com> References: <20210421165139.318432-1-nfraprado@collabora.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 2/4] libcamera: framebuffer_allocator: Make allocate() require count X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Andr=C3=A9_Almeida?= , kernel@collabora.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Make FrameBufferAllocator::allocate() require a 'count' argument for the amount of buffers to be allocated. Signed-off-by: Nícolas F. R. A. Prado --- include/libcamera/camera.h | 2 +- include/libcamera/framebuffer_allocator.h | 2 +- include/libcamera/internal/pipeline_handler.h | 2 +- src/cam/capture.cpp | 10 ++++------ src/gstreamer/gstlibcameraallocator.cpp | 4 +++- src/lc-compliance/simple_capture.cpp | 13 +++++++++++-- src/lc-compliance/simple_capture.h | 1 + src/lc-compliance/single_stream.cpp | 6 ++++++ 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 | 4 +++- src/v4l2/v4l2_camera.cpp | 2 +- test/camera/capture.cpp | 4 +++- test/camera/statemachine.cpp | 4 +++- test/mapped-buffer.cpp | 4 +++- 22 files changed, 63 insertions(+), 35 deletions(-) diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h index d71641805c0a..656cd92aecde 100644 --- a/include/libcamera/camera.h +++ b/include/libcamera/camera.h @@ -115,7 +115,7 @@ private: void requestComplete(Request *request); friend class FrameBufferAllocator; - int exportFrameBuffers(Stream *stream, + int exportFrameBuffers(Stream *stream, unsigned int count, std::vector> *buffers); }; diff --git a/include/libcamera/framebuffer_allocator.h b/include/libcamera/framebuffer_allocator.h index 0c85631a1da2..f1ae37288d50 100644 --- a/include/libcamera/framebuffer_allocator.h +++ b/include/libcamera/framebuffer_allocator.h @@ -25,7 +25,7 @@ public: FrameBufferAllocator(std::shared_ptr camera); ~FrameBufferAllocator(); - int allocate(Stream *stream); + int allocate(Stream *stream, unsigned int count); int free(Stream *stream); bool allocated() const { return !buffers_.empty(); } diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h index c6454db6b2c4..dc04ba041fe5 100644 --- a/include/libcamera/internal/pipeline_handler.h +++ b/include/libcamera/internal/pipeline_handler.h @@ -75,7 +75,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> *buffers) = 0; virtual int start(Camera *camera, const ControlList *controls) = 0; diff --git a/src/cam/capture.cpp b/src/cam/capture.cpp index 7b55fc677022..8ad121f5adc8 100644 --- a/src/cam/capture.cpp +++ b/src/cam/capture.cpp @@ -10,6 +10,8 @@ #include #include +#include + #include "capture.h" #include "main.h" @@ -77,17 +79,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::QueueDepth); 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); } /* diff --git a/src/gstreamer/gstlibcameraallocator.cpp b/src/gstreamer/gstlibcameraallocator.cpp index 7bd8ba2db71d..e7a5b5a27226 100644 --- a/src/gstreamer/gstlibcameraallocator.cpp +++ b/src/gstreamer/gstlibcameraallocator.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include "gstlibcamera-utils.h" @@ -188,13 +189,14 @@ gst_libcamera_allocator_new(std::shared_ptr camera, { auto *self = GST_LIBCAMERA_ALLOCATOR(g_object_new(GST_TYPE_LIBCAMERA_ALLOCATOR, nullptr)); + int bufferCount = camera->properties().get(properties::QueueDepth); 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; diff --git a/src/lc-compliance/simple_capture.cpp b/src/lc-compliance/simple_capture.cpp index 64e862a08e3a..875772a80c27 100644 --- a/src/lc-compliance/simple_capture.cpp +++ b/src/lc-compliance/simple_capture.cpp @@ -5,6 +5,8 @@ * simple_capture.cpp - Simple capture helper */ +#include + #include "simple_capture.h" using namespace libcamera; @@ -39,12 +41,19 @@ Results::Result SimpleCapture::configure(StreamRole role) return { Results::Pass, "Configure camera" }; } -Results::Result SimpleCapture::start() +Results::Result SimpleCapture::allocateBuffers() { + int minBuffers = camera_->properties().get(properties::QueueDepth); Stream *stream = config_->at(0).stream(); - if (allocator_->allocate(stream) < 0) + + if (allocator_->allocate(stream, minBuffers) < 0) return { Results::Fail, "Failed to allocate buffers" }; + return { Results::Pass, "Allocated buffers" }; +} + +Results::Result SimpleCapture::start() +{ if (camera_->start()) return { Results::Fail, "Failed to start camera" }; diff --git a/src/lc-compliance/simple_capture.h b/src/lc-compliance/simple_capture.h index d9de53fb63a3..82e2c56a55f1 100644 --- a/src/lc-compliance/simple_capture.h +++ b/src/lc-compliance/simple_capture.h @@ -18,6 +18,7 @@ class SimpleCapture { public: Results::Result configure(libcamera::StreamRole role); + Results::Result allocateBuffers(); protected: SimpleCapture(std::shared_ptr camera); diff --git a/src/lc-compliance/single_stream.cpp b/src/lc-compliance/single_stream.cpp index 8318b42f42d6..649291c7bb73 100644 --- a/src/lc-compliance/single_stream.cpp +++ b/src/lc-compliance/single_stream.cpp @@ -23,6 +23,9 @@ Results::Result testRequestBalance(std::shared_ptr camera, return ret; for (unsigned int starts = 0; starts < startCycles; starts++) { + capture.allocateBuffers(); + if (ret.first != Results::Pass) + return ret; ret = capture.capture(numRequests); if (ret.first != Results::Pass) return ret; @@ -39,6 +42,9 @@ Results::Result testRequestUnbalance(std::shared_ptr camera, SimpleCaptureUnbalanced capture(camera); Results::Result ret = capture.configure(role); + if (ret.first != Results::Pass) + return ret; + capture.allocateBuffers(); if (ret.first != Results::Pass) return ret; diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index 763f3b9926fd..e4da6e042bd0 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -656,7 +656,7 @@ void Camera::disconnect() disconnected.emit(this); } -int Camera::exportFrameBuffers(Stream *stream, +int Camera::exportFrameBuffers(Stream *stream, unsigned int count, std::vector> *buffers) { Private *const d = LIBCAMERA_D_PTR(); @@ -673,7 +673,7 @@ int Camera::exportFrameBuffers(Stream *stream, return d->pipe_->invokeMethod(&PipelineHandler::exportFrameBuffers, ConnectionTypeBlocking, this, stream, - buffers); + count, buffers); } /** diff --git a/src/libcamera/framebuffer_allocator.cpp b/src/libcamera/framebuffer_allocator.cpp index 2fbba37a1b0b..92d121f8c4ac 100644 --- a/src/libcamera/framebuffer_allocator.cpp +++ b/src/libcamera/framebuffer_allocator.cpp @@ -70,6 +70,7 @@ FrameBufferAllocator::~FrameBufferAllocator() /** * \brief Allocate buffers for a configured stream * \param[in] stream The stream to allocate buffers for + * \param[in] count The amount 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 @@ -85,14 +86,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() diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 6067db2f37a3..c8fcc2fda75f 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -130,7 +130,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> *buffers) override; int start(Camera *camera, const ControlList *controls) override; @@ -641,10 +641,10 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) } int PipelineHandlerIPU3::exportFrameBuffers(Camera *camera, Stream *stream, + unsigned int count, std::vector> *buffers) { IPU3CameraData *data = cameraData(camera); - unsigned int count = stream->configuration().bufferCount; if (stream == &data->outStream_) return data->imgu_->output_->exportBuffers(count, buffers); diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 8d1ade3a4352..3f35596fe550 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -249,7 +249,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> *buffers) override; int start(Camera *camera, const ControlList *controls) override; @@ -786,10 +786,10 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config) } int PipelineHandlerRPi::exportFrameBuffers([[maybe_unused]] Camera *camera, Stream *stream, + unsigned int count, std::vector> *buffers) { RPi::Stream *s = static_cast(stream); - unsigned int count = stream->configuration().bufferCount; int ret = s->dev()->exportBuffers(count, buffers); s->setExportedBuffers(buffers); diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 7d876e9387d7..2d95c1ca2a43 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -140,7 +140,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> *buffers) override; int start(Camera *camera, const ControlList *controls) override; @@ -667,10 +667,10 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c) } int PipelineHandlerRkISP1::exportFrameBuffers([[maybe_unused]] Camera *camera, Stream *stream, + unsigned int count, std::vector> *buffers) { RkISP1CameraData *data = cameraData(camera); - unsigned int count = stream->configuration().bufferCount; if (stream == &data->mainPathStream_) return mainPath_.exportBuffers(count, buffers); diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 6ee24f2f14e8..b9f14be6733f 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -225,7 +225,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> *buffers) override; int start(Camera *camera, const ControlList *controls) override; @@ -764,10 +764,10 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) } int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream, + unsigned int count, std::vector> *buffers) { SimpleCameraData *data = cameraData(camera); - unsigned int count = stream->configuration().bufferCount; /* * Export buffers on the converter or capture video node, depending on diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index 591f46b60d23..a148c35f1265 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -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> *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> *buffers) { UVCCameraData *data = cameraData(camera); - unsigned int count = stream->configuration().bufferCount; return data->video_->exportBuffers(count, buffers); } diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp index 605b3fe89152..22d6fdcbb141 100644 --- a/src/libcamera/pipeline/vimc/vimc.cpp +++ b/src/libcamera/pipeline/vimc/vimc.cpp @@ -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> *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> *buffers) { VimcCameraData *data = cameraData(camera); - unsigned int count = stream->configuration().bufferCount; return data->video_->exportBuffers(count, buffers); } diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index 3b3150bdbbf7..cdd456c599a4 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -322,6 +322,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 amount of buffers to allocate * \param[out] buffers Array of buffers successfully allocated * * This method allocates buffers for the \a stream from the devices associated diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index 39d034de6bb2..d2ddd976584a 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include "dng_writer.h" @@ -463,7 +464,8 @@ int MainWindow::startCapture() for (StreamConfiguration &config : *config_) { Stream *stream = config.stream(); - ret = allocator_->allocate(stream); + int minBuffers = camera_->properties().get(properties::QueueDepth); + ret = allocator_->allocate(stream, minBuffers); if (ret < 0) { qWarning() << "Failed to allocate capture buffers"; goto error; diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index 97825c715bba..53d97f3e6b86 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -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; diff --git a/test/camera/capture.cpp b/test/camera/capture.cpp index c4bc21100777..24ffbd8b2f6f 100644 --- a/test/camera/capture.cpp +++ b/test/camera/capture.cpp @@ -8,6 +8,7 @@ #include #include +#include #include "libcamera/internal/event_dispatcher.h" #include "libcamera/internal/thread.h" @@ -96,7 +97,8 @@ protected: Stream *stream = cfg.stream(); - int ret = allocator_->allocate(stream); + int minBuffers = camera_->properties().get(properties::QueueDepth); + int ret = allocator_->allocate(stream, minBuffers); if (ret < 0) return TestFail; diff --git a/test/camera/statemachine.cpp b/test/camera/statemachine.cpp index f0c3d7764027..80caa897bcaa 100644 --- a/test/camera/statemachine.cpp +++ b/test/camera/statemachine.cpp @@ -8,6 +8,7 @@ #include #include +#include #include "camera_test.h" #include "test.h" @@ -118,7 +119,8 @@ protected: /* Use internally allocated buffers. */ allocator_ = new FrameBufferAllocator(camera_); Stream *stream = *camera_->streams().begin(); - if (allocator_->allocate(stream) < 0) + int minBuffers = camera_->properties().get(properties::QueueDepth); + if (allocator_->allocate(stream, minBuffers) < 0) return TestFail; if (camera_->start()) diff --git a/test/mapped-buffer.cpp b/test/mapped-buffer.cpp index 5de8201e45f6..7c0264157229 100644 --- a/test/mapped-buffer.cpp +++ b/test/mapped-buffer.cpp @@ -8,6 +8,7 @@ #include #include +#include #include "libcamera/internal/buffer.h" @@ -54,7 +55,8 @@ protected: stream_ = cfg.stream(); - int ret = allocator_->allocate(stream_); + int minBuffers = camera_->properties().get(properties::QueueDepth); + int ret = allocator_->allocate(stream_, minBuffers); if (ret < 0) return TestFail; From patchwork Wed Apr 21 16:51:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= X-Patchwork-Id: 12052 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id ABD5EBDB15 for ; Wed, 21 Apr 2021 16:52:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6A1DC68854; Wed, 21 Apr 2021 18:52:30 +0200 (CEST) Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id CD98468851 for ; Wed, 21 Apr 2021 18:52:27 +0200 (CEST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: nfraprado) with ESMTPSA id BD7BC1F423ED From: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= To: libcamera-devel@lists.libcamera.org Date: Wed, 21 Apr 2021 13:51:38 -0300 Message-Id: <20210421165139.318432-4-nfraprado@collabora.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210421165139.318432-1-nfraprado@collabora.com> References: <20210421165139.318432-1-nfraprado@collabora.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 3/4] lc-compliance: Add test to queue more requests than hardware depth X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Andr=C3=A9_Almeida?= , kernel@collabora.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" A pipeline handler should be able to handle an arbitrary amount of simultaneous requests by submitting what it can to the video device and queuing the rest internally until resources are available. This isn't currently done by some pipeline handlers however [1]. Add a new test to lc-compliance that submits a lot of requests at once to check if the pipeline handler is behaving well in this situation. [1] https://bugs.libcamera.org/show_bug.cgi?id=24 Signed-off-by: Nícolas F. R. A. Prado --- src/lc-compliance/simple_capture.cpp | 70 ++++++++++++++++++++++++++++ src/lc-compliance/simple_capture.h | 15 ++++++ src/lc-compliance/single_stream.cpp | 31 +++++++++++- 3 files changed, 115 insertions(+), 1 deletion(-) diff --git a/src/lc-compliance/simple_capture.cpp b/src/lc-compliance/simple_capture.cpp index 875772a80c27..01d76380e998 100644 --- a/src/lc-compliance/simple_capture.cpp +++ b/src/lc-compliance/simple_capture.cpp @@ -223,3 +223,73 @@ void SimpleCaptureUnbalanced::requestComplete(Request *request) if (camera_->queueRequest(request)) loop_->exit(-EINVAL); } + +SimpleCaptureOverflow::SimpleCaptureOverflow(std::shared_ptr camera) + : SimpleCapture(camera) +{ +} + +Results::Result SimpleCaptureOverflow::capture() +{ + Results::Result ret = start(); + if (ret.first != Results::Pass) + return ret; + + Stream *stream = config_->at(0).stream(); + const std::vector> &buffers = allocator_->buffers(stream); + + captureCount_ = 0; + captureLimit_ = buffers.size(); + + std::vector> requests; + for (const std::unique_ptr &buffer : buffers) { + std::unique_ptr request = camera_->createRequest(); + if (!request) { + stop(); + return { Results::Fail, "Can't create request" }; + } + + if (request->addBuffer(stream, buffer.get())) { + stop(); + return { Results::Fail, "Can't set buffer for request" }; + } + + if (camera_->queueRequest(request.get()) < 0) { + stop(); + return { Results::Fail, "Failed to queue request" }; + } + + requests.push_back(std::move(request)); + } + + /* Run capture session. */ + loop_ = new EventLoop(); + loop_->exec(); + stop(); + delete loop_; + + if (captureCount_ != captureLimit_) + return { Results::Fail, "Got " + std::to_string(captureCount_) + + " request, wanted " + std::to_string(captureLimit_) }; + + return { Results::Pass, "Overflow capture of " + + std::to_string(captureLimit_) + " requests" }; +} + +void SimpleCaptureOverflow::requestComplete([[maybe_unused]]Request *request) +{ + captureCount_++; + if (captureCount_ >= captureLimit_) { + loop_->exit(0); + return; + } +} + +Results::Result SimpleCaptureOverflow::allocateBuffers(unsigned int count) +{ + Stream *stream = config_->at(0).stream(); + if (allocator_->allocate(stream, count) < 0) + return { Results::Fail, "Failed to allocate buffers" }; + + return { Results::Pass, "Allocated buffers" }; +} diff --git a/src/lc-compliance/simple_capture.h b/src/lc-compliance/simple_capture.h index 82e2c56a55f1..cafcdafe10c2 100644 --- a/src/lc-compliance/simple_capture.h +++ b/src/lc-compliance/simple_capture.h @@ -66,4 +66,19 @@ private: unsigned int captureLimit_; }; +class SimpleCaptureOverflow : public SimpleCapture +{ +public: + SimpleCaptureOverflow(std::shared_ptr camera); + + Results::Result allocateBuffers(unsigned int count); + Results::Result capture(); + +private: + void requestComplete(libcamera::Request *request) override; + + unsigned int captureCount_; + unsigned int captureLimit_; +}; + #endif /* __LC_COMPLIANCE_SIMPLE_CAPTURE_H__ */ diff --git a/src/lc-compliance/single_stream.cpp b/src/lc-compliance/single_stream.cpp index 649291c7bb73..61979f66d92d 100644 --- a/src/lc-compliance/single_stream.cpp +++ b/src/lc-compliance/single_stream.cpp @@ -12,6 +12,23 @@ using namespace libcamera; +static const unsigned int MAX_SIMULTANEOUS_REQUESTS = 8; + +Results::Result testRequestOverflow(std::shared_ptr camera, + StreamRole role, unsigned int numRequests) +{ + SimpleCaptureOverflow capture(camera); + + Results::Result ret = capture.configure(role); + if (ret.first != Results::Pass) + return ret; + capture.allocateBuffers(numRequests); + if (ret.first != Results::Pass) + return ret; + + return capture.capture(); +} + Results::Result testRequestBalance(std::shared_ptr camera, StreamRole role, unsigned int startCycles, unsigned int numRequests) @@ -61,7 +78,7 @@ Results testSingleStream(std::shared_ptr camera) }; static const std::vector numRequests = { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 }; - Results results(numRequests.size() * roles.size() * 3); + Results results(numRequests.size() * roles.size() * 3 + roles.size() * 1); for (const auto &role : roles) { std::cout << "= Test role " << role.first << std::endl; @@ -97,6 +114,18 @@ Results testSingleStream(std::shared_ptr camera) std::cout << "* Test unbalanced stop" << std::endl; for (unsigned int num : numRequests) results.add(testRequestUnbalance(camera, role.second, num)); + + /* + * Test overflowing pipeline with requests + * + * Makes sure that the camera supports receiving a large amount + * of requests at once. Example failure is a camera that doesn't + * check if there are available resources (free internal + * buffers, free buffers in the video devices) before handling a + * request. + */ + std::cout << "* Test overflowing requests" << std::endl; + results.add(testRequestOverflow(camera, role.second, MAX_SIMULTANEOUS_REQUESTS)); } return results; From patchwork Wed Apr 21 16:51:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= X-Patchwork-Id: 12053 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id EC9F4BDB15 for ; Wed, 21 Apr 2021 16:52:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9B55668853; Wed, 21 Apr 2021 18:52:32 +0200 (CEST) Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 51ECE68840 for ; Wed, 21 Apr 2021 18:52:30 +0200 (CEST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: nfraprado) with ESMTPSA id 1BFEB1F423F1 From: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= To: libcamera-devel@lists.libcamera.org Date: Wed, 21 Apr 2021 13:51:39 -0300 Message-Id: <20210421165139.318432-5-nfraprado@collabora.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210421165139.318432-1-nfraprado@collabora.com> References: <20210421165139.318432-1-nfraprado@collabora.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 4/4] libcamera: stream: Remove bufferCount X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Andr=C3=A9_Almeida?= , kernel@collabora.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Now that the amount of internal buffers allocated is hardcoded by the pipelines, and the amount of buffers allocated by the FrameBufferAllocator helper is passed through FrameBufferAllocator::allocate(), we no longer need to have bufferCount in the StreamConfiguration, so remove it. Signed-off-by: Nícolas F. R. A. Prado --- include/libcamera/stream.h | 2 -- src/libcamera/pipeline/ipu3/cio2.cpp | 1 - src/libcamera/pipeline/ipu3/ipu3.cpp | 15 +-------------- .../pipeline/raspberrypi/raspberrypi.cpp | 9 ++------- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 9 ++------- src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 2 -- src/libcamera/pipeline/simple/converter.cpp | 7 ++----- src/libcamera/pipeline/simple/converter.h | 5 ++--- src/libcamera/pipeline/simple/simple.cpp | 15 ++++----------- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 5 +---- src/libcamera/pipeline/vimc/vimc.cpp | 5 +---- src/libcamera/stream.cpp | 9 ++------- src/v4l2/v4l2_camera.cpp | 14 ++++++++++---- src/v4l2/v4l2_camera.h | 5 +++-- src/v4l2/v4l2_camera_proxy.cpp | 8 +++----- test/camera/buffer_import.cpp | 10 +++++++--- test/libtest/buffer_source.cpp | 4 ++-- test/libtest/buffer_source.h | 2 +- test/v4l2_videodevice/buffer_cache.cpp | 4 ++-- 19 files changed, 45 insertions(+), 86 deletions(-) diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h index bb47c390f8a1..f36aeffd9540 100644 --- a/include/libcamera/stream.h +++ b/include/libcamera/stream.h @@ -45,8 +45,6 @@ struct StreamConfiguration { unsigned int stride; unsigned int frameSize; - unsigned int bufferCount; - Stream *stream() const { return stream_; } void setStream(Stream *stream) { stream_ = stream; } const StreamFormats &formats() const { return formats_; } diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp index 3cd777d1b742..1e110fe0c189 100644 --- a/src/libcamera/pipeline/ipu3/cio2.cpp +++ b/src/libcamera/pipeline/ipu3/cio2.cpp @@ -213,7 +213,6 @@ StreamConfiguration CIO2Device::generateConfiguration(Size size) const cfg.size = sensorFormat.size; cfg.pixelFormat = mbusCodesToPixelFormat.at(sensorFormat.mbus_code); - cfg.bufferCount = CIO2_BUFFER_COUNT; return cfg; } diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index c8fcc2fda75f..f0a17a553bd3 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -291,7 +291,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() /* Initialize the RAW stream with the CIO2 configuration. */ cfg->size = cio2Configuration_.size; cfg->pixelFormat = cio2Configuration_.pixelFormat; - cfg->bufferCount = cio2Configuration_.bufferCount; cfg->stride = info.stride(cfg->size.width, 0, 64); cfg->frameSize = info.frameSize(cfg->size, 64); cfg->setStream(const_cast(&data_->rawStream_)); @@ -335,7 +334,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() IMGU_OUTPUT_HEIGHT_ALIGN); cfg->pixelFormat = formats::NV12; - cfg->bufferCount = IPU3_BUFFER_COUNT; cfg->stride = info.stride(cfg->size.width, 0, 1); cfg->frameSize = info.frameSize(cfg->size, 1); @@ -403,7 +401,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, Size sensorResolution = data->cio2_.sensor()->resolution(); for (const StreamRole role : roles) { std::map> streamFormats; - unsigned int bufferCount; PixelFormat pixelFormat; Size size; @@ -424,7 +421,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, size.height = utils::alignDown(size.height - 1, IMGU_OUTPUT_HEIGHT_MARGIN); pixelFormat = formats::NV12; - bufferCount = IPU3_BUFFER_COUNT; streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } }; break; @@ -434,7 +430,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, data->cio2_.generateConfiguration(sensorResolution); pixelFormat = cio2Config.pixelFormat; size = cio2Config.size; - bufferCount = cio2Config.bufferCount; for (const PixelFormat &format : data->cio2_.formats()) streamFormats[format] = data->cio2_.sizes(); @@ -453,7 +448,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, .alignedDownTo(IMGU_OUTPUT_WIDTH_ALIGN, IMGU_OUTPUT_HEIGHT_ALIGN); pixelFormat = formats::NV12; - bufferCount = IPU3_BUFFER_COUNT; streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } }; break; @@ -470,7 +464,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, StreamConfiguration cfg(formats); cfg.size = size; cfg.pixelFormat = pixelFormat; - cfg.bufferCount = bufferCount; config->addConfiguration(cfg); } @@ -668,15 +661,9 @@ int PipelineHandlerIPU3::allocateBuffers(Camera *camera) { IPU3CameraData *data = cameraData(camera); ImgUDevice *imgu = data->imgu_; - unsigned int bufferCount; + unsigned int bufferCount = data->properties_.get(properties::QueueDepth); int ret; - bufferCount = std::max({ - data->outStream_.configuration().bufferCount, - data->vfStream_.configuration().bufferCount, - data->rawStream_.configuration().bufferCount, - }); - ret = imgu->allocateBuffers(bufferCount); if (ret < 0) return ret; diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 3f35596fe550..44a8a472ae4f 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -471,7 +471,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera, RPiCameraData *data = cameraData(camera); CameraConfiguration *config = new RPiCameraConfiguration(data); V4L2DeviceFormat sensorFormat; - unsigned int bufferCount; PixelFormat pixelFormat; V4L2VideoDevice::Formats fmts; Size size; @@ -489,7 +488,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera, sensorFormat = findBestMode(fmts, size); pixelFormat = sensorFormat.fourcc.toPixelFormat(); ASSERT(pixelFormat.isValid()); - bufferCount = 2; rawCount++; break; @@ -498,7 +496,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera, pixelFormat = formats::NV12; /* Return the largest sensor resolution. */ size = data->sensor_->resolution(); - bufferCount = 1; outCount++; break; @@ -514,7 +511,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera, fmts = data->isp_[Isp::Output0].dev()->formats(); pixelFormat = formats::YUV420; size = { 1920, 1080 }; - bufferCount = 4; outCount++; break; @@ -522,7 +518,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera, fmts = data->isp_[Isp::Output0].dev()->formats(); pixelFormat = formats::ARGB8888; size = { 800, 600 }; - bufferCount = 4; outCount++; break; @@ -552,7 +547,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera, StreamConfiguration cfg(formats); cfg.size = size; cfg.pixelFormat = pixelFormat; - cfg.bufferCount = bufferCount; config->addConfiguration(cfg); } @@ -1142,6 +1136,7 @@ int PipelineHandlerRPi::prepareBuffers(Camera *camera) { RPiCameraData *data = cameraData(camera); int ret; + unsigned int bufferCount = data->properties_.get(properties::QueueDepth); /* * Decide how many internal buffers to allocate. For now, simply look @@ -1152,7 +1147,7 @@ int PipelineHandlerRPi::prepareBuffers(Camera *camera) unsigned int maxBuffers = 0; for (const Stream *s : camera->streams()) if (static_cast(s)->isExternal()) - maxBuffers = std::max(maxBuffers, s->configuration().bufferCount); + maxBuffers = std::max(maxBuffers, bufferCount); for (auto const stream : data->streams_) { ret = stream->prepareBuffers(maxBuffers); diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 2d95c1ca2a43..73d4ea6ba8f5 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -686,16 +686,11 @@ int PipelineHandlerRkISP1::allocateBuffers(Camera *camera) unsigned int ipaBufferId = 1; int ret; - unsigned int maxCount = std::max({ - data->mainPathStream_.configuration().bufferCount, - data->selfPathStream_.configuration().bufferCount, - }); - - ret = param_->allocateBuffers(maxCount, ¶mBuffers_); + ret = param_->allocateBuffers(RKISP1_BUFFER_COUNT, ¶mBuffers_); if (ret < 0) goto error; - ret = stat_->allocateBuffers(maxCount, &statBuffers_); + ret = stat_->allocateBuffers(RKISP1_BUFFER_COUNT, &statBuffers_); if (ret < 0) goto error; diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp index 25f482eb8d8e..200e3c2c4cca 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp @@ -61,7 +61,6 @@ StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution) StreamConfiguration cfg(formats); cfg.pixelFormat = formats::NV12; cfg.size = maxResolution; - cfg.bufferCount = RKISP1_BUFFER_COUNT; return cfg; } @@ -77,7 +76,6 @@ CameraConfiguration::Status RkISP1Path::validate(StreamConfiguration *cfg) cfg->size.boundTo(maxResolution_); cfg->size.expandTo(minResolution_); - cfg->bufferCount = RKISP1_BUFFER_COUNT; V4L2DeviceFormat format; format.fourcc = video_->toV4L2PixelFormat(cfg->pixelFormat); diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp index 68644ef6477f..54e7f1b051f7 100644 --- a/src/libcamera/pipeline/simple/converter.cpp +++ b/src/libcamera/pipeline/simple/converter.cpp @@ -86,9 +86,6 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg, return -EINVAL; } - inputBufferCount_ = inputCfg.bufferCount; - outputBufferCount_ = outputCfg.bufferCount; - return 0; } @@ -100,11 +97,11 @@ int SimpleConverter::Stream::exportBuffers(unsigned int count, int SimpleConverter::Stream::start() { - int ret = m2m_->output()->importBuffers(inputBufferCount_); + int ret = m2m_->output()->importBuffers(SIMPLE_QUEUE_DEPTH); if (ret < 0) return ret; - ret = m2m_->capture()->importBuffers(outputBufferCount_); + ret = m2m_->capture()->importBuffers(SIMPLE_QUEUE_DEPTH); if (ret < 0) { stop(); return ret; diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h index 480e528d2210..32313748cd24 100644 --- a/src/libcamera/pipeline/simple/converter.h +++ b/src/libcamera/pipeline/simple/converter.h @@ -29,6 +29,8 @@ class SizeRange; struct StreamConfiguration; class V4L2M2MDevice; +constexpr unsigned int SIMPLE_QUEUE_DEPTH = 3; + class SimpleConverter { public: @@ -84,9 +86,6 @@ private: SimpleConverter *converter_; unsigned int index_; std::unique_ptr m2m_; - - unsigned int inputBufferCount_; - unsigned int outputBufferCount_; }; std::string deviceNode_; diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index b9f14be6733f..9f28bb66e2e7 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -142,8 +142,6 @@ static const SimplePipelineInfo supportedDevices[] = { } /* namespace */ -static constexpr unsigned int kNumInternalBuffers = 3; - class SimpleCameraData : public CameraData { public: @@ -425,7 +423,7 @@ int SimpleCameraData::init() } properties_ = sensor_->properties(); - properties_.set(properties::QueueDepth, kNumInternalBuffers); + properties_.set(properties::QueueDepth, SIMPLE_QUEUE_DEPTH); return 0; } @@ -616,7 +614,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() cfg.size != pipeConfig_->captureSize) needConversion_ = true; - /* Set the stride, frameSize and bufferCount. */ + /* Set the stride and frameSize. */ if (needConversion_) { std::tie(cfg.stride, cfg.frameSize) = converter->strideAndFrameSize(cfg.pixelFormat, cfg.size); @@ -634,8 +632,6 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() cfg.stride = format.planes[0].bpl; cfg.frameSize = format.planes[0].size; } - - cfg.bufferCount = 3; } return status; @@ -758,7 +754,6 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) inputCfg.pixelFormat = pipeConfig->captureFormat; inputCfg.size = pipeConfig->captureSize; inputCfg.stride = captureFormat.planes[0].bpl; - inputCfg.bufferCount = kNumInternalBuffers; return converter_->configure(inputCfg, outputCfgs); } @@ -791,12 +786,10 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL * When using the converter allocate a fixed number of internal * buffers. */ - ret = video->allocateBuffers(kNumInternalBuffers, + ret = video->allocateBuffers(SIMPLE_QUEUE_DEPTH, &data->converterBuffers_); } else { - /* Otherwise, prepare for using buffers from the only stream. */ - Stream *stream = &data->streams_[0]; - ret = video->importBuffers(stream->configuration().bufferCount); + ret = video->importBuffers(SIMPLE_QUEUE_DEPTH); } if (ret < 0) return ret; diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index a148c35f1265..94e6fd9d2d56 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -148,8 +148,6 @@ CameraConfiguration::Status UVCCameraConfiguration::validate() status = Adjusted; } - cfg.bufferCount = 4; - V4L2DeviceFormat format; format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat); format.size = cfg.size; @@ -191,7 +189,6 @@ CameraConfiguration *PipelineHandlerUVC::generateConfiguration(Camera *camera, cfg.pixelFormat = formats.pixelformats().front(); cfg.size = formats.sizes(cfg.pixelFormat).back(); - cfg.bufferCount = 4; config->addConfiguration(cfg); @@ -236,7 +233,7 @@ int PipelineHandlerUVC::exportFrameBuffers(Camera *camera, int PipelineHandlerUVC::start(Camera *camera, [[maybe_unused]] const ControlList *controls) { UVCCameraData *data = cameraData(camera); - unsigned int count = data->stream_.configuration().bufferCount; + unsigned int count = data->properties_.get(properties::QueueDepth); int ret = data->video_->importBuffers(count); if (ret < 0) diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp index 22d6fdcbb141..891571afb3e5 100644 --- a/src/libcamera/pipeline/vimc/vimc.cpp +++ b/src/libcamera/pipeline/vimc/vimc.cpp @@ -165,8 +165,6 @@ CameraConfiguration::Status VimcCameraConfiguration::validate() status = Adjusted; } - cfg.bufferCount = 4; - V4L2DeviceFormat format; format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat); format.size = cfg.size; @@ -222,7 +220,6 @@ CameraConfiguration *PipelineHandlerVimc::generateConfiguration(Camera *camera, cfg.pixelFormat = formats::BGR888; cfg.size = { 1920, 1080 }; - cfg.bufferCount = 4; config->addConfiguration(cfg); @@ -312,7 +309,7 @@ int PipelineHandlerVimc::exportFrameBuffers(Camera *camera, int PipelineHandlerVimc::start(Camera *camera, [[maybe_unused]] const ControlList *controls) { VimcCameraData *data = cameraData(camera); - unsigned int count = data->stream_.configuration().bufferCount; + unsigned int count = data->properties_.get(properties::QueueDepth); int ret = data->video_->importBuffers(count); if (ret < 0) diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp index f7bafcf8fc97..be57abce4eb3 100644 --- a/src/libcamera/stream.cpp +++ b/src/libcamera/stream.cpp @@ -279,7 +279,7 @@ SizeRange StreamFormats::range(const PixelFormat &pixelformat) const * handlers provide StreamFormats. */ StreamConfiguration::StreamConfiguration() - : pixelFormat(0), stride(0), frameSize(0), bufferCount(0), + : pixelFormat(0), stride(0), frameSize(0), stream_(nullptr) { } @@ -288,7 +288,7 @@ StreamConfiguration::StreamConfiguration() * \brief Construct a configuration with stream formats */ StreamConfiguration::StreamConfiguration(const StreamFormats &formats) - : pixelFormat(0), stride(0), frameSize(0), bufferCount(0), + : pixelFormat(0), stride(0), frameSize(0), stream_(nullptr), formats_(formats) { } @@ -323,11 +323,6 @@ StreamConfiguration::StreamConfiguration(const StreamFormats &formats) * validating the configuration with a call to CameraConfiguration::validate(). */ -/** - * \var StreamConfiguration::bufferCount - * \brief Requested number of buffers to allocate for the stream - */ - /** * \fn StreamConfiguration::stream() * \brief Retrieve the stream associated with the configuration diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index 53d97f3e6b86..79bf7aec7782 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -10,6 +10,8 @@ #include #include +#include + #include "libcamera/internal/log.h" using namespace libcamera; @@ -107,14 +109,12 @@ void V4L2Camera::requestComplete(Request *request) } int V4L2Camera::configure(StreamConfiguration *streamConfigOut, - const Size &size, const PixelFormat &pixelformat, - unsigned int bufferCount) + const Size &size, const PixelFormat &pixelformat) { StreamConfiguration &streamConfig = config_->at(0); streamConfig.size.width = size.width; streamConfig.size.height = size.height; streamConfig.pixelFormat = pixelformat; - streamConfig.bufferCount = bufferCount; /* \todo memoryType (interval vs external) */ CameraConfiguration::Status validation = config_->validate(); @@ -146,7 +146,6 @@ int V4L2Camera::validateConfiguration(const PixelFormat &pixelFormat, StreamConfiguration &cfg = config->at(0); cfg.size = size; cfg.pixelFormat = pixelFormat; - cfg.bufferCount = 1; CameraConfiguration::Status validation = config->validate(); if (validation == CameraConfiguration::Invalid) @@ -299,3 +298,10 @@ bool V4L2Camera::isRunning() { return isRunning_; } + +int V4L2Camera::getBufCount(int count) +{ + int min = camera_->properties().get(properties::QueueDepth); + + return std::max(count, min); +} diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h index d238046250e3..68df8ad05917 100644 --- a/src/v4l2/v4l2_camera.h +++ b/src/v4l2/v4l2_camera.h @@ -45,8 +45,7 @@ public: std::vector completedBuffers(); int configure(StreamConfiguration *streamConfigOut, - const Size &size, const PixelFormat &pixelformat, - unsigned int bufferCount); + const Size &size, const PixelFormat &pixelformat); int validateConfiguration(const PixelFormat &pixelformat, const Size &size, StreamConfiguration *streamConfigOut); @@ -65,6 +64,8 @@ public: bool isRunning(); + int getBufCount(int count); + private: void requestComplete(Request *request); diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index f8bfe595e90e..cd32e44a01ad 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -348,8 +348,7 @@ int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg) Size size(arg->fmt.pix.width, arg->fmt.pix.height); V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->fmt.pix.pixelformat); ret = vcam_->configure(&streamConfig_, size, - PixelFormatInfo::info(v4l2Format).format, - bufferCount_); + PixelFormatInfo::info(v4l2Format).format); if (ret < 0) return -EINVAL; @@ -490,14 +489,13 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf Size size(v4l2PixFormat_.width, v4l2PixFormat_.height); V4L2PixelFormat v4l2Format = V4L2PixelFormat(v4l2PixFormat_.pixelformat); int ret = vcam_->configure(&streamConfig_, size, - PixelFormatInfo::info(v4l2Format).format, - arg->count); + PixelFormatInfo::info(v4l2Format).format); if (ret < 0) return -EINVAL; setFmtFromConfig(streamConfig_); - arg->count = streamConfig_.bufferCount; + arg->count = vcam_->getBufCount(arg->count); bufferCount_ = arg->count; ret = vcam_->allocBuffers(arg->count); diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp index 61f4eb92ae95..f2c38bfb0b72 100644 --- a/test/camera/buffer_import.cpp +++ b/test/camera/buffer_import.cpp @@ -12,6 +12,8 @@ #include #include +#include + #include "libcamera/internal/device_enumerator.h" #include "libcamera/internal/event_dispatcher.h" #include "libcamera/internal/media_device.h" @@ -91,10 +93,12 @@ protected: return TestFail; } + unsigned int bufCount = camera_->properties().get(properties::QueueDepth); + Stream *stream = cfg.stream(); BufferSource source; - int ret = source.allocate(cfg); + int ret = source.allocate(cfg, bufCount); if (ret != TestPass) return ret; @@ -138,10 +142,10 @@ protected: while (timer.isRunning()) dispatcher->processEvents(); - if (completeRequestsCount_ < cfg.bufferCount * 2) { + if (completeRequestsCount_ < bufCount * 2) { std::cout << "Failed to capture enough frames (got " << completeRequestsCount_ << " expected at least " - << cfg.bufferCount * 2 << ")" << std::endl; + << bufCount * 2 << ")" << std::endl; return TestFail; } diff --git a/test/libtest/buffer_source.cpp b/test/libtest/buffer_source.cpp index 73563f2fc39d..c3d5286a2462 100644 --- a/test/libtest/buffer_source.cpp +++ b/test/libtest/buffer_source.cpp @@ -24,7 +24,7 @@ BufferSource::~BufferSource() media_->release(); } -int BufferSource::allocate(const StreamConfiguration &config) +int BufferSource::allocate(const StreamConfiguration &config, unsigned int count) { /* Locate and open the video device. */ std::string videoDeviceName = "vivid-000-vid-out"; @@ -77,7 +77,7 @@ int BufferSource::allocate(const StreamConfiguration &config) return TestFail; } - if (video->allocateBuffers(config.bufferCount, &buffers_) < 0) { + if (video->allocateBuffers(count, &buffers_) < 0) { std::cout << "Failed to allocate buffers" << std::endl; return TestFail; } diff --git a/test/libtest/buffer_source.h b/test/libtest/buffer_source.h index 14b4770e8d8a..6a18e269a575 100644 --- a/test/libtest/buffer_source.h +++ b/test/libtest/buffer_source.h @@ -20,7 +20,7 @@ public: BufferSource(); ~BufferSource(); - int allocate(const StreamConfiguration &config); + int allocate(const StreamConfiguration &config, unsigned int count); const std::vector> &buffers(); private: diff --git a/test/v4l2_videodevice/buffer_cache.cpp b/test/v4l2_videodevice/buffer_cache.cpp index b3f2bec11783..07fddfd2617c 100644 --- a/test/v4l2_videodevice/buffer_cache.cpp +++ b/test/v4l2_videodevice/buffer_cache.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include "buffer_source.h" @@ -145,10 +146,9 @@ public: StreamConfiguration cfg; cfg.pixelFormat = formats::YUYV; cfg.size = Size(600, 800); - cfg.bufferCount = numBuffers; BufferSource source; - int ret = source.allocate(cfg); + int ret = source.allocate(cfg, numBuffers); if (ret != TestPass) return ret;