[vlc-devel] [PATCH v3 6/8] libvlc: player: use vlc_player

Romain Vimont rom1v at videolabs.io
Mon May 20 17:35:15 CEST 2019


Implement the old libvlc player API using the new vlc_player.
---
 lib/audio.c                 |   95 +-
 lib/media_player.c          | 1622 ++++++++++++++++-------------------
 lib/media_player_internal.h |   21 +-
 lib/video.c                 |  266 ++----
 4 files changed, 839 insertions(+), 1165 deletions(-)

diff --git a/lib/audio.c b/lib/audio.c
index 751584d0f1..f5e4493138 100644
--- a/lib/audio.c
+++ b/lib/audio.c
@@ -50,7 +50,7 @@ static audio_output_t *GetAOut( libvlc_media_player_t *mp )
 {
     assert( mp != NULL );
 
-    audio_output_t *p_aout = input_resource_HoldAout( mp->input.p_resource );
+    audio_output_t *p_aout = vlc_player_aout_Hold(mp->player);
     if( p_aout == NULL )
         libvlc_printerr( "No active audio output" );
     return p_aout;
@@ -131,14 +131,6 @@ int libvlc_audio_output_set( libvlc_media_player_t *mp, const char *psz_name )
     var_SetString( mp, "aout", value );
     free( value );
 
-    /* Forget the existing audio output */
-    input_resource_ResetAout(mp->input.p_resource);
-
-    /* Create a new audio output */
-    audio_output_t *aout = input_resource_GetAout(mp->input.p_resource);
-    if( aout != NULL )
-        input_resource_PutAout(mp->input.p_resource, aout);
-
     return 0;
 }
 
@@ -340,16 +332,13 @@ int libvlc_audio_set_volume( libvlc_media_player_t *mp, int volume )
  *****************************************************************************/
 int libvlc_audio_get_track_count( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
-    int i_track_count;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    if( !p_input_thread )
-        return -1;
+    int ret = vlc_player_GetTrackCount(p_mi->player, AUDIO_ES);
 
-    i_track_count = var_CountChoices( p_input_thread, "audio-es" );
-
-    input_Release(p_input_thread);
-    return i_track_count;
+    vlc_player_Unlock(player);
+    return ret;
 }
 
 /*****************************************************************************
@@ -358,7 +347,7 @@ int libvlc_audio_get_track_count( libvlc_media_player_t *p_mi )
 libvlc_track_description_t *
         libvlc_audio_get_track_description( libvlc_media_player_t *p_mi )
 {
-    return libvlc_get_track_description( p_mi, "audio-es" );
+    return libvlc_get_track_description( p_mi, AUDIO_ES );
 }
 
 /*****************************************************************************
@@ -366,12 +355,14 @@ libvlc_track_description_t *
  *****************************************************************************/
 int libvlc_audio_get_track( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
-    if( !p_input_thread )
-        return -1;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    int id = var_GetInteger( p_input_thread, "audio-es" );
-    input_Release(p_input_thread);
+    const struct vlc_player_track *track =
+        vlc_player_GetSelectedTrack(player, AUDIO_ES);
+    int id = track ? vlc_es_id_GetInputId(track->es_id) : -1;
+
+    vlc_player_Unlock(player);
     return id;
 }
 
@@ -380,30 +371,27 @@ int libvlc_audio_get_track( libvlc_media_player_t *p_mi )
  *****************************************************************************/
 int libvlc_audio_set_track( libvlc_media_player_t *p_mi, int i_track )
 {
-    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
-    vlc_value_t *val_list;
-    size_t count;
     int i_ret = -1;
 
-    if( !p_input_thread )
-        return -1;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    var_Change( p_input_thread, "audio-es", VLC_VAR_GETCHOICES,
-                &count, &val_list, (char ***)NULL );
+    size_t count = vlc_player_GetAudioTrackCount(player);
     for( size_t i = 0; i < count; i++ )
     {
-        if( i_track == val_list[i].i_int )
+        const struct vlc_player_track *track =
+            vlc_player_GetAudioTrackAt(player, i);
+        if (i_track == vlc_es_id_GetInputId(track->es_id))
         {
-            if( var_SetInteger( p_input_thread, "audio-es", i_track ) < 0 )
-                break;
+            /* found */
+            vlc_player_SelectTrack(player, track->es_id);
             i_ret = 0;
             goto end;
         }
     }
     libvlc_printerr( "Track identifier not found" );
 end:
-    free( val_list );
-    input_Release(p_input_thread);
+    vlc_player_Unlock(player);
     return i_ret;
 }
 
@@ -446,14 +434,14 @@ int libvlc_audio_set_channel( libvlc_media_player_t *mp, int channel )
  *****************************************************************************/
 int64_t libvlc_audio_get_delay( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
-    int64_t val = 0;
-    if( p_input_thread != NULL )
-    {
-      val = US_FROM_VLC_TICK( var_GetInteger( p_input_thread, "audio-delay" ) );
-      input_Release(p_input_thread);
-    }
-    return val;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
+
+    vlc_tick_t delay = vlc_player_GetAudioDelay(player);
+
+    vlc_player_Unlock(player);
+
+    return US_FROM_VLC_TICK(delay);
 }
 
 /*****************************************************************************
@@ -461,18 +449,15 @@ int64_t libvlc_audio_get_delay( libvlc_media_player_t *p_mi )
  *****************************************************************************/
 int libvlc_audio_set_delay( libvlc_media_player_t *p_mi, int64_t i_delay )
 {
-    input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
-    int ret = 0;
-    if( p_input_thread != NULL )
-    {
-      var_SetInteger( p_input_thread, "audio-delay", VLC_TICK_FROM_US( i_delay ) );
-      input_Release(p_input_thread);
-    }
-    else
-    {
-      ret = -1;
-    }
-    return ret;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
+
+    vlc_player_SetAudioDelay(player, VLC_TICK_FROM_US(i_delay),
+                             VLC_PLAYER_WHENCE_ABSOLUTE);
+
+    vlc_player_Unlock(player);
+    /* may not fail anymore, keep int not to break the API */
+    return 0;
 }
 
 /*****************************************************************************
diff --git a/lib/media_player.c b/lib/media_player.c
index ca65556cc3..057add2afe 100644
--- a/lib/media_player.c
+++ b/lib/media_player.c
@@ -47,470 +47,451 @@
 #define ES_INIT (-2) /* -1 is reserved for ES deselect */
 
 static int
-input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
-                        vlc_value_t oldval, vlc_value_t newval,
-                        void * p_userdata );
-static int
-input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
-                        vlc_value_t oldval, vlc_value_t newval,
-                        void * p_userdata );
-static int
-input_scrambled_changed( vlc_object_t * p_this, char const * psz_cmd,
-                        vlc_value_t oldval, vlc_value_t newval,
-                        void * p_userdata );
-static int
-input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
-                     vlc_value_t oldval, vlc_value_t newval,
-                     void * p_userdata );
-
-static int
-input_es_changed( vlc_object_t * p_this, char const * psz_cmd,
-                  int action, vlc_value_t *p_val,
-                  void *p_userdata);
+snapshot_was_taken( vlc_object_t *p_this, char const *psz_cmd,
+                    vlc_value_t oldval, vlc_value_t newval, void *p_data );
 
-static int
-corks_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
-              vlc_value_t cur, void *opaque);
+static void media_attach_preparsed_event(libvlc_media_t *);
+static void media_detach_preparsed_event(libvlc_media_t *);
 
-static int
-mute_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
-             vlc_value_t cur, void *opaque);
+static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi );
 
-static int
-volume_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
-               vlc_value_t cur, void *opaque);
+// player callbacks
 
 static void
-add_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi );
+on_current_media_changed(vlc_player_t *player, input_item_t *new_media,
+                         void *data)
+{
+    (void) player;
 
-static void
-del_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi );
+    libvlc_media_player_t *mp = data;
 
-static int
-snapshot_was_taken( vlc_object_t *p_this, char const *psz_cmd,
-                    vlc_value_t oldval, vlc_value_t newval, void *p_data );
+    libvlc_media_t *md = mp->p_md;
 
-static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi );
+    input_item_t *media = md ? md->p_input_item : NULL;
+    if (new_media == media)
+        /* no changes */
+        return;
 
-/*
- * Shortcuts
- */
+    if (md)
+        media_detach_preparsed_event(md);
 
-/*
- * The input lock protects the input and input resource pointer.
- * It MUST NOT be used from callbacks.
- *
- * The object lock protects the reset, namely the media and the player state.
- * It can, and usually needs to be taken from callbacks.
- * The object lock can be acquired under the input lock... and consequently
- * the opposite order is STRICTLY PROHIBITED.
- */
-static inline void lock(libvlc_media_player_t *mp)
-{
-    vlc_mutex_lock(&mp->object_lock);
+    if (new_media)
+    {
+        mp->p_md = libvlc_media_new_from_input_item(mp->p_libvlc_instance,
+                                                    new_media);
+        if (!mp->p_md)
+            /* error already printed by the function call */
+            return;
+
+        media_attach_preparsed_event(mp->p_md);
+    }
+    else
+        mp->p_md = NULL;
+
+    libvlc_media_release(md);
+
+    libvlc_event_t event;
+    event.type = libvlc_MediaPlayerMediaChanged;
+    event.u.media_player_media_changed.new_media = mp->p_md;
+    libvlc_event_send(&mp->event_manager, &event);
 }
 
-static inline void unlock(libvlc_media_player_t *mp)
+static void
+on_state_changed(vlc_player_t *player, enum vlc_player_state new_state,
+                 void *data)
 {
-    vlc_mutex_unlock(&mp->object_lock);
+    (void) player;
+
+    libvlc_media_player_t *mp = data;
+
+    libvlc_event_t event;
+    switch (new_state) {
+        case VLC_PLAYER_STATE_STOPPED:
+            event.type = libvlc_MediaPlayerStopped;
+            break;
+        case VLC_PLAYER_STATE_STOPPING:
+            event.type = libvlc_MediaPlayerEndReached;
+            break;
+        case VLC_PLAYER_STATE_STARTED:
+            event.type = libvlc_MediaPlayerOpening;
+            break;
+        case VLC_PLAYER_STATE_PLAYING:
+            event.type = libvlc_MediaPlayerPlaying;
+            break;
+        case VLC_PLAYER_STATE_PAUSED:
+            event.type = libvlc_MediaPlayerPaused;
+            break;
+        default:
+            vlc_assert_unreachable();
+    }
+
+    libvlc_event_send(&mp->event_manager, &event);
 }
 
-static inline void lock_input(libvlc_media_player_t *mp)
+static void
+on_error_changed(vlc_player_t *player, enum vlc_player_error error, void *data)
 {
-    vlc_mutex_lock(&mp->input.lock);
+    (void) player;
+
+    libvlc_media_player_t *mp = data;
+
+    libvlc_event_t event;
+    switch (error) {
+        case VLC_PLAYER_ERROR_NONE:
+            event.type = libvlc_MediaPlayerNothingSpecial;
+            break;
+        case VLC_PLAYER_ERROR_GENERIC:
+            event.type = libvlc_MediaPlayerEncounteredError;
+            break;
+        default:
+            vlc_assert_unreachable();
+    }
+
+    libvlc_event_send(&mp->event_manager, &event);
 }
 
-static inline void unlock_input(libvlc_media_player_t *mp)
+static void
+on_buffering_changed(vlc_player_t *player, float new_buffering, void *data)
 {
-    vlc_mutex_unlock(&mp->input.lock);
+    (void) player;
+
+    libvlc_media_player_t *mp = data;
+
+    libvlc_event_t event;
+    event.type = libvlc_MediaPlayerBuffering;
+    event.u.media_player_buffering.new_cache = 100 * new_buffering;
+
+    libvlc_event_send(&mp->event_manager, &event);
 }
 
