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 #include "videoscannerframe_p.h"
0007 
0008 #include <cstring>
0009 
0010 using namespace Prison;
0011 
0012 VideoScannerFrame::VideoScannerFrame() = default;
0013 
0014 VideoScannerFrame::VideoScannerFrame(const QVideoFrame &frame, bool isVerticallyFlipped, Format::BarcodeFormats formats)
0015     : m_frame(frame)
0016     , m_formats(formats)
0017     , m_verticallyFlipped(isVerticallyFlipped)
0018 {
0019 }
0020 
0021 VideoScannerFrame::~VideoScannerFrame() = default;
0022 
0023 int VideoScannerFrame::width() const
0024 {
0025     return m_frame.width();
0026 }
0027 
0028 int VideoScannerFrame::height() const
0029 {
0030     return m_frame.height();
0031 }
0032 
0033 int VideoScannerFrame::bytesPerLine() const
0034 {
0035     return m_frame.bytesPerLine(0);
0036 }
0037 
0038 QVideoFrameFormat::PixelFormat VideoScannerFrame::pixelFormat() const
0039 {
0040     return m_frame.pixelFormat();
0041 }
0042 
0043 void VideoScannerFrame::map()
0044 {
0045     if (!m_frameData && m_image.isNull()) {
0046         m_frame.map(QVideoFrame::ReadOnly);
0047     }
0048 }
0049 
0050 void VideoScannerFrame::unmap()
0051 {
0052     if (m_frame.isMapped()) {
0053         m_frame.unmap();
0054     }
0055 }
0056 
0057 const uint8_t *VideoScannerFrame::bits() const
0058 {
0059     if (m_frameData) {
0060         return m_frameData;
0061     }
0062     if (!m_image.isNull()) {
0063         return m_image.bits();
0064     }
0065 
0066     Q_ASSERT(m_frame.isMapped());
0067     return m_frame.bits(0);
0068 }
0069 
0070 bool VideoScannerFrame::copyRequired() const
0071 {
0072     return m_frame.handleType() == QVideoFrame::RhiTextureHandle;
0073 }
0074 
0075 void VideoScannerFrame::copyFrameData(QByteArray &buffer)
0076 {
0077     Q_ASSERT(m_frame.isMapped());
0078 
0079     const auto size = frameDataSize();
0080     if (buffer.size() != size) {
0081         buffer.resize(size);
0082     }
0083     std::memcpy(buffer.data(), m_frame.bits(0), size);
0084     m_frameData = reinterpret_cast<const uint8_t *>(buffer.constData());
0085 }
0086 
0087 int VideoScannerFrame::frameDataSize() const
0088 {
0089     Q_ASSERT(m_frame.isMapped());
0090 
0091     switch (m_frame.pixelFormat()) {
0092     case QVideoFrameFormat::Format_YUV420P:
0093     case QVideoFrameFormat::Format_YUV422P:
0094     case QVideoFrameFormat::Format_YV12:
0095     case QVideoFrameFormat::Format_NV12:
0096     case QVideoFrameFormat::Format_NV21:
0097     case QVideoFrameFormat::Format_IMC1:
0098     case QVideoFrameFormat::Format_IMC2:
0099     case QVideoFrameFormat::Format_IMC3:
0100     case QVideoFrameFormat::Format_IMC4:
0101         return m_frame.mappedBytes(0) / 2;
0102     default:
0103         return m_frame.mappedBytes(0);
0104     }
0105 }
0106 
0107 bool VideoScannerFrame::needsConversion() const
0108 {
0109     switch (m_frame.pixelFormat()) {
0110     case QVideoFrameFormat::Format_Jpeg:
0111     case QVideoFrameFormat::Format_SamplerExternalOES:
0112     case QVideoFrameFormat::Format_SamplerRect:
0113         return true;
0114     default:
0115         return false;
0116     }
0117 }
0118 
0119 void VideoScannerFrame::convertToImage()
0120 {
0121     if (!m_image.isNull()) {
0122         return;
0123     }
0124 
0125     Q_ASSERT(m_frame.isMapped());
0126     m_image = m_frame.toImage();
0127     m_image.convertTo(QImage::Format_Grayscale8);
0128 }
0129 
0130 bool VideoScannerFrame::isVerticallyFlipped() const
0131 {
0132     return m_verticallyFlipped;
0133 }
0134 
0135 Format::BarcodeFormats VideoScannerFrame::formats() const
0136 {
0137     return m_formats;
0138 }