qcam: Add RAW capture support

Add a toolbar button that captures RAW data to disk. The button is only
enabled if the camera is configured to provide a raw stream to the
application.

Only when the capture action is triggered will a request with a raw
buffer be queued to the camera.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
Niklas Söderlund 2020-04-29 16:59:15 +02:00
parent db7235b714
commit b20eb8ffb5
3 changed files with 72 additions and 1 deletions

View file

@ -27,6 +27,8 @@
#include <libcamera/camera_manager.h>
#include <libcamera/version.h>
#include "dng_writer.h"
using namespace libcamera;
/**
@ -48,7 +50,8 @@ public:
};
MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options)
: options_(options), cm_(cm), allocator_(nullptr), isCapturing_(false)
: saveRaw_(nullptr), options_(options), cm_(cm), allocator_(nullptr),
isCapturing_(false), captureRaw_(false)
{
int ret;
@ -144,6 +147,16 @@ int MainWindow::createToolbars()
action->setShortcut(QKeySequence::SaveAs);
connect(action, &QAction::triggered, this, &MainWindow::saveImageAs);
#ifdef HAVE_DNG
/* Save Raw action. */
action = toolbar_->addAction(QIcon::fromTheme("camera-photo",
QIcon(":aperture.svg")),
"Save Raw");
action->setEnabled(false);
connect(action, &QAction::triggered, this, &MainWindow::captureRaw);
saveRaw_ = action;
#endif
return 0;
}
@ -369,6 +382,10 @@ int MainWindow::startCapture()
adjustSize();
/* Configure the raw capture button. */
if (saveRaw_)
saveRaw_->setEnabled(config_->size() == 2);
/* Allocate and map buffers. */
allocator_ = new FrameBufferAllocator(camera_);
for (StreamConfiguration &config : *config_) {
@ -474,6 +491,9 @@ void MainWindow::stopCapture()
return;
viewfinder_->stop();
if (saveRaw_)
saveRaw_->setEnabled(false);
captureRaw_ = false;
int ret = camera_->stop();
if (ret)
@ -524,6 +544,32 @@ void MainWindow::saveImageAs()
writer.write(image);
}
void MainWindow::captureRaw()
{
captureRaw_ = true;
}
void MainWindow::processRaw(FrameBuffer *buffer)
{
#ifdef HAVE_DNG
QString defaultPath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
QString filename = QFileDialog::getSaveFileName(this, "Save DNG", defaultPath,
"DNG Files (*.dng)");
if (!filename.isEmpty()) {
const MappedBuffer &mapped = mappedBuffers_[buffer];
DNGWriter::write(filename.toStdString().c_str(), camera_.get(),
rawStream_->configuration(), buffer,
mapped.memory);
}
#endif
{
QMutexLocker locker(&mutex_);
freeBuffers_[rawStream_].enqueue(buffer);
}
}
/* -----------------------------------------------------------------------------
* Request Completion Handling
*/
@ -566,6 +612,9 @@ void MainWindow::processCapture()
/* Process buffers. */
if (buffers.count(vfStream_))
processViewfinder(buffers[vfStream_]);
if (buffers.count(rawStream_))
processRaw(buffers[rawStream_]);
}
void MainWindow::processViewfinder(FrameBuffer *buffer)
@ -598,5 +647,22 @@ void MainWindow::queueRequest(FrameBuffer *buffer)
request->addBuffer(vfStream_, buffer);
if (captureRaw_) {
FrameBuffer *buffer = nullptr;
{
QMutexLocker locker(&mutex_);
if (!freeBuffers_[rawStream_].isEmpty())
buffer = freeBuffers_[rawStream_].dequeue();
}
if (buffer) {
request->addBuffer(rawStream_, buffer);
captureRaw_ = false;
} else {
qWarning() << "No free buffer available for RAW capture";
}
}
camera_->queueRequest(request);
}