-static void input_item_preparsed_changed( const vlc_event_t *p_event,
-                                          void * user_data )
+static void
+on_capabilities_changed(vlc_player_t *player, int old_caps, int new_caps, void *data)
 {
-    libvlc_media_t *p_md = user_data;
-    if( p_event->u.input_item_preparsed_changed.new_status & ITEM_PREPARSED )
+    (void) player;
+
+    libvlc_media_player_t *mp = data;
+
+    libvlc_event_t event;
+
+    bool old_seekable = old_caps & VLC_INPUT_CAPABILITIES_SEEKABLE;
+    bool new_seekable = new_caps & VLC_INPUT_CAPABILITIES_SEEKABLE;
+    if (new_seekable != old_seekable)
     {
-        /* Send the event */
-        libvlc_event_t event;
-        event.type = libvlc_MediaParsedChanged;
-        event.u.media_parsed_changed.new_status = libvlc_media_parsed_status_done;
-        libvlc_event_send( &p_md->event_manager, &event );
+        event.type = libvlc_MediaPlayerSeekableChanged;
+        event.u.media_player_seekable_changed.new_seekable = new_seekable;
+        libvlc_event_send(&mp->event_manager, &event);
     }
-}
 
-static void media_attach_preparsed_event( libvlc_media_t *p_md )
-{
-    vlc_event_attach( &p_md->p_input_item->event_manager,
-                      vlc_InputItemPreparsedChanged,
-                      input_item_preparsed_changed, p_md );
+    bool old_pauseable = old_caps & VLC_INPUT_CAPABILITIES_PAUSEABLE;
+    bool new_pauseable = new_caps & VLC_INPUT_CAPABILITIES_PAUSEABLE;
+    if (new_pauseable != old_pauseable)
+    {
+        event.type = libvlc_MediaPlayerPausableChanged;
+        event.u.media_player_pausable_changed.new_pausable = new_pauseable;
+        libvlc_event_send(&mp->event_manager, &event);
+    }
 }
 
-static void media_detach_preparsed_event( libvlc_media_t *p_md )
+static void
+on_position_changed(vlc_player_t *player, vlc_tick_t new_time, float new_pos,
+                    void *data)
 {
-    vlc_event_detach( &p_md->p_input_item->event_manager,
-                      vlc_InputItemPreparsedChanged,
-                      input_item_preparsed_changed,
-                      p_md );
+    (void) player;
+
+    libvlc_media_player_t *mp = data;
+
+    libvlc_event_t event;
+
+    event.type = libvlc_MediaPlayerPositionChanged;
+    event.u.media_player_position_changed.new_position = new_pos;
+    libvlc_event_send(&mp->event_manager, &event);
+
+    event.type = libvlc_MediaPlayerTimeChanged;
+    event.u.media_player_time_changed.new_time = MS_FROM_VLC_TICK(new_time);
+    libvlc_event_send(&mp->event_manager, &event);
 }
 
-/*
- * Release the associated input thread.
- *
- * Object lock is NOT held.
- * Input lock is held or instance is being destroyed.
- */
-static void release_input_thread( libvlc_media_player_t *p_mi )
+static void
+on_length_changed(vlc_player_t *player, vlc_tick_t new_length, void *data)
 {
-    assert( p_mi );
+    (void) player;
 
-    input_thread_t *p_input_thread = p_mi->input.p_thread;
-    if( !p_input_thread )
-        return;
-    p_mi->input.p_thread = NULL;
+    libvlc_media_player_t *mp = data;
 
-    media_detach_preparsed_event( p_mi->p_md );
+    libvlc_event_t event;
 
-    var_DelCallback( p_input_thread, "can-seek",
-                     input_seekable_changed, p_mi );
-    var_DelCallback( p_input_thread, "can-pause",
-                    input_pausable_changed, p_mi );
-    var_DelCallback( p_input_thread, "program-scrambled",
-                    input_scrambled_changed, p_mi );
-    var_DelCallback( p_input_thread, "intf-event",
-                     input_event_changed, p_mi );
-    del_es_callbacks( p_input_thread, p_mi );
+    event.type = libvlc_MediaPlayerLengthChanged;
+    event.u.media_player_length_changed.new_length =
+        MS_FROM_VLC_TICK(new_length);
 
-    /* We owned this one */
-    input_Stop( p_input_thread );
-    input_Close( p_input_thread );
+    libvlc_event_send(&mp->event_manager, &event);
 }
 
-/*
- * Retrieve the input thread. Be sure to release the object
- * once you are done with it. (libvlc Internal)
- */
-input_thread_t *libvlc_get_input_thread( libvlc_media_player_t *p_mi )
+static int
+track_type_from_cat(enum es_format_category_e cat)
 {
-    input_thread_t *p_input_thread;
+    switch (cat)
+    {
+        case VIDEO_ES:
+            return libvlc_track_video;
+        case AUDIO_ES:
+            return libvlc_track_audio;
+        case SPU_ES:
+            return libvlc_track_text;
+        default:
+            return libvlc_track_unknown;
+    }
+}
 
-    assert( p_mi );
+static void
+on_track_list_changed(vlc_player_t *player, enum vlc_player_list_action action,
+                      const struct vlc_player_track *track, void *data)
+{
+    (void) player;
+
+    libvlc_media_player_t *mp = data;
 
-    lock_input(p_mi);
-    p_input_thread = p_mi->input.p_thread;
-    if( p_input_thread )
-        input_Hold(p_input_thread);
+    libvlc_event_t event;
+    if (action == VLC_PLAYER_LIST_ADDED)
+        event.type = libvlc_MediaPlayerESAdded;
+    else if (action == VLC_PLAYER_LIST_REMOVED)
+        event.type = libvlc_MediaPlayerESDeleted;
     else
-        libvlc_printerr( "No active input" );
-    unlock_input(p_mi);
+        /* no event to forward */
+        return;
 
-    return p_input_thread;
+    event.u.media_player_es_changed.i_type =
+        track_type_from_cat(track->fmt.i_cat);
+    event.u.media_player_es_changed.i_id = vlc_es_id_GetInputId(track->es_id);
+
+    libvlc_event_send(&mp->event_manager, &event);
 }
 
-/*
- * Set the internal state of the media_player. (media player Internal)
- *
- * Function will lock the media_player.
- */
-static void set_state( libvlc_media_player_t *p_mi, libvlc_state_t state,
-    bool b_locked )
+static void
+on_track_selection_changed(vlc_player_t *player, vlc_es_id_t *unselected_id,
+                           vlc_es_id_t *selected_id, void *data)
 {
-    if(!b_locked)
-        lock(p_mi);
-    p_mi->state = state;
+    (void) player;
+    (void) unselected_id;
 
-    libvlc_media_t *media = p_mi->p_md;
-    if (media)
-        libvlc_media_retain(media);
+    libvlc_media_player_t *mp = data;
 
-    if(!b_locked)
-        unlock(p_mi);
+    libvlc_event_t event;
+    event.type = libvlc_MediaPlayerESSelected;
 
-    if (media)
+    if (selected_id)
     {
-        // Also set the state of the corresponding media
-        // This is strictly for convenience.
-        libvlc_media_set_state(media, state);
-
-        libvlc_media_release(media);
+        enum es_format_category_e cat = vlc_es_id_GetCat(selected_id);
+        event.u.media_player_es_changed.i_type = track_type_from_cat(cat);
+        event.u.media_player_es_changed.i_id =
+            vlc_es_id_GetInputId(selected_id);
+        libvlc_event_send(&mp->event_manager, &event);
     }
 }
 
-static int
-input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
-                        vlc_value_t oldval, vlc_value_t newval,
-                        void * p_userdata )
-{
-    VLC_UNUSED(oldval);
-    VLC_UNUSED(p_this);
-    VLC_UNUSED(psz_cmd);
-    libvlc_media_player_t * p_mi = p_userdata;
-    libvlc_event_t event;
+static void
+on_program_list_changed(vlc_player_t *player,
+                        enum vlc_player_list_action action,
+                        const struct vlc_player_program *prgm, void* data)
+{
+    (void) action;
+    (void) prgm;
 
-    event.type = libvlc_MediaPlayerSeekableChanged;
-    event.u.media_player_seekable_changed.new_seekable = newval.b_bool;
+    libvlc_media_player_t *mp = data;
 
-    libvlc_event_send( &p_mi->event_manager, &event );
-    return VLC_SUCCESS;
-}
+    const struct vlc_player_program *selected =
+        vlc_player_GetSelectedProgram(player);
+    if (!selected)
+        return;
 
-static int
-input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
-                        vlc_value_t oldval, vlc_value_t newval,
-                        void * p_userdata )
-{
-    VLC_UNUSED(oldval);
-    VLC_UNUSED(p_this);
-    VLC_UNUSED(psz_cmd);
-    libvlc_media_player_t * p_mi = p_userdata;
     libvlc_event_t event;
+    event.type = libvlc_MediaPlayerScrambledChanged;
+    event.u.media_player_scrambled_changed.new_scrambled = selected->scrambled;
 
-    event.type = libvlc_MediaPlayerPausableChanged;
-    event.u.media_player_pausable_changed.new_pausable = newval.b_bool;
-
-    libvlc_event_send( &p_mi->event_manager, &event );
-    return VLC_SUCCESS;
+    libvlc_event_send(&mp->event_manager, &event);
 }
 
-static int
-input_scrambled_changed( vlc_object_t * p_this, char const * psz_cmd,
-                        vlc_value_t oldval, vlc_value_t newval,
-                        void * p_userdata )
-{
-    VLC_UNUSED(oldval);
-    VLC_UNUSED(p_this);
-    VLC_UNUSED(psz_cmd);
-    libvlc_media_player_t * p_mi = p_userdata;
-    libvlc_event_t event;
+static void
+on_program_selection_changed(vlc_player_t *player, int unselected_id,
+                             int selected_id, void *data)
+{
+    (void) unselected_id;
 
+    libvlc_media_player_t *mp = data;
+
+    if (selected_id == -1)
+        return;
+
+    const struct vlc_player_program *program =
+        vlc_player_GetSelectedProgram(player);
+    assert(program);
+
+    libvlc_event_t event;
     event.type = libvlc_MediaPlayerScrambledChanged;
-    event.u.media_player_scrambled_changed.new_scrambled = newval.b_bool;
+    event.u.media_player_scrambled_changed.new_scrambled = program->scrambled;
 
-    libvlc_event_send( &p_mi->event_manager, &event );
-    return VLC_SUCCESS;
+    libvlc_event_send(&mp->event_manager, &event);
 }
 
-static int
-input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
-                     vlc_value_t oldval, vlc_value_t newval,
-                     void * p_userdata )
+static void
+on_title_selection_changed(vlc_player_t *player,
+                           const struct vlc_player_title *new_title,
+                           size_t new_idx, void *data)
 {
-    VLC_UNUSED(oldval); VLC_UNUSED(psz_cmd);
-    input_thread_t * p_input = (input_thread_t *)p_this;
-    libvlc_media_player_t * p_mi = p_userdata;
+    (void) player;
+    (void) new_title;
+
+    libvlc_media_player_t *mp = data;
+
     libvlc_event_t event;
+    event.type = libvlc_MediaPlayerTitleChanged;
+    event.u.media_player_title_changed.new_title = new_idx;
 
-    assert( !strcmp( psz_cmd, "intf-event" ) );
+    libvlc_event_send(&mp->event_manager, &event);
+}
 
