[libcamera-devel] [PATCH 04/10] libcamera: ipu3: Breakout stream assignment to new function

Laurent Pinchart laurent.pinchart at ideasonboard.com
Fri Jun 5 23:58:02 CEST 2020


Hello,

On Tue, Jun 02, 2020 at 11:53:58AM +0200, Jacopo Mondi wrote:
> On Tue, Jun 02, 2020 at 03:39:03AM +0200, Niklas Söderlund wrote:
> > Picking which stream that is most suitable for the requested
> 
> s/Picking/Selecting
> s/that is/is the/
> 
> > configuration is mixed with adjusting the requested format when
> > validating configurations. This is hard to read and got worse when
> > support for Bayer formats where added, break it out into a separate
>
> s/where/were or better, was

And s/into/to/

> > function.
> >
> > Signed-off-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
> > ---
> >  src/libcamera/pipeline/ipu3/ipu3.cpp | 87 +++++++++++++++++-----------
> >  1 file changed, 53 insertions(+), 34 deletions(-)
> >
> > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> > index f7363244e1d2d0ff..0e7555c716b36749 100644
> > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> > @@ -190,6 +190,7 @@ private:
> >  	static constexpr unsigned int IPU3_BUFFER_COUNT = 4;
> >  	static constexpr unsigned int IPU3_MAX_STREAMS = 3;
> >
> > +	int updateStreams();
> >  	void adjustStream(StreamConfiguration &cfg, bool scale);
> >
> >  	/*
> > @@ -256,6 +257,51 @@ IPU3CameraConfiguration::IPU3CameraConfiguration(Camera *camera,
> >  	data_ = data;
> >  }
> >
> > +int IPU3CameraConfiguration::updateStreams()

Should this be called assignStreams() ?

> > +{
> > +	std::set<const IPU3Stream *> availableStreams = {
> > +		&data_->outStream_,
> > +		&data_->vfStream_,
> > +		&data_->rawStream_,
> > +	};
> > +
> > +	/* Pick the stream most suitable for the requested configuration. */
> > +	std::vector<const IPU3Stream *> streams;
> > +	for (unsigned int i = 0; i < config_.size(); ++i) {
> 
> Can't you iterate on config_ ?
> 
> > +		const StreamConfiguration &cfg = config_[i];
> > +		const IPU3Stream *stream;
> > +
> > +		/*
> > +		 * Only the raw stream can support Bayer formats.
> 
> Fits in one line
> 
> > +		 */
> > +		if (cfg.pixelFormat.modifier() == IPU3_FORMAT_MOD_PACKED)
> > +			stream = &data_->rawStream_;
> Emply line ?
> 
> > +		/*
> > +		 * Output stream can't scale so can only be used if the size
> > +		 * matches the size of the sensor.
> > +		 *
> > +		 * NOTE: It can crop but is not supported.
> 
> \todo ?
> 
> And I would keep the original comment. We can crop, the issue is that
> the FOV will be reduce when asking for a lower resolution than the
> one of the frame input the IMGU if I'm not mistaken.
> 
> > +		 */
> > +		else if (cfg.size == sensorFormat_.size)
> > +			stream = &data_->outStream_;
> > +		/*
> > +		 * Pick the view finder stream last as it may scale.
> 
> fits in one line ?
> 
> > +		 */
> > +		else
> > +			stream = &data_->vfStream_;
> > +
> > +		if (availableStreams.find(stream) == availableStreams.end())
> > +			return -EINVAL;
> 
> Is this right ? Shouldn't we fall back to use the first available
> stream if any ?

At least that's what the code used to do, and I think it's best to keep
that behaviour in this patch. If a change of behaviour is desired, it
should be implemented in a separate patch.

I would make availableStreams a vector to support this, as otherwise
availableStreams.begin() will return a random stream (not truly random,
but std::set is sorted using value comparison, and values are pointers
here).

> I would re-structure the code as
> 
> for (config : config_) {
> 
>         if (raw) {
>                 it = availableStreams.find(rawStream);
>                 if (it == end()) {
>                         // Fail as we can't provide two raw streams.
>                 }
> 
>                 availagleStreams.erase(rawStream);
>                 continue;
>         }

This is also a change of behaviour that should be discussed in a
separate patch.

> 
>         /* Handle non-raw streams. */
>         if (size == sensorSize)
>                 stream = output;
>         else
>                 stream = viewfinder;
> 
>         if (availableStream.find(stream) == end())
>                 stream = begin()
> 
>          availableStreams.erase(stream);
> }
> 
> 
> }
> > +
> > +		streams.push_back(stream);
> > +		availableStreams.erase(stream);
> > +	}
> > +
> > +	streams_ = streams;
> 
> Why don't you fill streams_ directly ?
> 
> > +
> > +	return 0;
> > +}
> > +
> >  void IPU3CameraConfiguration::adjustStream(StreamConfiguration &cfg, bool scale)
> >  {
> >  	/* The only pixel format the driver supports is NV12. */
> > @@ -342,40 +388,16 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()
> >  	if (!sensorFormat_.size.width || !sensorFormat_.size.height)
> >  		sensorFormat_.size = sensor->resolution();
> >
> > -	/*
> > -	 * Verify and update all configuration entries, and assign a stream to
> > -	 * each of them. The viewfinder stream can scale, while the output
> > -	 * stream can crop only, so select the output stream when the requested
> > -	 * resolution is equal to the sensor resolution, and the viewfinder
> > -	 * stream otherwise.
> > -	 */
> > -	std::set<const IPU3Stream *> availableStreams = {
> > -		&data_->outStream_,
> > -		&data_->vfStream_,
> > -		&data_->rawStream_,
> > -	};
> >
> 
> This results in two empty lines. Doesn't checkstyle report that ?
> 
> > -	streams_.clear();
> > -	streams_.reserve(config_.size());
> > +	/* Assign streams to each configuration entry. */
> > +	if (updateStreams())
> > +		return Invalid;
> >
> > +	/* Verify and adjust configuration if needed. */
> >  	for (unsigned int i = 0; i < config_.size(); ++i) {
> 
> Can you iterate on config_ ?
> 
> >  		StreamConfiguration &cfg = config_[i];
> > -		const PixelFormat pixelFormat = cfg.pixelFormat;
> > -		const Size size = cfg.size;
> > -		const IPU3Stream *stream;
> > -
> > -		if (cfg.pixelFormat.modifier() == IPU3_FORMAT_MOD_PACKED)
> > -			stream = &data_->rawStream_;
> > -		else if (cfg.size == sensorFormat_.size)
> > -			stream = &data_->outStream_;
> > -		else
> > -			stream = &data_->vfStream_;
> > -
> > -		if (availableStreams.find(stream) == availableStreams.end())
> > -			stream = *availableStreams.begin();
> > -
> > -		LOG(IPU3, Debug)
> > -			<< "Assigned '" << stream->name_ << "' to stream " << i;
> > +		const StreamConfiguration org = cfg;

org isn't a very explicit name. origCfg or oldCfg would be better.

> > +		const IPU3Stream *stream = streams_[i];
> 
> Ah no, you need i here.
> However, associating on index seems a bit weak, and as we can't assign
> streams to stream configurations here, have you considered having
> updateStreams() return a map of configs to streams ?
> 
> >
> >  		if (stream->raw_) {
> >  			const auto &itFormat =
> > @@ -392,15 +414,12 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()
> >
> >  		cfg.bufferCount = IPU3_BUFFER_COUNT;
> >
> > -		if (cfg.pixelFormat != pixelFormat || cfg.size != size) {
> > +		if (cfg.pixelFormat != org.pixelFormat || cfg.size != org.size) {
> >  			LOG(IPU3, Debug)
> >  				<< "Stream " << i << " configuration adjusted to "
> >  				<< cfg.toString();
> >  			status = Adjusted;
> >  		}
> > -
> > -		streams_.push_back(stream);
> > -		availableStreams.erase(stream);
> >  	}
> >
> >  	return status;

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list