@@ -663,19 +663,29 @@ associated with immutable values, which represent static characteristics that ca
be used by applications to identify camera devices in the system. Properties can be
registered by inspecting the values of V4L2 controls from the video devices and
camera sensor (for example to retrieve the position and orientation of a camera)
-or to express other immutable characteristics. The example pipeline handler does
-not register any property, but examples are available in the libcamera code
-base.
+or to express other immutable characteristics.
-.. TODO: Add a property example to the pipeline handler. At least the model.
+A required property is ``MinimumRequests``, which indicates how many requests
+need to be queued in the pipeline for capture without frame drops to be
+possible.
+
+In our case, the vivid driver requires two buffers before it'll start streaming
+(can be seen in the ``min_reqbufs_allocation`` property for the ``vid_cap`` queue in
+vivid's driver code). Therefore we will set our ``MinimumRequests`` to two.
+Append the following line to ``init()``:
+
+.. code-block:: cpp
+
+ properties_.set(properties::MinimumRequests, 2);
At this point you need to add the following includes to the top of the file for
-handling controls:
+handling controls and properties:
.. code-block:: cpp
#include <libcamera/controls.h>
#include <libcamera/control_ids.h>
+ #include <libcamera/property_ids.h>
Vendor-specific controls and properties
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -18,6 +18,7 @@
#include <libcamera/camera_manager.h>
#include <libcamera/formats.h>
#include <libcamera/geometry.h>
+#include <libcamera/property_ids.h>
#include <libcamera/stream.h>
#include "libcamera/internal/bayer_format.h"
@@ -165,6 +166,7 @@ int ISICameraData::init()
return ret;
properties_ = sensor_->properties();
+ properties_.set(properties::MinimumRequests, 2);
return 0;
}
@@ -168,6 +168,8 @@ private:
MediaDevice *imguMediaDev_;
std::vector<IPABuffer> ipaBuffers_;
+
+ static constexpr unsigned int kMinimumRequests = 3;
};
IPU3CameraConfiguration::IPU3CameraConfiguration(IPU3CameraData *data)
@@ -1074,6 +1076,8 @@ int PipelineHandlerIPU3::registerCameras()
/* Initialize the camera properties. */
data->properties_ = cio2->sensor()->properties();
+ data->properties_.set(properties::MinimumRequests, kMinimumRequests);
+
ret = initControls(data.get());
if (ret)
continue;
@@ -1602,6 +1602,7 @@ bool PipelineHandlerMaliC55::registerSensorCamera(MediaLink *ispLink)
return false;
data->properties_ = data->sensor_->properties();
+ data->properties_.set(properties::MinimumRequests, 2);
const CameraSensorProperties::SensorDelays &delays = data->sensor_->sensorDelays();
std::unordered_map<uint32_t, DelayedControls::ControlParams> params = {
@@ -1318,6 +1318,7 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor)
/* Initialize the camera properties. */
data->properties_ = data->sensor_->properties();
+ data->properties_.set(properties::MinimumRequests, 3);
scalerMaxCrop_ = Rectangle(data->sensor_->resolution());
@@ -848,6 +848,8 @@ int PipelineHandlerBase::registerCamera(std::unique_ptr<RPi::CameraData> &camera
*/
data->properties_.set(properties::ScalerCropMaximum, Rectangle{});
+ data->properties_.set(properties::MinimumRequests, 3);
+
ret = platformRegister(cameraData, frontend, backend);
if (ret)
return ret;
@@ -26,6 +26,7 @@
#include <libcamera/camera.h>
#include <libcamera/control_ids.h>
+#include <libcamera/property_ids.h>
#include <libcamera/request.h>
#include <libcamera/stream.h>
@@ -233,6 +234,10 @@ SimpleFrameInfo *SimpleFrames::find(uint32_t frame)
struct SimplePipelineInfo {
const char *driver;
+ /*
+ * Minimum number of buffers required by the driver to start streaming.
+ */
+ unsigned int minimumBuffers;
/*
* Each converter in the list contains the name
* and the number of streams it supports.
@@ -249,14 +254,14 @@ struct SimplePipelineInfo {
namespace {
static const SimplePipelineInfo supportedDevices[] = {
- { "dcmipp", {}, false },
- { "imx7-csi", { { "pxp", 1 } }, false },
- { "intel-ipu6", {}, true },
- { "j721e-csi2rx", {}, true },
- { "mtk-seninf", { { "mtk-mdp", 3 } }, false },
- { "mxc-isi", {}, false },
- { "qcom-camss", {}, true },
- { "sun6i-csi", {}, false },
+ { "dcmipp", 1, {}, false },
+ { "imx7-csi", 2, { { "pxp", 1 } }, false },
+ { "intel-ipu6", 3, {}, true }, // \todo Check if the minimumBuffers can be lowered
+ { "j721e-csi2rx", 1, {}, true },
+ { "mtk-seninf", 3, { { "mtk-mdp", 3 } }, false }, // \todo Check if the minimumBuffers can be lowered
+ { "mxc-isi", 3, {}, false },
+ { "qcom-camss", 1, {}, true },
+ { "sun6i-csi", 3, {}, false },
};
} /* namespace */
@@ -346,6 +351,8 @@ public:
std::unique_ptr<SoftwareIsp> swIsp_;
SimpleFrames frameInfo_;
+ unsigned int deviceInfoMinimumBuffers;
+
private:
void tryPipeline(unsigned int code, const Size &size);
static std::vector<const MediaPad *> routedSourcePads(MediaPad *sink);
@@ -1402,8 +1409,24 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)
inputCfg.bufferCount = kNumInternalBuffers;
if (data->converter_) {
+ /*
+ * The application will interact only with the capture node of
+ * the converter. Require two buffers for a frame drop free
+ * conversion, plus one extra to account for requeue delays.
+ */
+ data->properties_.set(properties::MinimumRequests, 3);
+
return data->converter_->configure(inputCfg, outputCfgs);
} else {
+ /*
+ * The application will interact directly with the video capture
+ * device. Require the minimum required by the driver, plus one
+ * extra to account for requeue delays. Force at least three
+ * buffers in order to not drop frames.
+ */
+ data->properties_.set(properties::MinimumRequests, std::max(data->deviceInfoMinimumBuffers + 1,
+ 3U));
+
ipa::soft::IPAConfigInfo configInfo;
configInfo.sensorControls = data->sensor_->controls();
return data->swIsp_->configure(inputCfg, outputCfgs, configInfo);
@@ -1787,6 +1810,8 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
bool registered = false;
for (std::unique_ptr<SimpleCameraData> &data : pipelines) {
+ data->deviceInfoMinimumBuffers = info->minimumBuffers;
+
int ret = data->init();
if (ret < 0)
continue;
@@ -586,6 +586,8 @@ int UVCCameraData::init(MediaDevice *media)
properties_.set(properties::PixelArraySize, resolution);
properties_.set(properties::PixelArrayActiveAreas, { Rectangle(resolution) });
+ properties_.set(properties::MinimumRequests, 3);
+
/* Initialise the supported controls. */
ControlInfoMap::Map ctrls;
@@ -24,6 +24,7 @@
#include <libcamera/formats.h>
#include <libcamera/framebuffer.h>
#include <libcamera/geometry.h>
+#include <libcamera/property_ids.h>
#include <libcamera/request.h>
#include <libcamera/stream.h>
@@ -592,6 +593,7 @@ int VimcCameraData::init()
/* Initialize the camera properties. */
properties_ = sensor_->properties();
+ properties_.set(properties::MinimumRequests, 3);
return 0;
}
@@ -126,6 +126,7 @@ VirtualCameraData::VirtualCameraData(PipelineHandler *pipe,
properties_.set(properties::PixelArrayActiveAreas,
{ Rectangle(config_.maxResolutionSize) });
+ properties_.set(properties::MinimumRequests, 3);
/* \todo Support multiple streams and pass multi_stream_test */
streamConfigs_.resize(kMaxStream);
@@ -701,4 +701,26 @@ controls:
Different cameras may report identical devices.
+ - MinimumRequests:
+ type: uint32_t
+ description: |
+ The minimum number of capture requests that the camera pipeline requires
+ to have queued in order to sustain capture operations with only minimal
+ frame drops. At this quantity, there's no guarantee that manual per
+ frame controls will apply correctly. This is also the minimum number of
+ requests that must be queued before capture starts.
+
+ This property is based on the minimum number of memory buffers
+ needed to fill the capture pipeline composed of hardware processing
+ blocks plus as many buffers as needed to take into account propagation
+ delays and avoid dropping frames.
+
+ \todo Should this be a per-stream property?
+
+ \todo Extend this property to expose the different minimum buffer and
+ request counts (the minimum number of buffers to be able to capture at
+ all, the minimum number of buffers to sustain capture without frame
+ drop, and the minimum number of requests to ensure proper operation of
+ per-frame controls).
+
...