Archives de la catégorie ‘MPlayer’

h1

Autour de la compilation d’Enna

2009.12.17

Hello,

je tiens juste à donner quelques précisions pour les personnes qui désirent compiler Enna, et donc également les bibliothèques rattachées. Cet article n’est pas un tutoriel. Si vous ne savez pas comment vous y prendre, il vaut mieux rechercher l’information ailleurs.

Faites aussi un tour à ces adresses (en anglais / in english) :

http://enna.geexbox.org/developers.html


http://captainigloo.wordpress.com/2009/12/21/enna-compilation-on-ubuntu-3/

Evas

Comme vous le savez, Enna se base sur les EFL. Je vous conseil fortement d’utiliser les snapshots ne serait-ce au moins pour ne pas que vous reportiez des "bugs" juste parce que les APIs des EFL auraient trop évoluées. En partant du principe que vous savez compiler les EFL, je vous rappel de ne pas oublier le flag ––enable–gl–x11 avec Evas, si vous avez l’accélération 3D avec votre PC. Les performances graphiques d’Enna sont nettement meilleurs. Toujours concernant Evas, il y a une petite modification dans les sources qui vous permettra d’avoir des textures anti-aliasées. Dans le cas contraire, Enna est plus beau (mais plus lent) en X11 Software plutôt qu’en OpenGL. Il faut tout simplement modifier les définitions GL_NEAREST en GL_LINEAR dans toutes les sources.

cd ~/e17_src/evas
sed -i "s/GL_NEAREST/GL_LINEAR/g" \
    `grep -Rl GL_NEAREST . | grep "\.c$"`

Libgeexbox

Libgeexbox est une manière naïve de parler de toutes les bibliothèques que nous développons en parallèle à la distribution et à Enna. Depuis quelques temps, des releases sont apparues pour libnfo, libplayer et libvalhalla. Il faut savoir que se sont les toutes premières releases! Là où je veux en venir c’est qu’il était totalement justifié de toujours se baser sur les versions de développement pour compiler Enna. Par exemple le premier import de libplayer date de 2006 et c’était une habitude que de faire un hg pull -u régulièrement. Mais maintenant que les versions 1.0.0 sont disponibles, veuillez s.v.p. vous baser uniquement sur celles-ci (ou sur n’importe quelles nouvelles releases de ces libs dans le futur).

Il y a deux solutions, en passant sur les sites web respectifs des projets (les liens sont disponibles à droite des articles de ce blog) ou alors avec Mercurial. Mais dans ce cas veuillez préciser la version de la dernière release. Tel que par exemple:

hg clone -r v1.0.0 http://hg.geexbox.org/libvalhalla

Si vous chargez la devel (donc le "tip") vous ne pourrez pas compiler Enna ou alors vous avez de la chance :-). Depuis qu’il y a les releases je me permets de casser les APIs des bibliothèques parce que je suis un éternel insatisfait (je rigole…) et ça faisait longtemps que je voulais faire un peu de ménage dans certaines en-têtes publiques.

Et après l’installation des libgeexbox, n’oubliez pas de faire un `sudo ldconfig`. Question que le chargeur de programme ait les nouvelles bibliothèques de référencées.

libvalhalla

Quand vous exécutez le configure de libvalhalla, jetez un œil aux informations retournées avant de faire bêtement un `make`. Le configure désactive les éléments en fonction des bibliothèques qu’il ne trouve pas. Par exemple, si vous n’avez pas la libcurl-dev, le support des grabbers est complètement désactivé mais cela n’empêche pas la compilation.

Admettons que vous avez toutes les libs nécessaires et que vous voyez certains grabbers de désactivés. Je pense par exemple à lyricsfly. Ce n’est pas un bug. Lyricsfly n’est pas utilisable car la clef de l’API pour le webservice était provisoire. Ce grabber est donc désactivé par défaut. Si vous utilisez ––enable–grabbers pour être sûr d’activer tous les grabbers vous n’aurez rien à gagner. Vous ferez perdre du temps à libvalhalla sur lyricsfly qui ne retournera jamais rien (je parle de lyricsfly, mais ça peut être d’autres à l’avenir).

