[libcamera-devel] [PATCH/RFC] libcamera: pipeline: simple: Support camera sensors that contain an ISP
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Mon Feb 8 17:19:31 CET 2021
Hi Jacopo,
On Mon, Feb 08, 2021 at 05:08:25PM +0100, Jacopo Mondi wrote:
> On Mon, Feb 08, 2021 at 05:15:58PM +0200, Laurent Pinchart wrote:
> > Camera sensors can include an ISP. For instance, the AP1302 external ISP
> > can be connected to up to two raw camera sensors, and the combination of
> > the sensors and ISP is considered as a (smart) camera sensor from
> > libcamera's point of view.
> >
> > The CameraSensor class has limited support for this already. Extend the
> > simple pipeline handler to support such sensors, by using the media
> > entity corresponding to the ISP instead of the raw camera sensor's
> > entity.
> >
> > We don't need to handle the case where an entity in the SoC would expose
> > the MEDIA_ENT_F_PROC_VIDEO_ISP function, as pipeline containing an ISP
> > would have a dedicated pipeline handler.
> >
> > The implementation is limited as it won't support other multi-entity
> > camera sensors (such as CCS). While this would be worth supporting, we
> > don't have a test platform with a CCS-compatible sensor at this point,
> > so let's not over-engineer the solution. Extending support to CCS (and
> > possibly other sensor topologies) will likely involve helpers that can
> > be used by other pipeline handlers (such as generic graph walk helpers
> > for instance) and extensions to the CameraSensor class.
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> > ---
> > src/libcamera/pipeline/simple/simple.cpp | 87 ++++++++++++++++++++----
> > 1 file changed, 74 insertions(+), 13 deletions(-)
> >
> > This patch depends on "[PATCH/RFC] libcamera: camera_sensor: Accept
> > entities exposing the ISP function" ([1]). It has been tested on a
> > MediaTek Pumpkin i500 board with an ON Semiconductor AP1302 and AR0330
> > and AR0144 sensors.
> >
> > [1] https://patchwork.libcamera.org/patch/11182/
>
> Doesn't it depend on the introduction of such entity function in
> kernel space too ?
Yes it does. That's scheduled for v5.12-rc1.
> Also, I'm not sure if the model for sensor that expose multiple
> entities has really been finalized. In example I don't see any driver
> for those sensors in mainline. Am I mistaken ?
You're not. The AP1302 driver should be posted soon. I wanted to get
this patch out as an RFC first to see if there was a general agreement
on the direction and approach, and I'll maintain it out of tree as long
as needed.
> > diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
> > index 9d468f7c9cc4..2df33a3a79ea 100644
> > --- a/src/libcamera/pipeline/simple/simple.cpp
> > +++ b/src/libcamera/pipeline/simple/simple.cpp
> > @@ -240,6 +240,8 @@ private:
> > PipelineHandler::cameraData(camera));
> > }
> >
> > + std::vector<MediaEntity *> locateSensors();
> > +
> > void bufferReady(FrameBuffer *buffer);
> > void converterInputDone(FrameBuffer *buffer);
> > void converterOutputDone(FrameBuffer *buffer);
> > @@ -865,6 +867,77 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request)
> > * Match and Setup
> > */
> >
> > +std::vector<MediaEntity *> SimplePipelineHandler::locateSensors()
> > +{
> > + std::vector<MediaEntity *> entities;
> > +
> > + /*
> > + * Gather all the camera sensor entities based on the function they
> > + * expose.
> > + */
> > + for (MediaEntity *entity : media_->entities()) {
> > + if (entity->function() == MEDIA_ENT_F_CAM_SENSOR)
> > + entities.push_back(entity);
> > + }
> > +
> > + if (entities.empty())
> > + return {};
> > +
> > + /*
> > + * Sensors can be made of multiple entities. For instance, a raw sensor
> > + * can be connected to an ISP, and the combination of both should be
> > + * treated as one sensor. To support this, as a crude heuristic, check
> > + * the downstream entity from the camera sensor, and if it is an ISP,
> > + * use it instead of the sensor.
> > + */
> > + std::vector<MediaEntity *> sensors;
> > +
> > + for (MediaEntity *entity : entities) {
> > + /*
> > + * Locate the downstream entity by following the first enabled
> > + * link from a source pad.
> > + */
> > + const MediaPad *pad = nullptr;
> > + const MediaLink *link = nullptr;
> > +
> > + for (const MediaPad *p : entity->pads()) {
> > + if (p->flags() & MEDIA_PAD_FL_SOURCE) {
> > + pad = p;
> > + break;
> > + }
> > + }
> > +
> > + if (!pad)
> > + continue;
> > +
> > + for (const MediaLink *l : pad->links()) {
> > + if (l->flags() & MEDIA_LNK_FL_ENABLED) {
> > + link = l;
> > + break;
> > + }
> > + }
> > +
> > + if (!link)
> > + continue;
> > +
> > + MediaEntity *remote = link->sink()->entity();
> > + if (remote->function() == MEDIA_ENT_F_PROC_VIDEO_ISP)
> > + sensors.push_back(remote);
> > + else
> > + sensors.push_back(entity);
> > + }
> > +
> > + /*
> > + * Remove duplicates, in case multiple sensors are connected to the
> > + * same ISP.
> > + */
> > + std::sort(sensors.begin(), sensors.end());
> > + auto last = std::unique(sensors.begin(), sensors.end());
> > + sensors.erase(last, sensors.end());
> > +
> > + return sensors;
> > +}
> > +
> > bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
> > {
> > const SimplePipelineInfo *info = nullptr;
> > @@ -888,19 +961,7 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
> > }
> >
> > /* Locate the sensors. */
> > - std::vector<MediaEntity *> sensors;
> > -
> > - for (MediaEntity *entity : media_->entities()) {
> > - switch (entity->function()) {
> > - case MEDIA_ENT_F_CAM_SENSOR:
> > - sensors.push_back(entity);
> > - break;
> > -
> > - default:
> > - break;
> > - }
> > - }
> > -
> > + std::vector<MediaEntity *> sensors = locateSensors();
> > if (sensors.empty()) {
> > LOG(SimplePipeline, Error) << "No sensor found";
> > return false;
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list