[libcamera-devel] [PATCH v3 7/9] libcamera: pipeline: virtual: Generate and validate StreamConfigurations
Harvey Yang
chenghaoyang at chromium.org
Thu Jan 5 05:37:24 CET 2023
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 at chromium.org>
---
src/libcamera/pipeline/virtual/virtual.cpp | 140 +++++++++++++++++++--
1 file changed, 132 insertions(+), 8 deletions(-)
diff --git a/src/libcamera/pipeline/virtual/virtual.cpp b/src/libcamera/pipeline/virtual/virtual.cpp
index ba77d757..ef2901e7 100644
--- a/src/libcamera/pipeline/virtual/virtual.cpp
+++ b/src/libcamera/pipeline/virtual/virtual.cpp
@@ -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";
--
2.39.0.314.g84b9a713c41-goog
More information about the libcamera-devel
mailing list