A noter également que dès que vous forcez les grabbers ou seulement quelques grabbers, leurs dépendances deviennent obligatoires. Par exemple si vous faites ––enable–grabber–ffmpeg vous forcez la dépendance sur libavcodec. Si vous avez vraiment libavcodec et que ça échoue, c’est simplement que votre version est trop ancienne. Par exemple, le libavcodec que vous trouvez avec Ubuntu Karmic ne supporte pas la fonction av_lockmgr_register() qui garanti l’utilisation des codecs à être multi-thread safe.

libplayer

Concernant libplayer, c’est la dépendance indirecte avec MPlayer qui est la plus importante. Assurez-vous que votre MPlayer est en anglais uniquement. Libplayer peut détecter les MPlayer incompatibles jusqu’à un certain point. En fonction de la manière dont MPlayer a été compilé, libplayer ne peut pas savoir s’il est en anglais ou non et va donc l’utiliser (pour les curieux, je parle de la variable d’environnement LINGUAS à la compilation d’MPlayer; libplayer ne détecte la langue que si celle-ci est passée avec ––language–msg= ou ––language=).

Démarrer Enna

Contrairement à certains tutoriels sur Enna, il n’est pas nécessaire de copier le fichier d’exemple enna.cfg qui se trouve à la racine des sources, dans le dossier ~/.enna. Parce que ce fichier est automatiquement créé au premier démarrage de l’interface. Et allez jeter un œil au contenu. Si vous voulez que libvalhalla puisse faire son travail, vaut mieux lui dire où il doit scanner. Dans le cas contraire 100% des fichiers seront traités en ondemand (je vous laisser chercher dans ce blog si vous ne comprenez pas).

Et maintenant que vous avez l’OpenGL, vous remarquerez assez vite qu’en le spécifiant dans ~/.enna/enna.cfg ça ne change pas grand chose. Pire que cela, ça ne change absolument rien ;-).

Pour l’instant il faudra le faire à la main depuis un terminal, avec:

ELM_ENGINE=gl enna

A bientôt,

Mathieu SCHROETER

h1

Un bug particulier avec Enna/libplayer

2009.07.17

Hello,

comme je l’ai plus d’une fois expliqué, la vidéo sous Enna passe par libplayer. Et depuis quelque temps, Ben et Nico m’ont à nouveau sensibilisé sur un problème d’aspect avec les vidéos.
Le plus simple des aspects correspond à une stupide fraction:

\textbf{aspect}=\frac{\textbf{largeur}}{\textbf{hauteur}}

Mais celle-ci n’est pas toujours vraie, ainsi l’aspect peut être directement enregistré en tant que propriété dans le fichier vidéo. Un exemple courant étant les films DVD. La définition de l’image est de 720×576 (PAL) néanmoins l’aspect peut être du 4:3, 16:9 ou du cinémascope 2.39:1. Pourtant l’image est toujours enregistrée afin d’utiliser un maximum de surface et donc les pixels ne sont pas carrés. Considérer le pixel carré est le dernier recours au cas où la vidéo ne donnerait aucune information sur son aspect.

Le bug…

