diff --git a/src/cam/main.cpp b/src/cam/main.cpp
index d3f1f341d44e7f98..1bf28ca8eb8c6da7 100644
--- a/src/cam/main.cpp
+++ b/src/cam/main.cpp
@@ -7,6 +7,7 @@
 
 #include <iomanip>
 #include <iostream>
+#include <limits.h>
 #include <map>
 #include <signal.h>
 #include <string.h>
@@ -17,6 +18,8 @@
 #include "event_loop.h"
 #include "options.h"
 
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
 using namespace libcamera;
 
 OptionsParser::Options options;
@@ -42,6 +45,9 @@ void signalHandler(int signal)
 static int parseOptions(int argc, char *argv[])
 {
 	KeyValueParser streamKeyValue;
+	streamKeyValue.addOption("hint", OptionString,
+				 "Usage hint for the stream (viewfinder, video, still)",
+				 ArgumentRequired);
 	streamKeyValue.addOption("width", OptionInteger, "Width in pixels",
 				 ArgumentRequired);
 	streamKeyValue.addOption("height", OptionInteger, "Height in pixels",
@@ -61,7 +67,7 @@ static int parseOptions(int argc, char *argv[])
 			 "The default file name is 'frame-#.bin'.",
 			 "file", ArgumentOptional, "filename");
 	parser.addOption(OptStream, &streamKeyValue,
-			 "Set configuration of the camera's streams", "stream");
+			 "Set configuration of the camera's streams", "stream", true);
 	parser.addOption(OptHelp, OptionNone, "Display this help message",
 			 "help");
 	parser.addOption(OptList, OptionNone, "List all cameras", "list");
@@ -80,12 +86,48 @@ static int parseOptions(int argc, char *argv[])
 
 static int prepare_camera_config(std::map<Stream *, StreamConfiguration> *config)
 {
-	std::set<Stream *> streams = camera->streams();
-	*config = camera->streamConfiguration({ Video() });
-	Stream *stream = config->begin()->first;
+	std::vector<StreamHint> hints;
 
-	if (options.isSet(OptStream)) {
-		KeyValueParser::Options conf = options[OptStream];
+	/* If no configuration is provided assume a single video stream. */
+	if (!options.isSet(OptStream)) {
+		*config = camera->streamConfiguration({ Video() });
+		return 0;
+	}
+
+	/* Use hints and get a default configuration. */
+	for (auto const &value : options[OptStream].toArray()) {
+		KeyValueParser::Options conf = value.toKeyValues();
+
+		if (!conf.isSet("hint"))
+			hints.push_back(Video());
+		else if (conf["hint"].toString() == "viewfinder")
+			hints.push_back(Viewfinder(conf["width"],
+						   conf["height"]));
+		else if (conf["hint"].toString() == "video")
+			hints.push_back(Video());
+		else if (conf["hint"].toString() == "still")
+			hints.push_back(Still());
+		else {
+			std::cerr << "Unknown stream hint "
+				  << conf["hint"].toString() << std::endl;
+			return -EINVAL;
+		}
+	}
+
+	*config = camera->streamConfiguration(hints);
+
+	if (config->size() != options[OptStream].toArray().size()) {
+		std::cerr << "Failed to get default stream configuration"
+			  << std::endl;
+		return -EINVAL;
+	}
+
+	/* Apply configuration explicitly requested. */
+	std::map<Stream *, StreamConfiguration>::iterator it = config->begin();
+	for (auto const &value : options[OptStream].toArray()) {
+		KeyValueParser::Options conf = value.toKeyValues();
+		Stream *stream = it->first;
+		it++;
 
 		if (conf.isSet("width"))
 			(*config)[stream].width = conf["width"];
@@ -137,7 +179,6 @@ static void requestComplete(Request *request, const std::map<Stream *, Buffer *>
 static int capture()
 {
 	std::map<Stream *, StreamConfiguration> config;
-	std::vector<Request *> requests;
 	int ret;
 
 	ret = prepare_camera_config(&config);
@@ -152,8 +193,6 @@ static int capture()
 		return ret;
 	}
 
-	Stream *stream = config.begin()->first;
-
 	ret = camera->allocateBuffers();
 	if (ret) {
 		std::cerr << "Failed to allocate buffers"
@@ -163,9 +202,18 @@ static int capture()
 
 	camera->requestCompleted.connect(requestComplete);
 
-	BufferPool &pool = stream->bufferPool();
+	/* Figure out which stream have least number of buffers. */
+	unsigned int nbuffers = UINT_MAX;
+	for (auto const &it : config)
+		nbuffers = MIN(nbuffers, it.first->bufferPool().count());
 
-	for (Buffer &buffer : pool.buffers()) {
+	/*
+	 * TODO: make cam tool smarter to support still capture by for
+	 * example pushing a button. For now run all streams all the time.
+	 */
+
+	std::vector<Request *> requests;
+	for (unsigned int i = 0; i < nbuffers; i++) {
 		Request *request = camera->createRequest();
 		if (!request) {
 			std::cerr << "Can't create request" << std::endl;
@@ -174,7 +222,11 @@ static int capture()
 		}
 
 		std::map<Stream *, Buffer *> map;
-		map[stream] = &buffer;
+		for (auto const &it : config) {
+			Stream *stream = it.first;
+			map[stream] = &stream->bufferPool().buffers()[i];
+		}
+
 		ret = request->setBuffers(map);
 		if (ret < 0) {
 			std::cerr << "Can't set buffers for request" << std::endl;
