1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include "qabstractvideofilter.h" |
41 | |
42 | QT_BEGIN_NAMESPACE |
43 | |
44 | /*! |
45 | \class QAbstractVideoFilter |
46 | \since 5.5 |
47 | \brief The QAbstractVideoFilter class represents a filter that is applied to the video frames |
48 | received by a VideoOutput type. |
49 | \inmodule QtMultimedia |
50 | |
51 | \ingroup multimedia |
52 | \ingroup multimedia_video |
53 | |
54 | QAbstractVideoFilter provides a convenient way for applications to run image |
55 | processing, computer vision algorithms or any generic transformation or |
56 | calculation on the output of a VideoOutput type, regardless of the source |
57 | (video or camera). By providing a simple interface it allows applications and |
58 | third parties to easily develop QML types that provide image processing |
59 | algorithms using popular frameworks like \l{http://opencv.org}{OpenCV}. Due to |
60 | the close integration with the final stages of the Qt Multimedia video |
61 | pipeline, accelerated and possibly zero-copy solutions are feasible too: for |
62 | instance, a plugin providing OpenCL-based algorithms can use OpenCL's OpenGL |
63 | interop to use the OpenGL textures created by a hardware accelerated video |
64 | decoder, without additional readbacks and copies. |
65 | |
66 | \note QAbstractVideoFilter is not always the best choice. To apply effects or |
67 | transformations using OpenGL shaders to the image shown on screen, the |
68 | standard Qt Quick approach of using ShaderEffect items in combination with |
69 | VideoOutput should be used. VideoFilter is not a replacement for this. It is |
70 | rather targeted for performing computations (that do not necessarily change |
71 | the image shown on screen) and computer vision algorithms provided by |
72 | external frameworks. |
73 | |
74 | QAbstractVideoFilter is meant to be subclassed. The subclasses are then registered to |
75 | the QML engine, so they can be used as a QML type. The list of filters are |
76 | assigned to a VideoOutput type via its \l{QtMultimedia::VideoOutput::filters}{filters} |
77 | property. |
78 | |
79 | A single filter represents one transformation or processing step on |
80 | a video frame. The output is a modified video frame, some arbitrary data or |
81 | both. For example, image transformations will result in a different image, |
82 | whereas an algorithm for detecting objects on an image will likely provide |
83 | a list of rectangles. |
84 | |
85 | Arbitrary data can be represented as properties on the QAbstractVideoFilter subclass |
86 | and on the QObject or QJSValue instances passed to its signals. What exactly |
87 | these properties and signals are, is up to the individual video |
88 | filters. Completion of the operations can be indicated by |
89 | signals. Computations that do not result in a modified image will pass the |
90 | input image through so that subsequent filters can be placed after them. |
91 | |
92 | Properties set on QAbstractVideoFilter serve as input to the computation, similarly |
93 | to how uniform values are specified in ShaderEffect types. The changed |
94 | property values are taken into use when the next video frame is processed. |
95 | |
96 | The typical usage is to subclass QAbstractVideoFilter and QVideoFilterRunnable: |
97 | |
98 | \badcode |
99 | class MyFilterRunnable : public QVideoFilterRunnable { |
100 | public: |
101 | QVideoFrame run(QVideoFrame *input, const QVideoSurfaceFormat &surfaceFormat, RunFlags flags) { ... } |
102 | }; |
103 | |
104 | class MyFilter : public QAbstractVideoFilter { |
105 | public: |
106 | QVideoFilterRunnable *createFilterRunnable() { return new MyFilterRunnable; } |
107 | signals: |
108 | void finished(QObject *result); |
109 | }; |
110 | |
111 | int main(int argc, char **argv) { |
112 | ... |
113 | qmlRegisterType<MyFilter>("my.uri", 1, 0, "MyFilter"); |
114 | ... |
115 | } |
116 | \endcode |
117 | |
118 | MyFilter is thus accessible from QML: |
119 | |
120 | \badcode |
121 | import my.uri 1.0 |
122 | |
123 | Camera { |
124 | id: camera |
125 | } |
126 | MyFilter { |
127 | id: filter |
128 | // set properties, they can also be animated |
129 | onFinished: console.log("results of the computation: " + result) |
130 | } |
131 | VideoOutput { |
132 | source: camera |
133 | filters: [ filter ] |
134 | anchors.fill: parent |
135 | } |
136 | \endcode |
137 | |
138 | This also allows providing filters in QML plugins, separately from the application. |
139 | |
140 | \sa VideoOutput, Camera, MediaPlayer, QVideoFilterRunnable |
141 | */ |
142 | |
143 | /*! |
144 | \class QVideoFilterRunnable |
145 | \since 5.5 |
146 | \brief The QVideoFilterRunnable class represents the implementation of a filter |
147 | that owns all graphics and computational resources, and performs the actual filtering |
148 | or calculations. |
149 | \inmodule QtMultimedia |
150 | |
151 | \ingroup multimedia |
152 | \ingroup multimedia_video |
153 | |
154 | Video filters are split into QAbstractVideoFilter and corresponding QVideoFilterRunnable |
155 | instances, similar to QQuickItem and QSGNode. This is necessary to support |
156 | threaded rendering scenarios. When using the threaded render loop of the Qt |
157 | Quick scene graph, all rendering happens on a dedicated thread. |
158 | QVideoFilterRunnable instances always live on this thread and all its functions, |
159 | run(), the constructor, and the destructor, are guaranteed to be invoked on |
160 | that thread with the OpenGL context bound. QAbstractVideoFilter instances live on |
161 | the main (GUI) thread, like any other QObject and QQuickItem instances |
162 | created from QML. |
163 | |
164 | Once created, QVideoFilterRunnable instances are managed by Qt Multimedia and |
165 | will be automatically destroyed and recreated when necessary, for example |
166 | when the scene graph is invalidated or the QQuickWindow changes or is closed. |
167 | Creation happens via the QAbstractVideoFilter::createFilterRunnable() factory function. |
168 | |
169 | \sa QAbstractVideoFilter |
170 | */ |
171 | |
172 | /*! |
173 | \fn QVideoFrame QVideoFilterRunnable::run(QVideoFrame *input, const QVideoSurfaceFormat &surfaceFormat, RunFlags flags) |
174 | |
175 | Reimplement this function to perform filtering or computation on the \a |
176 | input video frame. Like the constructor and destructor, this function is |
177 | always called on the render thread with the OpenGL context bound. |
178 | |
179 | Implementations that do not modify the video frame can simply return \a input. |
180 | |
181 | It is safe to access properties of the associated QAbstractVideoFilter instance from |
182 | this function. |
183 | |
184 | \a input will not be mapped, it is up to this function to call QVideoFrame::map() |
185 | and QVideoFrame::unmap() as necessary. |
186 | |
187 | \a surfaceFormat provides additional information, for example it can be used |
188 | to determine which way is up in the input image as that is important for |
189 | filters to operate on multiple platforms with multiple cameras. |
190 | |
191 | \a flags contains additional information about the filter's invocation. For |
192 | example the LastInChain flag indicates that the filter is the last in a |
193 | VideoOutput's associated filter list. This can be very useful in cases where |
194 | multiple filters are chained together and the work is performed on image data |
195 | in some custom format (for example a format specific to some computer vision |
196 | framework). To avoid conversion on every filter in the chain, all |
197 | intermediate filters can return a QVideoFrame hosting data in the custom |
198 | format. Only the last, where the flag is set, returns a QVideoFrame in a |
199 | format compatible with Qt. |
200 | |
201 | Filters that want to expose the results of their computation to Javascript |
202 | code in QML can declare their own custom signals in the QAbstractVideoFilter |
203 | subclass to indicate the completion of the operation. For filters that only |
204 | calculate some results and do not modify the video frame, it is also possible |
205 | to operate asynchronously. They can queue the necessary operations using the |
206 | compute API and return from this function without emitting any signals. The |
207 | signal indicating the completion is then emitted only when the compute API |
208 | indicates that the operations were done and the results are available. Note |
209 | that it is strongly recommended to represent the filter's output data as a |
210 | separate instance of QJSValue or a QObject-derived class which is passed as a |
211 | parameter to the signal and becomes exposed to the Javascript engine. In case |
212 | of QObject the ownership of this object is controlled by the standard QML |
213 | rules: if it has no parent, ownership is transferred to the Javascript engine, |
214 | otherwise it stays with the emitter. Note that the signal connection may be |
215 | queued,for example when using the threaded render loop of Qt Quick, and so the |
216 | object must stay valid for a longer time, destroying it right after calling |
217 | this function is not safe. Using a dedicated results object is guaranteed to |
218 | be safe even when using threaded rendering. The same is not necessarily true |
219 | for properties on the QAbstractVideoFilter instance itself: properties can |
220 | safely be read in run() since the gui thread is blocked during that time but |
221 | writing may become problematic. |
222 | |
223 | \note Avoid time consuming operations in this function as they block the |
224 | entire rendering of the application. |
225 | |
226 | \note The handleType() and pixelFormat() of \a input is completely up to the |
227 | video decoding backend on the platform in use. On some platforms different |
228 | forms of input are used depending on the graphics stack. For example, when |
229 | playing back videos on Windows with the WMF backend, QVideoFrame contains |
230 | OpenGL-wrapped Direct3D textures in case of using ANGLE, but regular pixel |
231 | data when using desktop OpenGL (opengl32.dll). Similarly, the video file |
232 | format will often decide if the data is RGB or YUV, but this may also depend |
233 | on the decoder and the configuration in use. The returned video frame does |
234 | not have to be in the same format as the input, for example a filter with an |
235 | input of a QVideoFrame backed by system memory can output a QVideoFrame with |
236 | an OpenGL texture handle. |
237 | |
238 | \sa QVideoFrame, QVideoSurfaceFormat |
239 | */ |
240 | |
241 | /*! |
242 | \enum QVideoFilterRunnable::RunFlag |
243 | |
244 | \value LastInChain Indicates that the filter runnable's associated QAbstractVideoFilter |
245 | is the last in the corresponding VideoOutput type's filters list, meaning |
246 | that the returned frame is the one that is going to be presented to the scene |
247 | graph without invoking any further filters. |
248 | */ |
249 | |
250 | class QAbstractVideoFilterPrivate |
251 | { |
252 | public: |
253 | QAbstractVideoFilterPrivate() : |
254 | active(true) |
255 | { } |
256 | |
257 | bool active; |
258 | }; |
259 | |
260 | /*! |
261 | \internal |
262 | */ |
263 | QVideoFilterRunnable::~QVideoFilterRunnable() |
264 | { |
265 | } |
266 | |
267 | /*! |
268 | Constructs a new QAbstractVideoFilter instance with parent object \a parent. |
269 | */ |
270 | QAbstractVideoFilter::QAbstractVideoFilter(QObject *parent) : |
271 | QObject(parent), |
272 | d_ptr(new QAbstractVideoFilterPrivate) |
273 | { |
274 | } |
275 | |
276 | /*! |
277 | \internal |
278 | */ |
279 | QAbstractVideoFilter::~QAbstractVideoFilter() |
280 | { |
281 | delete d_ptr; |
282 | } |
283 | |
284 | /*! |
285 | \property QAbstractVideoFilter::active |
286 | \brief the active status of the filter. |
287 | |
288 | This is true if the filter is active, false otherwise. |
289 | |
290 | By default filters are active. When set to \c false, the filter will be |
291 | ignored by the VideoOutput type. |
292 | */ |
293 | bool QAbstractVideoFilter::isActive() const |
294 | { |
295 | Q_D(const QAbstractVideoFilter); |
296 | return d->active; |
297 | } |
298 | |
299 | void QAbstractVideoFilter::setActive(bool v) |
300 | { |
301 | Q_D(QAbstractVideoFilter); |
302 | if (d->active != v) { |
303 | d->active = v; |
304 | emit activeChanged(); |
305 | } |
306 | } |
307 | |
308 | /*! |
309 | \fn QVideoFilterRunnable *QAbstractVideoFilter::createFilterRunnable() |
310 | |
311 | Factory function to create a new instance of a QVideoFilterRunnable subclass |
312 | corresponding to this filter. |
313 | |
314 | This function is called on the thread on which the Qt Quick scene graph |
315 | performs rendering, with the OpenGL context bound. Ownership of the returned |
316 | instance is transferred: the returned instance will live on the render thread |
317 | and will be destroyed automatically when necessary. |
318 | |
319 | Typically, implementations of the function will simply construct a new |
320 | QVideoFilterRunnable instance, passing \c this to the constructor as the |
321 | filter runnables must know their associated QAbstractVideoFilter instance to |
322 | access dynamic properties and optionally emit signals. |
323 | */ |
324 | |
325 | QT_END_NAMESPACE |
326 | |