EnnaLe problème rencontré part Ben et Nico n’était pas reproductible chez moi. Et étant principalement responsable de libplayer depuis toutes les modifications que j’ai apporté, et donc connaissant de fond en comble sa structure et son fonctionnement actuel, il est forcément de mon devoir que de corriger les problèmes connus.
Quand ils utilisaient libplayer avec Enna, ils avaient certaines vidéos qui s’affichaient avec un aspect de 1.00. Ce qui engendre donc une image parfaitement carrée. S’ils testaient cette même vidéo avec le logiciel test-player qui utilise libplayer, l’aspect était correcte. Là où ça devenait encore plus étrange, c’est quand j’ai testé la même vidéo que Nico et j’avais un aspect correct aussi bien sous Enna que sous test-player. Je ne savais donc pas comment reproduire le bug, même que j’avais de plus en plus de doute sur l’existence de ce bug. Non pas que je n’ai pas confiance en leurs manipulations (surtout qu’ils sont deux à être victime de ce problème) mais plutôt que je fais toujours une grande quantité de testes lorsque j’ajoute ou modifie des fonctionnalités dans la bibliothèque. Les problèmes d’aspect je les ai particulièrement travaillé quand j’ai rajouté le support de la navigation DVD pour les wrappers MPlayer et xine. Car il y a des conversions de coordonnées à effectuer pour que la souris agissent au bon endroit sur la surface de l’image et cela en tenant compte de l’aspect et des offsets en x et y.

Nico m’a alors transmis les logs Enna lorsque le problème survient et j’ai pu identifier le problème indirectement. libplayer écrit dans ses logs certaines informations sur les modifications qu’il effectue sur la fenêtre vidéo. Il apparait que la ligne qui indique l’aspect de l’image utilisait une virgule pour séparer les décimales. Sur mon ordinateur cette même ligne ne s’écrit pas avec une virgule, mais avec un point.

Un problème de LOCALE

libplayer utilise abondamment la fonction atof() pour la conversion des valeurs réelles transmissent par MPlayer. Une de ces valeurs est l’aspect. MPlayer retourne la valeur dans un champ ID_VIDEO_ASPECT=1.85 par exemple. Et ce champ a toujours un point comme délimiteur dans le cas d’un MPlayer utilisé avec libplayer (MPlayer doit toujours être en anglais). Là où ça devient un problème c’est le comportement de la fonction atof(). En fonction de la LOCALE du système, elle considère que le délimiteur est une virgule et non un point. De ce fait, (et surtout parce que la fonction atof() ne peut pas échouer) l’aspect lu n’était pas 1.85, mais 1. atof() ignorait tous les caractères depuis le point.

Bien qu’étant de langue francophone, en Suisse-Romande nous n’avons pas du tout la même LOCALE que la France. Notre clavier est également différent (disposition QWERTZ). Nous utilisons le point comme séparateur de décimale et non la virgule et la LOCALE est "fr_CH". En France, la LOCALE est "fr_FR" et le séparateur de décimale est une virgule. Ceci explique pourquoi je ne pouvais pas reproduire l’erreur. Qui pense aux LOCALEs quand il y a un bug sur l’aspect des vidéos? Et bien je tâcherais d’y penser à partir de maintenant.
Quoi qu’il en soit, de nombreux français devaient avoir des problème, mais je n’ai pas eu d’autres retours que les autres développeurs. Je suppose que les éventuels utilisateurs d’Enna se sont dit qu’étant donné qu’aucune version stable existe, ça finirait par être fixé pour la finale? Sachez qu’il y a un site où vous pouvez rapporter les problèmes: enna.geexbox.org, vérifiez si le bug est déjà listé et dans le cas contraire n’hésitez pas à vous inscrire et à soumettre un rapport de bug.

Correction

Pour y remédier il suffit donc de changer de LOCALE avec libplayer. Mais il n’y a pas de raison apparente de changer la LOCALE pour toute la bibliothèque. Ainsi il suffit de réécrire une fonction atof() qui s’exécute dans une autre LOCALE. En principe un programme utilise la LOCALE "C". Qui est celle par défaut. Enna étant internationalisé, la LOCALE change selon la langue. Ceci explique donc pourquoi le bug apparaissait sous Enna mais pas sous test-player.

En principe, la LOCALE se change avec la fonction setlocale(). Mais avant de dire youpie il faut garder à l’esprit que libplayer utilise abondamment les threads. Lorsque la fonction atof() est appelée, Enna peut être en train de faire autre chose. Et cet autre chose peut très bien être influencé par la LOCALE en cours. Le fait d’utiliser la fonction setlocale() modifie la LOCALE pour tout le processus.
Il est donc nécessaire d’avoir recours à une fonction qui ne modifie la LOCALE que sur le thread où atof() est exécuté. Cette fonction s’appelle uselocale(), le nouveau atof() se présente donc ainsi (patch libplayer):

