@@ -105,6 +105,7 @@ private:
std::map<const Stream *, std::unique_ptr<V4L2M2MStream>> streams_;
std::map<FrameBuffer *, unsigned int> queue_;
+ std::pair<Rectangle, Rectangle> inputCropBounds_;
};
} /* namespace libcamera */
@@ -195,6 +195,9 @@ Converter::~Converter()
* this function should be called after the \a stream has been configured using
* configure().
*
+ * When called with an invalid \a stream, the function returns the default crop
+ * bounds of the converter.
+ *
* \return A pair containing the minimum and maximum crop bound in that order
*/
@@ -30,6 +30,52 @@ namespace libcamera {
LOG_DECLARE_CATEGORY(Converter)
+namespace {
+
+int getCropBounds(V4L2VideoDevice *device, Rectangle &minCrop,
+ Rectangle &maxCrop)
+{
+ Rectangle minC;
+ Rectangle maxC;
+
+ /* Find crop bounds */
+ minC.width = 1;
+ minC.height = 1;
+ maxC.width = UINT_MAX;
+ maxC.height = UINT_MAX;
+
+ int ret = device->setSelection(V4L2_SEL_TGT_CROP, &minC);
+ if (ret) {
+ LOG(Converter, Error)
+ << "Could not query minimum selection crop: "
+ << strerror(-ret);
+ return ret;
+ }
+
+ ret = device->getSelection(V4L2_SEL_TGT_CROP_BOUNDS, &maxC);
+ if (ret) {
+ LOG(Converter, Error)
+ << "Could not query maximum selection crop: "
+ << strerror(-ret);
+ return ret;
+ }
+
+ /* Reset the crop to its maximum */
+ ret = device->setSelection(V4L2_SEL_TGT_CROP, &maxC);
+ if (ret) {
+ LOG(Converter, Error)
+ << "Could not reset selection crop: "
+ << strerror(-ret);
+ return ret;
+ }
+
+ minCrop = minC;
+ maxCrop = maxC;
+ return 0;
+}
+
+} /* namespace */
+
/* -----------------------------------------------------------------------------
* V4L2M2MConverter::V4L2M2MStream
*/
@@ -98,41 +144,10 @@ int V4L2M2MConverter::V4L2M2MStream::configure(const StreamConfiguration &inputC
outputBufferCount_ = outputCfg.bufferCount;
if (converter_->features() & Feature::InputCrop) {
- Rectangle minCrop;
- Rectangle maxCrop;
-
- /* Find crop bounds */
- minCrop.width = 1;
- minCrop.height = 1;
- maxCrop.width = UINT_MAX;
- maxCrop.height = UINT_MAX;
-
- ret = setInputSelection(V4L2_SEL_TGT_CROP, &minCrop);
- if (ret) {
- LOG(Converter, Error)
- << "Could not query minimum selection crop: "
- << strerror(-ret);
- return ret;
- }
-
- ret = getInputSelection(V4L2_SEL_TGT_CROP_BOUNDS, &maxCrop);
- if (ret) {
- LOG(Converter, Error)
- << "Could not query maximum selection crop: "
- << strerror(-ret);
- return ret;
- }
-
- /* Reset the crop to its maximum */
- ret = setInputSelection(V4L2_SEL_TGT_CROP, &maxCrop);
- if (ret) {
- LOG(Converter, Error)
- << "Could not reset selection crop: "
- << strerror(-ret);
+ ret = getCropBounds(m2m_->output(), inputCropBounds_.first,
+ inputCropBounds_.second);
+ if (ret)
return ret;
- }
-
- inputCropBounds_ = { minCrop, maxCrop };
}
return 0;
@@ -258,27 +273,9 @@ V4L2M2MConverter::V4L2M2MConverter(MediaDevice *media)
return;
}
- /* Discover Feature::InputCrop */
- Rectangle maxCrop;
- maxCrop.width = UINT_MAX;
- maxCrop.height = UINT_MAX;
-
- ret = m2m_->output()->setSelection(V4L2_SEL_TGT_CROP, &maxCrop);
- if (ret)
- return;
-
- /*
- * Rectangles for cropping targets are defined even if the device
- * does not support cropping. Their sizes and positions will be
- * fixed in such cases.
- *
- * Set and inspect a crop equivalent to half of the maximum crop
- * returned earlier. Use this to determine whether the crop on
- * input is really supported.
- */
- Rectangle halfCrop(maxCrop.size() / 2);
- ret = m2m_->output()->setSelection(V4L2_SEL_TGT_CROP, &halfCrop);
- if (!ret && halfCrop != maxCrop) {
+ ret = getCropBounds(m2m_->output(), inputCropBounds_.first,
+ inputCropBounds_.second);
+ if (!ret && inputCropBounds_.first != inputCropBounds_.second) {
features_ |= Feature::InputCrop;
LOG(Converter, Info)
@@ -477,10 +474,10 @@ std::pair<Rectangle, Rectangle>
V4L2M2MConverter::inputCropBounds(const Stream *stream)
{
auto iter = streams_.find(stream);
- if (iter == streams_.end())
- return {};
+ if (iter != streams_.end())
+ return iter->second->inputCropBounds();
- return iter->second->inputCropBounds();
+ return inputCropBounds_;
}
/**
When a converter (dw100 on imx8mp in this case) is used in a pipeline, the ScalerCrop control get's created at createCamera() time. As this is before configure(), no streams were configured on the converter and the stream specific crop bounds are not known. Extend the converter class to report the default crop bounds in case the provided stream is not found. Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com> --- .../internal/converter/converter_v4l2_m2m.h | 1 + src/libcamera/converter.cpp | 3 + .../converter/converter_v4l2_m2m.cpp | 113 +++++++++--------- 3 files changed, 59 insertions(+), 58 deletions(-)