[libcamera-devel] [PATCH 6/6] cam: add --format option to configure a stream

Kieran Bingham kieran.bingham at ideasonboard.com
Tue Jan 29 10:29:37 CET 2019


Hi Niklas,

On 28/01/2019 00:41, Niklas Söderlund wrote:
> Add a option to configure the first stream of a camera from an argument
> with options and parse the width, height and pixel format from that
> list.
> 
> The pixel format is still specified as a integer which should correspond
> to the kernels FOURCC identifiers. Going forward this should be turned
> into a string representation and the cam parser should translate between
> the two.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
> ---
>  src/cam/main.cpp | 104 +++++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 92 insertions(+), 12 deletions(-)
> 
> diff --git a/src/cam/main.cpp b/src/cam/main.cpp
> index bde47a8f17983912..4b4ce9aa29c80bd1 100644
> --- a/src/cam/main.cpp
> +++ b/src/cam/main.cpp
> @@ -20,7 +20,8 @@ using namespace libcamera;
>  OptionsParser::Options options;
>  
>  enum {
> -	OptCamera = 'c',
> +	OptCamera = 'C',
> +	OptFormat = 'f',
>  	OptHelp = 'h',
>  	OptList = 'l',
>  };
> @@ -35,10 +36,20 @@ void signalHandler(int signal)
>  
>  static int parseOptions(int argc, char *argv[])
>  {
> +	KeyValueParser formatKeyValue;
> +	formatKeyValue.addOption("width", "Set width in pixels",
> +				 ArgumentRequired, "w");
> +	formatKeyValue.addOption("height", "Set height in pixels",
> +				 ArgumentRequired, "h");
> +	formatKeyValue.addOption("pixelformat", "Set pixel format",
> +				 ArgumentRequired, "pf");

Hrm - can a short-option have two letters? (if so, should it?)

> +
>  	OptionsParser parser;
>  
>  	parser.addOption(OptCamera, "Specify which camera to operate on",
>  			 "camera", ArgumentRequired, "camera");
> +	parser.addOption(OptFormat, "Set format of the cameras first stream",
> +			 formatKeyValue, "format");
>  	parser.addOption(OptHelp, "Display this help message", "help");
>  	parser.addOption(OptList, "List all cameras", "list");
>  
> @@ -54,6 +65,42 @@ static int parseOptions(int argc, char *argv[])
>  	return 0;
>  }
>  
> +int str2uint(std::string str, unsigned int *dest)
> +{
> +	if (!dest || str == "" || !sscanf(str.c_str(), "%d", dest))
> +		return -EINVAL;
> +	return 0;
> +}
> +
> +bool configureStreams(Camera *camera, std::vector<Stream> &streams)
> +{
> +	if (!options.isKeyValue(OptFormat))
> +		return false;
> +
> +	KeyValueParser::Options format = options.keyValues(OptFormat);
> +
> +	std::map<unsigned int, StreamConfiguration> config = camera->streamConfiguration(streams);
> +	unsigned int id = streams.front().id();
> +
> +	if (format.isSet("width"))
> +		if (str2uint(format["width"], &config[id].width))
> +			return false;
> +
> +	if (format.isSet("height"))
> +		if (str2uint(format["height"], &config[id].height))
> +			return false;
> +
> +	/* TODO: Translate 4CC string to ID. */
> +	if (format.isSet("pixelformat"))
> +		if (str2uint(format["pixelformat"], &config[id].pixelFormat))
> +			return false;
> +
> +	if (camera->configureStreams(config))
> +		return false;
> +
> +	return true;
> +}
> +
>  int main(int argc, char **argv)
>  {
>  	int ret;
> @@ -63,6 +110,8 @@ int main(int argc, char **argv)
>  		return EXIT_FAILURE;
>  
>  	CameraManager *cm = CameraManager::instance();
> +	std::shared_ptr<Camera> camera;
> +	std::vector<Stream> streams;
>  
>  	ret = cm->start();
>  	if (ret) {
> @@ -71,31 +120,62 @@ int main(int argc, char **argv)
>  		return EXIT_FAILURE;
>  	}
>  
> +	loop = new EventLoop(cm->eventDispatcher());
> +
> +	struct sigaction sa = {};
> +	sa.sa_handler = &signalHandler;
> +	sigaction(SIGINT, &sa, nullptr);
> +
>  	if (options.isSet(OptList)) {
>  		std::cout << "Available cameras:" << std::endl;
> -		for (const std::shared_ptr<Camera> &camera : cm->cameras())
> -			std::cout << "- " << camera->name() << std::endl;
> +		for (const std::shared_ptr<Camera> &cam : cm->cameras())
> +			std::cout << "- " << cam->name() << std::endl;
>  	}
>  
>  	if (options.isSet(OptCamera)) {
> -		std::shared_ptr<Camera> cam = cm->get(options[OptCamera]);
> -
> -		if (cam) {
> -			std::cout << "Using camera " << cam->name() << std::endl;
> -		} else {
> +		camera = cm->get(options[OptCamera]);
> +		if (!camera) {
>  			std::cout << "Camera " << options[OptCamera]
>  				  << " not found" << std::endl;
> +			goto out;
> +		}
> +
> +		streams = camera->streams();
> +		if (streams.size() != 1) {
> +			std::cout << "Camera have " << streams.size()

Camera 'has' N streams...

> +				  << " streams, I only know how to work with 1"
> +				  << std::endl;
> +			goto out;
> +		}
> +
> +		if (camera->acquire()) {
> +			std::cout << "Failed to acquire camera" << std::endl;
> +			goto out;
>  		}
> +
> +		std::cout << "Using camera " << camera->name() << std::endl;
>  	}
>  
> -	loop = new EventLoop(cm->eventDispatcher());
> +	if (options.isSet(OptFormat)) {
> +		if (!camera) {
> +			std::cout << "Can't configure stream, no camera selected" << std::endl;
> +			goto out_camera;
> +		}
>  
> -	struct sigaction sa = {};
> -	sa.sa_handler = &signalHandler;
> -	sigaction(SIGINT, &sa, nullptr);
> +		if (!configureStreams(camera.get(), streams)) {
> +			std::cout << "Failed to configure camera" << std::endl;
> +			goto out_camera;
> +		}
> +	}
>  
>  	ret = loop->exec();
>  
> +out_camera:
> +	if (camera) {
> +		camera->release();
> +		camera.reset();

Uhm ... first a pointer call '->' then a direct member call ? '.' ?


> +	}
> +out:
>  	delete loop;
>  
>  	cm->stop();
> 

-- 
Regards
--
Kieran


More information about the libcamera-devel mailing list