File indexing completed on 2024-05-12 04:01:32

0001 /*
0002     SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
0003     SPDX-License-Identifier: MIT
0004 */
0005 
0006 #ifndef PRISON_VIDEOSCANNERFRAME_P_H
0007 #define PRISON_VIDEOSCANNERFRAME_P_H
0008 
0009 #include "format.h"
0010 
0011 #include <QImage>
0012 #include <QMetaType>
0013 #include <QVideoFrame>
0014 
0015 namespace Prison
0016 {
0017 
0018 /**
0019  *  A single frame from a video feed handed over to the barcode scanner worker thread.
0020  *
0021  *  This abstracts three possible states:
0022  *  - direct data access to the original frame data, when possible
0023  *  - access to an internal copy of at least the luminescence part of the raw frame data
0024  *    if access is only possible in the render thread and the raw format is consumeable
0025  *    by ZXing
0026  *  - a decoded 8bit grayscale QImage of the frame content, if the raw frame data is only
0027  *    accessible in the render thread and the native frame format is not consumeable by
0028  *    ZXing directly
0029  *
0030  *  @internal
0031  */
0032 class VideoScannerFrame
0033 {
0034 public:
0035     explicit VideoScannerFrame();
0036     explicit VideoScannerFrame(const QVideoFrame &frame, bool verticallyFlipped, Format::BarcodeFormats formats);
0037     ~VideoScannerFrame();
0038 
0039     int width() const;
0040     int height() const;
0041     int bytesPerLine() const;
0042     QVideoFrameFormat::PixelFormat pixelFormat() const;
0043 
0044     /** Map/unmap the frame if needed, ie. if we don't already have a copy. */
0045     void map();
0046     void unmap();
0047 
0048     /** Raw frame data, either zero copy or from an internal buffer
0049      *  if we were forced to copy.
0050      *  Possibly truncated to just the subset that contains all the luminescence
0051      *  channel, e.g. for planar formats.
0052      */
0053     const uint8_t *bits() const;
0054 
0055     /** Decides based on the input frame format whether an immediate
0056      *  copy in the reader thread is necessary.
0057      */
0058     bool copyRequired() const;
0059     /** Copy the required subset of the frame data to our internal buffer.
0060      *  @note Requires the frame to be mapped.
0061      */
0062     void copyFrameData(QByteArray &buffer);
0063 
0064     /** Returns whether we have a format that ZXing cannot consume without
0065      *  prior conversion. These are the formats we need to let Qt convert
0066      *  to a QImage first, and in case frame data access is only allowed in
0067      *  the render thread, this also has to happen there.
0068      */
0069     bool needsConversion() const;
0070     /** Convert to grayscale QImage.
0071      *  @note Requires the frame to be mapped.
0072      */
0073     void convertToImage();
0074 
0075     /** The requested barcode formats. */
0076     Format::BarcodeFormats formats() const;
0077 
0078     /** Returns @c true if the raw frame data is vertically flipped compared
0079      *  to how it's displayed. This doesn't impact barcode detection as such,
0080      *  but it requires corresponding adjustments to the coordinates at which
0081      *  a barcode has been detected.
0082      */
0083     bool isVerticallyFlipped() const;
0084 
0085 private:
0086     /** The amount of data to copy. This can be less than the entire frame
0087      *  size for planar formats.
0088      *  @note Requires the frame to be mapped.
0089      */
0090     int frameDataSize() const;
0091 
0092     QVideoFrame m_frame;
0093     const uint8_t *m_frameData = nullptr;
0094     QImage m_image;
0095     Format::BarcodeFormats m_formats = {};
0096     bool m_verticallyFlipped = false;
0097 };
0098 
0099 }
0100 
0101 Q_DECLARE_METATYPE(Prison::VideoScannerFrame)
0102 
0103 #endif // PRISON_VIDEOSCANNERFRAME_P_H