#define _GNU_SOURCE
#include <locale.h>
#include <stdlib.h>

double
my_atof (const char *nptr)
{
  double res;
  locale_t new_locale, prev_locale;

  new_locale = newlocale (LC_NUMERIC_MASK, "C", NULL);
  prev_locale = uselocale (new_locale);
  res = atof (nptr);
  uselocale (prev_locale);
  freelocale (new_locale);

  return res;
}

Afin de simplifier la fonction et d’éviter atof() qui a une réputation d’obsolescence je l’ai remplacé par strtod_l(). Du même coup il est possible d’éliminer uselocale() et donc de ne plus changer la LOCALE du thread.

#define _GNU_SOURCE
#include <locale.h>
#include <stdlib.h>

double
my_atof (const char *nptr)
{
  double res;
  locale_t new_locale;

  new_locale = newlocale (LC_NUMERIC_MASK, "C", NULL);
  res = strtod_l (nptr, NULL, new_locale);
  freelocale (new_locale);

  return res;
}

On notera que strtod() peut retourner HUGE_VAL contrairement à atof().

A bientôt,

Mathieu SCHROETER

h1

Enna/libplayer – Problèmes typiques

2009.01.20

Hello,

je reçois de temps en temps des emails de personnes qui ont des problèmes avec Enna. Comme par exemple le fait qu’ils ont des avertissements qui s’affichent tel que [mplayer] Warn: [hack] slave command ‘stop’, les snapshots des vidéos qui ne sont pas créés ou alors d’autres choses. Cette article a donc pour but de donner quelques précisions sur le fonctionnement général de Enna/libplayer et pourquoi certains messages apparaissent et comment utiliser libplayer correctement.

Les "backends"

Enna est une interface graphique et donc le décodage et la sortie audio/video sont confiés à un backend. Il existe actuellement deux backends dont l’un est lié aux EFLs en utilisant Emotion (donc GStreamer) et le second backend étant bien entendu libplayer. Une question légitime peut être de se demander pourquoi ne pas utiliser uniquement Emotion? L’avantage principale est son intégration avec les EFLs, il est donc facile de manipuler la fenêtre vidéo, de lui appliquer des effets, etc,.. Mais cette solution à aussi un désavantage, Evas étant un "canvas RGB" le sortie vidéo ne peut plus être accélérée à l’aide de Xv, XvMC, VIDIX (en VESA) et bientôt VDPAU (par exemple). Ainsi d’un point de vue performance c’est un désavantage et c’est là qu’intervient libplayer.
Je ne vais pas y revenir en détail, un article précédent explique déjà comment libplayer affiche la vidéo à travers Enna.

libplayer/MPlayer

Le titre de cet article aurait plutôt dû s’appeler "Enna/libplayer/MPlayer" mais vous conviendrez que c’est pas très esthétique. Le wrapper de MPlayer étant le plus avancé dans libplayer la raison est suffisante pour ne pas aborder les autres possibilités de libplayer tel que xine, VLC et GStreamer (en tout cas pour l’instant).

Ainsi lorsque vous utilisez Enna/libplayer vous avez besoin de MPlayer. Dans le cas contraire vous aurez droit à un joli message d’erreur en rouge vous avertissant que MPlayer est manquant, ou que vous n’avez pas compilé libplayer avec le support de MPlayer.

Les problèmes typiques

problem_solved

Problème I.

Vous avez tout compilé et installé mais lorsque vous exécutez Enna un message d’erreur apparait:

[player] Error: no wrapper registered

Le wrapper MPlayer n’a pas été compilé dans libplayer. La raison principale est que vous avez effectué un simple `./configure` en compilant libplayer. Vous n’avez pas prêté attention aux informations retournées par le script configure qui a choisi de ne pas compiler le wrapper MPlayer. Le script ignore ce wrapper s’il ne trouve pas le binaire ‘mplayer’ sur votre système. Il est possible de forcer le wrapper avec `./configure --enable-mplayer` ou alors en installant MPlayer avant de compiler libplayer.

