diff options
-rw-r--r-- | .github/workflows/cmake.yml | 2 | ||||
-rw-r--r-- | cmake/FindONNXRuntime.cmake | 81 | ||||
-rw-r--r-- | cmake/msvc.cmake | 1 | ||||
-rw-r--r-- | gui/process_detector.cpp | 8 | ||||
-rw-r--r-- | logic/pipeline.cpp | 11 | ||||
-rw-r--r-- | logic/pipeline.hpp | 2 | ||||
-rw-r--r-- | pose-widget/pose-widget.cpp | 2 | ||||
-rw-r--r-- | sdk-paths-sthalik@MSVC-windows.cmake | 9 | ||||
-rw-r--r-- | tracker-easy/CMakeLists.txt | 2 | ||||
-rw-r--r-- | tracker-neuralnet/CMakeLists.txt | 31 | ||||
-rw-r--r-- | tracker-neuralnet/ftnoir_tracker_neuralnet.h | 2 | ||||
-rw-r--r-- | tracker-pt/module/frame.cpp | 25 | ||||
-rw-r--r-- | tracker-pt/module/frame.hpp | 2 | ||||
-rw-r--r-- | tracker-pt/module/point_extractor.cpp | 7 | ||||
-rw-r--r-- | tracker-pt/pt-api.cpp | 4 | ||||
-rw-r--r-- | video-ps3eye/lang/nl_NL.ts | 15 | ||||
-rw-r--r-- | video-ps3eye/lang/ru_RU.ts | 15 | ||||
-rw-r--r-- | video-ps3eye/lang/stub.ts | 15 | ||||
-rw-r--r-- | video-ps3eye/lang/zh_CN.ts | 15 | ||||
-rw-r--r-- | video-ps3eye/module.cpp | 31 | ||||
-rw-r--r-- | video-ps3eye/module.hpp | 7 | ||||
m--------- | video-ps3eye/ps3eye-driver | 0 | ||||
-rw-r--r-- | video-ps3eye/shm-layout.hpp | 6 | ||||
-rw-r--r-- | video-ps3eye/wrapper.cxx | 10 | ||||
-rw-r--r-- | video/camera.hpp | 16 |
25 files changed, 264 insertions, 55 deletions
diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 59bace46..8555bfdf 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -26,7 +26,7 @@ jobs: - uses: actions/checkout@v2 - name: Install Linux Dependencies - run: sudo apt install libprocps-dev libopencv-dev + run: sudo apt update && sudo apt install libprocps-dev libopencv-dev if: matrix.os == 'ubuntu-latest' - name: Cache Qt diff --git a/cmake/FindONNXRuntime.cmake b/cmake/FindONNXRuntime.cmake new file mode 100644 index 00000000..44bc46c1 --- /dev/null +++ b/cmake/FindONNXRuntime.cmake @@ -0,0 +1,81 @@ +# FindONNXRuntime +# =============== +# +# Find an ONNX Runtime installation. +# ONNX Runtime is a cross-platform inference and training machine-learning +# accelerator. +# +# Input variables +# --------------- +# +# ONNXRuntime_ROOT Set root installation. This is an environment +# variable +# ONNXRuntime_DIR CMake variable to set the installation root. +# +# Output variable +# --------------- +# +# ONNXRuntime_FOUND True if headers and requested libraries were found +# ONNXRuntime_LIBRARIES Component libraries to be linked. +# ONNXRuntime_INCLUDE_DIRS Include directories. + +set(ONNXRuntime_DIR CACHE PATH "Root directory of the ONNX Runtime installation") + +# This script is mostly inspired by the guide there: +# https://gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/How-To-Find-Libraries +# Finding of the DLLs was added so we can install them with the application. +# We adhere to modern CMake standards and also define an import library. + +find_library(ONNXRuntime_LIBRARY onnxruntime + HINTS + ${ONNXRuntime_DIR} + PATHS + ${CMAKE_INSTALL_PREFIX} + PATH_SUFFIXES lib lib64 bin + CMAKE_FIND_ROOT_PATH_BOTH) + +if(WIN32) + SET(CMAKE_FIND_LIBRARY_SUFFIXES ".dll" ".DLL") + find_library(ONNXRuntime_RUNTIME onnxruntime + HINTS + ${ONNXRuntime_DIR} + PATHS + ${CMAKE_INSTALL_PREFIX} + PATH_SUFFIXES lib lib64 bin + CMAKE_FIND_ROOT_PATH_BOTH) +else() + SET(ONNXRuntime_RUNTIME ${ONNXRuntime_LIBRARY}) +endif() + +find_path(ONNXRuntime_INCLUDE_DIR onnxruntime_cxx_api.h + HINTS + ${ONNXRuntime_DIR}/include + ${ONNXRuntime_DIR} + PATHS + ${CMAKE_INSTALL_PREFIX}/include + PATH_SUFFIXES onnxruntime/core/session + CMAKE_FIND_ROOT_PATH_BOTH) + + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set ONNXRuntime_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(ONNXRuntime DEFAULT_MSG + ONNXRuntime_LIBRARY ONNXRuntime_INCLUDE_DIR ONNXRuntime_RUNTIME) + +if(ONNXRuntime_FOUND) + if(NOT TARGET onnxruntime::onnxruntime) + # Following this quide: + # https://cmake.org/cmake/help/git-stage/guide/importing-exporting/index.html#importing-libraries + add_library(onnxruntime::onnxruntime SHARED IMPORTED) + set_target_properties(onnxruntime::onnxruntime PROPERTIES + IMPORTED_LOCATION "${ONNXRuntime_RUNTIME}" + INTERFACE_INCLUDE_DIRECTORIES "${ONNXRuntime_INCLUDE_DIR}" + IMPORTED_IMPLIB "${ONNXRuntime_LIBRARY}") + endif() +endif() + +mark_as_advanced(ONNXRuntime_INCLUDE_DIR ONNXRuntime_LIBRARY ONNXRuntime_RUNTIME) + +set(ONNXRuntime_INCLUDE_DIRS ${ONNXRuntime_INCLUDE_DIR}) +set(ONNXRuntime_LIBRARIES ${ONNXRuntime_LIBRARY})
\ No newline at end of file diff --git a/cmake/msvc.cmake b/cmake/msvc.cmake index 4c688226..f810ac4d 100644 --- a/cmake/msvc.cmake +++ b/cmake/msvc.cmake @@ -4,6 +4,7 @@ SET(CMAKE_SYSTEM_NAME Windows) SET(CMAKE_SYSTEM_VERSION 5.01) +set(CMAKE_SYSTEM_PROCESSOR x86) # search for programs in the host directories SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) diff --git a/gui/process_detector.cpp b/gui/process_detector.cpp index 58ea4ca9..74e8caac 100644 --- a/gui/process_detector.cpp +++ b/gui/process_detector.cpp @@ -63,7 +63,13 @@ void proc_detector_settings::set_is_enabled(bool enabled) QHash<QString, QString> proc_detector_settings::split_process_names() { QString str = get_game_list(); - QStringList pairs = str.split(RECORD_SEPARATOR, QString::SkipEmptyParts); + constexpr auto split_flag = +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + Qt::SkipEmptyParts; +#else + QString::SkipEmptyParts; +#endif + QStringList pairs = str.split(RECORD_SEPARATOR, split_flag); QHash<QString, QString> ret; ret.reserve(pairs.size() * 2); for (auto const& pair : pairs) diff --git a/logic/pipeline.cpp b/logic/pipeline.cpp index 3a67eb90..f8827b7e 100644 --- a/logic/pipeline.cpp +++ b/logic/pipeline.cpp @@ -480,14 +480,13 @@ void pipeline::logic() nan_check(value); } - if (!hold_ordered) - goto ok; + goto ok; error: { QMutexLocker foo(&mtx); - value = output_pose; + value = last_value; raw = raw_6dof; // for widget last value display @@ -503,8 +502,10 @@ ok: for (int i = 0; i < 6; i++) value(i) = 0; - if (hold_ordered) value = output_pose; - else value = apply_zero_pos(value); + if (hold_ordered) + value = last_value; + last_value = value; + value = apply_zero_pos(value); ev.run_events(EV::ev_finished, value); libs.pProtocol->pose(value, raw); diff --git a/logic/pipeline.hpp b/logic/pipeline.hpp index 7b3703ee..80d4d8a7 100644 --- a/logic/pipeline.hpp +++ b/logic/pipeline.hpp @@ -88,7 +88,7 @@ class OTR_LOGIC_EXPORT pipeline : private QThread event_handler& ev; Timer t; - Pose output_pose, raw_6dof; + Pose output_pose, raw_6dof, last_value; Pose newpose; runtime_libraries const& libs; diff --git a/pose-widget/pose-widget.cpp b/pose-widget/pose-widget.cpp index e662424c..324cc639 100644 --- a/pose-widget/pose-widget.cpp +++ b/pose-widget/pose-widget.cpp @@ -47,6 +47,8 @@ pose_widget::pose_widget(QWidget* parent) : QWidget(parent) p.setCompositionMode(QPainter::CompositionMode_DestinationIn); p.drawImage(QPointF(0,0), front); p.end(); + + mirror.setFocusPolicy(Qt::NoFocus); } void pose_widget::present(double yaw, double pitch, double roll, double x, double y, double z) diff --git a/sdk-paths-sthalik@MSVC-windows.cmake b/sdk-paths-sthalik@MSVC-windows.cmake index 2f4f4ba2..ed176a3f 100644 --- a/sdk-paths-sthalik@MSVC-windows.cmake +++ b/sdk-paths-sthalik@MSVC-windows.cmake @@ -20,8 +20,6 @@ endfunction() set(opentrack_install-debug-info TRUE CACHE INTERNAL "" FORCE) set(opentrack_maintainer-mode TRUE CACHE INTERNAL "" FORCE) -setq(Qt5_DIR "../qt-5.12.0/lib/cmake/Qt5") - setq(EIGEN3_INCLUDE_DIR "eigen") setq(OpenCV_DIR "opencv/build") setq(SDL2_DIR "SDL2-win32") @@ -32,11 +30,14 @@ setq(SDK_KINECT20 "Kinect-v2.0") setq(SDK_LIBUSB "libusb-msvc-x86") setq(SDK_PS3EYEDRIVER "PS3EYEDriver") setq(SDK_REALSENSE "RSSDK-R3") -setq(SDK_RIFT_140 "ovr_sdk_win_1.43.0/LibOVR") +setq(SDK_RIFT_140 "ovr_sdk_win_23.0.0/LibOVR") setq(SDK_VALVE_STEAMVR "steamvr") setq(SDK_VJOYSTICK "vjoystick") +setq(ONNXRuntime_INCLUDE_DIR "onnxruntime-1.8.1/build/native/include") +setq(ONNXRuntime_LIBRARY "onnxruntime-1.8.1/runtimes/win-x86/native/onnxruntime.lib") +setq(ONNXRuntime_RUNTIME "onnxruntime-1.8.1/runtimes/win-x86/native/onnxruntime.dll") -set(Qt5_DIR "c:/qt/qt-5.14.0/lib/cmake/Qt5" CACHE PATH "" FORCE) +setq(Qt5_DIR "../qt-5.15.2/lib/cmake/Qt5") set(Qt5Core_DIR "${Qt5_DIR}Core" CACHE PATH "" FORCE) set(Qt5Gui_DIR "${Qt5_DIR}Gui" CACHE PATH "" FORCE) diff --git a/tracker-easy/CMakeLists.txt b/tracker-easy/CMakeLists.txt index c377dd9c..5ba49944 100644 --- a/tracker-easy/CMakeLists.txt +++ b/tracker-easy/CMakeLists.txt @@ -15,7 +15,7 @@ if(OpenCV_FOUND) if(CMAKE_COMPILER_IS_GNUCXX) add_compile_options(-Wno-sign-compare) elseif(MSVC) - add_compile_definitions(-wd4018) + add_compile_options(-wd4018) endif() otr_module(tracker-easy) diff --git a/tracker-neuralnet/CMakeLists.txt b/tracker-neuralnet/CMakeLists.txt index d06f0c83..70850925 100644 --- a/tracker-neuralnet/CMakeLists.txt +++ b/tracker-neuralnet/CMakeLists.txt @@ -1,23 +1,24 @@ include(opentrack-opencv) -find_package(OpenCV QUIET) +find_package(OpenCV QUIET COMPONENTS imgproc core imgcodecs calib3d) find_package(OpenMP QUIET) # Used to control number of onnx threads. -set(SDK_ONNX_LIBPATH "" CACHE FILEPATH "Full path of onnx library") - -if(OpenCV_FOUND AND SDK_ONNX_LIBPATH AND OpenMP_FOUND) - get_filename_component(ONNX_INCLUDE_DIR "${SDK_ONNX_LIBPATH}" DIRECTORY) - get_filename_component(ONNX_INCLUDE_DIR "${ONNX_INCLUDE_DIR}" ABSOLUTE) - set(ONNX_INCLUDE_DIR "${ONNX_INCLUDE_DIR}/../include") +find_package(ONNXRuntime QUIET) +if(OpenCV_FOUND AND ONNXRuntime_FOUND AND OpenMP_FOUND) otr_module(tracker-neuralnet) - target_include_directories(${self} SYSTEM PUBLIC - ${OpenCV_INCLUDE_DIRS} "${ONNX_INCLUDE_DIR}") + target_link_libraries(${self} - opentrack-cv "${SDK_ONNX_LIBPATH}" opencv_imgproc opencv_core - opencv_imgcodecs opencv_calib3d - OpenMP::OpenMP_C) + opentrack-cv + onnxruntime::onnxruntime + ${OpenCV_LIBS} + OpenMP::OpenMP_C + ) install( - FILES "models/head-localizer.onnx" "models/head-pose.onnx" + FILES "models/head-localizer.onnx" + "models/head-pose.onnx" DESTINATION "${opentrack-libexec}/models" - PERMISSIONS ${opentrack-perms-file}) -endif()
\ No newline at end of file + PERMISSIONS ${opentrack-perms-file} + ) + + otr_install_lib("${ONNXRuntime_RUNTIME}" ".") +endif() diff --git a/tracker-neuralnet/ftnoir_tracker_neuralnet.h b/tracker-neuralnet/ftnoir_tracker_neuralnet.h index b2eca6e3..7f496dc6 100644 --- a/tracker-neuralnet/ftnoir_tracker_neuralnet.h +++ b/tracker-neuralnet/ftnoir_tracker_neuralnet.h @@ -230,4 +230,4 @@ class neuralnet_metadata : public Metadata using neuralnet_tracker_ns::neuralnet_tracker; using neuralnet_tracker_ns::neuralnet_dialog; -using neuralnet_tracker_ns::neuralnet_metadata;
\ No newline at end of file +using neuralnet_tracker_ns::neuralnet_metadata; diff --git a/tracker-pt/module/frame.cpp b/tracker-pt/module/frame.cpp index ab110871..9247212b 100644 --- a/tracker-pt/module/frame.cpp +++ b/tracker-pt/module/frame.cpp @@ -8,19 +8,32 @@ namespace pt_module { Preview& Preview::operator=(const pt_frame& frame_) { - const cv::Mat& frame = frame_.as_const<const Frame>()->mat; + const cv::Mat& frame2 = frame_.as_const<const Frame>()->mat; + const cv::Mat* frame; - if (frame.channels() != 3) + if (frame2.channels() == 1) { - eval_once(qDebug() << "tracker/pt: camera frame depth: 3 !=" << frame.channels()); + frame_tmp.create(frame2.rows, frame2.cols, CV_8UC3); + const cv::Mat channels[] = { frame2, frame2, frame2 }; + cv::merge(channels, std::size(channels), frame_tmp); + frame = &frame_tmp; + } + else + frame = &frame2; + + if (frame->channels() != 3) + { + eval_once(qDebug() << "tracker/pt: camera frame depth: 3 !=" << frame->channels()); + frame_copy.create(cv::Size{frame_out.cols, frame_out.rows}, CV_8UC3); + frame_copy.setTo({0}); return *this; } - const bool need_resize = frame.cols != frame_out.cols || frame.rows != frame_out.rows; + const bool need_resize = frame2.cols != frame_out.cols || frame2.rows != frame_out.rows; if (need_resize) - cv::resize(frame, frame_copy, cv::Size(frame_out.cols, frame_out.rows), 0, 0, cv::INTER_NEAREST); + cv::resize(frame2, frame_copy, cv::Size(frame_out.cols, frame_out.rows), 0, 0, cv::INTER_NEAREST); else - frame.copyTo(frame_copy); + frame->copyTo(frame_copy); return *this; } diff --git a/tracker-pt/module/frame.hpp b/tracker-pt/module/frame.hpp index 89334599..ae0a0cbc 100644 --- a/tracker-pt/module/frame.hpp +++ b/tracker-pt/module/frame.hpp @@ -34,7 +34,7 @@ struct Preview final : pt_preview private: static void ensure_size(cv::Mat& frame, int w, int h, int type); - cv::Mat frame_copy, frame_out; + cv::Mat frame_copy, frame_out, frame_tmp; }; } // ns pt_module diff --git a/tracker-pt/module/point_extractor.cpp b/tracker-pt/module/point_extractor.cpp index a92c87c9..5e57ef34 100644 --- a/tracker-pt/module/point_extractor.cpp +++ b/tracker-pt/module/point_extractor.cpp @@ -124,6 +124,13 @@ void PointExtractor::filter_single_channel(const cv::Mat& orig_frame, float r, f void PointExtractor::color_to_grayscale(const cv::Mat& frame, cv::Mat1b& output) { + if (frame.channels() == 1) + { + output.create(frame.rows, frame.cols); + frame.copyTo(output); + return; + } + switch (s.blob_color) { case pt_color_green_only: diff --git a/tracker-pt/pt-api.cpp b/tracker-pt/pt-api.cpp index f64d5c9a..6aeef7dc 100644 --- a/tracker-pt/pt-api.cpp +++ b/tracker-pt/pt-api.cpp @@ -40,13 +40,13 @@ f pt_point_extractor::threshold_radius_value(int w, int h, int threshold) std::tuple<f, f> pt_pixel_pos_mixin::to_pixel_pos(f x, f y, int w, int h) { - return std::make_tuple(w*(x+f{.5}), f{.5}*(h - 2*y*w)); + return { w*(x+f{.5}), f{.5}*(h - 2*y*w) }; } std::tuple<f, f> pt_pixel_pos_mixin::to_screen_pos(f px, f py, int w, int h) { px *= w/(w-f{1}); py *= h/(h-f{1}); - return std::make_tuple((px - w/f{2})/w, -(py - h/f{2})/w); + return { (px - w/f{2})/w, -(py - h/f{2})/w }; } pt_frame::pt_frame() = default; diff --git a/video-ps3eye/lang/nl_NL.ts b/video-ps3eye/lang/nl_NL.ts index c98370ec..81ffc826 100644 --- a/video-ps3eye/lang/nl_NL.ts +++ b/video-ps3eye/lang/nl_NL.ts @@ -20,4 +20,19 @@ <translation type="unfinished"></translation> </message> </context> +<context> + <name>dialog</name> + <message> + <source>Can't open camera</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>PS3 Eye driver error: %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Unknown error</source> + <translation type="unfinished"></translation> + </message> +</context> </TS> diff --git a/video-ps3eye/lang/ru_RU.ts b/video-ps3eye/lang/ru_RU.ts index c98370ec..81ffc826 100644 --- a/video-ps3eye/lang/ru_RU.ts +++ b/video-ps3eye/lang/ru_RU.ts @@ -20,4 +20,19 @@ <translation type="unfinished"></translation> </message> </context> +<context> + <name>dialog</name> + <message> + <source>Can't open camera</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>PS3 Eye driver error: %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Unknown error</source> + <translation type="unfinished"></translation> + </message> +</context> </TS> diff --git a/video-ps3eye/lang/stub.ts b/video-ps3eye/lang/stub.ts index c98370ec..81ffc826 100644 --- a/video-ps3eye/lang/stub.ts +++ b/video-ps3eye/lang/stub.ts @@ -20,4 +20,19 @@ <translation type="unfinished"></translation> </message> </context> +<context> + <name>dialog</name> + <message> + <source>Can't open camera</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>PS3 Eye driver error: %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Unknown error</source> + <translation type="unfinished"></translation> + </message> +</context> </TS> diff --git a/video-ps3eye/lang/zh_CN.ts b/video-ps3eye/lang/zh_CN.ts index c98370ec..81ffc826 100644 --- a/video-ps3eye/lang/zh_CN.ts +++ b/video-ps3eye/lang/zh_CN.ts @@ -20,4 +20,19 @@ <translation type="unfinished"></translation> </message> </context> +<context> + <name>dialog</name> + <message> + <source>Can't open camera</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>PS3 Eye driver error: %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Unknown error</source> + <translation type="unfinished"></translation> + </message> +</context> </TS> diff --git a/video-ps3eye/module.cpp b/video-ps3eye/module.cpp index a7078180..25d82170 100644 --- a/video-ps3eye/module.cpp +++ b/video-ps3eye/module.cpp @@ -116,6 +116,8 @@ ps3eye_camera::ps3eye_camera() wrapper.setWorkingDirectory(library_path); #ifdef _WIN32 wrapper.setProgram("\"ps3eye-subprocess.exe\""); + // workaround apparent Qt 5.15.2 bug -sh 20210817 + wrapper.setProcessChannelMode(QProcess::ForwardedChannels); #else wrapper.setProgram("ps3eye-subprocess"); #endif @@ -132,6 +134,11 @@ void ps3eye_camera::stop() if (wrapper.state() != QProcess::NotRunning) { + volatile auto& ptr = *(ps3eye::shm*)shm.ptr(); + ptr.in.do_exit = 1; + std::atomic_thread_fence(std::memory_order_seq_cst); + wrapper.waitForFinished(5000); + if (wrapper.state() != QProcess::NotRunning) wrapper.kill(); wrapper.waitForFinished(1000); @@ -150,7 +157,7 @@ bool ps3eye_camera::start(info& args) open = false; fr = {}; - fr.channels = 3; + fr.channels = 1; fr.channel_size = 1; if (!args.width || args.width > 320) @@ -169,7 +176,7 @@ bool ps3eye_camera::start(info& args) ptr.in.gain = (uint8_t)s.gain; ptr.in.exposure = (uint8_t)s.exposure; - sleep_ms = std::clamp(int(std::floor(1000./ptr.in.framerate*2)), 1, 10); + sleep_ms = std::clamp(int(std::floor(450./ptr.in.framerate)), 1, 10); wrapper.start(); @@ -183,13 +190,13 @@ bool ps3eye_camera::start(info& args) } if (ptr.out.error_string[0] == '\0') - error = "Unknown error"; + error = QString{}; else error = QString::fromLatin1((const char*)ptr.out.error_string, strnlen((const char*)ptr.out.error_string, sizeof(ptr.out.error_string))); - run_in_thread_async(qApp, [=]() { - QMessageBox::critical(nullptr, "Can't open camera", "PS3 Eye driver error: " + error, QMessageBox::Close); + run_in_thread_async(qApp, [error = std::move(error)] { + dialog::show_open_failure_msgbox(error); }); return false; @@ -247,16 +254,26 @@ OTR_REGISTER_CAMERA(ps3eye_camera_) dialog::dialog(QWidget* parent) : QWidget(parent) { ui.setupUi(this); + t.setInterval(500); t.setSingleShot(true); tie_setting(s.exposure, ui.exposure_slider); tie_setting(s.gain, ui.gain_slider); ui.exposure_label->setValue((int)*s.exposure); ui.gain_label->setValue((int)*s.gain); - connect(&s.exposure, value_::value_changed<slider_value>(), this, [this](const slider_value&) { s.set_exposure(); }); - connect(&s.gain, value_::value_changed<slider_value>(), this, [this](const slider_value&) { s.set_gain(); }); + connect(&s.exposure, value_::value_changed<slider_value>(), this, [this](const slider_value&) { t.stop(); t.start(); }); + connect(&s.gain, value_::value_changed<slider_value>(), this, [this](const slider_value&) { t.stop(); t.start(); }); connect(ui.exposure_slider, &QSlider::valueChanged, ui.exposure_label, &QSpinBox::setValue); connect(ui.gain_slider, &QSlider::valueChanged, ui.gain_label, &QSpinBox::setValue); connect(ui.buttonBox, &QDialogButtonBox::accepted, this, &dialog::do_ok); connect(ui.buttonBox, &QDialogButtonBox::rejected, this, &dialog::do_cancel); + connect(&t, &QTimer::timeout, this, [this] { s.set_exposure(); s.set_gain(); }); +} +void dialog::show_open_failure_msgbox(const QString& error) +{ + const QString& error_ = error.isNull() ? tr("Unknown error") : error; + QMessageBox::critical(nullptr, + tr("Can't open camera"), + tr("PS3 Eye driver error: %1").arg(error_), + QMessageBox::Close); } // XXX copypasta -sh 20200329 diff --git a/video-ps3eye/module.hpp b/video-ps3eye/module.hpp index 56ffe5df..26cfad60 100644 --- a/video-ps3eye/module.hpp +++ b/video-ps3eye/module.hpp @@ -10,6 +10,7 @@ #include <QDialog> #include <QProcess> +#include <QTimer> using namespace options; @@ -34,6 +35,7 @@ class dialog final : public QWidget Q_OBJECT Ui_Dialog ui; settings s; + QTimer t{this}; shm_wrapper shm { "ps3eye-driver-shm", nullptr, sizeof(ps3eye::shm) }; @@ -41,10 +43,11 @@ class dialog final : public QWidget void do_cancel() { s.b->reload(); close(); deleteLater(); } protected: - void closeEvent(QCloseEvent*) override { do_cancel(); } + void closeEvent(QCloseEvent*) override { do_cancel(); if (t.isActive()) { s.set_exposure(); s.set_gain(); } } public: explicit dialog(QWidget* parent = nullptr); + static void show_open_failure_msgbox(const QString& error); }; struct ps3eye_camera final : video::impl::camera @@ -54,7 +57,7 @@ struct ps3eye_camera final : video::impl::camera settings s; frame fr; Timer t; - unsigned char data[640 * 480 * 3] = {}; + unsigned char data[640 * 480 * ps3eye::num_channels] = {}; int framerate = 30, sleep_ms = 1; bool open = false; unsigned timecode = 0; diff --git a/video-ps3eye/ps3eye-driver b/video-ps3eye/ps3eye-driver -Subproject ac056aa85dca83be3b1a14df7b20fd07104e052 +Subproject 67fa41fd0393076f4d0be3e17ae36a40f83bc0c diff --git a/video-ps3eye/shm-layout.hpp b/video-ps3eye/shm-layout.hpp index 577021b9..d7905109 100644 --- a/video-ps3eye/shm-layout.hpp +++ b/video-ps3eye/shm-layout.hpp @@ -3,6 +3,8 @@ namespace ps3eye { +static constexpr unsigned num_channels = 1; + struct shm_in { enum class mode : uint8_t { qvga, vga, }; @@ -23,8 +25,8 @@ struct shm_out status status_; char error_string[256]; union { - uint8_t data_320x240[320][240][3]; - uint8_t data_640x480[640][480][3]; + uint8_t data_320x240[320][240][num_channels]; + uint8_t data_640x480[640][480][num_channels]; }; }; diff --git a/video-ps3eye/wrapper.cxx b/video-ps3eye/wrapper.cxx index eca8968d..0f9344eb 100644 --- a/video-ps3eye/wrapper.cxx +++ b/video-ps3eye/wrapper.cxx @@ -61,16 +61,20 @@ int main(int argc, char** argv) error(out, "no camera found"); auto& camera = cameras[0]; - camera->set_debug(false); + camera->set_debug(true); auto* frame = (uint8_t*)out.data_640x480; decltype(out.timecode) timecode = 0; + constexpr auto fmt = ps3eye::num_channels == 1 + ? ps3eye::format::Gray + : ps3eye::format::BGR; + { int framerate = in.framerate; if (framerate <= 0) framerate = 60; - if (!camera->init(get_mode(in.resolution), framerate)) + if (!camera->init(get_mode(in.resolution), framerate, fmt)) error(out, "camera init failed: %s", camera->error_string()); update_settings(*camera, in); @@ -94,7 +98,7 @@ int main(int argc, char** argv) int framerate = in.framerate; if (framerate <= 0) framerate = 60; - if (!camera->init(get_mode(in.resolution), framerate)) + if (!camera->init(get_mode(in.resolution), framerate, fmt)) error(out, "camera init failed: %s", camera->error_string()); if (!camera->start()) error(out, "can't start camera: %s", camera->error_string()); diff --git a/video/camera.hpp b/video/camera.hpp index a0fe0adb..189f95e1 100644 --- a/video/camera.hpp +++ b/video/camera.hpp @@ -75,12 +75,22 @@ void register_camera(std::unique_ptr<impl::camera_> metadata); static const char init_ ## ctr = \ (::video::impl::register_camera(std::make_unique<type>()), 0); -#define OTR_REGISTER_CAMERA2(type, ctr) \ - OTR_REGISTER_CAMERA3(type, ctr) +#ifdef _MSC_VER + // shared library targets without any symbols break cmake build +# define OTR_REGISTER_CAMERA_IMPL(type) \ + extern "C" __declspec(dllexport) [[maybe_unused]] \ + void _opentrack_module_video_ ##type (void) {} +# define OTR_REGISTER_CAMERA_IMPL2(type) \ + OTR_REGISTER_CAMERA_IMPL(type) +#else +# define OTR_REGISTER_CAMERA_IMPL2(type) +#endif +#define OTR_REGISTER_CAMERA2(type, ctr) \ + OTR_REGISTER_CAMERA3(type, ctr) \ + OTR_REGISTER_CAMERA_IMPL2(type) #define OTR_REGISTER_CAMERA(type) \ OTR_REGISTER_CAMERA2(type, __COUNTER__) - namespace video { using camera_impl = impl::camera; |