summaryrefslogtreecommitdiffstats
path: root/examples/multimedia/video/doc/src/qmlvideofx.qdoc
blob: edbd369c076dfb4494168b9535774dfbef781255 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file.  Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: http://www.gnu.org/copyleft/fdl.html.
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
\example video/qmlvideofx
\title QML Video Shader Effects Example
\ingroup multimedia_examples

\brief The QML Video Shader Effects Example shows how \l {ShaderEffect}
can be used to apply postprocessing effects, expressed in \c GLSL, to video
and camera viewfinder content.

\include examples-run.qdocinc

\section1 Overview

This example shows how a \l {ShaderEffect} can be used to apply
postprocessing effects, expressed in GLSL, to QML \l {VideoOutput} items.

It also shows how native code can be combined with QML to implement more
advanced functionality - in this case, C++ code is used to calculate the QML
frame rate.  This value is rendered in QML in a semi-transparent item
overlaid on the video content.

The following screenshots show shader effects being applied.  In each case,
the effect is implemented using a fragment shader.

Here we see an edge detection algorithm being applied to a video clip
(\l{http://durian.blender.org/}{Sintel from blender.org}).
\image qmlvideofx-video-edgedetection.jpg

This image shows a page curl effect, applied to the same video clip.
\image qmlvideofx-video-pagecurl.jpg

Here we see a 'glow' effect (edge detection plus colour quantization) being
applied to the camera viewfinder.
\image qmlvideofx-camera-glow.jpg

This image shows a 'wobble' effect applied to the viewfinder.
\image qmlvideofx-camera-wobble.jpg

The application includes many more effects than the ones shown here - look
for Effect*.qml files in the list of files below to see the full range.

\section1 Application structure

Shader effects can be applied to video or viewfinder content using
\l{ShaderEffect}, as shown in the following example, which applies
a wiggly effect to the content:

\code
import QtQuick 2.0
import QtMultimedia 5.0

Rectangle {
    width: 300
    height: 300
    color: "black"

    MediaPlayer {
        id: mediaPlayer
        source: "test.mp4"
        playing: true
    }

    VideoOutput {
        id: video
        anchors.fill: parent
        source: mediaPlayer
    }

    ShaderEffect {
        property variant source: ShaderEffectSource { sourceItem: video; hideSource: true }
        property real wiggleAmount: 0.005
        anchors.fill: video

        fragmentShader: "
            varying highp vec2 qt_TexCoord0;
            uniform sampler2D source;
            uniform highp float wiggleAmount;
            void main(void)
            {
                highp vec2 wiggledTexCoord = qt_TexCoord0;
                wiggledTexCoord.s += sin(4.0 * 3.141592653589 * wiggledTexCoord.t) * wiggleAmount;
                gl_FragColor = texture2D(source, wiggledTexCoord.st);
            }
        "
    }
}
\endcode

In this application, the usage of the \l{ShaderEffect} and \l{VideoOutput}
types is a bit more complicated, for the following reasons:

\list
    \li Each effect can be applied to either a \l{VideoOutput} or an
       \l{Image} item, so the type of the source item must be abstracted away
       from the effect implementation
    \li For some effects (such as the edge detection and glow examples shown in
       the screenshots above), the transformation is applied only to pixels to
       the left of a dividing line - this allows the effect to be easily
       compared with the untransformed image on the right
    \li Most effects have one or more parameters which can be modified by the
       user - these are controlled by sliders in the UI which are connected
       to uniform values passed into the GLSL code
\endlist

The abstraction of source item type is achieved by the
\l{video/qmlvideofx/qml/qmlvideofx/Content.qml}{Content}, which uses a
\l{Loader} to create either a \l{MediaPlayer}, \l{Camera} or \l{Image}:

\quotefromfile video/qmlvideofx/qml/qmlvideofx/Content.qml
\skipto import
\printuntil {
\dots
\skipto Loader {
\printuntil }
\dots
\skipto function openImage
\printuntil "ContentImage.qml"
\skipto contentLoader.item.source
\printuntil path
\skipto }
\printuntil }
\skipto function openVideo
\printuntil "ContentVideo.qml"
\skipto contentLoader.item.mediaSource
\printuntil path
\skipto }
\printuntil }
\skipto function openCamera
\printuntil "ContentCamera.qml"
\skipto }
\printuntil }
\skipto /^\}/
\printuntil }

Each effect is implemented as a QML item which is based on the
\l{video/qmlvideofx/qml/qmlvideofx/Effect.qml}{Effect}, which in turn
is based on the \l{ShaderEffect}:

\quotefromfile video/qmlvideofx/qml/qmlvideofx/Effect.qml
\skipto import
\printuntil /^\}/

The interface of Effect allows for derived effects to specify the
number of parameters which they support (and therefore the number of sliders
which should be displayed), and whether a vertical dividing line should be drawn
between transformed and untransformed image regions.  As an example, here is the
implementation of the pixelation effect.  As you can see, the pixelation effect
supports one parameter (which controls the pixelation granularity), and states
that the divider should be displayed.

\quotefromfile video/qmlvideofx/qml/qmlvideofx/EffectPixelate.qml
\skipto import
\printuntil /^\}/

The main.qml file shows a
\l{video/qmlvideofx/qml/qmlvideofx/FileOpen.qml}{FileOpen}, which allows
the user to select the input source and an
\l{video/qmlvideofx/qml/qmlvideofx/EffectSelectionPanel.qml}{EffectSelectionPanel}
item, which lists each of the available shader effects.  As described above, a
\l{video/qmlvideofx/qml/qmlvideofx/Content.qml}{Content} item is used to load the
appropriate input and effect type.  A
\l{video/qmlvideofx/qml/qmlvideofx/Divider.qml}{Divider} item draws the
vertical dividing line, which can be dragged left / right by the user.  Finally,
a \l{video/qmlvideofx/qml/qmlvideofx/ParameterPanel.qml}{ParameterPanel} item
renders the sliders corresponding to each effect parameter.

Here is the effect selection menu:
\image qmlvideofx-effects-menu.jpg

\section1 Calculating and displaying QML painting rate

\input multimedia/doc/src/examples/video-qml-paint-rate.qdocinc

All that remains is to connect the afterRendering() signal of the QQuickView
object to a JavaScript function, which will eventually call frequencyItem.notify():

\quotefromfile video/qmlvideofx/main.cpp
\skipto QGuiApplication
\printuntil ;
\dots
\skipto QQuickItem
\printuntil ;
\dots
\skipto QObject::connect
\printuntil SLOT(qmlFramePainted()));

*/