[libcamera-devel] [PATCH v2 2/3] qcam: Add a GUI way to use capture script

Utkarsh Tiwari utkarsh02t at gmail.com
Wed Jun 22 15:16:37 CEST 2022


Implement an Open Capture Script button which would allow the user
to open a Capture Script (*.yaml).
This button has two states Open and Stop.

Open state allows user to load a capture script.
When clicked in open state present them with a QFileDialog
to allow user to select a single file.

Stop state stops the execution of the current capture script.

Introduce a queueCount_ to keep track of the requests queued.

When stopping the execution no count is reset and the
capture continues as it is, this would allow better testing
as we can stop in between script and observe.

Initialize a Script Parser instance when the user selects
a valid capture script.

At queueRequest() time if script parser has been initialized,
then populate the Request::controls() with it at
queueRequest time providing the queueCount_.

The queueCount_ is incremented after the getting controls from
the parser, so the first request is for frame 0.

Signed-off-by: Utkarsh Tiwari <utkarsh02t at gmail.com>
---
 src/qcam/assets/feathericons/feathericons.qrc |  2 +
 src/qcam/main_window.cpp                      | 61 +++++++++++++++++++
 src/qcam/main_window.h                        |  7 +++
 src/qcam/meson.build                          |  2 +
 4 files changed, 72 insertions(+)

diff --git a/src/qcam/assets/feathericons/feathericons.qrc b/src/qcam/assets/feathericons/feathericons.qrc
index c5302040..6b08395a 100644
--- a/src/qcam/assets/feathericons/feathericons.qrc
+++ b/src/qcam/assets/feathericons/feathericons.qrc
@@ -3,9 +3,11 @@
 <qresource>
 	<file>aperture.svg</file>
 	<file>camera-off.svg</file>
+	<file>file.svg</file>
 	<file>play-circle.svg</file>
 	<file>save.svg</file>
 	<file>stop-circle.svg</file>
 	<file>x-circle.svg</file>
+	<file>x-square.svg</file>
 </qresource>
 </RCC>
diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp
index adeb3181..29da3947 100644
--- a/src/qcam/main_window.cpp
+++ b/src/qcam/main_window.cpp
@@ -20,6 +20,7 @@
 #include <QImage>
 #include <QImageWriter>
 #include <QInputDialog>
+#include <QMessageBox>
 #include <QMutexLocker>
 #include <QStandardPaths>
 #include <QStringList>
@@ -232,6 +233,13 @@ int MainWindow::createToolbars()
 	saveRaw_ = action;
 #endif
 
+	/* Open Script... action. */
+	action = toolbar_->addAction(QIcon::fromTheme("document-open",
+						      QIcon(":file.svg")),
+				     "Open Capture Script");
+	connect(action, &QAction::triggered, this, &MainWindow::chooseScript);
+	scriptExecAction_ = action;
+
 	return 0;
 }
 
@@ -255,6 +263,53 @@ void MainWindow::updateTitle()
 	setWindowTitle(title_ + " : " + QString::number(fps, 'f', 2) + " fps");
 }
 
+/**
+ * \brief Load a capture script for handling the capture session.
+ *
+ * If already capturing, it would restart the capture.
+ */
+void MainWindow::chooseScript()
+{
+	if (isScriptExecuting_) {
+		/*
+		 * This is the second valid press of load script button,
+		 * It indicates stopping, Stop and set button for new script
+		 */
+		script_.reset();
+		scriptExecAction_->setIcon(QIcon::fromTheme("document-open",
+							    QIcon(":file.svg")));
+		scriptExecAction_->setText("Open Capture Script");
+		isScriptExecuting_ = false;
+		return;
+	}
+
+	QString scriptFile = QFileDialog::getOpenFileName(this, "Open Capture Script", QDir::currentPath(),
+							  "Capture Script (*.yaml)");
+	if (scriptFile.isEmpty())
+		return;
+	script_ = std::make_unique<CaptureScript>(camera_, scriptFile.toStdString());
+	if (!script_->valid()) {
+		script_.reset();
+		QMessageBox::critical(this, "Invalid Script",
+					      "Couldn't load the capture script");
+		return;
+	}
+
+	/*
+	 * Valid script verified
+	 * Set the button to indicate stopping availibility
+	 */
+	scriptExecAction_->setIcon(QIcon(":x-square.svg"));
+	scriptExecAction_->setText("Stop Script execution");
+	isScriptExecuting_ = true;
+
+	/* Restart the capture so we can reset every counter */
+	if (isCapturing_) {
+		toggleCapture(false);
+		toggleCapture(true);
+	}
+}
+
 /* -----------------------------------------------------------------------------
  * Camera Selection
  */
@@ -510,6 +565,7 @@ int MainWindow::startCapture()
 	previousFrames_ = 0;
 	framesCaptured_ = 0;
 	lastBufferTime_ = 0;
+	queueCount_ = 0;
 
 	ret = camera_->start();
 	if (ret) {
@@ -789,5 +845,10 @@ void MainWindow::renderComplete(FrameBuffer *buffer)
 
 int MainWindow::queueRequest(Request *request)
 {
+	if (script_)
+		request->controls() = script_->frameControls(queueCount_);
+
+	queueCount_++;
+
 	return camera_->queueRequest(request);
 }
diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h
index c3e4b665..58df4e15 100644
--- a/src/qcam/main_window.h
+++ b/src/qcam/main_window.h
@@ -26,6 +26,7 @@
 #include <libcamera/request.h>
 #include <libcamera/stream.h>
 
+#include "../cam/capture_script.h"
 #include "../cam/stream_options.h"
 #include "viewfinder.h"
 
@@ -86,11 +87,14 @@ private:
 	void processHotplug(HotplugEvent *e);
 	void processViewfinder(libcamera::FrameBuffer *buffer);
 
+	void chooseScript();
+
 	/* UI elements */
 	QToolBar *toolbar_;
 	QAction *startStopAction_;
 	QComboBox *cameraCombo_;
 	QAction *saveRaw_;
+	QAction *scriptExecAction_;
 	ViewFinder *viewfinder_;
 
 	QIcon iconPlay_;
@@ -112,6 +116,7 @@ private:
 
 	/* Capture state, buffers queue and statistics */
 	bool isCapturing_;
+	bool isScriptExecuting_;
 	bool captureRaw_;
 	libcamera::Stream *vfStream_;
 	libcamera::Stream *rawStream_;
@@ -124,6 +129,8 @@ private:
 	QElapsedTimer frameRateInterval_;
 	uint32_t previousFrames_;
 	uint32_t framesCaptured_;
+	uint32_t queueCount_;
 
 	std::vector<std::unique_ptr<libcamera::Request>> requests_;
+	std::unique_ptr<CaptureScript> script_;
 };
diff --git a/src/qcam/meson.build b/src/qcam/meson.build
index c46f4631..67074252 100644
--- a/src/qcam/meson.build
+++ b/src/qcam/meson.build
@@ -15,6 +15,7 @@ endif
 qcam_enabled = true
 
 qcam_sources = files([
+    '../cam/capture_script.cpp',
     '../cam/image.cpp',
     '../cam/options.cpp',
     '../cam/stream_options.cpp',
@@ -37,6 +38,7 @@ qcam_resources = files([
 qcam_deps = [
     libatomic,
     libcamera_public,
+    libyaml,
     qt5_dep,
 ]
 
-- 
2.25.1



More information about the libcamera-devel mailing list