Journal Conférence GStreamer 2017 : Oxydation de GStreamer

Posté par  (site web personnel) . Licence CC By‑SA.
36
5
nov.
2017
Ce journal a été promu en dépêche : Conférence GStreamer 2017 : Oxydation de GStreamer.

Sommaire

Rustifiez votre multimédia !

Voici une traduction de la présentation « Oxidising GStreamer — Rust out your multimedia! » qui a eu lieu le 22 octobre 2017 à Prague dans le cadre de la Conférence GStreamer 2017.

Merci à Sebastian Dröge pour cette présentation et pour son autorisation de traduction.

Pour les planches au format PDF, rendez-vous ici.


Résumé

Dans la suite logique de ma présentation de l’année dernière, je vais vous tenir au courant de ce qu’il s’est passé depuis autour de GStreamer pour le développement d’applications et d’extensions en Rust.

C’est maintenant le bon moment pour utiliser Rust dans le cadre de vos développements GStreamer au lieu du C ou du C++ et même à la place de Python ou de C#. Vous bénéficierez ainsi de plus de sûreté, d’une meilleure productivité et pourquoi pas d’un certain plaisir à développer, tout en conservant un haut niveau de performance et un faible surcoût qui ne se rencontrent généralement qu’en utilisant le C ou le C++ et avec en plus la possibilité d’exécuter votre application sur des équipements embarqués.

Alors que l’apprentissage d’un nouveau langage peut sembler superflu et qu’il y a trop de langages de nos jours, je vais vous montrer pourquoi vous devriez vous en préoccuper et pourquoi le langage en question semble être un candidat parfait pour les applications multimédias et pour plein d’autres cas d’utilisation sur environnements embarqués. Je vais vous indiquer comment vous mettre le pied à l’étrier et vous présenter quelques courts exemples de code.

Sebastian Dröge est un développeur de Logiciels Libres et l’un des mainteneurs et développeurs principaux de GStreamer. Il est impliqué dans le projet depuis plus de 10 ans. Il contribue également à plusieurs autres projets tels que Debian, GNOME et WebKit. Après son master en sciences des Systèmes d’Information à l’Université de Paderborn en Allemagne, il commence à travailler en tant qu’entrepreneur autour de GStreamer et des technologies connexes. Sebastian est l’un des fondateurs de Centricular, une société proposant des services de conseil. Depuis son nouveau domicile en Grèce, il travaille à l’amélioration de GStreamer et de l’écosystème du Logiciel Libre en général.

En plus des sujets relatifs au multimédia, Sebastian s’intéresse au traitement numérique du signal, aux langages de programmation, à l’apprentissage automatique, aux protocoles réseau et aux systèmes distribués.

Logo de Rust
Logo de GStreamer

Introduction, Qui ?

Aujourd’hui, nous allons parler de l’oxydation de GStreamer ou comment rustifier votre multimédia. Je suis Sebastian Dröge, je participe au développement de GStreamer depuis 2006 environ. Actuellement, je suis en charge de la préparation des versions. J’ai touché à pratiquement tout dans GStreamer. Je suis aussi l’un des cofondateurs de Centricular. Nous proposons du conseil autour de GStreamer et des Logiciels Libres de cette catégorie. C’est tout ce que j’ai à dire à mon sujet, passons au contenu.

Quoi ?

Je vais vous parler de Rust et de GStreamer. Je suppose que certains d’entre vous ne connaissent pas Rust, je vais donc commencer par une courte introduction. Si vous souhaitez approfondir, rendez-vous sur le site web, la documentation est de très bonne qualité. Je ne vais pas vous expliquer ce qu’est GStreamer, je pense que vous le savez déjà.

J’ai déjà eu l’occasion de vous parler de ce sujet l’année dernière, je vais donc évoquer ce qu’il s’est passé depuis, puis entrer un peu plus dans les détails sur la manière de développer des applications et des extensions GStreamer avec Rust. Je vous montrerai aussi quelques exemples de code. Enfin, je vous parlerai de ce à quoi on peut s’attendre pour l’avenir.

Qu’est-ce que Rust ?

Définition

C’est « un langage de programmation système qui vise à garantir un typage sûr et une gestion sûre de la mémoire ». Les développements ont commencé chez Mozilla. Tout est open source. De nos jours, le langage bénéficie d’une large communauté et une bonne proportion des développeurs n’est plus employée par Mozilla. C’est une communauté assez diversifiée. La conception du langage suit les pratiques du développement open source. Ils utilisent un processus d’appel à commentaires (Request For Comments) pour toutes les modifications du langage. Chaque membre de la communauté peut apporter des éléments à la discussion, c’est très transparent… ça me plaît bien !

Qu’est-ce que ces mots signifient au juste et plus particulièrement « gestion sûre de la mémoire » ? En fait, c’est un peu l’argument de vente de Rust. On sait tous ce qui peut arriver en C, si on dé-référence le mauvais pointeur ou si on dépasse les limites d’un tableau : le truc part à veau-l’eau. Rust empêche cela. Le typage est aussi beaucoup plus sûr qu’en C. Le C apporte un peu de sécurité pour le typage, mais bon… passons !

Selon moi, la caractéristique la plus importante est qu’il s’agit d’un langage de programmation système. Il travaille vraiment près du matériel, il n’y a pas de gros environnement d’exécution. Tout ce que vous écrivez tourne vraiment sur le processeur. Toutes les abstractions que le langage propose sont sans surcoûts, du moins c’est la manière dont ils en font la pub, et je le crois aussi. Mais je dirais que c’est à vous de le vérifier par vous-même.

Une autre caractéristique importante est l’existence d’un système très puissant permettant l’interopérabilité avec des bibliothèques écrites en C. Quel que soit l’existant écrit en C dont vous disposez, vous pouvez l’utiliser depuis votre code écrit en Rust.

De la programmation bas-niveau avec un air de programmation haut-niveau

Si vous regardez le code, cela ressemble parfois à ce que vous écririez en Javascript ou en Python ou avec un autre langage d’orchestration (scripting). Ça peut sembler de plus haut niveau que ce que vous obtiendriez en C++. Néanmoins, on parle bien de programmation bas-niveau : vous conservez le contrôle sur tout si vous le souhaitez. Vous pouvez décider d’où allouer la mémoire — doit-on utiliser le tas ou la pile — de quand allouer, de quand désallouer. Mais l’important c’est que vous n’avez pas à vous en soucier. Vous pouvez le faire… vous pouvez aussi, dans une certaine mesure, l’ignorer. Ça n’implique pas une gestion manuelle de la mémoire, c’est le compilateur qui s’assure que vous n’êtes pas en train de faire quelque chose de stupide.

