[libcamera-devel] [PATCH v2] libcamera: pipeline: simple: Support camera sensors that contain an ISP

Dafna Hirschfeld dafna.hirschfeld at collabora.com
Wed Mar 3 15:21:08 CET 2021


Hi,

On 03.03.21 00:53, 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>
> ---
> Changes since v1:
> 
> - Fix link handling
> ---
>   src/libcamera/pipeline/simple/simple.cpp | 88 ++++++++++++++++++++----
>   1 file changed, 75 insertions(+), 13 deletions(-)
> 
> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
> index 36f55e8709f1..aa6155f0596f 100644
> --- a/src/libcamera/pipeline/simple/simple.cpp
> +++ b/src/libcamera/pipeline/simple/simple.cpp
> @@ -245,6 +245,8 @@ private:
>   			PipelineHandler::cameraData(camera));
>   	}
>   
> +	std::vector<MediaEntity *> locateSensors();
> +
>   	void bufferReady(FrameBuffer *buffer);
>   	void converterInputDone(FrameBuffer *buffer);
>   	void converterOutputDone(FrameBuffer *buffer);
> @@ -869,6 +871,78 @@ 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 ||
> +			    !(l->flags() & MEDIA_LNK_FL_IMMUTABLE)) {

Same issue as discussed in the irc, this condition is always true.

Thanks,
Dafna

> +				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;
> @@ -892,19 +966,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;
> 


More information about the libcamera-devel mailing list