[libcamera-devel,15/30] libcamera: buffer: Move capture information to BufferInfo

Message ID 20191126233620.1695316-16-niklas.soderlund@ragnatech.se
State Superseded
Headers show
Series
  • libcamera: Rework buffer API
Related show

Commit Message

Niklas Söderlund Nov. 26, 2019, 11:36 p.m. UTC
Move the metadata information retrieved when dequeuing a V4L2 buffer
into a BufferInfo. This is done as a step to migrate to the FrameBuffer
interface as the functions added to Buffer around BufferInfo matches the
one in FrameBuffer.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
---
 include/libcamera/buffer.h               |  2 ++
 src/android/camera_device.cpp            |  4 +--
 src/cam/buffer_writer.cpp                |  2 +-
 src/cam/capture.cpp                      |  8 ++++--
 src/libcamera/buffer.cpp                 | 34 +++++++++++++++++-------
 src/libcamera/pipeline/ipu3/ipu3.cpp     |  4 +--
 src/libcamera/pipeline/rkisp1/rkisp1.cpp |  8 +++---
 src/libcamera/request.cpp                |  2 +-
 src/libcamera/v4l2_videodevice.cpp       | 23 +++++++++-------
 src/qcam/main_window.cpp                 | 13 ++++-----
 test/camera/buffer_import.cpp            |  2 +-
 test/camera/capture.cpp                  |  2 +-
 test/v4l2_videodevice/buffer_sharing.cpp | 12 ++++++---
 13 files changed, 72 insertions(+), 44 deletions(-)

Comments

Jacopo Mondi Nov. 27, 2019, 3:06 p.m. UTC | #1
Hi Niklas,

