CuteLogger
Fast and simple logging solution for Qt based applications
videowidget.h
1/*
2 * Copyright (c) 2011-2025 Meltytech, LLC
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef VIDEOWIDGET_H
19#define VIDEOWIDGET_H
20
21#include "mltcontroller.h"
22#include "settings.h"
23#include "sharedframe.h"
24
25#include <QMutex>
26#include <QQuickWidget>
27#include <QRectF>
28#include <QSemaphore>
29#include <QThread>
30#include <QTimer>
31
32class QmlFilter;
33class QmlMetadata;
34class QOpenGLContext;
35class QOffscreenSurface;
36
37namespace Mlt {
38
39class Filter;
40class RenderThread;
41class FrameRenderer;
42
43typedef void *(*thread_function_t)(void *);
44
45class VideoWidget : public QQuickWidget, public Controller
46{
47 Q_OBJECT
48 Q_PROPERTY(QRectF rect READ rect NOTIFY rectChanged)
49 Q_PROPERTY(int grid READ grid NOTIFY gridChanged)
50 Q_PROPERTY(bool snapToGrid READ snapToGrid NOTIFY snapToGridChanged)
51 Q_PROPERTY(float zoom READ zoom NOTIFY zoomChanged)
52 Q_PROPERTY(QPoint offset READ offset NOTIFY offsetChanged)
53
54public:
55 VideoWidget(QObject *parent = 0);
56 virtual ~VideoWidget();
57
58 int setProducer(Mlt::Producer *, bool isMulti = false) override;
59 void createThread(RenderThread **thread, thread_function_t function, void *data);
60 void startGlsl();
61 void stopGlsl();
62 int reconfigure(bool isMulti) override;
63
64 void play(double speed = 1.0) override
65 {
66 Controller::play(speed);
67 if (speed == 0)
68 emit paused();
69 else
70 emit playing();
71 }
72 void seek(int position) override
73 {
74 Controller::seek(position);
75 if (Settings.playerPauseAfterSeek())
76 emit paused();
77 }
78 void refreshConsumer(bool scrubAudio = false) override;
79 void pause(int position = -1) override
80 {
81 Controller::pause();
82 emit paused();
83 }
84 int displayWidth() const override { return m_rect.width(); }
85 int displayHeight() const override { return m_rect.height(); }
86
87 QObject *videoWidget() override { return this; }
88 QRectF rect() const { return m_rect; }
89 int grid() const { return m_grid; }
90 float zoom() const { return m_zoom * MLT.profile().width() / m_rect.width(); }
91 QPoint offset() const;
92 QImage image() const;
93 bool imageIsProxy() const;
94 void requestImage() const;
95 bool snapToGrid() const { return m_snapToGrid; }
96 int maxTextureSize() const { return m_maxTextureSize; }
97 void toggleVuiDisplay();
98
99public slots:
100 void setGrid(int grid);
101 void setZoom(float zoom);
102 void setOffsetX(int x);
103 void setOffsetY(int y);
104 void setBlankScene();
105 void setCurrentFilter(QmlFilter *filter, QmlMetadata *meta);
106 void setSnapToGrid(bool snap);
107 virtual void initialize();
108 virtual void beforeRendering(){};
109 virtual void renderVideo();
110 virtual void onFrameDisplayed(const SharedFrame &frame);
111
112signals:
113 void frameDisplayed(const SharedFrame &frame);
114 void dragStarted();
115 void seekTo(int x);
116 void gpuNotSupported();
117 void started();
118 void paused();
119 void playing();
120 void rectChanged();
121 void gridChanged();
122 void zoomChanged();
123 void offsetChanged(const QPoint &offset = QPoint());
124 void imageReady();
125 void snapToGridChanged();
126 void toggleZoom(bool);
127 void stepZoom(float, float);
128
129private:
130 QRectF m_rect;
131 int m_grid;
132 QPoint m_dragStart;
133 QSemaphore m_initSem;
134 bool m_isInitialized;
135 std::unique_ptr<Filter> m_glslManager;
136 std::unique_ptr<Event> m_threadStartEvent;
137 std::unique_ptr<Event> m_threadStopEvent;
138 std::unique_ptr<Event> m_threadCreateEvent;
139 std::unique_ptr<Event> m_threadJoinEvent;
140 FrameRenderer *m_frameRenderer;
141 float m_zoom;
142 QPoint m_offset;
143 QUrl m_savedQmlSource;
144 bool m_hideVui;
145 bool m_snapToGrid;
146 QTimer m_refreshTimer;
147 bool m_scrubAudio;
148 QPoint m_mousePosition;
149 std::unique_ptr<RenderThread> m_renderThread;
150
151 static void on_frame_show(mlt_consumer, VideoWidget *widget, mlt_event_data);
152
153private slots:
154 void resizeVideo(int width, int height);
155 void onRefreshTimeout();
156
157protected:
158 void resizeEvent(QResizeEvent *event) override;
159 void mousePressEvent(QMouseEvent *) override;
160 void mouseMoveEvent(QMouseEvent *) override;
161 void wheelEvent(QWheelEvent *event) override;
162 void keyPressEvent(QKeyEvent *event) override;
163 bool event(QEvent *event) override;
164 void createShader();
165
166 int m_maxTextureSize;
167 SharedFrame m_sharedFrame;
168 QMutex m_mutex;
169};
170
171class RenderThread : public QThread
172{
173 Q_OBJECT
174public:
175 RenderThread(thread_function_t function, void *data);
176 ~RenderThread();
177
178protected:
179 void run();
180
181private:
182 thread_function_t m_function;
183 void *m_data;
184 std::unique_ptr<QOpenGLContext> m_context;
185 std::unique_ptr<QOffscreenSurface> m_surface;
186};
187
188class FrameRenderer : public QThread
189{
190 Q_OBJECT
191public:
192 FrameRenderer();
193 ~FrameRenderer();
194 QSemaphore *semaphore() { return &m_semaphore; }
195 SharedFrame getDisplayFrame();
196 Q_INVOKABLE void showFrame(Mlt::Frame frame);
197 void requestImage();
198 QImage image() const { return m_image; }
199
200signals:
201 void frameDisplayed(const SharedFrame &frame);
202 void imageReady();
203
204private:
205 QSemaphore m_semaphore;
206 SharedFrame m_displayFrame;
207 bool m_imageRequested;
208 QImage m_image;
209};
210
211} // namespace Mlt
212
213#endif