-    if( newval.i_int == INPUT_EVENT_STATE )
-    {
-        libvlc_state_t libvlc_state;
+static void
+on_chapter_selection_changed(vlc_player_t *player,
+                             const struct vlc_player_title *title,
+                             size_t title_idx,
+                             const struct vlc_player_chapter *new_chapter,
+                             size_t new_chapter_idx,
+                             void *data)
+{
+    (void) player;
+    (void) title;
+    (void) title_idx;
+    (void) new_chapter;
 
-        switch ( var_GetInteger( p_input, "state" ) )
-        {
-            case INIT_S:
-                libvlc_state = libvlc_NothingSpecial;
-                event.type = libvlc_MediaPlayerNothingSpecial;
-                break;
-            case OPENING_S:
-                libvlc_state = libvlc_Opening;
-                event.type = libvlc_MediaPlayerOpening;
-                break;
-            case PLAYING_S:
-                libvlc_state = libvlc_Playing;
-                event.type = libvlc_MediaPlayerPlaying;
-                break;
-            case PAUSE_S:
-                libvlc_state = libvlc_Paused;
-                event.type = libvlc_MediaPlayerPaused;
-                break;
-            case END_S:
-                libvlc_state = libvlc_Ended;
-                event.type = libvlc_MediaPlayerEndReached;
-                break;
-            case ERROR_S:
-                libvlc_state = libvlc_Error;
-                event.type = libvlc_MediaPlayerEncounteredError;
-                break;
-
-            default:
-                return VLC_SUCCESS;
-        }
+    libvlc_media_player_t *mp = data;
 
-        set_state( p_mi, libvlc_state, false );
-        libvlc_event_send( &p_mi->event_manager, &event );
-    }
-    else if( newval.i_int == INPUT_EVENT_DEAD )
-    {
-        libvlc_state_t libvlc_state = libvlc_Ended;
-        event.type = libvlc_MediaPlayerEndReached;
+    libvlc_event_t event;
+    event.type = libvlc_MediaPlayerChapterChanged;
+    event.u.media_player_chapter_changed.new_chapter = new_chapter_idx;
 
-        set_state( p_mi, libvlc_state, false );
-        libvlc_event_send( &p_mi->event_manager, &event );
-    }
-    else if( newval.i_int == INPUT_EVENT_POSITION )
-    {
-        if( var_GetInteger( p_input, "state" ) != PLAYING_S )
-            return VLC_SUCCESS; /* Don't send the position while stopped */
-
-        /* */
-        event.type = libvlc_MediaPlayerPositionChanged;
-        event.u.media_player_position_changed.new_position =
-                                          var_GetFloat( p_input, "position" );
-        libvlc_event_send( &p_mi->event_manager, &event );
-
-        /* */
-        event.type = libvlc_MediaPlayerTimeChanged;
-        event.u.media_player_time_changed.new_time =
-           from_mtime(var_GetInteger( p_input, "time" ));
-        libvlc_event_send( &p_mi->event_manager, &event );
-    }
-    else if( newval.i_int == INPUT_EVENT_LENGTH )
-    {
-        event.type = libvlc_MediaPlayerLengthChanged;
-        event.u.media_player_length_changed.new_length =
-           from_mtime(var_GetInteger( p_input, "length" ));
-        libvlc_event_send( &p_mi->event_manager, &event );
-    }
-    else if( newval.i_int == INPUT_EVENT_CACHE )
-    {
-        event.type = libvlc_MediaPlayerBuffering;
-        event.u.media_player_buffering.new_cache = (100 *
-            var_GetFloat( p_input, "cache" ));
-        libvlc_event_send( &p_mi->event_manager, &event );
-    }
-    else if( newval.i_int == INPUT_EVENT_VOUT )
-    {
-        vout_thread_t **pp_vout;
-        size_t i_vout;
-        if( input_Control( p_input, INPUT_GET_VOUTS, &pp_vout, &i_vout ) )
-        {
-            i_vout  = 0;
-        }
-        else
-        {
-            for( size_t i = 0; i < i_vout; i++ )
-                vout_Release(pp_vout[i]);
-            free( pp_vout );
-        }
+    libvlc_event_send(&mp->event_manager, &event);
+}
 
-        event.type = libvlc_MediaPlayerVout;
-        event.u.media_player_vout.new_count = i_vout;
-        libvlc_event_send( &p_mi->event_manager, &event );
-    }
-    else if ( newval.i_int == INPUT_EVENT_TITLE )
-    {
-        event.type = libvlc_MediaPlayerTitleChanged;
-        event.u.media_player_title_changed.new_title = var_GetInteger( p_input, "title" );
-        libvlc_event_send( &p_mi->event_manager, &event );
-    }
-    else if ( newval.i_int == INPUT_EVENT_CHAPTER )
-    {
-        event.type = libvlc_MediaPlayerChapterChanged;
-        event.u.media_player_chapter_changed.new_chapter = var_GetInteger( p_input, "chapter" );
-        libvlc_event_send( &p_mi->event_manager, &event );
-    }
-    else if ( newval.i_int == INPUT_EVENT_ES )
-    {
-        /* Send ESSelected events from this callback ("intf-event") and not
-         * from "audio-es", "video-es", "spu-es" callbacks. Indeed, these
-         * callbacks are not triggered when the input_thread changes an ES
-         * while this callback is. */
-        struct {
-            const char *psz_name;
-            const libvlc_track_type_t type;
-            int new_es;
-        } es_list[] = {
-            { "audio-es", libvlc_track_audio, ES_INIT },
-            { "video-es", libvlc_track_video, ES_INIT },
-            { "spu-es", libvlc_track_text, ES_INIT },
-        };
-        /* Check if an ES selection changed */
-        lock( p_mi );
-        for( size_t i = 0; i < ARRAY_SIZE( es_list ); ++i )
-        {
-            int current_es = var_GetInteger( p_input, es_list[i].psz_name );
-            if( current_es != p_mi->selected_es[i] )
-                es_list[i].new_es = p_mi->selected_es[i] = current_es;
-        }
-        unlock( p_mi );
+static void
+on_media_subitems_changed(vlc_player_t *player, input_item_t *media,
+                          input_item_node_t *new_subitems, void *data)
+{
+    (void) player;
 
-        /* Send the ESSelected event for each ES that were newly selected */
-        for( size_t i = 0; i < ARRAY_SIZE( es_list ); ++i )
-        {
-            if( es_list[i].new_es != ES_INIT )
-            {
-                event.type = libvlc_MediaPlayerESSelected;
-                event.u.media_player_es_changed.i_type = es_list[i].type;
-                event.u.media_player_es_changed.i_id = es_list[i].new_es;
-                libvlc_event_send( &p_mi->event_manager, &event );
-            }
-        }
-    }
+    libvlc_media_player_t *mp = data;
 
-    return VLC_SUCCESS;
+    input_item_t *current = mp->p_md ? mp->p_md->p_input_item : NULL;
+    if (media == current)
+        libvlc_media_add_subtree(mp->p_md, new_subitems);
 }
 
-static int track_type_from_name(const char *psz_name)
+static void
+on_cork_changed(vlc_player_t *player, unsigned cork_count, void *data)
 {
-   if( !strcmp( psz_name, "video-es" ) )
-       return libvlc_track_video;
-    else if( !strcmp( psz_name, "audio-es" ) )
-        return libvlc_track_audio;
-    else if( !strcmp( psz_name, "spu-es" ) )
-        return libvlc_track_text;
-    else
-        return libvlc_track_unknown;
+    (void) player;
+
+    libvlc_media_player_t *mp = data;
+
+    libvlc_event_t event;
+    event.type = cork_count ? libvlc_MediaPlayerCorked
+                            : libvlc_MediaPlayerUncorked;
+
+    libvlc_event_send(&mp->event_manager, &event);
 }
 
-static int input_es_changed( vlc_object_t *p_this,
-                             char const *psz_cmd,
-                             int action,
-                             vlc_value_t *p_val,
-                             void *p_userdata )
+static void
+on_vout_changed(vlc_player_t *player, enum vlc_player_vout_action action,
+                vout_thread_t *vout, void *data)
 {
-    VLC_UNUSED(p_this);
-    libvlc_media_player_t *mp = p_userdata;
+    (void) action;
+    (void) vout;
+
+    libvlc_media_player_t *mp = data;
+
+    size_t count;
+    vout_thread_t **vouts = vlc_player_vout_HoldAll(player, &count);
+    if (!vouts)
+        return;
+    for (size_t i = 0; i < count; ++i)
+        vout_Release(vouts[i]);
+    free(vouts);
+
     libvlc_event_t event;
+    event.type = libvlc_MediaPlayerVout;
+    event.u.media_player_vout.new_count = count;
 
-    /* Ignore the "Disable" element */
-    if (p_val && p_val->i_int < 0)
-        return VLC_EGENERIC;
+    libvlc_event_send(&mp->event_manager, &event);
+}
 
-    switch (action)
-    {
-    case VLC_VAR_ADDCHOICE:
-        event.type = libvlc_MediaPlayerESAdded;
-        break;
-    case VLC_VAR_DELCHOICE:
-    case VLC_VAR_CLEARCHOICES:
-        event.type = libvlc_MediaPlayerESDeleted;
-        break;
-    default:
-        return VLC_EGENERIC;
-    }
+// player aout callbacks
 
-    event.u.media_player_es_changed.i_type = track_type_from_name(psz_cmd);
+static void
+on_volume_changed(vlc_player_t *player, float new_volume, void *data)
+{
+    (void) player;
 
-    int i_id;
-    if (action != VLC_VAR_CLEARCHOICES)
-    {
-        if (!p_val)
-            return VLC_EGENERIC;
-        i_id = p_val->i_int;
-    }
-    else
-    {
-        /* -1 means all ES tracks of this type were deleted. */
-        i_id = -1;
-    }
-    event.u.media_player_es_changed.i_id = i_id;
+    libvlc_media_player_t *mp = data;
+
+    libvlc_event_t event;
+    event.type = libvlc_MediaPlayerAudioVolume;
+    event.u.media_player_audio_volume.volume = new_volume;
 
     libvlc_event_send(&mp->event_manager, &event);
+}
 
-    return VLC_SUCCESS;
+static void
+on_mute_changed(vlc_player_t *player, bool new_muted, void *data)
+{
+    (void) player;
+
+    libvlc_media_player_t *mp = data;
+
+    libvlc_event_t event;
+    event.type = new_muted ? libvlc_MediaPlayerMuted
+                           : libvlc_MediaPlayerUnmuted;
+
+    libvlc_event_send(&mp->event_manager, &event);
+}
+
+static void
+on_audio_device_changed(vlc_player_t *player, const char *device, void *data)
+{
+    (void) player;
+
+    libvlc_media_player_t *mp = data;
+
+    libvlc_event_t event;
+    event.type = libvlc_MediaPlayerAudioDevice;
+    event.u.media_player_audio_device.device = device;
+
+    libvlc_event_send(&mp->event_manager, &event);
 }
 
