diff --git a/include/libcamera/internal/converter/converter_v4l2_m2m.h b/include/libcamera/internal/converter/converter_v4l2_m2m.h
index 0bc0d053e2c4..a5286166f574 100644
--- a/include/libcamera/internal/converter/converter_v4l2_m2m.h
+++ b/include/libcamera/internal/converter/converter_v4l2_m2m.h
@@ -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 */
diff --git a/src/libcamera/converter.cpp b/src/libcamera/converter.cpp
index 945f2527b96a..d4b5e5260e02 100644
--- a/src/libcamera/converter.cpp
+++ b/src/libcamera/converter.cpp
@@ -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
  */
 
diff --git a/src/libcamera/converter/converter_v4l2_m2m.cpp b/src/libcamera/converter/converter_v4l2_m2m.cpp
index d63ef2f8028f..bd7e5cce600d 100644
--- a/src/libcamera/converter/converter_v4l2_m2m.cpp
+++ b/src/libcamera/converter/converter_v4l2_m2m.cpp
@@ -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_;
 }
 
 /**