On Wed, Nov 27, 2019 at 12:36:05AM +0100, Niklas Söderlund wrote:
> Move the metadata information retrieved when dequeuing a V4L2 buffer
> into a BufferInfo. This is done as a step to migrate to the FrameBuffer
> interface as the functions added to Buffer around BufferInfo matches the
> one in FrameBuffer.
>
> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
> ---
>  include/libcamera/buffer.h               |  2 ++
>  src/android/camera_device.cpp            |  4 +--
>  src/cam/buffer_writer.cpp                |  2 +-
>  src/cam/capture.cpp                      |  8 ++++--
>  src/libcamera/buffer.cpp                 | 34 +++++++++++++++++-------
>  src/libcamera/pipeline/ipu3/ipu3.cpp     |  4 +--
>  src/libcamera/pipeline/rkisp1/rkisp1.cpp |  8 +++---
>  src/libcamera/request.cpp                |  2 +-
>  src/libcamera/v4l2_videodevice.cpp       | 23 +++++++++-------
>  src/qcam/main_window.cpp                 | 13 ++++-----
>  test/camera/buffer_import.cpp            |  2 +-
>  test/camera/capture.cpp                  |  2 +-
>  test/v4l2_videodevice/buffer_sharing.cpp | 12 ++++++---
>  13 files changed, 72 insertions(+), 44 deletions(-)
>
> diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h
> index d6db6138ca11d5fe..2e5376fb8b53a4c5 100644
> --- a/include/libcamera/buffer.h
> +++ b/include/libcamera/buffer.h
> @@ -122,6 +122,7 @@ public:
>  	unsigned int bytesused() const { return bytesused_; }
>  	uint64_t timestamp() const { return timestamp_; }
>  	unsigned int sequence() const { return sequence_; }
> +	const BufferInfo &info() const { return info_; };
>
>  	Status status() const { return status_; }
>  	Request *request() const { return request_; }
> @@ -142,6 +143,7 @@ private:
>  	unsigned int bytesused_;
>  	uint64_t timestamp_;
>  	unsigned int sequence_;
> +	BufferInfo info_;
>
>  	Status status_;
>  	Request *request_;
> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
> index 09588c16a6301649..55b29a9a41ab8943 100644
> --- a/src/android/camera_device.cpp
> +++ b/src/android/camera_device.cpp
> @@ -803,11 +803,11 @@ void CameraDevice::requestComplete(Request *request)
>
>  	if (status == CAMERA3_BUFFER_STATUS_OK) {
>  		notifyShutter(descriptor->frameNumber,
> -			      libcameraBuffer->timestamp());
> +			      libcameraBuffer->info().timestamp());
>
>  		captureResult.partial_result = 1;
>  		resultMetadata = getResultMetadata(descriptor->frameNumber,
> -						   libcameraBuffer->timestamp());
> +						   libcameraBuffer->info().timestamp());
>  		captureResult.result = resultMetadata->get();
>  	}
>
> diff --git a/src/cam/buffer_writer.cpp b/src/cam/buffer_writer.cpp
> index 5967efca07254666..b6b40baeee661df6 100644
> --- a/src/cam/buffer_writer.cpp
> +++ b/src/cam/buffer_writer.cpp
> @@ -32,7 +32,7 @@ int BufferWriter::write(Buffer *buffer, const std::string &streamName)
>  	if (pos != std::string::npos) {
>  		std::stringstream ss;
>  		ss << streamName << "-" << std::setw(6)
> -		   << std::setfill('0') << buffer->sequence();
> +		   << std::setfill('0') << buffer->info().sequence();
>  		filename.replace(pos, 1, ss.str());
>  	}
>
> diff --git a/src/cam/capture.cpp b/src/cam/capture.cpp
> index 1a4dbe7ce4a15a2d..a4fa88a8d99669bc 100644
> --- a/src/cam/capture.cpp
> +++ b/src/cam/capture.cpp
> @@ -155,8 +155,12 @@ void Capture::requestComplete(Request *request)
>  		const std::string &name = streamName_[stream];
>
>  		info << " " << name
> -		     << " seq: " << std::setw(6) << std::setfill('0') << buffer->sequence()
> -		     << " bytesused: " << buffer->bytesused();
> +		     << " seq: " << std::setw(6) << std::setfill('0') << buffer->info().sequence();
> +
> +		unsigned int nplane = 0;
> +		for (const BufferInfo::Plane &plane : buffer->info().planes())
> +			info << " bytesused(" << nplane++ << "): "
> +			     << plane.bytesused;
>
>  		if (writer_)
>  			writer_->write(buffer, name);
> diff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp
> index 7043345c3f3207cd..d5a4815a0bb8c528 100644
> --- a/src/libcamera/buffer.cpp
> +++ b/src/libcamera/buffer.cpp
> @@ -375,15 +375,22 @@ Buffer::Buffer(unsigned int index, const Buffer *metadata)
>  	  status_(Buffer::BufferSuccess), request_(nullptr),
>  	  stream_(nullptr)
>  {
> +	unsigned int sequence;
> +	uint64_t timestamp;
> +	unsigned int bytesused;
> +
>  	if (metadata) {
> -		bytesused_ = metadata->bytesused_;
> -		sequence_ = metadata->sequence_;
> -		timestamp_ = metadata->timestamp_;
> +		bytesused = metadata->info().planes()[0].bytesused;
> +		sequence = metadata->info().sequence();
> +		timestamp = metadata->info().timestamp();
>  	} else {
> -		bytesused_ = 0;
> -		sequence_ = 0;
> -		timestamp_ = 0;
> +		bytesused = 0;
> +		sequence = 0;
> +		timestamp = 0;
>  	}
> +
> +	info_.update(BufferInfo::BufferSuccess, sequence, timestamp,
> +		     { { bytesused } });

I am missing a bit of context here, but is it fair to assume we have
a single plane ?
>  }
>
>  /**
> @@ -439,6 +446,16 @@ Buffer::Buffer(unsigned int index, const Buffer *metadata)
>   * \return Sequence number of the buffer
>   */
>
> +/**
> + * \fn Buffer::info()
> + * \brief Retrieve the buffer metadata information
> + *

metadata + information is a bit of repetition, but that's fine

> + * The buffer metadata information is update every time the buffer contained

as in the previous patch, did you mean "buffer content" ?

> + * are changed, for example when it is dequeued from hardware.

buffer -> is

> + *
> + * \return Metadata of the buffer
> + */
> +
>  /**
>   * \fn Buffer::status()
>   * \brief Retrieve the buffer status
> @@ -482,10 +499,7 @@ Buffer::Buffer(unsigned int index, const Buffer *metadata)
>   */
>  void Buffer::cancel()
>  {
> -	bytesused_ = 0;
> -	timestamp_ = 0;
> -	sequence_ = 0;
> -	status_ = BufferCancelled;
> +	info_.update(BufferInfo::BufferCancelled, 0, 0, { {} });
>  }
>
>  /**
> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> index ad223d9101bdc6ed..8ba08351c950f5e2 100644
> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> @@ -928,7 +928,7 @@ int PipelineHandlerIPU3::registerCameras()
>  void IPU3CameraData::imguInputBufferReady(Buffer *buffer)
>  {
>  	/* \todo Handle buffer failures when state is set to BufferError. */
> -	if (buffer->status() == Buffer::BufferCancelled)
> +	if (buffer->info().status() == BufferInfo::BufferCancelled)
>  		return;
>
>  	cio2_.output_->queueBuffer(buffer);
> @@ -962,7 +962,7 @@ void IPU3CameraData::imguOutputBufferReady(Buffer *buffer)
>  void IPU3CameraData::cio2BufferReady(Buffer *buffer)
>  {
>  	/* \todo Handle buffer failures when state is set to BufferError. */
> -	if (buffer->status() == Buffer::BufferCancelled)
> +	if (buffer->info().status() == BufferInfo::BufferCancelled)
>  		return;
>
>  	imgu_->input_->queueBuffer(buffer);
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> index e8b6a278e97b0ba0..6ad9b57d8353896c 100644
> --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> @@ -100,10 +100,10 @@ public:
>  		ASSERT(frameOffset(SOE) == 0);
>
>  		utils::time_point soe = std::chrono::time_point<utils::clock>()
> -			+ std::chrono::nanoseconds(buffer->timestamp())
> +			+ std::chrono::nanoseconds(buffer->info().timestamp())
>  			+ timeOffset(SOE);
>
> -		notifyStartOfExposure(buffer->sequence(), soe);
> +		notifyStartOfExposure(buffer->info().sequence(), soe);
>  	}
>
>  	void setDelay(unsigned int type, int frame, int msdelay)
> @@ -1006,8 +1006,8 @@ void PipelineHandlerRkISP1::bufferReady(Buffer *buffer)
>
>  	data->timeline_.bufferReady(buffer);
>
> -	if (data->frame_ <= buffer->sequence())
> -		data->frame_ = buffer->sequence() + 1;
> +	if (data->frame_ <= buffer->info().sequence())
> +		data->frame_ = buffer->info().sequence() + 1;
>
>  	completeBuffer(activeCamera_, request, buffer);
>  	tryCompleteRequest(request);
> diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp
> index 3b49e52510918eee..7593bf9dfa546401 100644
> --- a/src/libcamera/request.cpp
> +++ b/src/libcamera/request.cpp
> @@ -260,7 +260,7 @@ bool Request::completeBuffer(Buffer *buffer)
>
>  	buffer->request_ = nullptr;
>
> -	if (buffer->status() == Buffer::BufferCancelled)
> +	if (buffer->info().status() == BufferInfo::BufferCancelled)
>  		cancelled_ = true;
>
>  	return !hasPendingBuffers();
> diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
> index cc0a1c9382a2b1ed..8f962c7e9d0c7d01 100644
> --- a/src/libcamera/v4l2_videodevice.cpp
> +++ b/src/libcamera/v4l2_videodevice.cpp
> @@ -1012,10 +1012,12 @@ int V4L2VideoDevice::queueBuffer(Buffer *buffer)
>  	}
>
>  	if (V4L2_TYPE_IS_OUTPUT(buf.type)) {
> -		buf.bytesused = buffer->bytesused_;
> -		buf.sequence = buffer->sequence_;
> -		buf.timestamp.tv_sec = buffer->timestamp_ / 1000000000;
> -		buf.timestamp.tv_usec = (buffer->timestamp_ / 1000) % 1000000;
> +		const BufferInfo &info = buffer->info();
> +
> +		buf.bytesused = info.planes()[0].bytesused;
> +		buf.sequence = info.sequence();
> +		buf.timestamp.tv_sec = info.timestamp() / 1000000000;
> +		buf.timestamp.tv_usec = (info.timestamp() / 1000) % 1000000;
>  	}
>
>  	LOG(V4L2, Debug) << "Queueing buffer " << buf.index;
> @@ -1121,12 +1123,13 @@ Buffer *V4L2VideoDevice::dequeueBuffer()
>  		fdEvent_->setEnabled(false);
>
>  	buffer->index_ = buf.index;
> -	buffer->bytesused_ = buf.bytesused;
> -	buffer->timestamp_ = buf.timestamp.tv_sec * 1000000000ULL
> -			   + buf.timestamp.tv_usec * 1000ULL;
> -	buffer->sequence_ = buf.sequence;
> -	buffer->status_ = buf.flags & V4L2_BUF_FLAG_ERROR
> -			? Buffer::BufferError : Buffer::BufferSuccess;
> +
> +	BufferInfo::Status status = buf.flags & V4L2_BUF_FLAG_ERROR
> +		? BufferInfo::BufferError : BufferInfo::BufferSuccess;
> +	uint64_t timestamp = buf.timestamp.tv_sec * 1000000000ULL
> +		+ buf.timestamp.tv_usec * 1000ULL;
> +
> +	buffer->info_.update(status, buf.sequence, timestamp, { { buf.bytesused } });

