[libcamera-devel] [PATCH v3 4/5] cam: Extend request completion handler to deal with multiple streams
Niklas Söderlund
niklas.soderlund at ragnatech.se
Mon Apr 8 15:24:30 CEST 2019
Hi Laurent,
Thanks for your feedback.
On 2019-04-06 20:23:40 +0300, Laurent Pinchart wrote:
> Hi Niklas,
>
> Thank you for the patch.
>
> On Sat, Apr 06, 2019 at 01:59:28AM +0200, Niklas Söderlund wrote:
> > The completion handler needs to handle all buffers in the request. Solve
> > this by iterating over all buffers in the completed request. The streams
> > are named automatically streamX, where X is the order of how the stream
>
> s/how/which/
>
> > was passed to configureStream().
> >
> > Signed-off-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
> > ---
> > src/cam/main.cpp | 39 +++++++++++++++++++++++++++------------
> > 1 file changed, 27 insertions(+), 12 deletions(-)
> >
> > diff --git a/src/cam/main.cpp b/src/cam/main.cpp
> > index da05612b1c347b31..da5ca3402ce1a823 100644
> > --- a/src/cam/main.cpp
> > +++ b/src/cam/main.cpp
> > @@ -23,6 +23,7 @@ using namespace libcamera;
> >
> > OptionsParser::Options options;
> > std::shared_ptr<Camera> camera;
> > +std::map<Stream *, std::string> streamInfo;
> > EventLoop *loop;
> > BufferWriter *writer;
>
> Unrelated to this patch, we should really create a class to hold all
> this.
I agree, I feel bad when I have to add to this hack. I will try to find
time to rework this in a follow up patch.
>
> >
> > @@ -87,9 +88,12 @@ static int prepareCameraConfig(CameraConfiguration *config)
> > {
> > std::vector<StreamUsage> roles;
> >
> > + streamInfo.clear();
> > +
> > /* If no configuration is provided assume a single video stream. */
> > if (!options.isSet(OptStream)) {
> > *config = camera->streamConfiguration({ Stream::VideoRecording() });
> > + streamInfo[config->front()] = "stream0";
> > return 0;
> > }
> >
> > @@ -142,31 +146,42 @@ static int prepareCameraConfig(CameraConfiguration *config)
> > (*config)[stream].pixelFormat = conf["pixelformat"];
> > }
> >
> > + for (unsigned int i = 0; i < config->size(); i++)
> > + streamInfo[(*config)[i]] = "stream" + std::to_string(i);
>
> How about using iterators ?
>
> index = 0;
> for (Stream *stream : *config) {
> streamInfo[stream] = "stream" + std::to_string(index);
> index++;
> }
Sure.
>
> > +
> > return 0;
> > }
> >
> > static void requestComplete(Request *request, const std::map<Stream *, Buffer *> &buffers)
> > {
> > static uint64_t last = 0;
> > + double fps = 0.0;
> >
> > if (request->status() == Request::RequestCancelled)
> > return;
> >
> > - Buffer *buffer = buffers.begin()->second;
> > + for (auto it = buffers.begin(); it != buffers.end(); ++it) {
> > + Stream *stream = it->first;
> > + Buffer *buffer = it->second;
> > + std::string name = streamInfo[stream];
> >
> > - double fps = buffer->timestamp() - last;
> > - fps = last && fps ? 1000000000.0 / fps : 0.0;
> > - last = buffer->timestamp();
> > + if (it == buffers.begin()) {
> > + fps = buffer->timestamp() - last;
> > + fps = last && fps ? 1000000000.0 / fps : 0.0;
> > + last = buffer->timestamp();
> > + }
> >
> > - std::cout << "seq: " << std::setw(6) << std::setfill('0') << buffer->sequence()
> > - << " buf: " << buffer->index()
> > - << " bytesused: " << buffer->bytesused()
> > - << " timestamp: " << buffer->timestamp()
> > - << " fps: " << std::fixed << std::setprecision(2) << fps
> > - << std::endl;
> > + std::cout << name << " seq: " << std::setw(6)
> > + << std::setfill('0') << buffer->sequence()
> > + << " buf: " << buffer->index()
> > + << " bytesused: " << buffer->bytesused()
> > + << " timestamp: " << buffer->timestamp()
> > + << " fps: " << std::fixed << std::setprecision(2) << fps
>
> As the fps is per-request and not per-stream we should ideally print it
> once only. One option would be to print a single line per request that
> contains per-request information as well as per-stream information for
> each stream, but that may be difficult to read. Another option would be
> to first print per-request information, and then one line for each
> stream. This may be best, otherwise the log
>
> stream0 seq:...
> stream1 seq:...
>
> could be understood as either one request containing both streams, or
> two requests containing stream0 and stream1 respectively.
>
> I'm tempted to see if we could go for the single line per request
> option while keeping it readable enough.
I had an attempt of makig this a single line, lets see how it plays out.
>
> > + << std::endl;
> >
> > - if (writer)
> > - writer->write(buffer, "stream0");
> > + if (writer)
> > + writer->write(buffer, name);
> > + }
> >
> > request = camera->createRequest();
> > if (!request) {
>
> --
> Regards,
>
> Laurent Pinchart
--
Regards,
Niklas Söderlund
More information about the libcamera-devel
mailing list