[{"id":18278,"web_url":"https://patchwork.libcamera.org/comment/18278/","msgid":"<CAHW6GYJbVdFebNca9ZeM8LY=Ca4P1uaUd3B-r5FF7mJ9k853fg@mail.gmail.com>","date":"2021-07-23T08:42:56","subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","submitter":{"id":42,"url":"https://patchwork.libcamera.org/api/people/42/","name":"David Plowman","email":"david.plowman@raspberrypi.com"},"content":"Hi Nicolas\n\nThanks very much for all this work! I was wondering if I could ask a\nlittle more about this patch. In our applications, for example, we set\nthe bufferCount according to the use-case that the application is\nimplementing. For example:\n\n* For preview windows we set bufferCount to 4.\n* For video capture we drop fewer frames with a deeper queue so we set it to 6.\n* For stills capture we can get by with one frame, though use cases\nthat capture several stills images for fusion work better if we set\nbufferCount to 2 or 3.\n\nI was wondering how our applications can achieve this behaviour if the\nbufferCount field is no longer available.\n\nThanks!\nDavid\n\nOn Fri, 23 Jul 2021 at 00:29, Nícolas F. R. A. Prado\n<nfraprado@collabora.com> wrote:\n>\n> Now that the number of buffers allocated by the FrameBufferAllocator\n> helper is passed through FrameBufferAllocator::allocate() and the\n> pipelines no longer use bufferCount for internal buffer or V4L2 buffer\n> slots allocation, we no longer need to have bufferCount in the\n> StreamConfiguration, so remove it.\n>\n> Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>\n> ---\n>\n> No changes in v7\n>\n> Changes in v6:\n> - Removed IPU3_BUFFER_COUNT as it was unused\n>\n>  include/libcamera/stream.h                         |  2 --\n>  src/android/camera_stream.cpp                      |  2 +-\n>  src/libcamera/pipeline/ipu3/cio2.cpp               |  1 -\n>  src/libcamera/pipeline/ipu3/ipu3.cpp               |  8 --------\n>  src/libcamera/pipeline/raspberrypi/raspberrypi.cpp |  6 ------\n>  src/libcamera/pipeline/rkisp1/rkisp1_path.cpp      |  2 --\n>  src/libcamera/pipeline/simple/converter.cpp        |  3 ---\n>  src/libcamera/pipeline/simple/converter.h          |  3 ---\n>  src/libcamera/pipeline/simple/simple.cpp           |  5 +----\n>  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp       |  3 ---\n>  src/libcamera/pipeline/vimc/vimc.cpp               |  3 ---\n>  src/libcamera/stream.cpp                           |  9 ++-------\n>  src/v4l2/v4l2_camera.cpp                           | 14 ++++++++++----\n>  src/v4l2/v4l2_camera.h                             |  5 +++--\n>  src/v4l2/v4l2_camera_proxy.cpp                     |  8 +++-----\n>  test/camera/buffer_import.cpp                      | 10 +++++++---\n>  test/libtest/buffer_source.cpp                     |  4 ++--\n>  test/libtest/buffer_source.h                       |  2 +-\n>  test/v4l2_videodevice/buffer_cache.cpp             |  4 ++--\n>  19 files changed, 32 insertions(+), 62 deletions(-)\n>\n> diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\n> index 0c55e7164592..b25f0059f2f1 100644\n> --- a/include/libcamera/stream.h\n> +++ b/include/libcamera/stream.h\n> @@ -45,8 +45,6 @@ struct StreamConfiguration {\n>         unsigned int stride;\n>         unsigned int frameSize;\n>\n> -       unsigned int bufferCount;\n> -\n>         Stream *stream() const { return stream_; }\n>         void setStream(Stream *stream) { stream_ = stream; }\n>         const StreamFormats &formats() const { return formats_; }\n> diff --git a/src/android/camera_stream.cpp b/src/android/camera_stream.cpp\n> index b168e3c0c288..0794be409f82 100644\n> --- a/src/android/camera_stream.cpp\n> +++ b/src/android/camera_stream.cpp\n> @@ -94,7 +94,7 @@ int CameraStream::configure()\n>                         buffers_.push_back(frameBuffer.get());\n>         }\n>\n> -       camera3Stream_->max_buffers = configuration().bufferCount;\n> +       camera3Stream_->max_buffers = bufferCount;\n>\n>         return 0;\n>  }\n> diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp\n> index 1bcd580e251c..0e04e7214489 100644\n> --- a/src/libcamera/pipeline/ipu3/cio2.cpp\n> +++ b/src/libcamera/pipeline/ipu3/cio2.cpp\n> @@ -214,7 +214,6 @@ StreamConfiguration CIO2Device::generateConfiguration(Size size) const\n>\n>         cfg.size = sensorFormat.size;\n>         cfg.pixelFormat = mbusCodesToPixelFormat.at(sensorFormat.mbus_code);\n> -       cfg.bufferCount = CIO2_BUFFER_COUNT;\n>\n>         return cfg;\n>  }\n> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> index 4efd201c05e5..b223b3f33cd0 100644\n> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> @@ -38,7 +38,6 @@ namespace libcamera {\n>\n>  LOG_DEFINE_CATEGORY(IPU3)\n>\n> -static constexpr unsigned int IPU3_BUFFER_COUNT = 4;\n>  static constexpr unsigned int IPU3_MAX_STREAMS = 3;\n>  static const Size IMGU_OUTPUT_MIN_SIZE = { 2, 2 };\n>  static const Size IMGU_OUTPUT_MAX_SIZE = { 4480, 34004 };\n> @@ -295,7 +294,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n>                         /* Initialize the RAW stream with the CIO2 configuration. */\n>                         cfg->size = cio2Configuration_.size;\n>                         cfg->pixelFormat = cio2Configuration_.pixelFormat;\n> -                       cfg->bufferCount = cio2Configuration_.bufferCount;\n>                         cfg->stride = info.stride(cfg->size.width, 0, 64);\n>                         cfg->frameSize = info.frameSize(cfg->size, 64);\n>                         cfg->setStream(const_cast<Stream *>(&data_->rawStream_));\n> @@ -339,7 +337,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n>                                               IMGU_OUTPUT_HEIGHT_ALIGN);\n>\n>                         cfg->pixelFormat = formats::NV12;\n> -                       cfg->bufferCount = IPU3_BUFFER_COUNT;\n>                         cfg->stride = info.stride(cfg->size.width, 0, 1);\n>                         cfg->frameSize = info.frameSize(cfg->size, 1);\n>\n> @@ -407,7 +404,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n>         Size sensorResolution = data->cio2_.sensor()->resolution();\n>         for (const StreamRole role : roles) {\n>                 std::map<PixelFormat, std::vector<SizeRange>> streamFormats;\n> -               unsigned int bufferCount;\n>                 PixelFormat pixelFormat;\n>                 Size size;\n>\n> @@ -428,7 +424,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n>                         size.height = utils::alignDown(size.height - 1,\n>                                                        IMGU_OUTPUT_HEIGHT_MARGIN);\n>                         pixelFormat = formats::NV12;\n> -                       bufferCount = IPU3_BUFFER_COUNT;\n>                         streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n>\n>                         break;\n> @@ -438,7 +433,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n>                                 data->cio2_.generateConfiguration(sensorResolution);\n>                         pixelFormat = cio2Config.pixelFormat;\n>                         size = cio2Config.size;\n> -                       bufferCount = cio2Config.bufferCount;\n>\n>                         for (const PixelFormat &format : data->cio2_.formats())\n>                                 streamFormats[format] = data->cio2_.sizes();\n> @@ -457,7 +451,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n>                                                .alignedDownTo(IMGU_OUTPUT_WIDTH_ALIGN,\n>                                                               IMGU_OUTPUT_HEIGHT_ALIGN);\n>                         pixelFormat = formats::NV12;\n> -                       bufferCount = IPU3_BUFFER_COUNT;\n>                         streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n>\n>                         break;\n> @@ -474,7 +467,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n>                 StreamConfiguration cfg(formats);\n>                 cfg.size = size;\n>                 cfg.pixelFormat = pixelFormat;\n> -               cfg.bufferCount = bufferCount;\n>                 config->addConfiguration(cfg);\n>         }\n>\n> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> index 776e0f92aed1..e6fc0425c3ef 100644\n> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> @@ -473,7 +473,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n>         RPiCameraData *data = cameraData(camera);\n>         CameraConfiguration *config = new RPiCameraConfiguration(data);\n>         V4L2DeviceFormat sensorFormat;\n> -       unsigned int bufferCount;\n>         PixelFormat pixelFormat;\n>         V4L2VideoDevice::Formats fmts;\n>         Size size;\n> @@ -491,7 +490,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n>                         sensorFormat = findBestMode(fmts, size);\n>                         pixelFormat = sensorFormat.fourcc.toPixelFormat();\n>                         ASSERT(pixelFormat.isValid());\n> -                       bufferCount = 2;\n>                         rawCount++;\n>                         break;\n>\n> @@ -500,7 +498,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n>                         pixelFormat = formats::NV12;\n>                         /* Return the largest sensor resolution. */\n>                         size = data->sensor_->resolution();\n> -                       bufferCount = 1;\n>                         outCount++;\n>                         break;\n>\n> @@ -516,7 +513,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n>                         fmts = data->isp_[Isp::Output0].dev()->formats();\n>                         pixelFormat = formats::YUV420;\n>                         size = { 1920, 1080 };\n> -                       bufferCount = 4;\n>                         outCount++;\n>                         break;\n>\n> @@ -524,7 +520,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n>                         fmts = data->isp_[Isp::Output0].dev()->formats();\n>                         pixelFormat = formats::ARGB8888;\n>                         size = { 800, 600 };\n> -                       bufferCount = 4;\n>                         outCount++;\n>                         break;\n>\n> @@ -554,7 +549,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n>                 StreamConfiguration cfg(formats);\n>                 cfg.size = size;\n>                 cfg.pixelFormat = pixelFormat;\n> -               cfg.bufferCount = bufferCount;\n>                 config->addConfiguration(cfg);\n>         }\n>\n> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> index fea330f72886..4961f3971e59 100644\n> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> @@ -61,7 +61,6 @@ StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution)\n>         StreamConfiguration cfg(formats);\n>         cfg.pixelFormat = formats::NV12;\n>         cfg.size = maxResolution;\n> -       cfg.bufferCount = RKISP1_BUFFER_COUNT;\n>\n>         return cfg;\n>  }\n> @@ -77,7 +76,6 @@ CameraConfiguration::Status RkISP1Path::validate(StreamConfiguration *cfg)\n>\n>         cfg->size.boundTo(maxResolution_);\n>         cfg->size.expandTo(minResolution_);\n> -       cfg->bufferCount = RKISP1_BUFFER_COUNT;\n>\n>         V4L2DeviceFormat format;\n>         format.fourcc = video_->toV4L2PixelFormat(cfg->pixelFormat);\n> diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp\n> index b3bcf01483f7..fda417793e80 100644\n> --- a/src/libcamera/pipeline/simple/converter.cpp\n> +++ b/src/libcamera/pipeline/simple/converter.cpp\n> @@ -89,9 +89,6 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg,\n>                 return -EINVAL;\n>         }\n>\n> -       inputBufferCount_ = inputCfg.bufferCount;\n> -       outputBufferCount_ = outputCfg.bufferCount;\n> -\n>         return 0;\n>  }\n>\n> diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h\n> index 7e1d60674f62..406e63ca2a80 100644\n> --- a/src/libcamera/pipeline/simple/converter.h\n> +++ b/src/libcamera/pipeline/simple/converter.h\n> @@ -87,9 +87,6 @@ private:\n>                 SimpleConverter *converter_;\n>                 unsigned int index_;\n>                 std::unique_ptr<V4L2M2MDevice> m2m_;\n> -\n> -               unsigned int inputBufferCount_;\n> -               unsigned int outputBufferCount_;\n>         };\n>\n>         std::string deviceNode_;\n> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\n> index a1163eaf8be2..ded04914f610 100644\n> --- a/src/libcamera/pipeline/simple/simple.cpp\n> +++ b/src/libcamera/pipeline/simple/simple.cpp\n> @@ -628,7 +628,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n>                     cfg.size != pipeConfig_->captureSize)\n>                         needConversion_ = true;\n>\n> -               /* Set the stride, frameSize and bufferCount. */\n> +               /* Set the stride and frameSize. */\n>                 if (needConversion_) {\n>                         std::tie(cfg.stride, cfg.frameSize) =\n>                                 converter->strideAndFrameSize(cfg.pixelFormat, cfg.size);\n> @@ -646,8 +646,6 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n>                         cfg.stride = format.planes[0].bpl;\n>                         cfg.frameSize = format.planes[0].size;\n>                 }\n> -\n> -               cfg.bufferCount = 3;\n>         }\n>\n>         return status;\n> @@ -770,7 +768,6 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)\n>         inputCfg.pixelFormat = pipeConfig->captureFormat;\n>         inputCfg.size = pipeConfig->captureSize;\n>         inputCfg.stride = captureFormat.planes[0].bpl;\n> -       inputCfg.bufferCount = kNumInternalBuffers;\n>\n>         return converter_->configure(inputCfg, outputCfgs);\n>  }\n> diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> index 755949e7a59a..32482300f09a 100644\n> --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> @@ -150,8 +150,6 @@ CameraConfiguration::Status UVCCameraConfiguration::validate()\n>                 status = Adjusted;\n>         }\n>\n> -       cfg.bufferCount = 4;\n> -\n>         V4L2DeviceFormat format;\n>         format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n>         format.size = cfg.size;\n> @@ -193,7 +191,6 @@ CameraConfiguration *PipelineHandlerUVC::generateConfiguration(Camera *camera,\n>\n>         cfg.pixelFormat = formats.pixelformats().front();\n>         cfg.size = formats.sizes(cfg.pixelFormat).back();\n> -       cfg.bufferCount = 4;\n>\n>         config->addConfiguration(cfg);\n>\n> diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp\n> index 24ba743a946c..a698427c4361 100644\n> --- a/src/libcamera/pipeline/vimc/vimc.cpp\n> +++ b/src/libcamera/pipeline/vimc/vimc.cpp\n> @@ -167,8 +167,6 @@ CameraConfiguration::Status VimcCameraConfiguration::validate()\n>                 status = Adjusted;\n>         }\n>\n> -       cfg.bufferCount = 4;\n> -\n>         V4L2DeviceFormat format;\n>         format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n>         format.size = cfg.size;\n> @@ -224,7 +222,6 @@ CameraConfiguration *PipelineHandlerVimc::generateConfiguration(Camera *camera,\n>\n>         cfg.pixelFormat = formats::BGR888;\n>         cfg.size = { 1920, 1080 };\n> -       cfg.bufferCount = 4;\n>\n>         config->addConfiguration(cfg);\n>\n> diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp\n> index b8626775d224..ca507b72b26a 100644\n> --- a/src/libcamera/stream.cpp\n> +++ b/src/libcamera/stream.cpp\n> @@ -280,7 +280,7 @@ SizeRange StreamFormats::range(const PixelFormat &pixelformat) const\n>   * handlers provide StreamFormats.\n>   */\n>  StreamConfiguration::StreamConfiguration()\n> -       : pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> +       : pixelFormat(0), stride(0), frameSize(0),\n>           stream_(nullptr)\n>  {\n>  }\n> @@ -289,7 +289,7 @@ StreamConfiguration::StreamConfiguration()\n>   * \\brief Construct a configuration with stream formats\n>   */\n>  StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n> -       : pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> +       : pixelFormat(0), stride(0), frameSize(0),\n>           stream_(nullptr), formats_(formats)\n>  {\n>  }\n> @@ -324,11 +324,6 @@ StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n>   * validating the configuration with a call to CameraConfiguration::validate().\n>   */\n>\n> -/**\n> - * \\var StreamConfiguration::bufferCount\n> - * \\brief Requested number of buffers to allocate for the stream\n> - */\n> -\n>  /**\n>   * \\fn StreamConfiguration::stream()\n>   * \\brief Retrieve the stream associated with the configuration\n> diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp\n> index d01eacfa2b84..2ff9affc6388 100644\n> --- a/src/v4l2/v4l2_camera.cpp\n> +++ b/src/v4l2/v4l2_camera.cpp\n> @@ -12,6 +12,8 @@\n>\n>  #include <libcamera/base/log.h>\n>\n> +#include <libcamera/property_ids.h>\n> +\n>  using namespace libcamera;\n>\n>  LOG_DECLARE_CATEGORY(V4L2Compat)\n> @@ -107,14 +109,12 @@ void V4L2Camera::requestComplete(Request *request)\n>  }\n>\n>  int V4L2Camera::configure(StreamConfiguration *streamConfigOut,\n> -                         const Size &size, const PixelFormat &pixelformat,\n> -                         unsigned int bufferCount)\n> +                         const Size &size, const PixelFormat &pixelformat)\n>  {\n>         StreamConfiguration &streamConfig = config_->at(0);\n>         streamConfig.size.width = size.width;\n>         streamConfig.size.height = size.height;\n>         streamConfig.pixelFormat = pixelformat;\n> -       streamConfig.bufferCount = bufferCount;\n>         /* \\todo memoryType (interval vs external) */\n>\n>         CameraConfiguration::Status validation = config_->validate();\n> @@ -146,7 +146,6 @@ int V4L2Camera::validateConfiguration(const PixelFormat &pixelFormat,\n>         StreamConfiguration &cfg = config->at(0);\n>         cfg.size = size;\n>         cfg.pixelFormat = pixelFormat;\n> -       cfg.bufferCount = 1;\n>\n>         CameraConfiguration::Status validation = config->validate();\n>         if (validation == CameraConfiguration::Invalid)\n> @@ -299,3 +298,10 @@ bool V4L2Camera::isRunning()\n>  {\n>         return isRunning_;\n>  }\n> +\n> +unsigned int V4L2Camera::minimumRequests(unsigned int count)\n> +{\n> +       unsigned int min = camera_->properties().get(properties::MinimumRequests);\n> +\n> +       return std::max(count, min);\n> +}\n> diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h\n> index a095f4e27524..4b5618ac12b5 100644\n> --- a/src/v4l2/v4l2_camera.h\n> +++ b/src/v4l2/v4l2_camera.h\n> @@ -45,8 +45,7 @@ public:\n>         std::vector<Buffer> completedBuffers();\n>\n>         int configure(StreamConfiguration *streamConfigOut,\n> -                     const Size &size, const PixelFormat &pixelformat,\n> -                     unsigned int bufferCount);\n> +                     const Size &size, const PixelFormat &pixelformat);\n>         int validateConfiguration(const PixelFormat &pixelformat,\n>                                   const Size &size,\n>                                   StreamConfiguration *streamConfigOut);\n> @@ -65,6 +64,8 @@ public:\n>\n>         bool isRunning();\n>\n> +       unsigned int minimumRequests(unsigned int count);\n> +\n>  private:\n>         void requestComplete(Request *request);\n>\n> diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp\n> index 7682c4bddf90..634ec84e0cbb 100644\n> --- a/src/v4l2/v4l2_camera_proxy.cpp\n> +++ b/src/v4l2/v4l2_camera_proxy.cpp\n> @@ -349,8 +349,7 @@ int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg)\n>         Size size(arg->fmt.pix.width, arg->fmt.pix.height);\n>         V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->fmt.pix.pixelformat);\n>         ret = vcam_->configure(&streamConfig_, size,\n> -                              PixelFormatInfo::info(v4l2Format).format,\n> -                              bufferCount_);\n> +                              PixelFormatInfo::info(v4l2Format).format);\n>         if (ret < 0)\n>                 return -EINVAL;\n>\n> @@ -491,14 +490,13 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf\n>         Size size(v4l2PixFormat_.width, v4l2PixFormat_.height);\n>         V4L2PixelFormat v4l2Format = V4L2PixelFormat(v4l2PixFormat_.pixelformat);\n>         int ret = vcam_->configure(&streamConfig_, size,\n> -                                  PixelFormatInfo::info(v4l2Format).format,\n> -                                  arg->count);\n> +                                  PixelFormatInfo::info(v4l2Format).format);\n>         if (ret < 0)\n>                 return -EINVAL;\n>\n>         setFmtFromConfig(streamConfig_);\n>\n> -       arg->count = streamConfig_.bufferCount;\n> +       arg->count = vcam_->minimumRequests(arg->count);\n>         bufferCount_ = arg->count;\n>\n>         ret = vcam_->allocBuffers(arg->count);\n> diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp\n> index c504ea09e64b..67ac0ad20e15 100644\n> --- a/test/camera/buffer_import.cpp\n> +++ b/test/camera/buffer_import.cpp\n> @@ -16,6 +16,8 @@\n>  #include <libcamera/base/thread.h>\n>  #include <libcamera/base/timer.h>\n>\n> +#include <libcamera/property_ids.h>\n> +\n>  #include \"libcamera/internal/device_enumerator.h\"\n>  #include \"libcamera/internal/media_device.h\"\n>  #include \"libcamera/internal/v4l2_videodevice.h\"\n> @@ -92,10 +94,12 @@ protected:\n>                         return TestFail;\n>                 }\n>\n> +               unsigned int bufferCount = camera_->properties().get(properties::MinimumRequests);\n> +\n>                 Stream *stream = cfg.stream();\n>\n>                 BufferSource source;\n> -               int ret = source.allocate(cfg);\n> +               int ret = source.allocate(cfg, bufferCount);\n>                 if (ret != TestPass)\n>                         return ret;\n>\n> @@ -139,10 +143,10 @@ protected:\n>                 while (timer.isRunning())\n>                         dispatcher->processEvents();\n>\n> -               if (completeRequestsCount_ < cfg.bufferCount * 2) {\n> +               if (completeRequestsCount_ < bufferCount * 2) {\n>                         std::cout << \"Failed to capture enough frames (got \"\n>                                   << completeRequestsCount_ << \" expected at least \"\n> -                                 << cfg.bufferCount * 2 << \")\" << std::endl;\n> +                                 << bufferCount * 2 << \")\" << std::endl;\n>                         return TestFail;\n>                 }\n>\n> diff --git a/test/libtest/buffer_source.cpp b/test/libtest/buffer_source.cpp\n> index 73563f2fc39d..c3d5286a2462 100644\n> --- a/test/libtest/buffer_source.cpp\n> +++ b/test/libtest/buffer_source.cpp\n> @@ -24,7 +24,7 @@ BufferSource::~BufferSource()\n>                 media_->release();\n>  }\n>\n> -int BufferSource::allocate(const StreamConfiguration &config)\n> +int BufferSource::allocate(const StreamConfiguration &config, unsigned int count)\n>  {\n>         /* Locate and open the video device. */\n>         std::string videoDeviceName = \"vivid-000-vid-out\";\n> @@ -77,7 +77,7 @@ int BufferSource::allocate(const StreamConfiguration &config)\n>                 return TestFail;\n>         }\n>\n> -       if (video->allocateBuffers(config.bufferCount, &buffers_) < 0) {\n> +       if (video->allocateBuffers(count, &buffers_) < 0) {\n>                 std::cout << \"Failed to allocate buffers\" << std::endl;\n>                 return TestFail;\n>         }\n> diff --git a/test/libtest/buffer_source.h b/test/libtest/buffer_source.h\n> index 14b4770e8d8a..6a18e269a575 100644\n> --- a/test/libtest/buffer_source.h\n> +++ b/test/libtest/buffer_source.h\n> @@ -20,7 +20,7 @@ public:\n>         BufferSource();\n>         ~BufferSource();\n>\n> -       int allocate(const StreamConfiguration &config);\n> +       int allocate(const StreamConfiguration &config, unsigned int count);\n>         const std::vector<std::unique_ptr<FrameBuffer>> &buffers();\n>\n>  private:\n> diff --git a/test/v4l2_videodevice/buffer_cache.cpp b/test/v4l2_videodevice/buffer_cache.cpp\n> index b3f2bec11783..07fddfd2617c 100644\n> --- a/test/v4l2_videodevice/buffer_cache.cpp\n> +++ b/test/v4l2_videodevice/buffer_cache.cpp\n> @@ -10,6 +10,7 @@\n>  #include <vector>\n>\n>  #include <libcamera/formats.h>\n> +#include <libcamera/property_ids.h>\n>  #include <libcamera/stream.h>\n>\n>  #include \"buffer_source.h\"\n> @@ -145,10 +146,9 @@ public:\n>                 StreamConfiguration cfg;\n>                 cfg.pixelFormat = formats::YUYV;\n>                 cfg.size = Size(600, 800);\n> -               cfg.bufferCount = numBuffers;\n>\n>                 BufferSource source;\n> -               int ret = source.allocate(cfg);\n> +               int ret = source.allocate(cfg, numBuffers);\n>                 if (ret != TestPass)\n>                         return ret;\n>\n> --\n> 2.32.0\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id E0C92C0109\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 23 Jul 2021 08:43:09 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 48741687A6;\n\tFri, 23 Jul 2021 10:43:09 +0200 (CEST)","from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com\n\t[IPv6:2a00:1450:4864:20::32c])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4F8626853F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 23 Jul 2021 10:43:08 +0200 (CEST)","by mail-wm1-x32c.google.com with SMTP id\n\tj34-20020a05600c1c22b029024e75084404so185672wms.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 23 Jul 2021 01:43:08 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=raspberrypi.com header.i=@raspberrypi.com\n\theader.b=\"kkHEwYd6\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=mime-version:references:in-reply-to:from:date:message-id:subject:to\n\t:cc:content-transfer-encoding;\n\tbh=8oWjCW98IWa/vuc8WzpaRzmFZyHlOCtHo6TJ1cCAjFI=;\n\tb=kkHEwYd6/V0lI/oNExrkYDF/9xBQeQwWO3hikDvaz0F7zuZyIiNfT19s5fbQQiA884\n\tExq5Hpcq/FaiEuGxGKcLhAehmGKhEUxkbncqvDCZrURMhKZxRZ+UawoFS9nLwDEDXM8l\n\tuZtD8Xgb8Ifbv56WxnSz66J+Iim+hke5w711CEvqJ1WxKzWKrre1YSh2jBnU4t65CbTx\n\t18XDoxNSkEc+2rWqGVoYkMKMbk9mdEnXCIOspp2xlbqKkTJWr1EUjZ6WQ2YuTCXYshJD\n\tes+jFDMlUDcVjWYgZJqPJb2CuGYqKflIFtktQZmB9/KzPPpNezgC2uaMJKAWsvs+2JTF\n\tlKuw==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to:cc:content-transfer-encoding;\n\tbh=8oWjCW98IWa/vuc8WzpaRzmFZyHlOCtHo6TJ1cCAjFI=;\n\tb=GjynI2NlAUq9n8LD0K4xKDIB1wTUJUsSsvBLBJn66iepH2MbWwQXmFZ1/N8Alz9hNG\n\tehN9BxKKCq55BsJLB+TmWNni0ex+AFeUFAccUJwt29spnB+gTLHLlE9q1CU8CFFIbN7C\n\t73ZI3c6bJKpCySefwNU95WIGJ41g36HTWEeOrGZothxmmYKRoJ3mab4cCQanurW+ELjg\n\tsVFSU7iomsZz3hOw0cCPPi2o838LmlwoFyTIuv9Buhujr6p2XKNu655JpZ1SEXdLWYc5\n\tG/EiSIFzvwEcwExw4cGsJKATyf5ydizSGl2TIm0Qzz2QNDgTEji8Yakk09Wj0bgTrieW\n\t/UOQ==","X-Gm-Message-State":"AOAM530pPX1T931OaAQ1wbsm+8/dRP5VPz60xa5NL1jHEPNYEauu9/bC\n\tw949x/IoO7Pfqhr2jmRfHfEKwfCMbNr6TMaYmBHNGw==","X-Google-Smtp-Source":"ABdhPJxUUKZCHkHCeozsD9JGRpA7iYyghanSKqb8tjbas77KCSzfgoEBxPCbIRCn4W9jGRZSDowCPNkZGQYWuSy+7WA=","X-Received":"by 2002:a05:600c:1d04:: with SMTP id\n\tl4mr12975155wms.130.1627029787643; \n\tFri, 23 Jul 2021 01:43:07 -0700 (PDT)","MIME-Version":"1.0","References":"<20210722232851.747614-1-nfraprado@collabora.com>\n\t<20210722232851.747614-11-nfraprado@collabora.com>","In-Reply-To":"<20210722232851.747614-11-nfraprado@collabora.com>","From":"David Plowman <david.plowman@raspberrypi.com>","Date":"Fri, 23 Jul 2021 09:42:56 +0100","Message-ID":"<CAHW6GYJbVdFebNca9ZeM8LY=Ca4P1uaUd3B-r5FF7mJ9k853fg@mail.gmail.com>","To":"=?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= <nfraprado@collabora.com>","Content-Type":"text/plain; charset=\"UTF-8\"","Content-Transfer-Encoding":"quoted-printable","Subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>,\n\tkernel@collabora.com, =?utf-8?q?Andr=C3=A9_Almeida?=\n\t<andrealmeid@collabora.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":18285,"web_url":"https://patchwork.libcamera.org/comment/18285/","msgid":"<20210723131039.ire2z7u6sdxws3dt@notapiano>","date":"2021-07-23T13:10:39","subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","submitter":{"id":84,"url":"https://patchwork.libcamera.org/api/people/84/","name":"Nícolas F. R. A. Prado","email":"nfraprado@collabora.com"},"content":"Hi David,\n\nOn Fri, Jul 23, 2021 at 09:42:56AM +0100, David Plowman wrote:\n> Hi Nicolas\n> \n> Thanks very much for all this work! I was wondering if I could ask a\n> little more about this patch. In our applications, for example, we set\n> the bufferCount according to the use-case that the application is\n> implementing. For example:\n> \n> * For preview windows we set bufferCount to 4.\n> * For video capture we drop fewer frames with a deeper queue so we set it to 6.\n> * For stills capture we can get by with one frame, though use cases\n> that capture several stills images for fusion work better if we set\n> bufferCount to 2 or 3.\n> \n> I was wondering how our applications can achieve this behaviour if the\n> bufferCount field is no longer available.\n\nOkay, so the short answer is that the applications, knowing their particular use\ncase, are responsible to provide enough requests to keep the pipeline going. On\nthe pipeline handler side, it's free to use how many internal buffers it wants.\n\nSo in your case, the pipeline handler could still allocate that same number of\ninternal buffers as you previously did based on bufferCount, but now based\nsolely on the StreamRole set. The application would then allocate and queue\nhow many buffers fits the usage. (Note that before the application would call\nFrameBufferAllocator::allocate() and it would allocate 'bufferCount' buffers,\nbut now the function takes a count argument so the application is free to choose\nhow many) \n\nNow, I guess it would be nice for the application to be able to query what is a\ngood number of buffers to use, for example 6 in the video capture of your use\ncase. At the moment, the only information available is that 1 is the minimum\nnumber of buffers required. So the application would have to know that 6 is a\ngood number for video capture. Maybe another property could be introduced later\nfor this recommended amount, but previous discussions suggested this is very use\ncase dependent, so might not make sense.\n\nI hope this answers the question. If not, I'm still here :).\n\nThanks,\nNícolas\n\n> \n> Thanks!\n> David\n> \n> On Fri, 23 Jul 2021 at 00:29, Nícolas F. R. A. Prado\n> <nfraprado@collabora.com> wrote:\n> >\n> > Now that the number of buffers allocated by the FrameBufferAllocator\n> > helper is passed through FrameBufferAllocator::allocate() and the\n> > pipelines no longer use bufferCount for internal buffer or V4L2 buffer\n> > slots allocation, we no longer need to have bufferCount in the\n> > StreamConfiguration, so remove it.\n> >\n> > Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>\n> > ---\n> >\n> > No changes in v7\n> >\n> > Changes in v6:\n> > - Removed IPU3_BUFFER_COUNT as it was unused\n> >\n> >  include/libcamera/stream.h                         |  2 --\n> >  src/android/camera_stream.cpp                      |  2 +-\n> >  src/libcamera/pipeline/ipu3/cio2.cpp               |  1 -\n> >  src/libcamera/pipeline/ipu3/ipu3.cpp               |  8 --------\n> >  src/libcamera/pipeline/raspberrypi/raspberrypi.cpp |  6 ------\n> >  src/libcamera/pipeline/rkisp1/rkisp1_path.cpp      |  2 --\n> >  src/libcamera/pipeline/simple/converter.cpp        |  3 ---\n> >  src/libcamera/pipeline/simple/converter.h          |  3 ---\n> >  src/libcamera/pipeline/simple/simple.cpp           |  5 +----\n> >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp       |  3 ---\n> >  src/libcamera/pipeline/vimc/vimc.cpp               |  3 ---\n> >  src/libcamera/stream.cpp                           |  9 ++-------\n> >  src/v4l2/v4l2_camera.cpp                           | 14 ++++++++++----\n> >  src/v4l2/v4l2_camera.h                             |  5 +++--\n> >  src/v4l2/v4l2_camera_proxy.cpp                     |  8 +++-----\n> >  test/camera/buffer_import.cpp                      | 10 +++++++---\n> >  test/libtest/buffer_source.cpp                     |  4 ++--\n> >  test/libtest/buffer_source.h                       |  2 +-\n> >  test/v4l2_videodevice/buffer_cache.cpp             |  4 ++--\n> >  19 files changed, 32 insertions(+), 62 deletions(-)\n> >\n> > diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\n> > index 0c55e7164592..b25f0059f2f1 100644\n> > --- a/include/libcamera/stream.h\n> > +++ b/include/libcamera/stream.h\n> > @@ -45,8 +45,6 @@ struct StreamConfiguration {\n> >         unsigned int stride;\n> >         unsigned int frameSize;\n> >\n> > -       unsigned int bufferCount;\n> > -\n> >         Stream *stream() const { return stream_; }\n> >         void setStream(Stream *stream) { stream_ = stream; }\n> >         const StreamFormats &formats() const { return formats_; }\n> > diff --git a/src/android/camera_stream.cpp b/src/android/camera_stream.cpp\n> > index b168e3c0c288..0794be409f82 100644\n> > --- a/src/android/camera_stream.cpp\n> > +++ b/src/android/camera_stream.cpp\n> > @@ -94,7 +94,7 @@ int CameraStream::configure()\n> >                         buffers_.push_back(frameBuffer.get());\n> >         }\n> >\n> > -       camera3Stream_->max_buffers = configuration().bufferCount;\n> > +       camera3Stream_->max_buffers = bufferCount;\n> >\n> >         return 0;\n> >  }\n> > diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp\n> > index 1bcd580e251c..0e04e7214489 100644\n> > --- a/src/libcamera/pipeline/ipu3/cio2.cpp\n> > +++ b/src/libcamera/pipeline/ipu3/cio2.cpp\n> > @@ -214,7 +214,6 @@ StreamConfiguration CIO2Device::generateConfiguration(Size size) const\n> >\n> >         cfg.size = sensorFormat.size;\n> >         cfg.pixelFormat = mbusCodesToPixelFormat.at(sensorFormat.mbus_code);\n> > -       cfg.bufferCount = CIO2_BUFFER_COUNT;\n> >\n> >         return cfg;\n> >  }\n> > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > index 4efd201c05e5..b223b3f33cd0 100644\n> > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > @@ -38,7 +38,6 @@ namespace libcamera {\n> >\n> >  LOG_DEFINE_CATEGORY(IPU3)\n> >\n> > -static constexpr unsigned int IPU3_BUFFER_COUNT = 4;\n> >  static constexpr unsigned int IPU3_MAX_STREAMS = 3;\n> >  static const Size IMGU_OUTPUT_MIN_SIZE = { 2, 2 };\n> >  static const Size IMGU_OUTPUT_MAX_SIZE = { 4480, 34004 };\n> > @@ -295,7 +294,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n> >                         /* Initialize the RAW stream with the CIO2 configuration. */\n> >                         cfg->size = cio2Configuration_.size;\n> >                         cfg->pixelFormat = cio2Configuration_.pixelFormat;\n> > -                       cfg->bufferCount = cio2Configuration_.bufferCount;\n> >                         cfg->stride = info.stride(cfg->size.width, 0, 64);\n> >                         cfg->frameSize = info.frameSize(cfg->size, 64);\n> >                         cfg->setStream(const_cast<Stream *>(&data_->rawStream_));\n> > @@ -339,7 +337,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n> >                                               IMGU_OUTPUT_HEIGHT_ALIGN);\n> >\n> >                         cfg->pixelFormat = formats::NV12;\n> > -                       cfg->bufferCount = IPU3_BUFFER_COUNT;\n> >                         cfg->stride = info.stride(cfg->size.width, 0, 1);\n> >                         cfg->frameSize = info.frameSize(cfg->size, 1);\n> >\n> > @@ -407,7 +404,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> >         Size sensorResolution = data->cio2_.sensor()->resolution();\n> >         for (const StreamRole role : roles) {\n> >                 std::map<PixelFormat, std::vector<SizeRange>> streamFormats;\n> > -               unsigned int bufferCount;\n> >                 PixelFormat pixelFormat;\n> >                 Size size;\n> >\n> > @@ -428,7 +424,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> >                         size.height = utils::alignDown(size.height - 1,\n> >                                                        IMGU_OUTPUT_HEIGHT_MARGIN);\n> >                         pixelFormat = formats::NV12;\n> > -                       bufferCount = IPU3_BUFFER_COUNT;\n> >                         streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n> >\n> >                         break;\n> > @@ -438,7 +433,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> >                                 data->cio2_.generateConfiguration(sensorResolution);\n> >                         pixelFormat = cio2Config.pixelFormat;\n> >                         size = cio2Config.size;\n> > -                       bufferCount = cio2Config.bufferCount;\n> >\n> >                         for (const PixelFormat &format : data->cio2_.formats())\n> >                                 streamFormats[format] = data->cio2_.sizes();\n> > @@ -457,7 +451,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> >                                                .alignedDownTo(IMGU_OUTPUT_WIDTH_ALIGN,\n> >                                                               IMGU_OUTPUT_HEIGHT_ALIGN);\n> >                         pixelFormat = formats::NV12;\n> > -                       bufferCount = IPU3_BUFFER_COUNT;\n> >                         streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n> >\n> >                         break;\n> > @@ -474,7 +467,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> >                 StreamConfiguration cfg(formats);\n> >                 cfg.size = size;\n> >                 cfg.pixelFormat = pixelFormat;\n> > -               cfg.bufferCount = bufferCount;\n> >                 config->addConfiguration(cfg);\n> >         }\n> >\n> > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > index 776e0f92aed1..e6fc0425c3ef 100644\n> > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > @@ -473,7 +473,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> >         RPiCameraData *data = cameraData(camera);\n> >         CameraConfiguration *config = new RPiCameraConfiguration(data);\n> >         V4L2DeviceFormat sensorFormat;\n> > -       unsigned int bufferCount;\n> >         PixelFormat pixelFormat;\n> >         V4L2VideoDevice::Formats fmts;\n> >         Size size;\n> > @@ -491,7 +490,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> >                         sensorFormat = findBestMode(fmts, size);\n> >                         pixelFormat = sensorFormat.fourcc.toPixelFormat();\n> >                         ASSERT(pixelFormat.isValid());\n> > -                       bufferCount = 2;\n> >                         rawCount++;\n> >                         break;\n> >\n> > @@ -500,7 +498,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> >                         pixelFormat = formats::NV12;\n> >                         /* Return the largest sensor resolution. */\n> >                         size = data->sensor_->resolution();\n> > -                       bufferCount = 1;\n> >                         outCount++;\n> >                         break;\n> >\n> > @@ -516,7 +513,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> >                         fmts = data->isp_[Isp::Output0].dev()->formats();\n> >                         pixelFormat = formats::YUV420;\n> >                         size = { 1920, 1080 };\n> > -                       bufferCount = 4;\n> >                         outCount++;\n> >                         break;\n> >\n> > @@ -524,7 +520,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> >                         fmts = data->isp_[Isp::Output0].dev()->formats();\n> >                         pixelFormat = formats::ARGB8888;\n> >                         size = { 800, 600 };\n> > -                       bufferCount = 4;\n> >                         outCount++;\n> >                         break;\n> >\n> > @@ -554,7 +549,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> >                 StreamConfiguration cfg(formats);\n> >                 cfg.size = size;\n> >                 cfg.pixelFormat = pixelFormat;\n> > -               cfg.bufferCount = bufferCount;\n> >                 config->addConfiguration(cfg);\n> >         }\n> >\n> > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > index fea330f72886..4961f3971e59 100644\n> > --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > @@ -61,7 +61,6 @@ StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution)\n> >         StreamConfiguration cfg(formats);\n> >         cfg.pixelFormat = formats::NV12;\n> >         cfg.size = maxResolution;\n> > -       cfg.bufferCount = RKISP1_BUFFER_COUNT;\n> >\n> >         return cfg;\n> >  }\n> > @@ -77,7 +76,6 @@ CameraConfiguration::Status RkISP1Path::validate(StreamConfiguration *cfg)\n> >\n> >         cfg->size.boundTo(maxResolution_);\n> >         cfg->size.expandTo(minResolution_);\n> > -       cfg->bufferCount = RKISP1_BUFFER_COUNT;\n> >\n> >         V4L2DeviceFormat format;\n> >         format.fourcc = video_->toV4L2PixelFormat(cfg->pixelFormat);\n> > diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp\n> > index b3bcf01483f7..fda417793e80 100644\n> > --- a/src/libcamera/pipeline/simple/converter.cpp\n> > +++ b/src/libcamera/pipeline/simple/converter.cpp\n> > @@ -89,9 +89,6 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg,\n> >                 return -EINVAL;\n> >         }\n> >\n> > -       inputBufferCount_ = inputCfg.bufferCount;\n> > -       outputBufferCount_ = outputCfg.bufferCount;\n> > -\n> >         return 0;\n> >  }\n> >\n> > diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h\n> > index 7e1d60674f62..406e63ca2a80 100644\n> > --- a/src/libcamera/pipeline/simple/converter.h\n> > +++ b/src/libcamera/pipeline/simple/converter.h\n> > @@ -87,9 +87,6 @@ private:\n> >                 SimpleConverter *converter_;\n> >                 unsigned int index_;\n> >                 std::unique_ptr<V4L2M2MDevice> m2m_;\n> > -\n> > -               unsigned int inputBufferCount_;\n> > -               unsigned int outputBufferCount_;\n> >         };\n> >\n> >         std::string deviceNode_;\n> > diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\n> > index a1163eaf8be2..ded04914f610 100644\n> > --- a/src/libcamera/pipeline/simple/simple.cpp\n> > +++ b/src/libcamera/pipeline/simple/simple.cpp\n> > @@ -628,7 +628,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n> >                     cfg.size != pipeConfig_->captureSize)\n> >                         needConversion_ = true;\n> >\n> > -               /* Set the stride, frameSize and bufferCount. */\n> > +               /* Set the stride and frameSize. */\n> >                 if (needConversion_) {\n> >                         std::tie(cfg.stride, cfg.frameSize) =\n> >                                 converter->strideAndFrameSize(cfg.pixelFormat, cfg.size);\n> > @@ -646,8 +646,6 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n> >                         cfg.stride = format.planes[0].bpl;\n> >                         cfg.frameSize = format.planes[0].size;\n> >                 }\n> > -\n> > -               cfg.bufferCount = 3;\n> >         }\n> >\n> >         return status;\n> > @@ -770,7 +768,6 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)\n> >         inputCfg.pixelFormat = pipeConfig->captureFormat;\n> >         inputCfg.size = pipeConfig->captureSize;\n> >         inputCfg.stride = captureFormat.planes[0].bpl;\n> > -       inputCfg.bufferCount = kNumInternalBuffers;\n> >\n> >         return converter_->configure(inputCfg, outputCfgs);\n> >  }\n> > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > index 755949e7a59a..32482300f09a 100644\n> > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > @@ -150,8 +150,6 @@ CameraConfiguration::Status UVCCameraConfiguration::validate()\n> >                 status = Adjusted;\n> >         }\n> >\n> > -       cfg.bufferCount = 4;\n> > -\n> >         V4L2DeviceFormat format;\n> >         format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n> >         format.size = cfg.size;\n> > @@ -193,7 +191,6 @@ CameraConfiguration *PipelineHandlerUVC::generateConfiguration(Camera *camera,\n> >\n> >         cfg.pixelFormat = formats.pixelformats().front();\n> >         cfg.size = formats.sizes(cfg.pixelFormat).back();\n> > -       cfg.bufferCount = 4;\n> >\n> >         config->addConfiguration(cfg);\n> >\n> > diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp\n> > index 24ba743a946c..a698427c4361 100644\n> > --- a/src/libcamera/pipeline/vimc/vimc.cpp\n> > +++ b/src/libcamera/pipeline/vimc/vimc.cpp\n> > @@ -167,8 +167,6 @@ CameraConfiguration::Status VimcCameraConfiguration::validate()\n> >                 status = Adjusted;\n> >         }\n> >\n> > -       cfg.bufferCount = 4;\n> > -\n> >         V4L2DeviceFormat format;\n> >         format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n> >         format.size = cfg.size;\n> > @@ -224,7 +222,6 @@ CameraConfiguration *PipelineHandlerVimc::generateConfiguration(Camera *camera,\n> >\n> >         cfg.pixelFormat = formats::BGR888;\n> >         cfg.size = { 1920, 1080 };\n> > -       cfg.bufferCount = 4;\n> >\n> >         config->addConfiguration(cfg);\n> >\n> > diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp\n> > index b8626775d224..ca507b72b26a 100644\n> > --- a/src/libcamera/stream.cpp\n> > +++ b/src/libcamera/stream.cpp\n> > @@ -280,7 +280,7 @@ SizeRange StreamFormats::range(const PixelFormat &pixelformat) const\n> >   * handlers provide StreamFormats.\n> >   */\n> >  StreamConfiguration::StreamConfiguration()\n> > -       : pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> > +       : pixelFormat(0), stride(0), frameSize(0),\n> >           stream_(nullptr)\n> >  {\n> >  }\n> > @@ -289,7 +289,7 @@ StreamConfiguration::StreamConfiguration()\n> >   * \\brief Construct a configuration with stream formats\n> >   */\n> >  StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n> > -       : pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> > +       : pixelFormat(0), stride(0), frameSize(0),\n> >           stream_(nullptr), formats_(formats)\n> >  {\n> >  }\n> > @@ -324,11 +324,6 @@ StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n> >   * validating the configuration with a call to CameraConfiguration::validate().\n> >   */\n> >\n> > -/**\n> > - * \\var StreamConfiguration::bufferCount\n> > - * \\brief Requested number of buffers to allocate for the stream\n> > - */\n> > -\n> >  /**\n> >   * \\fn StreamConfiguration::stream()\n> >   * \\brief Retrieve the stream associated with the configuration\n> > diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp\n> > index d01eacfa2b84..2ff9affc6388 100644\n> > --- a/src/v4l2/v4l2_camera.cpp\n> > +++ b/src/v4l2/v4l2_camera.cpp\n> > @@ -12,6 +12,8 @@\n> >\n> >  #include <libcamera/base/log.h>\n> >\n> > +#include <libcamera/property_ids.h>\n> > +\n> >  using namespace libcamera;\n> >\n> >  LOG_DECLARE_CATEGORY(V4L2Compat)\n> > @@ -107,14 +109,12 @@ void V4L2Camera::requestComplete(Request *request)\n> >  }\n> >\n> >  int V4L2Camera::configure(StreamConfiguration *streamConfigOut,\n> > -                         const Size &size, const PixelFormat &pixelformat,\n> > -                         unsigned int bufferCount)\n> > +                         const Size &size, const PixelFormat &pixelformat)\n> >  {\n> >         StreamConfiguration &streamConfig = config_->at(0);\n> >         streamConfig.size.width = size.width;\n> >         streamConfig.size.height = size.height;\n> >         streamConfig.pixelFormat = pixelformat;\n> > -       streamConfig.bufferCount = bufferCount;\n> >         /* \\todo memoryType (interval vs external) */\n> >\n> >         CameraConfiguration::Status validation = config_->validate();\n> > @@ -146,7 +146,6 @@ int V4L2Camera::validateConfiguration(const PixelFormat &pixelFormat,\n> >         StreamConfiguration &cfg = config->at(0);\n> >         cfg.size = size;\n> >         cfg.pixelFormat = pixelFormat;\n> > -       cfg.bufferCount = 1;\n> >\n> >         CameraConfiguration::Status validation = config->validate();\n> >         if (validation == CameraConfiguration::Invalid)\n> > @@ -299,3 +298,10 @@ bool V4L2Camera::isRunning()\n> >  {\n> >         return isRunning_;\n> >  }\n> > +\n> > +unsigned int V4L2Camera::minimumRequests(unsigned int count)\n> > +{\n> > +       unsigned int min = camera_->properties().get(properties::MinimumRequests);\n> > +\n> > +       return std::max(count, min);\n> > +}\n> > diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h\n> > index a095f4e27524..4b5618ac12b5 100644\n> > --- a/src/v4l2/v4l2_camera.h\n> > +++ b/src/v4l2/v4l2_camera.h\n> > @@ -45,8 +45,7 @@ public:\n> >         std::vector<Buffer> completedBuffers();\n> >\n> >         int configure(StreamConfiguration *streamConfigOut,\n> > -                     const Size &size, const PixelFormat &pixelformat,\n> > -                     unsigned int bufferCount);\n> > +                     const Size &size, const PixelFormat &pixelformat);\n> >         int validateConfiguration(const PixelFormat &pixelformat,\n> >                                   const Size &size,\n> >                                   StreamConfiguration *streamConfigOut);\n> > @@ -65,6 +64,8 @@ public:\n> >\n> >         bool isRunning();\n> >\n> > +       unsigned int minimumRequests(unsigned int count);\n> > +\n> >  private:\n> >         void requestComplete(Request *request);\n> >\n> > diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp\n> > index 7682c4bddf90..634ec84e0cbb 100644\n> > --- a/src/v4l2/v4l2_camera_proxy.cpp\n> > +++ b/src/v4l2/v4l2_camera_proxy.cpp\n> > @@ -349,8 +349,7 @@ int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg)\n> >         Size size(arg->fmt.pix.width, arg->fmt.pix.height);\n> >         V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->fmt.pix.pixelformat);\n> >         ret = vcam_->configure(&streamConfig_, size,\n> > -                              PixelFormatInfo::info(v4l2Format).format,\n> > -                              bufferCount_);\n> > +                              PixelFormatInfo::info(v4l2Format).format);\n> >         if (ret < 0)\n> >                 return -EINVAL;\n> >\n> > @@ -491,14 +490,13 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf\n> >         Size size(v4l2PixFormat_.width, v4l2PixFormat_.height);\n> >         V4L2PixelFormat v4l2Format = V4L2PixelFormat(v4l2PixFormat_.pixelformat);\n> >         int ret = vcam_->configure(&streamConfig_, size,\n> > -                                  PixelFormatInfo::info(v4l2Format).format,\n> > -                                  arg->count);\n> > +                                  PixelFormatInfo::info(v4l2Format).format);\n> >         if (ret < 0)\n> >                 return -EINVAL;\n> >\n> >         setFmtFromConfig(streamConfig_);\n> >\n> > -       arg->count = streamConfig_.bufferCount;\n> > +       arg->count = vcam_->minimumRequests(arg->count);\n> >         bufferCount_ = arg->count;\n> >\n> >         ret = vcam_->allocBuffers(arg->count);\n> > diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp\n> > index c504ea09e64b..67ac0ad20e15 100644\n> > --- a/test/camera/buffer_import.cpp\n> > +++ b/test/camera/buffer_import.cpp\n> > @@ -16,6 +16,8 @@\n> >  #include <libcamera/base/thread.h>\n> >  #include <libcamera/base/timer.h>\n> >\n> > +#include <libcamera/property_ids.h>\n> > +\n> >  #include \"libcamera/internal/device_enumerator.h\"\n> >  #include \"libcamera/internal/media_device.h\"\n> >  #include \"libcamera/internal/v4l2_videodevice.h\"\n> > @@ -92,10 +94,12 @@ protected:\n> >                         return TestFail;\n> >                 }\n> >\n> > +               unsigned int bufferCount = camera_->properties().get(properties::MinimumRequests);\n> > +\n> >                 Stream *stream = cfg.stream();\n> >\n> >                 BufferSource source;\n> > -               int ret = source.allocate(cfg);\n> > +               int ret = source.allocate(cfg, bufferCount);\n> >                 if (ret != TestPass)\n> >                         return ret;\n> >\n> > @@ -139,10 +143,10 @@ protected:\n> >                 while (timer.isRunning())\n> >                         dispatcher->processEvents();\n> >\n> > -               if (completeRequestsCount_ < cfg.bufferCount * 2) {\n> > +               if (completeRequestsCount_ < bufferCount * 2) {\n> >                         std::cout << \"Failed to capture enough frames (got \"\n> >                                   << completeRequestsCount_ << \" expected at least \"\n> > -                                 << cfg.bufferCount * 2 << \")\" << std::endl;\n> > +                                 << bufferCount * 2 << \")\" << std::endl;\n> >                         return TestFail;\n> >                 }\n> >\n> > diff --git a/test/libtest/buffer_source.cpp b/test/libtest/buffer_source.cpp\n> > index 73563f2fc39d..c3d5286a2462 100644\n> > --- a/test/libtest/buffer_source.cpp\n> > +++ b/test/libtest/buffer_source.cpp\n> > @@ -24,7 +24,7 @@ BufferSource::~BufferSource()\n> >                 media_->release();\n> >  }\n> >\n> > -int BufferSource::allocate(const StreamConfiguration &config)\n> > +int BufferSource::allocate(const StreamConfiguration &config, unsigned int count)\n> >  {\n> >         /* Locate and open the video device. */\n> >         std::string videoDeviceName = \"vivid-000-vid-out\";\n> > @@ -77,7 +77,7 @@ int BufferSource::allocate(const StreamConfiguration &config)\n> >                 return TestFail;\n> >         }\n> >\n> > -       if (video->allocateBuffers(config.bufferCount, &buffers_) < 0) {\n> > +       if (video->allocateBuffers(count, &buffers_) < 0) {\n> >                 std::cout << \"Failed to allocate buffers\" << std::endl;\n> >                 return TestFail;\n> >         }\n> > diff --git a/test/libtest/buffer_source.h b/test/libtest/buffer_source.h\n> > index 14b4770e8d8a..6a18e269a575 100644\n> > --- a/test/libtest/buffer_source.h\n> > +++ b/test/libtest/buffer_source.h\n> > @@ -20,7 +20,7 @@ public:\n> >         BufferSource();\n> >         ~BufferSource();\n> >\n> > -       int allocate(const StreamConfiguration &config);\n> > +       int allocate(const StreamConfiguration &config, unsigned int count);\n> >         const std::vector<std::unique_ptr<FrameBuffer>> &buffers();\n> >\n> >  private:\n> > diff --git a/test/v4l2_videodevice/buffer_cache.cpp b/test/v4l2_videodevice/buffer_cache.cpp\n> > index b3f2bec11783..07fddfd2617c 100644\n> > --- a/test/v4l2_videodevice/buffer_cache.cpp\n> > +++ b/test/v4l2_videodevice/buffer_cache.cpp\n> > @@ -10,6 +10,7 @@\n> >  #include <vector>\n> >\n> >  #include <libcamera/formats.h>\n> > +#include <libcamera/property_ids.h>\n> >  #include <libcamera/stream.h>\n> >\n> >  #include \"buffer_source.h\"\n> > @@ -145,10 +146,9 @@ public:\n> >                 StreamConfiguration cfg;\n> >                 cfg.pixelFormat = formats::YUYV;\n> >                 cfg.size = Size(600, 800);\n> > -               cfg.bufferCount = numBuffers;\n> >\n> >                 BufferSource source;\n> > -               int ret = source.allocate(cfg);\n> > +               int ret = source.allocate(cfg, numBuffers);\n> >                 if (ret != TestPass)\n> >                         return ret;\n> >\n> > --\n> > 2.32.0\n> >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id E611DC0109\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 23 Jul 2021 13:10:47 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4EF13687A4;\n\tFri, 23 Jul 2021 15:10:47 +0200 (CEST)","from bhuna.collabora.co.uk (bhuna.collabora.co.uk\n\t[IPv6:2a00:1098:0:82:1000:25:2eeb:e3e3])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 53D5568536\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 23 Jul 2021 15:10:46 +0200 (CEST)","from notapiano (unknown\n\t[IPv6:2804:14c:1a9:2434:8020:4e71:6276:33d6])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits))\n\t(No client certificate requested) (Authenticated sender: nfraprado)\n\tby bhuna.collabora.co.uk (Postfix) with ESMTPSA id 7C4341F44C28;\n\tFri, 23 Jul 2021 14:10:44 +0100 (BST)"],"Date":"Fri, 23 Jul 2021 10:10:39 -0300","From":"=?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4=?= Prado <nfraprado@collabora.com>","To":"David Plowman <david.plowman@raspberrypi.com>","Message-ID":"<20210723131039.ire2z7u6sdxws3dt@notapiano>","References":"<20210722232851.747614-1-nfraprado@collabora.com>\n\t<20210722232851.747614-11-nfraprado@collabora.com>\n\t<CAHW6GYJbVdFebNca9ZeM8LY=Ca4P1uaUd3B-r5FF7mJ9k853fg@mail.gmail.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=iso-8859-1","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<CAHW6GYJbVdFebNca9ZeM8LY=Ca4P1uaUd3B-r5FF7mJ9k853fg@mail.gmail.com>","Subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>,\n\tkernel@collabora.com, =?utf-8?b?QW5kcsOp?=\n\tAlmeida <andrealmeid@collabora.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":18293,"web_url":"https://patchwork.libcamera.org/comment/18293/","msgid":"<CAHW6GYKCBXmNSzo+_EcQCvJEaPg-ahMsWXKwVA=J8YzZEtBUWA@mail.gmail.com>","date":"2021-07-23T15:53:55","subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","submitter":{"id":42,"url":"https://patchwork.libcamera.org/api/people/42/","name":"David Plowman","email":"david.plowman@raspberrypi.com"},"content":"Hi Nicolas\n\nThanks for the explanations. I'm still not sure I entirely understand\nso perhaps a quick look at how I would have to change my application\ncode might help? Here's what I have now (I've removed any\n\"unimportant\" bits!):\n\nconfiguration_ = camera_->generateConfiguration({ StreamRole::StillCapture });\nconfiguration_->at(0).bufferCount = <value I have determined>;\ncamera_->configure(configuration_.get());\nallocator_ = new FrameBufferAllocator(camera_);\nStream *stream = configuration_->at(0).stream();\nallocator_->allocate(stream);\n// now allocator_->buffers(stream) has the buffers I want!\n\nI guess one thing to note is that the bufferCount value varies with\nmore than just the StreamRole, and I don't in general trust the\npipeline handler to \"know\" what I want. Will this still be possible?\n\nThanks!\nDavid\n\nOn Fri, 23 Jul 2021 at 14:10, Nícolas F. R. A. Prado\n<nfraprado@collabora.com> wrote:\n>\n> Hi David,\n>\n> On Fri, Jul 23, 2021 at 09:42:56AM +0100, David Plowman wrote:\n> > Hi Nicolas\n> >\n> > Thanks very much for all this work! I was wondering if I could ask a\n> > little more about this patch. In our applications, for example, we set\n> > the bufferCount according to the use-case that the application is\n> > implementing. For example:\n> >\n> > * For preview windows we set bufferCount to 4.\n> > * For video capture we drop fewer frames with a deeper queue so we set it to 6.\n> > * For stills capture we can get by with one frame, though use cases\n> > that capture several stills images for fusion work better if we set\n> > bufferCount to 2 or 3.\n> >\n> > I was wondering how our applications can achieve this behaviour if the\n> > bufferCount field is no longer available.\n>\n> Okay, so the short answer is that the applications, knowing their particular use\n> case, are responsible to provide enough requests to keep the pipeline going. On\n> the pipeline handler side, it's free to use how many internal buffers it wants.\n>\n> So in your case, the pipeline handler could still allocate that same number of\n> internal buffers as you previously did based on bufferCount, but now based\n> solely on the StreamRole set. The application would then allocate and queue\n> how many buffers fits the usage. (Note that before the application would call\n> FrameBufferAllocator::allocate() and it would allocate 'bufferCount' buffers,\n> but now the function takes a count argument so the application is free to choose\n> how many)\n>\n> Now, I guess it would be nice for the application to be able to query what is a\n> good number of buffers to use, for example 6 in the video capture of your use\n> case. At the moment, the only information available is that 1 is the minimum\n> number of buffers required. So the application would have to know that 6 is a\n> good number for video capture. Maybe another property could be introduced later\n> for this recommended amount, but previous discussions suggested this is very use\n> case dependent, so might not make sense.\n>\n> I hope this answers the question. If not, I'm still here :).\n>\n> Thanks,\n> Nícolas\n>\n> >\n> > Thanks!\n> > David\n> >\n> > On Fri, 23 Jul 2021 at 00:29, Nícolas F. R. A. Prado\n> > <nfraprado@collabora.com> wrote:\n> > >\n> > > Now that the number of buffers allocated by the FrameBufferAllocator\n> > > helper is passed through FrameBufferAllocator::allocate() and the\n> > > pipelines no longer use bufferCount for internal buffer or V4L2 buffer\n> > > slots allocation, we no longer need to have bufferCount in the\n> > > StreamConfiguration, so remove it.\n> > >\n> > > Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>\n> > > ---\n> > >\n> > > No changes in v7\n> > >\n> > > Changes in v6:\n> > > - Removed IPU3_BUFFER_COUNT as it was unused\n> > >\n> > >  include/libcamera/stream.h                         |  2 --\n> > >  src/android/camera_stream.cpp                      |  2 +-\n> > >  src/libcamera/pipeline/ipu3/cio2.cpp               |  1 -\n> > >  src/libcamera/pipeline/ipu3/ipu3.cpp               |  8 --------\n> > >  src/libcamera/pipeline/raspberrypi/raspberrypi.cpp |  6 ------\n> > >  src/libcamera/pipeline/rkisp1/rkisp1_path.cpp      |  2 --\n> > >  src/libcamera/pipeline/simple/converter.cpp        |  3 ---\n> > >  src/libcamera/pipeline/simple/converter.h          |  3 ---\n> > >  src/libcamera/pipeline/simple/simple.cpp           |  5 +----\n> > >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp       |  3 ---\n> > >  src/libcamera/pipeline/vimc/vimc.cpp               |  3 ---\n> > >  src/libcamera/stream.cpp                           |  9 ++-------\n> > >  src/v4l2/v4l2_camera.cpp                           | 14 ++++++++++----\n> > >  src/v4l2/v4l2_camera.h                             |  5 +++--\n> > >  src/v4l2/v4l2_camera_proxy.cpp                     |  8 +++-----\n> > >  test/camera/buffer_import.cpp                      | 10 +++++++---\n> > >  test/libtest/buffer_source.cpp                     |  4 ++--\n> > >  test/libtest/buffer_source.h                       |  2 +-\n> > >  test/v4l2_videodevice/buffer_cache.cpp             |  4 ++--\n> > >  19 files changed, 32 insertions(+), 62 deletions(-)\n> > >\n> > > diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\n> > > index 0c55e7164592..b25f0059f2f1 100644\n> > > --- a/include/libcamera/stream.h\n> > > +++ b/include/libcamera/stream.h\n> > > @@ -45,8 +45,6 @@ struct StreamConfiguration {\n> > >         unsigned int stride;\n> > >         unsigned int frameSize;\n> > >\n> > > -       unsigned int bufferCount;\n> > > -\n> > >         Stream *stream() const { return stream_; }\n> > >         void setStream(Stream *stream) { stream_ = stream; }\n> > >         const StreamFormats &formats() const { return formats_; }\n> > > diff --git a/src/android/camera_stream.cpp b/src/android/camera_stream.cpp\n> > > index b168e3c0c288..0794be409f82 100644\n> > > --- a/src/android/camera_stream.cpp\n> > > +++ b/src/android/camera_stream.cpp\n> > > @@ -94,7 +94,7 @@ int CameraStream::configure()\n> > >                         buffers_.push_back(frameBuffer.get());\n> > >         }\n> > >\n> > > -       camera3Stream_->max_buffers = configuration().bufferCount;\n> > > +       camera3Stream_->max_buffers = bufferCount;\n> > >\n> > >         return 0;\n> > >  }\n> > > diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > index 1bcd580e251c..0e04e7214489 100644\n> > > --- a/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > +++ b/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > @@ -214,7 +214,6 @@ StreamConfiguration CIO2Device::generateConfiguration(Size size) const\n> > >\n> > >         cfg.size = sensorFormat.size;\n> > >         cfg.pixelFormat = mbusCodesToPixelFormat.at(sensorFormat.mbus_code);\n> > > -       cfg.bufferCount = CIO2_BUFFER_COUNT;\n> > >\n> > >         return cfg;\n> > >  }\n> > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > index 4efd201c05e5..b223b3f33cd0 100644\n> > > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > @@ -38,7 +38,6 @@ namespace libcamera {\n> > >\n> > >  LOG_DEFINE_CATEGORY(IPU3)\n> > >\n> > > -static constexpr unsigned int IPU3_BUFFER_COUNT = 4;\n> > >  static constexpr unsigned int IPU3_MAX_STREAMS = 3;\n> > >  static const Size IMGU_OUTPUT_MIN_SIZE = { 2, 2 };\n> > >  static const Size IMGU_OUTPUT_MAX_SIZE = { 4480, 34004 };\n> > > @@ -295,7 +294,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n> > >                         /* Initialize the RAW stream with the CIO2 configuration. */\n> > >                         cfg->size = cio2Configuration_.size;\n> > >                         cfg->pixelFormat = cio2Configuration_.pixelFormat;\n> > > -                       cfg->bufferCount = cio2Configuration_.bufferCount;\n> > >                         cfg->stride = info.stride(cfg->size.width, 0, 64);\n> > >                         cfg->frameSize = info.frameSize(cfg->size, 64);\n> > >                         cfg->setStream(const_cast<Stream *>(&data_->rawStream_));\n> > > @@ -339,7 +337,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n> > >                                               IMGU_OUTPUT_HEIGHT_ALIGN);\n> > >\n> > >                         cfg->pixelFormat = formats::NV12;\n> > > -                       cfg->bufferCount = IPU3_BUFFER_COUNT;\n> > >                         cfg->stride = info.stride(cfg->size.width, 0, 1);\n> > >                         cfg->frameSize = info.frameSize(cfg->size, 1);\n> > >\n> > > @@ -407,7 +404,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > >         Size sensorResolution = data->cio2_.sensor()->resolution();\n> > >         for (const StreamRole role : roles) {\n> > >                 std::map<PixelFormat, std::vector<SizeRange>> streamFormats;\n> > > -               unsigned int bufferCount;\n> > >                 PixelFormat pixelFormat;\n> > >                 Size size;\n> > >\n> > > @@ -428,7 +424,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > >                         size.height = utils::alignDown(size.height - 1,\n> > >                                                        IMGU_OUTPUT_HEIGHT_MARGIN);\n> > >                         pixelFormat = formats::NV12;\n> > > -                       bufferCount = IPU3_BUFFER_COUNT;\n> > >                         streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n> > >\n> > >                         break;\n> > > @@ -438,7 +433,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > >                                 data->cio2_.generateConfiguration(sensorResolution);\n> > >                         pixelFormat = cio2Config.pixelFormat;\n> > >                         size = cio2Config.size;\n> > > -                       bufferCount = cio2Config.bufferCount;\n> > >\n> > >                         for (const PixelFormat &format : data->cio2_.formats())\n> > >                                 streamFormats[format] = data->cio2_.sizes();\n> > > @@ -457,7 +451,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > >                                                .alignedDownTo(IMGU_OUTPUT_WIDTH_ALIGN,\n> > >                                                               IMGU_OUTPUT_HEIGHT_ALIGN);\n> > >                         pixelFormat = formats::NV12;\n> > > -                       bufferCount = IPU3_BUFFER_COUNT;\n> > >                         streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n> > >\n> > >                         break;\n> > > @@ -474,7 +467,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > >                 StreamConfiguration cfg(formats);\n> > >                 cfg.size = size;\n> > >                 cfg.pixelFormat = pixelFormat;\n> > > -               cfg.bufferCount = bufferCount;\n> > >                 config->addConfiguration(cfg);\n> > >         }\n> > >\n> > > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > index 776e0f92aed1..e6fc0425c3ef 100644\n> > > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > @@ -473,7 +473,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > >         RPiCameraData *data = cameraData(camera);\n> > >         CameraConfiguration *config = new RPiCameraConfiguration(data);\n> > >         V4L2DeviceFormat sensorFormat;\n> > > -       unsigned int bufferCount;\n> > >         PixelFormat pixelFormat;\n> > >         V4L2VideoDevice::Formats fmts;\n> > >         Size size;\n> > > @@ -491,7 +490,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > >                         sensorFormat = findBestMode(fmts, size);\n> > >                         pixelFormat = sensorFormat.fourcc.toPixelFormat();\n> > >                         ASSERT(pixelFormat.isValid());\n> > > -                       bufferCount = 2;\n> > >                         rawCount++;\n> > >                         break;\n> > >\n> > > @@ -500,7 +498,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > >                         pixelFormat = formats::NV12;\n> > >                         /* Return the largest sensor resolution. */\n> > >                         size = data->sensor_->resolution();\n> > > -                       bufferCount = 1;\n> > >                         outCount++;\n> > >                         break;\n> > >\n> > > @@ -516,7 +513,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > >                         fmts = data->isp_[Isp::Output0].dev()->formats();\n> > >                         pixelFormat = formats::YUV420;\n> > >                         size = { 1920, 1080 };\n> > > -                       bufferCount = 4;\n> > >                         outCount++;\n> > >                         break;\n> > >\n> > > @@ -524,7 +520,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > >                         fmts = data->isp_[Isp::Output0].dev()->formats();\n> > >                         pixelFormat = formats::ARGB8888;\n> > >                         size = { 800, 600 };\n> > > -                       bufferCount = 4;\n> > >                         outCount++;\n> > >                         break;\n> > >\n> > > @@ -554,7 +549,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > >                 StreamConfiguration cfg(formats);\n> > >                 cfg.size = size;\n> > >                 cfg.pixelFormat = pixelFormat;\n> > > -               cfg.bufferCount = bufferCount;\n> > >                 config->addConfiguration(cfg);\n> > >         }\n> > >\n> > > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > index fea330f72886..4961f3971e59 100644\n> > > --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > @@ -61,7 +61,6 @@ StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution)\n> > >         StreamConfiguration cfg(formats);\n> > >         cfg.pixelFormat = formats::NV12;\n> > >         cfg.size = maxResolution;\n> > > -       cfg.bufferCount = RKISP1_BUFFER_COUNT;\n> > >\n> > >         return cfg;\n> > >  }\n> > > @@ -77,7 +76,6 @@ CameraConfiguration::Status RkISP1Path::validate(StreamConfiguration *cfg)\n> > >\n> > >         cfg->size.boundTo(maxResolution_);\n> > >         cfg->size.expandTo(minResolution_);\n> > > -       cfg->bufferCount = RKISP1_BUFFER_COUNT;\n> > >\n> > >         V4L2DeviceFormat format;\n> > >         format.fourcc = video_->toV4L2PixelFormat(cfg->pixelFormat);\n> > > diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp\n> > > index b3bcf01483f7..fda417793e80 100644\n> > > --- a/src/libcamera/pipeline/simple/converter.cpp\n> > > +++ b/src/libcamera/pipeline/simple/converter.cpp\n> > > @@ -89,9 +89,6 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg,\n> > >                 return -EINVAL;\n> > >         }\n> > >\n> > > -       inputBufferCount_ = inputCfg.bufferCount;\n> > > -       outputBufferCount_ = outputCfg.bufferCount;\n> > > -\n> > >         return 0;\n> > >  }\n> > >\n> > > diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h\n> > > index 7e1d60674f62..406e63ca2a80 100644\n> > > --- a/src/libcamera/pipeline/simple/converter.h\n> > > +++ b/src/libcamera/pipeline/simple/converter.h\n> > > @@ -87,9 +87,6 @@ private:\n> > >                 SimpleConverter *converter_;\n> > >                 unsigned int index_;\n> > >                 std::unique_ptr<V4L2M2MDevice> m2m_;\n> > > -\n> > > -               unsigned int inputBufferCount_;\n> > > -               unsigned int outputBufferCount_;\n> > >         };\n> > >\n> > >         std::string deviceNode_;\n> > > diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\n> > > index a1163eaf8be2..ded04914f610 100644\n> > > --- a/src/libcamera/pipeline/simple/simple.cpp\n> > > +++ b/src/libcamera/pipeline/simple/simple.cpp\n> > > @@ -628,7 +628,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n> > >                     cfg.size != pipeConfig_->captureSize)\n> > >                         needConversion_ = true;\n> > >\n> > > -               /* Set the stride, frameSize and bufferCount. */\n> > > +               /* Set the stride and frameSize. */\n> > >                 if (needConversion_) {\n> > >                         std::tie(cfg.stride, cfg.frameSize) =\n> > >                                 converter->strideAndFrameSize(cfg.pixelFormat, cfg.size);\n> > > @@ -646,8 +646,6 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n> > >                         cfg.stride = format.planes[0].bpl;\n> > >                         cfg.frameSize = format.planes[0].size;\n> > >                 }\n> > > -\n> > > -               cfg.bufferCount = 3;\n> > >         }\n> > >\n> > >         return status;\n> > > @@ -770,7 +768,6 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)\n> > >         inputCfg.pixelFormat = pipeConfig->captureFormat;\n> > >         inputCfg.size = pipeConfig->captureSize;\n> > >         inputCfg.stride = captureFormat.planes[0].bpl;\n> > > -       inputCfg.bufferCount = kNumInternalBuffers;\n> > >\n> > >         return converter_->configure(inputCfg, outputCfgs);\n> > >  }\n> > > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > index 755949e7a59a..32482300f09a 100644\n> > > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > @@ -150,8 +150,6 @@ CameraConfiguration::Status UVCCameraConfiguration::validate()\n> > >                 status = Adjusted;\n> > >         }\n> > >\n> > > -       cfg.bufferCount = 4;\n> > > -\n> > >         V4L2DeviceFormat format;\n> > >         format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n> > >         format.size = cfg.size;\n> > > @@ -193,7 +191,6 @@ CameraConfiguration *PipelineHandlerUVC::generateConfiguration(Camera *camera,\n> > >\n> > >         cfg.pixelFormat = formats.pixelformats().front();\n> > >         cfg.size = formats.sizes(cfg.pixelFormat).back();\n> > > -       cfg.bufferCount = 4;\n> > >\n> > >         config->addConfiguration(cfg);\n> > >\n> > > diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp\n> > > index 24ba743a946c..a698427c4361 100644\n> > > --- a/src/libcamera/pipeline/vimc/vimc.cpp\n> > > +++ b/src/libcamera/pipeline/vimc/vimc.cpp\n> > > @@ -167,8 +167,6 @@ CameraConfiguration::Status VimcCameraConfiguration::validate()\n> > >                 status = Adjusted;\n> > >         }\n> > >\n> > > -       cfg.bufferCount = 4;\n> > > -\n> > >         V4L2DeviceFormat format;\n> > >         format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n> > >         format.size = cfg.size;\n> > > @@ -224,7 +222,6 @@ CameraConfiguration *PipelineHandlerVimc::generateConfiguration(Camera *camera,\n> > >\n> > >         cfg.pixelFormat = formats::BGR888;\n> > >         cfg.size = { 1920, 1080 };\n> > > -       cfg.bufferCount = 4;\n> > >\n> > >         config->addConfiguration(cfg);\n> > >\n> > > diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp\n> > > index b8626775d224..ca507b72b26a 100644\n> > > --- a/src/libcamera/stream.cpp\n> > > +++ b/src/libcamera/stream.cpp\n> > > @@ -280,7 +280,7 @@ SizeRange StreamFormats::range(const PixelFormat &pixelformat) const\n> > >   * handlers provide StreamFormats.\n> > >   */\n> > >  StreamConfiguration::StreamConfiguration()\n> > > -       : pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> > > +       : pixelFormat(0), stride(0), frameSize(0),\n> > >           stream_(nullptr)\n> > >  {\n> > >  }\n> > > @@ -289,7 +289,7 @@ StreamConfiguration::StreamConfiguration()\n> > >   * \\brief Construct a configuration with stream formats\n> > >   */\n> > >  StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n> > > -       : pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> > > +       : pixelFormat(0), stride(0), frameSize(0),\n> > >           stream_(nullptr), formats_(formats)\n> > >  {\n> > >  }\n> > > @@ -324,11 +324,6 @@ StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n> > >   * validating the configuration with a call to CameraConfiguration::validate().\n> > >   */\n> > >\n> > > -/**\n> > > - * \\var StreamConfiguration::bufferCount\n> > > - * \\brief Requested number of buffers to allocate for the stream\n> > > - */\n> > > -\n> > >  /**\n> > >   * \\fn StreamConfiguration::stream()\n> > >   * \\brief Retrieve the stream associated with the configuration\n> > > diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp\n> > > index d01eacfa2b84..2ff9affc6388 100644\n> > > --- a/src/v4l2/v4l2_camera.cpp\n> > > +++ b/src/v4l2/v4l2_camera.cpp\n> > > @@ -12,6 +12,8 @@\n> > >\n> > >  #include <libcamera/base/log.h>\n> > >\n> > > +#include <libcamera/property_ids.h>\n> > > +\n> > >  using namespace libcamera;\n> > >\n> > >  LOG_DECLARE_CATEGORY(V4L2Compat)\n> > > @@ -107,14 +109,12 @@ void V4L2Camera::requestComplete(Request *request)\n> > >  }\n> > >\n> > >  int V4L2Camera::configure(StreamConfiguration *streamConfigOut,\n> > > -                         const Size &size, const PixelFormat &pixelformat,\n> > > -                         unsigned int bufferCount)\n> > > +                         const Size &size, const PixelFormat &pixelformat)\n> > >  {\n> > >         StreamConfiguration &streamConfig = config_->at(0);\n> > >         streamConfig.size.width = size.width;\n> > >         streamConfig.size.height = size.height;\n> > >         streamConfig.pixelFormat = pixelformat;\n> > > -       streamConfig.bufferCount = bufferCount;\n> > >         /* \\todo memoryType (interval vs external) */\n> > >\n> > >         CameraConfiguration::Status validation = config_->validate();\n> > > @@ -146,7 +146,6 @@ int V4L2Camera::validateConfiguration(const PixelFormat &pixelFormat,\n> > >         StreamConfiguration &cfg = config->at(0);\n> > >         cfg.size = size;\n> > >         cfg.pixelFormat = pixelFormat;\n> > > -       cfg.bufferCount = 1;\n> > >\n> > >         CameraConfiguration::Status validation = config->validate();\n> > >         if (validation == CameraConfiguration::Invalid)\n> > > @@ -299,3 +298,10 @@ bool V4L2Camera::isRunning()\n> > >  {\n> > >         return isRunning_;\n> > >  }\n> > > +\n> > > +unsigned int V4L2Camera::minimumRequests(unsigned int count)\n> > > +{\n> > > +       unsigned int min = camera_->properties().get(properties::MinimumRequests);\n> > > +\n> > > +       return std::max(count, min);\n> > > +}\n> > > diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h\n> > > index a095f4e27524..4b5618ac12b5 100644\n> > > --- a/src/v4l2/v4l2_camera.h\n> > > +++ b/src/v4l2/v4l2_camera.h\n> > > @@ -45,8 +45,7 @@ public:\n> > >         std::vector<Buffer> completedBuffers();\n> > >\n> > >         int configure(StreamConfiguration *streamConfigOut,\n> > > -                     const Size &size, const PixelFormat &pixelformat,\n> > > -                     unsigned int bufferCount);\n> > > +                     const Size &size, const PixelFormat &pixelformat);\n> > >         int validateConfiguration(const PixelFormat &pixelformat,\n> > >                                   const Size &size,\n> > >                                   StreamConfiguration *streamConfigOut);\n> > > @@ -65,6 +64,8 @@ public:\n> > >\n> > >         bool isRunning();\n> > >\n> > > +       unsigned int minimumRequests(unsigned int count);\n> > > +\n> > >  private:\n> > >         void requestComplete(Request *request);\n> > >\n> > > diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp\n> > > index 7682c4bddf90..634ec84e0cbb 100644\n> > > --- a/src/v4l2/v4l2_camera_proxy.cpp\n> > > +++ b/src/v4l2/v4l2_camera_proxy.cpp\n> > > @@ -349,8 +349,7 @@ int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg)\n> > >         Size size(arg->fmt.pix.width, arg->fmt.pix.height);\n> > >         V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->fmt.pix.pixelformat);\n> > >         ret = vcam_->configure(&streamConfig_, size,\n> > > -                              PixelFormatInfo::info(v4l2Format).format,\n> > > -                              bufferCount_);\n> > > +                              PixelFormatInfo::info(v4l2Format).format);\n> > >         if (ret < 0)\n> > >                 return -EINVAL;\n> > >\n> > > @@ -491,14 +490,13 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf\n> > >         Size size(v4l2PixFormat_.width, v4l2PixFormat_.height);\n> > >         V4L2PixelFormat v4l2Format = V4L2PixelFormat(v4l2PixFormat_.pixelformat);\n> > >         int ret = vcam_->configure(&streamConfig_, size,\n> > > -                                  PixelFormatInfo::info(v4l2Format).format,\n> > > -                                  arg->count);\n> > > +                                  PixelFormatInfo::info(v4l2Format).format);\n> > >         if (ret < 0)\n> > >                 return -EINVAL;\n> > >\n> > >         setFmtFromConfig(streamConfig_);\n> > >\n> > > -       arg->count = streamConfig_.bufferCount;\n> > > +       arg->count = vcam_->minimumRequests(arg->count);\n> > >         bufferCount_ = arg->count;\n> > >\n> > >         ret = vcam_->allocBuffers(arg->count);\n> > > diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp\n> > > index c504ea09e64b..67ac0ad20e15 100644\n> > > --- a/test/camera/buffer_import.cpp\n> > > +++ b/test/camera/buffer_import.cpp\n> > > @@ -16,6 +16,8 @@\n> > >  #include <libcamera/base/thread.h>\n> > >  #include <libcamera/base/timer.h>\n> > >\n> > > +#include <libcamera/property_ids.h>\n> > > +\n> > >  #include \"libcamera/internal/device_enumerator.h\"\n> > >  #include \"libcamera/internal/media_device.h\"\n> > >  #include \"libcamera/internal/v4l2_videodevice.h\"\n> > > @@ -92,10 +94,12 @@ protected:\n> > >                         return TestFail;\n> > >                 }\n> > >\n> > > +               unsigned int bufferCount = camera_->properties().get(properties::MinimumRequests);\n> > > +\n> > >                 Stream *stream = cfg.stream();\n> > >\n> > >                 BufferSource source;\n> > > -               int ret = source.allocate(cfg);\n> > > +               int ret = source.allocate(cfg, bufferCount);\n> > >                 if (ret != TestPass)\n> > >                         return ret;\n> > >\n> > > @@ -139,10 +143,10 @@ protected:\n> > >                 while (timer.isRunning())\n> > >                         dispatcher->processEvents();\n> > >\n> > > -               if (completeRequestsCount_ < cfg.bufferCount * 2) {\n> > > +               if (completeRequestsCount_ < bufferCount * 2) {\n> > >                         std::cout << \"Failed to capture enough frames (got \"\n> > >                                   << completeRequestsCount_ << \" expected at least \"\n> > > -                                 << cfg.bufferCount * 2 << \")\" << std::endl;\n> > > +                                 << bufferCount * 2 << \")\" << std::endl;\n> > >                         return TestFail;\n> > >                 }\n> > >\n> > > diff --git a/test/libtest/buffer_source.cpp b/test/libtest/buffer_source.cpp\n> > > index 73563f2fc39d..c3d5286a2462 100644\n> > > --- a/test/libtest/buffer_source.cpp\n> > > +++ b/test/libtest/buffer_source.cpp\n> > > @@ -24,7 +24,7 @@ BufferSource::~BufferSource()\n> > >                 media_->release();\n> > >  }\n> > >\n> > > -int BufferSource::allocate(const StreamConfiguration &config)\n> > > +int BufferSource::allocate(const StreamConfiguration &config, unsigned int count)\n> > >  {\n> > >         /* Locate and open the video device. */\n> > >         std::string videoDeviceName = \"vivid-000-vid-out\";\n> > > @@ -77,7 +77,7 @@ int BufferSource::allocate(const StreamConfiguration &config)\n> > >                 return TestFail;\n> > >         }\n> > >\n> > > -       if (video->allocateBuffers(config.bufferCount, &buffers_) < 0) {\n> > > +       if (video->allocateBuffers(count, &buffers_) < 0) {\n> > >                 std::cout << \"Failed to allocate buffers\" << std::endl;\n> > >                 return TestFail;\n> > >         }\n> > > diff --git a/test/libtest/buffer_source.h b/test/libtest/buffer_source.h\n> > > index 14b4770e8d8a..6a18e269a575 100644\n> > > --- a/test/libtest/buffer_source.h\n> > > +++ b/test/libtest/buffer_source.h\n> > > @@ -20,7 +20,7 @@ public:\n> > >         BufferSource();\n> > >         ~BufferSource();\n> > >\n> > > -       int allocate(const StreamConfiguration &config);\n> > > +       int allocate(const StreamConfiguration &config, unsigned int count);\n> > >         const std::vector<std::unique_ptr<FrameBuffer>> &buffers();\n> > >\n> > >  private:\n> > > diff --git a/test/v4l2_videodevice/buffer_cache.cpp b/test/v4l2_videodevice/buffer_cache.cpp\n> > > index b3f2bec11783..07fddfd2617c 100644\n> > > --- a/test/v4l2_videodevice/buffer_cache.cpp\n> > > +++ b/test/v4l2_videodevice/buffer_cache.cpp\n> > > @@ -10,6 +10,7 @@\n> > >  #include <vector>\n> > >\n> > >  #include <libcamera/formats.h>\n> > > +#include <libcamera/property_ids.h>\n> > >  #include <libcamera/stream.h>\n> > >\n> > >  #include \"buffer_source.h\"\n> > > @@ -145,10 +146,9 @@ public:\n> > >                 StreamConfiguration cfg;\n> > >                 cfg.pixelFormat = formats::YUYV;\n> > >                 cfg.size = Size(600, 800);\n> > > -               cfg.bufferCount = numBuffers;\n> > >\n> > >                 BufferSource source;\n> > > -               int ret = source.allocate(cfg);\n> > > +               int ret = source.allocate(cfg, numBuffers);\n> > >                 if (ret != TestPass)\n> > >                         return ret;\n> > >\n> > > --\n> > > 2.32.0\n> > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 7DCC3C0109\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 23 Jul 2021 15:54:09 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6001C687AC;\n\tFri, 23 Jul 2021 17:54:08 +0200 (CEST)","from mail-wr1-x435.google.com (mail-wr1-x435.google.com\n\t[IPv6:2a00:1450:4864:20::435])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 0280E68537\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 23 Jul 2021 17:54:06 +0200 (CEST)","by mail-wr1-x435.google.com with SMTP id q3so2948655wrx.0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 23 Jul 2021 08:54:06 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=raspberrypi.com header.i=@raspberrypi.com\n\theader.b=\"EiZ9wWao\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=mime-version:references:in-reply-to:from:date:message-id:subject:to\n\t:cc:content-transfer-encoding;\n\tbh=SDO37f2Gw8bHPqdPzrrA+GfmJZru5VK9T3K0z0eRTSc=;\n\tb=EiZ9wWaoP0PWvB8t/SVn+iTIaDive/rktZiNs6YinLoiYjbECwMyjIgQirUc29I/Wb\n\tXatdWP5Xj2s4MS91my9S3x3vmknwNvNvO8LFtpgsUhvESFjw/HmcnAdQe/VMQOlvAwUk\n\t/LIJSdtYfvx+EQx0VWKdK21ts7hrF1OR6EpdaA8ov9LVJGhcPckzVvYVar37BDliD1M5\n\t63qgy9IKSUEACWwu1zXAOQE0zwQajHtF4Yjb6gyCfZLdo97rN6X/ZKfslZHgsHlfOYHB\n\tU+mNhM748oN6aokdA9pyiFi7xHogeAUuD/AITU+9Wr6KOnXFjYbq6PKXBbAFCqVFbZQe\n\tkObA==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to:cc:content-transfer-encoding;\n\tbh=SDO37f2Gw8bHPqdPzrrA+GfmJZru5VK9T3K0z0eRTSc=;\n\tb=JzY+2uGTmx7rTj6cWmoFRCJVYoVTn9qMmd06dA582KUuneYnPbTHZIyMw4vKoPlM9K\n\tKs/X/FuQHFuC9ra15h5SFxHPOXArs/3EMReiYKGCKKdJI8GiUMHR0cM2LP9rxE5XJgWO\n\tAD0usOznRZ2cNFki03X2hNUdHuz1BfOt1k9dmn2LE3/Cj9KXQ9JokF7TYVdMpWRe/99Y\n\tnqgQbQVzQeI8IrEnYv/qabcn9fLDmYEb0Ta0q1CVaqRXG5WZ+Ahzz6cJcm8i8Yvb5OOU\n\t8qOE4mBSzdx0n2TNqnJPjUgUjRAvXt3Cy9Il6Qk3F/WmVEIekULarbvdxYNsTvGv7o8D\n\txvJw==","X-Gm-Message-State":"AOAM532DhN/XHTtFAcf+8cp0PhiO+suegNRipzkq3Yfcr4AgS4CxjFPd\n\txQSxqkn7IFT2q/B1p3LyDVh9H3N28PihmvweVhjvTQ==","X-Google-Smtp-Source":"ABdhPJxFylOB5PVPpZTcrbSnoz4CuA91J/xtb2zmfMQJnrUrSIZ3sk0XnWHWCaxSgcOPLJ6VA2X99kNKbFO0TN+J6E8=","X-Received":"by 2002:a5d:6506:: with SMTP id x6mr5895681wru.86.1627055645912; \n\tFri, 23 Jul 2021 08:54:05 -0700 (PDT)","MIME-Version":"1.0","References":"<20210722232851.747614-1-nfraprado@collabora.com>\n\t<20210722232851.747614-11-nfraprado@collabora.com>\n\t<CAHW6GYJbVdFebNca9ZeM8LY=Ca4P1uaUd3B-r5FF7mJ9k853fg@mail.gmail.com>\n\t<20210723131039.ire2z7u6sdxws3dt@notapiano>","In-Reply-To":"<20210723131039.ire2z7u6sdxws3dt@notapiano>","From":"David Plowman <david.plowman@raspberrypi.com>","Date":"Fri, 23 Jul 2021 16:53:55 +0100","Message-ID":"<CAHW6GYKCBXmNSzo+_EcQCvJEaPg-ahMsWXKwVA=J8YzZEtBUWA@mail.gmail.com>","To":"=?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= <nfraprado@collabora.com>","Content-Type":"text/plain; charset=\"UTF-8\"","Content-Transfer-Encoding":"quoted-printable","Subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>,\n\tkernel@collabora.com, =?utf-8?q?Andr=C3=A9_Almeida?=\n\t<andrealmeid@collabora.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":18294,"web_url":"https://patchwork.libcamera.org/comment/18294/","msgid":"<20210723210807.emekovdwbehrzr44@notapiano>","date":"2021-07-23T21:08:07","subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","submitter":{"id":84,"url":"https://patchwork.libcamera.org/api/people/84/","name":"Nícolas F. R. A. Prado","email":"nfraprado@collabora.com"},"content":"Hi David,\n\nOn Fri, Jul 23, 2021 at 04:53:55PM +0100, David Plowman wrote:\n> Hi Nicolas\n> \n> Thanks for the explanations. I'm still not sure I entirely understand\n> so perhaps a quick look at how I would have to change my application\n> code might help? Here's what I have now (I've removed any\n> \"unimportant\" bits!):\n> \n> configuration_ = camera_->generateConfiguration({ StreamRole::StillCapture });\n> configuration_->at(0).bufferCount = <value I have determined>;\n> camera_->configure(configuration_.get());\n> allocator_ = new FrameBufferAllocator(camera_);\n> Stream *stream = configuration_->at(0).stream();\n> allocator_->allocate(stream);\n> // now allocator_->buffers(stream) has the buffers I want!\n> \n> I guess one thing to note is that the bufferCount value varies with\n> more than just the StreamRole, and I don't in general trust the\n> pipeline handler to \"know\" what I want. Will this still be possible?\n\nOh I see... No, this won't be possible after we drop bufferCount. The\npipeline handler will decide for itself how many buffers to allocate internally,\npossibly using the StreamRole as a hint.\n\nI wasn't aware this could impact an application, since all the other pipeline\nhandlers actually ignore when bufferCount is set by the application, overriding\nit when the configuration is validated. But now I'm noticing the raspberrypi\npipeline actually uses it.\n\nSome context: This series actually began with me making\nFrameBufferAllocator::allocate() receive a count argument instead of using the\nvalue of bufferCount. But since Laurent mentioned that bufferCount was going\naway eventually anyway I ended up removing it as well as part of this series.\n\nI do understand how being able to specify a bufferCount value that suits your\nspecific usecase is useful, though... Laurent, what's your take on this? :)\n\nThanks,\nNícolas\n\n> \n> Thanks!\n> David\n> \n> On Fri, 23 Jul 2021 at 14:10, Nícolas F. R. A. Prado\n> <nfraprado@collabora.com> wrote:\n> >\n> > Hi David,\n> >\n> > On Fri, Jul 23, 2021 at 09:42:56AM +0100, David Plowman wrote:\n> > > Hi Nicolas\n> > >\n> > > Thanks very much for all this work! I was wondering if I could ask a\n> > > little more about this patch. In our applications, for example, we set\n> > > the bufferCount according to the use-case that the application is\n> > > implementing. For example:\n> > >\n> > > * For preview windows we set bufferCount to 4.\n> > > * For video capture we drop fewer frames with a deeper queue so we set it to 6.\n> > > * For stills capture we can get by with one frame, though use cases\n> > > that capture several stills images for fusion work better if we set\n> > > bufferCount to 2 or 3.\n> > >\n> > > I was wondering how our applications can achieve this behaviour if the\n> > > bufferCount field is no longer available.\n> >\n> > Okay, so the short answer is that the applications, knowing their particular use\n> > case, are responsible to provide enough requests to keep the pipeline going. On\n> > the pipeline handler side, it's free to use how many internal buffers it wants.\n> >\n> > So in your case, the pipeline handler could still allocate that same number of\n> > internal buffers as you previously did based on bufferCount, but now based\n> > solely on the StreamRole set. The application would then allocate and queue\n> > how many buffers fits the usage. (Note that before the application would call\n> > FrameBufferAllocator::allocate() and it would allocate 'bufferCount' buffers,\n> > but now the function takes a count argument so the application is free to choose\n> > how many)\n> >\n> > Now, I guess it would be nice for the application to be able to query what is a\n> > good number of buffers to use, for example 6 in the video capture of your use\n> > case. At the moment, the only information available is that 1 is the minimum\n> > number of buffers required. So the application would have to know that 6 is a\n> > good number for video capture. Maybe another property could be introduced later\n> > for this recommended amount, but previous discussions suggested this is very use\n> > case dependent, so might not make sense.\n> >\n> > I hope this answers the question. If not, I'm still here :).\n> >\n> > Thanks,\n> > Nícolas\n> >\n> > >\n> > > Thanks!\n> > > David\n> > >\n> > > On Fri, 23 Jul 2021 at 00:29, Nícolas F. R. A. Prado\n> > > <nfraprado@collabora.com> wrote:\n> > > >\n> > > > Now that the number of buffers allocated by the FrameBufferAllocator\n> > > > helper is passed through FrameBufferAllocator::allocate() and the\n> > > > pipelines no longer use bufferCount for internal buffer or V4L2 buffer\n> > > > slots allocation, we no longer need to have bufferCount in the\n> > > > StreamConfiguration, so remove it.\n> > > >\n> > > > Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>\n> > > > ---\n> > > >\n> > > > No changes in v7\n> > > >\n> > > > Changes in v6:\n> > > > - Removed IPU3_BUFFER_COUNT as it was unused\n> > > >\n> > > >  include/libcamera/stream.h                         |  2 --\n> > > >  src/android/camera_stream.cpp                      |  2 +-\n> > > >  src/libcamera/pipeline/ipu3/cio2.cpp               |  1 -\n> > > >  src/libcamera/pipeline/ipu3/ipu3.cpp               |  8 --------\n> > > >  src/libcamera/pipeline/raspberrypi/raspberrypi.cpp |  6 ------\n> > > >  src/libcamera/pipeline/rkisp1/rkisp1_path.cpp      |  2 --\n> > > >  src/libcamera/pipeline/simple/converter.cpp        |  3 ---\n> > > >  src/libcamera/pipeline/simple/converter.h          |  3 ---\n> > > >  src/libcamera/pipeline/simple/simple.cpp           |  5 +----\n> > > >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp       |  3 ---\n> > > >  src/libcamera/pipeline/vimc/vimc.cpp               |  3 ---\n> > > >  src/libcamera/stream.cpp                           |  9 ++-------\n> > > >  src/v4l2/v4l2_camera.cpp                           | 14 ++++++++++----\n> > > >  src/v4l2/v4l2_camera.h                             |  5 +++--\n> > > >  src/v4l2/v4l2_camera_proxy.cpp                     |  8 +++-----\n> > > >  test/camera/buffer_import.cpp                      | 10 +++++++---\n> > > >  test/libtest/buffer_source.cpp                     |  4 ++--\n> > > >  test/libtest/buffer_source.h                       |  2 +-\n> > > >  test/v4l2_videodevice/buffer_cache.cpp             |  4 ++--\n> > > >  19 files changed, 32 insertions(+), 62 deletions(-)\n> > > >\n> > > > diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\n> > > > index 0c55e7164592..b25f0059f2f1 100644\n> > > > --- a/include/libcamera/stream.h\n> > > > +++ b/include/libcamera/stream.h\n> > > > @@ -45,8 +45,6 @@ struct StreamConfiguration {\n> > > >         unsigned int stride;\n> > > >         unsigned int frameSize;\n> > > >\n> > > > -       unsigned int bufferCount;\n> > > > -\n> > > >         Stream *stream() const { return stream_; }\n> > > >         void setStream(Stream *stream) { stream_ = stream; }\n> > > >         const StreamFormats &formats() const { return formats_; }\n> > > > diff --git a/src/android/camera_stream.cpp b/src/android/camera_stream.cpp\n> > > > index b168e3c0c288..0794be409f82 100644\n> > > > --- a/src/android/camera_stream.cpp\n> > > > +++ b/src/android/camera_stream.cpp\n> > > > @@ -94,7 +94,7 @@ int CameraStream::configure()\n> > > >                         buffers_.push_back(frameBuffer.get());\n> > > >         }\n> > > >\n> > > > -       camera3Stream_->max_buffers = configuration().bufferCount;\n> > > > +       camera3Stream_->max_buffers = bufferCount;\n> > > >\n> > > >         return 0;\n> > > >  }\n> > > > diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > > index 1bcd580e251c..0e04e7214489 100644\n> > > > --- a/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > > +++ b/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > > @@ -214,7 +214,6 @@ StreamConfiguration CIO2Device::generateConfiguration(Size size) const\n> > > >\n> > > >         cfg.size = sensorFormat.size;\n> > > >         cfg.pixelFormat = mbusCodesToPixelFormat.at(sensorFormat.mbus_code);\n> > > > -       cfg.bufferCount = CIO2_BUFFER_COUNT;\n> > > >\n> > > >         return cfg;\n> > > >  }\n> > > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > index 4efd201c05e5..b223b3f33cd0 100644\n> > > > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > @@ -38,7 +38,6 @@ namespace libcamera {\n> > > >\n> > > >  LOG_DEFINE_CATEGORY(IPU3)\n> > > >\n> > > > -static constexpr unsigned int IPU3_BUFFER_COUNT = 4;\n> > > >  static constexpr unsigned int IPU3_MAX_STREAMS = 3;\n> > > >  static const Size IMGU_OUTPUT_MIN_SIZE = { 2, 2 };\n> > > >  static const Size IMGU_OUTPUT_MAX_SIZE = { 4480, 34004 };\n> > > > @@ -295,7 +294,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n> > > >                         /* Initialize the RAW stream with the CIO2 configuration. */\n> > > >                         cfg->size = cio2Configuration_.size;\n> > > >                         cfg->pixelFormat = cio2Configuration_.pixelFormat;\n> > > > -                       cfg->bufferCount = cio2Configuration_.bufferCount;\n> > > >                         cfg->stride = info.stride(cfg->size.width, 0, 64);\n> > > >                         cfg->frameSize = info.frameSize(cfg->size, 64);\n> > > >                         cfg->setStream(const_cast<Stream *>(&data_->rawStream_));\n> > > > @@ -339,7 +337,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n> > > >                                               IMGU_OUTPUT_HEIGHT_ALIGN);\n> > > >\n> > > >                         cfg->pixelFormat = formats::NV12;\n> > > > -                       cfg->bufferCount = IPU3_BUFFER_COUNT;\n> > > >                         cfg->stride = info.stride(cfg->size.width, 0, 1);\n> > > >                         cfg->frameSize = info.frameSize(cfg->size, 1);\n> > > >\n> > > > @@ -407,7 +404,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > >         Size sensorResolution = data->cio2_.sensor()->resolution();\n> > > >         for (const StreamRole role : roles) {\n> > > >                 std::map<PixelFormat, std::vector<SizeRange>> streamFormats;\n> > > > -               unsigned int bufferCount;\n> > > >                 PixelFormat pixelFormat;\n> > > >                 Size size;\n> > > >\n> > > > @@ -428,7 +424,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > >                         size.height = utils::alignDown(size.height - 1,\n> > > >                                                        IMGU_OUTPUT_HEIGHT_MARGIN);\n> > > >                         pixelFormat = formats::NV12;\n> > > > -                       bufferCount = IPU3_BUFFER_COUNT;\n> > > >                         streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n> > > >\n> > > >                         break;\n> > > > @@ -438,7 +433,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > >                                 data->cio2_.generateConfiguration(sensorResolution);\n> > > >                         pixelFormat = cio2Config.pixelFormat;\n> > > >                         size = cio2Config.size;\n> > > > -                       bufferCount = cio2Config.bufferCount;\n> > > >\n> > > >                         for (const PixelFormat &format : data->cio2_.formats())\n> > > >                                 streamFormats[format] = data->cio2_.sizes();\n> > > > @@ -457,7 +451,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > >                                                .alignedDownTo(IMGU_OUTPUT_WIDTH_ALIGN,\n> > > >                                                               IMGU_OUTPUT_HEIGHT_ALIGN);\n> > > >                         pixelFormat = formats::NV12;\n> > > > -                       bufferCount = IPU3_BUFFER_COUNT;\n> > > >                         streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n> > > >\n> > > >                         break;\n> > > > @@ -474,7 +467,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > >                 StreamConfiguration cfg(formats);\n> > > >                 cfg.size = size;\n> > > >                 cfg.pixelFormat = pixelFormat;\n> > > > -               cfg.bufferCount = bufferCount;\n> > > >                 config->addConfiguration(cfg);\n> > > >         }\n> > > >\n> > > > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > > index 776e0f92aed1..e6fc0425c3ef 100644\n> > > > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > > @@ -473,7 +473,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > >         RPiCameraData *data = cameraData(camera);\n> > > >         CameraConfiguration *config = new RPiCameraConfiguration(data);\n> > > >         V4L2DeviceFormat sensorFormat;\n> > > > -       unsigned int bufferCount;\n> > > >         PixelFormat pixelFormat;\n> > > >         V4L2VideoDevice::Formats fmts;\n> > > >         Size size;\n> > > > @@ -491,7 +490,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > >                         sensorFormat = findBestMode(fmts, size);\n> > > >                         pixelFormat = sensorFormat.fourcc.toPixelFormat();\n> > > >                         ASSERT(pixelFormat.isValid());\n> > > > -                       bufferCount = 2;\n> > > >                         rawCount++;\n> > > >                         break;\n> > > >\n> > > > @@ -500,7 +498,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > >                         pixelFormat = formats::NV12;\n> > > >                         /* Return the largest sensor resolution. */\n> > > >                         size = data->sensor_->resolution();\n> > > > -                       bufferCount = 1;\n> > > >                         outCount++;\n> > > >                         break;\n> > > >\n> > > > @@ -516,7 +513,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > >                         fmts = data->isp_[Isp::Output0].dev()->formats();\n> > > >                         pixelFormat = formats::YUV420;\n> > > >                         size = { 1920, 1080 };\n> > > > -                       bufferCount = 4;\n> > > >                         outCount++;\n> > > >                         break;\n> > > >\n> > > > @@ -524,7 +520,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > >                         fmts = data->isp_[Isp::Output0].dev()->formats();\n> > > >                         pixelFormat = formats::ARGB8888;\n> > > >                         size = { 800, 600 };\n> > > > -                       bufferCount = 4;\n> > > >                         outCount++;\n> > > >                         break;\n> > > >\n> > > > @@ -554,7 +549,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > >                 StreamConfiguration cfg(formats);\n> > > >                 cfg.size = size;\n> > > >                 cfg.pixelFormat = pixelFormat;\n> > > > -               cfg.bufferCount = bufferCount;\n> > > >                 config->addConfiguration(cfg);\n> > > >         }\n> > > >\n> > > > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > > index fea330f72886..4961f3971e59 100644\n> > > > --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > > +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > > @@ -61,7 +61,6 @@ StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution)\n> > > >         StreamConfiguration cfg(formats);\n> > > >         cfg.pixelFormat = formats::NV12;\n> > > >         cfg.size = maxResolution;\n> > > > -       cfg.bufferCount = RKISP1_BUFFER_COUNT;\n> > > >\n> > > >         return cfg;\n> > > >  }\n> > > > @@ -77,7 +76,6 @@ CameraConfiguration::Status RkISP1Path::validate(StreamConfiguration *cfg)\n> > > >\n> > > >         cfg->size.boundTo(maxResolution_);\n> > > >         cfg->size.expandTo(minResolution_);\n> > > > -       cfg->bufferCount = RKISP1_BUFFER_COUNT;\n> > > >\n> > > >         V4L2DeviceFormat format;\n> > > >         format.fourcc = video_->toV4L2PixelFormat(cfg->pixelFormat);\n> > > > diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp\n> > > > index b3bcf01483f7..fda417793e80 100644\n> > > > --- a/src/libcamera/pipeline/simple/converter.cpp\n> > > > +++ b/src/libcamera/pipeline/simple/converter.cpp\n> > > > @@ -89,9 +89,6 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg,\n> > > >                 return -EINVAL;\n> > > >         }\n> > > >\n> > > > -       inputBufferCount_ = inputCfg.bufferCount;\n> > > > -       outputBufferCount_ = outputCfg.bufferCount;\n> > > > -\n> > > >         return 0;\n> > > >  }\n> > > >\n> > > > diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h\n> > > > index 7e1d60674f62..406e63ca2a80 100644\n> > > > --- a/src/libcamera/pipeline/simple/converter.h\n> > > > +++ b/src/libcamera/pipeline/simple/converter.h\n> > > > @@ -87,9 +87,6 @@ private:\n> > > >                 SimpleConverter *converter_;\n> > > >                 unsigned int index_;\n> > > >                 std::unique_ptr<V4L2M2MDevice> m2m_;\n> > > > -\n> > > > -               unsigned int inputBufferCount_;\n> > > > -               unsigned int outputBufferCount_;\n> > > >         };\n> > > >\n> > > >         std::string deviceNode_;\n> > > > diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\n> > > > index a1163eaf8be2..ded04914f610 100644\n> > > > --- a/src/libcamera/pipeline/simple/simple.cpp\n> > > > +++ b/src/libcamera/pipeline/simple/simple.cpp\n> > > > @@ -628,7 +628,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n> > > >                     cfg.size != pipeConfig_->captureSize)\n> > > >                         needConversion_ = true;\n> > > >\n> > > > -               /* Set the stride, frameSize and bufferCount. */\n> > > > +               /* Set the stride and frameSize. */\n> > > >                 if (needConversion_) {\n> > > >                         std::tie(cfg.stride, cfg.frameSize) =\n> > > >                                 converter->strideAndFrameSize(cfg.pixelFormat, cfg.size);\n> > > > @@ -646,8 +646,6 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n> > > >                         cfg.stride = format.planes[0].bpl;\n> > > >                         cfg.frameSize = format.planes[0].size;\n> > > >                 }\n> > > > -\n> > > > -               cfg.bufferCount = 3;\n> > > >         }\n> > > >\n> > > >         return status;\n> > > > @@ -770,7 +768,6 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)\n> > > >         inputCfg.pixelFormat = pipeConfig->captureFormat;\n> > > >         inputCfg.size = pipeConfig->captureSize;\n> > > >         inputCfg.stride = captureFormat.planes[0].bpl;\n> > > > -       inputCfg.bufferCount = kNumInternalBuffers;\n> > > >\n> > > >         return converter_->configure(inputCfg, outputCfgs);\n> > > >  }\n> > > > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > > index 755949e7a59a..32482300f09a 100644\n> > > > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > > @@ -150,8 +150,6 @@ CameraConfiguration::Status UVCCameraConfiguration::validate()\n> > > >                 status = Adjusted;\n> > > >         }\n> > > >\n> > > > -       cfg.bufferCount = 4;\n> > > > -\n> > > >         V4L2DeviceFormat format;\n> > > >         format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n> > > >         format.size = cfg.size;\n> > > > @@ -193,7 +191,6 @@ CameraConfiguration *PipelineHandlerUVC::generateConfiguration(Camera *camera,\n> > > >\n> > > >         cfg.pixelFormat = formats.pixelformats().front();\n> > > >         cfg.size = formats.sizes(cfg.pixelFormat).back();\n> > > > -       cfg.bufferCount = 4;\n> > > >\n> > > >         config->addConfiguration(cfg);\n> > > >\n> > > > diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp\n> > > > index 24ba743a946c..a698427c4361 100644\n> > > > --- a/src/libcamera/pipeline/vimc/vimc.cpp\n> > > > +++ b/src/libcamera/pipeline/vimc/vimc.cpp\n> > > > @@ -167,8 +167,6 @@ CameraConfiguration::Status VimcCameraConfiguration::validate()\n> > > >                 status = Adjusted;\n> > > >         }\n> > > >\n> > > > -       cfg.bufferCount = 4;\n> > > > -\n> > > >         V4L2DeviceFormat format;\n> > > >         format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n> > > >         format.size = cfg.size;\n> > > > @@ -224,7 +222,6 @@ CameraConfiguration *PipelineHandlerVimc::generateConfiguration(Camera *camera,\n> > > >\n> > > >         cfg.pixelFormat = formats::BGR888;\n> > > >         cfg.size = { 1920, 1080 };\n> > > > -       cfg.bufferCount = 4;\n> > > >\n> > > >         config->addConfiguration(cfg);\n> > > >\n> > > > diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp\n> > > > index b8626775d224..ca507b72b26a 100644\n> > > > --- a/src/libcamera/stream.cpp\n> > > > +++ b/src/libcamera/stream.cpp\n> > > > @@ -280,7 +280,7 @@ SizeRange StreamFormats::range(const PixelFormat &pixelformat) const\n> > > >   * handlers provide StreamFormats.\n> > > >   */\n> > > >  StreamConfiguration::StreamConfiguration()\n> > > > -       : pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> > > > +       : pixelFormat(0), stride(0), frameSize(0),\n> > > >           stream_(nullptr)\n> > > >  {\n> > > >  }\n> > > > @@ -289,7 +289,7 @@ StreamConfiguration::StreamConfiguration()\n> > > >   * \\brief Construct a configuration with stream formats\n> > > >   */\n> > > >  StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n> > > > -       : pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> > > > +       : pixelFormat(0), stride(0), frameSize(0),\n> > > >           stream_(nullptr), formats_(formats)\n> > > >  {\n> > > >  }\n> > > > @@ -324,11 +324,6 @@ StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n> > > >   * validating the configuration with a call to CameraConfiguration::validate().\n> > > >   */\n> > > >\n> > > > -/**\n> > > > - * \\var StreamConfiguration::bufferCount\n> > > > - * \\brief Requested number of buffers to allocate for the stream\n> > > > - */\n> > > > -\n> > > >  /**\n> > > >   * \\fn StreamConfiguration::stream()\n> > > >   * \\brief Retrieve the stream associated with the configuration\n> > > > diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp\n> > > > index d01eacfa2b84..2ff9affc6388 100644\n> > > > --- a/src/v4l2/v4l2_camera.cpp\n> > > > +++ b/src/v4l2/v4l2_camera.cpp\n> > > > @@ -12,6 +12,8 @@\n> > > >\n> > > >  #include <libcamera/base/log.h>\n> > > >\n> > > > +#include <libcamera/property_ids.h>\n> > > > +\n> > > >  using namespace libcamera;\n> > > >\n> > > >  LOG_DECLARE_CATEGORY(V4L2Compat)\n> > > > @@ -107,14 +109,12 @@ void V4L2Camera::requestComplete(Request *request)\n> > > >  }\n> > > >\n> > > >  int V4L2Camera::configure(StreamConfiguration *streamConfigOut,\n> > > > -                         const Size &size, const PixelFormat &pixelformat,\n> > > > -                         unsigned int bufferCount)\n> > > > +                         const Size &size, const PixelFormat &pixelformat)\n> > > >  {\n> > > >         StreamConfiguration &streamConfig = config_->at(0);\n> > > >         streamConfig.size.width = size.width;\n> > > >         streamConfig.size.height = size.height;\n> > > >         streamConfig.pixelFormat = pixelformat;\n> > > > -       streamConfig.bufferCount = bufferCount;\n> > > >         /* \\todo memoryType (interval vs external) */\n> > > >\n> > > >         CameraConfiguration::Status validation = config_->validate();\n> > > > @@ -146,7 +146,6 @@ int V4L2Camera::validateConfiguration(const PixelFormat &pixelFormat,\n> > > >         StreamConfiguration &cfg = config->at(0);\n> > > >         cfg.size = size;\n> > > >         cfg.pixelFormat = pixelFormat;\n> > > > -       cfg.bufferCount = 1;\n> > > >\n> > > >         CameraConfiguration::Status validation = config->validate();\n> > > >         if (validation == CameraConfiguration::Invalid)\n> > > > @@ -299,3 +298,10 @@ bool V4L2Camera::isRunning()\n> > > >  {\n> > > >         return isRunning_;\n> > > >  }\n> > > > +\n> > > > +unsigned int V4L2Camera::minimumRequests(unsigned int count)\n> > > > +{\n> > > > +       unsigned int min = camera_->properties().get(properties::MinimumRequests);\n> > > > +\n> > > > +       return std::max(count, min);\n> > > > +}\n> > > > diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h\n> > > > index a095f4e27524..4b5618ac12b5 100644\n> > > > --- a/src/v4l2/v4l2_camera.h\n> > > > +++ b/src/v4l2/v4l2_camera.h\n> > > > @@ -45,8 +45,7 @@ public:\n> > > >         std::vector<Buffer> completedBuffers();\n> > > >\n> > > >         int configure(StreamConfiguration *streamConfigOut,\n> > > > -                     const Size &size, const PixelFormat &pixelformat,\n> > > > -                     unsigned int bufferCount);\n> > > > +                     const Size &size, const PixelFormat &pixelformat);\n> > > >         int validateConfiguration(const PixelFormat &pixelformat,\n> > > >                                   const Size &size,\n> > > >                                   StreamConfiguration *streamConfigOut);\n> > > > @@ -65,6 +64,8 @@ public:\n> > > >\n> > > >         bool isRunning();\n> > > >\n> > > > +       unsigned int minimumRequests(unsigned int count);\n> > > > +\n> > > >  private:\n> > > >         void requestComplete(Request *request);\n> > > >\n> > > > diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp\n> > > > index 7682c4bddf90..634ec84e0cbb 100644\n> > > > --- a/src/v4l2/v4l2_camera_proxy.cpp\n> > > > +++ b/src/v4l2/v4l2_camera_proxy.cpp\n> > > > @@ -349,8 +349,7 @@ int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg)\n> > > >         Size size(arg->fmt.pix.width, arg->fmt.pix.height);\n> > > >         V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->fmt.pix.pixelformat);\n> > > >         ret = vcam_->configure(&streamConfig_, size,\n> > > > -                              PixelFormatInfo::info(v4l2Format).format,\n> > > > -                              bufferCount_);\n> > > > +                              PixelFormatInfo::info(v4l2Format).format);\n> > > >         if (ret < 0)\n> > > >                 return -EINVAL;\n> > > >\n> > > > @@ -491,14 +490,13 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf\n> > > >         Size size(v4l2PixFormat_.width, v4l2PixFormat_.height);\n> > > >         V4L2PixelFormat v4l2Format = V4L2PixelFormat(v4l2PixFormat_.pixelformat);\n> > > >         int ret = vcam_->configure(&streamConfig_, size,\n> > > > -                                  PixelFormatInfo::info(v4l2Format).format,\n> > > > -                                  arg->count);\n> > > > +                                  PixelFormatInfo::info(v4l2Format).format);\n> > > >         if (ret < 0)\n> > > >                 return -EINVAL;\n> > > >\n> > > >         setFmtFromConfig(streamConfig_);\n> > > >\n> > > > -       arg->count = streamConfig_.bufferCount;\n> > > > +       arg->count = vcam_->minimumRequests(arg->count);\n> > > >         bufferCount_ = arg->count;\n> > > >\n> > > >         ret = vcam_->allocBuffers(arg->count);\n> > > > diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp\n> > > > index c504ea09e64b..67ac0ad20e15 100644\n> > > > --- a/test/camera/buffer_import.cpp\n> > > > +++ b/test/camera/buffer_import.cpp\n> > > > @@ -16,6 +16,8 @@\n> > > >  #include <libcamera/base/thread.h>\n> > > >  #include <libcamera/base/timer.h>\n> > > >\n> > > > +#include <libcamera/property_ids.h>\n> > > > +\n> > > >  #include \"libcamera/internal/device_enumerator.h\"\n> > > >  #include \"libcamera/internal/media_device.h\"\n> > > >  #include \"libcamera/internal/v4l2_videodevice.h\"\n> > > > @@ -92,10 +94,12 @@ protected:\n> > > >                         return TestFail;\n> > > >                 }\n> > > >\n> > > > +               unsigned int bufferCount = camera_->properties().get(properties::MinimumRequests);\n> > > > +\n> > > >                 Stream *stream = cfg.stream();\n> > > >\n> > > >                 BufferSource source;\n> > > > -               int ret = source.allocate(cfg);\n> > > > +               int ret = source.allocate(cfg, bufferCount);\n> > > >                 if (ret != TestPass)\n> > > >                         return ret;\n> > > >\n> > > > @@ -139,10 +143,10 @@ protected:\n> > > >                 while (timer.isRunning())\n> > > >                         dispatcher->processEvents();\n> > > >\n> > > > -               if (completeRequestsCount_ < cfg.bufferCount * 2) {\n> > > > +               if (completeRequestsCount_ < bufferCount * 2) {\n> > > >                         std::cout << \"Failed to capture enough frames (got \"\n> > > >                                   << completeRequestsCount_ << \" expected at least \"\n> > > > -                                 << cfg.bufferCount * 2 << \")\" << std::endl;\n> > > > +                                 << bufferCount * 2 << \")\" << std::endl;\n> > > >                         return TestFail;\n> > > >                 }\n> > > >\n> > > > diff --git a/test/libtest/buffer_source.cpp b/test/libtest/buffer_source.cpp\n> > > > index 73563f2fc39d..c3d5286a2462 100644\n> > > > --- a/test/libtest/buffer_source.cpp\n> > > > +++ b/test/libtest/buffer_source.cpp\n> > > > @@ -24,7 +24,7 @@ BufferSource::~BufferSource()\n> > > >                 media_->release();\n> > > >  }\n> > > >\n> > > > -int BufferSource::allocate(const StreamConfiguration &config)\n> > > > +int BufferSource::allocate(const StreamConfiguration &config, unsigned int count)\n> > > >  {\n> > > >         /* Locate and open the video device. */\n> > > >         std::string videoDeviceName = \"vivid-000-vid-out\";\n> > > > @@ -77,7 +77,7 @@ int BufferSource::allocate(const StreamConfiguration &config)\n> > > >                 return TestFail;\n> > > >         }\n> > > >\n> > > > -       if (video->allocateBuffers(config.bufferCount, &buffers_) < 0) {\n> > > > +       if (video->allocateBuffers(count, &buffers_) < 0) {\n> > > >                 std::cout << \"Failed to allocate buffers\" << std::endl;\n> > > >                 return TestFail;\n> > > >         }\n> > > > diff --git a/test/libtest/buffer_source.h b/test/libtest/buffer_source.h\n> > > > index 14b4770e8d8a..6a18e269a575 100644\n> > > > --- a/test/libtest/buffer_source.h\n> > > > +++ b/test/libtest/buffer_source.h\n> > > > @@ -20,7 +20,7 @@ public:\n> > > >         BufferSource();\n> > > >         ~BufferSource();\n> > > >\n> > > > -       int allocate(const StreamConfiguration &config);\n> > > > +       int allocate(const StreamConfiguration &config, unsigned int count);\n> > > >         const std::vector<std::unique_ptr<FrameBuffer>> &buffers();\n> > > >\n> > > >  private:\n> > > > diff --git a/test/v4l2_videodevice/buffer_cache.cpp b/test/v4l2_videodevice/buffer_cache.cpp\n> > > > index b3f2bec11783..07fddfd2617c 100644\n> > > > --- a/test/v4l2_videodevice/buffer_cache.cpp\n> > > > +++ b/test/v4l2_videodevice/buffer_cache.cpp\n> > > > @@ -10,6 +10,7 @@\n> > > >  #include <vector>\n> > > >\n> > > >  #include <libcamera/formats.h>\n> > > > +#include <libcamera/property_ids.h>\n> > > >  #include <libcamera/stream.h>\n> > > >\n> > > >  #include \"buffer_source.h\"\n> > > > @@ -145,10 +146,9 @@ public:\n> > > >                 StreamConfiguration cfg;\n> > > >                 cfg.pixelFormat = formats::YUYV;\n> > > >                 cfg.size = Size(600, 800);\n> > > > -               cfg.bufferCount = numBuffers;\n> > > >\n> > > >                 BufferSource source;\n> > > > -               int ret = source.allocate(cfg);\n> > > > +               int ret = source.allocate(cfg, numBuffers);\n> > > >                 if (ret != TestPass)\n> > > >                         return ret;\n> > > >\n> > > > --\n> > > > 2.32.0\n> > > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id BA4A2C322C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 23 Jul 2021 21:08:46 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 2E4A9687A9;\n\tFri, 23 Jul 2021 23:08:46 +0200 (CEST)","from bhuna.collabora.co.uk (bhuna.collabora.co.uk\n\t[IPv6:2a00:1098:0:82:1000:25:2eeb:e3e3])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id CBA2A68537\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 23 Jul 2021 23:08:44 +0200 (CEST)","from [127.0.0.1] (localhost [127.0.0.1])\n\t(Authenticated sender: nfraprado) with ESMTPSA id E81401F44E7F"],"Date":"Fri, 23 Jul 2021 18:08:07 -0300","From":"=?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4=?= Prado <nfraprado@collabora.com>","To":"David Plowman <david.plowman@raspberrypi.com>","Message-ID":"<20210723210807.emekovdwbehrzr44@notapiano>","References":"<20210722232851.747614-1-nfraprado@collabora.com>\n\t<20210722232851.747614-11-nfraprado@collabora.com>\n\t<CAHW6GYJbVdFebNca9ZeM8LY=Ca4P1uaUd3B-r5FF7mJ9k853fg@mail.gmail.com>\n\t<20210723131039.ire2z7u6sdxws3dt@notapiano>\n\t<CAHW6GYKCBXmNSzo+_EcQCvJEaPg-ahMsWXKwVA=J8YzZEtBUWA@mail.gmail.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=iso-8859-1","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<CAHW6GYKCBXmNSzo+_EcQCvJEaPg-ahMsWXKwVA=J8YzZEtBUWA@mail.gmail.com>","Subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>,\n\tkernel@collabora.com, =?utf-8?b?QW5kcsOp?=\n\tAlmeida <andrealmeid@collabora.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":18417,"web_url":"https://patchwork.libcamera.org/comment/18417/","msgid":"<CAHW6GYLbPU0TKbMNeNsHdif6Nm+-iUfBgRAcnUN6=ftKYsmYoQ@mail.gmail.com>","date":"2021-07-29T10:00:33","subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","submitter":{"id":42,"url":"https://patchwork.libcamera.org/api/people/42/","name":"David Plowman","email":"david.plowman@raspberrypi.com"},"content":"Hi again\n\nI thought that perhaps I could explain in more detail why I think\napplications need to be able to set (or influence) the buffer count\nand not leave it to the pipeline handler. My use-case is as follows.\n\nI'm running some standard sort of application such as video recording\nfor which there are maybe 4 buffers allocated. Now, I also want to do\nsome image analysis that perhaps causes me to change something about\nthe recording (maybe change camera settings, or even stop the\nrecording). But this image analysis task is relatively slow.\n\nOne option is to copy the camera frames so that I can return the\nbuffers in the request back to the camera. But copying images is\ngenerally undesirable. Instead I'd prefer to hold on to the buffer\nonly now my camera pipeline is effectively working with only 3\nbuffers, which is not enough. When I eventually finish with the buffer\nI will return it, and then grab the next one to keep again!\n\nSo at the very least, the application needs to be able to say \"please\nallocate <n> more buffers than you thought you needed\". Does that make\nsense? Will this be possible in the new scheme?\n\nThanks!\nDavid\n\nOn Fri, 23 Jul 2021 at 22:08, Nícolas F. R. A. Prado\n<nfraprado@collabora.com> wrote:\n>\n> Hi David,\n>\n> On Fri, Jul 23, 2021 at 04:53:55PM +0100, David Plowman wrote:\n> > Hi Nicolas\n> >\n> > Thanks for the explanations. I'm still not sure I entirely understand\n> > so perhaps a quick look at how I would have to change my application\n> > code might help? Here's what I have now (I've removed any\n> > \"unimportant\" bits!):\n> >\n> > configuration_ = camera_->generateConfiguration({ StreamRole::StillCapture });\n> > configuration_->at(0).bufferCount = <value I have determined>;\n> > camera_->configure(configuration_.get());\n> > allocator_ = new FrameBufferAllocator(camera_);\n> > Stream *stream = configuration_->at(0).stream();\n> > allocator_->allocate(stream);\n> > // now allocator_->buffers(stream) has the buffers I want!\n> >\n> > I guess one thing to note is that the bufferCount value varies with\n> > more than just the StreamRole, and I don't in general trust the\n> > pipeline handler to \"know\" what I want. Will this still be possible?\n>\n> Oh I see... No, this won't be possible after we drop bufferCount. The\n> pipeline handler will decide for itself how many buffers to allocate internally,\n> possibly using the StreamRole as a hint.\n>\n> I wasn't aware this could impact an application, since all the other pipeline\n> handlers actually ignore when bufferCount is set by the application, overriding\n> it when the configuration is validated. But now I'm noticing the raspberrypi\n> pipeline actually uses it.\n>\n> Some context: This series actually began with me making\n> FrameBufferAllocator::allocate() receive a count argument instead of using the\n> value of bufferCount. But since Laurent mentioned that bufferCount was going\n> away eventually anyway I ended up removing it as well as part of this series.\n>\n> I do understand how being able to specify a bufferCount value that suits your\n> specific usecase is useful, though... Laurent, what's your take on this? :)\n>\n> Thanks,\n> Nícolas\n>\n> >\n> > Thanks!\n> > David\n> >\n> > On Fri, 23 Jul 2021 at 14:10, Nícolas F. R. A. Prado\n> > <nfraprado@collabora.com> wrote:\n> > >\n> > > Hi David,\n> > >\n> > > On Fri, Jul 23, 2021 at 09:42:56AM +0100, David Plowman wrote:\n> > > > Hi Nicolas\n> > > >\n> > > > Thanks very much for all this work! I was wondering if I could ask a\n> > > > little more about this patch. In our applications, for example, we set\n> > > > the bufferCount according to the use-case that the application is\n> > > > implementing. For example:\n> > > >\n> > > > * For preview windows we set bufferCount to 4.\n> > > > * For video capture we drop fewer frames with a deeper queue so we set it to 6.\n> > > > * For stills capture we can get by with one frame, though use cases\n> > > > that capture several stills images for fusion work better if we set\n> > > > bufferCount to 2 or 3.\n> > > >\n> > > > I was wondering how our applications can achieve this behaviour if the\n> > > > bufferCount field is no longer available.\n> > >\n> > > Okay, so the short answer is that the applications, knowing their particular use\n> > > case, are responsible to provide enough requests to keep the pipeline going. On\n> > > the pipeline handler side, it's free to use how many internal buffers it wants.\n> > >\n> > > So in your case, the pipeline handler could still allocate that same number of\n> > > internal buffers as you previously did based on bufferCount, but now based\n> > > solely on the StreamRole set. The application would then allocate and queue\n> > > how many buffers fits the usage. (Note that before the application would call\n> > > FrameBufferAllocator::allocate() and it would allocate 'bufferCount' buffers,\n> > > but now the function takes a count argument so the application is free to choose\n> > > how many)\n> > >\n> > > Now, I guess it would be nice for the application to be able to query what is a\n> > > good number of buffers to use, for example 6 in the video capture of your use\n> > > case. At the moment, the only information available is that 1 is the minimum\n> > > number of buffers required. So the application would have to know that 6 is a\n> > > good number for video capture. Maybe another property could be introduced later\n> > > for this recommended amount, but previous discussions suggested this is very use\n> > > case dependent, so might not make sense.\n> > >\n> > > I hope this answers the question. If not, I'm still here :).\n> > >\n> > > Thanks,\n> > > Nícolas\n> > >\n> > > >\n> > > > Thanks!\n> > > > David\n> > > >\n> > > > On Fri, 23 Jul 2021 at 00:29, Nícolas F. R. A. Prado\n> > > > <nfraprado@collabora.com> wrote:\n> > > > >\n> > > > > Now that the number of buffers allocated by the FrameBufferAllocator\n> > > > > helper is passed through FrameBufferAllocator::allocate() and the\n> > > > > pipelines no longer use bufferCount for internal buffer or V4L2 buffer\n> > > > > slots allocation, we no longer need to have bufferCount in the\n> > > > > StreamConfiguration, so remove it.\n> > > > >\n> > > > > Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>\n> > > > > ---\n> > > > >\n> > > > > No changes in v7\n> > > > >\n> > > > > Changes in v6:\n> > > > > - Removed IPU3_BUFFER_COUNT as it was unused\n> > > > >\n> > > > >  include/libcamera/stream.h                         |  2 --\n> > > > >  src/android/camera_stream.cpp                      |  2 +-\n> > > > >  src/libcamera/pipeline/ipu3/cio2.cpp               |  1 -\n> > > > >  src/libcamera/pipeline/ipu3/ipu3.cpp               |  8 --------\n> > > > >  src/libcamera/pipeline/raspberrypi/raspberrypi.cpp |  6 ------\n> > > > >  src/libcamera/pipeline/rkisp1/rkisp1_path.cpp      |  2 --\n> > > > >  src/libcamera/pipeline/simple/converter.cpp        |  3 ---\n> > > > >  src/libcamera/pipeline/simple/converter.h          |  3 ---\n> > > > >  src/libcamera/pipeline/simple/simple.cpp           |  5 +----\n> > > > >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp       |  3 ---\n> > > > >  src/libcamera/pipeline/vimc/vimc.cpp               |  3 ---\n> > > > >  src/libcamera/stream.cpp                           |  9 ++-------\n> > > > >  src/v4l2/v4l2_camera.cpp                           | 14 ++++++++++----\n> > > > >  src/v4l2/v4l2_camera.h                             |  5 +++--\n> > > > >  src/v4l2/v4l2_camera_proxy.cpp                     |  8 +++-----\n> > > > >  test/camera/buffer_import.cpp                      | 10 +++++++---\n> > > > >  test/libtest/buffer_source.cpp                     |  4 ++--\n> > > > >  test/libtest/buffer_source.h                       |  2 +-\n> > > > >  test/v4l2_videodevice/buffer_cache.cpp             |  4 ++--\n> > > > >  19 files changed, 32 insertions(+), 62 deletions(-)\n> > > > >\n> > > > > diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\n> > > > > index 0c55e7164592..b25f0059f2f1 100644\n> > > > > --- a/include/libcamera/stream.h\n> > > > > +++ b/include/libcamera/stream.h\n> > > > > @@ -45,8 +45,6 @@ struct StreamConfiguration {\n> > > > >         unsigned int stride;\n> > > > >         unsigned int frameSize;\n> > > > >\n> > > > > -       unsigned int bufferCount;\n> > > > > -\n> > > > >         Stream *stream() const { return stream_; }\n> > > > >         void setStream(Stream *stream) { stream_ = stream; }\n> > > > >         const StreamFormats &formats() const { return formats_; }\n> > > > > diff --git a/src/android/camera_stream.cpp b/src/android/camera_stream.cpp\n> > > > > index b168e3c0c288..0794be409f82 100644\n> > > > > --- a/src/android/camera_stream.cpp\n> > > > > +++ b/src/android/camera_stream.cpp\n> > > > > @@ -94,7 +94,7 @@ int CameraStream::configure()\n> > > > >                         buffers_.push_back(frameBuffer.get());\n> > > > >         }\n> > > > >\n> > > > > -       camera3Stream_->max_buffers = configuration().bufferCount;\n> > > > > +       camera3Stream_->max_buffers = bufferCount;\n> > > > >\n> > > > >         return 0;\n> > > > >  }\n> > > > > diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > > > index 1bcd580e251c..0e04e7214489 100644\n> > > > > --- a/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > > > +++ b/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > > > @@ -214,7 +214,6 @@ StreamConfiguration CIO2Device::generateConfiguration(Size size) const\n> > > > >\n> > > > >         cfg.size = sensorFormat.size;\n> > > > >         cfg.pixelFormat = mbusCodesToPixelFormat.at(sensorFormat.mbus_code);\n> > > > > -       cfg.bufferCount = CIO2_BUFFER_COUNT;\n> > > > >\n> > > > >         return cfg;\n> > > > >  }\n> > > > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > > index 4efd201c05e5..b223b3f33cd0 100644\n> > > > > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > > @@ -38,7 +38,6 @@ namespace libcamera {\n> > > > >\n> > > > >  LOG_DEFINE_CATEGORY(IPU3)\n> > > > >\n> > > > > -static constexpr unsigned int IPU3_BUFFER_COUNT = 4;\n> > > > >  static constexpr unsigned int IPU3_MAX_STREAMS = 3;\n> > > > >  static const Size IMGU_OUTPUT_MIN_SIZE = { 2, 2 };\n> > > > >  static const Size IMGU_OUTPUT_MAX_SIZE = { 4480, 34004 };\n> > > > > @@ -295,7 +294,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n> > > > >                         /* Initialize the RAW stream with the CIO2 configuration. */\n> > > > >                         cfg->size = cio2Configuration_.size;\n> > > > >                         cfg->pixelFormat = cio2Configuration_.pixelFormat;\n> > > > > -                       cfg->bufferCount = cio2Configuration_.bufferCount;\n> > > > >                         cfg->stride = info.stride(cfg->size.width, 0, 64);\n> > > > >                         cfg->frameSize = info.frameSize(cfg->size, 64);\n> > > > >                         cfg->setStream(const_cast<Stream *>(&data_->rawStream_));\n> > > > > @@ -339,7 +337,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n> > > > >                                               IMGU_OUTPUT_HEIGHT_ALIGN);\n> > > > >\n> > > > >                         cfg->pixelFormat = formats::NV12;\n> > > > > -                       cfg->bufferCount = IPU3_BUFFER_COUNT;\n> > > > >                         cfg->stride = info.stride(cfg->size.width, 0, 1);\n> > > > >                         cfg->frameSize = info.frameSize(cfg->size, 1);\n> > > > >\n> > > > > @@ -407,7 +404,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > >         Size sensorResolution = data->cio2_.sensor()->resolution();\n> > > > >         for (const StreamRole role : roles) {\n> > > > >                 std::map<PixelFormat, std::vector<SizeRange>> streamFormats;\n> > > > > -               unsigned int bufferCount;\n> > > > >                 PixelFormat pixelFormat;\n> > > > >                 Size size;\n> > > > >\n> > > > > @@ -428,7 +424,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > >                         size.height = utils::alignDown(size.height - 1,\n> > > > >                                                        IMGU_OUTPUT_HEIGHT_MARGIN);\n> > > > >                         pixelFormat = formats::NV12;\n> > > > > -                       bufferCount = IPU3_BUFFER_COUNT;\n> > > > >                         streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n> > > > >\n> > > > >                         break;\n> > > > > @@ -438,7 +433,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > >                                 data->cio2_.generateConfiguration(sensorResolution);\n> > > > >                         pixelFormat = cio2Config.pixelFormat;\n> > > > >                         size = cio2Config.size;\n> > > > > -                       bufferCount = cio2Config.bufferCount;\n> > > > >\n> > > > >                         for (const PixelFormat &format : data->cio2_.formats())\n> > > > >                                 streamFormats[format] = data->cio2_.sizes();\n> > > > > @@ -457,7 +451,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > >                                                .alignedDownTo(IMGU_OUTPUT_WIDTH_ALIGN,\n> > > > >                                                               IMGU_OUTPUT_HEIGHT_ALIGN);\n> > > > >                         pixelFormat = formats::NV12;\n> > > > > -                       bufferCount = IPU3_BUFFER_COUNT;\n> > > > >                         streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n> > > > >\n> > > > >                         break;\n> > > > > @@ -474,7 +467,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > >                 StreamConfiguration cfg(formats);\n> > > > >                 cfg.size = size;\n> > > > >                 cfg.pixelFormat = pixelFormat;\n> > > > > -               cfg.bufferCount = bufferCount;\n> > > > >                 config->addConfiguration(cfg);\n> > > > >         }\n> > > > >\n> > > > > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > > > index 776e0f92aed1..e6fc0425c3ef 100644\n> > > > > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > > > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > > > @@ -473,7 +473,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > >         RPiCameraData *data = cameraData(camera);\n> > > > >         CameraConfiguration *config = new RPiCameraConfiguration(data);\n> > > > >         V4L2DeviceFormat sensorFormat;\n> > > > > -       unsigned int bufferCount;\n> > > > >         PixelFormat pixelFormat;\n> > > > >         V4L2VideoDevice::Formats fmts;\n> > > > >         Size size;\n> > > > > @@ -491,7 +490,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > >                         sensorFormat = findBestMode(fmts, size);\n> > > > >                         pixelFormat = sensorFormat.fourcc.toPixelFormat();\n> > > > >                         ASSERT(pixelFormat.isValid());\n> > > > > -                       bufferCount = 2;\n> > > > >                         rawCount++;\n> > > > >                         break;\n> > > > >\n> > > > > @@ -500,7 +498,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > >                         pixelFormat = formats::NV12;\n> > > > >                         /* Return the largest sensor resolution. */\n> > > > >                         size = data->sensor_->resolution();\n> > > > > -                       bufferCount = 1;\n> > > > >                         outCount++;\n> > > > >                         break;\n> > > > >\n> > > > > @@ -516,7 +513,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > >                         fmts = data->isp_[Isp::Output0].dev()->formats();\n> > > > >                         pixelFormat = formats::YUV420;\n> > > > >                         size = { 1920, 1080 };\n> > > > > -                       bufferCount = 4;\n> > > > >                         outCount++;\n> > > > >                         break;\n> > > > >\n> > > > > @@ -524,7 +520,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > >                         fmts = data->isp_[Isp::Output0].dev()->formats();\n> > > > >                         pixelFormat = formats::ARGB8888;\n> > > > >                         size = { 800, 600 };\n> > > > > -                       bufferCount = 4;\n> > > > >                         outCount++;\n> > > > >                         break;\n> > > > >\n> > > > > @@ -554,7 +549,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > >                 StreamConfiguration cfg(formats);\n> > > > >                 cfg.size = size;\n> > > > >                 cfg.pixelFormat = pixelFormat;\n> > > > > -               cfg.bufferCount = bufferCount;\n> > > > >                 config->addConfiguration(cfg);\n> > > > >         }\n> > > > >\n> > > > > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > > > index fea330f72886..4961f3971e59 100644\n> > > > > --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > > > +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > > > @@ -61,7 +61,6 @@ StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution)\n> > > > >         StreamConfiguration cfg(formats);\n> > > > >         cfg.pixelFormat = formats::NV12;\n> > > > >         cfg.size = maxResolution;\n> > > > > -       cfg.bufferCount = RKISP1_BUFFER_COUNT;\n> > > > >\n> > > > >         return cfg;\n> > > > >  }\n> > > > > @@ -77,7 +76,6 @@ CameraConfiguration::Status RkISP1Path::validate(StreamConfiguration *cfg)\n> > > > >\n> > > > >         cfg->size.boundTo(maxResolution_);\n> > > > >         cfg->size.expandTo(minResolution_);\n> > > > > -       cfg->bufferCount = RKISP1_BUFFER_COUNT;\n> > > > >\n> > > > >         V4L2DeviceFormat format;\n> > > > >         format.fourcc = video_->toV4L2PixelFormat(cfg->pixelFormat);\n> > > > > diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp\n> > > > > index b3bcf01483f7..fda417793e80 100644\n> > > > > --- a/src/libcamera/pipeline/simple/converter.cpp\n> > > > > +++ b/src/libcamera/pipeline/simple/converter.cpp\n> > > > > @@ -89,9 +89,6 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg,\n> > > > >                 return -EINVAL;\n> > > > >         }\n> > > > >\n> > > > > -       inputBufferCount_ = inputCfg.bufferCount;\n> > > > > -       outputBufferCount_ = outputCfg.bufferCount;\n> > > > > -\n> > > > >         return 0;\n> > > > >  }\n> > > > >\n> > > > > diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h\n> > > > > index 7e1d60674f62..406e63ca2a80 100644\n> > > > > --- a/src/libcamera/pipeline/simple/converter.h\n> > > > > +++ b/src/libcamera/pipeline/simple/converter.h\n> > > > > @@ -87,9 +87,6 @@ private:\n> > > > >                 SimpleConverter *converter_;\n> > > > >                 unsigned int index_;\n> > > > >                 std::unique_ptr<V4L2M2MDevice> m2m_;\n> > > > > -\n> > > > > -               unsigned int inputBufferCount_;\n> > > > > -               unsigned int outputBufferCount_;\n> > > > >         };\n> > > > >\n> > > > >         std::string deviceNode_;\n> > > > > diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\n> > > > > index a1163eaf8be2..ded04914f610 100644\n> > > > > --- a/src/libcamera/pipeline/simple/simple.cpp\n> > > > > +++ b/src/libcamera/pipeline/simple/simple.cpp\n> > > > > @@ -628,7 +628,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n> > > > >                     cfg.size != pipeConfig_->captureSize)\n> > > > >                         needConversion_ = true;\n> > > > >\n> > > > > -               /* Set the stride, frameSize and bufferCount. */\n> > > > > +               /* Set the stride and frameSize. */\n> > > > >                 if (needConversion_) {\n> > > > >                         std::tie(cfg.stride, cfg.frameSize) =\n> > > > >                                 converter->strideAndFrameSize(cfg.pixelFormat, cfg.size);\n> > > > > @@ -646,8 +646,6 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n> > > > >                         cfg.stride = format.planes[0].bpl;\n> > > > >                         cfg.frameSize = format.planes[0].size;\n> > > > >                 }\n> > > > > -\n> > > > > -               cfg.bufferCount = 3;\n> > > > >         }\n> > > > >\n> > > > >         return status;\n> > > > > @@ -770,7 +768,6 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)\n> > > > >         inputCfg.pixelFormat = pipeConfig->captureFormat;\n> > > > >         inputCfg.size = pipeConfig->captureSize;\n> > > > >         inputCfg.stride = captureFormat.planes[0].bpl;\n> > > > > -       inputCfg.bufferCount = kNumInternalBuffers;\n> > > > >\n> > > > >         return converter_->configure(inputCfg, outputCfgs);\n> > > > >  }\n> > > > > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > > > index 755949e7a59a..32482300f09a 100644\n> > > > > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > > > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > > > @@ -150,8 +150,6 @@ CameraConfiguration::Status UVCCameraConfiguration::validate()\n> > > > >                 status = Adjusted;\n> > > > >         }\n> > > > >\n> > > > > -       cfg.bufferCount = 4;\n> > > > > -\n> > > > >         V4L2DeviceFormat format;\n> > > > >         format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n> > > > >         format.size = cfg.size;\n> > > > > @@ -193,7 +191,6 @@ CameraConfiguration *PipelineHandlerUVC::generateConfiguration(Camera *camera,\n> > > > >\n> > > > >         cfg.pixelFormat = formats.pixelformats().front();\n> > > > >         cfg.size = formats.sizes(cfg.pixelFormat).back();\n> > > > > -       cfg.bufferCount = 4;\n> > > > >\n> > > > >         config->addConfiguration(cfg);\n> > > > >\n> > > > > diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp\n> > > > > index 24ba743a946c..a698427c4361 100644\n> > > > > --- a/src/libcamera/pipeline/vimc/vimc.cpp\n> > > > > +++ b/src/libcamera/pipeline/vimc/vimc.cpp\n> > > > > @@ -167,8 +167,6 @@ CameraConfiguration::Status VimcCameraConfiguration::validate()\n> > > > >                 status = Adjusted;\n> > > > >         }\n> > > > >\n> > > > > -       cfg.bufferCount = 4;\n> > > > > -\n> > > > >         V4L2DeviceFormat format;\n> > > > >         format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n> > > > >         format.size = cfg.size;\n> > > > > @@ -224,7 +222,6 @@ CameraConfiguration *PipelineHandlerVimc::generateConfiguration(Camera *camera,\n> > > > >\n> > > > >         cfg.pixelFormat = formats::BGR888;\n> > > > >         cfg.size = { 1920, 1080 };\n> > > > > -       cfg.bufferCount = 4;\n> > > > >\n> > > > >         config->addConfiguration(cfg);\n> > > > >\n> > > > > diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp\n> > > > > index b8626775d224..ca507b72b26a 100644\n> > > > > --- a/src/libcamera/stream.cpp\n> > > > > +++ b/src/libcamera/stream.cpp\n> > > > > @@ -280,7 +280,7 @@ SizeRange StreamFormats::range(const PixelFormat &pixelformat) const\n> > > > >   * handlers provide StreamFormats.\n> > > > >   */\n> > > > >  StreamConfiguration::StreamConfiguration()\n> > > > > -       : pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> > > > > +       : pixelFormat(0), stride(0), frameSize(0),\n> > > > >           stream_(nullptr)\n> > > > >  {\n> > > > >  }\n> > > > > @@ -289,7 +289,7 @@ StreamConfiguration::StreamConfiguration()\n> > > > >   * \\brief Construct a configuration with stream formats\n> > > > >   */\n> > > > >  StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n> > > > > -       : pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> > > > > +       : pixelFormat(0), stride(0), frameSize(0),\n> > > > >           stream_(nullptr), formats_(formats)\n> > > > >  {\n> > > > >  }\n> > > > > @@ -324,11 +324,6 @@ StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n> > > > >   * validating the configuration with a call to CameraConfiguration::validate().\n> > > > >   */\n> > > > >\n> > > > > -/**\n> > > > > - * \\var StreamConfiguration::bufferCount\n> > > > > - * \\brief Requested number of buffers to allocate for the stream\n> > > > > - */\n> > > > > -\n> > > > >  /**\n> > > > >   * \\fn StreamConfiguration::stream()\n> > > > >   * \\brief Retrieve the stream associated with the configuration\n> > > > > diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp\n> > > > > index d01eacfa2b84..2ff9affc6388 100644\n> > > > > --- a/src/v4l2/v4l2_camera.cpp\n> > > > > +++ b/src/v4l2/v4l2_camera.cpp\n> > > > > @@ -12,6 +12,8 @@\n> > > > >\n> > > > >  #include <libcamera/base/log.h>\n> > > > >\n> > > > > +#include <libcamera/property_ids.h>\n> > > > > +\n> > > > >  using namespace libcamera;\n> > > > >\n> > > > >  LOG_DECLARE_CATEGORY(V4L2Compat)\n> > > > > @@ -107,14 +109,12 @@ void V4L2Camera::requestComplete(Request *request)\n> > > > >  }\n> > > > >\n> > > > >  int V4L2Camera::configure(StreamConfiguration *streamConfigOut,\n> > > > > -                         const Size &size, const PixelFormat &pixelformat,\n> > > > > -                         unsigned int bufferCount)\n> > > > > +                         const Size &size, const PixelFormat &pixelformat)\n> > > > >  {\n> > > > >         StreamConfiguration &streamConfig = config_->at(0);\n> > > > >         streamConfig.size.width = size.width;\n> > > > >         streamConfig.size.height = size.height;\n> > > > >         streamConfig.pixelFormat = pixelformat;\n> > > > > -       streamConfig.bufferCount = bufferCount;\n> > > > >         /* \\todo memoryType (interval vs external) */\n> > > > >\n> > > > >         CameraConfiguration::Status validation = config_->validate();\n> > > > > @@ -146,7 +146,6 @@ int V4L2Camera::validateConfiguration(const PixelFormat &pixelFormat,\n> > > > >         StreamConfiguration &cfg = config->at(0);\n> > > > >         cfg.size = size;\n> > > > >         cfg.pixelFormat = pixelFormat;\n> > > > > -       cfg.bufferCount = 1;\n> > > > >\n> > > > >         CameraConfiguration::Status validation = config->validate();\n> > > > >         if (validation == CameraConfiguration::Invalid)\n> > > > > @@ -299,3 +298,10 @@ bool V4L2Camera::isRunning()\n> > > > >  {\n> > > > >         return isRunning_;\n> > > > >  }\n> > > > > +\n> > > > > +unsigned int V4L2Camera::minimumRequests(unsigned int count)\n> > > > > +{\n> > > > > +       unsigned int min = camera_->properties().get(properties::MinimumRequests);\n> > > > > +\n> > > > > +       return std::max(count, min);\n> > > > > +}\n> > > > > diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h\n> > > > > index a095f4e27524..4b5618ac12b5 100644\n> > > > > --- a/src/v4l2/v4l2_camera.h\n> > > > > +++ b/src/v4l2/v4l2_camera.h\n> > > > > @@ -45,8 +45,7 @@ public:\n> > > > >         std::vector<Buffer> completedBuffers();\n> > > > >\n> > > > >         int configure(StreamConfiguration *streamConfigOut,\n> > > > > -                     const Size &size, const PixelFormat &pixelformat,\n> > > > > -                     unsigned int bufferCount);\n> > > > > +                     const Size &size, const PixelFormat &pixelformat);\n> > > > >         int validateConfiguration(const PixelFormat &pixelformat,\n> > > > >                                   const Size &size,\n> > > > >                                   StreamConfiguration *streamConfigOut);\n> > > > > @@ -65,6 +64,8 @@ public:\n> > > > >\n> > > > >         bool isRunning();\n> > > > >\n> > > > > +       unsigned int minimumRequests(unsigned int count);\n> > > > > +\n> > > > >  private:\n> > > > >         void requestComplete(Request *request);\n> > > > >\n> > > > > diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp\n> > > > > index 7682c4bddf90..634ec84e0cbb 100644\n> > > > > --- a/src/v4l2/v4l2_camera_proxy.cpp\n> > > > > +++ b/src/v4l2/v4l2_camera_proxy.cpp\n> > > > > @@ -349,8 +349,7 @@ int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg)\n> > > > >         Size size(arg->fmt.pix.width, arg->fmt.pix.height);\n> > > > >         V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->fmt.pix.pixelformat);\n> > > > >         ret = vcam_->configure(&streamConfig_, size,\n> > > > > -                              PixelFormatInfo::info(v4l2Format).format,\n> > > > > -                              bufferCount_);\n> > > > > +                              PixelFormatInfo::info(v4l2Format).format);\n> > > > >         if (ret < 0)\n> > > > >                 return -EINVAL;\n> > > > >\n> > > > > @@ -491,14 +490,13 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf\n> > > > >         Size size(v4l2PixFormat_.width, v4l2PixFormat_.height);\n> > > > >         V4L2PixelFormat v4l2Format = V4L2PixelFormat(v4l2PixFormat_.pixelformat);\n> > > > >         int ret = vcam_->configure(&streamConfig_, size,\n> > > > > -                                  PixelFormatInfo::info(v4l2Format).format,\n> > > > > -                                  arg->count);\n> > > > > +                                  PixelFormatInfo::info(v4l2Format).format);\n> > > > >         if (ret < 0)\n> > > > >                 return -EINVAL;\n> > > > >\n> > > > >         setFmtFromConfig(streamConfig_);\n> > > > >\n> > > > > -       arg->count = streamConfig_.bufferCount;\n> > > > > +       arg->count = vcam_->minimumRequests(arg->count);\n> > > > >         bufferCount_ = arg->count;\n> > > > >\n> > > > >         ret = vcam_->allocBuffers(arg->count);\n> > > > > diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp\n> > > > > index c504ea09e64b..67ac0ad20e15 100644\n> > > > > --- a/test/camera/buffer_import.cpp\n> > > > > +++ b/test/camera/buffer_import.cpp\n> > > > > @@ -16,6 +16,8 @@\n> > > > >  #include <libcamera/base/thread.h>\n> > > > >  #include <libcamera/base/timer.h>\n> > > > >\n> > > > > +#include <libcamera/property_ids.h>\n> > > > > +\n> > > > >  #include \"libcamera/internal/device_enumerator.h\"\n> > > > >  #include \"libcamera/internal/media_device.h\"\n> > > > >  #include \"libcamera/internal/v4l2_videodevice.h\"\n> > > > > @@ -92,10 +94,12 @@ protected:\n> > > > >                         return TestFail;\n> > > > >                 }\n> > > > >\n> > > > > +               unsigned int bufferCount = camera_->properties().get(properties::MinimumRequests);\n> > > > > +\n> > > > >                 Stream *stream = cfg.stream();\n> > > > >\n> > > > >                 BufferSource source;\n> > > > > -               int ret = source.allocate(cfg);\n> > > > > +               int ret = source.allocate(cfg, bufferCount);\n> > > > >                 if (ret != TestPass)\n> > > > >                         return ret;\n> > > > >\n> > > > > @@ -139,10 +143,10 @@ protected:\n> > > > >                 while (timer.isRunning())\n> > > > >                         dispatcher->processEvents();\n> > > > >\n> > > > > -               if (completeRequestsCount_ < cfg.bufferCount * 2) {\n> > > > > +               if (completeRequestsCount_ < bufferCount * 2) {\n> > > > >                         std::cout << \"Failed to capture enough frames (got \"\n> > > > >                                   << completeRequestsCount_ << \" expected at least \"\n> > > > > -                                 << cfg.bufferCount * 2 << \")\" << std::endl;\n> > > > > +                                 << bufferCount * 2 << \")\" << std::endl;\n> > > > >                         return TestFail;\n> > > > >                 }\n> > > > >\n> > > > > diff --git a/test/libtest/buffer_source.cpp b/test/libtest/buffer_source.cpp\n> > > > > index 73563f2fc39d..c3d5286a2462 100644\n> > > > > --- a/test/libtest/buffer_source.cpp\n> > > > > +++ b/test/libtest/buffer_source.cpp\n> > > > > @@ -24,7 +24,7 @@ BufferSource::~BufferSource()\n> > > > >                 media_->release();\n> > > > >  }\n> > > > >\n> > > > > -int BufferSource::allocate(const StreamConfiguration &config)\n> > > > > +int BufferSource::allocate(const StreamConfiguration &config, unsigned int count)\n> > > > >  {\n> > > > >         /* Locate and open the video device. */\n> > > > >         std::string videoDeviceName = \"vivid-000-vid-out\";\n> > > > > @@ -77,7 +77,7 @@ int BufferSource::allocate(const StreamConfiguration &config)\n> > > > >                 return TestFail;\n> > > > >         }\n> > > > >\n> > > > > -       if (video->allocateBuffers(config.bufferCount, &buffers_) < 0) {\n> > > > > +       if (video->allocateBuffers(count, &buffers_) < 0) {\n> > > > >                 std::cout << \"Failed to allocate buffers\" << std::endl;\n> > > > >                 return TestFail;\n> > > > >         }\n> > > > > diff --git a/test/libtest/buffer_source.h b/test/libtest/buffer_source.h\n> > > > > index 14b4770e8d8a..6a18e269a575 100644\n> > > > > --- a/test/libtest/buffer_source.h\n> > > > > +++ b/test/libtest/buffer_source.h\n> > > > > @@ -20,7 +20,7 @@ public:\n> > > > >         BufferSource();\n> > > > >         ~BufferSource();\n> > > > >\n> > > > > -       int allocate(const StreamConfiguration &config);\n> > > > > +       int allocate(const StreamConfiguration &config, unsigned int count);\n> > > > >         const std::vector<std::unique_ptr<FrameBuffer>> &buffers();\n> > > > >\n> > > > >  private:\n> > > > > diff --git a/test/v4l2_videodevice/buffer_cache.cpp b/test/v4l2_videodevice/buffer_cache.cpp\n> > > > > index b3f2bec11783..07fddfd2617c 100644\n> > > > > --- a/test/v4l2_videodevice/buffer_cache.cpp\n> > > > > +++ b/test/v4l2_videodevice/buffer_cache.cpp\n> > > > > @@ -10,6 +10,7 @@\n> > > > >  #include <vector>\n> > > > >\n> > > > >  #include <libcamera/formats.h>\n> > > > > +#include <libcamera/property_ids.h>\n> > > > >  #include <libcamera/stream.h>\n> > > > >\n> > > > >  #include \"buffer_source.h\"\n> > > > > @@ -145,10 +146,9 @@ public:\n> > > > >                 StreamConfiguration cfg;\n> > > > >                 cfg.pixelFormat = formats::YUYV;\n> > > > >                 cfg.size = Size(600, 800);\n> > > > > -               cfg.bufferCount = numBuffers;\n> > > > >\n> > > > >                 BufferSource source;\n> > > > > -               int ret = source.allocate(cfg);\n> > > > > +               int ret = source.allocate(cfg, numBuffers);\n> > > > >                 if (ret != TestPass)\n> > > > >                         return ret;\n> > > > >\n> > > > > --\n> > > > > 2.32.0\n> > > > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id B96D2C322E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 29 Jul 2021 10:00:46 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4C228687C5;\n\tThu, 29 Jul 2021 12:00:46 +0200 (CEST)","from mail-wr1-x430.google.com (mail-wr1-x430.google.com\n\t[IPv6:2a00:1450:4864:20::430])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A54CB687BA\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 29 Jul 2021 12:00:44 +0200 (CEST)","by mail-wr1-x430.google.com with SMTP id p5so6190802wro.7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 29 Jul 2021 03:00:44 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=raspberrypi.com header.i=@raspberrypi.com\n\theader.b=\"Vz5fsvRO\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=mime-version:references:in-reply-to:from:date:message-id:subject:to\n\t:cc:content-transfer-encoding;\n\tbh=2tjS4PVWcWGZpwystTIzP63fYu7OR11VX7UfYwlTdOg=;\n\tb=Vz5fsvROD2kY9cF/6Ln9htmSpJ15wpuFyQHs45Z1Jlec01sfr3tMexW1ishC6tI2c1\n\tCtME1v7Sno1Oa9J9sA2vx17wfQiknRyTd7No4PkczVg/Y19O24D+fCl3dgdIBPtQzMMS\n\tlt3ZHV7XyUTcfDTh0VEEUxijtEvuaAhsYXvZpeAWlz4FAWkNvTuR0vQMPxTew23s42Dn\n\tO1f8cKm83XsC4aowPeoQj65+sUctBotiXEC7H7w1CSpBD2oKvkOCRt7m5AlA+A6BCQyN\n\to/EoVUlORFjHE1HuW5FoGdrngr8p0fUddbNVRUnFv551DTEMl+pknKr1ZwHXC8JdNOt3\n\tW9yQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to:cc:content-transfer-encoding;\n\tbh=2tjS4PVWcWGZpwystTIzP63fYu7OR11VX7UfYwlTdOg=;\n\tb=mMvVIPCUx8/tC0pHyUXPoIeu1iBn4tdOc3tN0QfUZ5XBdpYJUnQ7CqPRbDziFedY5r\n\tUsmgTQFLTFnnggCJ/JxXL8gQjT4lIkxmLpWxXHW4J4anHDb3bsEMv6BptJ8OWp5X87ZJ\n\twEIwCCpJWtHyfod802Wa0rY7aHXCRdaII6hXgIPKtlwZdIhWJyMg+Okd9rXz3ECNx9Lx\n\ttxHnfI37XBR1sQxQoY7Td/IussrmJ0T3II/pu4f8mdmT13s0uOko59sbvD2x/g7fCxdV\n\tBV1Zi8IPmaV+s30jlL6gI6c1xeRurzZFveA4cwOa/+15izf1rLLM2d+gbLtve5xHbd1e\n\tvy8Q==","X-Gm-Message-State":"AOAM533GdK/I/UYuLFw3x032gI1/lpvBZL8Zi7LcgHKCdyDiuRpBJYIb\n\tJsfTTiYbzJ0fcQ7zcM9sKJw4VJySSFmCLWA2hlGgCA==","X-Google-Smtp-Source":"ABdhPJx/BJepXQdGQ+978DreEunyAucvwa4IP3n4DjgZiaOP9NKdPZd+9O9J0eHPZ5sbtwaWqcse53vvFAvtCIVEKuU=","X-Received":"by 2002:a5d:68cd:: with SMTP id\n\tp13mr3914046wrw.163.1627552843983; \n\tThu, 29 Jul 2021 03:00:43 -0700 (PDT)","MIME-Version":"1.0","References":"<20210722232851.747614-1-nfraprado@collabora.com>\n\t<20210722232851.747614-11-nfraprado@collabora.com>\n\t<CAHW6GYJbVdFebNca9ZeM8LY=Ca4P1uaUd3B-r5FF7mJ9k853fg@mail.gmail.com>\n\t<20210723131039.ire2z7u6sdxws3dt@notapiano>\n\t<CAHW6GYKCBXmNSzo+_EcQCvJEaPg-ahMsWXKwVA=J8YzZEtBUWA@mail.gmail.com>\n\t<20210723210807.emekovdwbehrzr44@notapiano>","In-Reply-To":"<20210723210807.emekovdwbehrzr44@notapiano>","From":"David Plowman <david.plowman@raspberrypi.com>","Date":"Thu, 29 Jul 2021 11:00:33 +0100","Message-ID":"<CAHW6GYLbPU0TKbMNeNsHdif6Nm+-iUfBgRAcnUN6=ftKYsmYoQ@mail.gmail.com>","To":"=?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= <nfraprado@collabora.com>","Content-Type":"text/plain; charset=\"UTF-8\"","Content-Transfer-Encoding":"quoted-printable","Subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>,\n\tkernel@collabora.com, =?utf-8?q?Andr=C3=A9_Almeida?=\n\t<andrealmeid@collabora.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":18420,"web_url":"https://patchwork.libcamera.org/comment/18420/","msgid":"<20210729143820.yumwo33jpwaljyb2@notapiano>","date":"2021-07-29T14:38:20","subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","submitter":{"id":84,"url":"https://patchwork.libcamera.org/api/people/84/","name":"Nícolas F. R. A. Prado","email":"nfraprado@collabora.com"},"content":"Hi David,\n\nOn Thu, Jul 29, 2021 at 11:00:33AM +0100, David Plowman wrote:\n> Hi again\n> \n> I thought that perhaps I could explain in more detail why I think\n> applications need to be able to set (or influence) the buffer count\n> and not leave it to the pipeline handler. My use-case is as follows.\n> \n> I'm running some standard sort of application such as video recording\n> for which there are maybe 4 buffers allocated. Now, I also want to do\n> some image analysis that perhaps causes me to change something about\n> the recording (maybe change camera settings, or even stop the\n> recording). But this image analysis task is relatively slow.\n> \n> One option is to copy the camera frames so that I can return the\n> buffers in the request back to the camera. But copying images is\n> generally undesirable. Instead I'd prefer to hold on to the buffer\n> only now my camera pipeline is effectively working with only 3\n> buffers, which is not enough. When I eventually finish with the buffer\n> I will return it, and then grab the next one to keep again!\n\nOhh, I see. Sorry, I got a bit confused there, but this is not a problem at all.\nIf you want the pipeline to work with extra requests/buffers, you just supply\nmore to it :). Going back to your code snippet, this would be the change:\n\t\n    configuration_ = camera_->generateConfiguration({ StreamRole::StillCapture });\n-   configuration_->at(0).bufferCount = <value I have determined>;\n    camera_->configure(configuration_.get());\n    allocator_ = new FrameBufferAllocator(camera_);\n    Stream *stream = configuration_->at(0).stream();\n-   allocator_->allocate(stream);\n+   allocator_->allocate(stream, <value I have determined>);\n    // now allocator_->buffers(stream) has the buffers I want!\n\nSo, basically, you don't need to set bufferCount anymore, and instead you\nallocate as many buffers as you need to give the pipeline handler by directly\npassing the number to FrameBufferAllocator. In your case you want to allocate an\nextra buffer to compensate for the one you'll be keeping.\n\nIt was already possible to supply the pipeline handler with how many\nbuffers you wanted, but previously you had to allocate them elsewhere, while now\nyou can allocate with the FrameBufferAllocator since it accepts the count\nargument. (Actually for the raspberry pipeline it was already possible to do\nthis implicitly through bufferCount as you did, but not with the other\npipelines).\n\nWhat I meant wasn't possible to change is how many internal buffers for metadata\nand parameters the pipeline uses together with the IPA. And also how many V4L2\nbuffer slots are created to queue the requests into. But all of this is indeed\nonly relevant to the pipeline handler, so an application shouldn't care about\nit. All of this, together with how many buffers the application would allocate,\nwas previously grouped on bufferCount. With its deletion, however, they are\ngetting split up.\n\nI hope I got it right this time :).\n\nThanks,\nNícolas\n\n> \n> So at the very least, the application needs to be able to say \"please\n> allocate <n> more buffers than you thought you needed\". Does that make\n> sense? Will this be possible in the new scheme?\n> \n> Thanks!\n> David\n> \n> On Fri, 23 Jul 2021 at 22:08, Nícolas F. R. A. Prado\n> <nfraprado@collabora.com> wrote:\n> >\n> > Hi David,\n> >\n> > On Fri, Jul 23, 2021 at 04:53:55PM +0100, David Plowman wrote:\n> > > Hi Nicolas\n> > >\n> > > Thanks for the explanations. I'm still not sure I entirely understand\n> > > so perhaps a quick look at how I would have to change my application\n> > > code might help? Here's what I have now (I've removed any\n> > > \"unimportant\" bits!):\n> > >\n> > > configuration_ = camera_->generateConfiguration({ StreamRole::StillCapture });\n> > > configuration_->at(0).bufferCount = <value I have determined>;\n> > > camera_->configure(configuration_.get());\n> > > allocator_ = new FrameBufferAllocator(camera_);\n> > > Stream *stream = configuration_->at(0).stream();\n> > > allocator_->allocate(stream);\n> > > // now allocator_->buffers(stream) has the buffers I want!\n> > >\n> > > I guess one thing to note is that the bufferCount value varies with\n> > > more than just the StreamRole, and I don't in general trust the\n> > > pipeline handler to \"know\" what I want. Will this still be possible?\n> >\n> > Oh I see... No, this won't be possible after we drop bufferCount. The\n> > pipeline handler will decide for itself how many buffers to allocate internally,\n> > possibly using the StreamRole as a hint.\n> >\n> > I wasn't aware this could impact an application, since all the other pipeline\n> > handlers actually ignore when bufferCount is set by the application, overriding\n> > it when the configuration is validated. But now I'm noticing the raspberrypi\n> > pipeline actually uses it.\n> >\n> > Some context: This series actually began with me making\n> > FrameBufferAllocator::allocate() receive a count argument instead of using the\n> > value of bufferCount. But since Laurent mentioned that bufferCount was going\n> > away eventually anyway I ended up removing it as well as part of this series.\n> >\n> > I do understand how being able to specify a bufferCount value that suits your\n> > specific usecase is useful, though... Laurent, what's your take on this? :)\n> >\n> > Thanks,\n> > Nícolas\n> >\n> > >\n> > > Thanks!\n> > > David\n> > >\n> > > On Fri, 23 Jul 2021 at 14:10, Nícolas F. R. A. Prado\n> > > <nfraprado@collabora.com> wrote:\n> > > >\n> > > > Hi David,\n> > > >\n> > > > On Fri, Jul 23, 2021 at 09:42:56AM +0100, David Plowman wrote:\n> > > > > Hi Nicolas\n> > > > >\n> > > > > Thanks very much for all this work! I was wondering if I could ask a\n> > > > > little more about this patch. In our applications, for example, we set\n> > > > > the bufferCount according to the use-case that the application is\n> > > > > implementing. For example:\n> > > > >\n> > > > > * For preview windows we set bufferCount to 4.\n> > > > > * For video capture we drop fewer frames with a deeper queue so we set it to 6.\n> > > > > * For stills capture we can get by with one frame, though use cases\n> > > > > that capture several stills images for fusion work better if we set\n> > > > > bufferCount to 2 or 3.\n> > > > >\n> > > > > I was wondering how our applications can achieve this behaviour if the\n> > > > > bufferCount field is no longer available.\n> > > >\n> > > > Okay, so the short answer is that the applications, knowing their particular use\n> > > > case, are responsible to provide enough requests to keep the pipeline going. On\n> > > > the pipeline handler side, it's free to use how many internal buffers it wants.\n> > > >\n> > > > So in your case, the pipeline handler could still allocate that same number of\n> > > > internal buffers as you previously did based on bufferCount, but now based\n> > > > solely on the StreamRole set. The application would then allocate and queue\n> > > > how many buffers fits the usage. (Note that before the application would call\n> > > > FrameBufferAllocator::allocate() and it would allocate 'bufferCount' buffers,\n> > > > but now the function takes a count argument so the application is free to choose\n> > > > how many)\n> > > >\n> > > > Now, I guess it would be nice for the application to be able to query what is a\n> > > > good number of buffers to use, for example 6 in the video capture of your use\n> > > > case. At the moment, the only information available is that 1 is the minimum\n> > > > number of buffers required. So the application would have to know that 6 is a\n> > > > good number for video capture. Maybe another property could be introduced later\n> > > > for this recommended amount, but previous discussions suggested this is very use\n> > > > case dependent, so might not make sense.\n> > > >\n> > > > I hope this answers the question. If not, I'm still here :).\n> > > >\n> > > > Thanks,\n> > > > Nícolas\n> > > >\n> > > > >\n> > > > > Thanks!\n> > > > > David\n> > > > >\n> > > > > On Fri, 23 Jul 2021 at 00:29, Nícolas F. R. A. Prado\n> > > > > <nfraprado@collabora.com> wrote:\n> > > > > >\n> > > > > > Now that the number of buffers allocated by the FrameBufferAllocator\n> > > > > > helper is passed through FrameBufferAllocator::allocate() and the\n> > > > > > pipelines no longer use bufferCount for internal buffer or V4L2 buffer\n> > > > > > slots allocation, we no longer need to have bufferCount in the\n> > > > > > StreamConfiguration, so remove it.\n> > > > > >\n> > > > > > Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>\n> > > > > > ---\n> > > > > >\n> > > > > > No changes in v7\n> > > > > >\n> > > > > > Changes in v6:\n> > > > > > - Removed IPU3_BUFFER_COUNT as it was unused\n> > > > > >\n> > > > > >  include/libcamera/stream.h                         |  2 --\n> > > > > >  src/android/camera_stream.cpp                      |  2 +-\n> > > > > >  src/libcamera/pipeline/ipu3/cio2.cpp               |  1 -\n> > > > > >  src/libcamera/pipeline/ipu3/ipu3.cpp               |  8 --------\n> > > > > >  src/libcamera/pipeline/raspberrypi/raspberrypi.cpp |  6 ------\n> > > > > >  src/libcamera/pipeline/rkisp1/rkisp1_path.cpp      |  2 --\n> > > > > >  src/libcamera/pipeline/simple/converter.cpp        |  3 ---\n> > > > > >  src/libcamera/pipeline/simple/converter.h          |  3 ---\n> > > > > >  src/libcamera/pipeline/simple/simple.cpp           |  5 +----\n> > > > > >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp       |  3 ---\n> > > > > >  src/libcamera/pipeline/vimc/vimc.cpp               |  3 ---\n> > > > > >  src/libcamera/stream.cpp                           |  9 ++-------\n> > > > > >  src/v4l2/v4l2_camera.cpp                           | 14 ++++++++++----\n> > > > > >  src/v4l2/v4l2_camera.h                             |  5 +++--\n> > > > > >  src/v4l2/v4l2_camera_proxy.cpp                     |  8 +++-----\n> > > > > >  test/camera/buffer_import.cpp                      | 10 +++++++---\n> > > > > >  test/libtest/buffer_source.cpp                     |  4 ++--\n> > > > > >  test/libtest/buffer_source.h                       |  2 +-\n> > > > > >  test/v4l2_videodevice/buffer_cache.cpp             |  4 ++--\n> > > > > >  19 files changed, 32 insertions(+), 62 deletions(-)\n> > > > > >\n> > > > > > diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\n> > > > > > index 0c55e7164592..b25f0059f2f1 100644\n> > > > > > --- a/include/libcamera/stream.h\n> > > > > > +++ b/include/libcamera/stream.h\n> > > > > > @@ -45,8 +45,6 @@ struct StreamConfiguration {\n> > > > > >         unsigned int stride;\n> > > > > >         unsigned int frameSize;\n> > > > > >\n> > > > > > -       unsigned int bufferCount;\n> > > > > > -\n> > > > > >         Stream *stream() const { return stream_; }\n> > > > > >         void setStream(Stream *stream) { stream_ = stream; }\n> > > > > >         const StreamFormats &formats() const { return formats_; }\n> > > > > > diff --git a/src/android/camera_stream.cpp b/src/android/camera_stream.cpp\n> > > > > > index b168e3c0c288..0794be409f82 100644\n> > > > > > --- a/src/android/camera_stream.cpp\n> > > > > > +++ b/src/android/camera_stream.cpp\n> > > > > > @@ -94,7 +94,7 @@ int CameraStream::configure()\n> > > > > >                         buffers_.push_back(frameBuffer.get());\n> > > > > >         }\n> > > > > >\n> > > > > > -       camera3Stream_->max_buffers = configuration().bufferCount;\n> > > > > > +       camera3Stream_->max_buffers = bufferCount;\n> > > > > >\n> > > > > >         return 0;\n> > > > > >  }\n> > > > > > diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > > > > index 1bcd580e251c..0e04e7214489 100644\n> > > > > > --- a/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > > > > +++ b/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > > > > @@ -214,7 +214,6 @@ StreamConfiguration CIO2Device::generateConfiguration(Size size) const\n> > > > > >\n> > > > > >         cfg.size = sensorFormat.size;\n> > > > > >         cfg.pixelFormat = mbusCodesToPixelFormat.at(sensorFormat.mbus_code);\n> > > > > > -       cfg.bufferCount = CIO2_BUFFER_COUNT;\n> > > > > >\n> > > > > >         return cfg;\n> > > > > >  }\n> > > > > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > > > index 4efd201c05e5..b223b3f33cd0 100644\n> > > > > > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > > > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > > > @@ -38,7 +38,6 @@ namespace libcamera {\n> > > > > >\n> > > > > >  LOG_DEFINE_CATEGORY(IPU3)\n> > > > > >\n> > > > > > -static constexpr unsigned int IPU3_BUFFER_COUNT = 4;\n> > > > > >  static constexpr unsigned int IPU3_MAX_STREAMS = 3;\n> > > > > >  static const Size IMGU_OUTPUT_MIN_SIZE = { 2, 2 };\n> > > > > >  static const Size IMGU_OUTPUT_MAX_SIZE = { 4480, 34004 };\n> > > > > > @@ -295,7 +294,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n> > > > > >                         /* Initialize the RAW stream with the CIO2 configuration. */\n> > > > > >                         cfg->size = cio2Configuration_.size;\n> > > > > >                         cfg->pixelFormat = cio2Configuration_.pixelFormat;\n> > > > > > -                       cfg->bufferCount = cio2Configuration_.bufferCount;\n> > > > > >                         cfg->stride = info.stride(cfg->size.width, 0, 64);\n> > > > > >                         cfg->frameSize = info.frameSize(cfg->size, 64);\n> > > > > >                         cfg->setStream(const_cast<Stream *>(&data_->rawStream_));\n> > > > > > @@ -339,7 +337,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n> > > > > >                                               IMGU_OUTPUT_HEIGHT_ALIGN);\n> > > > > >\n> > > > > >                         cfg->pixelFormat = formats::NV12;\n> > > > > > -                       cfg->bufferCount = IPU3_BUFFER_COUNT;\n> > > > > >                         cfg->stride = info.stride(cfg->size.width, 0, 1);\n> > > > > >                         cfg->frameSize = info.frameSize(cfg->size, 1);\n> > > > > >\n> > > > > > @@ -407,7 +404,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > > >         Size sensorResolution = data->cio2_.sensor()->resolution();\n> > > > > >         for (const StreamRole role : roles) {\n> > > > > >                 std::map<PixelFormat, std::vector<SizeRange>> streamFormats;\n> > > > > > -               unsigned int bufferCount;\n> > > > > >                 PixelFormat pixelFormat;\n> > > > > >                 Size size;\n> > > > > >\n> > > > > > @@ -428,7 +424,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > > >                         size.height = utils::alignDown(size.height - 1,\n> > > > > >                                                        IMGU_OUTPUT_HEIGHT_MARGIN);\n> > > > > >                         pixelFormat = formats::NV12;\n> > > > > > -                       bufferCount = IPU3_BUFFER_COUNT;\n> > > > > >                         streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n> > > > > >\n> > > > > >                         break;\n> > > > > > @@ -438,7 +433,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > > >                                 data->cio2_.generateConfiguration(sensorResolution);\n> > > > > >                         pixelFormat = cio2Config.pixelFormat;\n> > > > > >                         size = cio2Config.size;\n> > > > > > -                       bufferCount = cio2Config.bufferCount;\n> > > > > >\n> > > > > >                         for (const PixelFormat &format : data->cio2_.formats())\n> > > > > >                                 streamFormats[format] = data->cio2_.sizes();\n> > > > > > @@ -457,7 +451,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > > >                                                .alignedDownTo(IMGU_OUTPUT_WIDTH_ALIGN,\n> > > > > >                                                               IMGU_OUTPUT_HEIGHT_ALIGN);\n> > > > > >                         pixelFormat = formats::NV12;\n> > > > > > -                       bufferCount = IPU3_BUFFER_COUNT;\n> > > > > >                         streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n> > > > > >\n> > > > > >                         break;\n> > > > > > @@ -474,7 +467,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > > >                 StreamConfiguration cfg(formats);\n> > > > > >                 cfg.size = size;\n> > > > > >                 cfg.pixelFormat = pixelFormat;\n> > > > > > -               cfg.bufferCount = bufferCount;\n> > > > > >                 config->addConfiguration(cfg);\n> > > > > >         }\n> > > > > >\n> > > > > > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > > > > index 776e0f92aed1..e6fc0425c3ef 100644\n> > > > > > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > > > > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > > > > @@ -473,7 +473,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > >         RPiCameraData *data = cameraData(camera);\n> > > > > >         CameraConfiguration *config = new RPiCameraConfiguration(data);\n> > > > > >         V4L2DeviceFormat sensorFormat;\n> > > > > > -       unsigned int bufferCount;\n> > > > > >         PixelFormat pixelFormat;\n> > > > > >         V4L2VideoDevice::Formats fmts;\n> > > > > >         Size size;\n> > > > > > @@ -491,7 +490,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > >                         sensorFormat = findBestMode(fmts, size);\n> > > > > >                         pixelFormat = sensorFormat.fourcc.toPixelFormat();\n> > > > > >                         ASSERT(pixelFormat.isValid());\n> > > > > > -                       bufferCount = 2;\n> > > > > >                         rawCount++;\n> > > > > >                         break;\n> > > > > >\n> > > > > > @@ -500,7 +498,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > >                         pixelFormat = formats::NV12;\n> > > > > >                         /* Return the largest sensor resolution. */\n> > > > > >                         size = data->sensor_->resolution();\n> > > > > > -                       bufferCount = 1;\n> > > > > >                         outCount++;\n> > > > > >                         break;\n> > > > > >\n> > > > > > @@ -516,7 +513,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > >                         fmts = data->isp_[Isp::Output0].dev()->formats();\n> > > > > >                         pixelFormat = formats::YUV420;\n> > > > > >                         size = { 1920, 1080 };\n> > > > > > -                       bufferCount = 4;\n> > > > > >                         outCount++;\n> > > > > >                         break;\n> > > > > >\n> > > > > > @@ -524,7 +520,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > >                         fmts = data->isp_[Isp::Output0].dev()->formats();\n> > > > > >                         pixelFormat = formats::ARGB8888;\n> > > > > >                         size = { 800, 600 };\n> > > > > > -                       bufferCount = 4;\n> > > > > >                         outCount++;\n> > > > > >                         break;\n> > > > > >\n> > > > > > @@ -554,7 +549,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > >                 StreamConfiguration cfg(formats);\n> > > > > >                 cfg.size = size;\n> > > > > >                 cfg.pixelFormat = pixelFormat;\n> > > > > > -               cfg.bufferCount = bufferCount;\n> > > > > >                 config->addConfiguration(cfg);\n> > > > > >         }\n> > > > > >\n> > > > > > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > > > > index fea330f72886..4961f3971e59 100644\n> > > > > > --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > > > > +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > > > > @@ -61,7 +61,6 @@ StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution)\n> > > > > >         StreamConfiguration cfg(formats);\n> > > > > >         cfg.pixelFormat = formats::NV12;\n> > > > > >         cfg.size = maxResolution;\n> > > > > > -       cfg.bufferCount = RKISP1_BUFFER_COUNT;\n> > > > > >\n> > > > > >         return cfg;\n> > > > > >  }\n> > > > > > @@ -77,7 +76,6 @@ CameraConfiguration::Status RkISP1Path::validate(StreamConfiguration *cfg)\n> > > > > >\n> > > > > >         cfg->size.boundTo(maxResolution_);\n> > > > > >         cfg->size.expandTo(minResolution_);\n> > > > > > -       cfg->bufferCount = RKISP1_BUFFER_COUNT;\n> > > > > >\n> > > > > >         V4L2DeviceFormat format;\n> > > > > >         format.fourcc = video_->toV4L2PixelFormat(cfg->pixelFormat);\n> > > > > > diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp\n> > > > > > index b3bcf01483f7..fda417793e80 100644\n> > > > > > --- a/src/libcamera/pipeline/simple/converter.cpp\n> > > > > > +++ b/src/libcamera/pipeline/simple/converter.cpp\n> > > > > > @@ -89,9 +89,6 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg,\n> > > > > >                 return -EINVAL;\n> > > > > >         }\n> > > > > >\n> > > > > > -       inputBufferCount_ = inputCfg.bufferCount;\n> > > > > > -       outputBufferCount_ = outputCfg.bufferCount;\n> > > > > > -\n> > > > > >         return 0;\n> > > > > >  }\n> > > > > >\n> > > > > > diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h\n> > > > > > index 7e1d60674f62..406e63ca2a80 100644\n> > > > > > --- a/src/libcamera/pipeline/simple/converter.h\n> > > > > > +++ b/src/libcamera/pipeline/simple/converter.h\n> > > > > > @@ -87,9 +87,6 @@ private:\n> > > > > >                 SimpleConverter *converter_;\n> > > > > >                 unsigned int index_;\n> > > > > >                 std::unique_ptr<V4L2M2MDevice> m2m_;\n> > > > > > -\n> > > > > > -               unsigned int inputBufferCount_;\n> > > > > > -               unsigned int outputBufferCount_;\n> > > > > >         };\n> > > > > >\n> > > > > >         std::string deviceNode_;\n> > > > > > diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\n> > > > > > index a1163eaf8be2..ded04914f610 100644\n> > > > > > --- a/src/libcamera/pipeline/simple/simple.cpp\n> > > > > > +++ b/src/libcamera/pipeline/simple/simple.cpp\n> > > > > > @@ -628,7 +628,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n> > > > > >                     cfg.size != pipeConfig_->captureSize)\n> > > > > >                         needConversion_ = true;\n> > > > > >\n> > > > > > -               /* Set the stride, frameSize and bufferCount. */\n> > > > > > +               /* Set the stride and frameSize. */\n> > > > > >                 if (needConversion_) {\n> > > > > >                         std::tie(cfg.stride, cfg.frameSize) =\n> > > > > >                                 converter->strideAndFrameSize(cfg.pixelFormat, cfg.size);\n> > > > > > @@ -646,8 +646,6 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n> > > > > >                         cfg.stride = format.planes[0].bpl;\n> > > > > >                         cfg.frameSize = format.planes[0].size;\n> > > > > >                 }\n> > > > > > -\n> > > > > > -               cfg.bufferCount = 3;\n> > > > > >         }\n> > > > > >\n> > > > > >         return status;\n> > > > > > @@ -770,7 +768,6 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)\n> > > > > >         inputCfg.pixelFormat = pipeConfig->captureFormat;\n> > > > > >         inputCfg.size = pipeConfig->captureSize;\n> > > > > >         inputCfg.stride = captureFormat.planes[0].bpl;\n> > > > > > -       inputCfg.bufferCount = kNumInternalBuffers;\n> > > > > >\n> > > > > >         return converter_->configure(inputCfg, outputCfgs);\n> > > > > >  }\n> > > > > > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > > > > index 755949e7a59a..32482300f09a 100644\n> > > > > > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > > > > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > > > > @@ -150,8 +150,6 @@ CameraConfiguration::Status UVCCameraConfiguration::validate()\n> > > > > >                 status = Adjusted;\n> > > > > >         }\n> > > > > >\n> > > > > > -       cfg.bufferCount = 4;\n> > > > > > -\n> > > > > >         V4L2DeviceFormat format;\n> > > > > >         format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n> > > > > >         format.size = cfg.size;\n> > > > > > @@ -193,7 +191,6 @@ CameraConfiguration *PipelineHandlerUVC::generateConfiguration(Camera *camera,\n> > > > > >\n> > > > > >         cfg.pixelFormat = formats.pixelformats().front();\n> > > > > >         cfg.size = formats.sizes(cfg.pixelFormat).back();\n> > > > > > -       cfg.bufferCount = 4;\n> > > > > >\n> > > > > >         config->addConfiguration(cfg);\n> > > > > >\n> > > > > > diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp\n> > > > > > index 24ba743a946c..a698427c4361 100644\n> > > > > > --- a/src/libcamera/pipeline/vimc/vimc.cpp\n> > > > > > +++ b/src/libcamera/pipeline/vimc/vimc.cpp\n> > > > > > @@ -167,8 +167,6 @@ CameraConfiguration::Status VimcCameraConfiguration::validate()\n> > > > > >                 status = Adjusted;\n> > > > > >         }\n> > > > > >\n> > > > > > -       cfg.bufferCount = 4;\n> > > > > > -\n> > > > > >         V4L2DeviceFormat format;\n> > > > > >         format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n> > > > > >         format.size = cfg.size;\n> > > > > > @@ -224,7 +222,6 @@ CameraConfiguration *PipelineHandlerVimc::generateConfiguration(Camera *camera,\n> > > > > >\n> > > > > >         cfg.pixelFormat = formats::BGR888;\n> > > > > >         cfg.size = { 1920, 1080 };\n> > > > > > -       cfg.bufferCount = 4;\n> > > > > >\n> > > > > >         config->addConfiguration(cfg);\n> > > > > >\n> > > > > > diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp\n> > > > > > index b8626775d224..ca507b72b26a 100644\n> > > > > > --- a/src/libcamera/stream.cpp\n> > > > > > +++ b/src/libcamera/stream.cpp\n> > > > > > @@ -280,7 +280,7 @@ SizeRange StreamFormats::range(const PixelFormat &pixelformat) const\n> > > > > >   * handlers provide StreamFormats.\n> > > > > >   */\n> > > > > >  StreamConfiguration::StreamConfiguration()\n> > > > > > -       : pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> > > > > > +       : pixelFormat(0), stride(0), frameSize(0),\n> > > > > >           stream_(nullptr)\n> > > > > >  {\n> > > > > >  }\n> > > > > > @@ -289,7 +289,7 @@ StreamConfiguration::StreamConfiguration()\n> > > > > >   * \\brief Construct a configuration with stream formats\n> > > > > >   */\n> > > > > >  StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n> > > > > > -       : pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> > > > > > +       : pixelFormat(0), stride(0), frameSize(0),\n> > > > > >           stream_(nullptr), formats_(formats)\n> > > > > >  {\n> > > > > >  }\n> > > > > > @@ -324,11 +324,6 @@ StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n> > > > > >   * validating the configuration with a call to CameraConfiguration::validate().\n> > > > > >   */\n> > > > > >\n> > > > > > -/**\n> > > > > > - * \\var StreamConfiguration::bufferCount\n> > > > > > - * \\brief Requested number of buffers to allocate for the stream\n> > > > > > - */\n> > > > > > -\n> > > > > >  /**\n> > > > > >   * \\fn StreamConfiguration::stream()\n> > > > > >   * \\brief Retrieve the stream associated with the configuration\n> > > > > > diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp\n> > > > > > index d01eacfa2b84..2ff9affc6388 100644\n> > > > > > --- a/src/v4l2/v4l2_camera.cpp\n> > > > > > +++ b/src/v4l2/v4l2_camera.cpp\n> > > > > > @@ -12,6 +12,8 @@\n> > > > > >\n> > > > > >  #include <libcamera/base/log.h>\n> > > > > >\n> > > > > > +#include <libcamera/property_ids.h>\n> > > > > > +\n> > > > > >  using namespace libcamera;\n> > > > > >\n> > > > > >  LOG_DECLARE_CATEGORY(V4L2Compat)\n> > > > > > @@ -107,14 +109,12 @@ void V4L2Camera::requestComplete(Request *request)\n> > > > > >  }\n> > > > > >\n> > > > > >  int V4L2Camera::configure(StreamConfiguration *streamConfigOut,\n> > > > > > -                         const Size &size, const PixelFormat &pixelformat,\n> > > > > > -                         unsigned int bufferCount)\n> > > > > > +                         const Size &size, const PixelFormat &pixelformat)\n> > > > > >  {\n> > > > > >         StreamConfiguration &streamConfig = config_->at(0);\n> > > > > >         streamConfig.size.width = size.width;\n> > > > > >         streamConfig.size.height = size.height;\n> > > > > >         streamConfig.pixelFormat = pixelformat;\n> > > > > > -       streamConfig.bufferCount = bufferCount;\n> > > > > >         /* \\todo memoryType (interval vs external) */\n> > > > > >\n> > > > > >         CameraConfiguration::Status validation = config_->validate();\n> > > > > > @@ -146,7 +146,6 @@ int V4L2Camera::validateConfiguration(const PixelFormat &pixelFormat,\n> > > > > >         StreamConfiguration &cfg = config->at(0);\n> > > > > >         cfg.size = size;\n> > > > > >         cfg.pixelFormat = pixelFormat;\n> > > > > > -       cfg.bufferCount = 1;\n> > > > > >\n> > > > > >         CameraConfiguration::Status validation = config->validate();\n> > > > > >         if (validation == CameraConfiguration::Invalid)\n> > > > > > @@ -299,3 +298,10 @@ bool V4L2Camera::isRunning()\n> > > > > >  {\n> > > > > >         return isRunning_;\n> > > > > >  }\n> > > > > > +\n> > > > > > +unsigned int V4L2Camera::minimumRequests(unsigned int count)\n> > > > > > +{\n> > > > > > +       unsigned int min = camera_->properties().get(properties::MinimumRequests);\n> > > > > > +\n> > > > > > +       return std::max(count, min);\n> > > > > > +}\n> > > > > > diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h\n> > > > > > index a095f4e27524..4b5618ac12b5 100644\n> > > > > > --- a/src/v4l2/v4l2_camera.h\n> > > > > > +++ b/src/v4l2/v4l2_camera.h\n> > > > > > @@ -45,8 +45,7 @@ public:\n> > > > > >         std::vector<Buffer> completedBuffers();\n> > > > > >\n> > > > > >         int configure(StreamConfiguration *streamConfigOut,\n> > > > > > -                     const Size &size, const PixelFormat &pixelformat,\n> > > > > > -                     unsigned int bufferCount);\n> > > > > > +                     const Size &size, const PixelFormat &pixelformat);\n> > > > > >         int validateConfiguration(const PixelFormat &pixelformat,\n> > > > > >                                   const Size &size,\n> > > > > >                                   StreamConfiguration *streamConfigOut);\n> > > > > > @@ -65,6 +64,8 @@ public:\n> > > > > >\n> > > > > >         bool isRunning();\n> > > > > >\n> > > > > > +       unsigned int minimumRequests(unsigned int count);\n> > > > > > +\n> > > > > >  private:\n> > > > > >         void requestComplete(Request *request);\n> > > > > >\n> > > > > > diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp\n> > > > > > index 7682c4bddf90..634ec84e0cbb 100644\n> > > > > > --- a/src/v4l2/v4l2_camera_proxy.cpp\n> > > > > > +++ b/src/v4l2/v4l2_camera_proxy.cpp\n> > > > > > @@ -349,8 +349,7 @@ int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg)\n> > > > > >         Size size(arg->fmt.pix.width, arg->fmt.pix.height);\n> > > > > >         V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->fmt.pix.pixelformat);\n> > > > > >         ret = vcam_->configure(&streamConfig_, size,\n> > > > > > -                              PixelFormatInfo::info(v4l2Format).format,\n> > > > > > -                              bufferCount_);\n> > > > > > +                              PixelFormatInfo::info(v4l2Format).format);\n> > > > > >         if (ret < 0)\n> > > > > >                 return -EINVAL;\n> > > > > >\n> > > > > > @@ -491,14 +490,13 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf\n> > > > > >         Size size(v4l2PixFormat_.width, v4l2PixFormat_.height);\n> > > > > >         V4L2PixelFormat v4l2Format = V4L2PixelFormat(v4l2PixFormat_.pixelformat);\n> > > > > >         int ret = vcam_->configure(&streamConfig_, size,\n> > > > > > -                                  PixelFormatInfo::info(v4l2Format).format,\n> > > > > > -                                  arg->count);\n> > > > > > +                                  PixelFormatInfo::info(v4l2Format).format);\n> > > > > >         if (ret < 0)\n> > > > > >                 return -EINVAL;\n> > > > > >\n> > > > > >         setFmtFromConfig(streamConfig_);\n> > > > > >\n> > > > > > -       arg->count = streamConfig_.bufferCount;\n> > > > > > +       arg->count = vcam_->minimumRequests(arg->count);\n> > > > > >         bufferCount_ = arg->count;\n> > > > > >\n> > > > > >         ret = vcam_->allocBuffers(arg->count);\n> > > > > > diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp\n> > > > > > index c504ea09e64b..67ac0ad20e15 100644\n> > > > > > --- a/test/camera/buffer_import.cpp\n> > > > > > +++ b/test/camera/buffer_import.cpp\n> > > > > > @@ -16,6 +16,8 @@\n> > > > > >  #include <libcamera/base/thread.h>\n> > > > > >  #include <libcamera/base/timer.h>\n> > > > > >\n> > > > > > +#include <libcamera/property_ids.h>\n> > > > > > +\n> > > > > >  #include \"libcamera/internal/device_enumerator.h\"\n> > > > > >  #include \"libcamera/internal/media_device.h\"\n> > > > > >  #include \"libcamera/internal/v4l2_videodevice.h\"\n> > > > > > @@ -92,10 +94,12 @@ protected:\n> > > > > >                         return TestFail;\n> > > > > >                 }\n> > > > > >\n> > > > > > +               unsigned int bufferCount = camera_->properties().get(properties::MinimumRequests);\n> > > > > > +\n> > > > > >                 Stream *stream = cfg.stream();\n> > > > > >\n> > > > > >                 BufferSource source;\n> > > > > > -               int ret = source.allocate(cfg);\n> > > > > > +               int ret = source.allocate(cfg, bufferCount);\n> > > > > >                 if (ret != TestPass)\n> > > > > >                         return ret;\n> > > > > >\n> > > > > > @@ -139,10 +143,10 @@ protected:\n> > > > > >                 while (timer.isRunning())\n> > > > > >                         dispatcher->processEvents();\n> > > > > >\n> > > > > > -               if (completeRequestsCount_ < cfg.bufferCount * 2) {\n> > > > > > +               if (completeRequestsCount_ < bufferCount * 2) {\n> > > > > >                         std::cout << \"Failed to capture enough frames (got \"\n> > > > > >                                   << completeRequestsCount_ << \" expected at least \"\n> > > > > > -                                 << cfg.bufferCount * 2 << \")\" << std::endl;\n> > > > > > +                                 << bufferCount * 2 << \")\" << std::endl;\n> > > > > >                         return TestFail;\n> > > > > >                 }\n> > > > > >\n> > > > > > diff --git a/test/libtest/buffer_source.cpp b/test/libtest/buffer_source.cpp\n> > > > > > index 73563f2fc39d..c3d5286a2462 100644\n> > > > > > --- a/test/libtest/buffer_source.cpp\n> > > > > > +++ b/test/libtest/buffer_source.cpp\n> > > > > > @@ -24,7 +24,7 @@ BufferSource::~BufferSource()\n> > > > > >                 media_->release();\n> > > > > >  }\n> > > > > >\n> > > > > > -int BufferSource::allocate(const StreamConfiguration &config)\n> > > > > > +int BufferSource::allocate(const StreamConfiguration &config, unsigned int count)\n> > > > > >  {\n> > > > > >         /* Locate and open the video device. */\n> > > > > >         std::string videoDeviceName = \"vivid-000-vid-out\";\n> > > > > > @@ -77,7 +77,7 @@ int BufferSource::allocate(const StreamConfiguration &config)\n> > > > > >                 return TestFail;\n> > > > > >         }\n> > > > > >\n> > > > > > -       if (video->allocateBuffers(config.bufferCount, &buffers_) < 0) {\n> > > > > > +       if (video->allocateBuffers(count, &buffers_) < 0) {\n> > > > > >                 std::cout << \"Failed to allocate buffers\" << std::endl;\n> > > > > >                 return TestFail;\n> > > > > >         }\n> > > > > > diff --git a/test/libtest/buffer_source.h b/test/libtest/buffer_source.h\n> > > > > > index 14b4770e8d8a..6a18e269a575 100644\n> > > > > > --- a/test/libtest/buffer_source.h\n> > > > > > +++ b/test/libtest/buffer_source.h\n> > > > > > @@ -20,7 +20,7 @@ public:\n> > > > > >         BufferSource();\n> > > > > >         ~BufferSource();\n> > > > > >\n> > > > > > -       int allocate(const StreamConfiguration &config);\n> > > > > > +       int allocate(const StreamConfiguration &config, unsigned int count);\n> > > > > >         const std::vector<std::unique_ptr<FrameBuffer>> &buffers();\n> > > > > >\n> > > > > >  private:\n> > > > > > diff --git a/test/v4l2_videodevice/buffer_cache.cpp b/test/v4l2_videodevice/buffer_cache.cpp\n> > > > > > index b3f2bec11783..07fddfd2617c 100644\n> > > > > > --- a/test/v4l2_videodevice/buffer_cache.cpp\n> > > > > > +++ b/test/v4l2_videodevice/buffer_cache.cpp\n> > > > > > @@ -10,6 +10,7 @@\n> > > > > >  #include <vector>\n> > > > > >\n> > > > > >  #include <libcamera/formats.h>\n> > > > > > +#include <libcamera/property_ids.h>\n> > > > > >  #include <libcamera/stream.h>\n> > > > > >\n> > > > > >  #include \"buffer_source.h\"\n> > > > > > @@ -145,10 +146,9 @@ public:\n> > > > > >                 StreamConfiguration cfg;\n> > > > > >                 cfg.pixelFormat = formats::YUYV;\n> > > > > >                 cfg.size = Size(600, 800);\n> > > > > > -               cfg.bufferCount = numBuffers;\n> > > > > >\n> > > > > >                 BufferSource source;\n> > > > > > -               int ret = source.allocate(cfg);\n> > > > > > +               int ret = source.allocate(cfg, numBuffers);\n> > > > > >                 if (ret != TestPass)\n> > > > > >                         return ret;\n> > > > > >\n> > > > > > --\n> > > > > > 2.32.0\n> > > > > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 38041C3230\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 29 Jul 2021 14:38:28 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6216A687C5;\n\tThu, 29 Jul 2021 16:38:27 +0200 (CEST)","from bhuna.collabora.co.uk (bhuna.collabora.co.uk\n\t[IPv6:2a00:1098:0:82:1000:25:2eeb:e3e3])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id B2127687BA\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 29 Jul 2021 16:38:26 +0200 (CEST)","from notapiano (unknown\n\t[IPv6:2804:14c:1a9:2434:3299:38f2:eede:8f33])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits))\n\t(No client certificate requested) (Authenticated sender: nfraprado)\n\tby bhuna.collabora.co.uk (Postfix) with ESMTPSA id D90F61F44271;\n\tThu, 29 Jul 2021 15:38:24 +0100 (BST)"],"Date":"Thu, 29 Jul 2021 11:38:20 -0300","From":"=?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4=?= Prado <nfraprado@collabora.com>","To":"David Plowman <david.plowman@raspberrypi.com>","Message-ID":"<20210729143820.yumwo33jpwaljyb2@notapiano>","References":"<20210722232851.747614-1-nfraprado@collabora.com>\n\t<20210722232851.747614-11-nfraprado@collabora.com>\n\t<CAHW6GYJbVdFebNca9ZeM8LY=Ca4P1uaUd3B-r5FF7mJ9k853fg@mail.gmail.com>\n\t<20210723131039.ire2z7u6sdxws3dt@notapiano>\n\t<CAHW6GYKCBXmNSzo+_EcQCvJEaPg-ahMsWXKwVA=J8YzZEtBUWA@mail.gmail.com>\n\t<20210723210807.emekovdwbehrzr44@notapiano>\n\t<CAHW6GYLbPU0TKbMNeNsHdif6Nm+-iUfBgRAcnUN6=ftKYsmYoQ@mail.gmail.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=iso-8859-1","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<CAHW6GYLbPU0TKbMNeNsHdif6Nm+-iUfBgRAcnUN6=ftKYsmYoQ@mail.gmail.com>","Subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>,\n\tkernel@collabora.com, =?utf-8?b?QW5kcsOp?=\n\tAlmeida <andrealmeid@collabora.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":18421,"web_url":"https://patchwork.libcamera.org/comment/18421/","msgid":"<CAHW6GYJCx2kOyikHr7S2St9ud8ssZDb_rNByGSbciR7J1sYSVg@mail.gmail.com>","date":"2021-07-29T16:03:24","subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","submitter":{"id":42,"url":"https://patchwork.libcamera.org/api/people/42/","name":"David Plowman","email":"david.plowman@raspberrypi.com"},"content":"Ah, OK, that sounds straightforward, then. Thanks for the explanation!\n\nBest regards\nDavid\n\nOn Thu, 29 Jul 2021 at 15:38, Nícolas F. R. A. Prado\n<nfraprado@collabora.com> wrote:\n>\n> Hi David,\n>\n> On Thu, Jul 29, 2021 at 11:00:33AM +0100, David Plowman wrote:\n> > Hi again\n> >\n> > I thought that perhaps I could explain in more detail why I think\n> > applications need to be able to set (or influence) the buffer count\n> > and not leave it to the pipeline handler. My use-case is as follows.\n> >\n> > I'm running some standard sort of application such as video recording\n> > for which there are maybe 4 buffers allocated. Now, I also want to do\n> > some image analysis that perhaps causes me to change something about\n> > the recording (maybe change camera settings, or even stop the\n> > recording). But this image analysis task is relatively slow.\n> >\n> > One option is to copy the camera frames so that I can return the\n> > buffers in the request back to the camera. But copying images is\n> > generally undesirable. Instead I'd prefer to hold on to the buffer\n> > only now my camera pipeline is effectively working with only 3\n> > buffers, which is not enough. When I eventually finish with the buffer\n> > I will return it, and then grab the next one to keep again!\n>\n> Ohh, I see. Sorry, I got a bit confused there, but this is not a problem at all.\n> If you want the pipeline to work with extra requests/buffers, you just supply\n> more to it :). Going back to your code snippet, this would be the change:\n>\n>     configuration_ = camera_->generateConfiguration({ StreamRole::StillCapture });\n> -   configuration_->at(0).bufferCount = <value I have determined>;\n>     camera_->configure(configuration_.get());\n>     allocator_ = new FrameBufferAllocator(camera_);\n>     Stream *stream = configuration_->at(0).stream();\n> -   allocator_->allocate(stream);\n> +   allocator_->allocate(stream, <value I have determined>);\n>     // now allocator_->buffers(stream) has the buffers I want!\n>\n> So, basically, you don't need to set bufferCount anymore, and instead you\n> allocate as many buffers as you need to give the pipeline handler by directly\n> passing the number to FrameBufferAllocator. In your case you want to allocate an\n> extra buffer to compensate for the one you'll be keeping.\n>\n> It was already possible to supply the pipeline handler with how many\n> buffers you wanted, but previously you had to allocate them elsewhere, while now\n> you can allocate with the FrameBufferAllocator since it accepts the count\n> argument. (Actually for the raspberry pipeline it was already possible to do\n> this implicitly through bufferCount as you did, but not with the other\n> pipelines).\n>\n> What I meant wasn't possible to change is how many internal buffers for metadata\n> and parameters the pipeline uses together with the IPA. And also how many V4L2\n> buffer slots are created to queue the requests into. But all of this is indeed\n> only relevant to the pipeline handler, so an application shouldn't care about\n> it. All of this, together with how many buffers the application would allocate,\n> was previously grouped on bufferCount. With its deletion, however, they are\n> getting split up.\n>\n> I hope I got it right this time :).\n>\n> Thanks,\n> Nícolas\n>\n> >\n> > So at the very least, the application needs to be able to say \"please\n> > allocate <n> more buffers than you thought you needed\". Does that make\n> > sense? Will this be possible in the new scheme?\n> >\n> > Thanks!\n> > David\n> >\n> > On Fri, 23 Jul 2021 at 22:08, Nícolas F. R. A. Prado\n> > <nfraprado@collabora.com> wrote:\n> > >\n> > > Hi David,\n> > >\n> > > On Fri, Jul 23, 2021 at 04:53:55PM +0100, David Plowman wrote:\n> > > > Hi Nicolas\n> > > >\n> > > > Thanks for the explanations. I'm still not sure I entirely understand\n> > > > so perhaps a quick look at how I would have to change my application\n> > > > code might help? Here's what I have now (I've removed any\n> > > > \"unimportant\" bits!):\n> > > >\n> > > > configuration_ = camera_->generateConfiguration({ StreamRole::StillCapture });\n> > > > configuration_->at(0).bufferCount = <value I have determined>;\n> > > > camera_->configure(configuration_.get());\n> > > > allocator_ = new FrameBufferAllocator(camera_);\n> > > > Stream *stream = configuration_->at(0).stream();\n> > > > allocator_->allocate(stream);\n> > > > // now allocator_->buffers(stream) has the buffers I want!\n> > > >\n> > > > I guess one thing to note is that the bufferCount value varies with\n> > > > more than just the StreamRole, and I don't in general trust the\n> > > > pipeline handler to \"know\" what I want. Will this still be possible?\n> > >\n> > > Oh I see... No, this won't be possible after we drop bufferCount. The\n> > > pipeline handler will decide for itself how many buffers to allocate internally,\n> > > possibly using the StreamRole as a hint.\n> > >\n> > > I wasn't aware this could impact an application, since all the other pipeline\n> > > handlers actually ignore when bufferCount is set by the application, overriding\n> > > it when the configuration is validated. But now I'm noticing the raspberrypi\n> > > pipeline actually uses it.\n> > >\n> > > Some context: This series actually began with me making\n> > > FrameBufferAllocator::allocate() receive a count argument instead of using the\n> > > value of bufferCount. But since Laurent mentioned that bufferCount was going\n> > > away eventually anyway I ended up removing it as well as part of this series.\n> > >\n> > > I do understand how being able to specify a bufferCount value that suits your\n> > > specific usecase is useful, though... Laurent, what's your take on this? :)\n> > >\n> > > Thanks,\n> > > Nícolas\n> > >\n> > > >\n> > > > Thanks!\n> > > > David\n> > > >\n> > > > On Fri, 23 Jul 2021 at 14:10, Nícolas F. R. A. Prado\n> > > > <nfraprado@collabora.com> wrote:\n> > > > >\n> > > > > Hi David,\n> > > > >\n> > > > > On Fri, Jul 23, 2021 at 09:42:56AM +0100, David Plowman wrote:\n> > > > > > Hi Nicolas\n> > > > > >\n> > > > > > Thanks very much for all this work! I was wondering if I could ask a\n> > > > > > little more about this patch. In our applications, for example, we set\n> > > > > > the bufferCount according to the use-case that the application is\n> > > > > > implementing. For example:\n> > > > > >\n> > > > > > * For preview windows we set bufferCount to 4.\n> > > > > > * For video capture we drop fewer frames with a deeper queue so we set it to 6.\n> > > > > > * For stills capture we can get by with one frame, though use cases\n> > > > > > that capture several stills images for fusion work better if we set\n> > > > > > bufferCount to 2 or 3.\n> > > > > >\n> > > > > > I was wondering how our applications can achieve this behaviour if the\n> > > > > > bufferCount field is no longer available.\n> > > > >\n> > > > > Okay, so the short answer is that the applications, knowing their particular use\n> > > > > case, are responsible to provide enough requests to keep the pipeline going. On\n> > > > > the pipeline handler side, it's free to use how many internal buffers it wants.\n> > > > >\n> > > > > So in your case, the pipeline handler could still allocate that same number of\n> > > > > internal buffers as you previously did based on bufferCount, but now based\n> > > > > solely on the StreamRole set. The application would then allocate and queue\n> > > > > how many buffers fits the usage. (Note that before the application would call\n> > > > > FrameBufferAllocator::allocate() and it would allocate 'bufferCount' buffers,\n> > > > > but now the function takes a count argument so the application is free to choose\n> > > > > how many)\n> > > > >\n> > > > > Now, I guess it would be nice for the application to be able to query what is a\n> > > > > good number of buffers to use, for example 6 in the video capture of your use\n> > > > > case. At the moment, the only information available is that 1 is the minimum\n> > > > > number of buffers required. So the application would have to know that 6 is a\n> > > > > good number for video capture. Maybe another property could be introduced later\n> > > > > for this recommended amount, but previous discussions suggested this is very use\n> > > > > case dependent, so might not make sense.\n> > > > >\n> > > > > I hope this answers the question. If not, I'm still here :).\n> > > > >\n> > > > > Thanks,\n> > > > > Nícolas\n> > > > >\n> > > > > >\n> > > > > > Thanks!\n> > > > > > David\n> > > > > >\n> > > > > > On Fri, 23 Jul 2021 at 00:29, Nícolas F. R. A. Prado\n> > > > > > <nfraprado@collabora.com> wrote:\n> > > > > > >\n> > > > > > > Now that the number of buffers allocated by the FrameBufferAllocator\n> > > > > > > helper is passed through FrameBufferAllocator::allocate() and the\n> > > > > > > pipelines no longer use bufferCount for internal buffer or V4L2 buffer\n> > > > > > > slots allocation, we no longer need to have bufferCount in the\n> > > > > > > StreamConfiguration, so remove it.\n> > > > > > >\n> > > > > > > Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>\n> > > > > > > ---\n> > > > > > >\n> > > > > > > No changes in v7\n> > > > > > >\n> > > > > > > Changes in v6:\n> > > > > > > - Removed IPU3_BUFFER_COUNT as it was unused\n> > > > > > >\n> > > > > > >  include/libcamera/stream.h                         |  2 --\n> > > > > > >  src/android/camera_stream.cpp                      |  2 +-\n> > > > > > >  src/libcamera/pipeline/ipu3/cio2.cpp               |  1 -\n> > > > > > >  src/libcamera/pipeline/ipu3/ipu3.cpp               |  8 --------\n> > > > > > >  src/libcamera/pipeline/raspberrypi/raspberrypi.cpp |  6 ------\n> > > > > > >  src/libcamera/pipeline/rkisp1/rkisp1_path.cpp      |  2 --\n> > > > > > >  src/libcamera/pipeline/simple/converter.cpp        |  3 ---\n> > > > > > >  src/libcamera/pipeline/simple/converter.h          |  3 ---\n> > > > > > >  src/libcamera/pipeline/simple/simple.cpp           |  5 +----\n> > > > > > >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp       |  3 ---\n> > > > > > >  src/libcamera/pipeline/vimc/vimc.cpp               |  3 ---\n> > > > > > >  src/libcamera/stream.cpp                           |  9 ++-------\n> > > > > > >  src/v4l2/v4l2_camera.cpp                           | 14 ++++++++++----\n> > > > > > >  src/v4l2/v4l2_camera.h                             |  5 +++--\n> > > > > > >  src/v4l2/v4l2_camera_proxy.cpp                     |  8 +++-----\n> > > > > > >  test/camera/buffer_import.cpp                      | 10 +++++++---\n> > > > > > >  test/libtest/buffer_source.cpp                     |  4 ++--\n> > > > > > >  test/libtest/buffer_source.h                       |  2 +-\n> > > > > > >  test/v4l2_videodevice/buffer_cache.cpp             |  4 ++--\n> > > > > > >  19 files changed, 32 insertions(+), 62 deletions(-)\n> > > > > > >\n> > > > > > > diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\n> > > > > > > index 0c55e7164592..b25f0059f2f1 100644\n> > > > > > > --- a/include/libcamera/stream.h\n> > > > > > > +++ b/include/libcamera/stream.h\n> > > > > > > @@ -45,8 +45,6 @@ struct StreamConfiguration {\n> > > > > > >         unsigned int stride;\n> > > > > > >         unsigned int frameSize;\n> > > > > > >\n> > > > > > > -       unsigned int bufferCount;\n> > > > > > > -\n> > > > > > >         Stream *stream() const { return stream_; }\n> > > > > > >         void setStream(Stream *stream) { stream_ = stream; }\n> > > > > > >         const StreamFormats &formats() const { return formats_; }\n> > > > > > > diff --git a/src/android/camera_stream.cpp b/src/android/camera_stream.cpp\n> > > > > > > index b168e3c0c288..0794be409f82 100644\n> > > > > > > --- a/src/android/camera_stream.cpp\n> > > > > > > +++ b/src/android/camera_stream.cpp\n> > > > > > > @@ -94,7 +94,7 @@ int CameraStream::configure()\n> > > > > > >                         buffers_.push_back(frameBuffer.get());\n> > > > > > >         }\n> > > > > > >\n> > > > > > > -       camera3Stream_->max_buffers = configuration().bufferCount;\n> > > > > > > +       camera3Stream_->max_buffers = bufferCount;\n> > > > > > >\n> > > > > > >         return 0;\n> > > > > > >  }\n> > > > > > > diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > > > > > index 1bcd580e251c..0e04e7214489 100644\n> > > > > > > --- a/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > > > > > +++ b/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > > > > > @@ -214,7 +214,6 @@ StreamConfiguration CIO2Device::generateConfiguration(Size size) const\n> > > > > > >\n> > > > > > >         cfg.size = sensorFormat.size;\n> > > > > > >         cfg.pixelFormat = mbusCodesToPixelFormat.at(sensorFormat.mbus_code);\n> > > > > > > -       cfg.bufferCount = CIO2_BUFFER_COUNT;\n> > > > > > >\n> > > > > > >         return cfg;\n> > > > > > >  }\n> > > > > > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > > > > index 4efd201c05e5..b223b3f33cd0 100644\n> > > > > > > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > > > > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > > > > @@ -38,7 +38,6 @@ namespace libcamera {\n> > > > > > >\n> > > > > > >  LOG_DEFINE_CATEGORY(IPU3)\n> > > > > > >\n> > > > > > > -static constexpr unsigned int IPU3_BUFFER_COUNT = 4;\n> > > > > > >  static constexpr unsigned int IPU3_MAX_STREAMS = 3;\n> > > > > > >  static const Size IMGU_OUTPUT_MIN_SIZE = { 2, 2 };\n> > > > > > >  static const Size IMGU_OUTPUT_MAX_SIZE = { 4480, 34004 };\n> > > > > > > @@ -295,7 +294,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n> > > > > > >                         /* Initialize the RAW stream with the CIO2 configuration. */\n> > > > > > >                         cfg->size = cio2Configuration_.size;\n> > > > > > >                         cfg->pixelFormat = cio2Configuration_.pixelFormat;\n> > > > > > > -                       cfg->bufferCount = cio2Configuration_.bufferCount;\n> > > > > > >                         cfg->stride = info.stride(cfg->size.width, 0, 64);\n> > > > > > >                         cfg->frameSize = info.frameSize(cfg->size, 64);\n> > > > > > >                         cfg->setStream(const_cast<Stream *>(&data_->rawStream_));\n> > > > > > > @@ -339,7 +337,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n> > > > > > >                                               IMGU_OUTPUT_HEIGHT_ALIGN);\n> > > > > > >\n> > > > > > >                         cfg->pixelFormat = formats::NV12;\n> > > > > > > -                       cfg->bufferCount = IPU3_BUFFER_COUNT;\n> > > > > > >                         cfg->stride = info.stride(cfg->size.width, 0, 1);\n> > > > > > >                         cfg->frameSize = info.frameSize(cfg->size, 1);\n> > > > > > >\n> > > > > > > @@ -407,7 +404,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > > > >         Size sensorResolution = data->cio2_.sensor()->resolution();\n> > > > > > >         for (const StreamRole role : roles) {\n> > > > > > >                 std::map<PixelFormat, std::vector<SizeRange>> streamFormats;\n> > > > > > > -               unsigned int bufferCount;\n> > > > > > >                 PixelFormat pixelFormat;\n> > > > > > >                 Size size;\n> > > > > > >\n> > > > > > > @@ -428,7 +424,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > > > >                         size.height = utils::alignDown(size.height - 1,\n> > > > > > >                                                        IMGU_OUTPUT_HEIGHT_MARGIN);\n> > > > > > >                         pixelFormat = formats::NV12;\n> > > > > > > -                       bufferCount = IPU3_BUFFER_COUNT;\n> > > > > > >                         streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n> > > > > > >\n> > > > > > >                         break;\n> > > > > > > @@ -438,7 +433,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > > > >                                 data->cio2_.generateConfiguration(sensorResolution);\n> > > > > > >                         pixelFormat = cio2Config.pixelFormat;\n> > > > > > >                         size = cio2Config.size;\n> > > > > > > -                       bufferCount = cio2Config.bufferCount;\n> > > > > > >\n> > > > > > >                         for (const PixelFormat &format : data->cio2_.formats())\n> > > > > > >                                 streamFormats[format] = data->cio2_.sizes();\n> > > > > > > @@ -457,7 +451,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > > > >                                                .alignedDownTo(IMGU_OUTPUT_WIDTH_ALIGN,\n> > > > > > >                                                               IMGU_OUTPUT_HEIGHT_ALIGN);\n> > > > > > >                         pixelFormat = formats::NV12;\n> > > > > > > -                       bufferCount = IPU3_BUFFER_COUNT;\n> > > > > > >                         streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n> > > > > > >\n> > > > > > >                         break;\n> > > > > > > @@ -474,7 +467,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > > > >                 StreamConfiguration cfg(formats);\n> > > > > > >                 cfg.size = size;\n> > > > > > >                 cfg.pixelFormat = pixelFormat;\n> > > > > > > -               cfg.bufferCount = bufferCount;\n> > > > > > >                 config->addConfiguration(cfg);\n> > > > > > >         }\n> > > > > > >\n> > > > > > > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > > > > > index 776e0f92aed1..e6fc0425c3ef 100644\n> > > > > > > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > > > > > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > > > > > @@ -473,7 +473,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > > >         RPiCameraData *data = cameraData(camera);\n> > > > > > >         CameraConfiguration *config = new RPiCameraConfiguration(data);\n> > > > > > >         V4L2DeviceFormat sensorFormat;\n> > > > > > > -       unsigned int bufferCount;\n> > > > > > >         PixelFormat pixelFormat;\n> > > > > > >         V4L2VideoDevice::Formats fmts;\n> > > > > > >         Size size;\n> > > > > > > @@ -491,7 +490,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > > >                         sensorFormat = findBestMode(fmts, size);\n> > > > > > >                         pixelFormat = sensorFormat.fourcc.toPixelFormat();\n> > > > > > >                         ASSERT(pixelFormat.isValid());\n> > > > > > > -                       bufferCount = 2;\n> > > > > > >                         rawCount++;\n> > > > > > >                         break;\n> > > > > > >\n> > > > > > > @@ -500,7 +498,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > > >                         pixelFormat = formats::NV12;\n> > > > > > >                         /* Return the largest sensor resolution. */\n> > > > > > >                         size = data->sensor_->resolution();\n> > > > > > > -                       bufferCount = 1;\n> > > > > > >                         outCount++;\n> > > > > > >                         break;\n> > > > > > >\n> > > > > > > @@ -516,7 +513,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > > >                         fmts = data->isp_[Isp::Output0].dev()->formats();\n> > > > > > >                         pixelFormat = formats::YUV420;\n> > > > > > >                         size = { 1920, 1080 };\n> > > > > > > -                       bufferCount = 4;\n> > > > > > >                         outCount++;\n> > > > > > >                         break;\n> > > > > > >\n> > > > > > > @@ -524,7 +520,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > > >                         fmts = data->isp_[Isp::Output0].dev()->formats();\n> > > > > > >                         pixelFormat = formats::ARGB8888;\n> > > > > > >                         size = { 800, 600 };\n> > > > > > > -                       bufferCount = 4;\n> > > > > > >                         outCount++;\n> > > > > > >                         break;\n> > > > > > >\n> > > > > > > @@ -554,7 +549,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > > >                 StreamConfiguration cfg(formats);\n> > > > > > >                 cfg.size = size;\n> > > > > > >                 cfg.pixelFormat = pixelFormat;\n> > > > > > > -               cfg.bufferCount = bufferCount;\n> > > > > > >                 config->addConfiguration(cfg);\n> > > > > > >         }\n> > > > > > >\n> > > > > > > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > > > > > index fea330f72886..4961f3971e59 100644\n> > > > > > > --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > > > > > +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > > > > > @@ -61,7 +61,6 @@ StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution)\n> > > > > > >         StreamConfiguration cfg(formats);\n> > > > > > >         cfg.pixelFormat = formats::NV12;\n> > > > > > >         cfg.size = maxResolution;\n> > > > > > > -       cfg.bufferCount = RKISP1_BUFFER_COUNT;\n> > > > > > >\n> > > > > > >         return cfg;\n> > > > > > >  }\n> > > > > > > @@ -77,7 +76,6 @@ CameraConfiguration::Status RkISP1Path::validate(StreamConfiguration *cfg)\n> > > > > > >\n> > > > > > >         cfg->size.boundTo(maxResolution_);\n> > > > > > >         cfg->size.expandTo(minResolution_);\n> > > > > > > -       cfg->bufferCount = RKISP1_BUFFER_COUNT;\n> > > > > > >\n> > > > > > >         V4L2DeviceFormat format;\n> > > > > > >         format.fourcc = video_->toV4L2PixelFormat(cfg->pixelFormat);\n> > > > > > > diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp\n> > > > > > > index b3bcf01483f7..fda417793e80 100644\n> > > > > > > --- a/src/libcamera/pipeline/simple/converter.cpp\n> > > > > > > +++ b/src/libcamera/pipeline/simple/converter.cpp\n> > > > > > > @@ -89,9 +89,6 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg,\n> > > > > > >                 return -EINVAL;\n> > > > > > >         }\n> > > > > > >\n> > > > > > > -       inputBufferCount_ = inputCfg.bufferCount;\n> > > > > > > -       outputBufferCount_ = outputCfg.bufferCount;\n> > > > > > > -\n> > > > > > >         return 0;\n> > > > > > >  }\n> > > > > > >\n> > > > > > > diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h\n> > > > > > > index 7e1d60674f62..406e63ca2a80 100644\n> > > > > > > --- a/src/libcamera/pipeline/simple/converter.h\n> > > > > > > +++ b/src/libcamera/pipeline/simple/converter.h\n> > > > > > > @@ -87,9 +87,6 @@ private:\n> > > > > > >                 SimpleConverter *converter_;\n> > > > > > >                 unsigned int index_;\n> > > > > > >                 std::unique_ptr<V4L2M2MDevice> m2m_;\n> > > > > > > -\n> > > > > > > -               unsigned int inputBufferCount_;\n> > > > > > > -               unsigned int outputBufferCount_;\n> > > > > > >         };\n> > > > > > >\n> > > > > > >         std::string deviceNode_;\n> > > > > > > diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\n> > > > > > > index a1163eaf8be2..ded04914f610 100644\n> > > > > > > --- a/src/libcamera/pipeline/simple/simple.cpp\n> > > > > > > +++ b/src/libcamera/pipeline/simple/simple.cpp\n> > > > > > > @@ -628,7 +628,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n> > > > > > >                     cfg.size != pipeConfig_->captureSize)\n> > > > > > >                         needConversion_ = true;\n> > > > > > >\n> > > > > > > -               /* Set the stride, frameSize and bufferCount. */\n> > > > > > > +               /* Set the stride and frameSize. */\n> > > > > > >                 if (needConversion_) {\n> > > > > > >                         std::tie(cfg.stride, cfg.frameSize) =\n> > > > > > >                                 converter->strideAndFrameSize(cfg.pixelFormat, cfg.size);\n> > > > > > > @@ -646,8 +646,6 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n> > > > > > >                         cfg.stride = format.planes[0].bpl;\n> > > > > > >                         cfg.frameSize = format.planes[0].size;\n> > > > > > >                 }\n> > > > > > > -\n> > > > > > > -               cfg.bufferCount = 3;\n> > > > > > >         }\n> > > > > > >\n> > > > > > >         return status;\n> > > > > > > @@ -770,7 +768,6 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)\n> > > > > > >         inputCfg.pixelFormat = pipeConfig->captureFormat;\n> > > > > > >         inputCfg.size = pipeConfig->captureSize;\n> > > > > > >         inputCfg.stride = captureFormat.planes[0].bpl;\n> > > > > > > -       inputCfg.bufferCount = kNumInternalBuffers;\n> > > > > > >\n> > > > > > >         return converter_->configure(inputCfg, outputCfgs);\n> > > > > > >  }\n> > > > > > > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > > > > > index 755949e7a59a..32482300f09a 100644\n> > > > > > > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > > > > > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > > > > > @@ -150,8 +150,6 @@ CameraConfiguration::Status UVCCameraConfiguration::validate()\n> > > > > > >                 status = Adjusted;\n> > > > > > >         }\n> > > > > > >\n> > > > > > > -       cfg.bufferCount = 4;\n> > > > > > > -\n> > > > > > >         V4L2DeviceFormat format;\n> > > > > > >         format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n> > > > > > >         format.size = cfg.size;\n> > > > > > > @@ -193,7 +191,6 @@ CameraConfiguration *PipelineHandlerUVC::generateConfiguration(Camera *camera,\n> > > > > > >\n> > > > > > >         cfg.pixelFormat = formats.pixelformats().front();\n> > > > > > >         cfg.size = formats.sizes(cfg.pixelFormat).back();\n> > > > > > > -       cfg.bufferCount = 4;\n> > > > > > >\n> > > > > > >         config->addConfiguration(cfg);\n> > > > > > >\n> > > > > > > diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp\n> > > > > > > index 24ba743a946c..a698427c4361 100644\n> > > > > > > --- a/src/libcamera/pipeline/vimc/vimc.cpp\n> > > > > > > +++ b/src/libcamera/pipeline/vimc/vimc.cpp\n> > > > > > > @@ -167,8 +167,6 @@ CameraConfiguration::Status VimcCameraConfiguration::validate()\n> > > > > > >                 status = Adjusted;\n> > > > > > >         }\n> > > > > > >\n> > > > > > > -       cfg.bufferCount = 4;\n> > > > > > > -\n> > > > > > >         V4L2DeviceFormat format;\n> > > > > > >         format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n> > > > > > >         format.size = cfg.size;\n> > > > > > > @@ -224,7 +222,6 @@ CameraConfiguration *PipelineHandlerVimc::generateConfiguration(Camera *camera,\n> > > > > > >\n> > > > > > >         cfg.pixelFormat = formats::BGR888;\n> > > > > > >         cfg.size = { 1920, 1080 };\n> > > > > > > -       cfg.bufferCount = 4;\n> > > > > > >\n> > > > > > >         config->addConfiguration(cfg);\n> > > > > > >\n> > > > > > > diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp\n> > > > > > > index b8626775d224..ca507b72b26a 100644\n> > > > > > > --- a/src/libcamera/stream.cpp\n> > > > > > > +++ b/src/libcamera/stream.cpp\n> > > > > > > @@ -280,7 +280,7 @@ SizeRange StreamFormats::range(const PixelFormat &pixelformat) const\n> > > > > > >   * handlers provide StreamFormats.\n> > > > > > >   */\n> > > > > > >  StreamConfiguration::StreamConfiguration()\n> > > > > > > -       : pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> > > > > > > +       : pixelFormat(0), stride(0), frameSize(0),\n> > > > > > >           stream_(nullptr)\n> > > > > > >  {\n> > > > > > >  }\n> > > > > > > @@ -289,7 +289,7 @@ StreamConfiguration::StreamConfiguration()\n> > > > > > >   * \\brief Construct a configuration with stream formats\n> > > > > > >   */\n> > > > > > >  StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n> > > > > > > -       : pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> > > > > > > +       : pixelFormat(0), stride(0), frameSize(0),\n> > > > > > >           stream_(nullptr), formats_(formats)\n> > > > > > >  {\n> > > > > > >  }\n> > > > > > > @@ -324,11 +324,6 @@ StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n> > > > > > >   * validating the configuration with a call to CameraConfiguration::validate().\n> > > > > > >   */\n> > > > > > >\n> > > > > > > -/**\n> > > > > > > - * \\var StreamConfiguration::bufferCount\n> > > > > > > - * \\brief Requested number of buffers to allocate for the stream\n> > > > > > > - */\n> > > > > > > -\n> > > > > > >  /**\n> > > > > > >   * \\fn StreamConfiguration::stream()\n> > > > > > >   * \\brief Retrieve the stream associated with the configuration\n> > > > > > > diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp\n> > > > > > > index d01eacfa2b84..2ff9affc6388 100644\n> > > > > > > --- a/src/v4l2/v4l2_camera.cpp\n> > > > > > > +++ b/src/v4l2/v4l2_camera.cpp\n> > > > > > > @@ -12,6 +12,8 @@\n> > > > > > >\n> > > > > > >  #include <libcamera/base/log.h>\n> > > > > > >\n> > > > > > > +#include <libcamera/property_ids.h>\n> > > > > > > +\n> > > > > > >  using namespace libcamera;\n> > > > > > >\n> > > > > > >  LOG_DECLARE_CATEGORY(V4L2Compat)\n> > > > > > > @@ -107,14 +109,12 @@ void V4L2Camera::requestComplete(Request *request)\n> > > > > > >  }\n> > > > > > >\n> > > > > > >  int V4L2Camera::configure(StreamConfiguration *streamConfigOut,\n> > > > > > > -                         const Size &size, const PixelFormat &pixelformat,\n> > > > > > > -                         unsigned int bufferCount)\n> > > > > > > +                         const Size &size, const PixelFormat &pixelformat)\n> > > > > > >  {\n> > > > > > >         StreamConfiguration &streamConfig = config_->at(0);\n> > > > > > >         streamConfig.size.width = size.width;\n> > > > > > >         streamConfig.size.height = size.height;\n> > > > > > >         streamConfig.pixelFormat = pixelformat;\n> > > > > > > -       streamConfig.bufferCount = bufferCount;\n> > > > > > >         /* \\todo memoryType (interval vs external) */\n> > > > > > >\n> > > > > > >         CameraConfiguration::Status validation = config_->validate();\n> > > > > > > @@ -146,7 +146,6 @@ int V4L2Camera::validateConfiguration(const PixelFormat &pixelFormat,\n> > > > > > >         StreamConfiguration &cfg = config->at(0);\n> > > > > > >         cfg.size = size;\n> > > > > > >         cfg.pixelFormat = pixelFormat;\n> > > > > > > -       cfg.bufferCount = 1;\n> > > > > > >\n> > > > > > >         CameraConfiguration::Status validation = config->validate();\n> > > > > > >         if (validation == CameraConfiguration::Invalid)\n> > > > > > > @@ -299,3 +298,10 @@ bool V4L2Camera::isRunning()\n> > > > > > >  {\n> > > > > > >         return isRunning_;\n> > > > > > >  }\n> > > > > > > +\n> > > > > > > +unsigned int V4L2Camera::minimumRequests(unsigned int count)\n> > > > > > > +{\n> > > > > > > +       unsigned int min = camera_->properties().get(properties::MinimumRequests);\n> > > > > > > +\n> > > > > > > +       return std::max(count, min);\n> > > > > > > +}\n> > > > > > > diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h\n> > > > > > > index a095f4e27524..4b5618ac12b5 100644\n> > > > > > > --- a/src/v4l2/v4l2_camera.h\n> > > > > > > +++ b/src/v4l2/v4l2_camera.h\n> > > > > > > @@ -45,8 +45,7 @@ public:\n> > > > > > >         std::vector<Buffer> completedBuffers();\n> > > > > > >\n> > > > > > >         int configure(StreamConfiguration *streamConfigOut,\n> > > > > > > -                     const Size &size, const PixelFormat &pixelformat,\n> > > > > > > -                     unsigned int bufferCount);\n> > > > > > > +                     const Size &size, const PixelFormat &pixelformat);\n> > > > > > >         int validateConfiguration(const PixelFormat &pixelformat,\n> > > > > > >                                   const Size &size,\n> > > > > > >                                   StreamConfiguration *streamConfigOut);\n> > > > > > > @@ -65,6 +64,8 @@ public:\n> > > > > > >\n> > > > > > >         bool isRunning();\n> > > > > > >\n> > > > > > > +       unsigned int minimumRequests(unsigned int count);\n> > > > > > > +\n> > > > > > >  private:\n> > > > > > >         void requestComplete(Request *request);\n> > > > > > >\n> > > > > > > diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp\n> > > > > > > index 7682c4bddf90..634ec84e0cbb 100644\n> > > > > > > --- a/src/v4l2/v4l2_camera_proxy.cpp\n> > > > > > > +++ b/src/v4l2/v4l2_camera_proxy.cpp\n> > > > > > > @@ -349,8 +349,7 @@ int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg)\n> > > > > > >         Size size(arg->fmt.pix.width, arg->fmt.pix.height);\n> > > > > > >         V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->fmt.pix.pixelformat);\n> > > > > > >         ret = vcam_->configure(&streamConfig_, size,\n> > > > > > > -                              PixelFormatInfo::info(v4l2Format).format,\n> > > > > > > -                              bufferCount_);\n> > > > > > > +                              PixelFormatInfo::info(v4l2Format).format);\n> > > > > > >         if (ret < 0)\n> > > > > > >                 return -EINVAL;\n> > > > > > >\n> > > > > > > @@ -491,14 +490,13 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf\n> > > > > > >         Size size(v4l2PixFormat_.width, v4l2PixFormat_.height);\n> > > > > > >         V4L2PixelFormat v4l2Format = V4L2PixelFormat(v4l2PixFormat_.pixelformat);\n> > > > > > >         int ret = vcam_->configure(&streamConfig_, size,\n> > > > > > > -                                  PixelFormatInfo::info(v4l2Format).format,\n> > > > > > > -                                  arg->count);\n> > > > > > > +                                  PixelFormatInfo::info(v4l2Format).format);\n> > > > > > >         if (ret < 0)\n> > > > > > >                 return -EINVAL;\n> > > > > > >\n> > > > > > >         setFmtFromConfig(streamConfig_);\n> > > > > > >\n> > > > > > > -       arg->count = streamConfig_.bufferCount;\n> > > > > > > +       arg->count = vcam_->minimumRequests(arg->count);\n> > > > > > >         bufferCount_ = arg->count;\n> > > > > > >\n> > > > > > >         ret = vcam_->allocBuffers(arg->count);\n> > > > > > > diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp\n> > > > > > > index c504ea09e64b..67ac0ad20e15 100644\n> > > > > > > --- a/test/camera/buffer_import.cpp\n> > > > > > > +++ b/test/camera/buffer_import.cpp\n> > > > > > > @@ -16,6 +16,8 @@\n> > > > > > >  #include <libcamera/base/thread.h>\n> > > > > > >  #include <libcamera/base/timer.h>\n> > > > > > >\n> > > > > > > +#include <libcamera/property_ids.h>\n> > > > > > > +\n> > > > > > >  #include \"libcamera/internal/device_enumerator.h\"\n> > > > > > >  #include \"libcamera/internal/media_device.h\"\n> > > > > > >  #include \"libcamera/internal/v4l2_videodevice.h\"\n> > > > > > > @@ -92,10 +94,12 @@ protected:\n> > > > > > >                         return TestFail;\n> > > > > > >                 }\n> > > > > > >\n> > > > > > > +               unsigned int bufferCount = camera_->properties().get(properties::MinimumRequests);\n> > > > > > > +\n> > > > > > >                 Stream *stream = cfg.stream();\n> > > > > > >\n> > > > > > >                 BufferSource source;\n> > > > > > > -               int ret = source.allocate(cfg);\n> > > > > > > +               int ret = source.allocate(cfg, bufferCount);\n> > > > > > >                 if (ret != TestPass)\n> > > > > > >                         return ret;\n> > > > > > >\n> > > > > > > @@ -139,10 +143,10 @@ protected:\n> > > > > > >                 while (timer.isRunning())\n> > > > > > >                         dispatcher->processEvents();\n> > > > > > >\n> > > > > > > -               if (completeRequestsCount_ < cfg.bufferCount * 2) {\n> > > > > > > +               if (completeRequestsCount_ < bufferCount * 2) {\n> > > > > > >                         std::cout << \"Failed to capture enough frames (got \"\n> > > > > > >                                   << completeRequestsCount_ << \" expected at least \"\n> > > > > > > -                                 << cfg.bufferCount * 2 << \")\" << std::endl;\n> > > > > > > +                                 << bufferCount * 2 << \")\" << std::endl;\n> > > > > > >                         return TestFail;\n> > > > > > >                 }\n> > > > > > >\n> > > > > > > diff --git a/test/libtest/buffer_source.cpp b/test/libtest/buffer_source.cpp\n> > > > > > > index 73563f2fc39d..c3d5286a2462 100644\n> > > > > > > --- a/test/libtest/buffer_source.cpp\n> > > > > > > +++ b/test/libtest/buffer_source.cpp\n> > > > > > > @@ -24,7 +24,7 @@ BufferSource::~BufferSource()\n> > > > > > >                 media_->release();\n> > > > > > >  }\n> > > > > > >\n> > > > > > > -int BufferSource::allocate(const StreamConfiguration &config)\n> > > > > > > +int BufferSource::allocate(const StreamConfiguration &config, unsigned int count)\n> > > > > > >  {\n> > > > > > >         /* Locate and open the video device. */\n> > > > > > >         std::string videoDeviceName = \"vivid-000-vid-out\";\n> > > > > > > @@ -77,7 +77,7 @@ int BufferSource::allocate(const StreamConfiguration &config)\n> > > > > > >                 return TestFail;\n> > > > > > >         }\n> > > > > > >\n> > > > > > > -       if (video->allocateBuffers(config.bufferCount, &buffers_) < 0) {\n> > > > > > > +       if (video->allocateBuffers(count, &buffers_) < 0) {\n> > > > > > >                 std::cout << \"Failed to allocate buffers\" << std::endl;\n> > > > > > >                 return TestFail;\n> > > > > > >         }\n> > > > > > > diff --git a/test/libtest/buffer_source.h b/test/libtest/buffer_source.h\n> > > > > > > index 14b4770e8d8a..6a18e269a575 100644\n> > > > > > > --- a/test/libtest/buffer_source.h\n> > > > > > > +++ b/test/libtest/buffer_source.h\n> > > > > > > @@ -20,7 +20,7 @@ public:\n> > > > > > >         BufferSource();\n> > > > > > >         ~BufferSource();\n> > > > > > >\n> > > > > > > -       int allocate(const StreamConfiguration &config);\n> > > > > > > +       int allocate(const StreamConfiguration &config, unsigned int count);\n> > > > > > >         const std::vector<std::unique_ptr<FrameBuffer>> &buffers();\n> > > > > > >\n> > > > > > >  private:\n> > > > > > > diff --git a/test/v4l2_videodevice/buffer_cache.cpp b/test/v4l2_videodevice/buffer_cache.cpp\n> > > > > > > index b3f2bec11783..07fddfd2617c 100644\n> > > > > > > --- a/test/v4l2_videodevice/buffer_cache.cpp\n> > > > > > > +++ b/test/v4l2_videodevice/buffer_cache.cpp\n> > > > > > > @@ -10,6 +10,7 @@\n> > > > > > >  #include <vector>\n> > > > > > >\n> > > > > > >  #include <libcamera/formats.h>\n> > > > > > > +#include <libcamera/property_ids.h>\n> > > > > > >  #include <libcamera/stream.h>\n> > > > > > >\n> > > > > > >  #include \"buffer_source.h\"\n> > > > > > > @@ -145,10 +146,9 @@ public:\n> > > > > > >                 StreamConfiguration cfg;\n> > > > > > >                 cfg.pixelFormat = formats::YUYV;\n> > > > > > >                 cfg.size = Size(600, 800);\n> > > > > > > -               cfg.bufferCount = numBuffers;\n> > > > > > >\n> > > > > > >                 BufferSource source;\n> > > > > > > -               int ret = source.allocate(cfg);\n> > > > > > > +               int ret = source.allocate(cfg, numBuffers);\n> > > > > > >                 if (ret != TestPass)\n> > > > > > >                         return ret;\n> > > > > > >\n> > > > > > > --\n> > > > > > > 2.32.0\n> > > > > > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 0AC36C322E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 29 Jul 2021 16:03:39 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4D74B687C5;\n\tThu, 29 Jul 2021 18:03:38 +0200 (CEST)","from mail-wr1-x429.google.com (mail-wr1-x429.google.com\n\t[IPv6:2a00:1450:4864:20::429])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E95CF687BA\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 29 Jul 2021 18:03:35 +0200 (CEST)","by mail-wr1-x429.google.com with SMTP id p5so7578498wro.7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 29 Jul 2021 09:03:35 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=raspberrypi.com header.i=@raspberrypi.com\n\theader.b=\"W1rBIzRP\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=mime-version:references:in-reply-to:from:date:message-id:subject:to\n\t:cc:content-transfer-encoding;\n\tbh=ms4ffXythg8u9oKk8T7LX36okbYi4MpGYbSp+w6kxmg=;\n\tb=W1rBIzRPW03nV/LhUxrHH0rc0GzdqYVYpRh4l6cXyCodj0a1ZIdvBhGVdTyMMoIJQj\n\trdqseYgb2hDxhJowV76OXAf2L+vJ13L66kmqA4EswLq6OLzRdtx29omZwvWicz4ypn/J\n\tFNb7PHirNp4ZGO76qR+9pfhCvg9nazxtnES1LumJuRIr2VD+ERlJsz75bakMrCPBlICS\n\tsNjfu/miPdbh0LssXy7FO/bFSWVkeq86EDogQszIRs48Eg9gNZZg5OsYRhW/8T4yc4pr\n\tsMrTp1H1CgmdeVASWZksFPglaFH6O/lLKZJFFhfZxZvcNls2Avi19l573+TDsaVcfv4Z\n\t232w==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to:cc:content-transfer-encoding;\n\tbh=ms4ffXythg8u9oKk8T7LX36okbYi4MpGYbSp+w6kxmg=;\n\tb=rdQpf9zkKQS1S3dbllaEp3Q2KQFKyditzvCYW0/vBc0ZuWX28nIwLUoHRCKPZXfU+o\n\twkxs+8H6yW5ceHZ7e96nJUCtu1PS+R7BJHNop9wMNhUIYqVo/ovnagymv7JkgOmNhJcV\n\tz9Kmmtn+ODih0w8etwsTflUa5goZNk7Sy+aBxiw6hhR45IgmIAbqrvY2ZbM7iDn/Z/JU\n\tXRzeCyF6wAR3Bhv/yUEIot/EEN9bxlTeLsRGbMntL0zwpNS2gVZ7gcs2C15SkvsKouRA\n\tP64NGBIq7vOInpr1rZsCxtpn0oI5E5cU3f4M5DlIvjvHQF0pvpQTMI1ycSmWZ4MFbgVU\n\tqgOw==","X-Gm-Message-State":"AOAM531HwhTAblUJ+zJ83xwvpjt+65IoaLbqD+neE9cdf0Gyj6bD8SKz\n\t2aOwiIK/fmWV0PNDs5nh82W4MyAkGK66ZTSYevAtfg==","X-Google-Smtp-Source":"ABdhPJwwFbdLYV1CoCLSmO9xa635W8vETqUyUI4zRyQYMv3d0GmuffN6UjBlCGnx20uzI8B3zALzAqgFh/Bk6uzbXg0=","X-Received":"by 2002:a5d:64ac:: with SMTP id m12mr5552440wrp.89.1627574615090;\n\tThu, 29 Jul 2021 09:03:35 -0700 (PDT)","MIME-Version":"1.0","References":"<20210722232851.747614-1-nfraprado@collabora.com>\n\t<20210722232851.747614-11-nfraprado@collabora.com>\n\t<CAHW6GYJbVdFebNca9ZeM8LY=Ca4P1uaUd3B-r5FF7mJ9k853fg@mail.gmail.com>\n\t<20210723131039.ire2z7u6sdxws3dt@notapiano>\n\t<CAHW6GYKCBXmNSzo+_EcQCvJEaPg-ahMsWXKwVA=J8YzZEtBUWA@mail.gmail.com>\n\t<20210723210807.emekovdwbehrzr44@notapiano>\n\t<CAHW6GYLbPU0TKbMNeNsHdif6Nm+-iUfBgRAcnUN6=ftKYsmYoQ@mail.gmail.com>\n\t<20210729143820.yumwo33jpwaljyb2@notapiano>","In-Reply-To":"<20210729143820.yumwo33jpwaljyb2@notapiano>","From":"David Plowman <david.plowman@raspberrypi.com>","Date":"Thu, 29 Jul 2021 17:03:24 +0100","Message-ID":"<CAHW6GYJCx2kOyikHr7S2St9ud8ssZDb_rNByGSbciR7J1sYSVg@mail.gmail.com>","To":"=?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= <nfraprado@collabora.com>","Content-Type":"text/plain; charset=\"UTF-8\"","Content-Transfer-Encoding":"quoted-printable","Subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>,\n\tkernel@collabora.com, =?utf-8?q?Andr=C3=A9_Almeida?=\n\t<andrealmeid@collabora.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":18444,"web_url":"https://patchwork.libcamera.org/comment/18444/","msgid":"<YQPhujfA1QtrfDHj@pendragon.ideasonboard.com>","date":"2021-07-30T11:25:46","subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hello everybody,\n\nSorry for replying late to this mail thread.\n\nOn Thu, Jul 29, 2021 at 05:03:24PM +0100, David Plowman wrote:\n> Ah, OK, that sounds straightforward, then. Thanks for the explanation!\n\nIt sounds like the issue is solved :-) I would however like to point out\na detail that may affect performance.\n\nWe have a cache in the V4L2VideoDevice that tries to keep the\nassociation between a V4L2 buffer slot and a dma-buf constant. This is\nimportant as if a different dma-buf is passed to a QBUF ioctl call to a\nbuffer slot, V4L2 will unmap the previous dma-buf and map the new one,\nwhich is an expensive operation. This mechanism can only work if you\nallocate at least as many buffers slots as the number of different\ndma-bufs an application may queue. If the application constantly queue\ndifferent buffers there's nothing that can be done about it and new\nmappings will have to be created all the time, but in most cases the\napplication will cycle through the same buffers.\n\nThere is, in this patch series, no mechanism to inform the pipeline\nhandler about the maximum number of different dma-bufs that will be used\nfor a given stream. V4L2 buffer slots are cheap, so one option is to\nsimply over-allocate when calling VIDIOC_REQBUFS. If this causes issues,\nthen we'll have to add a way for applications to specify how many\ndifferent buffers they expect to use.\n\n> On Thu, 29 Jul 2021 at 15:38, Nícolas F. R. A. Prado wrote:\n> > On Thu, Jul 29, 2021 at 11:00:33AM +0100, David Plowman wrote:\n> > > Hi again\n> > >\n> > > I thought that perhaps I could explain in more detail why I think\n> > > applications need to be able to set (or influence) the buffer count\n> > > and not leave it to the pipeline handler. My use-case is as follows.\n> > >\n> > > I'm running some standard sort of application such as video recording\n> > > for which there are maybe 4 buffers allocated. Now, I also want to do\n> > > some image analysis that perhaps causes me to change something about\n> > > the recording (maybe change camera settings, or even stop the\n> > > recording). But this image analysis task is relatively slow.\n> > >\n> > > One option is to copy the camera frames so that I can return the\n> > > buffers in the request back to the camera. But copying images is\n> > > generally undesirable. Instead I'd prefer to hold on to the buffer\n> > > only now my camera pipeline is effectively working with only 3\n> > > buffers, which is not enough. When I eventually finish with the buffer\n> > > I will return it, and then grab the next one to keep again!\n> >\n> > Ohh, I see. Sorry, I got a bit confused there, but this is not a problem at all.\n> > If you want the pipeline to work with extra requests/buffers, you just supply\n> > more to it :). Going back to your code snippet, this would be the change:\n> >\n> >     configuration_ = camera_->generateConfiguration({ StreamRole::StillCapture });\n> > -   configuration_->at(0).bufferCount = <value I have determined>;\n> >     camera_->configure(configuration_.get());\n> >     allocator_ = new FrameBufferAllocator(camera_);\n> >     Stream *stream = configuration_->at(0).stream();\n> > -   allocator_->allocate(stream);\n> > +   allocator_->allocate(stream, <value I have determined>);\n> >     // now allocator_->buffers(stream) has the buffers I want!\n> >\n> > So, basically, you don't need to set bufferCount anymore, and instead you\n> > allocate as many buffers as you need to give the pipeline handler by directly\n> > passing the number to FrameBufferAllocator. In your case you want to allocate an\n> > extra buffer to compensate for the one you'll be keeping.\n> >\n> > It was already possible to supply the pipeline handler with how many\n> > buffers you wanted, but previously you had to allocate them elsewhere, while now\n> > you can allocate with the FrameBufferAllocator since it accepts the count\n> > argument. (Actually for the raspberry pipeline it was already possible to do\n> > this implicitly through bufferCount as you did, but not with the other\n> > pipelines).\n> >\n> > What I meant wasn't possible to change is how many internal buffers for metadata\n> > and parameters the pipeline uses together with the IPA. And also how many V4L2\n> > buffer slots are created to queue the requests into. But all of this is indeed\n> > only relevant to the pipeline handler, so an application shouldn't care about\n> > it. All of this, together with how many buffers the application would allocate,\n> > was previously grouped on bufferCount. With its deletion, however, they are\n> > getting split up.\n> >\n> > I hope I got it right this time :).\n> >\n> > > So at the very least, the application needs to be able to say \"please\n> > > allocate <n> more buffers than you thought you needed\". Does that make\n> > > sense? Will this be possible in the new scheme?\n> > >\n> > > On Fri, 23 Jul 2021 at 22:08, Nícolas F. R. A. Prado wrote:\n> > > > On Fri, Jul 23, 2021 at 04:53:55PM +0100, David Plowman wrote:\n> > > > > Hi Nicolas\n> > > > >\n> > > > > Thanks for the explanations. I'm still not sure I entirely understand\n> > > > > so perhaps a quick look at how I would have to change my application\n> > > > > code might help? Here's what I have now (I've removed any\n> > > > > \"unimportant\" bits!):\n> > > > >\n> > > > > configuration_ = camera_->generateConfiguration({ StreamRole::StillCapture });\n> > > > > configuration_->at(0).bufferCount = <value I have determined>;\n> > > > > camera_->configure(configuration_.get());\n> > > > > allocator_ = new FrameBufferAllocator(camera_);\n> > > > > Stream *stream = configuration_->at(0).stream();\n> > > > > allocator_->allocate(stream);\n> > > > > // now allocator_->buffers(stream) has the buffers I want!\n> > > > >\n> > > > > I guess one thing to note is that the bufferCount value varies with\n> > > > > more than just the StreamRole, and I don't in general trust the\n> > > > > pipeline handler to \"know\" what I want. Will this still be possible?\n> > > >\n> > > > Oh I see... No, this won't be possible after we drop bufferCount. The\n> > > > pipeline handler will decide for itself how many buffers to allocate internally,\n> > > > possibly using the StreamRole as a hint.\n> > > >\n> > > > I wasn't aware this could impact an application, since all the other pipeline\n> > > > handlers actually ignore when bufferCount is set by the application, overriding\n> > > > it when the configuration is validated. But now I'm noticing the raspberrypi\n> > > > pipeline actually uses it.\n> > > >\n> > > > Some context: This series actually began with me making\n> > > > FrameBufferAllocator::allocate() receive a count argument instead of using the\n> > > > value of bufferCount. But since Laurent mentioned that bufferCount was going\n> > > > away eventually anyway I ended up removing it as well as part of this series.\n> > > >\n> > > > I do understand how being able to specify a bufferCount value that suits your\n> > > > specific usecase is useful, though... Laurent, what's your take on this? :)\n> > > >\n> > > > > On Fri, 23 Jul 2021 at 14:10, Nícolas F. R. A. Prado wrote:\n> > > > > >\n> > > > > > Hi David,\n> > > > > >\n> > > > > > On Fri, Jul 23, 2021 at 09:42:56AM +0100, David Plowman wrote:\n> > > > > > > Hi Nicolas\n> > > > > > >\n> > > > > > > Thanks very much for all this work! I was wondering if I could ask a\n> > > > > > > little more about this patch. In our applications, for example, we set\n> > > > > > > the bufferCount according to the use-case that the application is\n> > > > > > > implementing. For example:\n> > > > > > >\n> > > > > > > * For preview windows we set bufferCount to 4.\n> > > > > > > * For video capture we drop fewer frames with a deeper queue so we set it to 6.\n> > > > > > > * For stills capture we can get by with one frame, though use cases\n> > > > > > > that capture several stills images for fusion work better if we set\n> > > > > > > bufferCount to 2 or 3.\n> > > > > > >\n> > > > > > > I was wondering how our applications can achieve this behaviour if the\n> > > > > > > bufferCount field is no longer available.\n> > > > > >\n> > > > > > Okay, so the short answer is that the applications, knowing their particular use\n> > > > > > case, are responsible to provide enough requests to keep the pipeline going. On\n> > > > > > the pipeline handler side, it's free to use how many internal buffers it wants.\n> > > > > >\n> > > > > > So in your case, the pipeline handler could still allocate that same number of\n> > > > > > internal buffers as you previously did based on bufferCount, but now based\n> > > > > > solely on the StreamRole set. The application would then allocate and queue\n> > > > > > how many buffers fits the usage. (Note that before the application would call\n> > > > > > FrameBufferAllocator::allocate() and it would allocate 'bufferCount' buffers,\n> > > > > > but now the function takes a count argument so the application is free to choose\n> > > > > > how many)\n> > > > > >\n> > > > > > Now, I guess it would be nice for the application to be able to query what is a\n> > > > > > good number of buffers to use, for example 6 in the video capture of your use\n> > > > > > case. At the moment, the only information available is that 1 is the minimum\n> > > > > > number of buffers required. So the application would have to know that 6 is a\n> > > > > > good number for video capture. Maybe another property could be introduced later\n> > > > > > for this recommended amount, but previous discussions suggested this is very use\n> > > > > > case dependent, so might not make sense.\n> > > > > >\n> > > > > > I hope this answers the question. If not, I'm still here :).\n> > > > > >\n> > > > > > Thanks,\n> > > > > > Nícolas\n> > > > > >\n> > > > > > >\n> > > > > > > Thanks!\n> > > > > > > David\n> > > > > > >\n> > > > > > > On Fri, 23 Jul 2021 at 00:29, Nícolas F. R. A. Prado\n> > > > > > > <nfraprado@collabora.com> wrote:\n> > > > > > > >\n> > > > > > > > Now that the number of buffers allocated by the FrameBufferAllocator\n> > > > > > > > helper is passed through FrameBufferAllocator::allocate() and the\n> > > > > > > > pipelines no longer use bufferCount for internal buffer or V4L2 buffer\n> > > > > > > > slots allocation, we no longer need to have bufferCount in the\n> > > > > > > > StreamConfiguration, so remove it.\n> > > > > > > >\n> > > > > > > > Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>\n> > > > > > > > ---\n> > > > > > > >\n> > > > > > > > No changes in v7\n> > > > > > > >\n> > > > > > > > Changes in v6:\n> > > > > > > > - Removed IPU3_BUFFER_COUNT as it was unused\n> > > > > > > >\n> > > > > > > >  include/libcamera/stream.h                         |  2 --\n> > > > > > > >  src/android/camera_stream.cpp                      |  2 +-\n> > > > > > > >  src/libcamera/pipeline/ipu3/cio2.cpp               |  1 -\n> > > > > > > >  src/libcamera/pipeline/ipu3/ipu3.cpp               |  8 --------\n> > > > > > > >  src/libcamera/pipeline/raspberrypi/raspberrypi.cpp |  6 ------\n> > > > > > > >  src/libcamera/pipeline/rkisp1/rkisp1_path.cpp      |  2 --\n> > > > > > > >  src/libcamera/pipeline/simple/converter.cpp        |  3 ---\n> > > > > > > >  src/libcamera/pipeline/simple/converter.h          |  3 ---\n> > > > > > > >  src/libcamera/pipeline/simple/simple.cpp           |  5 +----\n> > > > > > > >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp       |  3 ---\n> > > > > > > >  src/libcamera/pipeline/vimc/vimc.cpp               |  3 ---\n> > > > > > > >  src/libcamera/stream.cpp                           |  9 ++-------\n> > > > > > > >  src/v4l2/v4l2_camera.cpp                           | 14 ++++++++++----\n> > > > > > > >  src/v4l2/v4l2_camera.h                             |  5 +++--\n> > > > > > > >  src/v4l2/v4l2_camera_proxy.cpp                     |  8 +++-----\n> > > > > > > >  test/camera/buffer_import.cpp                      | 10 +++++++---\n> > > > > > > >  test/libtest/buffer_source.cpp                     |  4 ++--\n> > > > > > > >  test/libtest/buffer_source.h                       |  2 +-\n> > > > > > > >  test/v4l2_videodevice/buffer_cache.cpp             |  4 ++--\n> > > > > > > >  19 files changed, 32 insertions(+), 62 deletions(-)\n> > > > > > > >\n> > > > > > > > diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\n> > > > > > > > index 0c55e7164592..b25f0059f2f1 100644\n> > > > > > > > --- a/include/libcamera/stream.h\n> > > > > > > > +++ b/include/libcamera/stream.h\n> > > > > > > > @@ -45,8 +45,6 @@ struct StreamConfiguration {\n> > > > > > > >         unsigned int stride;\n> > > > > > > >         unsigned int frameSize;\n> > > > > > > >\n> > > > > > > > -       unsigned int bufferCount;\n> > > > > > > > -\n> > > > > > > >         Stream *stream() const { return stream_; }\n> > > > > > > >         void setStream(Stream *stream) { stream_ = stream; }\n> > > > > > > >         const StreamFormats &formats() const { return formats_; }\n> > > > > > > > diff --git a/src/android/camera_stream.cpp b/src/android/camera_stream.cpp\n> > > > > > > > index b168e3c0c288..0794be409f82 100644\n> > > > > > > > --- a/src/android/camera_stream.cpp\n> > > > > > > > +++ b/src/android/camera_stream.cpp\n> > > > > > > > @@ -94,7 +94,7 @@ int CameraStream::configure()\n> > > > > > > >                         buffers_.push_back(frameBuffer.get());\n> > > > > > > >         }\n> > > > > > > >\n> > > > > > > > -       camera3Stream_->max_buffers = configuration().bufferCount;\n> > > > > > > > +       camera3Stream_->max_buffers = bufferCount;\n> > > > > > > >\n> > > > > > > >         return 0;\n> > > > > > > >  }\n> > > > > > > > diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > > > > > > index 1bcd580e251c..0e04e7214489 100644\n> > > > > > > > --- a/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > > > > > > +++ b/src/libcamera/pipeline/ipu3/cio2.cpp\n> > > > > > > > @@ -214,7 +214,6 @@ StreamConfiguration CIO2Device::generateConfiguration(Size size) const\n> > > > > > > >\n> > > > > > > >         cfg.size = sensorFormat.size;\n> > > > > > > >         cfg.pixelFormat = mbusCodesToPixelFormat.at(sensorFormat.mbus_code);\n> > > > > > > > -       cfg.bufferCount = CIO2_BUFFER_COUNT;\n> > > > > > > >\n> > > > > > > >         return cfg;\n> > > > > > > >  }\n> > > > > > > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > > > > > index 4efd201c05e5..b223b3f33cd0 100644\n> > > > > > > > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > > > > > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > > > > > > @@ -38,7 +38,6 @@ namespace libcamera {\n> > > > > > > >\n> > > > > > > >  LOG_DEFINE_CATEGORY(IPU3)\n> > > > > > > >\n> > > > > > > > -static constexpr unsigned int IPU3_BUFFER_COUNT = 4;\n> > > > > > > >  static constexpr unsigned int IPU3_MAX_STREAMS = 3;\n> > > > > > > >  static const Size IMGU_OUTPUT_MIN_SIZE = { 2, 2 };\n> > > > > > > >  static const Size IMGU_OUTPUT_MAX_SIZE = { 4480, 34004 };\n> > > > > > > > @@ -295,7 +294,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n> > > > > > > >                         /* Initialize the RAW stream with the CIO2 configuration. */\n> > > > > > > >                         cfg->size = cio2Configuration_.size;\n> > > > > > > >                         cfg->pixelFormat = cio2Configuration_.pixelFormat;\n> > > > > > > > -                       cfg->bufferCount = cio2Configuration_.bufferCount;\n> > > > > > > >                         cfg->stride = info.stride(cfg->size.width, 0, 64);\n> > > > > > > >                         cfg->frameSize = info.frameSize(cfg->size, 64);\n> > > > > > > >                         cfg->setStream(const_cast<Stream *>(&data_->rawStream_));\n> > > > > > > > @@ -339,7 +337,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n> > > > > > > >                                               IMGU_OUTPUT_HEIGHT_ALIGN);\n> > > > > > > >\n> > > > > > > >                         cfg->pixelFormat = formats::NV12;\n> > > > > > > > -                       cfg->bufferCount = IPU3_BUFFER_COUNT;\n> > > > > > > >                         cfg->stride = info.stride(cfg->size.width, 0, 1);\n> > > > > > > >                         cfg->frameSize = info.frameSize(cfg->size, 1);\n> > > > > > > >\n> > > > > > > > @@ -407,7 +404,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > > > > >         Size sensorResolution = data->cio2_.sensor()->resolution();\n> > > > > > > >         for (const StreamRole role : roles) {\n> > > > > > > >                 std::map<PixelFormat, std::vector<SizeRange>> streamFormats;\n> > > > > > > > -               unsigned int bufferCount;\n> > > > > > > >                 PixelFormat pixelFormat;\n> > > > > > > >                 Size size;\n> > > > > > > >\n> > > > > > > > @@ -428,7 +424,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > > > > >                         size.height = utils::alignDown(size.height - 1,\n> > > > > > > >                                                        IMGU_OUTPUT_HEIGHT_MARGIN);\n> > > > > > > >                         pixelFormat = formats::NV12;\n> > > > > > > > -                       bufferCount = IPU3_BUFFER_COUNT;\n> > > > > > > >                         streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n> > > > > > > >\n> > > > > > > >                         break;\n> > > > > > > > @@ -438,7 +433,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > > > > >                                 data->cio2_.generateConfiguration(sensorResolution);\n> > > > > > > >                         pixelFormat = cio2Config.pixelFormat;\n> > > > > > > >                         size = cio2Config.size;\n> > > > > > > > -                       bufferCount = cio2Config.bufferCount;\n> > > > > > > >\n> > > > > > > >                         for (const PixelFormat &format : data->cio2_.formats())\n> > > > > > > >                                 streamFormats[format] = data->cio2_.sizes();\n> > > > > > > > @@ -457,7 +451,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > > > > >                                                .alignedDownTo(IMGU_OUTPUT_WIDTH_ALIGN,\n> > > > > > > >                                                               IMGU_OUTPUT_HEIGHT_ALIGN);\n> > > > > > > >                         pixelFormat = formats::NV12;\n> > > > > > > > -                       bufferCount = IPU3_BUFFER_COUNT;\n> > > > > > > >                         streamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n> > > > > > > >\n> > > > > > > >                         break;\n> > > > > > > > @@ -474,7 +467,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n> > > > > > > >                 StreamConfiguration cfg(formats);\n> > > > > > > >                 cfg.size = size;\n> > > > > > > >                 cfg.pixelFormat = pixelFormat;\n> > > > > > > > -               cfg.bufferCount = bufferCount;\n> > > > > > > >                 config->addConfiguration(cfg);\n> > > > > > > >         }\n> > > > > > > >\n> > > > > > > > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > > > > > > index 776e0f92aed1..e6fc0425c3ef 100644\n> > > > > > > > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > > > > > > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > > > > > > > @@ -473,7 +473,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > > > >         RPiCameraData *data = cameraData(camera);\n> > > > > > > >         CameraConfiguration *config = new RPiCameraConfiguration(data);\n> > > > > > > >         V4L2DeviceFormat sensorFormat;\n> > > > > > > > -       unsigned int bufferCount;\n> > > > > > > >         PixelFormat pixelFormat;\n> > > > > > > >         V4L2VideoDevice::Formats fmts;\n> > > > > > > >         Size size;\n> > > > > > > > @@ -491,7 +490,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > > > >                         sensorFormat = findBestMode(fmts, size);\n> > > > > > > >                         pixelFormat = sensorFormat.fourcc.toPixelFormat();\n> > > > > > > >                         ASSERT(pixelFormat.isValid());\n> > > > > > > > -                       bufferCount = 2;\n> > > > > > > >                         rawCount++;\n> > > > > > > >                         break;\n> > > > > > > >\n> > > > > > > > @@ -500,7 +498,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > > > >                         pixelFormat = formats::NV12;\n> > > > > > > >                         /* Return the largest sensor resolution. */\n> > > > > > > >                         size = data->sensor_->resolution();\n> > > > > > > > -                       bufferCount = 1;\n> > > > > > > >                         outCount++;\n> > > > > > > >                         break;\n> > > > > > > >\n> > > > > > > > @@ -516,7 +513,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > > > >                         fmts = data->isp_[Isp::Output0].dev()->formats();\n> > > > > > > >                         pixelFormat = formats::YUV420;\n> > > > > > > >                         size = { 1920, 1080 };\n> > > > > > > > -                       bufferCount = 4;\n> > > > > > > >                         outCount++;\n> > > > > > > >                         break;\n> > > > > > > >\n> > > > > > > > @@ -524,7 +520,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > > > >                         fmts = data->isp_[Isp::Output0].dev()->formats();\n> > > > > > > >                         pixelFormat = formats::ARGB8888;\n> > > > > > > >                         size = { 800, 600 };\n> > > > > > > > -                       bufferCount = 4;\n> > > > > > > >                         outCount++;\n> > > > > > > >                         break;\n> > > > > > > >\n> > > > > > > > @@ -554,7 +549,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n> > > > > > > >                 StreamConfiguration cfg(formats);\n> > > > > > > >                 cfg.size = size;\n> > > > > > > >                 cfg.pixelFormat = pixelFormat;\n> > > > > > > > -               cfg.bufferCount = bufferCount;\n> > > > > > > >                 config->addConfiguration(cfg);\n> > > > > > > >         }\n> > > > > > > >\n> > > > > > > > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > > > > > > index fea330f72886..4961f3971e59 100644\n> > > > > > > > --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > > > > > > +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> > > > > > > > @@ -61,7 +61,6 @@ StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution)\n> > > > > > > >         StreamConfiguration cfg(formats);\n> > > > > > > >         cfg.pixelFormat = formats::NV12;\n> > > > > > > >         cfg.size = maxResolution;\n> > > > > > > > -       cfg.bufferCount = RKISP1_BUFFER_COUNT;\n> > > > > > > >\n> > > > > > > >         return cfg;\n> > > > > > > >  }\n> > > > > > > > @@ -77,7 +76,6 @@ CameraConfiguration::Status RkISP1Path::validate(StreamConfiguration *cfg)\n> > > > > > > >\n> > > > > > > >         cfg->size.boundTo(maxResolution_);\n> > > > > > > >         cfg->size.expandTo(minResolution_);\n> > > > > > > > -       cfg->bufferCount = RKISP1_BUFFER_COUNT;\n> > > > > > > >\n> > > > > > > >         V4L2DeviceFormat format;\n> > > > > > > >         format.fourcc = video_->toV4L2PixelFormat(cfg->pixelFormat);\n> > > > > > > > diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp\n> > > > > > > > index b3bcf01483f7..fda417793e80 100644\n> > > > > > > > --- a/src/libcamera/pipeline/simple/converter.cpp\n> > > > > > > > +++ b/src/libcamera/pipeline/simple/converter.cpp\n> > > > > > > > @@ -89,9 +89,6 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg,\n> > > > > > > >                 return -EINVAL;\n> > > > > > > >         }\n> > > > > > > >\n> > > > > > > > -       inputBufferCount_ = inputCfg.bufferCount;\n> > > > > > > > -       outputBufferCount_ = outputCfg.bufferCount;\n> > > > > > > > -\n> > > > > > > >         return 0;\n> > > > > > > >  }\n> > > > > > > >\n> > > > > > > > diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h\n> > > > > > > > index 7e1d60674f62..406e63ca2a80 100644\n> > > > > > > > --- a/src/libcamera/pipeline/simple/converter.h\n> > > > > > > > +++ b/src/libcamera/pipeline/simple/converter.h\n> > > > > > > > @@ -87,9 +87,6 @@ private:\n> > > > > > > >                 SimpleConverter *converter_;\n> > > > > > > >                 unsigned int index_;\n> > > > > > > >                 std::unique_ptr<V4L2M2MDevice> m2m_;\n> > > > > > > > -\n> > > > > > > > -               unsigned int inputBufferCount_;\n> > > > > > > > -               unsigned int outputBufferCount_;\n> > > > > > > >         };\n> > > > > > > >\n> > > > > > > >         std::string deviceNode_;\n> > > > > > > > diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\n> > > > > > > > index a1163eaf8be2..ded04914f610 100644\n> > > > > > > > --- a/src/libcamera/pipeline/simple/simple.cpp\n> > > > > > > > +++ b/src/libcamera/pipeline/simple/simple.cpp\n> > > > > > > > @@ -628,7 +628,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n> > > > > > > >                     cfg.size != pipeConfig_->captureSize)\n> > > > > > > >                         needConversion_ = true;\n> > > > > > > >\n> > > > > > > > -               /* Set the stride, frameSize and bufferCount. */\n> > > > > > > > +               /* Set the stride and frameSize. */\n> > > > > > > >                 if (needConversion_) {\n> > > > > > > >                         std::tie(cfg.stride, cfg.frameSize) =\n> > > > > > > >                                 converter->strideAndFrameSize(cfg.pixelFormat, cfg.size);\n> > > > > > > > @@ -646,8 +646,6 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n> > > > > > > >                         cfg.stride = format.planes[0].bpl;\n> > > > > > > >                         cfg.frameSize = format.planes[0].size;\n> > > > > > > >                 }\n> > > > > > > > -\n> > > > > > > > -               cfg.bufferCount = 3;\n> > > > > > > >         }\n> > > > > > > >\n> > > > > > > >         return status;\n> > > > > > > > @@ -770,7 +768,6 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)\n> > > > > > > >         inputCfg.pixelFormat = pipeConfig->captureFormat;\n> > > > > > > >         inputCfg.size = pipeConfig->captureSize;\n> > > > > > > >         inputCfg.stride = captureFormat.planes[0].bpl;\n> > > > > > > > -       inputCfg.bufferCount = kNumInternalBuffers;\n> > > > > > > >\n> > > > > > > >         return converter_->configure(inputCfg, outputCfgs);\n> > > > > > > >  }\n> > > > > > > > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > > > > > > index 755949e7a59a..32482300f09a 100644\n> > > > > > > > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > > > > > > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> > > > > > > > @@ -150,8 +150,6 @@ CameraConfiguration::Status UVCCameraConfiguration::validate()\n> > > > > > > >                 status = Adjusted;\n> > > > > > > >         }\n> > > > > > > >\n> > > > > > > > -       cfg.bufferCount = 4;\n> > > > > > > > -\n> > > > > > > >         V4L2DeviceFormat format;\n> > > > > > > >         format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n> > > > > > > >         format.size = cfg.size;\n> > > > > > > > @@ -193,7 +191,6 @@ CameraConfiguration *PipelineHandlerUVC::generateConfiguration(Camera *camera,\n> > > > > > > >\n> > > > > > > >         cfg.pixelFormat = formats.pixelformats().front();\n> > > > > > > >         cfg.size = formats.sizes(cfg.pixelFormat).back();\n> > > > > > > > -       cfg.bufferCount = 4;\n> > > > > > > >\n> > > > > > > >         config->addConfiguration(cfg);\n> > > > > > > >\n> > > > > > > > diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp\n> > > > > > > > index 24ba743a946c..a698427c4361 100644\n> > > > > > > > --- a/src/libcamera/pipeline/vimc/vimc.cpp\n> > > > > > > > +++ b/src/libcamera/pipeline/vimc/vimc.cpp\n> > > > > > > > @@ -167,8 +167,6 @@ CameraConfiguration::Status VimcCameraConfiguration::validate()\n> > > > > > > >                 status = Adjusted;\n> > > > > > > >         }\n> > > > > > > >\n> > > > > > > > -       cfg.bufferCount = 4;\n> > > > > > > > -\n> > > > > > > >         V4L2DeviceFormat format;\n> > > > > > > >         format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n> > > > > > > >         format.size = cfg.size;\n> > > > > > > > @@ -224,7 +222,6 @@ CameraConfiguration *PipelineHandlerVimc::generateConfiguration(Camera *camera,\n> > > > > > > >\n> > > > > > > >         cfg.pixelFormat = formats::BGR888;\n> > > > > > > >         cfg.size = { 1920, 1080 };\n> > > > > > > > -       cfg.bufferCount = 4;\n> > > > > > > >\n> > > > > > > >         config->addConfiguration(cfg);\n> > > > > > > >\n> > > > > > > > diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp\n> > > > > > > > index b8626775d224..ca507b72b26a 100644\n> > > > > > > > --- a/src/libcamera/stream.cpp\n> > > > > > > > +++ b/src/libcamera/stream.cpp\n> > > > > > > > @@ -280,7 +280,7 @@ SizeRange StreamFormats::range(const PixelFormat &pixelformat) const\n> > > > > > > >   * handlers provide StreamFormats.\n> > > > > > > >   */\n> > > > > > > >  StreamConfiguration::StreamConfiguration()\n> > > > > > > > -       : pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> > > > > > > > +       : pixelFormat(0), stride(0), frameSize(0),\n> > > > > > > >           stream_(nullptr)\n> > > > > > > >  {\n> > > > > > > >  }\n> > > > > > > > @@ -289,7 +289,7 @@ StreamConfiguration::StreamConfiguration()\n> > > > > > > >   * \\brief Construct a configuration with stream formats\n> > > > > > > >   */\n> > > > > > > >  StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n> > > > > > > > -       : pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> > > > > > > > +       : pixelFormat(0), stride(0), frameSize(0),\n> > > > > > > >           stream_(nullptr), formats_(formats)\n> > > > > > > >  {\n> > > > > > > >  }\n> > > > > > > > @@ -324,11 +324,6 @@ StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n> > > > > > > >   * validating the configuration with a call to CameraConfiguration::validate().\n> > > > > > > >   */\n> > > > > > > >\n> > > > > > > > -/**\n> > > > > > > > - * \\var StreamConfiguration::bufferCount\n> > > > > > > > - * \\brief Requested number of buffers to allocate for the stream\n> > > > > > > > - */\n> > > > > > > > -\n> > > > > > > >  /**\n> > > > > > > >   * \\fn StreamConfiguration::stream()\n> > > > > > > >   * \\brief Retrieve the stream associated with the configuration\n> > > > > > > > diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp\n> > > > > > > > index d01eacfa2b84..2ff9affc6388 100644\n> > > > > > > > --- a/src/v4l2/v4l2_camera.cpp\n> > > > > > > > +++ b/src/v4l2/v4l2_camera.cpp\n> > > > > > > > @@ -12,6 +12,8 @@\n> > > > > > > >\n> > > > > > > >  #include <libcamera/base/log.h>\n> > > > > > > >\n> > > > > > > > +#include <libcamera/property_ids.h>\n> > > > > > > > +\n> > > > > > > >  using namespace libcamera;\n> > > > > > > >\n> > > > > > > >  LOG_DECLARE_CATEGORY(V4L2Compat)\n> > > > > > > > @@ -107,14 +109,12 @@ void V4L2Camera::requestComplete(Request *request)\n> > > > > > > >  }\n> > > > > > > >\n> > > > > > > >  int V4L2Camera::configure(StreamConfiguration *streamConfigOut,\n> > > > > > > > -                         const Size &size, const PixelFormat &pixelformat,\n> > > > > > > > -                         unsigned int bufferCount)\n> > > > > > > > +                         const Size &size, const PixelFormat &pixelformat)\n> > > > > > > >  {\n> > > > > > > >         StreamConfiguration &streamConfig = config_->at(0);\n> > > > > > > >         streamConfig.size.width = size.width;\n> > > > > > > >         streamConfig.size.height = size.height;\n> > > > > > > >         streamConfig.pixelFormat = pixelformat;\n> > > > > > > > -       streamConfig.bufferCount = bufferCount;\n> > > > > > > >         /* \\todo memoryType (interval vs external) */\n> > > > > > > >\n> > > > > > > >         CameraConfiguration::Status validation = config_->validate();\n> > > > > > > > @@ -146,7 +146,6 @@ int V4L2Camera::validateConfiguration(const PixelFormat &pixelFormat,\n> > > > > > > >         StreamConfiguration &cfg = config->at(0);\n> > > > > > > >         cfg.size = size;\n> > > > > > > >         cfg.pixelFormat = pixelFormat;\n> > > > > > > > -       cfg.bufferCount = 1;\n> > > > > > > >\n> > > > > > > >         CameraConfiguration::Status validation = config->validate();\n> > > > > > > >         if (validation == CameraConfiguration::Invalid)\n> > > > > > > > @@ -299,3 +298,10 @@ bool V4L2Camera::isRunning()\n> > > > > > > >  {\n> > > > > > > >         return isRunning_;\n> > > > > > > >  }\n> > > > > > > > +\n> > > > > > > > +unsigned int V4L2Camera::minimumRequests(unsigned int count)\n> > > > > > > > +{\n> > > > > > > > +       unsigned int min = camera_->properties().get(properties::MinimumRequests);\n> > > > > > > > +\n> > > > > > > > +       return std::max(count, min);\n> > > > > > > > +}\n> > > > > > > > diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h\n> > > > > > > > index a095f4e27524..4b5618ac12b5 100644\n> > > > > > > > --- a/src/v4l2/v4l2_camera.h\n> > > > > > > > +++ b/src/v4l2/v4l2_camera.h\n> > > > > > > > @@ -45,8 +45,7 @@ public:\n> > > > > > > >         std::vector<Buffer> completedBuffers();\n> > > > > > > >\n> > > > > > > >         int configure(StreamConfiguration *streamConfigOut,\n> > > > > > > > -                     const Size &size, const PixelFormat &pixelformat,\n> > > > > > > > -                     unsigned int bufferCount);\n> > > > > > > > +                     const Size &size, const PixelFormat &pixelformat);\n> > > > > > > >         int validateConfiguration(const PixelFormat &pixelformat,\n> > > > > > > >                                   const Size &size,\n> > > > > > > >                                   StreamConfiguration *streamConfigOut);\n> > > > > > > > @@ -65,6 +64,8 @@ public:\n> > > > > > > >\n> > > > > > > >         bool isRunning();\n> > > > > > > >\n> > > > > > > > +       unsigned int minimumRequests(unsigned int count);\n> > > > > > > > +\n> > > > > > > >  private:\n> > > > > > > >         void requestComplete(Request *request);\n> > > > > > > >\n> > > > > > > > diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp\n> > > > > > > > index 7682c4bddf90..634ec84e0cbb 100644\n> > > > > > > > --- a/src/v4l2/v4l2_camera_proxy.cpp\n> > > > > > > > +++ b/src/v4l2/v4l2_camera_proxy.cpp\n> > > > > > > > @@ -349,8 +349,7 @@ int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg)\n> > > > > > > >         Size size(arg->fmt.pix.width, arg->fmt.pix.height);\n> > > > > > > >         V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->fmt.pix.pixelformat);\n> > > > > > > >         ret = vcam_->configure(&streamConfig_, size,\n> > > > > > > > -                              PixelFormatInfo::info(v4l2Format).format,\n> > > > > > > > -                              bufferCount_);\n> > > > > > > > +                              PixelFormatInfo::info(v4l2Format).format);\n> > > > > > > >         if (ret < 0)\n> > > > > > > >                 return -EINVAL;\n> > > > > > > >\n> > > > > > > > @@ -491,14 +490,13 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf\n> > > > > > > >         Size size(v4l2PixFormat_.width, v4l2PixFormat_.height);\n> > > > > > > >         V4L2PixelFormat v4l2Format = V4L2PixelFormat(v4l2PixFormat_.pixelformat);\n> > > > > > > >         int ret = vcam_->configure(&streamConfig_, size,\n> > > > > > > > -                                  PixelFormatInfo::info(v4l2Format).format,\n> > > > > > > > -                                  arg->count);\n> > > > > > > > +                                  PixelFormatInfo::info(v4l2Format).format);\n> > > > > > > >         if (ret < 0)\n> > > > > > > >                 return -EINVAL;\n> > > > > > > >\n> > > > > > > >         setFmtFromConfig(streamConfig_);\n> > > > > > > >\n> > > > > > > > -       arg->count = streamConfig_.bufferCount;\n> > > > > > > > +       arg->count = vcam_->minimumRequests(arg->count);\n> > > > > > > >         bufferCount_ = arg->count;\n> > > > > > > >\n> > > > > > > >         ret = vcam_->allocBuffers(arg->count);\n> > > > > > > > diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp\n> > > > > > > > index c504ea09e64b..67ac0ad20e15 100644\n> > > > > > > > --- a/test/camera/buffer_import.cpp\n> > > > > > > > +++ b/test/camera/buffer_import.cpp\n> > > > > > > > @@ -16,6 +16,8 @@\n> > > > > > > >  #include <libcamera/base/thread.h>\n> > > > > > > >  #include <libcamera/base/timer.h>\n> > > > > > > >\n> > > > > > > > +#include <libcamera/property_ids.h>\n> > > > > > > > +\n> > > > > > > >  #include \"libcamera/internal/device_enumerator.h\"\n> > > > > > > >  #include \"libcamera/internal/media_device.h\"\n> > > > > > > >  #include \"libcamera/internal/v4l2_videodevice.h\"\n> > > > > > > > @@ -92,10 +94,12 @@ protected:\n> > > > > > > >                         return TestFail;\n> > > > > > > >                 }\n> > > > > > > >\n> > > > > > > > +               unsigned int bufferCount = camera_->properties().get(properties::MinimumRequests);\n> > > > > > > > +\n> > > > > > > >                 Stream *stream = cfg.stream();\n> > > > > > > >\n> > > > > > > >                 BufferSource source;\n> > > > > > > > -               int ret = source.allocate(cfg);\n> > > > > > > > +               int ret = source.allocate(cfg, bufferCount);\n> > > > > > > >                 if (ret != TestPass)\n> > > > > > > >                         return ret;\n> > > > > > > >\n> > > > > > > > @@ -139,10 +143,10 @@ protected:\n> > > > > > > >                 while (timer.isRunning())\n> > > > > > > >                         dispatcher->processEvents();\n> > > > > > > >\n> > > > > > > > -               if (completeRequestsCount_ < cfg.bufferCount * 2) {\n> > > > > > > > +               if (completeRequestsCount_ < bufferCount * 2) {\n> > > > > > > >                         std::cout << \"Failed to capture enough frames (got \"\n> > > > > > > >                                   << completeRequestsCount_ << \" expected at least \"\n> > > > > > > > -                                 << cfg.bufferCount * 2 << \")\" << std::endl;\n> > > > > > > > +                                 << bufferCount * 2 << \")\" << std::endl;\n> > > > > > > >                         return TestFail;\n> > > > > > > >                 }\n> > > > > > > >\n> > > > > > > > diff --git a/test/libtest/buffer_source.cpp b/test/libtest/buffer_source.cpp\n> > > > > > > > index 73563f2fc39d..c3d5286a2462 100644\n> > > > > > > > --- a/test/libtest/buffer_source.cpp\n> > > > > > > > +++ b/test/libtest/buffer_source.cpp\n> > > > > > > > @@ -24,7 +24,7 @@ BufferSource::~BufferSource()\n> > > > > > > >                 media_->release();\n> > > > > > > >  }\n> > > > > > > >\n> > > > > > > > -int BufferSource::allocate(const StreamConfiguration &config)\n> > > > > > > > +int BufferSource::allocate(const StreamConfiguration &config, unsigned int count)\n> > > > > > > >  {\n> > > > > > > >         /* Locate and open the video device. */\n> > > > > > > >         std::string videoDeviceName = \"vivid-000-vid-out\";\n> > > > > > > > @@ -77,7 +77,7 @@ int BufferSource::allocate(const StreamConfiguration &config)\n> > > > > > > >                 return TestFail;\n> > > > > > > >         }\n> > > > > > > >\n> > > > > > > > -       if (video->allocateBuffers(config.bufferCount, &buffers_) < 0) {\n> > > > > > > > +       if (video->allocateBuffers(count, &buffers_) < 0) {\n> > > > > > > >                 std::cout << \"Failed to allocate buffers\" << std::endl;\n> > > > > > > >                 return TestFail;\n> > > > > > > >         }\n> > > > > > > > diff --git a/test/libtest/buffer_source.h b/test/libtest/buffer_source.h\n> > > > > > > > index 14b4770e8d8a..6a18e269a575 100644\n> > > > > > > > --- a/test/libtest/buffer_source.h\n> > > > > > > > +++ b/test/libtest/buffer_source.h\n> > > > > > > > @@ -20,7 +20,7 @@ public:\n> > > > > > > >         BufferSource();\n> > > > > > > >         ~BufferSource();\n> > > > > > > >\n> > > > > > > > -       int allocate(const StreamConfiguration &config);\n> > > > > > > > +       int allocate(const StreamConfiguration &config, unsigned int count);\n> > > > > > > >         const std::vector<std::unique_ptr<FrameBuffer>> &buffers();\n> > > > > > > >\n> > > > > > > >  private:\n> > > > > > > > diff --git a/test/v4l2_videodevice/buffer_cache.cpp b/test/v4l2_videodevice/buffer_cache.cpp\n> > > > > > > > index b3f2bec11783..07fddfd2617c 100644\n> > > > > > > > --- a/test/v4l2_videodevice/buffer_cache.cpp\n> > > > > > > > +++ b/test/v4l2_videodevice/buffer_cache.cpp\n> > > > > > > > @@ -10,6 +10,7 @@\n> > > > > > > >  #include <vector>\n> > > > > > > >\n> > > > > > > >  #include <libcamera/formats.h>\n> > > > > > > > +#include <libcamera/property_ids.h>\n> > > > > > > >  #include <libcamera/stream.h>\n> > > > > > > >\n> > > > > > > >  #include \"buffer_source.h\"\n> > > > > > > > @@ -145,10 +146,9 @@ public:\n> > > > > > > >                 StreamConfiguration cfg;\n> > > > > > > >                 cfg.pixelFormat = formats::YUYV;\n> > > > > > > >                 cfg.size = Size(600, 800);\n> > > > > > > > -               cfg.bufferCount = numBuffers;\n> > > > > > > >\n> > > > > > > >                 BufferSource source;\n> > > > > > > > -               int ret = source.allocate(cfg);\n> > > > > > > > +               int ret = source.allocate(cfg, numBuffers);\n> > > > > > > >                 if (ret != TestPass)\n> > > > > > > >                         return ret;\n> > > > > > > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id D77E3C322E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 30 Jul 2021 11:25:57 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3ECEE687C7;\n\tFri, 30 Jul 2021 13:25:57 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id B3062687BF\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 30 Jul 2021 13:25:55 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 251DBE81;\n\tFri, 30 Jul 2021 13:25:55 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"gDP8G+a5\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1627644355;\n\tbh=1f++Tis7PIShOZZsobv+Uh8PqoWqi9wTJcewAl2LU/0=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=gDP8G+a5fUOz3Dnuj68UDilw000O3fzRYIne3mQRrBIx9VNbOEbN9hFbpPzhu3uM3\n\tywv6UNzUjFC4BgaZICrAyt9qtpZ4Rtrg5rNZA2i9WPkIET8HRGERcZl/KHl+QzMyK3\n\tYQZtUpEBpDr8I+BztCUUpCVLdWMEmA41JadC6qGo=","Date":"Fri, 30 Jul 2021 14:25:46 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"David Plowman <david.plowman@raspberrypi.com>","Message-ID":"<YQPhujfA1QtrfDHj@pendragon.ideasonboard.com>","References":"<20210722232851.747614-1-nfraprado@collabora.com>\n\t<20210722232851.747614-11-nfraprado@collabora.com>\n\t<CAHW6GYJbVdFebNca9ZeM8LY=Ca4P1uaUd3B-r5FF7mJ9k853fg@mail.gmail.com>\n\t<20210723131039.ire2z7u6sdxws3dt@notapiano>\n\t<CAHW6GYKCBXmNSzo+_EcQCvJEaPg-ahMsWXKwVA=J8YzZEtBUWA@mail.gmail.com>\n\t<20210723210807.emekovdwbehrzr44@notapiano>\n\t<CAHW6GYLbPU0TKbMNeNsHdif6Nm+-iUfBgRAcnUN6=ftKYsmYoQ@mail.gmail.com>\n\t<20210729143820.yumwo33jpwaljyb2@notapiano>\n\t<CAHW6GYJCx2kOyikHr7S2St9ud8ssZDb_rNByGSbciR7J1sYSVg@mail.gmail.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<CAHW6GYJCx2kOyikHr7S2St9ud8ssZDb_rNByGSbciR7J1sYSVg@mail.gmail.com>","Subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>,\n\tkernel@collabora.com, =?utf-8?b?QW5kcsOp?=\n\tAlmeida <andrealmeid@collabora.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":18463,"web_url":"https://patchwork.libcamera.org/comment/18463/","msgid":"<YQczbDTU+9IGQqzz@pendragon.ideasonboard.com>","date":"2021-08-01T23:51:08","subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Nícolas,\n\nThank you for the patch.\n\nOn Thu, Jul 22, 2021 at 08:28:50PM -0300, Nícolas F. R. A. Prado wrote:\n> Now that the number of buffers allocated by the FrameBufferAllocator\n> helper is passed through FrameBufferAllocator::allocate() and the\n> pipelines no longer use bufferCount for internal buffer or V4L2 buffer\n> slots allocation, we no longer need to have bufferCount in the\n> StreamConfiguration, so remove it.\n> \n> Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>\n> ---\n> \n> No changes in v7\n> \n> Changes in v6:\n> - Removed IPU3_BUFFER_COUNT as it was unused\n> \n>  include/libcamera/stream.h                         |  2 --\n>  src/android/camera_stream.cpp                      |  2 +-\n>  src/libcamera/pipeline/ipu3/cio2.cpp               |  1 -\n>  src/libcamera/pipeline/ipu3/ipu3.cpp               |  8 --------\n>  src/libcamera/pipeline/raspberrypi/raspberrypi.cpp |  6 ------\n>  src/libcamera/pipeline/rkisp1/rkisp1_path.cpp      |  2 --\n>  src/libcamera/pipeline/simple/converter.cpp        |  3 ---\n>  src/libcamera/pipeline/simple/converter.h          |  3 ---\n>  src/libcamera/pipeline/simple/simple.cpp           |  5 +----\n>  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp       |  3 ---\n>  src/libcamera/pipeline/vimc/vimc.cpp               |  3 ---\n>  src/libcamera/stream.cpp                           |  9 ++-------\n>  src/v4l2/v4l2_camera.cpp                           | 14 ++++++++++----\n>  src/v4l2/v4l2_camera.h                             |  5 +++--\n>  src/v4l2/v4l2_camera_proxy.cpp                     |  8 +++-----\n>  test/camera/buffer_import.cpp                      | 10 +++++++---\n>  test/libtest/buffer_source.cpp                     |  4 ++--\n>  test/libtest/buffer_source.h                       |  2 +-\n>  test/v4l2_videodevice/buffer_cache.cpp             |  4 ++--\n>  19 files changed, 32 insertions(+), 62 deletions(-)\n> \n> diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\n> index 0c55e7164592..b25f0059f2f1 100644\n> --- a/include/libcamera/stream.h\n> +++ b/include/libcamera/stream.h\n> @@ -45,8 +45,6 @@ struct StreamConfiguration {\n>  \tunsigned int stride;\n>  \tunsigned int frameSize;\n>  \n> -\tunsigned int bufferCount;\n> -\n>  \tStream *stream() const { return stream_; }\n>  \tvoid setStream(Stream *stream) { stream_ = stream; }\n>  \tconst StreamFormats &formats() const { return formats_; }\n> diff --git a/src/android/camera_stream.cpp b/src/android/camera_stream.cpp\n> index b168e3c0c288..0794be409f82 100644\n> --- a/src/android/camera_stream.cpp\n> +++ b/src/android/camera_stream.cpp\n> @@ -94,7 +94,7 @@ int CameraStream::configure()\n>  \t\t\tbuffers_.push_back(frameBuffer.get());\n>  \t}\n>  \n> -\tcamera3Stream_->max_buffers = configuration().bufferCount;\n> +\tcamera3Stream_->max_buffers = bufferCount;\n>  \n>  \treturn 0;\n>  }\n> diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp\n> index 1bcd580e251c..0e04e7214489 100644\n> --- a/src/libcamera/pipeline/ipu3/cio2.cpp\n> +++ b/src/libcamera/pipeline/ipu3/cio2.cpp\n> @@ -214,7 +214,6 @@ StreamConfiguration CIO2Device::generateConfiguration(Size size) const\n>  \n>  \tcfg.size = sensorFormat.size;\n>  \tcfg.pixelFormat = mbusCodesToPixelFormat.at(sensorFormat.mbus_code);\n> -\tcfg.bufferCount = CIO2_BUFFER_COUNT;\n>  \n>  \treturn cfg;\n>  }\n> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> index 4efd201c05e5..b223b3f33cd0 100644\n> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> @@ -38,7 +38,6 @@ namespace libcamera {\n>  \n>  LOG_DEFINE_CATEGORY(IPU3)\n>  \n> -static constexpr unsigned int IPU3_BUFFER_COUNT = 4;\n>  static constexpr unsigned int IPU3_MAX_STREAMS = 3;\n>  static const Size IMGU_OUTPUT_MIN_SIZE = { 2, 2 };\n>  static const Size IMGU_OUTPUT_MAX_SIZE = { 4480, 34004 };\n> @@ -295,7 +294,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n>  \t\t\t/* Initialize the RAW stream with the CIO2 configuration. */\n>  \t\t\tcfg->size = cio2Configuration_.size;\n>  \t\t\tcfg->pixelFormat = cio2Configuration_.pixelFormat;\n> -\t\t\tcfg->bufferCount = cio2Configuration_.bufferCount;\n>  \t\t\tcfg->stride = info.stride(cfg->size.width, 0, 64);\n>  \t\t\tcfg->frameSize = info.frameSize(cfg->size, 64);\n>  \t\t\tcfg->setStream(const_cast<Stream *>(&data_->rawStream_));\n> @@ -339,7 +337,6 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n>  \t\t\t\t\t      IMGU_OUTPUT_HEIGHT_ALIGN);\n>  \n>  \t\t\tcfg->pixelFormat = formats::NV12;\n> -\t\t\tcfg->bufferCount = IPU3_BUFFER_COUNT;\n>  \t\t\tcfg->stride = info.stride(cfg->size.width, 0, 1);\n>  \t\t\tcfg->frameSize = info.frameSize(cfg->size, 1);\n>  \n> @@ -407,7 +404,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n>  \tSize sensorResolution = data->cio2_.sensor()->resolution();\n>  \tfor (const StreamRole role : roles) {\n>  \t\tstd::map<PixelFormat, std::vector<SizeRange>> streamFormats;\n> -\t\tunsigned int bufferCount;\n>  \t\tPixelFormat pixelFormat;\n>  \t\tSize size;\n>  \n> @@ -428,7 +424,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n>  \t\t\tsize.height = utils::alignDown(size.height - 1,\n>  \t\t\t\t\t\t       IMGU_OUTPUT_HEIGHT_MARGIN);\n>  \t\t\tpixelFormat = formats::NV12;\n> -\t\t\tbufferCount = IPU3_BUFFER_COUNT;\n>  \t\t\tstreamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n>  \n>  \t\t\tbreak;\n> @@ -438,7 +433,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n>  \t\t\t\tdata->cio2_.generateConfiguration(sensorResolution);\n>  \t\t\tpixelFormat = cio2Config.pixelFormat;\n>  \t\t\tsize = cio2Config.size;\n> -\t\t\tbufferCount = cio2Config.bufferCount;\n>  \n>  \t\t\tfor (const PixelFormat &format : data->cio2_.formats())\n>  \t\t\t\tstreamFormats[format] = data->cio2_.sizes();\n> @@ -457,7 +451,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n>  \t\t\t\t\t       .alignedDownTo(IMGU_OUTPUT_WIDTH_ALIGN,\n>  \t\t\t\t\t\t\t      IMGU_OUTPUT_HEIGHT_ALIGN);\n>  \t\t\tpixelFormat = formats::NV12;\n> -\t\t\tbufferCount = IPU3_BUFFER_COUNT;\n>  \t\t\tstreamFormats[pixelFormat] = { { IMGU_OUTPUT_MIN_SIZE, size } };\n>  \n>  \t\t\tbreak;\n> @@ -474,7 +467,6 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera,\n>  \t\tStreamConfiguration cfg(formats);\n>  \t\tcfg.size = size;\n>  \t\tcfg.pixelFormat = pixelFormat;\n> -\t\tcfg.bufferCount = bufferCount;\n>  \t\tconfig->addConfiguration(cfg);\n>  \t}\n>  \n> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> index 776e0f92aed1..e6fc0425c3ef 100644\n> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> @@ -473,7 +473,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n>  \tRPiCameraData *data = cameraData(camera);\n>  \tCameraConfiguration *config = new RPiCameraConfiguration(data);\n>  \tV4L2DeviceFormat sensorFormat;\n> -\tunsigned int bufferCount;\n>  \tPixelFormat pixelFormat;\n>  \tV4L2VideoDevice::Formats fmts;\n>  \tSize size;\n> @@ -491,7 +490,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n>  \t\t\tsensorFormat = findBestMode(fmts, size);\n>  \t\t\tpixelFormat = sensorFormat.fourcc.toPixelFormat();\n>  \t\t\tASSERT(pixelFormat.isValid());\n> -\t\t\tbufferCount = 2;\n>  \t\t\trawCount++;\n>  \t\t\tbreak;\n>  \n> @@ -500,7 +498,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n>  \t\t\tpixelFormat = formats::NV12;\n>  \t\t\t/* Return the largest sensor resolution. */\n>  \t\t\tsize = data->sensor_->resolution();\n> -\t\t\tbufferCount = 1;\n>  \t\t\toutCount++;\n>  \t\t\tbreak;\n>  \n> @@ -516,7 +513,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n>  \t\t\tfmts = data->isp_[Isp::Output0].dev()->formats();\n>  \t\t\tpixelFormat = formats::YUV420;\n>  \t\t\tsize = { 1920, 1080 };\n> -\t\t\tbufferCount = 4;\n>  \t\t\toutCount++;\n>  \t\t\tbreak;\n>  \n> @@ -524,7 +520,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n>  \t\t\tfmts = data->isp_[Isp::Output0].dev()->formats();\n>  \t\t\tpixelFormat = formats::ARGB8888;\n>  \t\t\tsize = { 800, 600 };\n> -\t\t\tbufferCount = 4;\n>  \t\t\toutCount++;\n>  \t\t\tbreak;\n>  \n> @@ -554,7 +549,6 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n>  \t\tStreamConfiguration cfg(formats);\n>  \t\tcfg.size = size;\n>  \t\tcfg.pixelFormat = pixelFormat;\n> -\t\tcfg.bufferCount = bufferCount;\n>  \t\tconfig->addConfiguration(cfg);\n>  \t}\n>  \n> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> index fea330f72886..4961f3971e59 100644\n> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp\n> @@ -61,7 +61,6 @@ StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution)\n>  \tStreamConfiguration cfg(formats);\n>  \tcfg.pixelFormat = formats::NV12;\n>  \tcfg.size = maxResolution;\n> -\tcfg.bufferCount = RKISP1_BUFFER_COUNT;\n>  \n>  \treturn cfg;\n>  }\n> @@ -77,7 +76,6 @@ CameraConfiguration::Status RkISP1Path::validate(StreamConfiguration *cfg)\n>  \n>  \tcfg->size.boundTo(maxResolution_);\n>  \tcfg->size.expandTo(minResolution_);\n> -\tcfg->bufferCount = RKISP1_BUFFER_COUNT;\n>  \n>  \tV4L2DeviceFormat format;\n>  \tformat.fourcc = video_->toV4L2PixelFormat(cfg->pixelFormat);\n> diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp\n> index b3bcf01483f7..fda417793e80 100644\n> --- a/src/libcamera/pipeline/simple/converter.cpp\n> +++ b/src/libcamera/pipeline/simple/converter.cpp\n> @@ -89,9 +89,6 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg,\n>  \t\treturn -EINVAL;\n>  \t}\n>  \n> -\tinputBufferCount_ = inputCfg.bufferCount;\n> -\toutputBufferCount_ = outputCfg.bufferCount;\n> -\n>  \treturn 0;\n>  }\n>  \n> diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h\n> index 7e1d60674f62..406e63ca2a80 100644\n> --- a/src/libcamera/pipeline/simple/converter.h\n> +++ b/src/libcamera/pipeline/simple/converter.h\n> @@ -87,9 +87,6 @@ private:\n>  \t\tSimpleConverter *converter_;\n>  \t\tunsigned int index_;\n>  \t\tstd::unique_ptr<V4L2M2MDevice> m2m_;\n> -\n> -\t\tunsigned int inputBufferCount_;\n> -\t\tunsigned int outputBufferCount_;\n>  \t};\n>  \n>  \tstd::string deviceNode_;\n> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\n> index a1163eaf8be2..ded04914f610 100644\n> --- a/src/libcamera/pipeline/simple/simple.cpp\n> +++ b/src/libcamera/pipeline/simple/simple.cpp\n> @@ -628,7 +628,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n>  \t\t    cfg.size != pipeConfig_->captureSize)\n>  \t\t\tneedConversion_ = true;\n>  \n> -\t\t/* Set the stride, frameSize and bufferCount. */\n> +\t\t/* Set the stride and frameSize. */\n>  \t\tif (needConversion_) {\n>  \t\t\tstd::tie(cfg.stride, cfg.frameSize) =\n>  \t\t\t\tconverter->strideAndFrameSize(cfg.pixelFormat, cfg.size);\n> @@ -646,8 +646,6 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()\n>  \t\t\tcfg.stride = format.planes[0].bpl;\n>  \t\t\tcfg.frameSize = format.planes[0].size;\n>  \t\t}\n> -\n> -\t\tcfg.bufferCount = 3;\n>  \t}\n>  \n>  \treturn status;\n> @@ -770,7 +768,6 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)\n>  \tinputCfg.pixelFormat = pipeConfig->captureFormat;\n>  \tinputCfg.size = pipeConfig->captureSize;\n>  \tinputCfg.stride = captureFormat.planes[0].bpl;\n> -\tinputCfg.bufferCount = kNumInternalBuffers;\n\nYou should also drop the kNumInternalBuffers constant.\n\n>  \n>  \treturn converter_->configure(inputCfg, outputCfgs);\n>  }\n> diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> index 755949e7a59a..32482300f09a 100644\n> --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> @@ -150,8 +150,6 @@ CameraConfiguration::Status UVCCameraConfiguration::validate()\n>  \t\tstatus = Adjusted;\n>  \t}\n>  \n> -\tcfg.bufferCount = 4;\n> -\n>  \tV4L2DeviceFormat format;\n>  \tformat.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n>  \tformat.size = cfg.size;\n> @@ -193,7 +191,6 @@ CameraConfiguration *PipelineHandlerUVC::generateConfiguration(Camera *camera,\n>  \n>  \tcfg.pixelFormat = formats.pixelformats().front();\n>  \tcfg.size = formats.sizes(cfg.pixelFormat).back();\n> -\tcfg.bufferCount = 4;\n>  \n>  \tconfig->addConfiguration(cfg);\n>  \n> diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp\n> index 24ba743a946c..a698427c4361 100644\n> --- a/src/libcamera/pipeline/vimc/vimc.cpp\n> +++ b/src/libcamera/pipeline/vimc/vimc.cpp\n> @@ -167,8 +167,6 @@ CameraConfiguration::Status VimcCameraConfiguration::validate()\n>  \t\tstatus = Adjusted;\n>  \t}\n>  \n> -\tcfg.bufferCount = 4;\n> -\n>  \tV4L2DeviceFormat format;\n>  \tformat.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);\n>  \tformat.size = cfg.size;\n> @@ -224,7 +222,6 @@ CameraConfiguration *PipelineHandlerVimc::generateConfiguration(Camera *camera,\n>  \n>  \tcfg.pixelFormat = formats::BGR888;\n>  \tcfg.size = { 1920, 1080 };\n> -\tcfg.bufferCount = 4;\n>  \n>  \tconfig->addConfiguration(cfg);\n>  \n> diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp\n> index b8626775d224..ca507b72b26a 100644\n> --- a/src/libcamera/stream.cpp\n> +++ b/src/libcamera/stream.cpp\n> @@ -280,7 +280,7 @@ SizeRange StreamFormats::range(const PixelFormat &pixelformat) const\n>   * handlers provide StreamFormats.\n>   */\n>  StreamConfiguration::StreamConfiguration()\n> -\t: pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> +\t: pixelFormat(0), stride(0), frameSize(0),\n>  \t  stream_(nullptr)\n\nThis now holds on a single line.\n\n>  {\n>  }\n> @@ -289,7 +289,7 @@ StreamConfiguration::StreamConfiguration()\n>   * \\brief Construct a configuration with stream formats\n>   */\n>  StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n> -\t: pixelFormat(0), stride(0), frameSize(0), bufferCount(0),\n> +\t: pixelFormat(0), stride(0), frameSize(0),\n>  \t  stream_(nullptr), formats_(formats)\n>  {\n>  }\n> @@ -324,11 +324,6 @@ StreamConfiguration::StreamConfiguration(const StreamFormats &formats)\n>   * validating the configuration with a call to CameraConfiguration::validate().\n>   */\n>  \n> -/**\n> - * \\var StreamConfiguration::bufferCount\n> - * \\brief Requested number of buffers to allocate for the stream\n> - */\n> -\n>  /**\n>   * \\fn StreamConfiguration::stream()\n>   * \\brief Retrieve the stream associated with the configuration\n> diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp\n> index d01eacfa2b84..2ff9affc6388 100644\n> --- a/src/v4l2/v4l2_camera.cpp\n> +++ b/src/v4l2/v4l2_camera.cpp\n> @@ -12,6 +12,8 @@\n>  \n>  #include <libcamera/base/log.h>\n>  \n> +#include <libcamera/property_ids.h>\n> +\n>  using namespace libcamera;\n>  \n>  LOG_DECLARE_CATEGORY(V4L2Compat)\n> @@ -107,14 +109,12 @@ void V4L2Camera::requestComplete(Request *request)\n>  }\n>  \n>  int V4L2Camera::configure(StreamConfiguration *streamConfigOut,\n> -\t\t\t  const Size &size, const PixelFormat &pixelformat,\n> -\t\t\t  unsigned int bufferCount)\n> +\t\t\t  const Size &size, const PixelFormat &pixelformat)\n>  {\n>  \tStreamConfiguration &streamConfig = config_->at(0);\n>  \tstreamConfig.size.width = size.width;\n>  \tstreamConfig.size.height = size.height;\n>  \tstreamConfig.pixelFormat = pixelformat;\n> -\tstreamConfig.bufferCount = bufferCount;\n>  \t/* \\todo memoryType (interval vs external) */\n\nWhile at it, could you s/interval/internal/ ?\n\n>  \n>  \tCameraConfiguration::Status validation = config_->validate();\n> @@ -146,7 +146,6 @@ int V4L2Camera::validateConfiguration(const PixelFormat &pixelFormat,\n>  \tStreamConfiguration &cfg = config->at(0);\n>  \tcfg.size = size;\n>  \tcfg.pixelFormat = pixelFormat;\n> -\tcfg.bufferCount = 1;\n>  \n>  \tCameraConfiguration::Status validation = config->validate();\n>  \tif (validation == CameraConfiguration::Invalid)\n> @@ -299,3 +298,10 @@ bool V4L2Camera::isRunning()\n>  {\n>  \treturn isRunning_;\n>  }\n> +\n> +unsigned int V4L2Camera::minimumRequests(unsigned int count)\n> +{\n> +\tunsigned int min = camera_->properties().get(properties::MinimumRequests);\n> +\n> +\treturn std::max(count, min);\n> +}\n\nThe rework of the V4L2 adaptation layer should go to a separate patch,\nit's not just about removing bufferCount.\n\nHow about making this a function that just returns the value of the\nproperty, and moving the std::max() to the caller ?\n\n> diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h\n> index a095f4e27524..4b5618ac12b5 100644\n> --- a/src/v4l2/v4l2_camera.h\n> +++ b/src/v4l2/v4l2_camera.h\n> @@ -45,8 +45,7 @@ public:\n>  \tstd::vector<Buffer> completedBuffers();\n>  \n>  \tint configure(StreamConfiguration *streamConfigOut,\n> -\t\t      const Size &size, const PixelFormat &pixelformat,\n> -\t\t      unsigned int bufferCount);\n> +\t\t      const Size &size, const PixelFormat &pixelformat);\n>  \tint validateConfiguration(const PixelFormat &pixelformat,\n>  \t\t\t\t  const Size &size,\n>  \t\t\t\t  StreamConfiguration *streamConfigOut);\n> @@ -65,6 +64,8 @@ public:\n>  \n>  \tbool isRunning();\n>  \n> +\tunsigned int minimumRequests(unsigned int count);\n> +\n>  private:\n>  \tvoid requestComplete(Request *request);\n>  \n> diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp\n> index 7682c4bddf90..634ec84e0cbb 100644\n> --- a/src/v4l2/v4l2_camera_proxy.cpp\n> +++ b/src/v4l2/v4l2_camera_proxy.cpp\n> @@ -349,8 +349,7 @@ int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg)\n>  \tSize size(arg->fmt.pix.width, arg->fmt.pix.height);\n>  \tV4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->fmt.pix.pixelformat);\n>  \tret = vcam_->configure(&streamConfig_, size,\n> -\t\t\t       PixelFormatInfo::info(v4l2Format).format,\n> -\t\t\t       bufferCount_);\n> +\t\t\t       PixelFormatInfo::info(v4l2Format).format);\n>  \tif (ret < 0)\n>  \t\treturn -EINVAL;\n>  \n> @@ -491,14 +490,13 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf\n>  \tSize size(v4l2PixFormat_.width, v4l2PixFormat_.height);\n>  \tV4L2PixelFormat v4l2Format = V4L2PixelFormat(v4l2PixFormat_.pixelformat);\n>  \tint ret = vcam_->configure(&streamConfig_, size,\n> -\t\t\t\t   PixelFormatInfo::info(v4l2Format).format,\n> -\t\t\t\t   arg->count);\n> +\t\t\t\t   PixelFormatInfo::info(v4l2Format).format);\n>  \tif (ret < 0)\n>  \t\treturn -EINVAL;\n>  \n>  \tsetFmtFromConfig(streamConfig_);\n>  \n> -\targ->count = streamConfig_.bufferCount;\n> +\targ->count = vcam_->minimumRequests(arg->count);\n>  \tbufferCount_ = arg->count;\n>  \n>  \tret = vcam_->allocBuffers(arg->count);\n\nUnless I'm mistaken, allocBuffers() could return a lower buffer count\nthan requested, this should be taken into account.\n\n> diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp\n> index c504ea09e64b..67ac0ad20e15 100644\n> --- a/test/camera/buffer_import.cpp\n> +++ b/test/camera/buffer_import.cpp\n> @@ -16,6 +16,8 @@\n>  #include <libcamera/base/thread.h>\n>  #include <libcamera/base/timer.h>\n>  \n> +#include <libcamera/property_ids.h>\n> +\n>  #include \"libcamera/internal/device_enumerator.h\"\n>  #include \"libcamera/internal/media_device.h\"\n>  #include \"libcamera/internal/v4l2_videodevice.h\"\n> @@ -92,10 +94,12 @@ protected:\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> +\t\tunsigned int bufferCount = camera_->properties().get(properties::MinimumRequests);\n> +\n>  \t\tStream *stream = cfg.stream();\n>  \n>  \t\tBufferSource source;\n> -\t\tint ret = source.allocate(cfg);\n> +\t\tint ret = source.allocate(cfg, bufferCount);\n>  \t\tif (ret != TestPass)\n>  \t\t\treturn ret;\n>  \n> @@ -139,10 +143,10 @@ protected:\n>  \t\twhile (timer.isRunning())\n>  \t\t\tdispatcher->processEvents();\n>  \n> -\t\tif (completeRequestsCount_ < cfg.bufferCount * 2) {\n> +\t\tif (completeRequestsCount_ < bufferCount * 2) {\n>  \t\t\tstd::cout << \"Failed to capture enough frames (got \"\n>  \t\t\t\t  << completeRequestsCount_ << \" expected at least \"\n> -\t\t\t\t  << cfg.bufferCount * 2 << \")\" << std::endl;\n> +\t\t\t\t  << bufferCount * 2 << \")\" << std::endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> diff --git a/test/libtest/buffer_source.cpp b/test/libtest/buffer_source.cpp\n> index 73563f2fc39d..c3d5286a2462 100644\n> --- a/test/libtest/buffer_source.cpp\n> +++ b/test/libtest/buffer_source.cpp\n> @@ -24,7 +24,7 @@ BufferSource::~BufferSource()\n>  \t\tmedia_->release();\n>  }\n>  \n> -int BufferSource::allocate(const StreamConfiguration &config)\n> +int BufferSource::allocate(const StreamConfiguration &config, unsigned int count)\n>  {\n>  \t/* Locate and open the video device. */\n>  \tstd::string videoDeviceName = \"vivid-000-vid-out\";\n> @@ -77,7 +77,7 @@ int BufferSource::allocate(const StreamConfiguration &config)\n>  \t\treturn TestFail;\n>  \t}\n>  \n> -\tif (video->allocateBuffers(config.bufferCount, &buffers_) < 0) {\n> +\tif (video->allocateBuffers(count, &buffers_) < 0) {\n>  \t\tstd::cout << \"Failed to allocate buffers\" << std::endl;\n>  \t\treturn TestFail;\n>  \t}\n> diff --git a/test/libtest/buffer_source.h b/test/libtest/buffer_source.h\n> index 14b4770e8d8a..6a18e269a575 100644\n> --- a/test/libtest/buffer_source.h\n> +++ b/test/libtest/buffer_source.h\n> @@ -20,7 +20,7 @@ public:\n>  \tBufferSource();\n>  \t~BufferSource();\n>  \n> -\tint allocate(const StreamConfiguration &config);\n> +\tint allocate(const StreamConfiguration &config, unsigned int count);\n>  \tconst std::vector<std::unique_ptr<FrameBuffer>> &buffers();\n>  \n>  private:\n> diff --git a/test/v4l2_videodevice/buffer_cache.cpp b/test/v4l2_videodevice/buffer_cache.cpp\n> index b3f2bec11783..07fddfd2617c 100644\n> --- a/test/v4l2_videodevice/buffer_cache.cpp\n> +++ b/test/v4l2_videodevice/buffer_cache.cpp\n> @@ -10,6 +10,7 @@\n>  #include <vector>\n>  \n>  #include <libcamera/formats.h>\n> +#include <libcamera/property_ids.h>\n>  #include <libcamera/stream.h>\n>  \n>  #include \"buffer_source.h\"\n> @@ -145,10 +146,9 @@ public:\n>  \t\tStreamConfiguration cfg;\n>  \t\tcfg.pixelFormat = formats::YUYV;\n>  \t\tcfg.size = Size(600, 800);\n> -\t\tcfg.bufferCount = numBuffers;\n>  \n>  \t\tBufferSource source;\n> -\t\tint ret = source.allocate(cfg);\n> +\t\tint ret = source.allocate(cfg, numBuffers);\n>  \t\tif (ret != TestPass)\n>  \t\t\treturn ret;\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 38E7BC3232\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSun,  1 Aug 2021 23:51:21 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B5163687C4;\n\tMon,  2 Aug 2021 01:51:20 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 74B13687BD\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  2 Aug 2021 01:51:19 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id D7B6287C;\n\tMon,  2 Aug 2021 01:51:18 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"DbYDgH6Q\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1627861879;\n\tbh=6DHSJ0La1N2CaNdGh1omDEPWBv5kLqegdAHS5IzGn0o=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=DbYDgH6Qg+nJtu1NxBZoHP0M0cpKH1qHjXvNUttmL3HF9yyAYm13WVD75Dz0KnMqN\n\tH5/4Ik4tKlJeS1i9ckOB7x9l0IWlR+XA23L7w2OvlG9epybmK+iIgqQYGQ5ZFN5Guk\n\t/Pvo7C0Qlta0/Gx7hXmKhbplJfPxHu6Im7fU9kbw=","Date":"Mon, 2 Aug 2021 02:51:08 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"=?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4=?= Prado <nfraprado@collabora.com>","Message-ID":"<YQczbDTU+9IGQqzz@pendragon.ideasonboard.com>","References":"<20210722232851.747614-1-nfraprado@collabora.com>\n\t<20210722232851.747614-11-nfraprado@collabora.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20210722232851.747614-11-nfraprado@collabora.com>","Subject":"Re: [libcamera-devel] [PATCH v7 10/11] libcamera: stream: Remove\n\tbufferCount","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org, kernel@collabora.com, =?utf-8?q?A?=\n\t=?utf-8?b?bmRyw6k=?= Almeida <andrealmeid@collabora.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]