123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- \section{Cadre du projet}
- La mission s'inscrivait dans le cadre de la diffusion d'un flux vidéo vers un
- chromecast. Il s'avère que le chromecast ne supporte pas de recevoir des flux de
- sous-titre, ou alors certains formats seulement. Ceci parce qu'il était à la
- base prévu pour Youtube qui n'est jamais très loin du format Webm.
- Le webm est un format utilisant une sous-partie du format Matroska, en étant
- spécialement dédié à la diffusion de vidéo sur le web et dans un navigateur.
- % TODO: expliquer demuxage
- L'idée pour intégrer les sous-titres lors de la diffusion est donc de démuxer
- les fichiers, puis de rendre ces sous-titres avant directement sur la vidéo
- avant de remuxer puis envoyer au chromecast, le tout en temps réel.
- Lors de la diffusion d'une vidéo depuis un téléphone, on tombe alors sur un
- nouveau problème: l'usage de la batterie. Décoder et réencoder de la vidéo
- consomme beaucoup de CPU et le téléphone finit par chauffer et se décharger très
- vite.
- On peut alors utiliser plutôt les circuits d'encodage intégrés sur presque tous
- les téléphones. Ces derniers consomment beaucoup moins d'énergie que leur
- pendant logiciel, mais leurs fonctionnalités sont matériellement figées dans les
- circuits qui les composent. Ils sont également limités en nombre de sessions
- possible, et peuvent avoir des comportements différents entre chaque téléphone
- ou faire crasher le programme, voire le téléphone en cas d'utilisation
- incorrecte.
- % TODO: reference MediaCodec
- Pour les téléphones Android, c'est l'API MediaCodec
- \footnote{\url{https://developer.android.com/reference/android/media/MediaCodec}}
- qu'il faut utiliser afin de manipuler les décodeurs/encodeurs disponibles sur le
- téléphone. Un décodeur MediaCodec étant déjà existant, il s'agit plus ou moins
- d'étendre les fonctionnalités déjà en place pour pouvoir également instancier un
- encodeur.
- Dans cette partie-là, nous allons voir ce qu'est un encodeur, comment ils sont
- construits et utilisés au sein de VLC ainsi que quelques détails de
- l'implémentation finale de l'encodeur utilisant l'API MediaCodec d'Android.
- \section{Qu'est-ce qu'un encodeur}
- L'encodeur est le module qui récupère des images dans un format fixé et produit
- un bytestream vidéo correspondant au format d'encodage vidéo choisi. Il se situe
- donc après les filtres vidéos et avant le muxer. Pour la plupart des formats,
- l'encodeur a besoin de données spéciales relative au format utilisé. Pour h264,
- il s'agit du SPS et PPS, décrivant les informations communes aux images
- encodées.
- L'encodeur dans MediaCodec fonctionne comme une machine à état asynchone. Il est
- probablement important de noter que l'API n'indique pas qu'elle est thread-safe.
- % TODO: rôle dans la chaine avec schéma
- % TODO: codec specific data
- % TODO: état de l'encodeur
- % TODO: flux de données
- \section{Fonctionnement d'un encodeur dans VLC}
- Dans VLC, l'encodeur est principalement utilisé par un seul module: le module
- \og{}transcode\fg{}. À ce jour, il utilise un flux multimédia complet en entrée,
- c'est-à-dire plusieurs \og{}elementary streams\fg{} que sont les les sous-titres, les
- flux vidéos et les flux audios. Il produit ensuite le même flux multimédia
- encodé par un muxer.
- % TODO: exemple d'utilisation du module transcode en console
- L'encodeur est définit par la structure suivante dans le core de VLC.
- \begin{code}{c}{Structure d'un encodeur dans VLC}
- struct encoder_t
- {
- /* common fields */
- /* ... */
- /* Properties of the input data fed to the encoder */
- es_format_t fmt_in;
- /* Properties of the output of the encoder */
- es_format_t fmt_out;
- block_t * ( * pf_encode_video )( encoder_t *, picture_t * );
- block_t * ( * pf_encode_audio )( encoder_t *, block_t * );
- block_t * ( * pf_encode_sub )( encoder_t *, subpicture_t * );
- /* Common encoder options */
- /* ... */
- };
- \end{code}
- La première remarque est que l'encodage se fait de façon asynchrone. En effet,
- malgré l'interface ici, le module a la possibilité de renvoyer des
- pointeur \inltype{block_t} vers \inltype{NULL} pour indiquer qu'il n'a pas fini
- de décoder.
- % TODO: encodage synchrone : on remplit les pf des types de flux qu'on supporte
- % TODO: fmt_in / fmt_out => pas modifiable après ouverture de l'encodeur
- % TODO :modifier paragraphe d'apres
- \section{Implémentation de l'encodeur}
- Des problèmes arrivent dès le début de l'implémentation. Il n'est en effet pas
- possible de modifier le format de sortie de l'encodeur après son initialisation
- dans la fonction \inltype{OpenEncoder}. Or les informations sur le codec --
- codec specific data -- ne sont disponibles qu'après avoir commencé à encoder les
- premières images.
- L'implémentation que j'ai réalisée fait en sorte de retarder la création du flux
- de sortie jusqu'au moment où les premières images encodées sont disponibles. Or,
- certains muxeur en sortie ne permettent pas de réaliser ce délai. Des
- modifications sur l'architecture étaient donc nécessaires pour l'intégration de
- mon travail et étaient en cours à la fin de mon stage.
- L'encodeur fonctionne à travers l'API java de MediaCodec, appelé depuis
- l'interface JNI. La raison de ce choix est l'impossibilité d'effectuer certaines
- actions essentielles à partir de l'interface proposée par le NDK d'android.
- Les principales difficultés ont été de:
- \begin{itemize}
- \item Comprendre le fonctionnement de l'encodeur dans VLC.
- \item Comprendre les interactions avec le muxer.
- \item Déterminer la façon la plus correcte de définir des PTS et DTS.\@
- \end{itemize}
- La réalisation du module a été une excellente occasion pour comprendre en
- profondeur l'agencement des différents modules du pipeline de VLC.
|