Files
external_libcamera/src/qcam/main_window.cpp
Kieran Bingham 2976dd6a7e qcam: Add the version string to the title
Provide the version string reported by the libcamera library on the qcam
test utility.

This helps confirm the exact version of the library that is being used
while testing.

The version string is stored in the MainWindow so that it can be reused
without reconstructing.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2019-07-04 22:11:27 +01:00

235 lines
4.9 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2019, Google Inc.
*
* main_window.cpp - qcam - Main application window
*/
#include <iomanip>
#include <iostream>
#include <string>
#include <QCoreApplication>
#include <QInputDialog>
#include <QTimer>
#include <libcamera/camera_manager.h>
#include <libcamera/version.h>
#include "main_window.h"
#include "viewfinder.h"
using namespace libcamera;
MainWindow::MainWindow(const OptionsParser::Options &options)
: options_(options), isCapturing_(false)
{
int ret;
title_ = "QCam " + QString::fromStdString(libcamera::version);
setWindowTitle(title_);
viewfinder_ = new ViewFinder(this);
setCentralWidget(viewfinder_);
viewfinder_->setFixedSize(500, 500);
adjustSize();
ret = openCamera();
if (!ret)
ret = startCapture();
if (ret < 0)
QTimer::singleShot(0, QCoreApplication::instance(),
&QCoreApplication::quit);
}
MainWindow::~MainWindow()
{
if (camera_) {
stopCapture();
camera_->release();
camera_.reset();
}
CameraManager::instance()->stop();
}
int MainWindow::openCamera()
{
CameraManager *cm = CameraManager::instance();
std::string cameraName;
if (!options_.isSet(OptCamera)) {
QStringList cameras;
bool result;
for (const std::shared_ptr<Camera> &cam : cm->cameras())
cameras.append(QString::fromStdString(cam->name()));
QString name = QInputDialog::getItem(this, "Select Camera",
"Camera:", cameras, 0,
false, &result);
if (!result)
return -EINVAL;
cameraName = name.toStdString();
} else {
cameraName = static_cast<std::string>(options_[OptCamera]);
}
camera_ = cm->get(cameraName);
if (!camera_) {
std::cout << "Camera " << cameraName << " not found"
<< std::endl;
return -ENODEV;
}
if (camera_->acquire()) {
std::cout << "Failed to acquire camera" << std::endl;
camera_.reset();
return -EBUSY;
}
std::cout << "Using camera " << camera_->name() << std::endl;
camera_->requestCompleted.connect(this, &MainWindow::requestComplete);
return 0;
}
int MainWindow::startCapture()
{
int ret;
config_ = camera_->generateConfiguration({ StreamRole::VideoRecording });
ret = camera_->configure(config_.get());
if (ret < 0) {
std::cout << "Failed to configure camera" << std::endl;
return ret;
}
const StreamConfiguration &cfg = config_->at(0);
Stream *stream = cfg.stream();
ret = viewfinder_->setFormat(cfg.pixelFormat, cfg.size.width,
cfg.size.height);
if (ret < 0) {
std::cout << "Failed to set viewfinder format" << std::endl;
return ret;
}
adjustSize();
ret = camera_->allocateBuffers();
if (ret) {
std::cerr << "Failed to allocate buffers"
<< std::endl;
return ret;
}
BufferPool &pool = stream->bufferPool();
std::vector<Request *> requests;
for (Buffer &buffer : pool.buffers()) {
Request *request = camera_->createRequest();
if (!request) {
std::cerr << "Can't create request" << std::endl;
ret = -ENOMEM;
goto error;
}
std::map<Stream *, Buffer *> map;
map[stream] = &buffer;
ret = request->setBuffers(map);
if (ret < 0) {
std::cerr << "Can't set buffers for request" << std::endl;
goto error;
}
requests.push_back(request);
}
lastBufferTime_ = 0;
ret = camera_->start();
if (ret) {
std::cout << "Failed to start capture" << std::endl;
goto error;
}
for (Request *request : requests) {
ret = camera_->queueRequest(request);
if (ret < 0) {
std::cerr << "Can't queue request" << std::endl;
goto error;
}
}
isCapturing_ = true;
return 0;
error:
for (Request *request : requests)
delete request;
camera_->freeBuffers();
return ret;
}
void MainWindow::stopCapture()
{
if (!isCapturing_)
return;
int ret = camera_->stop();
if (ret)
std::cout << "Failed to stop capture" << std::endl;
camera_->freeBuffers();
isCapturing_ = false;
config_.reset();
}
void MainWindow::requestComplete(Request *request,
const std::map<Stream *, Buffer *> &buffers)
{
if (request->status() == Request::RequestCancelled)
return;
Buffer *buffer = buffers.begin()->second;
double fps = buffer->timestamp() - lastBufferTime_;
fps = lastBufferTime_ && fps ? 1000000000.0 / fps : 0.0;
lastBufferTime_ = buffer->timestamp();
std::cout << "seq: " << std::setw(6) << std::setfill('0') << buffer->sequence()
<< " buf: " << buffer->index()
<< " bytesused: " << buffer->bytesused()
<< " timestamp: " << buffer->timestamp()
<< " fps: " << std::fixed << std::setprecision(2) << fps
<< std::endl;
display(buffer);
request = camera_->createRequest();
if (!request) {
std::cerr << "Can't create request" << std::endl;
return;
}
request->setBuffers(buffers);
camera_->queueRequest(request);
}
int MainWindow::display(Buffer *buffer)
{
if (buffer->planes().size() != 1)
return -EINVAL;
Plane &plane = buffer->planes().front();
unsigned char *raw = static_cast<unsigned char *>(plane.mem());
viewfinder_->display(raw, buffer->bytesused());
return 0;
}