Here it's where I wondered if we should not provide an update()
version which takes a struct v4l2_buffer, but it would maybe be a bit
of a layering violation.

>
>  	return buffer;
>  }
> diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp
> index 4cecf7e351214f3d..771020112f09b1ef 100644
> --- a/src/qcam/main_window.cpp
> +++ b/src/qcam/main_window.cpp
> @@ -258,14 +258,15 @@ void MainWindow::requestComplete(Request *request)
>  	framesCaptured_++;
>
>  	Buffer *buffer = buffers.begin()->second;
> +	const BufferInfo &info = buffer->info();
>
> -	double fps = buffer->timestamp() - lastBufferTime_;
> +	double fps = info.timestamp() - lastBufferTime_;
>  	fps = lastBufferTime_ && fps ? 1000000000.0 / fps : 0.0;
> -	lastBufferTime_ = buffer->timestamp();
> +	lastBufferTime_ = info.timestamp();
>
> -	std::cout << "seq: " << std::setw(6) << std::setfill('0') << buffer->sequence()
> -		  << " bytesused: " << buffer->bytesused()
> -		  << " timestamp: " << buffer->timestamp()
> +	std::cout << "seq: " << std::setw(6) << std::setfill('0') << info.sequence()
> +		  << " bytesused: " << info.planes()[0].bytesused

Assuming a single plane is fine ?

