@@ -8,6 +8,7 @@
#include <libcamera/base/log.h>
#include <libcamera/camera.h>
+#include <libcamera/formats.h>
#include "libcamera/internal/camera.h"
#include "libcamera/internal/media_device_virtual.h"
@@ -20,6 +21,11 @@ LOG_DEFINE_CATEGORY(VIRTUAL)
class VirtualCameraData : public Camera::Private
{
public:
+ struct Resolution {
+ Size size;
+ std::vector<int> frame_rates;
+ std::vector<std::string> formats;
+ };
VirtualCameraData(PipelineHandler *pipe)
: Camera::Private(pipe)
{
@@ -27,15 +33,22 @@ public:
~VirtualCameraData() = default;
+ std::vector<Resolution> supportedResolutions_;
+
Stream stream_;
};
class VirtualCameraConfiguration : public CameraConfiguration
{
public:
- VirtualCameraConfiguration();
+ static constexpr unsigned int kBufferCount = 4; // 4~6
+
+ VirtualCameraConfiguration(VirtualCameraData *data);
Status validate() override;
+
+private:
+ const VirtualCameraData *data_;
};
class PipelineHandlerVirtual : public PipelineHandler
@@ -58,17 +71,56 @@ public:
bool match(DeviceEnumerator *enumerator) override;
private:
+ VirtualCameraData *cameraData(Camera *camera)
+ {
+ return static_cast<VirtualCameraData *>(camera->_d());
+ }
+
std::shared_ptr<MediaDeviceVirtual> mediaDeviceVirtual_;
};
-VirtualCameraConfiguration::VirtualCameraConfiguration()
- : CameraConfiguration()
+VirtualCameraConfiguration::VirtualCameraConfiguration(VirtualCameraData *data)
+ : CameraConfiguration(), data_(data)
{
}
CameraConfiguration::Status VirtualCameraConfiguration::validate()
{
- return Invalid;
+ Status status = Valid;
+
+ if (config_.empty()) {
+ LOG(VIRTUAL, Error) << "Empty config";
+ return Invalid;
+ }
+
+ // TODO: check if we should limit |config_.size()|
+
+ Size maxSize;
+ for (const auto &resolution : data_->supportedResolutions_)
+ maxSize = std::max(maxSize, resolution.size);
+
+ for (StreamConfiguration &cfg : config_) {
+ // TODO: check |cfg.pixelFormat|.
+
+ bool found = false;
+ for (const auto &resolution : data_->supportedResolutions_) {
+ if (resolution.size.width >= cfg.size.width && resolution.size.height >= cfg.size.height) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ cfg.size = maxSize;
+ status = Adjusted;
+ }
+
+ cfg.setStream(const_cast<Stream *>(&data_->stream_));
+
+ cfg.bufferCount = VirtualCameraConfiguration::kBufferCount;
+ }
+
+ return status;
}
PipelineHandlerVirtual::PipelineHandlerVirtual(CameraManager *manager)
@@ -79,16 +131,81 @@ PipelineHandlerVirtual::PipelineHandlerVirtual(CameraManager *manager)
std::unique_ptr<CameraConfiguration> PipelineHandlerVirtual::generateConfiguration(Camera *camera,
const StreamRoles &roles)
{
- (void)camera;
- (void)roles;
- return std::unique_ptr<VirtualCameraConfiguration>(nullptr);
+ VirtualCameraData *data = cameraData(camera);
+ auto config =
+ std::make_unique<VirtualCameraConfiguration>(data);
+
+ if (roles.empty())
+ return config;
+
+ Size minSize, sensorResolution;
+ for (const auto &resolution : data->supportedResolutions_) {
+ if (minSize.isNull() || minSize > resolution.size)
+ minSize = resolution.size;
+
+ sensorResolution = std::max(sensorResolution, resolution.size);
+ }
+
+ for (const StreamRole role : roles) {
+ std::map<PixelFormat, std::vector<SizeRange>> streamFormats;
+ unsigned int bufferCount;
+ PixelFormat pixelFormat;
+
+ switch (role) {
+ case StreamRole::StillCapture:
+ pixelFormat = formats::NV12;
+ bufferCount = VirtualCameraConfiguration::kBufferCount;
+ streamFormats[pixelFormat] = { { minSize, sensorResolution } };
+
+ break;
+
+ case StreamRole::Raw: {
+ // TODO: check
+ pixelFormat = formats::SBGGR10;
+ bufferCount = VirtualCameraConfiguration::kBufferCount;
+ streamFormats[pixelFormat] = { { minSize, sensorResolution } };
+
+ break;
+ }
+
+ case StreamRole::Viewfinder:
+ case StreamRole::VideoRecording: {
+ pixelFormat = formats::NV12;
+ bufferCount = VirtualCameraConfiguration::kBufferCount;
+ streamFormats[pixelFormat] = { { minSize, sensorResolution } };
+
+ break;
+ }
+
+ default:
+ LOG(VIRTUAL, Error)
+ << "Requested stream role not supported: " << role;
+ config.reset();
+ return config;
+ }
+
+ StreamFormats formats(streamFormats);
+ StreamConfiguration cfg(formats);
+ cfg.size = sensorResolution;
+ cfg.pixelFormat = pixelFormat;
+ cfg.bufferCount = bufferCount;
+ config->addConfiguration(cfg);
+ }
+
+ if (config->validate() == CameraConfiguration::Invalid) {
+ config.reset();
+ return config;
+ }
+
+ return config;
}
int PipelineHandlerVirtual::configure(Camera *camera, CameraConfiguration *config)
{
(void)camera;
(void)config;
- return -1;
+ // Nothing to be done.
+ return 0;
}
int PipelineHandlerVirtual::exportFrameBuffers(Camera *camera, Stream *stream,
@@ -124,7 +241,14 @@ bool PipelineHandlerVirtual::match(DeviceEnumerator *enumerator)
(void)enumerator;
mediaDevices_.push_back(mediaDeviceVirtual_);
+ // TODO: Add virtual cameras according to a config file.
+
std::unique_ptr<VirtualCameraData> data = std::make_unique<VirtualCameraData>(this);
+
+ data->supportedResolutions_.resize(2);
+ data->supportedResolutions_[0] = { .size = Size(1920, 1080), .frame_rates = { 30 }, .formats = { "YCbCr_420_888" } };
+ data->supportedResolutions_[1] = { .size = Size(1280, 720), .frame_rates = { 30, 60 }, .formats = { "YCbCr_420_888" } };
+
/* Create and register the camera. */
std::set<Stream *> streams{ &data->stream_ };
const std::string id = "Virtual0";
Implement the support for Generating and Validating the streams the Camera can provide. Currently use only one camera with fixed configuration. Will add a configuration file to specify virtual cameras. In |PipelineHandlerVirtual::configure|, nothing needs to be done. Test the configurations can be generated and reported with cam -I: """ build/src/apps/cam/cam -c 1 -I [45:19:28.901456135] [2611530] INFO IPAManager ipa_manager.cpp:143 libcamera is not installed. Adding '/usr/local/google/home/chenghaoyang/cros2/src/third_party/libcamera/build/src /ipa' to the IPA search path [45:19:28.904364465] [2611530] INFO Camera camera_manager.cpp:293 libcamera v0.0.1+56-4f4554fa-dirty (2022-12-07T06:55:04+00:00) Using camera Virtual0 as cam0 0: 1920x1080-NV12 * Pixelformat: NV12 (1280x720)-(1920x1080)/(+1,+1) - 1280x720 - 1280x800 - 1360x768 - 1366x768 - 1440x900 - 1280x1024 - 1536x864 - 1280x1080 - 1600x900 - 1400x1050 - 1680x1050 - 1920x1080 """ Signed-off-by: Harvey Yang <chenghaoyang@chromium.org> --- src/libcamera/pipeline/virtual/virtual.cpp | 140 +++++++++++++++++++-- 1 file changed, 132 insertions(+), 8 deletions(-)