summaryrefslogtreecommitdiffhomepage
path: root/video/video-widget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'video/video-widget.cpp')
-rw-r--r--video/video-widget.cpp90
1 files changed, 90 insertions, 0 deletions
diff --git a/video/video-widget.cpp b/video/video-widget.cpp
new file mode 100644
index 00000000..3018a3c4
--- /dev/null
+++ b/video/video-widget.cpp
@@ -0,0 +1,90 @@
+#include "video-widget.hpp"
+
+#include "compat/check-visible.hpp"
+#include "compat/math.hpp"
+
+#include <cstring>
+
+#include <QPainter>
+#include <QtAlgorithms>
+#include <QDebug>
+
+void video_widget::init_image_nolock()
+{
+ double dpi = devicePixelRatioF();
+ size_.store({ iround(width() * dpi), iround(height() * dpi) }, std::memory_order_release);
+}
+
+video_widget::video_widget(QWidget* parent) : QWidget(parent)
+{
+ if (parent)
+ setFixedSize(parent->size());
+ else
+ setFixedSize(320, 240);
+ init_image_nolock();
+ connect(&timer, &QTimer::timeout, this, &video_widget::draw_image, Qt::DirectConnection);
+ timer.start(15);
+}
+
+void video_widget::update_image(const QImage& img)
+{
+ if (fresh())
+ return;
+
+ set_image(img.constBits(), img.width(), img.height(),
+ img.bytesPerLine(), img.format());
+ set_fresh(true);
+}
+
+void video_widget::set_image(const unsigned char* src, int width, int height, int stride, QImage::Format fmt)
+{
+ QMutexLocker l(&mtx);
+
+ texture = QImage();
+ unsigned nbytes = (unsigned)(stride * height);
+ vec.resize(nbytes); vec.shrink_to_fit();
+ std::memcpy(vec.data(), src, nbytes);
+ texture = QImage((const unsigned char*)vec.data(), width, height, stride, fmt);
+}
+
+void video_widget::paintEvent(QPaintEvent*)
+{
+ QPainter painter(this);
+
+ QMutexLocker l(&mtx);
+ painter.drawImage(rect(), texture);
+}
+
+void video_widget::draw_image()
+{
+ if (!fresh())
+ return;
+
+ if (!check_is_visible())
+ return;
+
+ repaint();
+ set_fresh(false);
+}
+
+void video_widget::resizeEvent(QResizeEvent*)
+{
+ QMutexLocker l(&mtx);
+ init_image_nolock();
+}
+
+std::tuple<int, int> video_widget::preview_size() const
+{
+ QSize sz = size_.load(std::memory_order_acquire);
+ return { sz.width(), sz.height() };
+}
+
+bool video_widget::fresh() const
+{
+ return fresh_.load(std::memory_order_acquire);
+}
+
+void video_widget::set_fresh(bool x)
+{
+ fresh_.store(x, std::memory_order_release);
+}