Problème II.

Vous êtes sûr d’avoir compilé et installé libplayer correctement mais lorsque vous exécutez Enna et tentez de lire un fichier audio/video rien ne se passe. Dans les messages vous pouvez voir:

[Enna] [module.c:nnn] Warn: Unable to load module libplayer

C’est un problème classique qui arrive lorsque tout est installé mais la bibliothèque libplayer n’a pas été référencée pour ld.so (run-time linker). Il suffit alors de faire `sudo ldconfig` pour que les liens soient remis à jour. Je pense que c’est le problème le plus répandu et le plus simple de cette liste. Même que de nombreux développeurs se font avoir.

D’une fois que la librairie est référencée, il est inutile de re-exécuter cette commande, à moins d’avoir changé de --prefix.

Problème III.

Tout fonctionne mais lorsque vous lisez des fichiers audio/video des avertissements apparaissent dans la console:

[mplayer] Warn: [hack] slave command 'stop'

Ce message apparait uniquement avec les versions relativement anciennes de MPlayer. Il faut savoir que la dernière version largement "packagée" à ce jour par les distributions Linux est mplayer-rc2 (version packagée par Ubuntu dans Intrepid Ibex par exemple). Cette version date de presque un an et demi et aucune nouvelle RC n’a été publiée par le team MPlayer. Néanmoins quelques fonctionnalités nécessaires au bon fonctionnement de libplayer n’existaient pas encore. Un article précédent aborde justement la commande ‘stop’. La solution est donc de compiler une version récente de MPlayer.

Problème IV.

Vous pouvez écouter de la musique et regarder des vidéos, mais les snapshots ne s’affichent pas (les snapshots étant les images de fond capturées dans la video depuis le module video d’Enna).

Il peut y avoir plusieurs raisons à ce problème. Tout d’abord assurez-vous d’avoir la propriété use_snapshots=1 dans votre fichier ~/.enna/enna.cfg. Si le problème persiste, vérifiez qu’il n’y a pas de message d’avertissement venant de libplayer comme quoi l’image du snapshot n’a pas pu être copiée. Si c’est le cas vous devez compiler une version plus récente d’MPlayer car les snapshots PNG ne sont possibles que depuis quelques mois.

Depuis peu c’est le module metadata/libplayer qui s’occupe des snapshots et donc le backend n’est pas concerné. Par défaut ce module devrait être compilé, dans le cas contraire vérifiez s’il est bien notifié comme actif dans les messages retournés par le script configure (généré par autogen.sh) de Enna.

Problème V.

Lorsque vous fermez Enna (ou suite à une erreur), des instances de MPlayer sont toujours visibles dans la liste des processus.

Lorsque vous quittez Enna, vous devez voir des messages qui informent que les modules sont désactivés comme par exemple [Enna] [module.c:nn] Info: disable module : backend_libplayer. Dans le cas contraire cela veut dire qu’Enna n’a pas été fermé correctement et donc libplayer n’a pas été "uninitialisé". Les processus enfants de libplayer restent alors en vie et il est donc nécessaire de les tuer manuellement (notez bien que se ne sont pas des processus zombies comme certains peuvent le penser, ils sont bien vivants mais sont en mode ‘-idle -slave‘ et attendent donc des ordres sur leur stdin).

Il y a deux conditions classiques où ce problème apparaît. Par exemple Enna c’est fait tuer tout bêtement, typiquement suite à une erreur de segmentation. Le second cas très courant est que vous avez fermé Enna en cliquant sur la croix de la fenêtre. Ce bug avait été corrigé mais est réapparut depuis quelques temps. La solution est donc de quitter Enna avec la touche d’échappement (Esc).

Problème VI.

