From patchwork Wed Sep 25 15:21:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 21370 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id D1E50C3257 for ; Wed, 25 Sep 2024 15:21:44 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D04126350E; Wed, 25 Sep 2024 17:21:43 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="M9+EBCBU"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0650C6350E for ; Wed, 25 Sep 2024 17:21:39 +0200 (CEST) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 67985A30; Wed, 25 Sep 2024 17:20:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1727277612; bh=Xb4kFu3MC60bJ9HiWNsd5B0IjQzz8KbAsaoIoSWqSgY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=M9+EBCBU64juZg7u6HBk1DvtZ2RRpMr+VeHrEhFfnuuwbUhTLTVAYbxqqykuIgTuo p8dCLVl12vEo6lqhg21pbv5Q9e2dT5/BxZfDsVnb104/X6Hf5PvNqOsiJ18Q9uKFyX +uyoBAS4hepuHF32JHB8Hun0vn7CE8TFHaY/8lkE= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Cc: Arne Caspari Subject: [PATCH 1/2] apps: Replace HAVE_DNG with HAVE_TIFF Date: Wed, 25 Sep 2024 18:21:33 +0300 Message-ID: <20240925152134.20284-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240925152134.20284-1-laurent.pinchart@ideasonboard.com> References: <20240925152134.20284-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Support for DNG capture is conditioned by the availability of libtiff, which is indicated by the HAVE_TIFF macro set by meson. The dng_writer.h header then defines HAVE_DNG, which is used is a couple of places to conditionally compile DNG-related code. Most of the other locations where conditional compilation is required use HAVE_TIFF. Using both HAVE_TIFF and HAVE_DNG is confusing. HAVE_DNG would be a better name, but as the macro is defined in dng_writer.h, it would require all files that need to test for DNG support to include that header. Failure to include it (directly or indirectly) would result in the code covered by the macro to be silently disabled. To avoid the confusion, standardize on using HAVE_TIFF everywhere and drop HAVE_DNG. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal Reviewed-by: Jacopo Mondi --- src/apps/common/dng_writer.h | 1 - src/apps/qcam/main_window.cpp | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/apps/common/dng_writer.h b/src/apps/common/dng_writer.h index 917713e61001..aaa8a852b307 100644 --- a/src/apps/common/dng_writer.h +++ b/src/apps/common/dng_writer.h @@ -8,7 +8,6 @@ #pragma once #ifdef HAVE_TIFF -#define HAVE_DNG #include #include diff --git a/src/apps/qcam/main_window.cpp b/src/apps/qcam/main_window.cpp index dd2aa19618a1..5144c6b3eb30 100644 --- a/src/apps/qcam/main_window.cpp +++ b/src/apps/qcam/main_window.cpp @@ -211,7 +211,7 @@ int MainWindow::createToolbars() action->setShortcut(QKeySequence::SaveAs); connect(action, &QAction::triggered, this, &MainWindow::saveImageAs); -#ifdef HAVE_DNG +#ifdef HAVE_TIFF /* Save Raw action. */ action = toolbar_->addAction(QIcon::fromTheme("camera-photo", QIcon(":aperture.svg")), @@ -646,7 +646,7 @@ void MainWindow::captureRaw() void MainWindow::processRaw(FrameBuffer *buffer, [[maybe_unused]] const ControlList &metadata) { -#ifdef HAVE_DNG +#ifdef HAVE_TIFF QString defaultPath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); QString filename = QFileDialog::getSaveFileName(this, "Save DNG", defaultPath, "DNG Files (*.dng)"); From patchwork Wed Sep 25 15:21:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 21371 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 4FB54C3257 for ; Wed, 25 Sep 2024 15:21:47 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 638476350E; Wed, 25 Sep 2024 17:21:46 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="oFehNpSU"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4E3C2634F4 for ; Wed, 25 Sep 2024 17:21:42 +0200 (CEST) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B5BDDA30; Wed, 25 Sep 2024 17:20:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1727277614; bh=ledoTUZWaXxhS0X5PpcpvRb5w95v4/FSCzoj14RHPJE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oFehNpSURpc/u2dRkuXMLWLWyf64hUa+4ACNYda13/QEYSSIgKRAOwDgqLFyC6Y5T 6RDGEMMP74EUaFn2dEwUKzL/DqusULd7KeFpjn5fOAQHlQNxmkRMGPZbIg54GRHQGS PEfksbWcI9bHL4orW0+dzq77gMQ2CwBbDS3tyDIU= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Cc: Arne Caspari Subject: [PATCH 2/2] apps: cam: Print an error when outputting DNG and DNG support is missing Date: Wed, 25 Sep 2024 18:21:34 +0300 Message-ID: <20240925152134.20284-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240925152134.20284-1-laurent.pinchart@ideasonboard.com> References: <20240925152134.20284-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" When DNG support is missing, the cam application ignores the .dng suffix of the file pattern and writes raw binary data instead, without notifying the user. This leads to confusion. Fix it by printing an error message. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal Reviewed-by: Jacopo Mondi --- src/apps/cam/camera_session.cpp | 15 ++++++--- src/apps/cam/file_sink.cpp | 60 +++++++++++++++++++++++---------- src/apps/cam/file_sink.h | 18 ++++++++-- 3 files changed, 68 insertions(+), 25 deletions(-) diff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp index 097dc479241a..227df9e922ea 100644 --- a/src/apps/cam/camera_session.cpp +++ b/src/apps/cam/camera_session.cpp @@ -230,11 +230,16 @@ int CameraSession::start() #endif if (options_.isSet(OptFile)) { - if (!options_[OptFile].toString().empty()) - sink_ = std::make_unique(camera_.get(), streamNames_, - options_[OptFile]); - else - sink_ = std::make_unique(camera_.get(), streamNames_); + std::unique_ptr sink = + std::make_unique(camera_.get(), streamNames_); + + if (!options_[OptFile].toString().empty()) { + ret = sink->setFilePattern(options_[OptFile]); + if (ret) + return ret; + } + + sink_ = std::move(sink); } if (sink_) { diff --git a/src/apps/cam/file_sink.cpp b/src/apps/cam/file_sink.cpp index 3e000d2fd9c6..76e21db9bf9a 100644 --- a/src/apps/cam/file_sink.cpp +++ b/src/apps/cam/file_sink.cpp @@ -5,6 +5,7 @@ * File Sink */ +#include #include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include @@ -24,13 +26,13 @@ using namespace libcamera; FileSink::FileSink([[maybe_unused]] const libcamera::Camera *camera, - const std::map &streamNames, - const std::string &pattern) + const std::map &streamNames) : #ifdef HAVE_TIFF camera_(camera), #endif - streamNames_(streamNames), pattern_(pattern) + pattern_(kDefaultFilePattern), fileType_(FileType::Binary), + streamNames_(streamNames) { } @@ -38,6 +40,41 @@ FileSink::~FileSink() { } +int FileSink::setFilePattern(const std::string &pattern) +{ + static const std::array, 2> types{{ + { ".dng", FileType::Dng }, + { ".ppm", FileType::Ppm }, + }}; + + pattern_ = pattern; + + if (pattern_.empty() || pattern_.back() == '/') + pattern_ += kDefaultFilePattern; + + fileType_ = FileType::Binary; + + for (const auto &type : types) { + if (pattern_.size() < type.first.size()) + continue; + + if (pattern_.find(type.first, pattern_.size() - type.first.size()) != + std::string::npos) { + fileType_ = type.second; + break; + } + } + +#ifndef HAVE_TIFF + if (fileType_ == FileType::Dng) { + std::cerr << "DNG support not available" << std::endl; + return -EINVAL; + } +#endif /* HAVE_TIFF */ + + return 0; +} + int FileSink::configure(const libcamera::CameraConfiguration &config) { int ret = FrameSink::configure(config); @@ -67,21 +104,10 @@ bool FileSink::processRequest(Request *request) void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer, [[maybe_unused]] const ControlList &metadata) { - std::string filename; + std::string filename = pattern_; size_t pos; int fd, ret = 0; - if (!pattern_.empty()) - filename = pattern_; - -#ifdef HAVE_TIFF - bool dng = filename.find(".dng", filename.size() - 4) != std::string::npos; -#endif /* HAVE_TIFF */ - bool ppm = filename.find(".ppm", filename.size() - 4) != std::string::npos; - - if (filename.empty() || filename.back() == '/') - filename += "frame-#.bin"; - pos = filename.find_first_of('#'); if (pos != std::string::npos) { std::stringstream ss; @@ -93,7 +119,7 @@ void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer, Image *image = mappedBuffers_[buffer].get(); #ifdef HAVE_TIFF - if (dng) { + if (fileType_ == FileType::Dng) { ret = DNGWriter::write(filename.c_str(), camera_, stream->configuration(), metadata, buffer, image->data(0).data()); @@ -104,7 +130,7 @@ void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer, return; } #endif /* HAVE_TIFF */ - if (ppm) { + if (fileType_ == FileType::Ppm) { ret = PPMWriter::write(filename.c_str(), stream->configuration(), image->data(0)); if (ret < 0) diff --git a/src/apps/cam/file_sink.h b/src/apps/cam/file_sink.h index 9d560783af09..71b7fe0feab5 100644 --- a/src/apps/cam/file_sink.h +++ b/src/apps/cam/file_sink.h @@ -21,10 +21,11 @@ class FileSink : public FrameSink { public: FileSink(const libcamera::Camera *camera, - const std::map &streamNames, - const std::string &pattern = ""); + const std::map &streamNames); ~FileSink(); + int setFilePattern(const std::string &pattern); + int configure(const libcamera::CameraConfiguration &config) override; void mapBuffer(libcamera::FrameBuffer *buffer) override; @@ -32,6 +33,14 @@ public: bool processRequest(libcamera::Request *request) override; private: + static constexpr const char *kDefaultFilePattern = "frame-#.bin"; + + enum class FileType { + Binary, + Dng, + Ppm, + }; + void writeBuffer(const libcamera::Stream *stream, libcamera::FrameBuffer *buffer, const libcamera::ControlList &metadata); @@ -39,7 +48,10 @@ private: #ifdef HAVE_TIFF const libcamera::Camera *camera_; #endif - std::map streamNames_; + std::string pattern_; + FileType fileType_; + + std::map streamNames_; std::map> mappedBuffers_; };