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
128private:
129 QRectF m_rect;
130 int m_grid;
131 QPoint m_dragStart;
132 QSemaphore m_initSem;
133 bool m_isInitialized;
134 std::unique_ptr<Filter> m_glslManager;
135 std::unique_ptr<Event> m_threadStartEvent;
136 std::unique_ptr<Event> m_threadStopEvent;
137 std::unique_ptr<Event> m_threadCreateEvent;
138 std::unique_ptr<Event> m_threadJoinEvent;
139 FrameRenderer *m_frameRenderer;
140 float m_zoom;
141 QPoint m_offset;
142 QUrl m_savedQmlSource;
143 bool m_hideVui;
144 bool m_snapToGrid;
145 QTimer m_refreshTimer;
146 bool m_scrubAudio;
147 QPoint m_mousePosition;
148 std::unique_ptr<RenderThread> m_renderThread;
149
150 static void on_frame_show(mlt_consumer, VideoWidget *widget, mlt_event_data);
151
152private slots:
153 void resizeVideo(int width, int height);
154 void onRefreshTimeout();
155
156protected:
157 void resizeEvent(QResizeEvent *event) override;
158 void mousePressEvent(QMouseEvent *) override;
159 void mouseMoveEvent(QMouseEvent *) override;
160 void keyPressEvent(QKeyEvent *event) override;
161 bool event(QEvent *event) override;
162 void createShader();
163
164 int m_maxTextureSize;
165 SharedFrame m_sharedFrame;
166 QMutex m_mutex;
167};
168
169class RenderThread : public QThread
170{
171 Q_OBJECT
172public:
173 RenderThread(thread_function_t function, void *data);
174 ~RenderThread();
175
176protected:
177 void run();
178
179private:
180 thread_function_t m_function;
181 void *m_data;
182 std::unique_ptr<QOpenGLContext> m_context;
183 std::unique_ptr<QOffscreenSurface> m_surface;
184};
185
186class FrameRenderer : public QThread
187{
188 Q_OBJECT
189public:
190 FrameRenderer();
191 ~FrameRenderer();
192 QSemaphore *semaphore() { return &m_semaphore; }
193 SharedFrame getDisplayFrame();
194 Q_INVOKABLE void showFrame(Mlt::Frame frame);
195 void requestImage();
196 QImage image() const { return m_image; }
197
198signals:
199 void frameDisplayed(const SharedFrame &frame);
200 void imageReady();
201
202private:
203 QSemaphore m_semaphore;
204 SharedFrame m_displayFrame;
205 bool m_imageRequested;
206 QImage m_image;
207};
208
209} // namespace Mlt
210
211#endif
The SharedFrame provides thread safe access to Mlt::Frame data.
Definition sharedframe.h:50