[libcamera-devel] [PATCH v5] cam: kms_sink: Remove limitation that camera and display must match

Laurent Pinchart laurent.pinchart at ideasonboard.com
Mon Jun 20 14:46:56 CEST 2022


Hi Eric,

On Mon, Jun 20, 2022 at 01:33:31PM +0100, Eric Curtin wrote:
> On Mon, 20 Jun 2022 at 13:00, Laurent Pinchart wrote:
> > On Mon, Jun 20, 2022 at 12:52:39PM +0100, Eric Curtin wrote:
> > > There is a limitation that requires input and output to be pixel
> > > for pixel identical in terms of height and width. Remove this
> > > limitation to enable more hardware that doesn't match. Just start
> > > drawing from top left 0, 0 corner. Try and pick the mode closest to the
> > > stream size.
> > >
> > > Suggested-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> > > Signed-off-by: Eric Curtin <ecurtin at redhat.com>
> > > Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> > > Tested-by: Eric Curtin <ecurtin at redhat.com>
> > > ---
> > > Changes in v5:
> > > - Tested Laurents suggested change successfully
> > > - Added to commit message about trying to pick closest
> >
> > I've also sent a v5, on Sunday (retaining your autorship of course). Did
> > I forget to CC you ?
> 
> Just tested that version exactly and it's perfect (and less code),
> feel free to add:
> 
> Tested-by: Eric Curtin <ecurtin at redhat.com>
> 
> to that one.

Thank you. I'll push the patch shortly.

> Sorry, I copy pasted code snippets from there to test, because I
> couldn't seem to find it on patchwork. Maybe it's about time I
> switched from using just git-send-email and gmail for email. I should
> probably set up some client that makes it easier for me to download
> patches w/o patchwork.

And we also need to setup a public-inbox instance for libcamera, so that
you could use b4 to download patches from the list.

> > > Changes in v4:
> > > - Change commit message to say top left
> > > - Spaces to tabs
> > >
> > > Changes in v3:
> > > - Much simplified version of the patch where we just attempt to
> > >   draw from point 0, 0. Only in the case where we do not find a
> > >   matching mode. Can expand to do centralization, scaling, etc.
> > >   in further patches if needs be.
> > >
> > > Changes in v2:
> > > - Tested and support drawing from negative pixel range
> > >   kernel parameter (video=960x540 at 60) was useful here
> > > ---
> > >  src/cam/kms_sink.cpp | 45 +++++++++++++++++++++++++++++++++++---------
> > >  1 file changed, 36 insertions(+), 9 deletions(-)
> > >
> > > diff --git a/src/cam/kms_sink.cpp b/src/cam/kms_sink.cpp
> > > index 7add81a6..7904bca8 100644
> > > --- a/src/cam/kms_sink.cpp
> > > +++ b/src/cam/kms_sink.cpp
> > > @@ -11,6 +11,7 @@
> > >  #include <algorithm>
> > >  #include <assert.h>
> > >  #include <iostream>
> > > +#include <limits.h>
> > >  #include <memory>
> > >  #include <stdint.h>
> > >  #include <string.h>
> > > @@ -112,6 +113,7 @@ int KMSSink::configure(const libcamera::CameraConfiguration &config)
> > >
> > >       const libcamera::StreamConfiguration &cfg = config.at(0);
> > >
> > > +     /* Find the best mode for the stream size. */
> > >       const std::vector<DRM::Mode> &modes = connector_->modes();
> > >       const auto iter = std::find_if(modes.begin(), modes.end(),
> > >                                      [&](const DRM::Mode &mode) {
> > > @@ -120,6 +122,32 @@ int KMSSink::configure(const libcamera::CameraConfiguration &config)
> > >                                      });
> > >       if (iter == modes.end()) {
> >
> > I think you could drop this search, as the iteration over the modes
> > below should be enough. Would you mind testing the v5 I posted ?
> >
> > >               std::cerr << "No mode matching " << cfg.size << std::endl;
> > > +
> > > +             unsigned int cfgArea = cfg.size.width * cfg.size.height;
> > > +             unsigned int bestDistance = UINT_MAX;
> > > +
> > > +             for (const DRM::Mode &mode : modes) {
> > > +                     unsigned int modeArea = mode.hdisplay * mode.vdisplay;
> > > +                     unsigned int distance = modeArea > cfgArea
> > > +                                                     ? modeArea - cfgArea
> > > +                                                     : cfgArea - modeArea;
> > > +
> > > +                     if (distance < bestDistance) {
> > > +                             mode_ = &mode;
> > > +                             bestDistance = distance;
> > > +
> > > +                             /*
> > > +                              * If the sizes match exactly, there will be no better
> > > +                              * match.
> > > +                              */
> > > +                             if (distance == 0)
> > > +                                     break;
> > > +                     }
> > > +             }
> > > +     }
> > > +
> > > +     if (!mode_) {
> > > +             std::cerr << "No modes\n";
> > >               return -EINVAL;
> > >       }
> > >
> > > @@ -127,7 +155,6 @@ int KMSSink::configure(const libcamera::CameraConfiguration &config)
> > >       if (ret < 0)
> > >               return ret;
> > >
> > > -     mode_ = &*iter;
> > >       size_ = cfg.size;
> > >       stride_ = cfg.stride;
> > >
> > > @@ -199,10 +226,10 @@ int KMSSink::configurePipeline(const libcamera::PixelFormat &format)
> > >               return ret;
> > >       }
> > >
> > > -     std::cout
> > > -             << "Using KMS plane " << plane_->id() << ", CRTC " << crtc_->id()
> > > -             << ", connector " << connector_->name()
> > > -             << " (" << connector_->id() << ")" << std::endl;
> > > +     std::cout << "Using KMS plane " << plane_->id() << ", CRTC "
> > > +               << crtc_->id() << ", connector " << connector_->name() << " ("
> > > +               << connector_->id() << "), mode " << mode_->hdisplay << "x"
> > > +               << mode_->vdisplay << "@" << mode_->vrefresh << std::endl;
> > >
> > >       return 0;
> > >  }
> > > @@ -295,12 +322,12 @@ bool KMSSink::processRequest(libcamera::Request *camRequest)
> > >               drmRequest->addProperty(plane_, "CRTC_ID", crtc_->id());
> > >               drmRequest->addProperty(plane_, "SRC_X", 0 << 16);
> > >               drmRequest->addProperty(plane_, "SRC_Y", 0 << 16);
> > > -             drmRequest->addProperty(plane_, "SRC_W", mode_->hdisplay << 16);
> > > -             drmRequest->addProperty(plane_, "SRC_H", mode_->vdisplay << 16);
> > > +             drmRequest->addProperty(plane_, "SRC_W", size_.width << 16);
> > > +             drmRequest->addProperty(plane_, "SRC_H", size_.height << 16);
> > >               drmRequest->addProperty(plane_, "CRTC_X", 0);
> > >               drmRequest->addProperty(plane_, "CRTC_Y", 0);
> > > -             drmRequest->addProperty(plane_, "CRTC_W", mode_->hdisplay);
> > > -             drmRequest->addProperty(plane_, "CRTC_H", mode_->vdisplay);
> > > +             drmRequest->addProperty(plane_, "CRTC_W", size_.width);
> > > +             drmRequest->addProperty(plane_, "CRTC_H", size_.height);
> > >
> > >               flags |= DRM::AtomicRequest::FlagAllowModeset;
> > >       }

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list