diff --git a/src/android/camera_buffer.h b/src/android/camera_buffer.h
index 87df2570..226a8f5c 100644
--- a/src/android/camera_buffer.h
+++ b/src/android/camera_buffer.h
@@ -31,6 +31,10 @@ public:
 	libcamera::Span<const uint8_t> plane(unsigned int plane) const;
 	libcamera::Span<uint8_t> plane(unsigned int plane);
 
+	unsigned int stride(unsigned int plane) const;
+	unsigned int offset(unsigned int plane) const;
+	unsigned int size(unsigned int plane) const;
+
 	size_t jpegBufferSize(size_t maxJpegBufferSize) const;
 };
 
@@ -62,6 +66,18 @@ Span<uint8_t> CameraBuffer::plane(unsigned int plane)			\
 {									\
 	return _d()->plane(plane);					\
 }									\
+unsigned int CameraBuffer::stride(unsigned int plane) const		\
+{									\
+	return _d()->stride(plane);					\
+}									\
+unsigned int CameraBuffer::offset(unsigned int plane) const		\
+{									\
+	return _d()->offset(plane);					\
+}									\
+unsigned int CameraBuffer::size(unsigned int plane) const		\
+{									\
+	return _d()->size(plane);					\
+}									\
 size_t CameraBuffer::jpegBufferSize(size_t maxJpegBufferSize) const	\
 {									\
 	return _d()->jpegBufferSize(maxJpegBufferSize);			\
diff --git a/src/android/mm/cros_camera_buffer.cpp b/src/android/mm/cros_camera_buffer.cpp
index ba6650cf..44993379 100644
--- a/src/android/mm/cros_camera_buffer.cpp
+++ b/src/android/mm/cros_camera_buffer.cpp
@@ -31,6 +31,10 @@ public:
 
 	Span<uint8_t> plane(unsigned int plane);
 
+	unsigned int stride(unsigned int plane) const;
+	unsigned int offset(unsigned int plane) const;
+	unsigned int size(unsigned int plane) const;
+
 	size_t jpegBufferSize(size_t maxJpegBufferSize) const;
 
 private:
@@ -111,6 +115,21 @@ Span<uint8_t> CameraBuffer::Private::plane(unsigned int plane)
 		 bufferManager_->GetPlaneSize(handle_, plane) };
 }
 
+unsigned int CameraBuffer::Private::stride(unsigned int plane) const
+{
+	return cros::CameraBufferManager::GetPlaneStride(handle_, plane);
+}
+
+unsigned int CameraBuffer::Private::offset(unsigned int plane) const
+{
+	return cros::CameraBufferManager::GetPlaneOffset(handle_, plane);
+}
+
+unsigned int CameraBuffer::Private::size(unsigned int plane) const
+{
+	return cros::CameraBufferManager::GetPlaneSize(handle_, plane);
+}
+
 size_t CameraBuffer::Private::jpegBufferSize([[maybe_unused]] size_t maxJpegBufferSize) const
 {
 	return bufferManager_->GetPlaneSize(handle_, 0);
diff --git a/src/android/mm/generic_camera_buffer.cpp b/src/android/mm/generic_camera_buffer.cpp
index cfe55b69..4f0a3207 100644
--- a/src/android/mm/generic_camera_buffer.cpp
+++ b/src/android/mm/generic_camera_buffer.cpp
@@ -34,10 +34,15 @@ public:
 
 	Span<uint8_t> plane(unsigned int plane);
 
+	unsigned int stride(unsigned int plane) const;
+	unsigned int offset(unsigned int plane) const;
+	unsigned int size(unsigned int plane) const;
+
 	size_t jpegBufferSize(size_t maxJpegBufferSize) const;
 
 private:
 	struct PlaneInfo {
+		unsigned int stride;
 		unsigned int offset;
 		unsigned int size;
 	};
@@ -114,6 +119,7 @@ CameraBuffer::Private::Private([[maybe_unused]] CameraBuffer *cameraBuffer,
 		const unsigned int planeSize =
 			stride * ((size.height + vertSubSample - 1) / vertSubSample);
 
+		planeInfo_[i].stride = stride;
 		planeInfo_[i].offset = offset;
 		planeInfo_[i].size = planeSize;
 
@@ -148,6 +154,30 @@ Span<uint8_t> CameraBuffer::Private::plane(unsigned int plane)
 	return planes_[plane];
 }
 
+unsigned int CameraBuffer::Private::stride(unsigned int plane) const
+{
+	if (plane >= planeInfo_.size())
+		return 0;
+
+	return planeInfo_[plane].stride;
+}
+
+unsigned int CameraBuffer::Private::offset(unsigned int plane) const
+{
+	if (plane >= planeInfo_.size())
+		return 0;
+
+	return planeInfo_[plane].offset;
+}
+
+unsigned int CameraBuffer::Private::size(unsigned int plane) const
+{
+	if (plane >= planeInfo_.size())
+		return 0;
+
+	return planeInfo_[plane].size;
+}
+
 size_t CameraBuffer::Private::jpegBufferSize(size_t maxJpegBufferSize) const
 {
 	ASSERT(bufferLength_ >= 0);