> +		  << " timestamp: " << info.timestamp()
>  		  << " fps: " << std::fixed << std::setprecision(2) << fps
>  		  << std::endl;
>
> @@ -302,7 +303,7 @@ int MainWindow::display(Buffer *buffer)
>
>  	Dmabuf &dmabuf = mem->planes().front();
>  	unsigned char *raw = static_cast<unsigned char *>(dmabuf.mem());
> -	viewfinder_->display(raw, buffer->bytesused());
> +	viewfinder_->display(raw, buffer->info().planes()[0].bytesused);
>
>  	return 0;
>  }
> diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp
> index dae907f9f41841c9..5dbaed9255d3d60c 100644
> --- a/test/camera/buffer_import.cpp
> +++ b/test/camera/buffer_import.cpp
> @@ -275,7 +275,7 @@ public:
>  protected:
>  	void bufferComplete(Request *request, Buffer *buffer)
>  	{
> -		if (buffer->status() != Buffer::BufferSuccess)
> +		if (buffer->info().status() != BufferInfo::BufferSuccess)
>  			return;
>
>  		unsigned int index = buffer->index();
> diff --git a/test/camera/capture.cpp b/test/camera/capture.cpp
> index ca1ebe419946dd4d..8307ea2629801679 100644
> --- a/test/camera/capture.cpp
> +++ b/test/camera/capture.cpp
> @@ -28,7 +28,7 @@ protected:
>
>  	void bufferComplete(Request *request, Buffer *buffer)
>  	{
> -		if (buffer->status() != Buffer::BufferSuccess)
> +		if (buffer->info().status() != BufferInfo::BufferSuccess)
>  			return;
>
>  		completeBuffersCount_++;
> diff --git a/test/v4l2_videodevice/buffer_sharing.cpp b/test/v4l2_videodevice/buffer_sharing.cpp
> index d02c391b95933922..6b71caef111693d6 100644
> --- a/test/v4l2_videodevice/buffer_sharing.cpp
> +++ b/test/v4l2_videodevice/buffer_sharing.cpp
> @@ -92,10 +92,12 @@ protected:
>
>  	void captureBufferReady(Buffer *buffer)
>  	{
> +		const BufferInfo &info = buffer->info();
> +
>  		std::cout << "Received capture buffer  sequence "
> -			  << buffer->sequence() << std::endl;
> +			  << info.sequence() << std::endl;
>
> -		if (buffer->status() != Buffer::BufferSuccess)
> +		if (info.status() != BufferInfo::BufferSuccess)
>  			return;
>
>  		output_->queueBuffer(buffer);
> @@ -104,10 +106,12 @@ protected:
>
>  	void outputBufferReady(Buffer *buffer)
>  	{
> +		const BufferInfo &info = buffer->info();
> +
>  		std::cout << "Received output buffer sequence "
> -			  << buffer->sequence() << std::endl;
> +			  << info.sequence() << std::endl;
>
> -		if (buffer->status() != Buffer::BufferSuccess)
> +		if (info.status() != BufferInfo::BufferSuccess)
>  			return;
>
>  		capture_->queueBuffer(buffer);
> --
> 2.24.0
>
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel@lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel
Laurent Pinchart Dec. 9, 2019, 9:19 p.m. UTC | #2
Hi Niklas,

Thank you for the patch.

On Wed, Nov 27, 2019 at 04:06:54PM +0100, Jacopo Mondi wrote:
> On Wed, Nov 27, 2019 at 12:36:05AM +0100, Niklas Söderlund wrote:
> > Move the metadata information retrieved when dequeuing a V4L2 buffer

"metadata" or "information", not "metadata information". I would pick
one or the other based on whether you want to rename BufferInfo to
FrameInfo or FrameMetadata (with a preference for the latter on my
side).

> > into a BufferInfo. This is done as a step to migrate to the FrameBuffer
> > interface as the functions added to Buffer around BufferInfo matches the

s/matches/match/

> > one in FrameBuffer.

s/one/ones/

> >
> > Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
> > ---
> >  include/libcamera/buffer.h               |  2 ++
> >  src/android/camera_device.cpp            |  4 +--
> >  src/cam/buffer_writer.cpp                |  2 +-
> >  src/cam/capture.cpp                      |  8 ++++--
> >  src/libcamera/buffer.cpp                 | 34 +++++++++++++++++-------
> >  src/libcamera/pipeline/ipu3/ipu3.cpp     |  4 +--
> >  src/libcamera/pipeline/rkisp1/rkisp1.cpp |  8 +++---
> >  src/libcamera/request.cpp                |  2 +-
> >  src/libcamera/v4l2_videodevice.cpp       | 23 +++++++++-------
> >  src/qcam/main_window.cpp                 | 13 ++++-----
> >  test/camera/buffer_import.cpp            |  2 +-
> >  test/camera/capture.cpp                  |  2 +-
> >  test/v4l2_videodevice/buffer_sharing.cpp | 12 ++++++---
> >  13 files changed, 72 insertions(+), 44 deletions(-)
> >
> > diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h
> > index d6db6138ca11d5fe..2e5376fb8b53a4c5 100644
> > --- a/include/libcamera/buffer.h
> > +++ b/include/libcamera/buffer.h
> > @@ -122,6 +122,7 @@ public:
> >  	unsigned int bytesused() const { return bytesused_; }
> >  	uint64_t timestamp() const { return timestamp_; }
> >  	unsigned int sequence() const { return sequence_; }
> > +	const BufferInfo &info() const { return info_; };
> >
> >  	Status status() const { return status_; }
> >  	Request *request() const { return request_; }
> > @@ -142,6 +143,7 @@ private:
> >  	unsigned int bytesused_;
> >  	uint64_t timestamp_;
> >  	unsigned int sequence_;
> > +	BufferInfo info_;
> >
> >  	Status status_;
> >  	Request *request_;
> > diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
> > index 09588c16a6301649..55b29a9a41ab8943 100644
> > --- a/src/android/camera_device.cpp
> > +++ b/src/android/camera_device.cpp
> > @@ -803,11 +803,11 @@ void CameraDevice::requestComplete(Request *request)
> >
> >  	if (status == CAMERA3_BUFFER_STATUS_OK) {
> >  		notifyShutter(descriptor->frameNumber,
> > -			      libcameraBuffer->timestamp());
> > +			      libcameraBuffer->info().timestamp());
> >
> >  		captureResult.partial_result = 1;
> >  		resultMetadata = getResultMetadata(descriptor->frameNumber,
> > -						   libcameraBuffer->timestamp());
> > +						   libcameraBuffer->info().timestamp());
> >  		captureResult.result = resultMetadata->get();
> >  	}
> >
> > diff --git a/src/cam/buffer_writer.cpp b/src/cam/buffer_writer.cpp
> > index 5967efca07254666..b6b40baeee661df6 100644
> > --- a/src/cam/buffer_writer.cpp
> > +++ b/src/cam/buffer_writer.cpp
> > @@ -32,7 +32,7 @@ int BufferWriter::write(Buffer *buffer, const std::string &streamName)
> >  	if (pos != std::string::npos) {
> >  		std::stringstream ss;
> >  		ss << streamName << "-" << std::setw(6)
> > -		   << std::setfill('0') << buffer->sequence();
> > +		   << std::setfill('0') << buffer->info().sequence();
> >  		filename.replace(pos, 1, ss.str());
> >  	}
> >
> > diff --git a/src/cam/capture.cpp b/src/cam/capture.cpp
> > index 1a4dbe7ce4a15a2d..a4fa88a8d99669bc 100644
> > --- a/src/cam/capture.cpp
> > +++ b/src/cam/capture.cpp
> > @@ -155,8 +155,12 @@ void Capture::requestComplete(Request *request)
> >  		const std::string &name = streamName_[stream];
> >
> >  		info << " " << name
> > -		     << " seq: " << std::setw(6) << std::setfill('0') << buffer->sequence()
> > -		     << " bytesused: " << buffer->bytesused();
> > +		     << " seq: " << std::setw(6) << std::setfill('0') << buffer->info().sequence();
> > +
> > +		unsigned int nplane = 0;
> > +		for (const BufferInfo::Plane &plane : buffer->info().planes())
> > +			info << " bytesused(" << nplane++ << "): "
> > +			     << plane.bytesused;

Nitpicking, this makes it quite long. How about

		const BufferInfo &info = buffer->info();

		info << " " << name
		     << " seq: " << std::setw(6) << std::setfill('0') << info..sequence()
		     << " bytesused: ";

		unsigned int nplane = 0;
		for (const BufferInfo::Plane &plane : info.planes()) {
			info << plane.bytesused;
			if (++nplane < info.planes().size())
				info << "/";
		}

> >
> >  		if (writer_)
> >  			writer_->write(buffer, name);
> > diff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp
> > index 7043345c3f3207cd..d5a4815a0bb8c528 100644
> > --- a/src/libcamera/buffer.cpp
> > +++ b/src/libcamera/buffer.cpp
> > @@ -375,15 +375,22 @@ Buffer::Buffer(unsigned int index, const Buffer *metadata)
> >  	  status_(Buffer::BufferSuccess), request_(nullptr),
> >  	  stream_(nullptr)
> >  {
> > +	unsigned int sequence;
> > +	uint64_t timestamp;
> > +	unsigned int bytesused;
> > +
> >  	if (metadata) {
> > -		bytesused_ = metadata->bytesused_;
> > -		sequence_ = metadata->sequence_;
> > -		timestamp_ = metadata->timestamp_;
> > +		bytesused = metadata->info().planes()[0].bytesused;
> > +		sequence = metadata->info().sequence();
> > +		timestamp = metadata->info().timestamp();
> >  	} else {
> > -		bytesused_ = 0;
> > -		sequence_ = 0;
> > -		timestamp_ = 0;
> > +		bytesused = 0;
> > +		sequence = 0;
> > +		timestamp = 0;
> >  	}
> > +
> > +	info_.update(BufferInfo::BufferSuccess, sequence, timestamp,
> > +		     { { bytesused } });

This would be simplified is BufferInfo was turned into a structure with
public members.

> 
> I am missing a bit of context here, but is it fair to assume we have
> a single plane ?
> >  }
> >
> >  /**
> > @@ -439,6 +446,16 @@ Buffer::Buffer(unsigned int index, const Buffer *metadata)
> >   * \return Sequence number of the buffer
> >   */
> >
> > +/**
> > + * \fn Buffer::info()
> > + * \brief Retrieve the buffer metadata information
> > + *
> 
> metadata + information is a bit of repetition, but that's fine

As commented above, I think we should use one or the other. If we go for
metadata, I would name the method metadata(). It probably doesn't matter
much here though, as the Buffer class is removed later in the series.

> > + * The buffer metadata information is update every time the buffer contained
> 
> as in the previous patch, did you mean "buffer content" ?
> 
> > + * are changed, for example when it is dequeued from hardware.
> 
> buffer -> is
> 
> > + *
> > + * \return Metadata of the buffer
> > + */
> > +
> >  /**
> >   * \fn Buffer::status()
> >   * \brief Retrieve the buffer status
> > @@ -482,10 +499,7 @@ Buffer::Buffer(unsigned int index, const Buffer *metadata)
> >   */
> >  void Buffer::cancel()
> >  {
> > -	bytesused_ = 0;
> > -	timestamp_ = 0;
> > -	sequence_ = 0;
> > -	status_ = BufferCancelled;
> > +	info_.update(BufferInfo::BufferCancelled, 0, 0, { {} });
> >  }
> >
> >  /**
> > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> > index ad223d9101bdc6ed..8ba08351c950f5e2 100644
> > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> > @@ -928,7 +928,7 @@ int PipelineHandlerIPU3::registerCameras()
> >  void IPU3CameraData::imguInputBufferReady(Buffer *buffer)
> >  {
> >  	/* \todo Handle buffer failures when state is set to BufferError. */
> > -	if (buffer->status() == Buffer::BufferCancelled)
> > +	if (buffer->info().status() == BufferInfo::BufferCancelled)
> >  		return;
> >
> >  	cio2_.output_->queueBuffer(buffer);
> > @@ -962,7 +962,7 @@ void IPU3CameraData::imguOutputBufferReady(Buffer *buffer)
> >  void IPU3CameraData::cio2BufferReady(Buffer *buffer)
> >  {
> >  	/* \todo Handle buffer failures when state is set to BufferError. */
> > -	if (buffer->status() == Buffer::BufferCancelled)
> > +	if (buffer->info().status() == BufferInfo::BufferCancelled)
> >  		return;
> >
> >  	imgu_->input_->queueBuffer(buffer);
> > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> > index e8b6a278e97b0ba0..6ad9b57d8353896c 100644
> > --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> > +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> > @@ -100,10 +100,10 @@ public:
> >  		ASSERT(frameOffset(SOE) == 0);
> >
> >  		utils::time_point soe = std::chrono::time_point<utils::clock>()
> > -			+ std::chrono::nanoseconds(buffer->timestamp())
> > +			+ std::chrono::nanoseconds(buffer->info().timestamp())
> >  			+ timeOffset(SOE);
> >
> > -		notifyStartOfExposure(buffer->sequence(), soe);
> > +		notifyStartOfExposure(buffer->info().sequence(), soe);
> >  	}
> >
> >  	void setDelay(unsigned int type, int frame, int msdelay)
> > @@ -1006,8 +1006,8 @@ void PipelineHandlerRkISP1::bufferReady(Buffer *buffer)
> >
> >  	data->timeline_.bufferReady(buffer);
> >
> > -	if (data->frame_ <= buffer->sequence())
> > -		data->frame_ = buffer->sequence() + 1;
> > +	if (data->frame_ <= buffer->info().sequence())
> > +		data->frame_ = buffer->info().sequence() + 1;
> >
> >  	completeBuffer(activeCamera_, request, buffer);
> >  	tryCompleteRequest(request);
> > diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp
> > index 3b49e52510918eee..7593bf9dfa546401 100644
> > --- a/src/libcamera/request.cpp
> > +++ b/src/libcamera/request.cpp
> > @@ -260,7 +260,7 @@ bool Request::completeBuffer(Buffer *buffer)
> >
> >  	buffer->request_ = nullptr;
> >
> > -	if (buffer->status() == Buffer::BufferCancelled)
> > +	if (buffer->info().status() == BufferInfo::BufferCancelled)
> >  		cancelled_ = true;
> >
> >  	return !hasPendingBuffers();
> > diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
> > index cc0a1c9382a2b1ed..8f962c7e9d0c7d01 100644
> > --- a/src/libcamera/v4l2_videodevice.cpp
> > +++ b/src/libcamera/v4l2_videodevice.cpp
> > @@ -1012,10 +1012,12 @@ int V4L2VideoDevice::queueBuffer(Buffer *buffer)
> >  	}
> >
> >  	if (V4L2_TYPE_IS_OUTPUT(buf.type)) {
> > -		buf.bytesused = buffer->bytesused_;
> > -		buf.sequence = buffer->sequence_;
> > -		buf.timestamp.tv_sec = buffer->timestamp_ / 1000000000;
> > -		buf.timestamp.tv_usec = (buffer->timestamp_ / 1000) % 1000000;
> > +		const BufferInfo &info = buffer->info();
> > +
> > +		buf.bytesused = info.planes()[0].bytesused;
> > +		buf.sequence = info.sequence();
> > +		buf.timestamp.tv_sec = info.timestamp() / 1000000000;
> > +		buf.timestamp.tv_usec = (info.timestamp() / 1000) % 1000000;
> >  	}
> >
> >  	LOG(V4L2, Debug) << "Queueing buffer " << buf.index;
> > @@ -1121,12 +1123,13 @@ Buffer *V4L2VideoDevice::dequeueBuffer()
> >  		fdEvent_->setEnabled(false);
> >
> >  	buffer->index_ = buf.index;
> > -	buffer->bytesused_ = buf.bytesused;
> > -	buffer->timestamp_ = buf.timestamp.tv_sec * 1000000000ULL
> > -			   + buf.timestamp.tv_usec * 1000ULL;
> > -	buffer->sequence_ = buf.sequence;
> > -	buffer->status_ = buf.flags & V4L2_BUF_FLAG_ERROR
> > -			? Buffer::BufferError : Buffer::BufferSuccess;
> > +
> > +	BufferInfo::Status status = buf.flags & V4L2_BUF_FLAG_ERROR
> > +		? BufferInfo::BufferError : BufferInfo::BufferSuccess;
> > +	uint64_t timestamp = buf.timestamp.tv_sec * 1000000000ULL
> > +		+ buf.timestamp.tv_usec * 1000ULL;

Could you align the ? and + under the = ?

> > +
> > +	buffer->info_.update(status, buf.sequence, timestamp, { { buf.bytesused } });
> 
> Here it's where I wondered if we should not provide an update()
> version which takes a struct v4l2_buffer, but it would maybe be a bit
> of a layering violation.

As it is needed in a single place I'd prefer keeping it in
v4l2_videodevice.cpp.

> >
> >  	return buffer;
> >  }
> > diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp
> > index 4cecf7e351214f3d..771020112f09b1ef 100644
> > --- a/src/qcam/main_window.cpp
> > +++ b/src/qcam/main_window.cpp
> > @@ -258,14 +258,15 @@ void MainWindow::requestComplete(Request *request)
> >  	framesCaptured_++;
> >
> >  	Buffer *buffer = buffers.begin()->second;
> > +	const BufferInfo &info = buffer->info();
> >
> > -	double fps = buffer->timestamp() - lastBufferTime_;
> > +	double fps = info.timestamp() - lastBufferTime_;
> >  	fps = lastBufferTime_ && fps ? 1000000000.0 / fps : 0.0;
> > -	lastBufferTime_ = buffer->timestamp();
> > +	lastBufferTime_ = info.timestamp();
> >
> > -	std::cout << "seq: " << std::setw(6) << std::setfill('0') << buffer->sequence()
> > -		  << " bytesused: " << buffer->bytesused()
> > -		  << " timestamp: " << buffer->timestamp()
> > +	std::cout << "seq: " << std::setw(6) << std::setfill('0') << info.sequence()
> > +		  << " bytesused: " << info.planes()[0].bytesused
> 
> Assuming a single plane is fine ?

