CuteLogger
Fast and simple logging solution for Qt based applications
videowidget.h
1/*
2 * Copyright (c) 2011-2023 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 "sharedframe.h"
23
24#include <QMutex>
25#include <QQuickWidget>
26#include <QRectF>
27#include <QSemaphore>
28#include <QThread>
29#include <QTimer>
30
31class QmlFilter;
32class QmlMetadata;
33class QOpenGLContext;
34class QOffscreenSurface;
35
36namespace Mlt {
37
38class Filter;
39class RenderThread;
40class FrameRenderer;
41
42typedef void *(*thread_function_t)(void *);
43
44class VideoWidget : public QQuickWidget, public Controller
45{
46 Q_OBJECT
47 Q_PROPERTY(QRectF rect READ rect NOTIFY rectChanged)
48 Q_PROPERTY(int grid READ grid NOTIFY gridChanged)
49 Q_PROPERTY(bool snapToGrid READ snapToGrid NOTIFY snapToGridChanged)
50 Q_PROPERTY(float zoom READ zoom NOTIFY zoomChanged)
51 Q_PROPERTY(QPoint offset READ offset NOTIFY offsetChanged)
52
53public:
54 VideoWidget(QObject *parent = 0);
55 virtual ~VideoWidget();
56
57 int setProducer(Mlt::Producer *, bool isMulti = false);
58 void createThread(RenderThread **thread, thread_function_t function, void *data);
59 void startGlsl();
60 void stopGlsl();
61 int reconfigure(bool isMulti);
62
63 void play(double speed = 1.0)
64 {
65 Controller::play(speed);
66 if (speed == 0)
67 emit paused();
68 else
69 emit playing();
70 }
71 void seek(int position)
72 {
73 Controller::seek(position);
74 emit paused();
75 }
76 void refreshConsumer(bool scrubAudio = false);
77 void pause()
78 {
79 Controller::pause();
80 emit paused();
81 }
82 int displayWidth() const { return m_rect.width(); }
83 int displayHeight() const { return m_rect.height(); }
84
85 QObject *videoWidget() { return this; }
86 QRectF rect() const { return m_rect; }
87 int grid() const { return m_grid; }
88 float zoom() const { return m_zoom * MLT.profile().width() / m_rect.width(); }
89 QPoint offset() const;
90 QImage image() const;
91 bool imageIsProxy() const;
92 void requestImage() const;
93 bool snapToGrid() const { return m_snapToGrid; }
94 int maxTextureSize() const { return m_maxTextureSize; }
95 void toggleVuiDisplay();
96
97public slots:
98 void setGrid(int grid);
99 void setZoom(float zoom);
100 void setOffsetX(int x);
101 void setOffsetY(int y);
102 void setBlankScene();
103 void setCurrentFilter(QmlFilter *filter, QmlMetadata *meta);
104 void setSnapToGrid(bool snap);
105 virtual void initialize();
106 virtual void beforeRendering(){};
107 virtual void renderVideo();
108 virtual void onFrameDisplayed(const SharedFrame &frame);
109
110signals:
111 void frameDisplayed(const SharedFrame &frame);
112 void dragStarted();
113 void seekTo(int x);
114 void gpuNotSupported();
115 void started();
116 void paused();
117 void playing();
118 void rectChanged();
119 void gridChanged();
120 void zoomChanged();
121 void offsetChanged(const QPoint &offset = QPoint());
122 void imageReady();
123 void snapToGridChanged();
124 void toggleZoom(bool);
125
126private:
127 QRectF m_rect;
128 int m_grid;
129 QPoint m_dragStart;
130 QSemaphore m_initSem;
131 bool m_isInitialized;
132 std::unique_ptr<Filter> m_glslManager;
133 std::unique_ptr<Event> m_threadStartEvent;
134 std::unique_ptr<Event> m_threadStopEvent;
135 std::unique_ptr<Event> m_threadCreateEvent;
136 std::unique_ptr<Event> m_threadJoinEvent;
137 FrameRenderer *m_frameRenderer;
138 float m_zoom;
139 QPoint m_offset;
140 QUrl m_savedQmlSource;
141 bool m_hideVui;
142 bool m_snapToGrid;
143 QTimer m_refreshTimer;
144 bool m_scrubAudio;
145 QPoint m_mousePosition;
146 std::unique_ptr<RenderThread> m_renderThread;
147
148 static void on_frame_show(mlt_consumer, VideoWidget *widget, mlt_event_data);
149
150private slots:
151 void resizeVideo(int width, int height);
152 void onRefreshTimeout();
153
154protected:
155 void resizeEvent(QResizeEvent *event);
156 void mousePressEvent(QMouseEvent *);
157 void mouseMoveEvent(QMouseEvent *);
158 void keyPressEvent(QKeyEvent *event);
159 bool event(QEvent *event);
160 void createShader();
161
162 int m_maxTextureSize;
163 SharedFrame m_sharedFrame;
164 QMutex m_mutex;
165};
166
167class RenderThread : public QThread
168{
169 Q_OBJECT
170public:
171 RenderThread(thread_function_t function, void *data);
172 ~RenderThread();
173
174protected:
175 void run();
176
177private:
178 thread_function_t m_function;
179 void *m_data;
180 std::unique_ptr<QOpenGLContext> m_context;
181 std::unique_ptr<QOffscreenSurface> m_surface;
182};
183
184class FrameRenderer : public QThread
185{
186 Q_OBJECT
187public:
188 FrameRenderer();
189 ~FrameRenderer();
190 QSemaphore *semaphore() { return &m_semaphore; }
191 SharedFrame getDisplayFrame();
192 Q_INVOKABLE void showFrame(Mlt::Frame frame);
193 void requestImage();
194 QImage image() const { return m_image; }
195
196signals:
197 void frameDisplayed(const SharedFrame &frame);
198 void imageReady();
199
200private:
201 QSemaphore m_semaphore;
202 SharedFrame m_displayFrame;
203 bool m_imageRequested;
204 QImage m_image;
205};
206
207} // namespace Mlt
208
209#endif