diff --git a/src/libcamera/pipeline/virtual/virtual.cpp b/src/libcamera/pipeline/virtual/virtual.cpp
index 6221196c..ba77d757 100644
--- a/src/libcamera/pipeline/virtual/virtual.cpp
+++ b/src/libcamera/pipeline/virtual/virtual.cpp
@@ -9,6 +9,7 @@
 
 #include <libcamera/camera.h>
 
+#include "libcamera/internal/camera.h"
 #include "libcamera/internal/media_device_virtual.h"
 #include "libcamera/internal/pipeline_handler.h"
 
@@ -16,6 +17,19 @@ namespace libcamera {
 
 LOG_DEFINE_CATEGORY(VIRTUAL)
 
+class VirtualCameraData : public Camera::Private
+{
+public:
+	VirtualCameraData(PipelineHandler *pipe)
+		: Camera::Private(pipe)
+	{
+	}
+
+	~VirtualCameraData() = default;
+
+	Stream stream_;
+};
+
 class VirtualCameraConfiguration : public CameraConfiguration
 {
 public:
@@ -109,6 +123,14 @@ bool PipelineHandlerVirtual::match(DeviceEnumerator *enumerator)
 {
 	(void)enumerator;
 	mediaDevices_.push_back(mediaDeviceVirtual_);
+
+	std::unique_ptr<VirtualCameraData> data = std::make_unique<VirtualCameraData>(this);
+	/* Create and register the camera. */
+	std::set<Stream *> streams{ &data->stream_ };
+	const std::string id = "Virtual0";
+	std::shared_ptr<Camera> camera = Camera::create(std::move(data), id, streams);
+	registerCamera(std::move(camera));
+
 	return false; // Prevent infinite loops for now
 }
 