It doesn't introduce any regression, but will need to be fixed. We need
to address multiplanar support.

> > +		  << " timestamp: " << info.timestamp()
> >  		  << " fps: " << std::fixed << std::setprecision(2) << fps
> >  		  << std::endl;
> >
> > @@ -302,7 +303,7 @@ int MainWindow::display(Buffer *buffer)
> >
> >  	Dmabuf &dmabuf = mem->planes().front();
> >  	unsigned char *raw = static_cast<unsigned char *>(dmabuf.mem());
> > -	viewfinder_->display(raw, buffer->bytesused());
> > +	viewfinder_->display(raw, buffer->info().planes()[0].bytesused);
> >
> >  	return 0;
> >  }
> > diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp
> > index dae907f9f41841c9..5dbaed9255d3d60c 100644
> > --- a/test/camera/buffer_import.cpp
> > +++ b/test/camera/buffer_import.cpp
> > @@ -275,7 +275,7 @@ public:
> >  protected:
> >  	void bufferComplete(Request *request, Buffer *buffer)
> >  	{
> > -		if (buffer->status() != Buffer::BufferSuccess)
> > +		if (buffer->info().status() != BufferInfo::BufferSuccess)
> >  			return;
> >
> >  		unsigned int index = buffer->index();
> > diff --git a/test/camera/capture.cpp b/test/camera/capture.cpp
> > index ca1ebe419946dd4d..8307ea2629801679 100644
> > --- a/test/camera/capture.cpp
> > +++ b/test/camera/capture.cpp
> > @@ -28,7 +28,7 @@ protected:
> >
> >  	void bufferComplete(Request *request, Buffer *buffer)
> >  	{
> > -		if (buffer->status() != Buffer::BufferSuccess)
> > +		if (buffer->info().status() != BufferInfo::BufferSuccess)
> >  			return;
> >
> >  		completeBuffersCount_++;
> > diff --git a/test/v4l2_videodevice/buffer_sharing.cpp b/test/v4l2_videodevice/buffer_sharing.cpp
> > index d02c391b95933922..6b71caef111693d6 100644
> > --- a/test/v4l2_videodevice/buffer_sharing.cpp
> > +++ b/test/v4l2_videodevice/buffer_sharing.cpp
> > @@ -92,10 +92,12 @@ protected:
> >
> >  	void captureBufferReady(Buffer *buffer)
> >  	{
> > +		const BufferInfo &info = buffer->info();
> > +
> >  		std::cout << "Received capture buffer  sequence "
> > -			  << buffer->sequence() << std::endl;
> > +			  << info.sequence() << std::endl;
> >
> > -		if (buffer->status() != Buffer::BufferSuccess)
> > +		if (info.status() != BufferInfo::BufferSuccess)
> >  			return;
> >
> >  		output_->queueBuffer(buffer);
> > @@ -104,10 +106,12 @@ protected:
> >
> >  	void outputBufferReady(Buffer *buffer)
> >  	{
> > +		const BufferInfo &info = buffer->info();
> > +
> >  		std::cout << "Received output buffer sequence "
> > -			  << buffer->sequence() << std::endl;
> > +			  << info.sequence() << std::endl;
> >
> > -		if (buffer->status() != Buffer::BufferSuccess)
> > +		if (info.status() != BufferInfo::BufferSuccess)
> >  			return;
> >
> >  		capture_->queueBuffer(buffer);

Patch

diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h
index d6db6138ca11d5fe..2e5376fb8b53a4c5 100644
--- a/include/libcamera/buffer.h
+++ b/include/libcamera/buffer.h
@@ -122,6 +122,7 @@  public:
 	unsigned int bytesused() const { return bytesused_; }
 	uint64_t timestamp() const { return timestamp_; }
 	unsigned int sequence() const { return sequence_; }
+	const BufferInfo &info() const { return info_; };
 
 	Status status() const { return status_; }
 	Request *request() const { return request_; }
@@ -142,6 +143,7 @@  private:
 	unsigned int bytesused_;
 	uint64_t timestamp_;
 	unsigned int sequence_;
+	BufferInfo info_;
 
 	Status status_;
 	Request *request_;
diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
index 09588c16a6301649..55b29a9a41ab8943 100644
--- a/src/android/camera_device.cpp
+++ b/src/android/camera_device.cpp
@@ -803,11 +803,11 @@  void CameraDevice::requestComplete(Request *request)
 
 	if (status == CAMERA3_BUFFER_STATUS_OK) {
 		notifyShutter(descriptor->frameNumber,
-			      libcameraBuffer->timestamp());
+			      libcameraBuffer->info().timestamp());
 
 		captureResult.partial_result = 1;
 		resultMetadata = getResultMetadata(descriptor->frameNumber,
-						   libcameraBuffer->timestamp());
+						   libcameraBuffer->info().timestamp());
 		captureResult.result = resultMetadata->get();
 	}
 
diff --git a/src/cam/buffer_writer.cpp b/src/cam/buffer_writer.cpp
index 5967efca07254666..b6b40baeee661df6 100644
--- a/src/cam/buffer_writer.cpp
+++ b/src/cam/buffer_writer.cpp
@@ -32,7 +32,7 @@  int BufferWriter::write(Buffer *buffer, const std::string &streamName)
 	if (pos != std::string::npos) {
 		std::stringstream ss;
 		ss << streamName << "-" << std::setw(6)
-		   << std::setfill('0') << buffer->sequence();
+		   << std::setfill('0') << buffer->info().sequence();
 		filename.replace(pos, 1, ss.str());
 	}
 
diff --git a/src/cam/capture.cpp b/src/cam/capture.cpp
index 1a4dbe7ce4a15a2d..a4fa88a8d99669bc 100644
--- a/src/cam/capture.cpp
+++ b/src/cam/capture.cpp
@@ -155,8 +155,12 @@  void Capture::requestComplete(Request *request)
 		const std::string &name = streamName_[stream];
 
 		info << " " << name
-		     << " seq: " << std::setw(6) << std::setfill('0') << buffer->sequence()
-		     << " bytesused: " << buffer->bytesused();
+		     << " seq: " << std::setw(6) << std::setfill('0') << buffer->info().sequence();
+
+		unsigned int nplane = 0;
+		for (const BufferInfo::Plane &plane : buffer->info().planes())
+			info << " bytesused(" << nplane++ << "): "
+			     << plane.bytesused;
 
 		if (writer_)
 			writer_->write(buffer, name);
diff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp
index 7043345c3f3207cd..d5a4815a0bb8c528 100644
--- a/src/libcamera/buffer.cpp
+++ b/src/libcamera/buffer.cpp
@@ -375,15 +375,22 @@  Buffer::Buffer(unsigned int index, const Buffer *metadata)
 	  status_(Buffer::BufferSuccess), request_(nullptr),
 	  stream_(nullptr)
 {
+	unsigned int sequence;
+	uint64_t timestamp;
+	unsigned int bytesused;
+
 	if (metadata) {
-		bytesused_ = metadata->bytesused_;
-		sequence_ = metadata->sequence_;
-		timestamp_ = metadata->timestamp_;
+		bytesused = metadata->info().planes()[0].bytesused;
+		sequence = metadata->info().sequence();
+		timestamp = metadata->info().timestamp();
 	} else {
-		bytesused_ = 0;
-		sequence_ = 0;
-		timestamp_ = 0;
+		bytesused = 0;
+		sequence = 0;
+		timestamp = 0;
 	}
+
+	info_.update(BufferInfo::BufferSuccess, sequence, timestamp,
+		     { { bytesused } });
 }
 
 /**
@@ -439,6 +446,16 @@  Buffer::Buffer(unsigned int index, const Buffer *metadata)
  * \return Sequence number of the buffer
  */
 
+/**
+ * \fn Buffer::info()
+ * \brief Retrieve the buffer metadata information
+ *
+ * The buffer metadata information is update every time the buffer contained
+ * are changed, for example when it is dequeued from hardware.
+ *
+ * \return Metadata of the buffer
+ */
+
 /**
  * \fn Buffer::status()
  * \brief Retrieve the buffer status
@@ -482,10 +499,7 @@  Buffer::Buffer(unsigned int index, const Buffer *metadata)
  */
 void Buffer::cancel()
 {
-	bytesused_ = 0;
-	timestamp_ = 0;
-	sequence_ = 0;
-	status_ = BufferCancelled;
+	info_.update(BufferInfo::BufferCancelled, 0, 0, { {} });
 }
 
 /**
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index ad223d9101bdc6ed..8ba08351c950f5e2 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -928,7 +928,7 @@  int PipelineHandlerIPU3::registerCameras()
 void IPU3CameraData::imguInputBufferReady(Buffer *buffer)
 {
 	/* \todo Handle buffer failures when state is set to BufferError. */
-	if (buffer->status() == Buffer::BufferCancelled)
+	if (buffer->info().status() == BufferInfo::BufferCancelled)
 		return;
 
 	cio2_.output_->queueBuffer(buffer);
@@ -962,7 +962,7 @@  void IPU3CameraData::imguOutputBufferReady(Buffer *buffer)
 void IPU3CameraData::cio2BufferReady(Buffer *buffer)
 {
 	/* \todo Handle buffer failures when state is set to BufferError. */
-	if (buffer->status() == Buffer::BufferCancelled)
+	if (buffer->info().status() == BufferInfo::BufferCancelled)
 		return;
 
 	imgu_->input_->queueBuffer(buffer);
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
index e8b6a278e97b0ba0..6ad9b57d8353896c 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
@@ -100,10 +100,10 @@  public:
 		ASSERT(frameOffset(SOE) == 0);
 
 		utils::time_point soe = std::chrono::time_point<utils::clock>()
-			+ std::chrono::nanoseconds(buffer->timestamp())
+			+ std::chrono::nanoseconds(buffer->info().timestamp())
 			+ timeOffset(SOE);
 
-		notifyStartOfExposure(buffer->sequence(), soe);
+		notifyStartOfExposure(buffer->info().sequence(), soe);
 	}
 
 	void setDelay(unsigned int type, int frame, int msdelay)
@@ -1006,8 +1006,8 @@  void PipelineHandlerRkISP1::bufferReady(Buffer *buffer)
 
 	data->timeline_.bufferReady(buffer);
 
-	if (data->frame_ <= buffer->sequence())
-		data->frame_ = buffer->sequence() + 1;
+	if (data->frame_ <= buffer->info().sequence())
+		data->frame_ = buffer->info().sequence() + 1;
 
 	completeBuffer(activeCamera_, request, buffer);
 	tryCompleteRequest(request);
diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp
index 3b49e52510918eee..7593bf9dfa546401 100644
--- a/src/libcamera/request.cpp
+++ b/src/libcamera/request.cpp
@@ -260,7 +260,7 @@  bool Request::completeBuffer(Buffer *buffer)
 
 	buffer->request_ = nullptr;
 
-	if (buffer->status() == Buffer::BufferCancelled)
+	if (buffer->info().status() == BufferInfo::BufferCancelled)
 		cancelled_ = true;
 
 	return !hasPendingBuffers();
diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
index cc0a1c9382a2b1ed..8f962c7e9d0c7d01 100644
--- a/src/libcamera/v4l2_videodevice.cpp
+++ b/src/libcamera/v4l2_videodevice.cpp
@@ -1012,10 +1012,12 @@  int V4L2VideoDevice::queueBuffer(Buffer *buffer)
 	}
 
 	if (V4L2_TYPE_IS_OUTPUT(buf.type)) {
-		buf.bytesused = buffer->bytesused_;
-		buf.sequence = buffer->sequence_;
-		buf.timestamp.tv_sec = buffer->timestamp_ / 1000000000;
-		buf.timestamp.tv_usec = (buffer->timestamp_ / 1000) % 1000000;
+		const BufferInfo &info = buffer->info();
+
+		buf.bytesused = info.planes()[0].bytesused;
+		buf.sequence = info.sequence();
+		buf.timestamp.tv_sec = info.timestamp() / 1000000000;
+		buf.timestamp.tv_usec = (info.timestamp() / 1000) % 1000000;
 	}
 
 	LOG(V4L2, Debug) << "Queueing buffer " << buf.index;
@@ -1121,12 +1123,13 @@  Buffer *V4L2VideoDevice::dequeueBuffer()
 		fdEvent_->setEnabled(false);
 
 	buffer->index_ = buf.index;
-	buffer->bytesused_ = buf.bytesused;
-	buffer->timestamp_ = buf.timestamp.tv_sec * 1000000000ULL
-			   + buf.timestamp.tv_usec * 1000ULL;
-	buffer->sequence_ = buf.sequence;
-	buffer->status_ = buf.flags & V4L2_BUF_FLAG_ERROR
-			? Buffer::BufferError : Buffer::BufferSuccess;
+
+	BufferInfo::Status status = buf.flags & V4L2_BUF_FLAG_ERROR
+		? BufferInfo::BufferError : BufferInfo::BufferSuccess;
+	uint64_t timestamp = buf.timestamp.tv_sec * 1000000000ULL
+		+ buf.timestamp.tv_usec * 1000ULL;
+
+	buffer->info_.update(status, buf.sequence, timestamp, { { buf.bytesused } });
 
 	return buffer;
 }
diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp
index 4cecf7e351214f3d..771020112f09b1ef 100644
--- a/src/qcam/main_window.cpp
+++ b/src/qcam/main_window.cpp
@@ -258,14 +258,15 @@  void MainWindow::requestComplete(Request *request)
 	framesCaptured_++;
 
 	Buffer *buffer = buffers.begin()->second;
+	const BufferInfo &info = buffer->info();
 
-	double fps = buffer->timestamp() - lastBufferTime_;
+	double fps = info.timestamp() - lastBufferTime_;
 	fps = lastBufferTime_ && fps ? 1000000000.0 / fps : 0.0;
-	lastBufferTime_ = buffer->timestamp();
+	lastBufferTime_ = info.timestamp();
 
-	std::cout << "seq: " << std::setw(6) << std::setfill('0') << buffer->sequence()
-		  << " bytesused: " << buffer->bytesused()
-		  << " timestamp: " << buffer->timestamp()
+	std::cout << "seq: " << std::setw(6) << std::setfill('0') << info.sequence()
+		  << " bytesused: " << info.planes()[0].bytesused
+		  << " timestamp: " << info.timestamp()
 		  << " fps: " << std::fixed << std::setprecision(2) << fps
 		  << std::endl;
 
@@ -302,7 +303,7 @@  int MainWindow::display(Buffer *buffer)
 
 	Dmabuf &dmabuf = mem->planes().front();
 	unsigned char *raw = static_cast<unsigned char *>(dmabuf.mem());
