From patchwork Sat Aug 10 01:13:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 1772 Return-Path: Received: from bin-mail-out-06.binero.net (bin-mail-out-06.binero.net [195.74.38.229]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 887FB61582 for ; Sat, 10 Aug 2019 03:13:56 +0200 (CEST) X-Halon-ID: 1a294aee-bb0c-11e9-bdc3-005056917a89 Authorized-sender: niklas@soderlund.pp.se Received: from wyvern.dyn.berto.se (unknown [155.4.79.45]) by bin-vsp-out-01.atm.binero.net (Halon) with ESMTPA id 1a294aee-bb0c-11e9-bdc3-005056917a89; Sat, 10 Aug 2019 03:13:47 +0200 (CEST) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 10 Aug 2019 03:13:31 +0200 Message-Id: <20190810011333.8731-3-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20190810011333.8731-1-niklas.soderlund@ragnatech.se> References: <20190810011333.8731-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 2/4] libcamera: pipeline: vimc: Switch to using the RGB/YUV Capture video node X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 10 Aug 2019 01:13:56 -0000 Linux commit 85ab1aa1fac17bcd ("media: vimc: deb: fix default sink bayer format") which is part of v5.2 changes the default media bus format for the debayer subdevices. This leads to a -EPIPE error when trying to use the raw capture video device nodes. Fix this by moving the vimc pipeline to use the RGB/YUV Capture capture video node. As a consequence of this change the scaler in the vimc pipeline is used and a hard coded upscale of 3 is present in the video pipeline. This limits the sizes exposed and accepted by libcamera to multiples of 3. Update the buffer import test case to match this new format constraint by setting the resolution to 1920x1080, a resolution which works with both vimc and vivid. With this new resolution the buffer import test takes a bit more time to complete 60 buffers and it's runtime also needs to be increased. The raw capture video node still needs to be handled by the pipeline as its format needs to be updated to allow the pipeline format validation to pass. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart --- src/libcamera/pipeline/vimc.cpp | 93 +++++++++++++++++++++++++++++---- test/camera/buffer_import.cpp | 10 ++-- 2 files changed, 89 insertions(+), 14 deletions(-) diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp index 3d6808222a8a2c5d..f8f91d6219b1aee4 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -10,6 +10,8 @@ #include #include +#include + #include #include #include @@ -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 400d02b350c1aa8f..98786469428f7f39 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();