diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2019-02-22 15:20:52 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2019-02-22 15:20:52 +0100 |
commit | 7de0f46028e964bd7b7979835ef0a80cf8cb01b7 (patch) | |
tree | 297ad74ff359a0b6975794e37c89764bd5ec5905 /cv | |
parent | 388e9e57d8dcc1b5eda16670bae0e4518515504c (diff) |
video/widget: fix mutex starvation
Get rid of contention in `preview_size' and `set_image'.
After switching the Qt mutex to non-recursive, turns out the writer
thread preempts the UI thread to the point of freezing the entire thing.
Mutex fairness is an implementation detail and we must assume unfair
mutexes in the worst case.
Diffstat (limited to 'cv')
-rw-r--r-- | cv/video-widget.cpp | 38 | ||||
-rw-r--r-- | cv/video-widget.hpp | 2 |
2 files changed, 17 insertions, 23 deletions
diff --git a/cv/video-widget.cpp b/cv/video-widget.cpp index 7240814f..8ff252c9 100644 --- a/cv/video-widget.cpp +++ b/cv/video-widget.cpp @@ -4,15 +4,15 @@ void cv_video_widget::update_image(const cv::Mat& frame) { - QMutexLocker l(&mtx); - - if (freshp) + if (fresh()) return; + auto [ W, H ] = preview_size(); + if (W < 1 || H < 1 || frame.rows < 1 || frame.cols < 1) return; - cv::Mat const* __restrict frame_scaled = nullptr; + cv::Mat const* __restrict scaled = nullptr; if (frame3.cols != W || frame3.rows != H) { @@ -26,22 +26,20 @@ void cv_video_widget::update_image(const cv::Mat& frame) if (frame.cols != W || frame.rows != H) { cv::resize(frame, frame3, { W, H }, 0, 0, cv::INTER_NEAREST); - frame_scaled = &frame3; + scaled = &frame3; } else if (!frame.isContinuous()) { frame.copyTo(frame3); - frame_scaled = &frame3; + scaled = &frame3; } else - frame_scaled = &frame; - - freshp = true; + scaled = &frame; int color_cvt = 0; constexpr int nchannels = 4; - switch (frame_scaled->channels()) + switch (scaled->channels()) { case 1: color_cvt = cv::COLOR_GRAY2BGRA; @@ -56,23 +54,19 @@ void cv_video_widget::update_image(const cv::Mat& frame) break; } - cv::Mat const* frame_color; + cv::Mat const* color; if (color_cvt != cv::COLOR_COLORCVT_MAX) { - cv::cvtColor(*frame_scaled, frame2, color_cvt); - frame_color = &frame2; + cv::cvtColor(*scaled, frame2, color_cvt); + color = &frame2; } else - frame_color = frame_scaled; + color = scaled; - int stride = frame_color->step.p[0], rows = frame_color->rows; - unsigned nbytes = (unsigned)(rows * stride); - vec.resize(nbytes); vec.shrink_to_fit(); - std::memcpy(vec.data(), frame_color->data, nbytes); + int width = color->cols, height = color->rows; + unsigned stride = color->step.p[0]; + set_image(color->data, width, height, stride, QImage::Format_ARGB32); - texture = QImage((const unsigned char*) vec.data(), W, H, stride, QImage::Format_ARGB32); - texture.setDevicePixelRatio(devicePixelRatioF()); + set_fresh(true); } - -cv_video_widget::cv_video_widget(QWidget* parent) : video_widget(parent) {} diff --git a/cv/video-widget.hpp b/cv/video-widget.hpp index 9d62f19e..54316d32 100644 --- a/cv/video-widget.hpp +++ b/cv/video-widget.hpp @@ -12,7 +12,7 @@ struct cv_video_widget final : video_widget { - cv_video_widget(QWidget* parent = nullptr); + using video_widget::video_widget; void update_image(const cv::Mat& frame); private: |