[libcamera-devel] [PATCH v3 09/11] libcamera: pipeline: Add a simple pipeline handler

Andrey Konovalov andrey.konovalov at linaro.org
Wed Apr 8 19:52:00 CEST 2020


Hi Laurent,

On 04.04.2020 03:08, Laurent Pinchart wrote:
> Hi Andrey,
> 
> On Fri, Apr 03, 2020 at 04:55:32PM +0300, Andrey Konovalov wrote:
>> On 20.03.2020 04:48, Laurent Pinchart wrote:
>>> From: Martijn Braam <martijn at brixit.nl>
>>>
>>> This new pipeline handler aims at supporting any simple device without
>>> requiring any device-specific code. Simple devices are currently defined
>>> as a graph made of one or multiple camera sensors and a single video
>>> node, with each sensor connected to the video node through a linear
>>> pipeline.
>>>
>>> The simple pipeline handler will automatically parse the media graph,
>>> enumerate sensors, build supported stream configurations, and configure
>>> the pipeline, without any device-specific knowledge. It doesn't support
>>> configuration of any processing in the pipeline at the moment, but may
>>> be extended to support simple processing such as format conversion or
>>> scaling in the future.
>>>
>>> The only device-specific information in the pipeline handler is the list
>>> of supported drivers, required for device matching. We may be able to
>>> remove this in the future by matching with the simple pipeline handler
>>> as a last resort option, after all other pipeline handlers have been
>>> tried.
>>>
>>> Signed-off-by: Martijn Braam <martijn at brixit.nl>
>>> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
>>> ---
>>> Changes since v2:
>>>
>>> - Log an error when setupFormats() fail
>>> - Propagate getFormat() and setFormat() errors to the caller of
>>>     setupFormats()
>>> - Reorder variable declarations in validate()
>>> - Add \todo comment related to the selection of the default format
>>> - Use log Error instead of Info if pipeline isn't valid
>>> - Rebase on top of V4L2PixelFormat
>>>
>>> Changes since v1:
>>>
>>> - Rebase on top of buffer API rework
>>> - Expose stream formats
>>> - Rework camera data config
>>> ---
>>>    src/libcamera/pipeline/meson.build        |   1 +
>>>    src/libcamera/pipeline/simple/meson.build |   3 +
>>>    src/libcamera/pipeline/simple/simple.cpp  | 710 ++++++++++++++++++++++
>>>    3 files changed, 714 insertions(+)
>>>    create mode 100644 src/libcamera/pipeline/simple/meson.build
>>>    create mode 100644 src/libcamera/pipeline/simple/simple.cpp
>>>
>>> diff --git a/src/libcamera/pipeline/meson.build b/src/libcamera/pipeline/meson.build
>>> index 0d466225a72e..606ba31a0319 100644
>>> --- a/src/libcamera/pipeline/meson.build
>>> +++ b/src/libcamera/pipeline/meson.build
>>> @@ -5,3 +5,4 @@ libcamera_sources += files([
>>>    
>>>    subdir('ipu3')
>>>    subdir('rkisp1')
>>> +subdir('simple')
>>> diff --git a/src/libcamera/pipeline/simple/meson.build b/src/libcamera/pipeline/simple/meson.build
>>> new file mode 100644
>>> index 000000000000..4945a3e173cf
>>> --- /dev/null
>>> +++ b/src/libcamera/pipeline/simple/meson.build
>>> @@ -0,0 +1,3 @@
>>> +libcamera_sources += files([
>>> +    'simple.cpp',
>>> +])
>>> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
>>> new file mode 100644
>>> index 000000000000..545a99fe31ca
>>> --- /dev/null
>>> +++ b/src/libcamera/pipeline/simple/simple.cpp

<snip>

>>> +	if (video_->caps().isMultiplanar()) {
>>> +		LOG(SimplePipeline, Error)
>>> +			<< "V4L2 multiplanar devices are not supported";
>>> +		return false;
>>
>> Same here. For the same reasons.
> 
> Do you mean that your multiplanar device works with this series ?

qcom-camss uses multiplanar API for single-planar formats
(just like the current RPi's unicam driver iirc).

And on db410c with ov5640 sensor this works with this series
(if I am not trying to fix the enumeration of pipeline configurations).

Though (as it worked as is) I didn't check how exactly this happened.
Maybe I'll get better understanding of the details now that I am trying to figure out
why BA81 isn't currently working for me (see my earlier email today).


Thanks,
Andrey

>>> +	}
>>> +
>>> +	video_->bufferReady.connect(this, &SimplePipelineHandler::bufferReady);
>>> +
>>> +	/*
>>> +	 * Create one camera data instance for each sensor and gather all
>>> +	 * entities in all pipelines.
>>> +	 */
>>> +	std::vector<std::unique_ptr<SimpleCameraData>> pipelines;
>>> +	std::set<MediaEntity *> entities;
>>> +
>>> +	pipelines.reserve(sensors.size());
>>> +
>>> +	for (MediaEntity *sensor : sensors) {
>>> +		std::unique_ptr<SimpleCameraData> data =
>>> +			std::make_unique<SimpleCameraData>(this, sensor,
>>> +							   videos[0]);
>>> +		if (!data->isValid()) {
>>> +			LOG(SimplePipeline, Error)
>>> +				<< "No valid pipeline for sensor '"
>>> +				<< sensor->name() << "', skipping";
>>> +			continue;
>>> +		}
>>> +
>>> +		for (SimpleCameraData::Entity &entity : data->entities_)
>>> +			entities.insert(entity.entity);
>>> +
>>> +		pipelines.push_back(std::move(data));
>>> +	}
>>> +
>>> +	if (entities.empty())
>>> +		return false;
>>> +
>>> +	/* Create and open V4L2Subdev instances for all the entities. */
>>> +	for (MediaEntity *entity : entities) {
>>> +		auto elem = subdevs_.emplace(std::piecewise_construct,
>>> +					     std::forward_as_tuple(entity),
>>> +					     std::forward_as_tuple(entity));
>>> +		V4L2Subdevice *subdev = &elem.first->second;
>>> +		int ret = subdev->open();
>>> +		if (ret < 0) {
>>> +			LOG(SimplePipeline, Error)
>>> +				<< "Failed to open " << subdev->deviceNode()
>>> +				<< ": " << strerror(-ret);
>>> +			return false;
>>> +		}
>>> +	}
>>> +
>>> +	/* Initialize each pipeline and register a corresponding camera. */
>>> +	for (std::unique_ptr<SimpleCameraData> &data : pipelines) {
>>> +		int ret = data->init();
>>> +		if (ret < 0)
>>> +			continue;
>>> +
>>> +		std::shared_ptr<Camera> camera =
>>> +			Camera::create(this, data->sensor_->entity()->name(),
>>> +				       data->streams());
>>> +		registerCamera(std::move(camera), std::move(data));
>>> +	}
>>> +
>>> +	return true;
>>> +}
>>> +
>>> +V4L2Subdevice *SimplePipelineHandler::subdev(const MediaEntity *entity)
>>> +{
>>> +	auto iter = subdevs_.find(entity);
>>> +	if (iter == subdevs_.end())
>>> +		return nullptr;
>>> +
>>> +	return &iter->second;
>>> +}
>>> +
>>> +/* -----------------------------------------------------------------------------
>>> + * Buffer Handling
>>> + */
>>> +
>>> +void SimplePipelineHandler::bufferReady(FrameBuffer *buffer)
>>> +{
>>> +	ASSERT(activeCamera_);
>>> +	Request *request = buffer->request();
>>> +	completeBuffer(activeCamera_, request, buffer);
>>> +	completeRequest(activeCamera_, request);
>>> +}
>>> +
>>> +REGISTER_PIPELINE_HANDLER(SimplePipelineHandler);
>>> +
>>> +} /* namespace libcamera */
> 


More information about the libcamera-devel mailing list