1 | // Copyright (C) 2024 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include "framegenerator_p.h" |
5 | #include <QtCore/qdebug.h> |
6 | |
7 | #include <private/qplatformmediaintegration_p.h> |
8 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | void VideoGenerator::setPattern(ImagePattern pattern) |
12 | { |
13 | m_pattern = pattern; |
14 | } |
15 | |
16 | void VideoGenerator::setFrameCount(int count) |
17 | { |
18 | m_maxFrameCount = count; |
19 | } |
20 | |
21 | void VideoGenerator::setSize(QSize size) |
22 | { |
23 | m_size = size; |
24 | } |
25 | |
26 | void VideoGenerator::setPixelFormat(QVideoFrameFormat::PixelFormat pixelFormat) |
27 | { |
28 | m_pixelFormat = pixelFormat; |
29 | } |
30 | |
31 | void VideoGenerator::setFrameRate(double rate) |
32 | { |
33 | m_frameRate = rate; |
34 | } |
35 | |
36 | void VideoGenerator::setPeriod(std::chrono::milliseconds period) |
37 | { |
38 | m_period = period; |
39 | } |
40 | |
41 | void VideoGenerator::setPresentationRotation(QtVideo::Rotation rotation) |
42 | { |
43 | m_presentationRotation = rotation; |
44 | } |
45 | |
46 | void VideoGenerator::setPresentationMirrored(bool mirror) |
47 | { |
48 | m_presentationMirrored = mirror; |
49 | } |
50 | |
51 | void VideoGenerator::emitEmptyFrameOnStop() |
52 | { |
53 | m_emitEmptyFrameOnStop = true; |
54 | } |
55 | |
56 | static void fillColoredSquares(QImage& image) |
57 | { |
58 | QList<QColor> colors = { Qt::red, Qt::green, Qt::blue, Qt::yellow }; |
59 | const int width = image.width(); |
60 | const int height = image.height(); |
61 | |
62 | for (int j = 0; j < height; ++j) { |
63 | for (int i = 0; i < width; ++i) { |
64 | const int colorX = i < width / 2 ? 0 : 1; |
65 | const int colorY = j < height / 2 ? 0 : 1; |
66 | const int colorIndex = colorX + 2 * colorY; |
67 | image.setPixel(x: i, y: j, index_or_rgb: colors[colorIndex].rgb()); |
68 | } |
69 | } |
70 | } |
71 | |
72 | QVideoFrame VideoGenerator::createFrame() |
73 | { |
74 | using namespace std::chrono; |
75 | |
76 | QImage image(m_size, QImage::Format_ARGB32); |
77 | switch (m_pattern) { |
78 | case ImagePattern::SingleColor: |
79 | image.fill(color: colors[m_frameIndex % colors.size()]); |
80 | break; |
81 | case ImagePattern::ColoredSquares: |
82 | fillColoredSquares(image); |
83 | break; |
84 | } |
85 | |
86 | QVideoFrame rgbFrame(image); |
87 | QVideoFrameFormat outputFormat { m_size, m_pixelFormat }; |
88 | QVideoFrame frame = |
89 | QPlatformMediaIntegration::instance()->convertVideoFrame(rgbFrame, outputFormat); |
90 | |
91 | if (m_frameRate) |
92 | frame.setStreamFrameRate(*m_frameRate); |
93 | |
94 | if (m_period) { |
95 | frame.setStartTime(duration_cast<microseconds>(d: *m_period).count() * m_frameIndex); |
96 | frame.setEndTime(duration_cast<microseconds>(d: *m_period).count() * (m_frameIndex + 1)); |
97 | } |
98 | |
99 | if (m_presentationRotation) |
100 | frame.setRotation(*m_presentationRotation); |
101 | |
102 | if (m_presentationMirrored) |
103 | frame.setMirrored(*m_presentationMirrored); |
104 | |
105 | return frame; |
106 | } |
107 | |
108 | void VideoGenerator::nextFrame() |
109 | { |
110 | if (m_frameIndex == m_maxFrameCount) { |
111 | emit done(); |
112 | if (m_emitEmptyFrameOnStop) |
113 | emit frameCreated(frame: {}); |
114 | return; |
115 | } |
116 | |
117 | const QVideoFrame frame = createFrame(); |
118 | emit frameCreated(frame); |
119 | ++m_frameIndex; |
120 | } |
121 | |
122 | QT_END_NAMESPACE |
123 | |
124 | #include "moc_framegenerator_p.cpp" |
125 | |