diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 71b36ecf6cd9..daa66d23d5f3 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -226,38 +226,77 @@ CameraConfiguration
 PipelineHandlerIPU3::streamConfiguration(Camera *camera,
 					 const std::vector<StreamUsage> &usages)
 {
-	CameraConfiguration configs;
 	IPU3CameraData *data = cameraData(camera);
-	StreamConfiguration config = {};
+	CameraConfiguration cameraConfig;
+	std::set<IPU3Stream *> streams = {
+		&data->outStream_,
+		&data->vfStream_,
+	};
 
-	/*
-	 * FIXME: Soraka: the maximum resolution reported by both sensors
-	 * (2592x1944 for ov5670 and 4224x3136 for ov13858) are returned as
-	 * default configurations but they're not correctly processed by the
-	 * ImgU. Resolutions up tp 2560x1920 have been validated.
-	 *
-	 * \todo Clarify ImgU alignement requirements.
-	 */
-	config.width = 2560;
-	config.height = 1920;
-	config.pixelFormat = V4L2_PIX_FMT_NV12;
-	config.bufferCount = IPU3_BUFFER_COUNT;
-
-	configs[&data->outStream_] = config;
-	LOG(IPU3, Debug)
-		<< "Stream '" << data->outStream_.name_ << "' set to "
-		<< config.width << "x" << config.height << "-0x"
-		<< std::hex << std::setfill('0') << std::setw(8)
-		<< config.pixelFormat;
-
-	configs[&data->vfStream_] = config;
-	LOG(IPU3, Debug)
-		<< "Stream '" << data->vfStream_.name_ << "' set to "
-		<< config.width << "x" << config.height << "-0x"
-		<< std::hex << std::setfill('0') << std::setw(8)
-		<< config.pixelFormat;
-
-	return configs;
+	for (const StreamUsage &usage : usages) {
+		std::vector<IPU3Stream *>::iterator found;
+		StreamUsage::Role role = usage.role();
+		StreamConfiguration streamConfig = {};
+		IPU3Stream *stream = nullptr;
+
+		if (role == StreamUsage::Role::StillCapture) {
+			/*
+			 * We can use the viewfinder stream in case the
+			 * 'StillCapture' usage is required multiple times.
+			 */
+			if (streams.find(&data->outStream_) != streams.end())
+				stream = &data->outStream_;
+			else if (streams.find(&data->vfStream_) != streams.end())
+				stream = &data->vfStream_;
+			else
+				goto error;
+
+			/*
+			 * FIXME: Soraka: the maximum resolution reported by
+			 * both sensors (2592x1944 for ov5670 and 4224x3136 for
+			 * ov13858) are returned as default configurations but
+			 * they're not correctly processed by the ImgU.
+			 * Resolutions up tp 2560x1920 have been validated.
+			 *
+			 * \todo Clarify ImgU alignment requirements.
+			 */
+			streamConfig.width = 2560;
+			streamConfig.height = 1920;
+		} else if (role == StreamUsage::Role::Viewfinder ||
+			   role == StreamUsage::Role::VideoRecording) {
+			/*
+			 * We can't use the 'output' stream for viewfinder or
+			 * video capture usages.
+			 */
+			if (streams.find(&data->vfStream_) == streams.end())
+				goto error;
+
+			stream = &data->vfStream_;
+
+			streamConfig.width = usage.size().width;
+			streamConfig.height = usage.size().height;
+		}
+
+		streams.erase(stream);
+
+		streamConfig.pixelFormat = V4L2_PIX_FMT_NV12;
+		streamConfig.bufferCount = IPU3_BUFFER_COUNT;
+
+		cameraConfig[stream] = streamConfig;
+
+		LOG(IPU3, Debug)
+			<< "Stream '" << stream->name_ << "' format set to "
+			<< streamConfig.width << "x" << streamConfig.height
+			<< "-0x" << std::hex << std::setfill('0')
+			<< std::setw(8) << streamConfig.pixelFormat;
+	}
+
+	return cameraConfig;
+
+error:
+	LOG(IPU3, Error) << "Requested stream roles not supported";
+
+	return CameraConfiguration{};
 }
 
 int PipelineHandlerIPU3::configureStreams(Camera *camera,