Vous voyez tout le temps deux instances de MPlayer dans la liste des processus et même parfois plus.

Ce n’est pas un bug car il y a plusieurs "player" qui sont créés au chargement d’Enna. Tout d’abord il y a le backend qui créer une instance pour pouvoir lire les fichiers audio/video. Ensuite il y a le module metadata/libplayer qui créer également une instance. Le but étant d’avoir des modules indépendants. Vous pouvez très bien utiliser le backend libplayer sans compiler le module metadata/libplayer et inversement.

De temps en temps vous pouvez voir un troisième processus enfant mplayer. Celui-ci apparait que brièvement lorsque des meta-données sont recherchées ou lorsque des snapshots sont créés. Il faut comprendre que pour analyser des metadata, libplayer doit utiliser l’argument ‘-identify‘ d’MPlayer. Ceci ne peut se faire qu’au lancement de MPlayer pour un MRL précis. Les MPlayer lancés en mode ‘-idle -slave‘ ne peuvent en aucun cas identifier toutes les données.

Problème VII.

Vous avez un message d’erreur concernant X11, mais libplayer est correctement installé:

[mplayer] Err: auto-detection for videoout is not enabled
               without X11 support

Il y a deux possibilités.. Vous voulez utiliser Enna uniquement en Framebuffer et vous avez compilé libplayer sans le support de X11. Dans ce cas vous devez explicitement indiquer le video_out dans votre fichier ~/.enna/enna.cfg pour libplayer. L’auto-détection ne fonctionne pas sans le support de X11 pour une raison technique que je ne vais pas aborder ici. Si vous désirez garder l’auto-détection en Framebuffer, compilez libplayer également avec le support de X11.

Vous avez lancé Enna depuis X11, alors vous n’avez pas compilé libplayer avec le support de X11. Soit parce que vous avez explicitement indiqué ‘--disable-x11‘ au configure, soit parce que le configure n’a pas trouvé les en-têtes adéquates pour X11 et à donc décidé de désactiver son support. Pensez donc à installer la libX11-dev (ou équivalent). libplayer dépend de Xlib pour gérer les fenêtres X11.

Quelques remarques

Avant de poser des questions, lisez bien les messages d’erreurs retournés par Enna et libplayer. Les textes affichés dans la console ne sont pas là pour la remplir bêtement en la décorant avec des couleurs, mais ils sont là pour suivre ce qui se passe dans Enna. Les couleurs sont très importantes car elles reflètent l’importance de l’information. De manière simplifiée, les messages bleus sont insignifiants, les verts sont informatifs, les jaunes demandent à ce qu’on leurs prête plus d’attention mais ils n’indiquent pas de dysfonctionnement.
Par contre si vous voyez des messages rouges (Error) ou même pire, des messages sur fond rouge (Critical), alors il y a un problème sérieux.

Je vous conseil vivement de ne pas changer le niveau de verbosité par défaut de Enna et de libplayer. Enna est configuré en mode "info" et n’affichera pas les messages bleus. libplayer est configuré en mode "warning" et n’affichera pas les messages bleus et verts.

Si vous rencontrez un problème que je n’ai pas décrit plus haut et que vous nous contactez, veillez à nous transmettre le log complet retourné par Enna avec au moins les verbosités par défaut (ou alors avec plus de verbosité).

A bientôt,

Mathieu SCHROETER

h1

Une petite rétrospective de libplayer

2008.08.13

Le plus grand challenge que j’ai eu sur l’écriture de libplayer fut le wrapper MPlayer. La première version date d’à peine plus d’une année, c’est à dire la rév.44, le 27 juillet 2007. Aujourd’hui on est à la rév.786 et de très nombreuses améliorations ont été apportées. MPlayer n’étant pas utilisable en tant que librairie il a fallu passer par le mode esclave. Le principe est relativement simple, des commandes sont envoyées sur le stdin de MPlayer, tandis que celui-ci répond sur les stdout et stderr.