Comme je l’ai dit, Rust ressemble un peu à Python ou à d’autres langages d’orchestration. L’une de ses caractéristiques importantes est l’inférence de type : vous n’êtes pas obligés de préciser systématiquement le type des variables. Généralement, le compilateur se débrouille tout seul tout en vous garantissant un typage sûr. C’est quelque chose dont le C++ dispose aussi aujourd’hui. Vous avez également d’autres caractéristiques que l’on trouve plutôt dans les langages d’orchestration ou les langages fonctionnels, mais qui sont disponibles pour de la programmation système.

Domaines

Rust est actuellement utilisé pour :

  • Du développement d’applications web. Qui essaierait de développer des applications web en C aujourd’hui ? Personne ? Par contre, vous pouvez en écrire en Rust.
  • On l’utilise aussi pour le développement de jeux, la programmation de serveurs… en gros tous les domaines pour lesquels vous utiliseriez le C++.
  • Des gens écrivent aussi des systèmes d’exploitation en Rust, il y en a actuellement deux ou trois en cours d’écriture.
  • Certains l’utilisent pour des développements vraiment très proches du matériel comme de la programmation de micro-contrôleurs.

Rust couvre tout le spectre des cas d’utilisation pour lesquels vous utiliseriez un langage de programmation système.

Par ailleurs, Rust est désormais utilisé et poussé par des acteurs de l’Industrie. Vous pouvez consulter cette page pour découvrir les sociétés qui déclarent publiquement utiliser Rust. Il y a des noms tels que Dropbox, npm, Atlassian, Coursera, Canonical et bien d’autres.

Rust est ce que le C++ aurait dû être

Selon moi, Rust est ce que le C++ aurait dû être. Bon, un certain nombre d’années se sont écoulées, les gens ont appris de l’histoire. Aujourd’hui, je l’utiliserais pour n’importe quel projet pour lequel j’aurais utilisé le C++ ou même le C auparavant.

Pourquoi Rust ?

De la difficulté d’écrire du code sûr en C et en C++

Il est difficile d’écrire du code sûr en C et en C++. Toute personne pouvant dire qu’elle n’a pas subi d’erreur de segmentation durant l’année écoulée n’a probablement programmé ni en C, ni en C++. Vous pouvez facilement faire quelque chose qui fera planter votre système et permettra à un attaquant de prendre le contrôle de la machine de l’utilisateur, sans même vous rendre compte que ce que vous avez écrit n’est pas sûr.

La gestion des erreurs est plutôt compliquée avec ces deux langages. En C, on s’arrange généralement avec les valeurs de retour, vous pouvez facilement les ignorer et personne ne s’en offusquera ! Ça va juste échouer à l’exécution avec des symptômes bizarres. En C++, vous avez bien les exceptions, qui bénéficient de leur propre lot de problèmes. En général, ça entraîne une certaine verbosité qui finit par masquer ce que le programme fait vraiment et rend la tâche encore plus difficile pour faire en sorte que le code soit sûr.

Laissez le compilateur vous aider à écrire du code correct et rapide

Il y a un inconvénient à cela : le compilateur risque de beaucoup se plaindre ! Il vous dira des choses comme : « non, tu ne peux pas faire ça, ce n’est pas sûr ». Ça va vous prendre plus de temps avant de pouvoir exécuter votre code. Mais une fois qu’il s’exécute, vous savez qu’un gros paquet de problèmes ne vont pas se présenter parce que le compilateur vous aura déjà prévenu : « ici, ici et là, tu ne peux pas faire ça, tu devrais faire ça autrement ». Avec le C ou le C++, en général on fait cela à l’exécution et on sait tous combien il est pénible de déboguer des trucs à l’exécution.

Rust utilise un modèle très puissant de possession et de mutabilité. Il identifie en permanence le possesseur d’une variable et trace si celle-ci est accessible en lecture seule ou en lecture et en écriture. Par défaut, toute variable est accessible en lecture seule. C’est le contraire de ce que font les C et C++. Avec ces langages, vous pouvez préciser qu’une variable est constante, mais par défaut elle est visible en lecture et en écriture. Rien qu’avec cette approche (chaque variable en lecture seule par défaut) le code est déjà plus sûr et il est plus difficile d’introduire des bogues.

Par défaut avec Rust, le code doit respecter les contraintes de sûreté. Ce qui veut dire que si vous ne sortez pas du bac à sable, votre programme ne plantera pas… du moins il ne produira pas d’erreur de segmentation. Vous pouvez toujours introduire des erreurs de logique qui feront que votre programme ne fera pas ce qu’il était censé faire, mais au moins il ne plantera pas.

On bénéficie aussi d’une certaine sécurité pour les fils d’exécution. Vous indiquez si votre type de données est sûr pour le partage entre fils d’exécutions et/ou s’il peut être transféré d’un fil d’exécution à l’autre. Le compilateur se chargera ensuite de vérifier que ces contraintes sont bien respectées.

Comme je le disais dans la section relative aux erreurs, Rust vérifie la bonne prise en compte des erreurs. Vous ne pouvez pas ignorer les erreurs, vous devez les gérer. Mais la mécanique qui permet de le faire est telle que ça en devient sympa. Ça n’a rien à voir avec ce que l’on doit faire en C : « si ceci échoue, nettoie ceci et sors, si ceci échoue, nettoie cela et sors »… Dans le cas de Rust, c’est vraiment pratique à utiliser.

L’issue de secours : unsafe

Il y a une issue de secours : le mot clé unsafe. Dès qu’il introduit une section de code, vous pouvez faire ce que vous voulez dans cette section, comme vous le feriez en C. Vous pouvez dé-référencer des pointeurs, vous pouvez créer des pointeurs à partir de nombres, tout ce qui vous passe par la tête. L’idée principale est que c’est déclaratif. Vous savez alors que vous avez une petite partie de votre code qui n’est pas sûre. Si ensuite votre programme plante, ça viendra de là ! Et si vous voulez relire votre code, vous saurez que ce sera par là qu’il faudra commencer.

Un langage de haut niveau qui n’est pas juste une glorification de l’assembleur

… comme c’est le cas pour le C

Une autre différence notable par rapport au C est que Rust dispose d’une bonne bibliothèque standard. Elle contient tout un tas de structures de données. On sait tous qu’en C, la bibliothèque standard ne comporte aucune structure de données. Chacun développe ses propres listes chaînées, ses propres tableaux associatifs. La bibliothèque standard de Rust fournit des implémentations très efficaces de toutes les structures de données, d’algorithmes, etc.

