Prison

videoscanner.cpp
1/*
2 SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
3 SPDX-License-Identifier: MIT
4*/
5
6#include "videoscanner.h"
7#include "videoscannerframe_p.h"
8#include "videoscannerworker_p.h"
9
10#include <QDebug>
11
12using namespace Prison;
13
14namespace Prison
15{
16class VideoScannerPrivate
17{
18public:
19 void newFrame(const QVideoFrame &videoFrame, bool verticallyFlipped);
20 void setResult(VideoScanner *q, const ScanResult &result);
21
22 QVideoSink *m_sink = nullptr;
23 VideoScannerThread m_thread;
24 VideoScannerWorker m_worker;
25 QByteArray m_frameDataBuffer; // reused memory when we have to copy frame data
26 ScanResult m_result;
27 QVariant m_previousContent;
28 Format::BarcodeFormats m_formats = Format::NoFormat;
29 bool m_workerBusy = false;
30};
31}
32
33void VideoScannerPrivate::newFrame(const QVideoFrame &videoFrame, bool verticallyFlipped)
34{
35 // NOTE: this runs in the render thread
36 if (!m_workerBusy && videoFrame.isValid()) {
37 m_workerBusy = true;
38
39 VideoScannerFrame frame(videoFrame, verticallyFlipped, m_formats);
40 // check if we are only allowed to access this in the render thread
41 if (frame.copyRequired()) {
42 frame.map();
43 if (frame.needsConversion()) {
44 frame.convertToImage();
45 } else {
46 frame.copyFrameData(m_frameDataBuffer);
47 }
48 frame.unmap();
49 }
50
51 Q_EMIT m_worker.scanFrameRequest(frame);
52 }
53}
54
55void VideoScannerPrivate::setResult(VideoScanner *q, const ScanResult &result)
56{
57 m_workerBusy = false;
58 if (m_result == result) {
59 return;
60 }
61
62 m_result = result;
63 Q_EMIT q->resultChanged(result);
64
65 if (m_previousContent == result.content()) {
66 return;
67 }
68 m_previousContent = result.content();
69 Q_EMIT q->resultContentChanged(result);
70}
71
72VideoScanner::VideoScanner(QObject *parent)
73 : QObject(parent)
74 , d(new VideoScannerPrivate)
75{
76 d->m_worker.moveToThread(&d->m_thread);
77 connect(
78 &d->m_worker,
79 &VideoScannerWorker::result,
80 this,
81 [this](const ScanResult &result) {
82 d->setResult(this, result);
83 },
85
86 d->m_thread.setObjectName(QStringLiteral("Prison Barcode Scanner Worker"));
87 d->m_thread.start();
88}
89
90VideoScanner::~VideoScanner()
91{
92 d->m_thread.quit();
93 d->m_thread.wait();
94}
95
96ScanResult VideoScanner::result() const
97{
98 return d->m_result;
99}
100
101Format::BarcodeFormats VideoScanner::formats() const
102{
103 return d->m_formats;
104}
105
107{
108 if (d->m_formats == formats) {
109 return;
110 }
111
112 d->m_formats = formats;
113 Q_EMIT formatsChanged();
114}
115
116QVideoSink *VideoScanner::videoSink() const
117{
118 return d->m_sink;
119}
120
121void VideoScanner::setVideoSink(QVideoSink *sink)
122{
123 if (d->m_sink == sink) {
124 return;
125 }
126
127 if (d->m_sink) {
128 disconnect(d->m_sink, nullptr, this, nullptr);
129 }
130 d->m_sink = sink;
131 connect(d->m_sink, &QVideoSink::videoFrameChanged, this, [this](const QVideoFrame &frame) {
132 d->newFrame(frame, frame.surfaceFormat().scanLineDirection() == QVideoFrameFormat::BottomToTop);
133 });
134 Q_EMIT videoSinkChanged();
135}
136
137#include "moc_videoscanner.cpp"
Result of a barcode scan attempt.
Definition scanresult.h:31
Scans a live video feed for barcodes.
void resultContentChanged(const Prison::ScanResult &scanResult)
Emitted when a barcode with a new content has been detected, but not when merely the position of a ba...
void setFormats(Format::BarcodeFormats formats)
Sets the barcode formats to detect.
void setVideoSink(QVideoSink *sink)
Sets the video sink to scan for barcodes.
void resultChanged(const Prison::ScanResult &scanResult)
Emitted whenever we get a new scan result, as long as any property of the result changes.
Provides classes and methods for generating barcodes.
Definition barcode.h:24
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
void moveToThread(QThread *targetThread)
QueuedConnection
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sun Feb 25 2024 18:42:29 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.