I. L'article original▲
Le site Qt Labs permet aux développeurs de Qt de présenter les projets, plus ou moins avancés, sur lesquels ils travaillent.
Nokia, Qt, Qt Labs et leurs logos sont des marques déposées de Nokia Corporation en Finlande et/ou dans les autres pays. Les autres marques déposées sont détenues par leurs propriétaires respectifs.
Cet article est la traduction de l'article Pimp my video: shader effects and multimedia de Gareth Stockwell paru dans Qt Labs.
Cet article est une traduction d'un des tutoriels écrits par Nokia Corporation and/or its subsidiary(-ies) inclus dans la documentation de Qt, en anglais. Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia.
II. Introduction▲
Le récent sujet sur l'utilisation des shaders pour ajouter des effets dans les applications Qt Quick a reçu une attention particulière.
Une fois les bases du langage de programmation pour les shaders comprises, leur intégration dans une application est simplifiée grâce à Qt Quick : on aura des effets visuels amusants en peu de lignes de code.
Ce qui n'avait pas encore été dit, c'est que l'application des effets sur du contenu multimédia (une vidéo ou le flux d'une caméra) est aussi facile que de passer d'un élément QML à un autre. Cet article donne un aperçu de que l'on peut obtenir en combinant la programmation des shaders avec QtMultimedia.
La meilleure façon de présenter quelques-uns des effets que vous pouvez obtenir est d'utiliser une démonstration que voici :
Cliquez pour lire la vidéo
La vidéo ci-dessus présente une application Qt Quick 2, tournant sur une machine Linux de bureau. À part quelques morceaux de code C++ (écoute des signaux du graphe de scène afin de calculer le nombre d'images par seconde et la lecture du fichier de shaders), l'application est entièrement écrite en QML.
III. Détails de l'implémentation▲
Comme décrit précédemment, Qt Quick 2 intègre le support des shaders grâce à l'élément QML ShaderEffect. L'utiliser afin d'appliquer un effet sur un contenu vidéo ou un flux provenant de la caméra est aussi simple que d'appliquer ce même effet sur un autre élément QML. Le code ci-dessous montre un effet de vacillement dépendant du temps, appliqué sur le clip vidéo lu d'un fichier.
import
QtQuick 2.0
import
QtMultimedia 5.0
Rectangle
{
width
:
600
height
:
400
MediaPlayer
{
id
:
mediaPlayer
autoplay
:
true
source
:
"test.ogg"
}
VideoOutput
{
id
:
videoOutput
anchors.fill
:
parent
source
:
mediaPlayer
}
ShaderEffect
{
anchors.fill
:
parent
// Propriétés qui seront passées au shader comme variables uniformes
property
real
amplitude
:
0.02
property
real
frequency
:
20
property
real
time
:
0
NumberAnimation
on
time
{
loops
:
Animation.Infinite
from
:
0
to
:
Math.PI *
2
duration
:
600
}
property
variant source
:
ShaderEffectSource
{
sourceItem
:
videoOutput
hideSource
:
true
}
fragmentShader
:
"
uniform highp float amplitude;
uniform highp float frequency;
uniform highp float time
;
uniform sampler2D source
;
uniform lowp float qt_Opacity;
varying highp vec2 qt_TexCoord0;
void main() {
highp vec2 p =
sin
(
time +
frequency *
qt_TexCoord0);
highp vec2 tc =
qt_TexCoord0 +
amplitude *
vec2
(
p.
y,-
p.
x);
gl_FragColor =
qt_Opacity *
texture2D
(
source,
tc);
}
"
}
}
L'application de l'effet sur un flux provenant de la caméra consiste juste à remplacer l'élément Video par un élément Camera.
Dans la démo qmlvideofx, chaque effet est implémenté en tant qu'élément QML qui hérite de ShaderEffect. Ces éléments sont chargés dynamiquement et appliqués au contenu de la vidéo suite à la sélection de l'effet, via le menu, par l'utilisateur. De même, les différentes sources (image, vidéo et caméra) sont représentées par des éléments QML qui peuvent être chargés dynamiquement lorsque nécessaires.
L'ensemble des paramètres supportés par chaque effet (par exemple, la granularité pour l'effet Pixelate ; le radius et la diffraction pour l'effet Magnify) sont exposés dans un ListModel qui est utilisé pour construire les curseurs (sliders) avec lesquels chaque valeur peut être ajustée.
IV. Le code (Qt 5.x)▲
Le code source pour la démo qmlvideofx se trouve dans le dépôt qtmultimedia.
Tant que Qt 5.0 n'est pas finalisé, il faudra le compiler à partir des sources afin de compiler et exécuter la démo. La procédure est expliquée dans le wiki. Les modules Qt requis pour cette démo peuvent être clonés comme suit :
$QTDIR/init-repository --module-subset=qtbase,qtdeclarative,qtjsbackend,qtmultimedia,qtxmlpatterns
V. Le code (Qt 4.x)▲
Bien que Qt Quick 1 n'ait pas de support natif des shaders, on peut utiliser le plugin Qt.labs.shaders, intégré dans Qt 4.7.4 et suivant. Une version de la démo pour Qt 4 est disponible dans le dépôt qtmobility.
En plus de fonctionner sur des plateformes de bureau (testées sous Linux et Windows), la version Qt 4 de cette démonstration fonctionne aussi sur les périphériques mobiles. La vidéo ci-dessous montre un périphérique Symbian (Nokia C-701) exécutant la démo.
Cliquez pour lire la vidéo
Les plus attentifs remarqueront que l'application a une interface légèrement différente de la version de bureau. Grâce à la flexibilité de Qt Quick, il a été possible de la changer avec un simple fichier QML décrivant la mise en page.
De plus, il faut noter que l'application ne fonctionnera pas sur les versions actuelles de la plateforme Symbian. En effet, il faut un décodeur vidéo qui exporte une texture dans le moteur OpenGL ES. Cela est possible avec extension EGL, aidant à la coopération de la pile vidéo et la pile graphique (EGL_NOK_image_endpoint2) et qui sera ajoutée dans une mise à jour de Symbian. Une fois celle-ci disponible, le QtMultimediaKit utilisera automatiquement cette interface (voir QTMOBILITY-1818) et la démonstration pourra fonctionner.
Toutefois, vous pouvez tester dès aujourd'hui l'application sur le Nokia N9, comme présenté ci-dessous.
Cliquez pour lire la vidéo
VI. Plus d'informations▲
Si vous n'étiez pas déjà enthousiasmé par le potentiel des shaders, maintenant, vous devez l'être. Ci-dessous quelques autres exemples de leur utilisation en conjonction avec Qt/QML.
VII. Divers▲
Merci à Thibaut Cuvelier pour son support à la traduction de cet article. Merci à Claude Leloup pour sa relecture orthographique !