Avec tous les langages d’orchestration récents, on trouve des petits outils pour récupérer les dépendances. Pour node vous avez npm, pour Python il y a pip. Rust propose la même chose, vous pouvez facilement dire : « je veux telle et telle bibliothèques » et l’outil ira chercher les versions dont vous avez besoin, les compilera et les inclura lors de la construction de votre propre logiciel. Cet outil facilite vraiment l’utilisation des dépendances externes. Ça ne tourne pas au cauchemar comme en C ou en C++ où chaque chose fonctionne à sa manière et où il est très difficile de dépendre de quoi que ce soit. En fin de comptes, ça a poussé pas mal de bibliothèques en C et en C++ à ré-implémenter plein d’algorithmes qui existaient déjà partout ailleurs… mais bon, c’est tellement compliqué de tirer ces dépendances que l’on ré-implémente les fonctions nous-mêmes.

Pourquoi devrait-on s’en préoccuper ?

L’analyse syntaxique de formats de médias

… venant de sources non sûres

Je passerai assez vite sur le sujet, nous sommes déjà tous au courant des problèmes. L’analyse syntaxique (parsing) des formats multimédias n’est pas chose facile, particulièrement en C ou en C++. Par ailleurs, les données en entrée viennent rarement de sources de confiance. Certaines sources peuvent même proposer des médias qui contiennent intentionnellement quelque chose qui peut nuire à votre machine en exploitant des problèmes dans les logiciels que vous utilisez. C’est pour cela que je pense que pour nous, Rust serait un bon langage. Il permet d’éviter beaucoup de problèmes de sécurité courants. Tous les problèmes de sécurité que nous avons rencontrés dans GStreamer les années passées auraient pu être évités en utilisant Rust. Je pense que c’est déjà assez éloquent.

Et donc, l’analyse syntaxique est compliquée en C. Il n’y a pas beaucoup de moyens d’abstraction, alors qu’avec Rust on dispose de tout un tas de possibilités pour représenter des abstractions. Il est même possible d’écrire des grammaires formelles, du moins quelque chose qui ressemble à de la grammaire formelle. Le code correspondant est ensuite généré automatiquement, ce qui rend la compréhension de ce que fait ce code vraiment aisée en comparaison à du code écrit à la main.

La maîtrise des fils d’exécution concurrents est difficile

… surtout en C !

Rust dispose de tout un tas de fonctionnalités pour nous aider lorsque l’on développe dans un environnement à plusieurs fils d’exécution. GStreamer exploite massivement les fils d’exécution concurrents, ça pourrait donc être une bonne idée…

Programmer comme si on était en 2017

Et par-dessus tout, nous programmerions comme si nous étions en 2017 et non dans les années 60 du siècle dernier :

  • Les langages modernes offrent toute une variété de fonctionnalités et d’outils.
  • Nous ne sommes plus obligés de réinventer des ustensiles de base comme GObject.
  • Nous pourrions attirer de nouveaux développeurs. Plus personne n’a vraiment envie d’apprendre le C de nos jours et encore moins des choses comme GObject qui entraîne plein de copié-collés partout. C’est plutôt difficile à prendre en main pour les nouveaux contributeurs.

Cependant, ce n’est pas la panacée

Tout code non trivial comporte des bogues. Mais au moins, une importante classe de bogues peut être évitée.

État, il y a un an

Les bindings GStreamer

L’année dernière, nous disposions d’un ensemble de bindings Rust pour GStreamer. Cet ensemble était écrit à la main et ne s’intégrait pas très bien avec le reste du code Rust. Par ailleurs, il imposait aux utilisateurs d’utiliser des sections avec le mot clé unsafe, ce qui est tout simplement rédhibitoire. Il divergeait aussi vis-à-vis de certains concepts de GStreamer, ce qui le rendait difficile à appréhender et il était incomplet. Pas mal de gens utilisaient ces bindings, mais ce n’était vraiment pas idéal.

Nous avions aussi ce dont je vous parlais la dernière fois : une manière expérimentale d’écrire des extensions GStreamer. Ce projet était également écrit à la main, il était très incomplet et difficile à faire évoluer. Oublions tout cela, nous sommes en 2017 maintenant !

Écrire des applications GStreamer avec Rust

Les nouveaux bindings GStreamer

Comparaison par rapport aux anciens bindings

Les nouveaux bindings Rust pour GStreamer sont en grande partie générés à partir des informations d’introspection de GObject. Malheureusement, certaines choses ne peuvent pas être générées automatiquement. Mais globalement, ça facilite bien l’évolutivité. Ils remplacent complètement les anciens bindings. Ils ne sont pas compatibles au niveau interface de programmation, mais ça ne devrait pas être difficile de modifier un projet basé sur les anciens bindings pour qu’il utilise les nouveaux.

Une évolution importante du point de vue des applications est qu’il n’est plus nécessaire de passer par du code marqué unsafe… Sauf si le développeur le veut bien sûr, ou s’il veut s’intégrer avec X11, qui n’est pas sûr par conception, mais c’est un autre problème !

Les nouveaux bindings couvrent pratiquement tous les composants du cœur de GStreamer ainsi que ceux des autres bibliothèques. Ils s’intègrent bien avec les bibliothèques des infrastructures GLib et GTK, ce qui les rend sympas à utiliser ensemble.

Un style idiomatique rustien (en grande partie)

Les bindings sont écrits dans un style idiomatique rustien. Ils devraient être faciles à prendre en main par des développeurs habitués à Rust. Ils auront l’impression qu’il s’agit d’une vraie interface de programmation Rust. Et à la fois, les concepts des bindings correspondent pratiquement trait pour trait aux concepts de GStreamer. Ce qui signifie que vous, en tant que développeurs GStreamer, aurez seulement à apprendre un nouveau langage. Par contre, tous les concepts de GStreamer, c’est-à-dire comment l’interface de programmation fonctionne, restent les mêmes.

Les objets

Regardons rapidement quelques-uns des points d’entrée des bindings. Dans GStreamer, nous avons tout un tas d’objets : les Elements, les Pads, le Pipeline, l’objet Clock, etc. La manière dont ils sont représentés dans les bindings est telle que vous retrouvez précisément les mêmes objets. Ils disposent d’une sorte de mécanisme semi-automatique et sûr de comptage de références. Vous contrôlez toujours quand le compteur d’une référence est incrémenté, mais le compilateur se charge de vérifier que vous l’incrémentez bien quand c’est nécessaire. Ceci vous permet d’être alertés si vous faites des choses bizarres que vous n’auriez pas voulu faire. Donc, ce n’est pas complètement automatique, mais d’un autre côté, vous ne pouvez pas oublier de dé-référencer quoi que ce soit. Quand un objet n’est plus dans la portée courante, quand il n’est plus nécessaire, il est automatiquement dé-référencé et détruit au moment voulu.

Dans GStreamer, nous utilisons l’héritage. Rust ne gère pas l’héritage : il n’y a pas de classes, ni de vraie notion d’héritage. À la place, on peut utiliser des traits. Cela peut sembler un peu compliqué, un peu bizarre, mais si vous utilisez l’interface Rust, vous allez vous rendre compte qu’elle fonctionne de la même façon que si vous utilisiez, par exemple, les bindings C++ de GStreamer. Ça donne une sensation de quelque chose de naturel.

Comme je l’ai déjà dit, il y a une sorte de sûreté des fils d’exécution (thread safety) et elle est contrôlée à la compilation. Par exemple, on sait tous que les Elements de GStreamer sont censés être thread safe, on peut donc les échanger entre fils d’exécution et on peut les partager entre plusieurs fils d’exécution. Le compilateur n’ira pas se plaindre de tels agissements. En revanche, quelque chose comme GstAdapter n’est pas thread safe. Donc si vous tentez de l’utiliser dans d’autres fils d’exécution, vous allez devoir le migrer, car vous ne pouvez pas en disposer depuis deux fils d’exécution différents. Si vous faites cela, le compilateur vous dira : « non, tu ne peux pas faire ça ». C’est une caractéristique plutôt sympa.

Vous disposez également de toute l’interface standard GObject de GStreamer. Vous retouverez : les propriétés, les signaux, toutes les méthodes… tout ce dont vous avez besoin.

J’aurais dû mentionner ceci auparavant : tout est garanti contre l’utilisation inappropriée de pointeurs NULL. Il n’y a aucun pointeur NULL caché. Vous devez gérer explicitement tout ce qui peut être NULL, vous ne pouvez pas ignorer ce genre de problèmes. Donc dans toute l’interface, lorsque quelque chose renvoie un Element, il y aura bien un Element derrière. Il est impossible qu’il ne soit pas disponible. Ça ne peut pas planter ensuite, vous ne pouvez pas vous retrouver face à un pointeur NULL. Et bien sûr, si l’appel est susceptible d’échouer, vous devez gérer ce cas. Le compilateur ne vous laissera pas utiliser la valeur retournée sans avoir vérifié au préalable qu’elle est bien valide.

Les MiniObjects

Les MiniObjects sont probablement le recoin le plus obscur de GStreamer. Ils sont générés automatiquement dans la plupart des autres bindings, ce qui les rend un peu inhabituels vis-à-vis du langage cible. Avec Rust c’est différent : la plupart des concepts autour des MiniObjects correspondent à ce que l’on fait déjà en Rust. Par exemple, le concept de mutabilité des MiniObjects est tel que vous ne pouvez modifier un MiniObject que s’il n’est utilisé qu’à un seul endroit à un instant donné, sinon vous devez le copier. C’est quelque chose qui trouve un équivalent direct en Rust. Le compilateur vous empêchera de modifier des MiniObjects qui ne sont pas en mode écriture. À titre de comparaison, en C on a pas mal de code qui modifie des MiniObjects alors qu’ils ne sont pas en mode écriture. L’approche de Rust me semble présenter un avantage significatif.

Les types basés sur les MiniObjects paraissent aussi typiquement rustiens. Ils comprennent les Caps, les Structures, même quelque chose comme GstFraction, qui semblait un peu bizarre à l’utilisation en Python par le passé, ressemble vraiment à quelque chose que vous auriez utilisé en Rust.

Qu’est-ce qui manque ?

J’ai dit que la plupart du cœur de GStreamer était déjà disponible. Il manque encore :

  • GstMemory, GstAllocator, GstMeta et GstCapsFeatures. Non pas parce qu’ils présentent une difficulté, mais plutôt parce que je n’en ai pas encore eu l’utilité et apparemment personne n’en a eu besoin pour le moment. Donc, si quelqu’un rencontre un problème pour lequel le besoin se fait sentir, criez, on pourra les ajouter à ce moment-là.
  • Il manque aussi des trucs mineurs comme les TypeFinders. Ils sont du même acabit : faciles à ajouter en cas de besoin.
  • Les objets dans la catégorie des GstControlBindings.
  • A part pour celles du cœur, les bibliothèques des autres modules ne sont pas entièrement couvertes. Mais par exemple, pour la bibliothèque Audio, GstAudioInfo est disponible, pour la bibliothèque Video vous avez déjà VideoInfo et VideoFrame. Il y aussi GstAdapter, AppSrc et AppSink.

Tout ce dont vous avez habituellement besoin est donc disponible et pour le reste, criez et on l’ajoutera !

Est-ce utilisable ? Oui !

Selon moi, tout est déjà très utilisable. Je l’utilise moi-même pour pas mal d’applications de test afin de m’assurer que tout fonctionne correctement ou pour écrire des cas de test quand quelque chose ne marche pas. De part mon expérience, je peux dire que c’est facile et généralement plus rapide à écrire que l’équivalent en C. C’est facile à déboguer, ou du moins aussi facile à déboguer que le C. Vous pouvez toujours utiliser gdb, obtenir la pile d’appels, scruter les variables, etc. Ça marche de la même manière qu’avec du C. Et généralement, ça donne plus ou moins le même code machine que ce que vous obtiendriez avec du C. Si vous lisez ce que le compilateur produit, il est assez facile de savoir ce qui se passe, comment les correspondances avec le C se concrétisent. Donc c’est prêt à être utilisé !

Quelques exemples de code

Création d’Elements

Voici un exemple de création d’Elements. Ça ne devrait pas être trop difficile à lire :

let pipeline = gst::Pipeline::new(None);                // 1

let src = gst::ElementFactory::make("filesrc", None)
  .ok_or(MyError::ElementNotFound("filesrc"))?;         // 2
let dbin = gst::ElementFactory::make("decodebin", None)
  .ok_or(MyError::ElementNotFound("decodebin"))?;
  • En 1, on génère un nouveau Pipeline. Ici, on ne lui donne pas de nom particulier. En C, on passerait NULL, en Rust on indique None. On récupère toujours un Pipeline. Si vous regardez l’interface en C, vous verrez que ça ne renvoie jamais NULL, donc on récupère vraiment un Pipeline.
  • En 2, on veut construire une variable src. On utilise donc gst::ElementFactory::make, ce qui est très similaire à ce que vous feriez en C. L’objectif est de créer une source sur un fichier avec l’extension filesrc. Bien sûr, il peut arriver que l’extension filesrc ne soit pas disponible sur votre machine, cette fonction est donc susceptible d’échouer en renvoyant None. Vous pouvez indiquer comment gérer les différents cas avec la fonction ok_or : « si tout est ok, alors renvoie ce que la fonction gst::ElementFactory::make a généré, sinon renvoie un type d’erreur dédié ». Pour cela, vous pouvez créer une sorte d’énumération d’erreurs et préciser les différents cas tels que ElementNotFound, à quoi vous pouvez ajouter une variable. Dans notre cas, on a indiqué le nom de l’Element. À la fin de la ligne, on trouve un point d’interrogation. Il est là pour indiquer ceci : « en cas d’échec, sors de la fonction et renvoie l’erreur en question ». L’appelant peut donc gérer l’erreur et prendre les mesures appropriées, mais dans la fonction en question on s’arrêtera là en cas d’erreur. Bien sûr, il n’y aura pas de fuite mémoire, tout ce qui doit être dé-référencé et détruit le sera automatiquement.

Création de Caps

Voici maintenant un exemple de création d’un objet Caps :

let caps = gst::Caps::new_simple(                   // 1
    "video/x-raw",                                  // 2
    &[                                              // 3
        ("format", "BGRA"),                         // 4
        ("width", &(1080i32),                       // 5
        ("height", &(720i32)),                      // 6
        ("framerate", &gst::Fraction::new(30, 1)),  // 7
    ],
);
  • En 1, vous utilisez gst::Caps::new_simple exactement comme en C.
  • En 2, vous indiquez le nom, rien de spécial à signaler ici.
  • En 3, vous fournissez un tableau de propriétés qui sont en fait des tuples.
  • En 5, je pense que ce qu’il faut retenir, c’est que vous n’indiquez pas seulement la valeur pour la propriété, vous devez aussi préciser son type. Assez souvent, c’est quelque chose qui tourne mal en C : les gens fournissent un entier non signé ou un entier sur 64bits pour une propriété donnée et ça ne fonctionne pas comme prévu ensuite. Ici, vous devez être explicite. En interne, ça ne va pas créer d’objet GValue, si vous lisez le code généré, il sera très similaire à ce que vous auriez obtenu avec du C.

Question d’un membre du public :

— L’esperluette est nécessaire dans ce cas ?
— En fait, l’esperluette n’est pas indispensable ici. L’esperluette crée une référence, c’est comme un pointeur dont la valeur ne peut pas être NULL.
— Et donc, elle indique si ta constante est statique ou non ?
— En fait… Bon, parlons-en après, cela nécessiterait d’entrer un peu plus dans les détails. En bref, l’esperluette introduit une référence et les références ne peuvent jamais être NULL. Le compilateur s’assure que cette valeur est toujours valide au moment où tu l’utilises. Donc, tu ne peux pas libérer ce qui en dépend, sinon ça ne sera pas accepté à la compilation. Mais, la raison exacte pour laquelle nous avons besoin d’une esperluette ici nécessiterait une explication dans laquelle je ne souhaite pas m’engager maintenant. Ça a un rapport avec le fait que chacun des éléments présente un type différent : en 4 il s’agit d’une chaîne de caractères, en 5 et 6 ce sont des entiers signés, en 7 on trouve une fraction.

NDLT : à ce stade de la présentation, Sebastian commence à être à court de temps. Il décide donc de passer quelques exemples. Vous pouvez les retrouver dans les planches au format PDF.

Le signal pad-added

Le signal pad-added fait partie des choses utilisées fréquemment. Voici un court exemple utilisant ce signal :

let pipeline = _;                                           //  1
decodebin.connect_pad_added(move |dbin, src_pad| {          //  2
    let sink = gst::ElementFactory::make(                   //  3
        "fakesink",                                         //  4
        None                                                //  5
    ).unwrap();                                             //  6
    pipeline.add(&sink);                                    //  7

    let sink_pad = sink.get_static_pad("sink").unwrap();    //  8
    src_pad.link(&sink_pad);                                //  9

    sink.sync_state_with_parent();                          // 10
});
  • En 2, on utilise un decodebin qui a été créé auparavant. On le connecte au signal pad-added en lui passant une fermeture (closure). En C, vous auriez à définir une nouvelle fonction, sa déclaration, tout cette verbosité… Ici, vous pouvez écrire la fonction directement avec la connexion au signal. Tout ce qui est disponible en amont peut être capturé dans la fermeture. Par exemple, le pipeline défini en ligne 1 est utilisé à l’intérieur de la fermeture à la ligne 7. Rust s’assure que tout ce qui est capturé est utilisé en respectant les règles de sûreté. Vous pouvez être amenés à devoir copier les objets pour les utiliser à l’intérieur d’une fermeture parce qu’il peut y avoir des cas pour lesquels l’utilisation du même objet ne serait pas sûre. Mais généralement, c’est très pratique à utiliser et vous pouvez simplement écrire vos gestionnaires de signaux directement sans code superflu. Vous vous demandez peut-être à quoi correspond ce truc avec les | en ligne 2. C’est la façon dont on définit une fermeture : vous retrouvez les arguments decodebin et src_pad qui correspondent à ceux passés lors de l’invocation du signal pad-added.
  • À l’intérieur de la fermeture, on crée un fakesink (lignes 3 à 6),
  • que l’on ajoute au pipeline (ligne 7).
  • On récupère ensuite le pad « sink » (ligne 8), que l’on relie au pad « src » du decodebin (ligne 9).
  • Finalement en 10, on lance la synchronisation.

Toute personne ayant déjà utilisé GStreamer devrait être en mesure de lire cet exemple et de comprendre exactement tout ce qu’il s’y passe.

Réaction d’un membre du public :

— inaudible
— Ce n’est pas ton cas ?
— Est-ce que Rust permet à gst_element_sync_state_with_parent de devenir thread safe ? (rires)
— Bien sûr que non parce que l’implémentation est en C et que cette fonction est défectueuse par conception. Il faut que l’on trouve une meilleure solution à cela. La fermeture que tu passes ici est marquée comme devant respecter des contraintes de sûreté pour l’exécution en environnement à plusieurs fils d’exécution. Donc, tu ne peux pas simplement utiliser une autre référence vers un GstAdapter là-dedans par exemple, parce que GstAdapter ne respecte pas ces contraintes. Tu ne peux rien utiliser qui ne soit pas thread safe dans cette fermeture, à moins de migrer la variable à l’intérieur, ou dis autrement : à moins que l’unique référence restante sur cet objet se trouve à l’intérieur de la fermeture au final.

Mapping de Buffer

En Python le mapping de buffer est un peu étrange. En Rust, on peut le faire de façon assez élégante :

let mut buffer = gst::Buffer::with_size(320 * 240 * 4).unwrap();    // 1
{                                                                   // 2
    let buffer = buffer.get_mut().unwrap();                         // 3
    let mut data = buffer.map_writable().unwrap();                  // 4

    for p in data.as_mut_slice().chunks_mut(4) {                    // 5
        p[0] = b; p[1] = g;                                         // 6
        p[2] = r; p[3] = 0;                                         // 7
    }                                                               // 8
}                                                                   // 9
  • En 1, on crée un nouveau Buffer. On a besoin d’un Buffer mutable pour pouvoir écrire dedans.
  • Ensuite de 2 à 9, on est obligé d’écrire un truc un peu moche. Il s’agit d’un nouveau bloc qui limite la validité des variables qu’il contient. Elles seront libérées à la fin du bloc et le destructeur sera exécuté.
  • En 4, on mappe le Buffer en écriture. À la fin du bloc, la fonction unmap est exécutée automatiquement.
  • On peut aussi mentionner que le Buffer doit être récupéré sous une forme mutable (ligne 3) avant de pouvoir en extraire une map en écriture. Toutes ces fonctions peuvent échouer, c’est pour cela qu’on utilise unwrap. En cas d’échec, cette fonction termine l’application. Bien sûr, il y a des façons plus élégantes de gérer cela. Je ne les ai pas indiquées parce que ça surchargerait la planche. Il faudrait un peu de code pour gérer le cas d’erreur.
  • De 5 à 8, on itère sur la zone mémoire et on renseigne les valeurs des composantes R, G et B. On peut simplement utiliser les itérateurs de Rust pour parcourir le Buffer par tronçons de 4 octets, c’est ce que l’on peut lire en ligne 5.

Une fois compilé, ça ressemble pratiquement à ce que vous auriez obtenu si vous l’aviez écrit en C.

Quelques liens

  • Les bindings sont actuellement sur mon dépôt github. J’ai l’intention de les déplacer vers freedesktop à un moment donné, mais j’aimerais qu’on migre d’abord vers github. Je n’ai pas envie de les déplacer deux fois, donc pour le moment ils restent sur github.
  • Vous pouvez trouver plein d’exemples de code ici.
  • La plupart des tutoriels de GStreamer ont aussi été portés ici. Je n’en ai écrit qu’un, les autres ont été portés par des contributeurs, donc grâce à eux, vous disposez des tutoriels.

Écrire des extensions GStreamer en Rust

Je vais vous parler rapidement de la manière d’écrire des extensions GStreamer en Rust. Comme je l’ai dit plus haut, l’année dernière nous disposions d’une infrastructure écrite à la main. La plupart de l’infrastructure pour les extensions est toujours écrite à la main, mais ce qui est important c’est qu’elle s’appuie désormais sur les nouveaux bindings Rust de GStreamer. Toute l’infrastructure hors sous-classes est générée automatiquement et prise en charge par les bindings. Évidemment, toute l’infrastructure pour les sous-classes, la surcharge des méthodes virtuelles et l’installation des propriétés sont encore écrites à la main.

La différence par rapport à l’année dernière, c’est que vous pouvez maintenant utiliser des méthodes virtuelles et vous pouvez définir des propriétés. Par ailleurs, les gens qui implémentent des Elements ne sont plus obligés d’écrire du code Rust non sûr (déclaré unsafe), ils peuvent le faire, mais ils n’y sont plus contraints.

Le but de tout cela est de pouvoir écrire des extensions GStreamer en implémentant simplement des traits Rust, sans utiliser quoi que ce soit qui ne fasse pas partie du langage, de façon à ce que cela soit très facile pour des gens connaissant Rust d’écrire des extensions GStreamer.

Comme je l’ai dit, une partie du code est encore écrite à la main. Tout cela va être amélioré. Les gens de GNOME travaillent actuellement sur des solutions à base de macros qui font en gros la même chose que les GST_DEFINE_…s, mais d’une manière plus sympa. À l’avenir vous pourrez écrire du code qui ressemblera à du Vala ou du C#, et les macros convertiront cela en quelque chose de similaire à ce que j’ai écrit à la main. Ceci dit, c’est pour plus tard, cela va prendre un peu de temps avant d’en arriver là.

Classes de base disponibles

Actuellement, des classes de base sont disponibles pour :

  • Les Elements.
  • BaseSrc, BasSink et BaseTransform.
  • Thibault, qui est peut-être parmi nous, travaille actuellement sur le binding VideoDecoder et il a aussi l’intention d’écrire un décodeur d’images GIF.
  • Il y a une chose que je voudrais souligner ici. Chaque fois que vous faites quelque chose que vous n’êtes pas autorisé à faire, par exemple ce que je faisais tout à l’heure avec unwrap (la création d’un Element pouvant échouer, car il peut ne pas être disponible), et donc si vous utilisez unwrap, en cas d’erreur, Rust va paniquer. Ce que l’on entend par là, c’est que la pile va être déroulée et…

NDLT : l’organisation informe Sabastian qu’il ne lui reste plus beaucoup de temps.

Elements disponibles

Nous disposons des Elements suivants :

  • Démultiplexeur FLV.
  • Source HTTP.
  • Source et « dissipateur » (sink) depuis / vers un fichier.
  • Source et « dissipateur » (sink) depuis / vers Amazon S3.
  • Il y a quelques jours, j’ai ré-écrit en Rust l’Element AudioEcho qui existait déjà en C.
  • Et bientôt, si tout va bien, on aura aussi un décodeur d’images GIF (animées).

Une anecdote intéressante : lorsque j’ai écrit l’Element AudioEcho en Rust, il était environ 1,7 fois plus rapide que l’implémentation en C. Ce n’est pas parce que Rust est plus rapide mais plutôt parce qu’il était plus difficile de faire en sorte que l’équivalent en C soit rapide. J’ai trouvé l’expérience intéressante. Ce n’était pas exactement l’objectif initial lorsque j’ai entrepris la ré-écriture de cet Element, mais ça montre bien que l’on n’a pas affaire à un langage de haut niveau qui ralentirait les choses, c’est vraiment un langage que l’on peut utiliser pour ce genre de développements.

État actuel

  • Les bindings sont encore assez jeunes.
  • Ils sont utilisables pour une implémentation nécessitant les classes de base que je mentionnais plus haut.
  • Les fonctionnalités manquantes seront ajoutées le moment venu.

Si vous voulez écrire des extensions GStreamer en Rust maintenant, lancez-vous, dites-moi s’il manque des choses et je les ajouterai ou je vous aiderai à les ajouter. Jusqu’à présent, j’ai pris beaucoup de plaisir à écrire des extensions GStreamer en Rust, j’ai beaucoup plus apprécié cela que d’en écrire en C. Donc, essayez et voyez si c’est le cas pour vous aussi !

NDLT : Sebastian passe les exemples de code par manque de temps. Vous pouvez les retrouver dans les planches au format PDF.

Quelques liens

Si vous voulez voir à quoi cela ressemble, c’est sur mon dépôt github. Les extensions sont également dans le dépôt.

À venir…

Encore quelques mots à propos de l’avenir : mon objectif est que l’on écrive de plus en plus de code en Rust plutôt qu’en C. Commençons d’abord par les extensions externes. Plus tard, on pourra aussi envisager de remplacer le code du cœur. Mais ça, c’est pour l’avenir. Il n’y a pas de raison de se faire du souci pour le moment. Nous pouvons faire tout cela de façon itérative en remplaçant des petites portions de code grâce au système FFI de Rust qui rend les choses vraiment faciles pour s’intégrer dans du code C existant. Vous pouvez remplacer un simple module ou même une simple fonction si vous le souhaitez.

Globalement, je voudrais faire en sorte que les bindings soient mieux finis. Que l’infrastructure pour écrire des extensions soit mieux finie aussi, plus complète, mais bon, je suppose que c’est assez évident.

Et le plus important, c’est que j’aimerais faire en sorte que plus de personnes s’intéressent et s’impliquent dans l’utilisation de Rust, ce qui était le but principal de cette présentation. J’espère avoir atteint mon objectif. Jetez-y un œil, essayez-le, j’espère que vous ne le regretterez pas. Moi je ne le regrette pas ! Plus généralement, je dirais : n’écrivez plus de projets en C, c’est une mauvaise idée. Regardez tous les CVE des projets à base de C… ce n’est pas une bonne idée !

Merci / Questions ?

On n’a plus le temps pour des questions, donc passez me voir après. Voici encore quelques liens. Il y a pas mal d’informations sur le site web de Rust, la documentation est de très bonne qualité, vous y trouverez probablement toutes les réponses aux questions que vous vous posez.

Merci !

  • # Rust vs. unsafe Rust

    Posté par  (site web personnel) . Évalué à 10.

    Il y a une issue de secours : le mot clé unsafe. […] Vous savez alors que vous avez une petite partie de votre code qui n’est pas sûre. Si ensuite votre programme plante, ça viendra de là !

    Bien que fervent soutien de Rust (et même actuellement membre de RustBelt), je me permets de réagir à cette remarque. Je souhaiterais faire remarquer que ceci est une croyance assez répandue, mais complètement foireuse.

    La programmation à coup d'unsafe en Rust a des répercussions non-locales qui sont dues au fait que la sémantique d'une structure de donnée est décrite par son API, qui constitue un tout, et non pas par chaque fonction une par une. En gros, ça veut dire que la validité d'un code unsafe dépend de l'ensemble des interfaces transparentes qui en dépendent, ce qui peut être nettement plus vaste que le code dans un bloc unsafe. Il y a un très bon post de blog par Ralf Jung à ce sujet pour les gens intéressés.

    • [^] # Re: Rust vs. unsafe Rust

      Posté par  (site web personnel) . Évalué à 2.

      Merci pour les liens. Je ne connaissais pas RustBelt, l'approche semble très intéressante.

      J'ai prévu de rédiger un résumé des commentaires à l'attention de Sebastian, bien sûr ta remarque en fera partie.

    • [^] # Re: Rust vs. unsafe Rust

      Posté par  (site web personnel) . Évalué à 6.

      Voici la réponse Sebastian dont je vous propose une traduction à la suite.

      I completely agree with you, but you have to make some simplifications. I could do a whole presentation about the topic you're speaking of.

      The audience however is full of C developers, and everybody who ever wrote some C knows that a memory unsafety in one place could show up somewhere completely different. Nonetheless, it is caused by a single "unsafe block" in the end.

      Similarly, if your safe abstractions in Rust around unsafe code are leaky and broken, something completely different can explode later. But the bug itself is going to be in an unsafe block.

      So, IMHO what I said is right (minus compiler/language bugs), just a big simplification that everybody who ever wrote code in a memory unsafe language should understand.

      Je suis complètement d'accord avec toi, mais il est parfois nécessaire de passer par des simplifications. Je pourrais faire toute une présentation sur le sujet que tu évoques.

      Le public [de la conférence GStreamer] est constitué de plein de développeurs C et tous ceux qui ont écrit du code C savent qu'une utilisation non sûre de la mémoire à un endroit donné peut ré-apparaître à un endroit totalement différent. Néanmoins, en fin de compte, le problème est bien provoqué par un bloc non sûr donné.

      De la même façon, en Rust, si tes abstractions sûres basées sur du code non sûr fuient ou sont boguées, quelque chose de complètement différent risque d'exploser plus tard. Mais, le bug en lui-même se trouvera dans un bloc non sûr.

      Donc selon moi, ce que j'ai dit est exact (mis à parts les bugs du compilateur ou du langage), c'est une grosse simplification que tous ceux qui écrivent du code dans un langage à gestion de la mémoire non sûre devraient comprendre.

      • [^] # Re: Rust vs. unsafe Rust

        Posté par  . Évalué à 1.

        Donc en résumé : ça peut casser partout dans ton code, mais le bug viendra de la partie "unsafe" (modulo les bugs dans le langage ou compilateur).

  • # Une ode à Rust sur un sujet assez pointu

    Posté par  . Évalué à 5.

    Je trouve ton article intéressant. Tu expliques comment on arrive à Rust et quels sont certains de ses avantages par rapport à C, et bien que d'autres articles existent sur le sujet tu l'appliques sur ton sujet de prédilection : GStreamer. Et c'est un peu là que j'ai du mal.

    GStreamer est un code conséquent, les références que tu fais sont parfois floues et le code que tu montres ne m'a pas permis de comprendre intuitivement ce que tu faisais. Et ce n'est pas vraiment un reproche que je ferai à ton article, tu n'as sans doute pas le temps de présenter tous les concepts derrière GStreamer en détail. De ce fait, dès qu'on rentre dans "Écrire des applications GStreamer avec Rust" il devient difficile de suivre sans ouvrir une dizaine d'onglets… ça me rebute un peu. Du coup, je ne sais pas si l'article est trop grand ou pas assez.

    En tout cas merci, tu donnes de la visibilité à Rust et à GStreamer. Si en tant que développeur d'outils assez poussés et gourmands en ressources tu considères ce langage, cela lui donne encore plus de crédibilité.

    • [^] # Re: Une ode à Rust sur un sujet assez pointu

      Posté par  (site web personnel) . Évalué à 2.

      En effet, c'est le risque avec la traduction d'une présentation destinée à une conférence spécialisée. Ton commentaire me suggère une dépêche sur le développement avec GStreamer du coup. Je n'en suis pas un spécialiste, donc une rédaction à plusieurs mains pourrait être vraiment adaptée.

      Ta conclusion est précisément ce qui m'a donné envie de partager cette présentation avec vous. Merci pour Sebastian.

  • # VLC

    Posté par  . Évalué à 6.

    À noter que Rust est déjà utilisé dans VLC (http://dev.unhandledexpression.com/slides/rustconf-2016/vlc/).

    « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

    • [^] # Re: VLC

      Posté par  (site web personnel) . Évalué à 2.

      Commentaire de Sebastian, puis traduction:

      They're "using" it as much as GStreamer so far, AFAIU. It's not part of the main codebase yet, unless something has changed.

      But yes, VLC and ffmpeg people are also looking into Rust, which is great, also for GStreamer :) One of the VLC people for example wrote a FLV demuxer, around which I wrote a GStreamer plugin in Rust (also he wrote nom, which is generally useful). Or in the case of ffmpeg it would directly give the advantages to GStreamer without any work being needed on the GStreamer side (via the ffmpeg GStreamer plugin).

      À ma connaissance, ils l'« utilisent » autant que GStreamer pour le moment. Ça ne fait pas encore partie du tronc principal du projet, à moins que quelque chose ait changé.

      Mais en effet, les gens de VLC et de ffmpeg regardent aussi du côté de Rust, ce qui est super et ce, aussi pour GStreamer :) Par exemple, l'un des membres du projet VLC a écrit un démultiplexeur FLV autour duquel j'ai écrit une extension GStreamer en Rust (il a également écrit mom, qui est utile plus globalement). En ce qui concerne ffmpeg, cela profitera directement à GStreamer sans nécessiter de travail supplémentaire (grâce à l'extension ffmpeg de GStreamer).

      • [^] # Re: VLC

        Posté par  . Évalué à 5.

        Merci d'avoir transmis ces réponses.

        « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

  • # dans la durée

    Posté par  . Évalué à 5.

    Pourquoi la communauté Rust pense que leur langage doit s'affranchir d'applications conséquentes et d'évaluations dans le temps afin de démontrer sa supériorité effective?

    Le lien avec les CVEs en C est juste inapproprié, pas la même base de code vivante, pas la même longévité et pas le même nombre d'yeux qui ont effectué toutes ces relectures de codes, d'audit etc…

    Perso, je me fiche de savoir lequel est mieux, je trouve juste l'approche étrange et symptomatique de ce seul langage.

    • [^] # Re: dans la durée

      Posté par  (site web personnel) . Évalué à 6.

      Je ne vais pas m'exprimer au nom de la communauté, mais il m'a semblé lire assez souvent que Rust permettait d'éviter un certain nombre de failles de sécurité sans toutefois garantir un logiciel infaillible. Je pense que l'avantage du langage sur ce sujet réside principalement dans les contraintes imposées au développeur dès la compilation. Ces contraintes imposent des pratiques éprouvées pour permettre d'éviter un grand nombre de failles de sécurité. Je trouve que c'est quelque chose que Sebastian détaille vraiment bien dans les premières sections de la présentation. Voir aussi l'échange avec Renault dans mon précédent journal.

      Selon moi, Sebastian mentionne les CVE en C à la fin de l'article (le lien renvoie vers l'article Wikipedia, et non vers une liste de CVE lâchées en patûre ;-)) en écho à sa remarque en tant que développeur et mainteneur de GStreamer :

      Tous les problèmes de sécurité que nous avons rencontrés dans GStreamer les années passées auraient pu être évités en utilisant Rust.

      Rust doit faire ses preuves, comme les autres. Il est particulièrement prometteur et on sait déjà qu'il permet de faciliter la vie des développeurs.

    • [^] # Re: dans la durée

      Posté par  (site web personnel) . Évalué à 6.

      Comme pour les autres commentaires ci-dessus, voici la réponse de Sebastian, puis une traduction :

      All the security issues in GStreamer in the past year (and hundreds of other bugs) would've been impossible with Rust. Or D, Go, Haskell, JavaScript, …, just that those languages have other disadvantages that make them not suitable for GStreamer (except for application development).

      Tous les problèmes de sécurité qui sont apparus l'année dernière dans GStreamer (ainsi que des centaines d'autres bogues) auraient été impossibles avec Rust. Ça aurait également été le cas en utilisant D, Go, Haskell, JavaScript, … à la différence que ces langages comportent d'autres inconvénients qui ne les rendent pas appropriés pour GStreamer (à part pour le développement d'applications).

    • [^] # Re: dans la durée

      Posté par  . Évalué à 3.

      pas la même longévité et pas le même nombre d'yeux qui ont effectué toutes ces relectures de codes, d'audit etc…

      Y'a eu des relectures de code et des audits ? Vraiment ?

      "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

  • # Commentaire supprimé

    Posté par  . Évalué à 6.

    Ce commentaire a été supprimé par l’équipe de modération.

    • [^] # Re: Super dépêche

      Posté par  (site web personnel) . Évalué à 4.

      Merci yPhil et merci aussi pour l'explication et les exemples parlants ! J'ai hésité, mais d'ailleurs je préfère, et je dis « qu'est-ce qui manque » dans la vraie vie.

      • [^] # Re: Super dépêche

        Posté par  (site web personnel) . Évalué à 3.

        Corrigé, merci.

        • [^] # Commentaire supprimé

          Posté par  . Évalué à 3. Dernière modification le 08 novembre 2017 à 07:27.

          Ce commentaire a été supprimé par l’équipe de modération.

          • [^] # Re: Super dépêche

            Posté par  (site web personnel) . Évalué à 7.

            Corrigé, merci.

            La question de la conversion journal -> dépêche est sur la table depuis un moment, non tranchée. On ne « déplace » un journal, on en envoie une copie en rédaction, le contenu y est souvent modifié, parfois enrichi (notamment d'un résumé des discussions déjà présentes sur le journal), il est potentiellement aussi modifié en modération et ensuite publié. On aurait donc des commentaires commentant la version du texte du journal, qui serait mélangé à des commentaires concernant la nouvelle version, plus ou moins entrelacés. Il y a aussi les questions de l'auteur (le texte peut devenir Collectif dans la dépêche, contrairement au journal), du karma gagné sur une dépêche et pas sur le journal, de la double notation (une fois sur le journal, une fois sur la dépêche), de la durée d'exposition d'un journal/d'une dépêche, du relais des dépêches sur d'autres médias (courriel, réseaux sociaux, etc.), de la différence de nature des commentaires due à la différence de public sur les journaux et les dépêches. Etc. La suite de la discussion dans l'entrée de suivi correspondante, où je vais d'ailleurs recopier ce commentaire.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.