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

Kieran Bingham kieran.bingham at ideasonboard.com
Tue Jan 29 14:39:59 CET 2019


Hi Niklas,

On 29/01/2019 13:34, Niklas Söderlund wrote:
> Hi Kieran,
> 
> Thanks for your comment.
> 
> On 2019-01-29 09:29:37 +0000, Kieran Bingham wrote:
>> 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?)
> 
> This is not a shot-option :-) It is a descriptive name for the parameter 
> only used for printing the usage. The usage printing for the whole 
> --format options:
> 
>   -f, --format key=value[,key=value,...]        Set format of the cameras first stream
>                                                 height=h                Set height in pixels
>                                                 pixelformat=pf          Set pixel format
>                                                 width=w                 Set width in pixels
> 
> And one would use it as --format width=800,pixelformat=42

Ah - that's clear - this is fine then.

> 
>>
>>> +
>>>  	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...
> 
> Thanks :-)
> 
>>
>>> +				  << " 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 ? '.' ?
> 
> camera is a shard_ptr<Camera*> so the ->release() access the Camera 
> pointers that the shard_ptr<> holds while .reset() clears the 
> shard_ptr<> of the reference to the Camera hence reducing the refcount 
> by one and potentialy deleting the Camera object. 


Of course :) Ok - no issues there either then!
--
Kieran


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

-- 
Regards
--
Kieran


More information about the libcamera-devel mailing list