Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ExoPlayer, player multimédia pour les applications et la réalité virtuelle

ExoPlayer, player multimédia pour les applications et la réalité virtuelle

Cette présentation commencera avec une introduction à ExoPlayer qui en fait un remplaçant naturel de MediaPlayer. Les fonctionnalités de la v1 à v2 seront exposées avec les pour et les contre, le différents formats supportés par la player, ses différentes extensions... On vous montrera comment migrer votre code MediaPlayer vers ExoPlayer en quelques lignes de code. On finira par la capacité d'ExoPlayer à être utilisé dans le domaine de la réalité virtuelle sur Android pour créer des players pour Cardboard / Daydream ou GearVR et comment l'utiliser à l'aide d'un plugin sur Unity.

Julien Salvi

April 10, 2017
Tweet

More Decks by Julien Salvi

Other Decks in Programming

Transcript

  1. ExoPlayer
    Julien Salvi
    Player multimédia pour les applications et
    la réalité virtuelle

    View Slide

  2. Julien Salvi
    Android addict depuis Froyo
    Belgium beer lover!
    Twitter: @JulienSalvi
    Creative Technologist & Ingénieur
    Android @ Cinémur

    View Slide

  3. ExoPlayer à votre service !
    Un player multimédia sur Android ?

    View Slide

  4. 1
    Pour commencer
    Ce bon vieux MediaPlayer

    View Slide

  5. Modèle du MediaPlayer sur Android

    View Slide

  6. MediaPlayer, lecteur média par défaut sur Android.
    Introduction des API bas niveau MediaExtractor, MediaCodec ou MediaDrm
    depuis Jelly Bean.
    → Simple d’utilisation
    → Customisation difficile
    → Un nombre de formats limité
    Une solution basique

    View Slide

  7. 2.1
    Passons aux choses sérieuses
    ExoPlayer - Version 1

    View Slide

  8. repositories {
    jcenter()
    }
    dependencies {
    …….
    compile 'com.google.android.exoplayer:exoplayer:rX.X.X'
    …….
    }
    Import dans Gradle

    View Slide

  9. Une architecture améliorée

    View Slide

  10. Exoplayer v1 en chiffres
    5
    Extensions
    Supports
    DRM
    2
    10+
    Formats vidéo
    MP4, FMP4, FLV, WebM,
    MKV, Ogg...
    10+
    Formats audio
    MP3, AAC, Flac, MIDI, Opus,
    WAV...
    Formats
    textes
    3
    Adaptive
    streaming
    3

    View Slide

  11. Un peu de code !
    (quand même)

    View Slide

  12. // 1. Instantiate the player.
    player = ExoPlayer.Factory.newInstance(RENDERER_COUNT);
    // 2. Construct renderers.
    MediaCodecVideoTrackRenderer videoRenderer = ...
    MediaCodecAudioTrackRenderer audioRenderer = ...
    // 3. Inject the renderers through prepare.
    player.prepare(videoRenderer, audioRenderer);
    // 4. Pass the surface to the video renderer.
    player.sendMessage(videoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, surface);
    // 5. Start playback.
    player.setPlayWhenReady(true);
    ...
    player.release(); // Don’t forget to release when done!
    Instantiation du player

    View Slide

  13. Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE);
    DataSource dataSource = new DefaultUriDataSource(context, null, userAgent);
    ExtractorSampleSource sampleSource = new ExtractorSampleSource(
    uri, dataSource, allocator, BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE);
    MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(
    context, sampleSource, MediaCodecSelector.DEFAULT, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT);
    MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(
    sampleSource, MediaCodecSelector.DEFAULT);
    Préparation des renderers

    View Slide

  14. 2.2
    On sort l’artillerie lourde
    ExoPlayer - La version 2 à la rescousse !

    View Slide

  15. Introduit en Septembre 2016 (version 2.3.1 actuellement)
    Une nouvelle architecture pour lutter contre les limitations de la v1
    Amélioration de l’audio et des supports de formats vidéo
    Introduction de nouvelles extensions (ffmpeg, GVR)
    Implémentation et customisation simplifiées
    ExoPlayer v2 en quelques mots

    View Slide

  16. Et en chiffres ?
    7
    Extensions
    Supports
    DRM
    3
    10+
    Formats vidéo
    MP4, FMP4, FLV, WebM,
    MKV, Ogg...
    10+
    Formats audio
    MP3, AAC, Flac, MIDI, Opus,
    WAV...
    Formats
    textes
    4+
    Adaptive
    streaming
    3

    View Slide

  17. Spoiler : OUI
    Mais c’est si simple que
    ça dans le code ?

    View Slide

  18. // 1. Create a default TrackSelector
    Handler mainHandler = new Handler();
    BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
    TrackSelection.Factory videoTrackSelectionFactory =
    new AdaptiveTrackSelection.Factory(bandwidthMeter);
    TrackSelector trackSelector =
    new DefaultTrackSelector(videoTrackSelectionFactory);
    // 2. Create a default LoadControl
    LoadControl loadControl = new DefaultLoadControl();
    // 3. Create the player
    SimpleExoPlayer player =
    ExoPlayerFactory.newSimpleInstance(context, trackSelector, loadControl);
    // 4.Bind the player to the view.
    simpleExoPlayerView.setPlayer(player);

    View Slide

  19. // 5. Preparing the player
    // Produces DataSource instances through which media data is loaded.
    DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this,
    Util.getUserAgent(this, "yourApplicationName"), bandwidthMeter);
    // Produces Extractor instances for parsing the media data.
    ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
    // This is the MediaSource representing the media to be played.
    MediaSource videoSource = new ExtractorMediaSource(mp4VideoUri,
    dataSourceFactory, extractorsFactory, null, null);
    // Prepare the player with the source.
    player.prepare(videoSource);
    // 6. Play the content
    player.setPlayWhenReady(true);

    View Slide

  20. Nouvelles fonctionnalités

    View Slide

  21. Changement de sous-titres externes
    MediaSource videoSource = new ExtractorMediaSource(videoUri, ...);
    MediaSource subtitleSource = new SingleSampleMediaSource(subtitleUri, ...);
    // Plays the video with the sideloaded subtitle.
    MergingMediaSource mergedSource =
    new MergingMediaSource(videoSource, subtitleSource);

    View Slide

  22. Lecture d’une vidéo en boucle
    MediaSource source = new ExtractorMediaSource(videoUri, ...);
    // Loops the video indefinitely.
    LoopingMediaSource loopingSource = new LoopingMediaSource(source);

    View Slide

  23. Concaténation de vidéos
    MediaSource firstSource = new ExtractorMediaSource(firstVideoUri, ...);
    MediaSource secondSource = new ExtractorMediaSource(secondVideoUri, ...);
    // Plays the first video, then the second video.
    ConcatenatingMediaSource concatenatedSource =
    new ConcatenatingMediaSource(firstSource, secondSource);

    View Slide

  24. MediaPlayer ExoPlayer
    (You vs. the guy she told you not to worry about)

    View Slide

  25. 3
    La vidéo sur mobile ? #old
    Place à la Réalité Virtuelle !

    View Slide

  26. John Carmack
    It's a moral
    imperative that we
    must create this

    NOT SO BAD

    View Slide

  27. GoogleVR SDK (1.30)
    Java, OpenGL ES, JNI
    GearVR Mobile SDK
    (1.5) C/C++, JNI
    Développement natif sur Android

    View Slide

  28. Création d’une lib wrapper
    Création d’une classe helper pour exposer les méthodes
    d’initialisation du player et de ses contrôles.
    Ajout d’extensions nécessaires (GVR, FFMPEG, OkHttp… )
    Intégration d’une gestion DRM autre que Widevine

    View Slide

  29. Plugin player basé sur ExoPlayer
    GoogleVR SDK
    OpenGL ES
    Player de test

    View Slide

  30. MovieTexture de Unity pas compatible avec Android
    Etablir le lien entre la texture Unity et la surface Android pour
    effectuer le rendu vidéo
    Player Android pour Unity

    View Slide

  31. Developper son plugin en Java ou C/C++
    Plugins utilisables avec Unity : .jar, .aar ou .so
    Développer un plugin Android pour Unity

    View Slide

  32. Avec du C# et C++ au menu
    Direction Unity et la JNI !

    View Slide

  33. AndroidJavaObject localMediaPlayer = null;
    using (AndroidJavaClass javaUnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) {
    using (currentActivity = javaUnityPlayer.GetStatic("currentActivity")) {
    localMediaPlayer = new AndroidJavaObject("my/plugin/vr/ExoPlayerBridge", currentActivity);
    if (localMediaPlayer != null) {
    // Do some work with your java object outside the Android UI thread
    localMediaPlayer.Call("addSubtitles", subtitleURL);
    currentActivity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
    {
    // Do some work on Android UI thread
    localMediaPlayer.Call("prepare", true);
    }));
    }
    }
    }
    Appeler un objet Java depuis Unity

    View Slide

  34. Fonction se trouvant dans le plugin
    Définition de la fonction dans le script Unity
    extern "C" {
    float FooPluginFunction ();
    }
    Plugin C/C++
    [DllImport ("PluginName")]
    private static extern float FooPluginFunction ();

    View Slide

  35. Gain de performance en passant par la JNI pour appeler
    des fonctionnalités de votre plugin Java
    Important: chargement de la JVM
    jint JNI_OnLoad(JavaVM* vm, void* reserved) {
    JNIEnv* jni_env = 0;
    vm->AttachCurrentThread(&jni_env, 0);
    return JNI_VERSION_1_6;
    }
    Plugin Java et C/C++

    View Slide

  36. Exemple de fonction JNI pour interagir avec votre class Java
    JNIEXPORT jobject JNICALL Java_com_example_NativeClass_nativeMethod(JNIEnv* env) {
    jclass cls_JavaClass = env->FindClass("com/your/java/Class"); // find class definition
    jmethodID mid_JavaClass = env->GetMethodID (cls_JavaClass, "", "()V"); // find constructor method
    jobject obj_JavaClass = env->NewObject(cls_JavaClass, mid_JavaClass); // create object instance
    return env->NewGlobalRef(obj_JavaClass); // return object with a global reference
    }
    Plugin Java et C/C++

    View Slide

  37. Passage de la texture Unity vers Android
    // Can't use AndroidJavaObject.Call() with a jobject, must use low level interface
    IntPtr setSimplePlayerID = AndroidJNI.GetMethodID(localMediaPlayer.GetRawClass(), "setSurface",
    "(Landroid/view/Surface;)V");
    jvalue[] parms = new jvalue[1];
    parms[0] = new jvalue();
    parms[0].l = _androidSurface; // Android Surface reference as an IntPtr
    AndroidJNI.CallVoidMethod(localMediaPlayer.GetRawObject(), setSimplePlayerID, parms);
    Plugin Java et C/C++

    View Slide

  38. J
    N
    I
    Java code C/C++ code
    ExoPlayer

    View Slide

  39. View Slide

  40. https://medium.com/google-exoplayer
    https://medium.com/@cinemur/73ec7e83dd5c
    Medium ExoPlayer:
    ExoPlayer for building powerful VR players on Cardboard and GearVR:
    https://docs.unity3d.com/Manual/PluginsForAndroid.html
    Développer des plugins Android pour Unity:
    Pour en savoir plus

    View Slide

  41. "VR can be tremendously fun and beautiful.
    It's been frustrating that more people haven't
    been able to enjoy it for so many years. I hope
    lots of people will soon find VR to be as
    fascinating as I have."
    “La Réalité virtuelle peut être fun et
    magnifique. C’est frustrant de savoir que les
    gens n’en ont pas profité depuis des années.
    J’espère que bientôt beaucoup de monde
    seront fascinés par la VR autant que je le suis”
    Jaron Lanier - term of Virtual Reality Inventor
    Merci !

    View Slide