Avant d’écrire ce wrapper j’ai passé passablement de temps à regarder ce qui se faisait déjà, et j’ai été surpris de voir que la majorité des front-ends exécutent MPlayer le temps de jouer le média et attendent que celui-ci se ferme. Ainsi MPlayer est chargé et déchargé continuellement. Trouvant cela absurde, j’ai donc choisi de travailler avec les arguments ‘-idle -slave’ d’MPlayer. Ainsi, le player s’exécute une seule fois et attend de recevoir des ordres sur son mode esclave. Je dois reconnaître que cela a énormément compliqué l’implémentation dans libplayer. J’ai été rapidement confronté à plusieurs problèmes majeurs. Tout d’abord il n’existait aucune commande esclave pour stopper la lecture. Cela veut dire que le seul moyen de stopper proprement est de quitter MPlayer. Et je pense que c’est une des raison principale qui font que les front-ends n’utilisent pas le mode -idle.
Il me fallait donc résoudre deux cas, le premier était de savoir comment stopper sans quitter MPlayer pour être rétro-compatible, et le second cas, comment implémenter le ‘stop’ dans MPlayer pour leur envoyer un patch.

Stopper la lecture

Pour le premier cas j’ai d’abord eu une idée stupide mais qui a dépanné pendant quelque temps. Il faut savoir qu’en mode -idle, quand MPlayer a terminé de lire un stream il stoppe et ne fait plus rien. Et surtout, il ne se termine pas. La solution a donc été de forcer un "seek" à 100% pour simuler le stop. Avec la plupart des fichiers audio et vidéo cela marche plutôt bien, néanmoins tous les types de ressources ne sont pas "seekable" et donc ne se stoppe pas (le streaming réseau par exemple).
J’ai donc corrigé ce comportement en rév.237 pour un nouveau hack bien plus malin. Le meilleur moyen de stopper la lecture était de faire croire à MPlayer qu’il devait charger un nouveau stream. La solution est donc de lui dire de charger quelque chose qui n’existe pas avec la commande loadfile ". Aucun fichier n’est donné avec le loadfile mais néanmoins il y a les apostrophes. La commande ne retourne donc pas d’erreur sur le nombre d’arguments utilisés mais retourne une erreur car MPlayer ne trouve pas le fichier " (et du même coup, stoppe la lecture en cours) et dit simplement "File not found: "". Il est donc facile de détecter également que MPlayer a bien stoppé son activité.

Ce hack est toujours implémenté dans libplayer pour une question de rétro-compatibilité. Néanmoins la commande ‘stop’ existe désormais dans le mode esclave (patch MPlayer). Celle-ci a été ajouté dans libplayer avec la rév.458, c’est à dire il y a à peine 5 semaines. A l’initialisation de libplayer, des tests sont effectués sur le MPlayer hôte, et si la commande ‘stop’ n’existe pas alors le hack est utilisé à la place.

Détecter la fin de la lecture

Le second problème majeur dont je voulais parler concerne les évènements envoyés à l’utilisateur de la librairie. Et un de ces évènement n’était pas trivial à gérer. Lorsqu’un stream est lu en entier, MPlayer ne fait plus rien mais ne dit pas grand chose. En réalité MPlayer est tellement peu bavard par défaut qu’il est impossible de savoir quoi que se sois sans lui forcer la main. J’ai donc été obligé d’augmenter significativement sa verbosité (voir les rev.78 et rev.552) pour détecter les codes EOF (et bien d’autres choses encore). Ainsi il aurait pu être facile de savoir quand envoyer un évènement de type "PLAYBACK_FINISHED". Mais la encore, un problème n’arrive jamais seul et j’étais confronté à un autre  qui dépend directement de l’implémentation que j’avais fais du wrapper. Le principe était assez simple, après avoir envoyé une commande, je lisais la sortie de MPlayer pour voir ce qu’il faisait et ensuite je pouvais retourner les résultats adéquats à l’utilisateur de la librairie. Mais le EOF étant complètement asynchrone, je ne pouvais pas savoir quand est-ce qu’il fallait faire quelque chose. Pour régler ce cas, une seule solution propre. Utiliser un thread pour s’occuper de lire les messages de MPlayer (rév.77). Et qui dit thread, dit "race", "deadlock" et bien d’autres problèmes..

