[libcamera-devel] [PATCH 6/6] cam: add --format option to configure a stream
Niklas Söderlund
niklas.soderlund at ragnatech.se
Tue Jan 29 14:34:26 CET 2019
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
>
> > +
> > 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.
>
>
> > + }
> > +out:
> > delete loop;
> >
> > cm->stop();
> >
>
> --
> Regards
> --
> Kieran
--
Regards,
Niklas Söderlund
More information about the libcamera-devel
mailing list