From patchwork Fri Feb 14 00:18:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 2826 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3C635600FB for ; Fri, 14 Feb 2020 01:18:14 +0100 (CET) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id ABC619D3; Fri, 14 Feb 2020 01:18:13 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1581639493; bh=AzL5UoPbhR066r1KELklVWXAMFIrvOVlhJ+NTafcCcQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JOPz5fl8XByYPGGT+o/Szgcaqbtv95iLWAReZbWAHt+KlnMKu1/LVqHFiHA4ctp7L yKTxM9ogzYHS8yqJYC6mltvnY66znjarOaDzHwzfDRdxdp38VIM7WxXKd3k0Ls9tUF 48eqts29UFtbddE9uw29azmSge6I8XUR/YIcJ3vI= From: Kieran Bingham To: libcamera devel Date: Fri, 14 Feb 2020 00:18:04 +0000 Message-Id: <20200214001810.19302-2-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200214001810.19302-1-kieran.bingham@ideasonboard.com> References: <20200214001810.19302-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 1/7] qcam: Tie FrameBufferAllocator to stream life 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: , X-List-Received-Date: Fri, 14 Feb 2020 00:18:14 -0000 The FrameBufferAllocator must be deleted and reconstructed before performing any reconfiguration of the stream. Construct the allocator at startCapture, and destroy it during stopCapture so that we can successfully stop and restart the stream. Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- v2: - Remove unnecessary braces - Clean up in start_capture() error path. src/qcam/main_window.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index 70a3e61c66d8..db14245d7f51 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -36,10 +36,8 @@ MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options) adjustSize(); ret = openCamera(cm); - if (!ret) { - allocator_ = FrameBufferAllocator::create(camera_); + if (!ret) ret = startCapture(); - } if (ret < 0) QTimer::singleShot(0, QCoreApplication::instance(), @@ -50,7 +48,6 @@ MainWindow::~MainWindow() { if (camera_) { stopCapture(); - delete allocator_; camera_->release(); camera_.reset(); } @@ -171,6 +168,7 @@ int MainWindow::startCapture() adjustSize(); + allocator_ = FrameBufferAllocator::create(camera_); ret = allocator_->allocate(stream); if (ret < 0) { std::cerr << "Failed to allocate capture buffers" << std::endl; @@ -236,6 +234,9 @@ error: } mappedBuffers_.clear(); + delete allocator_; + allocator_ = nullptr; + return ret; } @@ -255,6 +256,8 @@ void MainWindow::stopCapture() } mappedBuffers_.clear(); + delete allocator_; + isCapturing_ = false; config_.reset(); From patchwork Fri Feb 14 00:18:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 2827 Return-Path: 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 78BE861A27 for ; Fri, 14 Feb 2020 01:18:14 +0100 (CET) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0EFEDACB; Fri, 14 Feb 2020 01:18:14 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1581639494; bh=ShGOxG420dnZpKSx4t3QMA9CliIH3Z8xwUWWjw5g+sM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lUE8d8Pnb1g56012UZAKKseqJZNNXd2YwEqem5vUdQKHZ7O2sQrxvX4l02tsYOtId QMrpgRX4yOaaAS0CqfKFS94WG69oLw849ohWb1K39CgK7DPNHhVxmzRXASvazsPcrF zWH6uhYTs/WdNKI5v+WcXNC2pUHQ6MqGnVu+9Flk= From: Kieran Bingham To: libcamera devel Date: Fri, 14 Feb 2020 00:18:05 +0000 Message-Id: <20200214001810.19302-3-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200214001810.19302-1-kieran.bingham@ideasonboard.com> References: <20200214001810.19302-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 2/7] qcam: Move requestCompleted signal mapping 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: , X-List-Received-Date: Fri, 14 Feb 2020 00:18:14 -0000 The MainWindow connects a handler to the Camera requestCompleted signal when the camera is opened, but never disconnects it. Move the connection to the startCapture() function, and ensure that it is disconnected again when the stream is stopped. This ensures that we can successfully tear down the stream, and restart with a new camera. Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/qcam/main_window.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index db14245d7f51..38d7063363f0 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -113,8 +113,6 @@ int MainWindow::openCamera(CameraManager *cm) std::cout << "Using camera " << camera_->name() << std::endl; - camera_->requestCompleted.connect(this, &MainWindow::requestComplete); - return 0; } @@ -212,17 +210,23 @@ int MainWindow::startCapture() goto error; } + camera_->requestCompleted.connect(this, &MainWindow::requestComplete); + for (Request *request : requests) { ret = camera_->queueRequest(request); if (ret < 0) { std::cerr << "Can't queue request" << std::endl; - goto error; + goto error_disconnect; } } isCapturing_ = true; return 0; +error_disconnect: + camera_->requestCompleted.disconnect(this, &MainWindow::requestComplete); + camera_->stop(); + error: for (Request *request : requests) delete request; @@ -249,6 +253,8 @@ void MainWindow::stopCapture() if (ret) std::cout << "Failed to stop capture" << std::endl; + camera_->requestCompleted.disconnect(this, &MainWindow::requestComplete); + for (auto &iter : mappedBuffers_) { void *memory = iter.second.first; unsigned int length = iter.second.second; From patchwork Fri Feb 14 00:18:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 2828 Return-Path: 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 BB24461A27 for ; Fri, 14 Feb 2020 01:18:14 +0100 (CET) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 59A00504; Fri, 14 Feb 2020 01:18:14 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1581639494; bh=PJBD0BJO2bAlaBlEtXIWFNa5qk3+v/4RVxho7ZVDOV4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Raazh/rJeIEazSpBQkyhBy0poJzEuTkvF8N1EoVCa6ks3iVKwoqvwyKoeaDd7lq5a bl6ASEq48TTDChVEBskkrboFyewh7U36ULG2pnA/tGJhTysL84yved2D6Nc4bmRvvl UWymSXT8rq5exyQ6FLd56JkLpwxQoA9aBA8208Ms= From: Kieran Bingham To: libcamera devel Date: Fri, 14 Feb 2020 00:18:06 +0000 Message-Id: <20200214001810.19302-4-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200214001810.19302-1-kieran.bingham@ideasonboard.com> References: <20200214001810.19302-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 3/7] qcam: Store CameraManager as class member 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: , X-List-Received-Date: Fri, 14 Feb 2020 00:18:14 -0000 Intialise a local copy of the CameraManager instance to ease access to the CameraManager which is frequently utilised. Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/qcam/main_window.cpp | 18 +++++++++--------- src/qcam/main_window.h | 5 +++-- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index 38d7063363f0..2ed84cacf655 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -23,7 +23,7 @@ using namespace libcamera; MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options) - : options_(options), allocator_(nullptr), isCapturing_(false) + : options_(options), cm_(cm), allocator_(nullptr), isCapturing_(false) { int ret; @@ -35,7 +35,7 @@ MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options) setCentralWidget(viewfinder_); adjustSize(); - ret = openCamera(cm); + ret = openCamera(); if (!ret) ret = startCapture(); @@ -66,15 +66,15 @@ void MainWindow::updateTitle() setWindowTitle(title_ + " : " + QString::number(fps, 'f', 2) + " fps"); } -std::string MainWindow::chooseCamera(CameraManager *cm) +std::string MainWindow::chooseCamera() { QStringList cameras; bool result; - if (cm->cameras().size() == 1) - return cm->cameras()[0]->name(); + if (cm_->cameras().size() == 1) + return cm_->cameras()[0]->name(); - for (const std::shared_ptr &cam : cm->cameras()) + for (const std::shared_ptr &cam : cm_->cameras()) cameras.append(QString::fromStdString(cam->name())); QString name = QInputDialog::getItem(this, "Select Camera", @@ -86,19 +86,19 @@ std::string MainWindow::chooseCamera(CameraManager *cm) return name.toStdString(); } -int MainWindow::openCamera(CameraManager *cm) +int MainWindow::openCamera() { std::string cameraName; if (options_.isSet(OptCamera)) cameraName = static_cast(options_[OptCamera]); else - cameraName = chooseCamera(cm); + cameraName = chooseCamera(); if (cameraName == "") return -EINVAL; - camera_ = cm->get(cameraName); + camera_ = cm_->get(cameraName); if (!camera_) { std::cout << "Camera " << cameraName << " not found" << std::endl; diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h index 04fb9e3ea869..d19cda16e36b 100644 --- a/src/qcam/main_window.h +++ b/src/qcam/main_window.h @@ -44,8 +44,8 @@ private Q_SLOTS: void updateTitle(); private: - std::string chooseCamera(CameraManager *cm); - int openCamera(CameraManager *cm); + std::string chooseCamera(); + int openCamera(); int startCapture(); void stopCapture(); @@ -58,6 +58,7 @@ private: const OptionsParser::Options &options_; + CameraManager *cm_; std::shared_ptr camera_; FrameBufferAllocator *allocator_; From patchwork Fri Feb 14 00:18:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 2829 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0AD1A61A2B for ; Fri, 14 Feb 2020 01:18:15 +0100 (CET) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A31179D3; Fri, 14 Feb 2020 01:18:14 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1581639494; bh=n8Ke77ofzJzoVF6fV89MLufSYAARGKeBWO4ic7rqD7U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OLP0PQne3AE7KSYTDyZyAdgUw1ILYgVZc4Xa8dtlNR/y+etPdAl+cPvOAeZih3Frp ZZnd4T7hSDm8NDnLVwacdtsEhhKKhDOddVbxCLmasCUW7DOmvG6xQjnB+1dLtgaBG9 dvfsIWr+vOqbK8LhsT4illUg2k7072PTZHKodl2o= From: Kieran Bingham To: libcamera devel Date: Fri, 14 Feb 2020 00:18:07 +0000 Message-Id: <20200214001810.19302-5-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200214001810.19302-1-kieran.bingham@ideasonboard.com> References: <20200214001810.19302-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 4/7] qcam: Introduce a toolbar and camera switching 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: , X-List-Received-Date: Fri, 14 Feb 2020 00:18:15 -0000 Implement a quit button, and a list of cameras. Selecting a different camera from the Toolbar will stop the current stream, and start streaming the chosen camera device if it can be acquired. Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- v2: - Add name to toolbar - Rename setCamera to switchCamera - Disable right click context menu on toolbar. - Utilise a combo box for camera selections - Squash in "qcam: Expose quit method for MainWindow" src/qcam/main_window.cpp | 64 ++++++++++++++++++++++++++++++++++++++-- src/qcam/main_window.h | 5 ++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index 2ed84cacf655..0e9e717b7e1a 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -10,9 +10,12 @@ #include #include +#include #include #include #include +#include +#include #include #include @@ -27,6 +30,8 @@ MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options) { int ret; + createToolbars(); + title_ = "QCam " + QString::fromStdString(CameraManager::version()); setWindowTitle(title_); connect(&titleTimer_, SIGNAL(timeout()), this, SLOT(updateTitle())); @@ -40,8 +45,7 @@ MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options) ret = startCapture(); if (ret < 0) - QTimer::singleShot(0, QCoreApplication::instance(), - &QCoreApplication::quit); + quit(); } MainWindow::~MainWindow() @@ -53,6 +57,39 @@ MainWindow::~MainWindow() } } +int MainWindow::createToolbars() +{ + QAction *action; + + toolbar_ = addToolBar("Main"); + + /* Disable right click context menu */ + toolbar_->setContextMenuPolicy(Qt::PreventContextMenu); + + action = toolbar_->addAction("Quit"); + connect(action, &QAction::triggered, this, &MainWindow::quit); + + /* Camera selection */ + QComboBox *cameraCombo = new QComboBox(); + connect(cameraCombo, QOverload::of(&QComboBox::activated), + this, &MainWindow::switchCamera); + + for (const std::shared_ptr &cam : cm_->cameras()) + cameraCombo->addItem(QString::fromStdString(cam->name())); + + toolbar_->addWidget(cameraCombo); + + toolbar_->addSeparator(); + + return 0; +} + +void MainWindow::quit() +{ + QTimer::singleShot(0, QCoreApplication::instance(), + &QCoreApplication::quit); +} + void MainWindow::updateTitle() { unsigned int duration = frameRateInterval_.elapsed(); @@ -66,6 +103,29 @@ void MainWindow::updateTitle() setWindowTitle(title_ + " : " + QString::number(fps, 'f', 2) + " fps"); } +void MainWindow::switchCamera(int index) +{ + const auto &cameras = cm_->cameras(); + if (static_cast(index) >= cameras.size()) + return; + + const std::shared_ptr &cam = cameras[index]; + + if (cam->acquire()) { + std::cout << "Failed to acquire camera " << cam->name() << std::endl; + return; + } + + std::cout << "Switching to camera " << cam->name() << std::endl; + + stopCapture(); + + camera_->release(); + camera_ = cam; + + startCapture(); +} + std::string MainWindow::chooseCamera() { QStringList cameras; diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h index d19cda16e36b..12af103f87d0 100644 --- a/src/qcam/main_window.h +++ b/src/qcam/main_window.h @@ -41,9 +41,13 @@ public: ~MainWindow(); private Q_SLOTS: + void quit(); void updateTitle(); + void switchCamera(int index); + private: + int createToolbars(); std::string chooseCamera(); int openCamera(); @@ -71,6 +75,7 @@ private: uint32_t previousFrames_; uint32_t framesCaptured_; + QToolBar *toolbar_; ViewFinder *viewfinder_; std::map> mappedBuffers_; }; From patchwork Fri Feb 14 00:18:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 2830 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 681D861A2B for ; Fri, 14 Feb 2020 01:18:15 +0100 (CET) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id F06CC504; Fri, 14 Feb 2020 01:18:14 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1581639495; bh=btTeRoEcVXAdYvXpeK4CRGVgiQGML7KYqrNkpbcE8y8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OxnDG64vSGBFsJq19TPastz+mUODgzJRA9cC14kMLBlVJ3OWac2sIUtC06VXwsFAu 49b638GKW6LfjKpUh3He/tz6Z9cnMWyMLxAwyCNofiNqoWjDo8Fpr3f7/qbaWTYXvf KPmQu9Xk93Suc1DPPdazDgBeHLy3nFHf73zS5MnA= From: Kieran Bingham To: libcamera devel Date: Fri, 14 Feb 2020 00:18:08 +0000 Message-Id: <20200214001810.19302-6-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200214001810.19302-1-kieran.bingham@ideasonboard.com> References: <20200214001810.19302-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 5/7] qcam: assets: Provide initial icon set 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: , X-List-Received-Date: Fri, 14 Feb 2020 00:18:15 -0000 Provide simple clean icons from https://feathericons.com/ (https://github.com/feathericons/feather) These are provided under the MIT license. Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/qcam/assets/feathericons/README.md | 5 +++++ src/qcam/assets/feathericons/*.svg | 1 + (*282) 283 files changed, 287 insertions(+) create mode 100644 src/qcam/assets/feathericons/README.md create mode 100644 src/qcam/assets/feathericons/*.svg diff --git a/src/qcam/assets/feathericons/README.md b/src/qcam/assets/feathericons/README.md new file mode 100644 index 000000000000..ce7664f6bf16 --- /dev/null +++ b/src/qcam/assets/feathericons/README.md @@ -0,0 +1,5 @@ +Icons from https://feathericons.com/ +License: MIT + +Generate the QRC file with: + rcc --project diff --git a/src/qcam/assets/feathericons/activity.svg b/src/qcam/assets/feathericons/activity.svg new file mode 100644 index 000000000000..669a57a772fa --- /dev/null +++ b/src/qcam/assets/feathericons/activity.svg @@ -0,0 +1 @@ + \ No newline at end of file From patchwork Fri Feb 14 00:18:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 2831 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BE10A61A2B for ; Fri, 14 Feb 2020 01:18:15 +0100 (CET) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 51CE99D3; Fri, 14 Feb 2020 01:18:15 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1581639495; bh=k6FWYGdYMSBVyrZG+Il02eJbl1ph4eBQhghcDofRDAo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TwLJIS/Eyjvd1iOFCRW1suVIbnROVPMm6aj4apncF5cBaEYDWLIhbn+fEm8LcSTOK OlEkjKU3y7U4kOnzMQlBB62BSE9CH0EwQ9jXnjeZs519s244xaHx4FhYZavLTdP1Oz k+INOD2QXS6vvPQKW+VF4DUDEkJrPi5j9+hcYPoA= From: Kieran Bingham To: libcamera devel Date: Fri, 14 Feb 2020 00:18:09 +0000 Message-Id: <20200214001810.19302-7-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200214001810.19302-1-kieran.bingham@ideasonboard.com> References: <20200214001810.19302-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 6/7] qcam: Provide initial icon buttons "Play/Stop" 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: , X-List-Received-Date: Fri, 14 Feb 2020 00:18:16 -0000 Provide Quit, Play, Stop icons. Create a Qt resource to compile icons into the binary and present them on the toolbar. Update the Quit button with a 'cross', and implement Play/Stop buttons. Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- v2 - Remove pause button src/qcam/assets/feathericons/feathericons.qrc | 7 +++++++ src/qcam/main_window.cpp | 9 ++++++++- src/qcam/main_window.h | 6 +++--- src/qcam/meson.build | 9 +++++++-- 4 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 src/qcam/assets/feathericons/feathericons.qrc diff --git a/src/qcam/assets/feathericons/feathericons.qrc b/src/qcam/assets/feathericons/feathericons.qrc new file mode 100644 index 000000000000..b8e5c2266408 --- /dev/null +++ b/src/qcam/assets/feathericons/feathericons.qrc @@ -0,0 +1,7 @@ + + +./play-circle.svg +./stop-circle.svg +./x-circle.svg + + diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index 0e9e717b7e1a..ec93e0177b41 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -66,7 +67,7 @@ int MainWindow::createToolbars() /* Disable right click context menu */ toolbar_->setContextMenuPolicy(Qt::PreventContextMenu); - action = toolbar_->addAction("Quit"); + action = toolbar_->addAction(QIcon(":x-circle.svg"), "Quit"); connect(action, &QAction::triggered, this, &MainWindow::quit); /* Camera selection */ @@ -81,6 +82,12 @@ int MainWindow::createToolbars() toolbar_->addSeparator(); + action = toolbar_->addAction(QIcon(":play-circle.svg"), "start"); + connect(action, &QAction::triggered, this, &MainWindow::startCapture); + + action = toolbar_->addAction(QIcon(":stop-circle.svg"), "stop"); + connect(action, &QAction::triggered, this, &MainWindow::stopCapture); + return 0; } diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h index 12af103f87d0..27ceed611d59 100644 --- a/src/qcam/main_window.h +++ b/src/qcam/main_window.h @@ -46,14 +46,14 @@ private Q_SLOTS: void switchCamera(int index); + int startCapture(); + void stopCapture(); + private: int createToolbars(); std::string chooseCamera(); int openCamera(); - int startCapture(); - void stopCapture(); - void requestComplete(Request *request); int display(FrameBuffer *buffer); diff --git a/src/qcam/meson.build b/src/qcam/meson.build index 1e71f20fa15e..5b877a84da85 100644 --- a/src/qcam/meson.build +++ b/src/qcam/meson.build @@ -11,6 +11,10 @@ qcam_moc_headers = files([ 'main_window.h', ]) +qcam_resources = files([ + 'assets/feathericons/feathericons.qrc', +]) + qt5 = import('qt5') qt5_dep = dependency('qt5', method : 'pkg-config', @@ -30,10 +34,11 @@ if qt5_dep.found() endif endif - moc_files = qt5.preprocess(moc_headers: qcam_moc_headers, + resources = qt5.preprocess(moc_headers: qcam_moc_headers, + qresources : qcam_resources, dependencies: qt5_dep) - qcam = executable('qcam', qcam_sources, moc_files, + qcam = executable('qcam', qcam_sources, resources, install : true, dependencies : [libcamera_dep, qt5_dep], cpp_args : qt5_cpp_args) From patchwork Fri Feb 14 00:18:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 2832 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 14FDE61A2E for ; Fri, 14 Feb 2020 01:18:16 +0100 (CET) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A5323504; Fri, 14 Feb 2020 01:18:15 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1581639495; bh=EKTNFapm9xD4ofe37wUsen3sqcrcEp0sQRca5slKVno=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=L9yV2kmjQ0W+PekQzwPxDO/FIbMD9q/0uG615tso3yJiJZP8LgWjJ4g5sg1aMyzVL q7W3CnBqazzBCLz9uwEryFf/2I5XjD8y+0zQPGGfNSyNpoFBp2GJ9JY6ahdFGucz78 GUIMLYpJD2zdlWflnc+EJyVsy6vwEiO+kcM4AgCQ= From: Kieran Bingham To: libcamera devel Date: Fri, 14 Feb 2020 00:18:10 +0000 Message-Id: <20200214001810.19302-8-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200214001810.19302-1-kieran.bingham@ideasonboard.com> References: <20200214001810.19302-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 7/7] qcam: Provide save image functionality 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: , X-List-Received-Date: Fri, 14 Feb 2020 00:18:17 -0000 Implement a save image button on the toolbar which will take a current viewfinder image and present the user with a QFileDialog to allow them to choose where to save the image. Utilise the QImageWriter to perform the output task. Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- v2: - Rename save to saveAs - Add empty file check - Lock concurrent access to the ViewFinder image src/qcam/assets/feathericons/feathericons.qrc | 1 + src/qcam/main_window.cpp | 22 +++++++++++++++++++ src/qcam/main_window.h | 1 + src/qcam/viewfinder.cpp | 11 ++++++++++ src/qcam/viewfinder.h | 5 +++++ 5 files changed, 40 insertions(+) diff --git a/src/qcam/assets/feathericons/feathericons.qrc b/src/qcam/assets/feathericons/feathericons.qrc index b8e5c2266408..6ca3a846803c 100644 --- a/src/qcam/assets/feathericons/feathericons.qrc +++ b/src/qcam/assets/feathericons/feathericons.qrc @@ -1,6 +1,7 @@ ./play-circle.svg +./save.svg ./stop-circle.svg ./x-circle.svg diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index ec93e0177b41..8ee2a7d68c96 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -12,7 +12,10 @@ #include #include +#include #include +#include +#include #include #include #include @@ -88,6 +91,9 @@ int MainWindow::createToolbars() action = toolbar_->addAction(QIcon(":stop-circle.svg"), "stop"); connect(action, &QAction::triggered, this, &MainWindow::stopCapture); + action = toolbar_->addAction(QIcon(":save.svg"), "saveAs"); + connect(action, &QAction::triggered, this, &MainWindow::saveImageAs); + return 0; } @@ -339,6 +345,22 @@ void MainWindow::stopCapture() setWindowTitle(title_); } +void MainWindow::saveImageAs() +{ + QImage image = viewfinder_->getCurrentImage(); + + QString filename = QFileDialog::getSaveFileName(this, "Save Image", "", + "Image Files (*.png *.jpg *.jpeg)"); + + std::cerr << "Save image to " << filename.toStdString() << std::endl; + + if (filename == "") + return; + + QImageWriter writer(filename); + writer.write(image); +} + void MainWindow::requestComplete(Request *request) { if (request->status() == Request::RequestCancelled) diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h index 27ceed611d59..dcc39d7de948 100644 --- a/src/qcam/main_window.h +++ b/src/qcam/main_window.h @@ -48,6 +48,7 @@ private Q_SLOTS: int startCapture(); void stopCapture(); + void saveImageAs(); private: int createToolbars(); diff --git a/src/qcam/viewfinder.cpp b/src/qcam/viewfinder.cpp index 6de284d1b782..211926e185d3 100644 --- a/src/qcam/viewfinder.cpp +++ b/src/qcam/viewfinder.cpp @@ -6,6 +6,8 @@ */ #include +#include +#include #include #include "format_converter.h" @@ -23,10 +25,19 @@ ViewFinder::~ViewFinder() void ViewFinder::display(const unsigned char *raw, size_t size) { + QMutexLocker locker(&mutex_); + converter_.convert(raw, size, image_); update(); } +QImage ViewFinder::getCurrentImage() +{ + QMutexLocker locker(&mutex_); + + return *image_; +} + int ViewFinder::setFormat(unsigned int format, unsigned int width, unsigned int height) { diff --git a/src/qcam/viewfinder.h b/src/qcam/viewfinder.h index ef5fd45b264a..06e8034fce1d 100644 --- a/src/qcam/viewfinder.h +++ b/src/qcam/viewfinder.h @@ -7,6 +7,7 @@ #ifndef __QCAM_VIEWFINDER_H__ #define __QCAM_VIEWFINDER_H__ +#include #include #include "format_converter.h" @@ -23,6 +24,8 @@ public: unsigned int height); void display(const unsigned char *rgb, size_t size); + QImage getCurrentImage(); + protected: void paintEvent(QPaintEvent *) override; QSize sizeHint() const override; @@ -33,7 +36,9 @@ private: unsigned int height_; FormatConverter converter_; + QImage *image_; + QMutex mutex_; // Prevent concurrent access to image_ }; #endif /* __QCAM_VIEWFINDER__ */