-	viewfinder_->display(raw, buffer->bytesused());
+	viewfinder_->display(raw, buffer->info().planes()[0].bytesused);
 
 	return 0;
 }
diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp
index dae907f9f41841c9..5dbaed9255d3d60c 100644
--- a/test/camera/buffer_import.cpp
+++ b/test/camera/buffer_import.cpp
@@ -275,7 +275,7 @@  public:
 protected:
 	void bufferComplete(Request *request, Buffer *buffer)
 	{
-		if (buffer->status() != Buffer::BufferSuccess)
+		if (buffer->info().status() != BufferInfo::BufferSuccess)
 			return;
 
 		unsigned int index = buffer->index();
diff --git a/test/camera/capture.cpp b/test/camera/capture.cpp
index ca1ebe419946dd4d..8307ea2629801679 100644
--- a/test/camera/capture.cpp
+++ b/test/camera/capture.cpp
@@ -28,7 +28,7 @@  protected:
 
 	void bufferComplete(Request *request, Buffer *buffer)
 	{
-		if (buffer->status() != Buffer::BufferSuccess)
+		if (buffer->info().status() != BufferInfo::BufferSuccess)
 			return;
 
 		completeBuffersCount_++;
diff --git a/test/v4l2_videodevice/buffer_sharing.cpp b/test/v4l2_videodevice/buffer_sharing.cpp
index d02c391b95933922..6b71caef111693d6 100644
--- a/test/v4l2_videodevice/buffer_sharing.cpp
+++ b/test/v4l2_videodevice/buffer_sharing.cpp
@@ -92,10 +92,12 @@  protected:
 
 	void captureBufferReady(Buffer *buffer)
 	{
+		const BufferInfo &info = buffer->info();
+
 		std::cout << "Received capture buffer  sequence "
-			  << buffer->sequence() << std::endl;
+			  << info.sequence() << std::endl;
 
-		if (buffer->status() != Buffer::BufferSuccess)
+		if (info.status() != BufferInfo::BufferSuccess)
 			return;
 
 		output_->queueBuffer(buffer);
@@ -104,10 +106,12 @@  protected:
 
 	void outputBufferReady(Buffer *buffer)
 	{
+		const BufferInfo &info = buffer->info();
+
 		std::cout << "Received output buffer sequence "
-			  << buffer->sequence() << std::endl;
+			  << info.sequence() << std::endl;
 
-		if (buffer->status() != Buffer::BufferSuccess)
+		if (info.status() != BufferInfo::BufferSuccess)
 			return;
 
 		capture_->queueBuffer(buffer);