diff options
Diffstat (limited to 'src/apps')
-rw-r--r-- | src/apps/cam/camera_session.cpp | 10 | ||||
-rw-r--r-- | src/apps/common/event_loop.cpp | 64 | ||||
-rw-r--r-- | src/apps/common/event_loop.h | 23 | ||||
-rw-r--r-- | src/apps/common/options.cpp | 2 | ||||
-rw-r--r-- | src/apps/common/ppm_writer.cpp | 7 | ||||
-rw-r--r-- | src/apps/lc-compliance/environment.h | 2 | ||||
-rw-r--r-- | src/apps/lc-compliance/helpers/capture.cpp | 162 | ||||
-rw-r--r-- | src/apps/lc-compliance/helpers/capture.h | 51 | ||||
-rw-r--r-- | src/apps/lc-compliance/main.cpp | 42 | ||||
-rw-r--r-- | src/apps/lc-compliance/tests/capture_test.cpp | 21 | ||||
-rw-r--r-- | src/apps/qcam/format_converter.cpp | 2 | ||||
-rw-r--r-- | src/apps/qcam/main_window.cpp | 43 | ||||
-rw-r--r-- | src/apps/qcam/main_window.h | 2 |
13 files changed, 174 insertions, 257 deletions
diff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp index 6e9890cc..9e934827 100644 --- a/src/apps/cam/camera_session.cpp +++ b/src/apps/cam/camera_session.cpp @@ -159,12 +159,18 @@ CameraSession::~CameraSession() void CameraSession::listControls() const { for (const auto &[id, info] : camera_->controls()) { + std::stringstream io; + io << "[" + << (id->isInput() ? "in" : " ") + << (id->isOutput() ? "out" : " ") + << "] "; + if (info.values().empty()) { - std::cout << "Control: " + std::cout << "Control: " << io.str() << id->vendor() << "::" << id->name() << ": " << info.toString() << std::endl; } else { - std::cout << "Control: " + std::cout << "Control: " << io.str() << id->vendor() << "::" << id->name() << ":" << std::endl; for (const auto &value : info.values()) { diff --git a/src/apps/common/event_loop.cpp b/src/apps/common/event_loop.cpp index f7f9afa0..b6230f4b 100644 --- a/src/apps/common/event_loop.cpp +++ b/src/apps/common/event_loop.cpp @@ -21,12 +21,35 @@ EventLoop::EventLoop() evthread_use_pthreads(); base_ = event_base_new(); instance_ = this; + + callsTrigger_ = event_new(base_, -1, EV_PERSIST, [](evutil_socket_t, short, void *closure) { + auto *self = static_cast<EventLoop *>(closure); + + for (;;) { + std::function<void()> call; + + { + std::lock_guard locker(self->lock_); + if (self->calls_.empty()) + break; + + call = std::move(self->calls_.front()); + self->calls_.pop_front(); + } + + call(); + } + }, this); + assert(callsTrigger_); + event_add(callsTrigger_, nullptr); } EventLoop::~EventLoop() { instance_ = nullptr; + event_free(callsTrigger_); + events_.clear(); event_base_free(base_); libevent_global_shutdown(); @@ -50,20 +73,20 @@ void EventLoop::exit(int code) event_base_loopbreak(base_); } -void EventLoop::callLater(const std::function<void()> &func) +void EventLoop::callLater(std::function<void()> &&func) { { std::unique_lock<std::mutex> locker(lock_); - calls_.push_back(func); + calls_.push_back(std::move(func)); } - event_base_once(base_, -1, EV_TIMEOUT, dispatchCallback, this, nullptr); + event_active(callsTrigger_, 0, 0); } void EventLoop::addFdEvent(int fd, EventType type, - const std::function<void()> &callback) + std::function<void()> &&callback) { - std::unique_ptr<Event> event = std::make_unique<Event>(callback); + std::unique_ptr<Event> event = std::make_unique<Event>(std::move(callback)); short events = (type & Read ? EV_READ : 0) | (type & Write ? EV_WRITE : 0) | EV_PERSIST; @@ -85,9 +108,9 @@ void EventLoop::addFdEvent(int fd, EventType type, } void EventLoop::addTimerEvent(const std::chrono::microseconds period, - const std::function<void()> &callback) + std::function<void()> &&callback) { - std::unique_ptr<Event> event = std::make_unique<Event>(callback); + std::unique_ptr<Event> event = std::make_unique<Event>(std::move(callback)); event->event_ = event_new(base_, -1, EV_PERSIST, &EventLoop::Event::dispatch, event.get()); if (!event->event_) { @@ -108,31 +131,8 @@ void EventLoop::addTimerEvent(const std::chrono::microseconds period, events_.push_back(std::move(event)); } -void EventLoop::dispatchCallback([[maybe_unused]] evutil_socket_t fd, - [[maybe_unused]] short flags, void *param) -{ - EventLoop *loop = static_cast<EventLoop *>(param); - loop->dispatchCall(); -} - -void EventLoop::dispatchCall() -{ - std::function<void()> call; - - { - std::unique_lock<std::mutex> locker(lock_); - if (calls_.empty()) - return; - - call = calls_.front(); - calls_.pop_front(); - } - - call(); -} - -EventLoop::Event::Event(const std::function<void()> &callback) - : callback_(callback), event_(nullptr) +EventLoop::Event::Event(std::function<void()> &&callback) + : callback_(std::move(callback)), event_(nullptr) { } diff --git a/src/apps/common/event_loop.h b/src/apps/common/event_loop.h index ef129b9a..d8b6df2f 100644 --- a/src/apps/common/event_loop.h +++ b/src/apps/common/event_loop.h @@ -8,11 +8,14 @@ #pragma once #include <chrono> +#include <deque> #include <functional> #include <list> #include <memory> #include <mutex> +#include <libcamera/base/class.h> + #include <event2/util.h> struct event_base; @@ -33,18 +36,20 @@ public: int exec(); void exit(int code = 0); - void callLater(const std::function<void()> &func); + void callLater(std::function<void()> &&func); void addFdEvent(int fd, EventType type, - const std::function<void()> &handler); + std::function<void()> &&handler); - using duration = std::chrono::steady_clock::duration; void addTimerEvent(const std::chrono::microseconds period, - const std::function<void()> &handler); + std::function<void()> &&handler); private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(EventLoop) + struct Event { - Event(const std::function<void()> &callback); + Event(std::function<void()> &&callback); + LIBCAMERA_DISABLE_COPY_AND_MOVE(Event) ~Event(); static void dispatch(int fd, short events, void *arg); @@ -58,11 +63,9 @@ private: struct event_base *base_; int exitCode_; - std::list<std::function<void()>> calls_; + std::deque<std::function<void()>> calls_; + struct event *callsTrigger_ = nullptr; + std::list<std::unique_ptr<Event>> events_; std::mutex lock_; - - static void dispatchCallback(evutil_socket_t fd, short flags, - void *param); - void dispatchCall(); }; diff --git a/src/apps/common/options.cpp b/src/apps/common/options.cpp index ece268d0..cae193cc 100644 --- a/src/apps/common/options.cpp +++ b/src/apps/common/options.cpp @@ -1040,7 +1040,7 @@ void OptionsParser::usageOptions(const std::list<Option> &options, std::cerr << std::setw(indent) << argument; - for (const char *help = option.help, *end = help; end; ) { + for (const char *help = option.help, *end = help; end;) { end = strchr(help, '\n'); if (end) { std::cerr << std::string(help, end - help + 1); diff --git a/src/apps/common/ppm_writer.cpp b/src/apps/common/ppm_writer.cpp index d6c8641d..368de8bf 100644 --- a/src/apps/common/ppm_writer.cpp +++ b/src/apps/common/ppm_writer.cpp @@ -7,6 +7,7 @@ #include "ppm_writer.h" +#include <errno.h> #include <fstream> #include <iostream> @@ -28,7 +29,7 @@ int PPMWriter::write(const char *filename, std::ofstream output(filename, std::ios::binary); if (!output) { std::cerr << "Failed to open ppm file: " << filename << std::endl; - return -EINVAL; + return -EIO; } output << "P6" << std::endl @@ -36,7 +37,7 @@ int PPMWriter::write(const char *filename, << "255" << std::endl; if (!output) { std::cerr << "Failed to write the file header" << std::endl; - return -EINVAL; + return -EIO; } const unsigned int rowLength = config.size.width * 3; @@ -45,7 +46,7 @@ int PPMWriter::write(const char *filename, output.write(row, rowLength); if (!output) { std::cerr << "Failed to write image data at row " << y << std::endl; - return -EINVAL; + return -EIO; } } diff --git a/src/apps/lc-compliance/environment.h b/src/apps/lc-compliance/environment.h index 543e5372..834c722e 100644 --- a/src/apps/lc-compliance/environment.h +++ b/src/apps/lc-compliance/environment.h @@ -23,5 +23,5 @@ private: Environment() = default; std::string cameraId_; - libcamera::CameraManager *cm_; + libcamera::CameraManager *cm_ = nullptr; }; diff --git a/src/apps/lc-compliance/helpers/capture.cpp b/src/apps/lc-compliance/helpers/capture.cpp index 90c1530b..f2c6d58c 100644 --- a/src/apps/lc-compliance/helpers/capture.cpp +++ b/src/apps/lc-compliance/helpers/capture.cpp @@ -7,13 +7,14 @@ #include "capture.h" +#include <assert.h> + #include <gtest/gtest.h> using namespace libcamera; Capture::Capture(std::shared_ptr<Camera> camera) - : loop_(nullptr), camera_(camera), - allocator_(std::make_unique<FrameBufferAllocator>(camera)) + : camera_(std::move(camera)), allocator_(camera_) { } @@ -26,10 +27,8 @@ void Capture::configure(StreamRole role) { config_ = camera_->generateConfiguration({ role }); - if (!config_) { - std::cout << "Role not supported by camera" << std::endl; - GTEST_SKIP(); - } + if (!config_) + GTEST_SKIP() << "Role not supported by camera"; if (config_->validate() != CameraConfiguration::Valid) { config_.reset(); @@ -42,155 +41,106 @@ void Capture::configure(StreamRole role) } } -void Capture::start() +void Capture::run(unsigned int captureLimit, std::optional<unsigned int> queueLimit) { - Stream *stream = config_->at(0).stream(); - int count = allocator_->allocate(stream); - - ASSERT_GE(count, 0) << "Failed to allocate buffers"; - EXPECT_EQ(count, config_->at(0).bufferCount) << "Allocated less buffers than expected"; - - camera_->requestCompleted.connect(this, &Capture::requestComplete); - - ASSERT_EQ(camera_->start(), 0) << "Failed to start camera"; -} + assert(!queueLimit || captureLimit <= *queueLimit); -void Capture::stop() -{ - if (!config_ || !allocator_->allocated()) - return; + captureLimit_ = captureLimit; + queueLimit_ = queueLimit; - camera_->stop(); + captureCount_ = queueCount_ = 0; - camera_->requestCompleted.disconnect(this); + EventLoop loop; + loop_ = &loop; - Stream *stream = config_->at(0).stream(); - requests_.clear(); - allocator_->free(stream); -} - -/* CaptureBalanced */ - -CaptureBalanced::CaptureBalanced(std::shared_ptr<Camera> camera) - : Capture(camera) -{ -} - -void CaptureBalanced::capture(unsigned int numRequests) -{ start(); - Stream *stream = config_->at(0).stream(); - const std::vector<std::unique_ptr<FrameBuffer>> &buffers = allocator_->buffers(stream); - - /* No point in testing less requests then the camera depth. */ - if (buffers.size() > numRequests) { - std::cout << "Camera needs " + std::to_string(buffers.size()) - + " requests, can't test only " - + std::to_string(numRequests) << std::endl; - GTEST_SKIP(); - } + for (const auto &request : requests_) + queueRequest(request.get()); - queueCount_ = 0; - captureCount_ = 0; - captureLimit_ = numRequests; + EXPECT_EQ(loop_->exec(), 0); - /* Queue the recommended number of requests. */ - for (const std::unique_ptr<FrameBuffer> &buffer : buffers) { - std::unique_ptr<Request> request = camera_->createRequest(); - ASSERT_TRUE(request) << "Can't create request"; - - ASSERT_EQ(request->addBuffer(stream, buffer.get()), 0) << "Can't set buffer for request"; - - ASSERT_EQ(queueRequest(request.get()), 0) << "Failed to queue request"; - - requests_.push_back(std::move(request)); - } - - /* Run capture session. */ - loop_ = new EventLoop(); - loop_->exec(); stop(); - delete loop_; - ASSERT_EQ(captureCount_, captureLimit_); + EXPECT_LE(captureLimit_, captureCount_); + EXPECT_LE(captureCount_, queueCount_); + EXPECT_TRUE(!queueLimit_ || queueCount_ <= *queueLimit_); } -int CaptureBalanced::queueRequest(Request *request) +int Capture::queueRequest(libcamera::Request *request) { - queueCount_++; - if (queueCount_ > captureLimit_) + if (queueLimit_ && queueCount_ >= *queueLimit_) return 0; - return camera_->queueRequest(request); + int ret = camera_->queueRequest(request); + if (ret < 0) + return ret; + + queueCount_ += 1; + return 0; } -void CaptureBalanced::requestComplete(Request *request) +void Capture::requestComplete(Request *request) { - EXPECT_EQ(request->status(), Request::Status::RequestComplete) - << "Request didn't complete successfully"; - captureCount_++; if (captureCount_ >= captureLimit_) { loop_->exit(0); return; } + EXPECT_EQ(request->status(), Request::Status::RequestComplete) + << "Request didn't complete successfully"; + request->reuse(Request::ReuseBuffers); if (queueRequest(request)) loop_->exit(-EINVAL); } -/* CaptureUnbalanced */ - -CaptureUnbalanced::CaptureUnbalanced(std::shared_ptr<Camera> camera) - : Capture(camera) -{ -} - -void CaptureUnbalanced::capture(unsigned int numRequests) +void Capture::start() { - start(); + assert(config_); + assert(!config_->empty()); + assert(!allocator_.allocated()); + assert(requests_.empty()); Stream *stream = config_->at(0).stream(); - const std::vector<std::unique_ptr<FrameBuffer>> &buffers = allocator_->buffers(stream); + int count = allocator_.allocate(stream); - captureCount_ = 0; - captureLimit_ = numRequests; + ASSERT_GE(count, 0) << "Failed to allocate buffers"; + EXPECT_EQ(count, config_->at(0).bufferCount) << "Allocated less buffers than expected"; + + const std::vector<std::unique_ptr<FrameBuffer>> &buffers = allocator_.buffers(stream); + + /* No point in testing less requests then the camera depth. */ + if (queueLimit_ && *queueLimit_ < buffers.size()) { + GTEST_SKIP() << "Camera needs " << buffers.size() + << " requests, can't test only " << *queueLimit_; + } - /* Queue the recommended number of requests. */ for (const std::unique_ptr<FrameBuffer> &buffer : buffers) { std::unique_ptr<Request> request = camera_->createRequest(); ASSERT_TRUE(request) << "Can't create request"; ASSERT_EQ(request->addBuffer(stream, buffer.get()), 0) << "Can't set buffer for request"; - ASSERT_EQ(camera_->queueRequest(request.get()), 0) << "Failed to queue request"; - requests_.push_back(std::move(request)); } - /* Run capture session. */ - loop_ = new EventLoop(); - int status = loop_->exec(); - stop(); - delete loop_; + camera_->requestCompleted.connect(this, &Capture::requestComplete); - ASSERT_EQ(status, 0); + ASSERT_EQ(camera_->start(), 0) << "Failed to start camera"; } -void CaptureUnbalanced::requestComplete(Request *request) +void Capture::stop() { - captureCount_++; - if (captureCount_ >= captureLimit_) { - loop_->exit(0); + if (!config_ || !allocator_.allocated()) return; - } - EXPECT_EQ(request->status(), Request::Status::RequestComplete) - << "Request didn't complete successfully"; + camera_->stop(); - request->reuse(Request::ReuseBuffers); - if (camera_->queueRequest(request)) - loop_->exit(-EINVAL); + camera_->requestCompleted.disconnect(this); + + Stream *stream = config_->at(0).stream(); + requests_.clear(); + allocator_.free(stream); } diff --git a/src/apps/lc-compliance/helpers/capture.h b/src/apps/lc-compliance/helpers/capture.h index 19b6927c..0e7b848f 100644 --- a/src/apps/lc-compliance/helpers/capture.h +++ b/src/apps/lc-compliance/helpers/capture.h @@ -8,6 +8,7 @@ #pragma once #include <memory> +#include <optional> #include <libcamera/libcamera.h> @@ -16,51 +17,29 @@ class Capture { public: + Capture(std::shared_ptr<libcamera::Camera> camera); + ~Capture(); + void configure(libcamera::StreamRole role); + void run(unsigned int captureLimit, std::optional<unsigned int> queueLimit = {}); -protected: - Capture(std::shared_ptr<libcamera::Camera> camera); - virtual ~Capture(); +private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(Capture) void start(); void stop(); - virtual void requestComplete(libcamera::Request *request) = 0; - - EventLoop *loop_; + int queueRequest(libcamera::Request *request); + void requestComplete(libcamera::Request *request); std::shared_ptr<libcamera::Camera> camera_; - std::unique_ptr<libcamera::FrameBufferAllocator> allocator_; + libcamera::FrameBufferAllocator allocator_; std::unique_ptr<libcamera::CameraConfiguration> config_; std::vector<std::unique_ptr<libcamera::Request>> requests_; -}; - -class CaptureBalanced : public Capture -{ -public: - CaptureBalanced(std::shared_ptr<libcamera::Camera> camera); - - void capture(unsigned int numRequests); - -private: - int queueRequest(libcamera::Request *request); - void requestComplete(libcamera::Request *request) override; - - unsigned int queueCount_; - unsigned int captureCount_; - unsigned int captureLimit_; -}; - -class CaptureUnbalanced : public Capture -{ -public: - CaptureUnbalanced(std::shared_ptr<libcamera::Camera> camera); - - void capture(unsigned int numRequests); - -private: - void requestComplete(libcamera::Request *request) override; - unsigned int captureCount_; - unsigned int captureLimit_; + EventLoop *loop_ = nullptr; + unsigned int captureLimit_ = 0; + std::optional<unsigned int> queueLimit_; + unsigned int captureCount_ = 0; + unsigned int queueCount_ = 0; }; diff --git a/src/apps/lc-compliance/main.cpp b/src/apps/lc-compliance/main.cpp index 3f1d2a61..e9f0ffbb 100644 --- a/src/apps/lc-compliance/main.cpp +++ b/src/apps/lc-compliance/main.cpp @@ -45,13 +45,11 @@ class ThrowListener : public testing::EmptyTestEventListener static void listCameras(CameraManager *cm) { for (const std::shared_ptr<Camera> &cam : cm->cameras()) - std::cout << "- " << cam.get()->id() << std::endl; + std::cout << "- " << cam->id() << std::endl; } static int initCamera(CameraManager *cm, OptionsParser::Options options) { - std::shared_ptr<Camera> camera; - int ret = cm->start(); if (ret) { std::cout << "Failed to start camera manager: " @@ -66,7 +64,7 @@ static int initCamera(CameraManager *cm, OptionsParser::Options options) } const std::string &cameraId = options[OptCamera]; - camera = cm->get(cameraId); + std::shared_ptr<Camera> camera = cm->get(cameraId); if (!camera) { std::cout << "Camera " << cameraId << " not found, available cameras:" << std::endl; listCameras(cm); @@ -82,45 +80,27 @@ static int initCamera(CameraManager *cm, OptionsParser::Options options) static int initGtestParameters(char *arg0, OptionsParser::Options options) { - const std::map<std::string, std::string> gtestFlags = { { "list", "--gtest_list_tests" }, - { "filter", "--gtest_filter" } }; - - int argc = 0; + std::vector<const char *> argv; std::string filterParam; - /* - * +2 to have space for both the 0th argument that is needed but not - * used and the null at the end. - */ - char **argv = new char *[(gtestFlags.size() + 2)]; - if (!argv) - return -ENOMEM; - - argv[0] = arg0; - argc++; + argv.push_back(arg0); - if (options.isSet(OptList)) { - argv[argc] = const_cast<char *>(gtestFlags.at("list").c_str()); - argc++; - } + if (options.isSet(OptList)) + argv.push_back("--gtest_list_tests"); if (options.isSet(OptFilter)) { /* * The filter flag needs to be passed as a single parameter, in * the format --gtest_filter=filterStr */ - filterParam = gtestFlags.at("filter") + "=" + - static_cast<const std::string &>(options[OptFilter]); - - argv[argc] = const_cast<char *>(filterParam.c_str()); - argc++; + filterParam = "--gtest_filter=" + options[OptFilter].toString(); + argv.push_back(filterParam.c_str()); } - argv[argc] = nullptr; - - ::testing::InitGoogleTest(&argc, argv); + argv.push_back(nullptr); - delete[] argv; + int argc = argv.size(); + ::testing::InitGoogleTest(&argc, const_cast<char **>(argv.data())); return 0; } diff --git a/src/apps/lc-compliance/tests/capture_test.cpp b/src/apps/lc-compliance/tests/capture_test.cpp index ad3a1da2..93bed48f 100644 --- a/src/apps/lc-compliance/tests/capture_test.cpp +++ b/src/apps/lc-compliance/tests/capture_test.cpp @@ -14,10 +14,13 @@ #include "environment.h" +namespace { + using namespace libcamera; -const std::vector<int> NUMREQUESTS = { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 }; -const std::vector<StreamRole> ROLES = { +const int NUMREQUESTS[] = { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 }; + +const StreamRole ROLES[] = { StreamRole::Raw, StreamRole::StillCapture, StreamRole::VideoRecording, @@ -84,11 +87,11 @@ TEST_P(SingleStream, Capture) { auto [role, numRequests] = GetParam(); - CaptureBalanced capture(camera_); + Capture capture(camera_); capture.configure(role); - capture.capture(numRequests); + capture.run(numRequests, numRequests); } /* @@ -103,12 +106,12 @@ TEST_P(SingleStream, CaptureStartStop) auto [role, numRequests] = GetParam(); unsigned int numRepeats = 3; - CaptureBalanced capture(camera_); + Capture capture(camera_); capture.configure(role); for (unsigned int starts = 0; starts < numRepeats; starts++) - capture.capture(numRequests); + capture.run(numRequests, numRequests); } /* @@ -122,11 +125,11 @@ TEST_P(SingleStream, UnbalancedStop) { auto [role, numRequests] = GetParam(); - CaptureUnbalanced capture(camera_); + Capture capture(camera_); capture.configure(role); - capture.capture(numRequests); + capture.run(numRequests); } INSTANTIATE_TEST_SUITE_P(CaptureTests, @@ -134,3 +137,5 @@ INSTANTIATE_TEST_SUITE_P(CaptureTests, testing::Combine(testing::ValuesIn(ROLES), testing::ValuesIn(NUMREQUESTS)), SingleStream::nameParameters); + +} /* namespace */ diff --git a/src/apps/qcam/format_converter.cpp b/src/apps/qcam/format_converter.cpp index 32123493..b025a3c7 100644 --- a/src/apps/qcam/format_converter.cpp +++ b/src/apps/qcam/format_converter.cpp @@ -249,7 +249,7 @@ void FormatConverter::convertYUVPacked(const Image *srcImage, unsigned char *dst dst_stride = width_ * 4; for (src_y = 0, dst_y = 0; dst_y < height_; src_y++, dst_y++) { - for (src_x = 0, dst_x = 0; dst_x < width_; ) { + for (src_x = 0, dst_x = 0; dst_x < width_;) { cb = src[src_y * src_stride + src_x * 4 + cb_pos_]; cr = src[src_y * src_stride + src_x * 4 + cr_pos]; diff --git a/src/apps/qcam/main_window.cpp b/src/apps/qcam/main_window.cpp index de487672..3880a846 100644 --- a/src/apps/qcam/main_window.cpp +++ b/src/apps/qcam/main_window.cpp @@ -251,16 +251,14 @@ void MainWindow::updateTitle() void MainWindow::switchCamera() { /* Get and acquire the new camera. */ - std::string newCameraId = chooseCamera(); + std::shared_ptr<Camera> cam = chooseCamera(); - if (newCameraId.empty()) + if (!cam) return; - if (camera_ && newCameraId == camera_->id()) + if (camera_ && cam == camera_) return; - const std::shared_ptr<Camera> &cam = cm_->get(newCameraId); - if (cam->acquire()) { qInfo() << "Failed to acquire camera" << cam->id().c_str(); return; @@ -282,46 +280,41 @@ void MainWindow::switchCamera() startStopAction_->setChecked(true); /* Display the current cameraId in the toolbar .*/ - cameraSelectButton_->setText(QString::fromStdString(newCameraId)); + cameraSelectButton_->setText(QString::fromStdString(cam->id())); } -std::string MainWindow::chooseCamera() +std::shared_ptr<Camera> MainWindow::chooseCamera() { if (cameraSelectorDialog_->exec() != QDialog::Accepted) - return std::string(); + return {}; - return cameraSelectorDialog_->getCameraId(); + std::string id = cameraSelectorDialog_->getCameraId(); + return cm_->get(id); } int MainWindow::openCamera() { - std::string cameraName; - /* * If a camera is specified on the command line, get it. Otherwise, if * only one camera is available, pick it automatically, else, display * the selector dialog box. */ if (options_.isSet(OptCamera)) { - cameraName = static_cast<std::string>(options_[OptCamera]); + std::string cameraName = static_cast<std::string>(options_[OptCamera]); + camera_ = cm_->get(cameraName); + if (!camera_) + qInfo() << "Camera" << cameraName.c_str() << "not found"; } else { std::vector<std::shared_ptr<Camera>> cameras = cm_->cameras(); - if (cameras.size() == 1) - cameraName = cameras[0]->id(); - else - cameraName = chooseCamera(); + camera_ = (cameras.size() == 1) ? cameras[0] : chooseCamera(); + if (!camera_) + qInfo() << "No camera detected"; } - if (cameraName == "") - return -EINVAL; - - /* Get and acquire the camera. */ - camera_ = cm_->get(cameraName); - if (!camera_) { - qInfo() << "Camera" << cameraName.c_str() << "not found"; + if (!camera_) return -ENODEV; - } + /* Acquire the camera. */ if (camera_->acquire()) { qInfo() << "Failed to acquire camera"; camera_.reset(); @@ -329,7 +322,7 @@ int MainWindow::openCamera() } /* Set the camera switch button with the currently selected Camera id. */ - cameraSelectButton_->setText(QString::fromStdString(cameraName)); + cameraSelectButton_->setText(QString::fromStdString(camera_->id())); return 0; } diff --git a/src/apps/qcam/main_window.h b/src/apps/qcam/main_window.h index 4cead734..81fcf915 100644 --- a/src/apps/qcam/main_window.h +++ b/src/apps/qcam/main_window.h @@ -73,7 +73,7 @@ private Q_SLOTS: private: int createToolbars(); - std::string chooseCamera(); + std::shared_ptr<libcamera::Camera> chooseCamera(); int openCamera(); int startCapture(); |