summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libcamera/pipeline/vimc.cpp93
-rw-r--r--test/camera/buffer_import.cpp10
2 files changed, 89 insertions, 14 deletions
diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp
index 3d680822..f8f91d62 100644
--- a/src/libcamera/pipeline/vimc.cpp
+++ b/src/libcamera/pipeline/vimc.cpp
@@ -10,6 +10,8 @@
#include <iomanip>
#include <tuple>
+#include <linux/media-bus-format.h>
+
#include <libcamera/camera.h>
#include <libcamera/controls.h>
#include <libcamera/ipa/ipa_interface.h>
@@ -25,6 +27,7 @@
#include "pipeline_handler.h"
#include "utils.h"
#include "v4l2_controls.h"
+#include "v4l2_subdevice.h"
#include "v4l2_videodevice.h"
namespace libcamera {
@@ -35,21 +38,28 @@ class VimcCameraData : public CameraData
{
public:
VimcCameraData(PipelineHandler *pipe)
- : CameraData(pipe), video_(nullptr), sensor_(nullptr)
+ : CameraData(pipe), sensor_(nullptr), debayer_(nullptr),
+ scaler_(nullptr), video_(nullptr), raw_(nullptr)
{
}
~VimcCameraData()
{
delete sensor_;
+ delete debayer_;
+ delete scaler_;
delete video_;
+ delete raw_;
}
int init(MediaDevice *media);
void bufferReady(Buffer *buffer);
- V4L2VideoDevice *video_;
CameraSensor *sensor_;
+ V4L2Subdevice *debayer_;
+ V4L2Subdevice *scaler_;
+ V4L2VideoDevice *video_;
+ V4L2VideoDevice *raw_;
Stream stream_;
};
@@ -131,8 +141,11 @@ CameraConfiguration::Status VimcCameraConfiguration::validate()
/* Clamp the size based on the device limits. */
const Size size = cfg.size;
- cfg.size.width = std::max(16U, std::min(4096U, cfg.size.width));
- cfg.size.height = std::max(16U, std::min(2160U, cfg.size.height));
+ /* The scaler hardcodes a x3 scale-up ratio. */
+ cfg.size.width = std::max(48U, std::min(4096U, cfg.size.width));
+ cfg.size.height = std::max(48U, std::min(2160U, cfg.size.height));
+ cfg.size.width -= cfg.size.width % 3;
+ cfg.size.height -= cfg.size.height % 3;
if (cfg.size != size) {
LOG(VIMC, Debug)
@@ -160,7 +173,7 @@ CameraConfiguration *PipelineHandlerVimc::generateConfiguration(Camera *camera,
StreamConfiguration cfg{};
cfg.pixelFormat = V4L2_PIX_FMT_RGB24;
- cfg.size = { 640, 480 };
+ cfg.size = { 1920, 1080 };
cfg.bufferCount = 4;
config->addConfiguration(cfg);
@@ -176,6 +189,33 @@ int PipelineHandlerVimc::configure(Camera *camera, CameraConfiguration *config)
StreamConfiguration &cfg = config->at(0);
int ret;
+ /* The scaler hardcodes a x3 scale-up ratio. */
+ V4L2SubdeviceFormat subformat = {};
+ subformat.mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8;
+ subformat.size = { cfg.size.width / 3, cfg.size.height / 3 };
+
+ ret = data->sensor_->setFormat(&subformat);
+ if (ret)
+ return ret;
+
+ ret = data->debayer_->setFormat(0, &subformat);
+ if (ret)
+ return ret;
+
+ subformat.mbus_code = MEDIA_BUS_FMT_RGB888_1X24;
+ ret = data->debayer_->setFormat(1, &subformat);
+ if (ret)
+ return ret;
+
+ ret = data->scaler_->setFormat(0, &subformat);
+ if (ret)
+ return ret;
+
+ subformat.size = cfg.size;
+ ret = data->scaler_->setFormat(1, &subformat);
+ if (ret)
+ return ret;
+
V4L2DeviceFormat format = {};
format.fourcc = cfg.pixelFormat;
format.size = cfg.size;
@@ -188,6 +228,17 @@ int PipelineHandlerVimc::configure(Camera *camera, CameraConfiguration *config)
format.fourcc != cfg.pixelFormat)
return -EINVAL;
+ /*
+ * Format has to be set on the raw capture video node, otherwise the
+ * vimc driver will fail pipeline validation.
+ */
+ format.fourcc = V4L2_PIX_FMT_SGRBG8;
+ format.size = { cfg.size.width / 3, cfg.size.height / 3 };
+
+ ret = data->raw_->setFormat(&format);
+ if (ret)
+ return ret;
+
cfg.setStream(&data->stream_);
return 0;
@@ -335,18 +386,42 @@ int VimcCameraData::init(MediaDevice *media)
{
int ret;
- /* Create and open the video device and the camera sensor. */
- video_ = new V4L2VideoDevice(media->getEntityByName("Raw Capture 1"));
- if (video_->open())
+ ret = media->disableLinks();
+ if (ret < 0)
+ return ret;
+
+ MediaLink *link = media->link("Debayer B", 1, "Scaler", 0);
+ if (!link)
return -ENODEV;
- video_->bufferReady.connect(this, &VimcCameraData::bufferReady);
+ ret = link->setEnabled(true);
+ if (ret < 0)
+ return ret;
+ /* Create and open the camera sensor, debayer, scaler and video device. */
sensor_ = new CameraSensor(media->getEntityByName("Sensor B"));
ret = sensor_->init();
if (ret)
return ret;
+ debayer_ = new V4L2Subdevice(media->getEntityByName("Debayer B"));
+ if (debayer_->open())
+ return -ENODEV;
+
+ scaler_ = new V4L2Subdevice(media->getEntityByName("Scaler"));
+ if (scaler_->open())
+ return -ENODEV;
+
+ video_ = new V4L2VideoDevice(media->getEntityByName("RGB/YUV Capture"));
+ if (video_->open())
+ return -ENODEV;
+
+ video_->bufferReady.connect(this, &VimcCameraData::bufferReady);
+
+ raw_ = new V4L2VideoDevice(media->getEntityByName("Raw Capture 1"));
+ if (raw_->open())
+ return -ENODEV;
+
/* Initialise the supported controls. */
const V4L2ControlInfoMap &controls = sensor_->controls();
for (const auto &ctrl : controls) {
diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp
index 400d02b3..98786469 100644
--- a/test/camera/buffer_import.cpp
+++ b/test/camera/buffer_import.cpp
@@ -72,12 +72,12 @@ public:
return ret;
}
- format_.size.width = 640;
- format_.size.height = 480;
+ format_.size.width = 1920;
+ format_.size.height = 1080;
format_.fourcc = V4L2_PIX_FMT_RGB24;
format_.planesCount = 1;
- format_.planes[0].size = 640 * 480 * 3;
- format_.planes[0].bpl = 640 * 3;
+ format_.planes[0].size = 1920 * 1080 * 3;
+ format_.planes[0].bpl = 1920 * 3;
if (video_->setFormat(&format_)) {
cleanup();
@@ -378,7 +378,7 @@ protected:
EventDispatcher *dispatcher = CameraManager::instance()->eventDispatcher();
Timer timer;
- timer.start(3000);
+ timer.start(5000);
while (timer.isRunning() && !sink_.done())
dispatcher->processEvents();