Mais encore…

Les deux cas au-dessus ne sont qu’une partie des problèmes rencontrés, il y en a eu bien d’autres et les 700 révisions ne sont pas tombées du ciel. Mais quoi qu’il en soit, aujourd’hui le wrapper MPlayer se porte bien, tous les patchs que j’ai soumis à MPlayer ont trouvés leur place et la rétro-compatibilité est assurée.
Pour résumer quelque peu l’état actuel de la librairie (de manière non exhaustive), on peut dire que le wrapper est implémenté à plus de 70% et permet de faire largement le job demandé par un lecteur audio/vidéo.

Ci-dessous, vous pouvez voir un extrait de la sortie donnée par le script ./stats.sh disponible dans le dépôt de libplayer:

Global statistics (sum):
~~~~~~~~~~~~~~~~~~~~~~~~

gstreamer  : (11)  13%  [#####.......................................]
mplayer    : (58)  72%  [###############################.............]
vlc        : (22)  27%  [###########.................................]
xine       : (30)  37%  [################............................]

Maximum: 80

libplayer  :       37%  [################............................]

A bientôt,

Mathieu SCHROETER

h1

libplayer: MPlayer et le dvd://

2008.07.03

Hello,

en voulant étendre libplayer comme à mon habitude je me suis confronté à un petit problème. Et de ce fait j’ai dû me pencher sur les sources d’MPlayer. Il faut dire que ce n’est pas la première fois, mais j’y reviendrais un jour dans un autre article.

Il y a quelques mois, libplayer permettait de gérer les dvd et dvdnav simplement parce que la commande pour ajouter un stream utilisait directement des MRLs. Mais ceci a changé pour différentes raisons.. Et donc il faut désormais explicitement dire à libplayer quel genre de ressource on désire lire. Dans le cas d’un DVD un enum donne le choix entre MRL_RESOURCE_DVD et MRL_RESOURCE_DVDNAV. Mon but est donc de gérer ces deux cas de figure afin que l’on puisse à nouveau lire ce genre de média. Et c’est exactement ici qu’un problème apparait.

Selon le manpage de MPlayer, le MRL pour lire un dvd/dvdnav se comporte ainsi:

[dvd|dvdnav]://[title|[start_title]-end_title]

Ce qui me semblait surprennant c’est que pour lire un CD-Audio ou même un VideoCD, les MRLs permettent de passer en plus un argument optionnel [/device] afin d’indiquer le lecteur CD à utiliser. Ce qui est extrêmement pratique dans le cas de libplayer, car il faut savoir que sans cet argument, le seul moyen de changer le lecteur de DVD par défaut est de le spécifier au démarrage de MPlayer avec -dvd-device ou alors en spécifiant celui-ci dans le fichier .mplayer/config.
Bien entendu ce n’est pas acceptable lorsque l’on travail en mode "-slave -idle". Car dans ce cas, MPlayer est chargé une fois pour toute au démarrage et il est fréquent que les utilisateurs aient plusieurs lecteurs DVD.

Je me suis donc plongé dans le code de MPlayer à la recherche de cet argument optionnel. Et j’ai constaté un détail très intéressant avec dvdnav. Celui-ci permet déjà de gérer l’argument [/device] mais pourtant le manpage n’est pas du même avis. J’en profite donc pour étudier le fonctionnement de l’argument dans stream/stream_vcd.c et stream/stream_dvdnav.c afin de créer un patch pour stream/stream_dvd.c.

Au moment même où j’écris ces lignes, ce patch est en attente d’être contrôlé et je l’espère commité par un dev d’MPlayer.


http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2008-July/058011.html

A bientôt…

Mathieu SCHROETER

Suivre

Recevez les nouvelles publications par mail.

%d bloggers like this: