\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.