diff --git a/include/libcamera/request.h b/include/libcamera/request.h
index 2d5a5964e99eb75f..88ef7bf03fcfb77b 100644
--- a/include/libcamera/request.h
+++ b/include/libcamera/request.h
@@ -12,12 +12,12 @@
 #include <stdint.h>
 #include <unordered_set>
 
+#include <libcamera/buffer.h>
 #include <libcamera/controls.h>
 #include <libcamera/signal.h>
 
 namespace libcamera {
 
-class Buffer;
 class Camera;
 class CameraControlValidator;
 class Stream;
@@ -39,6 +39,7 @@ public:
 	ControlList &controls() { return *controls_; }
 	ControlList &metadata() { return *metadata_; }
 	const std::map<Stream *, Buffer *> &buffers() const { return bufferMap_; }
+	const BufferInfo &info(Buffer *frame) const { return info_.find(frame)->second; };
 	int addBuffer(std::unique_ptr<Buffer> buffer);
 	Buffer *findBuffer(Stream *stream) const;
 
@@ -54,13 +55,14 @@ private:
 	int prepare();
 	void complete();
 
-	bool completeBuffer(Buffer *buffer);
+	bool completeBuffer(Buffer *buffer, const BufferInfo &info);
 
 	Camera *camera_;
 	CameraControlValidator *validator_;
 	ControlList *controls_;
 	ControlList *metadata_;
 	std::map<Stream *, Buffer *> bufferMap_;
+	std::map<Buffer *, BufferInfo> info_;
 	std::unordered_set<Buffer *> pending_;
 
 	const uint64_t cookie_;
diff --git a/src/cam/buffer_writer.cpp b/src/cam/buffer_writer.cpp
index c33e99c5f8173db8..3ee9e82ba216abb6 100644
--- a/src/cam/buffer_writer.cpp
+++ b/src/cam/buffer_writer.cpp
@@ -21,7 +21,8 @@ BufferWriter::BufferWriter(const std::string &pattern)
 {
 }
 
-int BufferWriter::write(Buffer *buffer, const std::string &streamName)
+int BufferWriter::write(Buffer *buffer, const BufferInfo &info,
+			const std::string &streamName)
 {
 	std::string filename;
 	size_t pos;
@@ -32,7 +33,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') << info.sequence();
 		filename.replace(pos, 1, ss.str());
 	}
 
diff --git a/src/cam/buffer_writer.h b/src/cam/buffer_writer.h
index 7bf785d1e83235ff..38f7045c7d4e68a4 100644
--- a/src/cam/buffer_writer.h
+++ b/src/cam/buffer_writer.h
@@ -16,7 +16,9 @@ class BufferWriter
 public:
 	BufferWriter(const std::string &pattern = "frame-#.bin");
 
-	int write(libcamera::Buffer *buffer, const std::string &streamName);
+	int write(libcamera::Buffer *buffer,
+		  const libcamera::BufferInfo &info,
+		  const std::string &streamName);
 
 private:
 	std::string pattern_;
diff --git a/src/cam/capture.cpp b/src/cam/capture.cpp
index e665d819fb777a90..251e9f86c86b508d 100644
--- a/src/cam/capture.cpp
+++ b/src/cam/capture.cpp
@@ -138,32 +138,33 @@ void Capture::requestComplete(Request *request)
 	if (request->status() == Request::RequestCancelled)
 		return;
 
-	const std::map<Stream *, Buffer *> &buffers = request->buffers();
-
 	std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
 	double fps = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_).count();
 	fps = last_ != std::chrono::steady_clock::time_point() && fps
 	    ? 1000.0 / fps : 0.0;
 	last_ = now;
 
-	std::stringstream info;
-	info << "fps: " << std::fixed << std::setprecision(2) << fps;
+	std::stringstream infostr;
+	infostr << "fps: " << std::fixed << std::setprecision(2) << fps;
 
+	const std::map<Stream *, Buffer *> &buffers = request->buffers();
 	for (auto it = buffers.begin(); it != buffers.end(); ++it) {
 		Stream *stream = it->first;
 		Buffer *buffer = it->second;
+		const BufferInfo &info = request->info(buffer);
 		const std::string &name = streamName_[stream];
 
-		info << " " << name
-		     << " (" << buffer->index() << ")"
-		     << " seq: " << std::setw(6) << std::setfill('0') << buffer->sequence()
-		     << " bytesused: " << buffer->bytesused();
+		infostr << " " << name
+			<< " seq: " << std::setw(6) << std::setfill('0') << info.sequence();
+
+		for (unsigned int i = 0; i < info.planes(); i++)
+			infostr << " bytesused(" << i << "): " << info.plane(i).bytesused;
 
 		if (writer_)
-			writer_->write(buffer, name);
+			writer_->write(buffer, info, name);
 	}
 
-	std::cout << info.str() << std::endl;
+	std::cout << infostr.str() << std::endl;
 
 	/*
 	 * Create a new request and populate it with one buffer for each
diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h
index 6024357e266c2e2b..e6dbd7687021e4ff 100644
--- a/src/libcamera/include/pipeline_handler.h
+++ b/src/libcamera/include/pipeline_handler.h
@@ -81,7 +81,8 @@ public:
 
 	virtual int queueRequest(Camera *camera, Request *request);
 
-	bool completeBuffer(Camera *camera, Request *request, Buffer *buffer);
+	bool completeBuffer(Camera *camera, Request *request, Buffer *buffer,
+			    const BufferInfo &info);
 	void completeRequest(Camera *camera, Request *request);
 
 	const char *name() const { return name_; }
diff --git a/src/libcamera/include/v4l2_videodevice.h b/src/libcamera/include/v4l2_videodevice.h
index 5b178339d0ce7e2c..01b90ab4654bfba2 100644
--- a/src/libcamera/include/v4l2_videodevice.h
+++ b/src/libcamera/include/v4l2_videodevice.h
@@ -12,6 +12,7 @@
 
 #include <linux/videodev2.h>
 
+#include <libcamera/buffer.h>
 #include <libcamera/geometry.h>
 #include <libcamera/signal.h>
 
@@ -166,7 +167,7 @@ public:
 
 	int queueBuffer(Buffer *buffer);
 	std::vector<std::unique_ptr<Buffer>> queueAllBuffers();
-	Signal<Buffer *> bufferReady;
+	Signal<Buffer *, const BufferInfo &> bufferReady;
 
 	int streamOn();
 	int streamOff();
@@ -194,7 +195,6 @@ private:
 	int createPlane(BufferMemory *buffer, unsigned int index,
 			unsigned int plane, unsigned int length);
 
-	Buffer *dequeueBuffer();
 	void bufferAvailable(EventNotifier *notifier);
 
 	V4L2Capability caps_;
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 8aa5f34febf16585..01064ac09859155d 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -161,9 +161,9 @@ public:
 		delete vfStream_;
 	}
 
-	void imguOutputBufferReady(Buffer *buffer);
-	void imguInputBufferReady(Buffer *buffer);
-	void cio2BufferReady(Buffer *buffer);
+	void imguOutputBufferReady(Buffer *buffer, const BufferInfo &info);
+	void imguInputBufferReady(Buffer *buffer, const BufferInfo &info);
+	void cio2BufferReady(Buffer *buffer, const BufferInfo &info);
 
 	CIO2Device cio2_;
 	ImgUDevice *imgu_;
@@ -931,10 +931,10 @@ int PipelineHandlerIPU3::registerCameras()
  * Buffers completed from the ImgU input are immediately queued back to the
  * CIO2 unit to continue frame capture.
  */
-void IPU3CameraData::imguInputBufferReady(Buffer *buffer)
+void IPU3CameraData::imguInputBufferReady(Buffer *buffer, const BufferInfo &info)
 {
 	/* \todo Handle buffer failures when state is set to BufferError. */
-	if (buffer->status() == Buffer::BufferCancelled)
+	if (info.status() == BufferInfo::BufferCancelled)
 		return;
 
 	cio2_.output_->queueBuffer(buffer);
@@ -946,15 +946,13 @@ void IPU3CameraData::imguInputBufferReady(Buffer *buffer)
  *
  * Buffers completed from the ImgU output are directed to the application.
  */
-void IPU3CameraData::imguOutputBufferReady(Buffer *buffer)
+void IPU3CameraData::imguOutputBufferReady(Buffer *buffer, const BufferInfo &info)
 {
 	Request *request = requestFromBuffer(buffer);
 
-	if (!pipe_->completeBuffer(camera_, request, buffer))
-		/* Request not completed yet, return here. */
+	if (!pipe_->completeBuffer(camera_, request, buffer, info))
 		return;
 
-	/* Mark the request as complete. */
 	pipe_->completeRequest(camera_, request);
 }
 
@@ -965,10 +963,10 @@ void IPU3CameraData::imguOutputBufferReady(Buffer *buffer)
  * Buffers completed from the CIO2 are immediately queued to the ImgU unit
  * for further processing.
  */
-void IPU3CameraData::cio2BufferReady(Buffer *buffer)
+void IPU3CameraData::cio2BufferReady(Buffer *buffer, const BufferInfo &info)
 {
 	/* \todo Handle buffer failures when state is set to BufferError. */
-	if (buffer->status() == Buffer::BufferCancelled)
+	if (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 0803572754364beb..33a058de18b8cf2e 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
@@ -88,7 +88,7 @@ public:
 		setDelay(QueueBuffers, -1, 10);
 	}
 
-	void bufferReady(Buffer *buffer)
+	void bufferReady(Buffer *buffer, const BufferInfo &info)
 	{
 		/*
 		 * Calculate SOE by taking the end of DMA set by the kernel and applying
@@ -99,10 +99,10 @@ public:
 		ASSERT(frameOffset(SOE) == 0);
 
 		utils::time_point soe = std::chrono::time_point<utils::clock>()
-			+ std::chrono::nanoseconds(buffer->timestamp())
+			+ std::chrono::nanoseconds(info.timestamp())
 			+ timeOffset(SOE);
 
-		notifyStartOfExposure(buffer->sequence(), soe);
+		notifyStartOfExposure(info.sequence(), soe);
 	}
 
 	void setDelay(unsigned int type, int frame, int msdelay)
@@ -202,9 +202,9 @@ private:
 	int initLinks();
 	int createCamera(MediaEntity *sensor);
 	void tryCompleteRequest(Request *request);
-	void bufferReady(Buffer *buffer);
-	void paramReady(Buffer *buffer);
-	void statReady(Buffer *buffer);
+	void bufferReady(Buffer *buffer, const BufferInfo &info);
+	void paramReady(Buffer *buffer, const BufferInfo &info);
+	void statReady(Buffer *buffer, const BufferInfo &info);
 
 	MediaDevice *media_;
 	V4L2Subdevice *dphy_;
@@ -987,43 +987,43 @@ void PipelineHandlerRkISP1::tryCompleteRequest(Request *request)
 	data->frameInfo_.destroy(info->frame);
 }
 
-void PipelineHandlerRkISP1::bufferReady(Buffer *buffer)
+void PipelineHandlerRkISP1::bufferReady(Buffer *buffer, const BufferInfo &info)
 {
 	ASSERT(activeCamera_);
 	RkISP1CameraData *data = cameraData(activeCamera_);
 	Request *request = data->requestFromBuffer(buffer);
 
-	data->timeline_.bufferReady(buffer);
+	data->timeline_.bufferReady(buffer, info);
 
-	if (data->frame_ <= buffer->sequence())
-		data->frame_ = buffer->sequence() + 1;
+	if (data->frame_ <= info.sequence())
+		data->frame_ = info.sequence() + 1;
 
-	completeBuffer(activeCamera_, request, buffer);
+	completeBuffer(activeCamera_, request, buffer, info);
 	tryCompleteRequest(request);
 }
 
-void PipelineHandlerRkISP1::paramReady(Buffer *buffer)
+void PipelineHandlerRkISP1::paramReady(Buffer *buffer, const BufferInfo &info)
 {
 	ASSERT(activeCamera_);
 	RkISP1CameraData *data = cameraData(activeCamera_);
 
-	RkISP1FrameInfo *info = data->frameInfo_.find(buffer);
+	RkISP1FrameInfo *rkinfo = data->frameInfo_.find(buffer);
 
-	info->paramDequeued = true;
-	tryCompleteRequest(info->request);
+	rkinfo->paramDequeued = true;
+	tryCompleteRequest(rkinfo->request);
 }
 
-void PipelineHandlerRkISP1::statReady(Buffer *buffer)
+void PipelineHandlerRkISP1::statReady(Buffer *buffer, const BufferInfo &info)
 {
 	ASSERT(activeCamera_);
 	RkISP1CameraData *data = cameraData(activeCamera_);
 
-	RkISP1FrameInfo *info = data->frameInfo_.find(buffer);
-	if (!info)
+	RkISP1FrameInfo *rkinfo = data->frameInfo_.find(buffer);
+	if (!rkinfo)
 		return;
 
-	unsigned int frame = info->frame;
-	unsigned int statid = RKISP1_STAT_BASE | info->statBuffer->index();
+	unsigned int frame = rkinfo->frame;
+	unsigned int statid = RKISP1_STAT_BASE | rkinfo->statBuffer->index();
 
 	IPAOperationData op;
 	op.operation = RKISP1_IPA_EVENT_SIGNAL_STAT_BUFFER;
diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp
index 679d82d38227b991..ef2e8c9734f844ce 100644
--- a/src/libcamera/pipeline/uvcvideo.cpp
+++ b/src/libcamera/pipeline/uvcvideo.cpp
@@ -42,7 +42,7 @@ public:
 	}
 
 	int init(MediaEntity *entity);
-	void bufferReady(Buffer *buffer);
+	void bufferReady(Buffer *buffer, const BufferInfo &info);
 
 	V4L2VideoDevice *video_;
 	Stream *stream_;
@@ -373,11 +373,11 @@ int UVCCameraData::init(MediaEntity *entity)
 	return 0;
 }
 
-void UVCCameraData::bufferReady(Buffer *buffer)
+void UVCCameraData::bufferReady(Buffer *buffer, const BufferInfo &info)
 {
 	Request *request = requestFromBuffer(buffer);
 
-	pipe_->completeBuffer(camera_, request, buffer);
+	pipe_->completeBuffer(camera_, request, buffer, info);
 	pipe_->completeRequest(camera_, request);
 }
 
diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp
index 56898716a8cde074..e3eefc49135179f2 100644
--- a/src/libcamera/pipeline/vimc.cpp
+++ b/src/libcamera/pipeline/vimc.cpp
@@ -56,7 +56,7 @@ public:
 	}
 
 	int init(MediaDevice *media);
-	void bufferReady(Buffer *buffer);
+	void bufferReady(Buffer *buffer, const BufferInfo &info);
 
 	CameraSensor *sensor_;
 	V4L2Subdevice *debayer_;
@@ -458,11 +458,11 @@ int VimcCameraData::init(MediaDevice *media)
 	return 0;
 }
 
-void VimcCameraData::bufferReady(Buffer *buffer)
+void VimcCameraData::bufferReady(Buffer *buffer, const BufferInfo &info)
 {
 	Request *request = requestFromBuffer(buffer);
 
-	pipe_->completeBuffer(camera_, request, buffer);
+	pipe_->completeBuffer(camera_, request, buffer, info);
 	pipe_->completeRequest(camera_, request);
 }
 
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index d70e286661aded8e..9ce9432449e0e133 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -393,10 +393,11 @@ int PipelineHandler::queueRequest(Camera *camera, Request *request)
  * otherwise
  */
 bool PipelineHandler::completeBuffer(Camera *camera, Request *request,
-				     Buffer *buffer)
+				     Buffer *buffer, const BufferInfo &info)
 {
+	bool ret = request->completeBuffer(buffer, info);
 	camera->bufferCompleted.emit(request, buffer);
-	return request->completeBuffer(buffer);
+	return ret;
 }
 
 /**
diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp
index a9468ed4b0512a7f..9a0e439a3d05d780 100644
--- a/src/libcamera/request.cpp
+++ b/src/libcamera/request.cpp
@@ -252,12 +252,14 @@ void Request::complete()
  * \return True if all buffers contained in the request have completed, false
  * otherwise
  */
-bool Request::completeBuffer(Buffer *buffer)
+bool Request::completeBuffer(Buffer *buffer, const BufferInfo &info)
 {
 	int ret = pending_.erase(buffer);
 	ASSERT(ret == 1);
 
-	if (buffer->status() == Buffer::BufferCancelled)
+	info_.emplace(buffer, info);
+
+	if (info.status() == BufferInfo::BufferCancelled)
 		cancelled_ = true;
 
 	return !hasPendingBuffers();
diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
index 8bc2e439e4faeb68..97c6722b8c4c98cf 100644
--- a/src/libcamera/v4l2_videodevice.cpp
+++ b/src/libcamera/v4l2_videodevice.cpp
@@ -1119,14 +1119,16 @@ std::vector<std::unique_ptr<Buffer>> V4L2VideoDevice::queueAllBuffers()
 }
 
 /**
- * \brief Dequeue the next available buffer from the video device
+ * \brief Slot to handle completed buffer events from the V4L2 video device
+ * \param[in] notifier The event notifier
  *
- * This method dequeues the next available buffer from the device. If no buffer
- * is available to be dequeued it will return nullptr immediately.
+ * When this slot is called, a Buffer has become available from the device, and
+ * will be emitted through the bufferReady Signal.
  *
- * \return A pointer to the dequeued buffer on success, or nullptr otherwise
+ * For Capture video devices the Buffer will contain valid data.
+ * For Output video devices the Buffer can be considered empty.
  */
-Buffer *V4L2VideoDevice::dequeueBuffer()
+void V4L2VideoDevice::bufferAvailable(EventNotifier *notifier)
 {
 	struct v4l2_buffer buf = {};
 	struct v4l2_plane planes[VIDEO_MAX_PLANES] = {};
@@ -1144,10 +1146,10 @@ Buffer *V4L2VideoDevice::dequeueBuffer()
 	if (ret < 0) {
 		LOG(V4L2, Error)
 			<< "Failed to dequeue buffer: " << strerror(-ret);
-		return nullptr;
+		return;
 	}
 
-	ASSERT(buf.index < bufferPool_->count());
+	LOG(V4L2, Debug) << "Buffer " << buf.index << " is available";
 
 	auto it = queuedBuffers_.find(buf.index);
 	Buffer *buffer = it->second;
@@ -1156,37 +1158,16 @@ Buffer *V4L2VideoDevice::dequeueBuffer()
 	if (queuedBuffers_.empty())
 		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;
-
-	return buffer;
-}
+	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;
 
-/**
- * \brief Slot to handle completed buffer events from the V4L2 video device
- * \param[in] notifier The event notifier
- *
- * When this slot is called, a Buffer has become available from the device, and
- * will be emitted through the bufferReady Signal.
- *
- * For Capture video devices the Buffer will contain valid data.
- * For Output video devices the Buffer can be considered empty.
- */
-void V4L2VideoDevice::bufferAvailable(EventNotifier *notifier)
-{
-	Buffer *buffer = dequeueBuffer();
-	if (!buffer)
-		return;
-
-	LOG(V4L2, Debug) << "Buffer " << buffer->index() << " is available";
+	BufferInfo info(status, buf.sequence, timestamp, { { buf.bytesused } });
+	buffer->index_ = buf.index;
 
 	/* Notify anyone listening to the device. */
-	bufferReady.emit(buffer);
+	bufferReady.emit(buffer, info);
 }
 
 /**
@@ -1238,9 +1219,11 @@ int V4L2VideoDevice::streamOff()
 		unsigned int index = it.first;
 		Buffer *buffer = it.second;
 
+		BufferInfo info(BufferInfo::BufferCancelled, 0, 0, { {} });
+
 		buffer->index_ = index;
 		buffer->cancel();
-		bufferReady.emit(buffer);
+		bufferReady.emit(buffer, info);
 	}
 
 	queuedBuffers_.clear();
diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp
index cca7365ae75687f9..2d7f4ba84fbb6838 100644
--- a/src/qcam/main_window.cpp
+++ b/src/qcam/main_window.cpp
@@ -258,19 +258,19 @@ void MainWindow::requestComplete(Request *request)
 	framesCaptured_++;
 
 	Buffer *buffer = buffers.begin()->second;
+	const BufferInfo &info = request->info(buffer);
 
-	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()
-		  << " buf: " << buffer->index()
-		  << " bytesused: " << buffer->bytesused()
-		  << " timestamp: " << buffer->timestamp()
+	std::cout << "seq: " << std::setw(6) << std::setfill('0') << info.sequence()
+		  << " bytesused: " << info.plane(0).bytesused
+		  << " timestamp: " << info.timestamp()
 		  << " fps: " << std::fixed << std::setprecision(2) << fps
 		  << std::endl;
 
-	display(buffer);
+	display(buffer, info);
 
 	request = camera_->createRequest();
 	if (!request) {
@@ -295,7 +295,7 @@ void MainWindow::requestComplete(Request *request)
 	camera_->queueRequest(request);
 }
 
-int MainWindow::display(Buffer *buffer)
+int MainWindow::display(Buffer *buffer, const BufferInfo &info)
 {
 	BufferMemory *mem = buffer->mem();
 	if (mem->planes().size() != 1)
@@ -303,7 +303,7 @@ int MainWindow::display(Buffer *buffer)
 
 	Plane &plane = mem->planes().front();
 	unsigned char *raw = static_cast<unsigned char *>(plane.mem());
-	viewfinder_->display(raw, buffer->bytesused());
+	viewfinder_->display(raw, info.plane(0).bytesused);
 
 	return 0;
 }
diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h
index 78511581a8d5c025..8cbd72eb0d63cbea 100644
--- a/src/qcam/main_window.h
+++ b/src/qcam/main_window.h
@@ -50,7 +50,7 @@ private:
 	void stopCapture();
 
 	void requestComplete(Request *request);
-	int display(Buffer *buffer);
+	int display(Buffer *frame, const BufferInfo &info);
 
 	QString title_;
 	QTimer titleTimer_;
diff --git a/test/camera/capture.cpp b/test/camera/capture.cpp
index 83f974749affd3cd..3cf5b798448d01db 100644
--- a/test/camera/capture.cpp
+++ b/test/camera/capture.cpp
@@ -21,7 +21,9 @@ protected:
 
 	void bufferComplete(Request *request, Buffer *buffer)
 	{
-		if (buffer->status() != Buffer::BufferSuccess)
+		const BufferInfo &info = request->info(buffer);
+
+		if (info.status() != BufferInfo::BufferSuccess)
 			return;
 
 		completeBuffersCount_++;
diff --git a/test/v4l2_videodevice/buffer_sharing.cpp b/test/v4l2_videodevice/buffer_sharing.cpp
index 1629f34cfa6c79fe..3609c331cf10e056 100644
--- a/test/v4l2_videodevice/buffer_sharing.cpp
+++ b/test/v4l2_videodevice/buffer_sharing.cpp
@@ -90,24 +90,25 @@ protected:
 		return 0;
 	}
 
-	void captureBufferReady(Buffer *buffer)
+	void captureBufferReady(Buffer *buffer, const BufferInfo &info)
 	{
-		std::cout << "Received capture buffer: " << buffer->index()
-			  << " sequence " << buffer->sequence() << std::endl;
+		std::cout << "Received capture buffer  sequence "
+			  << info.sequence() << std::endl;
 
-		if (buffer->status() != Buffer::BufferSuccess)
+		if (info.status() != BufferInfo::BufferSuccess)
 			return;
 
+		BufferInfo infocopy = info;
 		output_->queueBuffer(buffer);
 		framesCaptured_++;
 	}
 
-	void outputBufferReady(Buffer *buffer)
+	void outputBufferReady(Buffer *buffer, const BufferInfo &info)
 	{
-		std::cout << "Received output buffer: " << buffer->index()
-			  << " sequence " << buffer->sequence() << std::endl;
+		std::cout << "Received output buffer sequence "
+			  << info.sequence() << std::endl;
 
-		if (buffer->status() != Buffer::BufferSuccess)
+		if (info.status() != BufferInfo::BufferSuccess)
 			return;
 
 		capture_->queueBuffer(buffer);
diff --git a/test/v4l2_videodevice/capture_async.cpp b/test/v4l2_videodevice/capture_async.cpp
index 442a4fe56eace57e..26ea1d17fd901ef8 100644
--- a/test/v4l2_videodevice/capture_async.cpp
+++ b/test/v4l2_videodevice/capture_async.cpp
@@ -20,9 +20,9 @@ public:
 	CaptureAsyncTest()
 		: V4L2VideoDeviceTest("vimc", "Raw Capture 0"), frames(0) {}
 
-	void receiveBuffer(Buffer *buffer)
+	void receiveBuffer(Buffer *buffer, const BufferInfo &info)
 	{
-		std::cout << "Received buffer " << buffer->index() << std::endl;
+		std::cout << "Received buffer" << std::endl;
 		frames++;
 
 		/* Requeue the buffer for further use. */
diff --git a/test/v4l2_videodevice/v4l2_m2mdevice.cpp b/test/v4l2_videodevice/v4l2_m2mdevice.cpp
index 4d3644c2d28792f1..e6ca90a4604dfcda 100644
--- a/test/v4l2_videodevice/v4l2_m2mdevice.cpp
+++ b/test/v4l2_videodevice/v4l2_m2mdevice.cpp
@@ -29,9 +29,9 @@ public:
 	{
 	}
 
-	void outputBufferComplete(Buffer *buffer)
+	void outputBufferComplete(Buffer *buffer, const BufferInfo &info)
 	{
-		cout << "Received output buffer " << buffer->index() << endl;
+		cout << "Received output buffer" << endl;
 
 		outputFrames_++;
 
@@ -39,9 +39,9 @@ public:
 		vim2m_->output()->queueBuffer(buffer);
 	}
 
-	void receiveCaptureBuffer(Buffer *buffer)
+	void receiveCaptureBuffer(Buffer *buffer, const BufferInfo &info)
 	{
-		cout << "Received capture buffer " << buffer->index() << endl;
+		cout << "Received capture buffer" << endl;
 
 		captureFrames_++;
 