+static const struct vlc_player_cbs vlc_player_cbs = {
+    .on_current_media_changed = on_current_media_changed,
+    .on_state_changed = on_state_changed,
+    .on_error_changed = on_error_changed,
+    .on_buffering_changed = on_buffering_changed,
+    .on_capabilities_changed = on_capabilities_changed,
+    .on_position_changed = on_position_changed,
+    .on_length_changed = on_length_changed,
+    .on_track_list_changed = on_track_list_changed,
+    .on_track_selection_changed = on_track_selection_changed,
+    .on_program_list_changed = on_program_list_changed,
+    .on_program_selection_changed = on_program_selection_changed,
+    .on_title_selection_changed = on_title_selection_changed,
+    .on_chapter_selection_changed = on_chapter_selection_changed,
+    .on_media_subitems_changed = on_media_subitems_changed,
+    .on_cork_changed = on_cork_changed,
+    .on_vout_changed = on_vout_changed,
+};
+
+static const struct vlc_player_aout_cbs vlc_player_aout_cbs = {
+    .on_volume_changed = on_volume_changed,
+    .on_mute_changed = on_mute_changed,
+    .on_device_changed = on_audio_device_changed,
+};
+
 /**************************************************************************
  * Snapshot Taken Event.
  *
@@ -530,64 +511,33 @@ static int snapshot_was_taken(vlc_object_t *p_this, char const *psz_cmd,
     return VLC_SUCCESS;
 }
 
-static int corks_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
-                         vlc_value_t cur, void *opaque)
+static void input_item_preparsed_changed( const vlc_event_t *p_event,
+                                          void * user_data )
 {
-    libvlc_media_player_t *mp = (libvlc_media_player_t *)obj;
-
-    if (!old.i_int != !cur.i_int)
+    libvlc_media_t *p_md = user_data;
+    if( p_event->u.input_item_preparsed_changed.new_status & ITEM_PREPARSED )
     {
+        /* Send the event */
         libvlc_event_t event;
-
-        event.type = cur.i_int ? libvlc_MediaPlayerCorked
-                               : libvlc_MediaPlayerUncorked;
-        libvlc_event_send(&mp->event_manager, &event);
+        event.type = libvlc_MediaParsedChanged;
+        event.u.media_parsed_changed.new_status = libvlc_media_parsed_status_done;
+        libvlc_event_send( &p_md->event_manager, &event );
     }
-    VLC_UNUSED(name); VLC_UNUSED(opaque);
-    return VLC_SUCCESS;
-}
-
-static int audio_device_changed(vlc_object_t *obj, const char *name,
-                                vlc_value_t old, vlc_value_t cur, void *opaque)
-{
-    libvlc_media_player_t *mp = (libvlc_media_player_t *)obj;
-    libvlc_event_t event;
-
-    event.type = libvlc_MediaPlayerAudioDevice;
-    event.u.media_player_audio_device.device = cur.psz_string;
-    libvlc_event_send(&mp->event_manager, &event);
-    VLC_UNUSED(name); VLC_UNUSED(old); VLC_UNUSED(opaque);
-    return VLC_SUCCESS;
 }
 
-static int mute_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
-                        vlc_value_t cur, void *opaque)
+static void media_attach_preparsed_event( libvlc_media_t *p_md )
 {
-    libvlc_media_player_t *mp = (libvlc_media_player_t *)obj;
-
-    if (old.b_bool != cur.b_bool)
-    {
-        libvlc_event_t event;
-
-        event.type = cur.b_bool ? libvlc_MediaPlayerMuted
-                                : libvlc_MediaPlayerUnmuted;
-        libvlc_event_send(&mp->event_manager, &event);
-    }
-    VLC_UNUSED(name); VLC_UNUSED(opaque);
-    return VLC_SUCCESS;
+    vlc_event_attach( &p_md->p_input_item->event_manager,
+                      vlc_InputItemPreparsedChanged,
+                      input_item_preparsed_changed, p_md );
 }
 
-static int volume_changed(vlc_object_t *obj, const char *name, vlc_value_t old,
-                          vlc_value_t cur, void *opaque)
+static void media_detach_preparsed_event( libvlc_media_t *p_md )
 {
-    libvlc_media_player_t *mp = (libvlc_media_player_t *)obj;
-    libvlc_event_t event;
-
-    event.type = libvlc_MediaPlayerAudioVolume;
-    event.u.media_player_audio_volume.volume = cur.f_float;
-    libvlc_event_send(&mp->event_manager, &event);
-    VLC_UNUSED(name); VLC_UNUSED(old); VLC_UNUSED(opaque);
-    return VLC_SUCCESS;
+    vlc_event_detach( &p_md->p_input_item->event_manager,
+                      vlc_InputItemPreparsedChanged,
+                      input_item_preparsed_changed,
+                      p_md );
 }
 
 /**************************************************************************
@@ -745,33 +695,28 @@ libvlc_media_player_new( libvlc_instance_t *instance )
     }
 
     mp->p_md = NULL;
-    mp->state = libvlc_NothingSpecial;
     mp->p_libvlc_instance = instance;
-    mp->input.p_thread = NULL;
-    mp->input.p_renderer = NULL;
-    mp->input.p_resource = input_resource_New(VLC_OBJECT(mp));
-    if (unlikely(mp->input.p_resource == NULL))
-    {
-        vlc_object_delete(mp);
-        return NULL;
-    }
-    audio_output_t *aout = input_resource_GetAout(mp->input.p_resource);
-    if( aout != NULL )
-        input_resource_PutAout(mp->input.p_resource, aout);
+    /* use a reentrant lock to allow calling libvlc functions from callbacks */
+    mp->player = vlc_player_New(VLC_OBJECT(mp), VLC_PLAYER_LOCK_REENTRANT,
+                                NULL, NULL);
+    if (unlikely(!mp->player))
+        goto error1;
+
+    vlc_player_Lock(mp->player);
+
+    mp->listener = vlc_player_AddListener(mp->player, &vlc_player_cbs, mp);
+    if (unlikely(!mp->listener))
+        goto error2;
+
+    mp->aout_listener =
+        vlc_player_aout_AddListener(mp->player, &vlc_player_aout_cbs, mp);
+    if (unlikely(!mp->aout_listener))
+        goto error3;
 
-    vlc_viewpoint_init(&mp->viewpoint);
+    vlc_player_Unlock(mp->player);
 
-    var_Create (mp, "viewpoint", VLC_VAR_ADDRESS);
-    var_SetAddress( mp, "viewpoint", &mp->viewpoint );
-    vlc_mutex_init (&mp->input.lock);
     mp->i_refcount = 1;
     libvlc_event_manager_init(&mp->event_manager, mp);
-    vlc_mutex_init(&mp->object_lock);
-
-    var_AddCallback(mp, "corks", corks_changed, NULL);
-    var_AddCallback(mp, "audio-device", audio_device_changed, NULL);
-    var_AddCallback(mp, "mute", mute_changed, NULL);
-    var_AddCallback(mp, "volume", volume_changed, NULL);
 
     /* Snapshot initialization */
     /* Attach a var callback to the global object to provide the glue between
@@ -786,6 +731,15 @@ libvlc_media_player_new( libvlc_instance_t *instance )
 
     libvlc_retain(instance);
     return mp;
+
+error3:
+    vlc_player_RemoveListener(mp->player, mp->listener);
+error2:
+    vlc_player_Unlock(mp->player);
+    vlc_player_Delete(mp->player);
+error1:
+    vlc_object_delete(mp);
+    return NULL;
 }
 
 /**************************************************************************
@@ -802,6 +756,19 @@ libvlc_media_player_new_from_media( libvlc_media_t * p_md )
 
     libvlc_media_retain( p_md );
     p_mi->p_md = p_md;
+    media_attach_preparsed_event(p_md);
+
+    vlc_player_Lock(p_mi->player);
+    int ret = vlc_player_SetCurrentMedia(p_mi->player, p_md->p_input_item);
+    vlc_player_Unlock(p_mi->player);
+
+    if (ret != VLC_SUCCESS)
+    {
+        media_detach_preparsed_event(p_md);
+        libvlc_media_release(p_md);
+        p_mi->p_md = NULL;
+        return NULL;
+    }
 
     return p_mi;
 }
@@ -819,25 +786,15 @@ static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
     var_DelCallback( vlc_object_instance(p_mi),
                      "snapshot-file", snapshot_was_taken, p_mi );
 
-    /* Detach callback from the media player / input manager object */
-    var_DelCallback( p_mi, "volume", volume_changed, NULL );
-    var_DelCallback( p_mi, "mute", mute_changed, NULL );
-    var_DelCallback( p_mi, "audio-device", audio_device_changed, NULL );
-    var_DelCallback( p_mi, "corks", corks_changed, NULL );
-
-    /* No need for lock_input() because no other threads knows us anymore */
-    if( p_mi->input.p_thread )
-        release_input_thread(p_mi);
-    input_resource_Terminate( p_mi->input.p_resource );
-    input_resource_Release( p_mi->input.p_resource );
-    if( p_mi->input.p_renderer )
-        vlc_renderer_item_release( p_mi->input.p_renderer );
+    vlc_player_Lock(p_mi->player);
+    vlc_player_aout_RemoveListener(p_mi->player, p_mi->aout_listener);
+    vlc_player_RemoveListener(p_mi->player, p_mi->listener);
+    vlc_player_Unlock(p_mi->player);
 
-    vlc_mutex_destroy( &p_mi->input.lock );
+    vlc_player_Delete(p_mi->player);
 
     libvlc_event_manager_destroy(&p_mi->event_manager);
     libvlc_media_release( p_mi->p_md );
-    vlc_mutex_destroy( &p_mi->object_lock );
 
     vlc_http_cookie_jar_t *cookies = var_GetAddress( p_mi, "http-cookies" );
     if ( cookies )
@@ -861,9 +818,9 @@ void libvlc_media_player_release( libvlc_media_player_t *p_mi )
     bool destroy;
 
     assert( p_mi );
-    lock(p_mi);
+    vlc_player_Lock(p_mi->player);
     destroy = !--p_mi->i_refcount;
-    unlock(p_mi);
+    vlc_player_Unlock(p_mi->player);
 
     if( destroy )
         libvlc_media_player_destroy( p_mi );
@@ -878,9 +835,9 @@ void libvlc_media_player_retain( libvlc_media_player_t *p_mi )
 {
     assert( p_mi );
 
-    lock(p_mi);
+    vlc_player_Lock(p_mi->player);
     p_mi->i_refcount++;
-    unlock(p_mi);
+    vlc_player_Unlock(p_mi->player);
 }
 
 /**************************************************************************
@@ -892,38 +849,27 @@ void libvlc_media_player_set_media(
                             libvlc_media_player_t *p_mi,
                             libvlc_media_t *p_md )
 {
-    lock_input(p_mi);
+    vlc_player_Lock(p_mi->player);
 
-    release_input_thread( p_mi );
-
-    lock( p_mi );
-    set_state( p_mi, libvlc_NothingSpecial, true );
-    unlock_input( p_mi );
+    if (p_mi->p_md)
+        media_detach_preparsed_event(p_mi->p_md);
 
     libvlc_media_release( p_mi->p_md );
 
-    if( !p_md )
+    if( p_md )
     {
-        p_mi->p_md = NULL;
-        unlock(p_mi);
-        return; /* It is ok to pass a NULL md */
+        libvlc_media_retain( p_md );
+        media_attach_preparsed_event(p_md);
     }
-
-    libvlc_media_retain( p_md );
     p_mi->p_md = p_md;
 
+    vlc_player_SetCurrentMedia(p_mi->player, p_md->p_input_item);
+
     /* The policy here is to ignore that we were created using a different
      * libvlc_instance, because we don't really care */
     p_mi->p_libvlc_instance = p_md->p_libvlc_instance;
 
-    unlock(p_mi);
-
-    /* Send an event for the newly available media */
-    libvlc_event_t event;
-    event.type = libvlc_MediaPlayerMediaChanged;
-    event.u.media_player_media_changed.new_media = p_md;
-    libvlc_event_send( &p_mi->event_manager, &event );
-
+    vlc_player_Unlock(p_mi->player);
 }
 
 /**************************************************************************
@@ -934,11 +880,11 @@ libvlc_media_player_get_media( libvlc_media_player_t *p_mi )
 {
     libvlc_media_t *p_m;
 
-    lock( p_mi );
+    vlc_player_Lock(p_mi->player);
     p_m = p_mi->p_md;
     if( p_m )
         libvlc_media_retain( p_m );
-    unlock( p_mi );
+    vlc_player_Unlock(p_mi->player);
 
     return p_m;
 }
@@ -952,122 +898,43 @@ libvlc_media_player_event_manager( libvlc_media_player_t *p_mi )
     return &p_mi->event_manager;
 }
 
-static void add_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi )
-{
-    var_AddListCallback( p_input_thread, "video-es", input_es_changed, p_mi );
-    var_AddListCallback( p_input_thread, "audio-es", input_es_changed, p_mi );
-    var_AddListCallback( p_input_thread, "spu-es", input_es_changed, p_mi );
-}
-
-static void del_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi )
-{
-    var_DelListCallback( p_input_thread, "video-es", input_es_changed, p_mi );
-    var_DelListCallback( p_input_thread, "audio-es", input_es_changed, p_mi );
-    var_DelListCallback( p_input_thread, "spu-es", input_es_changed, p_mi );
-}
-
-static void on_input_event(input_thread_t *input,
-                           const struct vlc_input_event *event, void *userdata)
-{
-    if (event->type == INPUT_EVENT_SUBITEMS)
-    {
-        libvlc_media_player_t *media_player = userdata;
-        libvlc_media_t *media = media_player->p_md;
-        libvlc_media_add_subtree(media, event->subitems);
-    }
-
-    input_LegacyEvents(input, event, userdata);
-}
-
 /**************************************************************************
  * Tell media player to start playing.
  **************************************************************************/
 int libvlc_media_player_play( libvlc_media_player_t *p_mi )
 {
-    lock_input( p_mi );
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    input_thread_t *p_input_thread = p_mi->input.p_thread;
-    if( p_input_thread )
+    int ret = vlc_player_Start(player);
+    if (ret == VLC_SUCCESS)
     {
-        /* A thread already exists, send it a play message */
-        var_SetInteger( p_input_thread, "state", PLAYING_S );
-        unlock_input( p_mi );
-        return 0;
+        if (vlc_player_IsPaused(player))
+            vlc_player_Resume(player);
     }
 
-    /* Ignore previous exception */
-    lock(p_mi);
-
-    if( !p_mi->p_md )
-    {
-        unlock(p_mi);
-        unlock_input( p_mi );
-        libvlc_printerr( "No associated media descriptor" );
-        return -1;
-    }
-
-    for( size_t i = 0; i < ARRAY_SIZE( p_mi->selected_es ); ++i )
-        p_mi->selected_es[i] = ES_INIT;
-
-    media_attach_preparsed_event( p_mi->p_md );
-
-    p_input_thread = input_Create( p_mi, on_input_event, p_mi,
-                                   p_mi->p_md->p_input_item,
-                                   p_mi->input.p_resource,
-                                   p_mi->input.p_renderer );
-    unlock(p_mi);
-    if( !p_input_thread )
-    {
-        unlock_input(p_mi);
-        media_detach_preparsed_event( p_mi->p_md );
-        libvlc_printerr( "Not enough memory" );
-        return -1;
-    }
-
-    input_LegacyVarInit( p_input_thread );
-    var_AddCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
-    var_AddCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
-    var_AddCallback( p_input_thread, "program-scrambled", input_scrambled_changed, p_mi );
-    var_AddCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
-    add_es_callbacks( p_input_thread, p_mi );
-
-    if( input_Start( p_input_thread ) )
-    {
-        unlock_input(p_mi);
-        del_es_callbacks( p_input_thread, p_mi );
-        var_DelCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
-        var_DelCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
-        var_DelCallback( p_input_thread, "program-scrambled", input_scrambled_changed, p_mi );
-        var_DelCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
-        input_Close( p_input_thread );
-        media_detach_preparsed_event( p_mi->p_md );
-        libvlc_printerr( "Input initialization failure" );
-        return -1;
-    }
-    p_mi->input.p_thread = p_input_thread;
-    unlock_input(p_mi);
-    return 0;
+    vlc_player_Unlock(player);
+    return ret;
 }
 
 void libvlc_media_player_set_pause( libvlc_media_player_t *p_mi, int paused )
 {
-    input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi );
-    if( !p_input_thread )
-        return;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    if( paused )
+    if (paused)
     {
-        if( libvlc_media_player_can_pause( p_mi ) )
-            var_SetInteger( p_input_thread, "state", PAUSE_S );
+        if (vlc_player_CanPause(player))
+            vlc_player_Pause(player);
         else
-            input_Stop( p_input_thread );
+            vlc_player_Stop(player);
     }
     else
     {
-        var_SetInteger( p_input_thread, "state", PLAYING_S );
+        vlc_player_Resume(player);
     }
 
-    input_Release(p_input_thread);
+    vlc_player_Unlock(player);
 }
 
 /**************************************************************************
@@ -1075,7 +942,12 @@ void libvlc_media_player_set_pause( libvlc_media_player_t *p_mi, int paused )
  **************************************************************************/
 void libvlc_media_player_pause( libvlc_media_player_t *p_mi )
 {
-    libvlc_media_player_set_pause( p_mi, libvlc_media_player_is_playing( p_mi ) );
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
+
+    vlc_player_TogglePause(player);
+
+    vlc_player_Unlock(player);
 }
 
 /**************************************************************************
@@ -1083,8 +955,13 @@ void libvlc_media_player_pause( libvlc_media_player_t *p_mi )
  **************************************************************************/
 bool libvlc_media_player_is_playing(libvlc_media_player_t *p_mi)
 {
-    libvlc_state_t state = libvlc_media_player_get_state( p_mi );
-    return libvlc_Playing == state;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
+
+    bool ret = vlc_player_IsStarted(player) && !vlc_player_IsPaused(player);
+
+    vlc_player_Unlock(player);
+    return ret;
 }
 
 /**************************************************************************
@@ -1092,41 +969,24 @@ bool libvlc_media_player_is_playing(libvlc_media_player_t *p_mi)
  **************************************************************************/
 void libvlc_media_player_stop( libvlc_media_player_t *p_mi )
 {
-    lock_input(p_mi);
-    release_input_thread( p_mi ); /* This will stop the input thread */
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    /* Force to go to stopped state, in case we were in Ended, or Error
-     * state. */
-    if( p_mi->state != libvlc_Stopped )
-    {
-        set_state( p_mi, libvlc_Stopped, false );
-
-        /* Construct and send the event */
-        libvlc_event_t event;
-        event.type = libvlc_MediaPlayerStopped;
-        libvlc_event_send( &p_mi->event_manager, &event );
-    }
+    vlc_player_Stop(player);
 
-    input_resource_Terminate( p_mi->input.p_resource );
-    unlock_input(p_mi);
+    vlc_player_Unlock(player);
 }
 
 int libvlc_media_player_set_renderer( libvlc_media_player_t *p_mi,
                                       libvlc_renderer_item_t *p_litem )
 {
-    vlc_renderer_item_t *p_item =
-        p_litem ? libvlc_renderer_item_to_vlc( p_litem ) : NULL;
-
-    lock_input( p_mi );
-    input_thread_t *p_input_thread = p_mi->input.p_thread;
-    if( p_input_thread )
-        input_Control( p_input_thread, INPUT_SET_RENDERER, p_item );
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    if( p_mi->input.p_renderer )
-        vlc_renderer_item_release( p_mi->input.p_renderer );
-    p_mi->input.p_renderer = p_item ? vlc_renderer_item_hold( p_item ) : NULL;
-    unlock_input( p_mi );
+    vlc_renderer_item_t *renderer = libvlc_renderer_item_to_vlc(p_litem);
+    vlc_player_SetRenderer(player, renderer);
 
+    vlc_player_Unlock(player);
     return 0;
 }
 
@@ -1364,16 +1224,12 @@ void libvlc_audio_set_callbacks( libvlc_media_player_t *mp,
     var_SetAddress( mp, "amem-drain", drain_cb );
     var_SetAddress( mp, "amem-data", opaque );
     var_SetString( mp, "aout", "amem,none" );
-
-    input_resource_ResetAout(mp->input.p_resource);
 }
 
 void libvlc_audio_set_volume_callback( libvlc_media_player_t *mp,
                                        libvlc_audio_set_volume_cb cb )
 {
     var_SetAddress( mp, "amem-set-volume", cb );
-
-    input_resource_ResetAout(mp->input.p_resource);
 }
 
 void libvlc_audio_set_format_callbacks( libvlc_media_player_t *mp,
@@ -1382,8 +1238,6 @@ void libvlc_audio_set_format_callbacks( libvlc_media_player_t *mp,
 {
     var_SetAddress( mp, "amem-setup", setup );
     var_SetAddress( mp, "amem-cleanup", cleanup );
-
-    input_resource_ResetAout(mp->input.p_resource);
 }
 
 void libvlc_audio_set_format( libvlc_media_player_t *mp, const char *format,
@@ -1392,8 +1246,6 @@ void libvlc_audio_set_format( libvlc_media_player_t *mp, const char *format,
     var_SetString( mp, "amem-format", format );
     var_SetInteger( mp, "amem-rate", rate );
     var_SetInteger( mp, "amem-channels", channels );
-
-    input_resource_ResetAout(mp->input.p_resource);
 }
 
 
@@ -1403,185 +1255,169 @@ void libvlc_audio_set_format( libvlc_media_player_t *mp, const char *format,
 libvlc_time_t libvlc_media_player_get_length(
                              libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread;
-    libvlc_time_t i_time;
-
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if( !p_input_thread )
-        return -1;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    i_time = from_mtime(var_GetInteger( p_input_thread, "length" ));
-    input_Release(p_input_thread);
+    vlc_tick_t length = vlc_player_GetLength(player);
+    libvlc_time_t i_time = from_mtime(length);
 
+    vlc_player_Unlock(player);
     return i_time;
 }
 
 libvlc_time_t libvlc_media_player_get_time( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread;
-    libvlc_time_t i_time;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if( !p_input_thread )
-        return -1;
+    vlc_tick_t tick = vlc_player_GetTime(player);
+    libvlc_time_t i_time = from_mtime(tick);
 
-    i_time = from_mtime(var_GetInteger( p_input_thread , "time" ));
-    input_Release(p_input_thread);
+    vlc_player_Unlock(player);
     return i_time;
 }
 
 int libvlc_media_player_set_time( libvlc_media_player_t *p_mi,
                                    libvlc_time_t i_time, bool b_fast )
 {
-    input_thread_t *p_input_thread;
+    vlc_tick_t tick = to_mtime(i_time);
 
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if( !p_input_thread )
-        return -1;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
+
+    enum vlc_player_seek_speed speed = b_fast ? VLC_PLAYER_SEEK_FAST
+                                              : VLC_PLAYER_SEEK_PRECISE;
+    vlc_player_SeekByTime(player, tick, speed, VLC_PLAYER_WHENCE_ABSOLUTE);
 
-    input_SetTime( p_input_thread, to_mtime(i_time), b_fast );
-    input_Release(p_input_thread);
+    vlc_player_Unlock(player);
+
+    /* may not fail anymore, keep int not to break the API */
     return 0;
 }
 
 int libvlc_media_player_set_position( libvlc_media_player_t *p_mi,
                                        float position, bool b_fast )
 {
-    input_thread_t *p_input_thread;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if( !p_input_thread )
-        return -1;
+    enum vlc_player_seek_speed speed = b_fast ? VLC_PLAYER_SEEK_FAST
+                                              : VLC_PLAYER_SEEK_PRECISE;
+    vlc_player_SeekByPos(player, position, speed, VLC_PLAYER_WHENCE_ABSOLUTE);
+
+    vlc_player_Unlock(player);
 
-    input_SetPosition( p_input_thread, position, b_fast );
-    input_Release(p_input_thread);
+    /* may not fail anymore, keep int not to break the API */
     return 0;
 }
 
 float libvlc_media_player_get_position( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread;
-    float f_position;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if( !p_input_thread )
-        return -1.0;
-
-    f_position = var_GetFloat( p_input_thread, "position" );
-    input_Release(p_input_thread);
+    float f_position = vlc_player_GetPosition(player);
 
+    vlc_player_Unlock(player);
     return f_position;
 }
 
 void libvlc_media_player_set_chapter( libvlc_media_player_t *p_mi,
                                       int chapter )
 {
-    input_thread_t *p_input_thread;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if( !p_input_thread )
-        return;
+    vlc_player_SelectChapterIdx(player, chapter);
 
-    var_SetInteger( p_input_thread, "chapter", chapter );
-    input_Release(p_input_thread);
+    vlc_player_Unlock(player);
 }
 
 int libvlc_media_player_get_chapter( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread;
-    int i_chapter;
-
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if( !p_input_thread )
-        return -1;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    i_chapter = var_GetInteger( p_input_thread, "chapter" );
-    input_Release(p_input_thread);
+    ssize_t i_chapter = vlc_player_GetSelectedChapterIdx(player);
 
+    vlc_player_Unlock(player);
     return i_chapter;
 }
 
 int libvlc_media_player_get_chapter_count( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread;
-    size_t val;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if( !p_input_thread )
-        return -1;
-
-    int i_ret = var_Change( p_input_thread, "chapter", VLC_VAR_CHOICESCOUNT, &val );
-    input_Release(p_input_thread);
+    const struct vlc_player_title *title = vlc_player_GetSelectedTitle(player);
+    int ret = title ? (int) title->chapter_count : -1;
 
-    return i_ret == VLC_SUCCESS ? (ssize_t)val : -1;
+    vlc_player_Unlock(player);
+    return ret;
 }
 
 int libvlc_media_player_get_chapter_count_for_title(
                                  libvlc_media_player_t *p_mi,
                                  int i_title )
 {
-    size_t val;
+    assert(i_title >= 0);
+    size_t idx = i_title;
+    int ret = -1;
 
-    input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
-    if( !p_input_thread )
-        return -1;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
+
+    vlc_player_title_list *titles = vlc_player_GetTitleList(player);
+    if (!titles)
+        goto end;
+
+    size_t titles_count = vlc_player_title_list_GetCount(titles);
+    if (idx < titles_count)
+       goto end;
 
-    char psz_name[sizeof ("title ") + 3 * sizeof (int)];
-    sprintf( psz_name, "title %2u", i_title );
+    const struct vlc_player_title *title =
+        vlc_player_title_list_GetAt(titles, idx);
+    assert(title);
 
-    int i_ret = var_Change( p_input_thread, psz_name, VLC_VAR_CHOICESCOUNT, &val );
-    input_Release(p_input_thread);
+    ret = title->chapter_count;
 
-    return i_ret == VLC_SUCCESS ? (ssize_t)val : -1;
+end:
+    vlc_player_Unlock(player);
+    return ret;
 }
 
 void libvlc_media_player_set_title( libvlc_media_player_t *p_mi,
                                     int i_title )
 {
-    input_thread_t *p_input_thread;
-
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if( !p_input_thread )
-        return;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    var_SetInteger( p_input_thread, "title", i_title );
-    input_Release(p_input_thread);
+    vlc_player_SelectTitleIdx(player, i_title);
 
-    //send event
-    libvlc_event_t event;
-    event.type = libvlc_MediaPlayerTitleChanged;
-    event.u.media_player_title_changed.new_title = i_title;
-    libvlc_event_send( &p_mi->event_manager, &event );
+    vlc_player_Unlock(player);
 }
 
 int libvlc_media_player_get_title( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread;
-    int i_title;
-
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if( !p_input_thread )
-        return -1;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    i_title = var_GetInteger( p_input_thread, "title" );
-    input_Release(p_input_thread);
+    ssize_t i_title = vlc_player_GetSelectedTitleIdx(player);
 
+    vlc_player_Unlock(player);
     return i_title;
 }
 
 int libvlc_media_player_get_title_count( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread;
-    size_t val;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if( !p_input_thread )
-        return -1;
-
-    int i_ret = var_Change( p_input_thread, "title", VLC_VAR_CHOICESCOUNT, &val );
-    input_Release(p_input_thread);
+    vlc_player_title_list *titles = vlc_player_GetTitleList(player);
+    int ret = titles ? (int) vlc_player_title_list_GetCount(titles) : -1;
 
-    return i_ret == VLC_SUCCESS ? (ssize_t)val : -1;
+    vlc_player_Unlock(player);
+    return ret;
 }
 
 int libvlc_media_player_get_full_title_descriptions( libvlc_media_player_t *p_mi,
@@ -1589,49 +1425,46 @@ int libvlc_media_player_get_full_title_descriptions( libvlc_media_player_t *p_mi
 {
     assert( p_mi );
 
-    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
+    int ret = -1;
 
-    if( !p_input_thread )
-        return -1;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    input_title_t **p_input_title;
-    int count;
+    vlc_player_title_list *titles = vlc_player_GetTitleList(player);
+    if (!titles)
+        goto end;
 
-    /* fetch data */
-    int ret = input_Control( p_input_thread, INPUT_GET_FULL_TITLE_INFO,
-                             &p_input_title, &count );
-    input_Release(p_input_thread);
-    if( ret != VLC_SUCCESS )
-        return -1;
+    size_t count = vlc_player_title_list_GetCount(titles);
 
-    libvlc_title_description_t **titles = vlc_alloc( count, sizeof (*titles) );
-    if( count > 0 && unlikely(titles == NULL) )
-        return -1;
+    libvlc_title_description_t **descs = vlc_alloc(count, sizeof(*descs));
+    if (count > 0 && !descs)
+        goto end;
 
-    /* fill array */
-    for( int i = 0; i < count; i++)
+    for (size_t i = 0; i < count; i++)
     {
-        libvlc_title_description_t *title = malloc( sizeof (*title) );
-        if( unlikely(title == NULL) )
+        const struct vlc_player_title *title =
+            vlc_player_title_list_GetAt(titles, i);
+        libvlc_title_description_t *desc = malloc(sizeof(*desc));
+        if (!desc)
         {
-            libvlc_title_descriptions_release( titles, i );
-            return -1;
+            libvlc_title_descriptions_release(descs, i);
+            goto end;
         }
-        titles[i] = title;
+
+        descs[i] = desc;
 
         /* we want to return milliseconds to match the rest of the API */
-        title->i_duration = MS_FROM_VLC_TICK(p_input_title[i]->i_length);
-        title->i_flags = p_input_title[i]->i_flags;
-        if( p_input_title[i]->psz_name )
-            title->psz_name = strdup( p_input_title[i]->psz_name );
-        else
-            title->psz_name = NULL;
-        vlc_input_title_Delete( p_input_title[i] );
+        desc->i_duration = MS_FROM_VLC_TICK(title->length);
+        desc->i_flags = title->flags;
+        desc->psz_name = title->name ? strdup(title->name) : NULL;
     }
-    free( p_input_title );
 
-    *pp_titles = titles;
-    return count;
+    ret = count;
+    *pp_titles = descs;
+
+end:
+    vlc_player_Unlock(player);
+    return ret;
 }
 
 void libvlc_title_descriptions_release( libvlc_title_description_t **p_titles,
@@ -1654,82 +1487,56 @@ int libvlc_media_player_get_full_chapter_descriptions( libvlc_media_player_t *p_
 {
     assert( p_mi );
 
-    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
+    int ret = -1;
 
-    if( !p_input_thread )
-        return -1;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    seekpoint_t **p_seekpoint = NULL;
-    input_title_t **pp_title, *p_title = NULL;
-    int i_title_count = 0, ci_chapter_count = 0;
-    int ret = input_Control( p_input_thread, INPUT_GET_FULL_TITLE_INFO, &pp_title,
-                             &i_title_count );
-    input_Release(p_input_thread);
+    vlc_player_title_list *titles = vlc_player_GetTitleList(player);
+    if (!titles)
+        goto end;
 
-    if( ret != VLC_SUCCESS || i_chapters_of_title >= i_title_count )
-        goto error;
+    size_t titles_count = vlc_player_title_list_GetCount(titles);
+    if (i_chapters_of_title < (int) titles_count)
+       goto end;
 
-    p_title = pp_title[i_chapters_of_title];
-    int64_t i_title_duration = MS_FROM_VLC_TICK(p_title->i_length);
-    p_seekpoint = p_title->seekpoint;
-    ci_chapter_count = p_title->i_seekpoint;
+    const struct vlc_player_title *title =
+        vlc_player_title_list_GetAt(titles, i_chapters_of_title);
+    assert(title);
 
-    if( ci_chapter_count == 0 || p_seekpoint == NULL)
-        goto error;
+    size_t i_chapter_count = title->chapter_count;
 
-    *pp_chapters = calloc( ci_chapter_count, sizeof(**pp_chapters) );
-    if( !*pp_chapters )
-    {
-        goto error;
-    }
+    libvlc_chapter_description_t **descs =
+        vlc_alloc(i_chapter_count, sizeof(*descs));
+    if (i_chapter_count > 0 && !descs)
+        goto end;
 
-    /* fill array */
-    for( int i = 0; i < ci_chapter_count; ++i )
+    for (size_t i = 0; i < i_chapter_count; i++)
     {
-        libvlc_chapter_description_t *p_chapter = malloc( sizeof(*p_chapter) );
-        if( unlikely(p_chapter == NULL) )
+        const struct vlc_player_chapter *chapter = &title->chapters[i];
+        libvlc_chapter_description_t *desc = malloc(sizeof(*desc));
+        if (!desc)
         {
-            goto error;
+            libvlc_chapter_descriptions_release(descs, i);
+            goto end;
         }
-        (*pp_chapters)[i] = p_chapter;
-
-        p_chapter->i_time_offset = MS_FROM_VLC_TICK( p_seekpoint[i]->i_time_offset );
 
-        if( i < ci_chapter_count - 1 )
-        {
-            p_chapter->i_duration = MS_FROM_VLC_TICK( p_seekpoint[i + 1]->i_time_offset ) -
-                                    p_chapter->i_time_offset;
-        }
-        else
-        {
-            if ( i_title_duration )
-                p_chapter->i_duration = i_title_duration - p_chapter->i_time_offset;
-            else
-                p_chapter->i_duration = 0;
-        }
+        descs[i] = desc;
 
-        if( p_seekpoint[i]->psz_name )
-        {
-            p_chapter->psz_name = strdup( p_seekpoint[i]->psz_name );
-        }
-        else
-        {
-            p_chapter->psz_name = NULL;
-        }
-        vlc_seekpoint_Delete( p_seekpoint[i] );
-        p_seekpoint[i] = NULL;
+        vlc_tick_t chapter_end = i < i_chapter_count - 1
+                               ? title->chapters[i + 1].time
+                               : title->length;
+        desc->i_time_offset = MS_FROM_VLC_TICK(chapter->time);
+        desc->psz_name = chapter->name ? strdup(chapter->name) : NULL;
+        desc->i_duration = MS_FROM_VLC_TICK(chapter_end) - desc->i_time_offset;
     }
 
-    free( p_seekpoint );
-    return ci_chapter_count;
+    ret = i_chapter_count;
+    *pp_chapters = descs;
 
-error:
-    if( *pp_chapters )
-        libvlc_chapter_descriptions_release( *pp_chapters, ci_chapter_count );
-    for( int i = 0; i < i_title_count; i++ )
-        vlc_input_title_Delete( pp_title[i] );
-    free( pp_title ) ;
-    return -1;
+end:
+    vlc_player_Unlock(player);
+    return ret;
 }
 
 void libvlc_chapter_descriptions_release( libvlc_chapter_description_t **p_chapters,
@@ -1748,113 +1555,116 @@ void libvlc_chapter_descriptions_release( libvlc_chapter_description_t **p_chapt
 
 void libvlc_media_player_next_chapter( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if( !p_input_thread )
-        return;
-
-    int i_type = var_Type( p_input_thread, "next-chapter" );
-    var_TriggerCallback( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
-                            "next-chapter":"next-title" );
+    vlc_player_SelectNextChapter(player);
 
-    input_Release(p_input_thread);
+    vlc_player_Unlock(player);
 }
 
 void libvlc_media_player_previous_chapter( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread;
-
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if( !p_input_thread )
-        return;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    int i_type = var_Type( p_input_thread, "next-chapter" );
-    var_TriggerCallback( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
-                            "prev-chapter":"prev-title" );
+    vlc_player_SelectPrevChapter(player);
 
-    input_Release(p_input_thread);
+    vlc_player_Unlock(player);
 }
 
 int libvlc_media_player_set_rate( libvlc_media_player_t *p_mi, float rate )
 {
-    var_SetFloat (p_mi, "rate", rate);
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
-    if( !p_input_thread )
-        return 0;
-    var_SetFloat( p_input_thread, "rate", rate );
-    input_Release(p_input_thread);
+    vlc_player_ChangeRate(player, rate);
+
+    vlc_player_Unlock(player);
     return 0;
 }
 
 float libvlc_media_player_get_rate( libvlc_media_player_t *p_mi )
 {
-    return var_GetFloat (p_mi, "rate");
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
+
+    float rate = vlc_player_GetRate(player);
+
+    vlc_player_Unlock(player);
+    return rate;
 }
 
 libvlc_state_t libvlc_media_player_get_state( libvlc_media_player_t *p_mi )
 {
-    lock(p_mi);
-    libvlc_state_t state = p_mi->state;
-    unlock(p_mi);
-    return state;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
+
+    enum vlc_player_error error = vlc_player_GetError(player);
+    enum vlc_player_state state = vlc_player_GetState(player);
+
+    vlc_player_Unlock(player);
+
+    if (error != VLC_PLAYER_ERROR_NONE)
+        return libvlc_Error;
+    switch (state) {
+        case VLC_PLAYER_STATE_STOPPED:
+            return libvlc_Stopped;
+        case VLC_PLAYER_STATE_STOPPING:
+            return libvlc_Ended;
+        case VLC_PLAYER_STATE_STARTED:
+            return libvlc_Opening;
+        case VLC_PLAYER_STATE_PLAYING:
+            return libvlc_Playing;
+        case VLC_PLAYER_STATE_PAUSED:
+            return libvlc_Paused;
+        default:
+            vlc_assert_unreachable();
+    }
 }
 
 bool libvlc_media_player_is_seekable(libvlc_media_player_t *p_mi)
 {
-    input_thread_t *p_input_thread;
-    bool b_seekable;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if ( !p_input_thread )
-        return false;
-    b_seekable = var_GetBool( p_input_thread, "can-seek" );
-    input_Release(p_input_thread);
+    bool b_seekable = vlc_player_CanSeek(player);
 
+    vlc_player_Unlock(player);
     return b_seekable;
 }
 
 void libvlc_media_player_navigate( libvlc_media_player_t* p_mi,
                                    unsigned navigate )
 {
-    static const int map[] =
+    static const enum vlc_player_nav map[] =
     {
-        INPUT_NAV_ACTIVATE, INPUT_NAV_UP, INPUT_NAV_DOWN,
-        INPUT_NAV_LEFT, INPUT_NAV_RIGHT, INPUT_NAV_POPUP,
+        VLC_PLAYER_NAV_ACTIVATE, VLC_PLAYER_NAV_UP, VLC_PLAYER_NAV_DOWN,
+        VLC_PLAYER_NAV_LEFT, VLC_PLAYER_NAV_RIGHT, VLC_PLAYER_NAV_POPUP,
     };
 
     if( navigate >= sizeof(map) / sizeof(map[0]) )
       return;
 
-    input_thread_t *p_input = libvlc_get_input_thread ( p_mi );
-    if ( p_input == NULL )
-      return;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
+
+    vlc_player_Navigate(player, map[navigate]);
 
-    input_Control( p_input, map[navigate], NULL );
-    input_Release(p_input);
+    vlc_player_Unlock(player);
 }
 
 /* internal function, used by audio, video */
 libvlc_track_description_t *
         libvlc_get_track_description( libvlc_media_player_t *p_mi,
-                                      const char *psz_variable )
+                                      enum es_format_category_e cat )
 {
-    input_thread_t *p_input = libvlc_get_input_thread( p_mi );
-    libvlc_track_description_t *ret, **pp = &ret;
-
-    if( !p_input )
-        return NULL;
-
-    vlc_value_t *val_list;
-    char **text_list;
-    size_t count;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    int i_ret = var_Change( p_input, psz_variable, VLC_VAR_GETCHOICES,
-                            &count, &val_list, &text_list );
-    if( i_ret != VLC_SUCCESS )
-        return NULL;
+    libvlc_track_description_t *ret, **pp = &ret;
 
+    size_t count = vlc_player_GetTrackCount(player, cat);
     for (size_t i = 0; i < count; i++)
     {
         libvlc_track_description_t *tr = malloc(sizeof (*tr));
@@ -1864,17 +1674,23 @@ libvlc_track_description_t *
             continue;
         }
 
+        const struct vlc_player_track *track =
+            vlc_player_GetTrackAt(player, cat, i);
+
         *pp = tr;
-        tr->i_id = val_list[i].i_int;
-        tr->psz_name = text_list[i];
+        tr->i_id = vlc_es_id_GetInputId(track->es_id);
+        tr->psz_name = strdup(track->name);
+        if (unlikely(!tr->psz_name))
+        {
+            free(tr);
+            continue;
+        }
         pp = &tr->p_next;
     }
 
     *pp = NULL;
-    free(val_list);
-    free(text_list);
-    input_Release(p_input);
 
+    vlc_player_Unlock(player);
     return ret;
 }
 
@@ -1894,40 +1710,42 @@ void libvlc_track_description_list_release( libvlc_track_description_t *p_td )
 
 bool libvlc_media_player_can_pause(libvlc_media_player_t *p_mi)
 {
-    input_thread_t *p_input_thread;
-    bool b_can_pause;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if ( !p_input_thread )
-        return false;
-    b_can_pause = var_GetBool( p_input_thread, "can-pause" );
-    input_Release(p_input_thread);
+    bool b_can_pause = vlc_player_CanPause(player);
 
+    vlc_player_Unlock(player);
     return b_can_pause;
 }
 
 bool libvlc_media_player_program_scrambled(libvlc_media_player_t *p_mi)
 {
-    input_thread_t *p_input_thread;
-    bool b_program_scrambled;
+    bool b_program_scrambled = false;
 
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if ( !p_input_thread )
-        return false;
-    b_program_scrambled = var_GetBool( p_input_thread, "program-scrambled" );
-    input_Release(p_input_thread);
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
+
+    const struct vlc_player_program *program =
+        vlc_player_GetSelectedProgram(player);
+    if (!program)
+        goto end;
 
+    b_program_scrambled = program->scrambled;
+
+    vlc_player_Unlock(player);
+end:
     return b_program_scrambled;
 }
 
 void libvlc_media_player_next_frame( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
-    if( p_input_thread != NULL )
-    {
-        var_TriggerCallback( p_input_thread, "frame-next" );
-        input_Release(p_input_thread);
-    }
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
+
+    vlc_player_NextVideoFrame(player);
+
+    vlc_player_Unlock(player);
 }
 
 /**
@@ -1966,26 +1784,18 @@ int libvlc_media_player_add_slave( libvlc_media_player_t *p_mi,
                                    libvlc_media_slave_type_t i_type,
                                    const char *psz_uri, bool b_select )
 {
-    input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    if( p_input_thread == NULL )
-    {
-        libvlc_media_t *p_media = libvlc_media_player_get_media( p_mi );
-        if( p_media == NULL )
-            return -1;
+    enum es_format_category_e cat = i_type == libvlc_media_slave_type_subtitle
+                                  ? SPU_ES
+                                  : AUDIO_ES;
 
-        int i_ret = libvlc_media_slaves_add( p_media, i_type, 4, psz_uri );
-        libvlc_media_release( p_media );
-        return i_ret;
-    }
-    else
-    {
-        int i_ret = input_AddSlave( p_input_thread, (enum slave_type) i_type,
-                                    psz_uri, b_select, false, false );
-        input_Release(p_input_thread);
+    int ret = vlc_player_AddAssociatedMedia(player, cat, psz_uri, b_select,
+                                            false, false);
 
-        return i_ret == VLC_SUCCESS ? 0 : -1;
-    }
+    vlc_player_Unlock(player);
+    return ret;
 }
 
 /**
@@ -2018,7 +1828,7 @@ int libvlc_media_player_set_equalizer( libvlc_media_player_t *p_mi, libvlc_equal
     }
     var_SetString( p_mi, "audio-filter", p_equalizer ? "equalizer" : "" );
 
-    audio_output_t *p_aout = input_resource_HoldAout( p_mi->input.p_resource );
+    audio_output_t *p_aout = vlc_player_aout_Hold( p_mi->player );
     if( p_aout != NULL )
     {
         if( p_equalizer != NULL )
diff --git a/lib/media_player_internal.h b/lib/media_player_internal.h
index bc1faf44ba..c2d5348e22 100644
--- a/lib/media_player_internal.h
+++ b/lib/media_player_internal.h
@@ -31,6 +31,7 @@
 #include <vlc/vlc.h>
 #include <vlc/libvlc_media.h>
 #include <vlc_input.h>
+#include <vlc_player.h>
 #include <vlc_viewpoint.h>
 
 #include "../modules/audio_filter/equalizer_presets.h"
@@ -40,31 +41,19 @@ struct libvlc_media_player_t
     struct vlc_object_t obj;
 
     int                i_refcount;
-    vlc_mutex_t        object_lock;
 
-    struct
-    {
-        input_thread_t   *p_thread;
-        input_resource_t *p_resource;
-        vlc_renderer_item_t *p_renderer;
-        vlc_mutex_t       lock;
-    } input;
+    vlc_player_t *player;
+    vlc_player_listener_id *listener;
+    vlc_player_aout_listener_id *aout_listener;
 
     struct libvlc_instance_t * p_libvlc_instance; /* Parent instance */
     libvlc_media_t * p_md; /* current media descriptor */
     libvlc_event_manager_t event_manager;
-    libvlc_state_t state;
-    vlc_viewpoint_t viewpoint;
-    int selected_es[3];
 };
 
-/* Media player - audio, video */
-input_thread_t *libvlc_get_input_thread(libvlc_media_player_t * );
-
-
 libvlc_track_description_t * libvlc_get_track_description(
         libvlc_media_player_t *p_mi,
-        const char *psz_variable );
+        enum es_format_category_e cat );
 
 /**
  * Internal equalizer structure.
diff --git a/lib/video.c b/lib/video.c
index cb7838a28a..a318df0098 100644
--- a/lib/video.c
+++ b/lib/video.c
@@ -50,21 +50,8 @@
  */
 static vout_thread_t **GetVouts( libvlc_media_player_t *p_mi, size_t *n )
 {
-    input_thread_t *p_input = libvlc_get_input_thread( p_mi );
-    if( !p_input )
-    {
-        *n = 0;
-        return NULL;
-    }
-
-    vout_thread_t **pp_vouts;
-    if (input_Control( p_input, INPUT_GET_VOUTS, &pp_vouts, n))
-    {
-        *n = 0;
-        pp_vouts = NULL;
-    }
-    input_Release(p_input);
-    return pp_vouts;
+    vlc_player_t *player = p_mi->player;
+    return vlc_player_vout_HoldAll(player, n);
 }
 
 static vout_thread_t *GetVout (libvlc_media_player_t *mp, size_t num)
@@ -286,134 +273,94 @@ int libvlc_video_update_viewpoint( libvlc_media_player_t *p_mi,
         .fov   = p_viewpoint->f_field_of_view,
     };
 
-    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
-    if( p_input_thread != NULL )
-    {
-        if( input_UpdateViewpoint( p_input_thread, &update,
-                                   b_absolute ) != VLC_SUCCESS )
-        {
-            input_Release(p_input_thread);
-            return -1;
-        }
-        input_Release(p_input_thread);
-        return 0;
-    }
-
-    /* Save the viewpoint in case the input is not created yet */
-    if( !b_absolute )
-    {
-        p_mi->viewpoint.yaw += update.yaw;
-        p_mi->viewpoint.pitch += update.pitch;
-        p_mi->viewpoint.roll += update.roll;
-        p_mi->viewpoint.fov += update.fov;
-    }
-    else
-        p_mi->viewpoint = update;
-
-    vlc_viewpoint_clip( &p_mi->viewpoint );
+    enum vlc_player_whence whence = b_absolute ? VLC_PLAYER_WHENCE_ABSOLUTE
+                                               : VLC_PLAYER_WHENCE_RELATIVE;
+    vlc_player_UpdateViewpoint(p_mi->player, &update, whence);
 
+    /* may not fail anymore, keep int not to break the API */
     return 0;
 }
 
 int libvlc_video_get_spu( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    if( !p_input_thread )
-    {
-        libvlc_printerr( "No active input" );
-        return -1;
-    }
+    const struct vlc_player_track *track =
+        vlc_player_GetSelectedTrack(player, SPU_ES);
+    int i_spu = track ? vlc_es_id_GetInputId(track->es_id) : -1;
 
-    int i_spu = var_GetInteger( p_input_thread, "spu-es" );
-    input_Release(p_input_thread);
+    vlc_player_Unlock(player);
     return i_spu;
 }
 
 int libvlc_video_get_spu_count( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
-    int i_spu_count;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    if( !p_input_thread )
-        return 0;
+    int ret = vlc_player_GetTrackCount(p_mi->player, SPU_ES);
 
-    i_spu_count = var_CountChoices( p_input_thread, "spu-es" );
-    input_Release(p_input_thread);
-    return i_spu_count;
+    vlc_player_Unlock(player);
+    return ret;
 }
 
 libvlc_track_description_t *
         libvlc_video_get_spu_description( libvlc_media_player_t *p_mi )
 {
-    return libvlc_get_track_description( p_mi, "spu-es" );
+    return libvlc_get_track_description( p_mi, SPU_ES );
 }
 
 int libvlc_video_set_spu( libvlc_media_player_t *p_mi, int i_spu )
 {
-    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
-    vlc_value_t *list;
-    size_t count;
     int i_ret = -1;
 
-    if( !p_input_thread )
-        return -1;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    var_Change(p_input_thread, "spu-es", VLC_VAR_GETCHOICES,
-               &count, &list, (char ***)NULL);
+    size_t count = vlc_player_GetSubtitleTrackCount(player);
     for (size_t i = 0; i < count; i++)
     {
-        if( i_spu == list[i].i_int )
+        const struct vlc_player_track *track =
+            vlc_player_GetSubtitleTrackAt(player, i);
+        if (i_spu == vlc_es_id_GetInputId(track->es_id))
         {
-            if( var_SetInteger( p_input_thread, "spu-es", i_spu ) < 0 )
-                break;
+            /* found */
+            vlc_player_SelectTrack(player, track->es_id);
             i_ret = 0;
             goto end;
         }
     }
     libvlc_printerr( "Track identifier not found" );
 end:
-    input_Release(p_input_thread);
-    free(list);
+    vlc_player_Unlock(player);
     return i_ret;
 }
 
 int64_t libvlc_video_get_spu_delay( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
-    int64_t val = 0;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    if( p_input_thread )
-    {
-        val = US_FROM_VLC_TICK( var_GetInteger( p_input_thread, "spu-delay" ) );
-        input_Release(p_input_thread);
-    }
-    else
-    {
-        libvlc_printerr( "No active input" );
-    }
+    vlc_tick_t delay = vlc_player_GetSubtitleDelay(player);
 
-    return val;
+    vlc_player_Unlock(player);
+
+    return US_FROM_VLC_TICK(delay);
 }
 
 int libvlc_video_set_spu_delay( libvlc_media_player_t *p_mi,
                                 int64_t i_delay )
 {
-    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
-    int ret = -1;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    if( p_input_thread )
-    {
-        var_SetInteger( p_input_thread, "spu-delay", VLC_TICK_FROM_US( i_delay ) );
-        input_Release(p_input_thread);
-        ret = 0;
-    }
-    else
-    {
-        libvlc_printerr( "No active input" );
-    }
+    vlc_player_SetSubtitleDelay(player, VLC_TICK_FROM_US(i_delay),
+                                VLC_PLAYER_WHENCE_ABSOLUTE);
 
-    return ret;
+    vlc_player_Unlock(player);
+    /* may not fail anymore, keep int not to break the API */
+    return 0;
 }
 
 char *libvlc_video_get_crop_geometry (libvlc_media_player_t *p_mi)
@@ -447,50 +394,30 @@ int libvlc_video_get_teletext( libvlc_media_player_t *p_mi )
     return var_GetInteger (p_mi, "vbi-page");
 }
 
-static void teletext_enable( input_thread_t *p_input_thread, bool b_enable )
-{
-    if( b_enable )
-    {
-        vlc_value_t *list;
-        size_t count;
-
-        if( !var_Change( p_input_thread, "teletext-es", VLC_VAR_GETCHOICES,
-                         &count, &list, (char ***)NULL ) )
-        {
-            if( count > 0 )
-                var_SetInteger( p_input_thread, "spu-es", list[0].i_int );
-
-            free(list);
-        }
-    }
-    else
-        var_SetInteger( p_input_thread, "spu-es", -1 );
-}
-
 void libvlc_video_set_teletext( libvlc_media_player_t *p_mi, int i_page )
 {
-    input_thread_t *p_input_thread;
-    vlc_object_t *p_zvbi = NULL;
-    int telx;
-    bool b_key = false;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    if( i_page >= 0 && i_page < 1000 )
-        var_SetInteger( p_mi, "vbi-page", i_page );
-    else if( i_page >= 1000 )
+    if (i_page == 0)
+        vlc_player_SetTeletextEnabled(player, false);
+    else if (i_page > 0)
     {
-        switch (i_page)
+        if (i_page >= 1000)
         {
-            case libvlc_teletext_key_red:
-            case libvlc_teletext_key_green:
-            case libvlc_teletext_key_yellow:
-            case libvlc_teletext_key_blue:
-            case libvlc_teletext_key_index:
-                b_key = true;
-                break;
-            default:
+            bool is_key = i_page == libvlc_teletext_key_red
+                       || i_page == libvlc_teletext_key_green
+                       || i_page == libvlc_teletext_key_yellow
+                       || i_page == libvlc_teletext_key_blue
+                       || i_page == libvlc_teletext_key_index;
+            if (!is_key)
+            {
                 libvlc_printerr("Invalid key action");
                 return;
+            }
         }
+        vlc_player_SetTeletextEnabled(player, true);
+        vlc_player_SelectTeletextPage(player, i_page);
     }
     else
     {
@@ -498,99 +425,62 @@ void libvlc_video_set_teletext( libvlc_media_player_t *p_mi, int i_page )
         return;
     }
 
-    p_input_thread = libvlc_get_input_thread( p_mi );
-    if( !p_input_thread ) return;
-
-    if( var_CountChoices( p_input_thread, "teletext-es" ) <= 0 )
-    {
-        input_Release(p_input_thread);
-        return;
-    }
-
-    if( i_page == 0 )
-    {
-        teletext_enable( p_input_thread, false );
-    }
-    else
-    {
-        telx = var_GetInteger( p_input_thread, "teletext-es" );
-        if( telx >= 0 )
-        {
-            if( input_GetEsObjects( p_input_thread, telx, &p_zvbi )
-                == VLC_SUCCESS )
-            {
-                var_SetInteger( p_zvbi, "vbi-page", i_page );
-            }
-        }
-        else if (!b_key)
-        {
-            /* the "vbi-page" will be selected on es creation */
-            teletext_enable( p_input_thread, true );
-        }
-        else
-            libvlc_printerr("Key action sent while the teletext is disabled");
-    }
-    input_Release(p_input_thread);
+    vlc_player_Unlock(player);
 }
 
 int libvlc_video_get_track_count( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
-    int i_track_count;
-
-    if( !p_input_thread )
-        return -1;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    i_track_count = var_CountChoices( p_input_thread, "video-es" );
+    int ret = vlc_player_GetTrackCount(p_mi->player, VIDEO_ES);
 
-    input_Release(p_input_thread);
-    return i_track_count;
+    vlc_player_Unlock(player);
+    return ret;
 }
 
 libvlc_track_description_t *
         libvlc_video_get_track_description( libvlc_media_player_t *p_mi )
 {
-    return libvlc_get_track_description( p_mi, "video-es" );
+    return libvlc_get_track_description( p_mi, VIDEO_ES );
 }
 
 int libvlc_video_get_track( libvlc_media_player_t *p_mi )
 {
-    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    if( !p_input_thread )
-        return -1;
+    const struct vlc_player_track * track =
+        vlc_player_GetSelectedTrack(player, VIDEO_ES);
+    int id = track ? vlc_es_id_GetInputId(track->es_id) : -1;
 
-    int id = var_GetInteger( p_input_thread, "video-es" );
-    input_Release(p_input_thread);
+    vlc_player_Unlock(player);
     return id;
 }
 
 int libvlc_video_set_track( libvlc_media_player_t *p_mi, int i_track )
 {
-    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
-    vlc_value_t *val_list;
-    size_t count;
     int i_ret = -1;
 
-    if( !p_input_thread )
-        return -1;
+    vlc_player_t *player = p_mi->player;
+    vlc_player_Lock(player);
 
-    var_Change( p_input_thread, "video-es", VLC_VAR_GETCHOICES,
-                &count, &val_list, (char ***)NULL );
+    size_t count = vlc_player_GetVideoTrackCount(player);
     for( size_t i = 0; i < count; i++ )
     {
-        if( i_track == val_list[i].i_int )
+        const struct vlc_player_track *track =
+            vlc_player_GetVideoTrackAt(player, i);
+        if (i_track == vlc_es_id_GetInputId(track->es_id))
         {
-            if( var_SetInteger( p_input_thread, "video-es", i_track ) < 0 )
-                break;
+            /* found */
+            vlc_player_SelectTrack(player, track->es_id);
             i_ret = 0;
             goto end;
         }
     }
     libvlc_printerr( "Track identifier not found" );
 end:
-    free(val_list);
-    input_Release(p_input_thread);
+    vlc_player_Unlock(player);
     return i_ret;
 }
 
-- 
2.20.1




More information about the vlc-devel mailing list