diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h
index 7881971..0afdbf4 100644
--- a/include/vlc/libvlc_media_player.h
+++ b/include/vlc/libvlc_media_player.h
@@ -378,6 +378,19 @@ VLC_PUBLIC_API int libvlc_media_player_get_chapter_count( libvlc_media_player_t
 VLC_PUBLIC_API int libvlc_media_player_will_play( libvlc_media_player_t *p_mi );
 
 /**
+ * Current (fill) size of decoder buffer
+ *
+ * \param p_mi the Media Player
+ * \param pi_count pointer to int to receive count of buffer items or NULL
+ * \param pi_size pointer to size_t to receive size of buffer in bytes or NULL
+ * \param pi_length pointer to libvlc_time_t to receive bufferlength in ms or NULL
+ */
+VLC_PUBLIC_API void libvlc_media_player_get_buffer_state( libvlc_media_player_t *p_mi,
+                                                          int *pi_count,
+                                                          size_t *pi_size,
+                                                          libvlc_time_t *pi_length );
+
+/**
  * Get title chapter count
  *
  * \param p_mi the Media Player
diff --git a/include/vlc_input.h b/include/vlc_input.h
index da57548..6c9230e 100644
--- a/include/vlc_input.h
+++ b/include/vlc_input.h
@@ -518,6 +518,9 @@ enum input_query_e
     /* External clock managments */
     INPUT_GET_PCR_SYSTEM,   /* arg1=mtime_t *, arg2=mtime_t *       res=can fail */
     INPUT_MODIFY_PCR_SYSTEM,/* arg1=int absolute, arg2=mtime_t      res=can fail */
+
+    /* Input Decoder */
+    INPUT_GET_DECODER_FIFO_STATE, /* arg1=int*, arg2=size_t*, arg3=mtime_t*     res=cannot fail */
 };
 
 /** @}*/
diff --git a/src/control/media_player.c b/src/control/media_player.c
index 5b33293..e9c2cd4 100644
--- a/src/control/media_player.c
+++ b/src/control/media_player.c
@@ -1091,6 +1091,27 @@ int libvlc_media_player_will_play( libvlc_media_player_t *p_mi )
     return b_will_play;
 }
 
+void libvlc_media_player_get_buffer_state( libvlc_media_player_t *p_mi, int *pi_count, size_t *pi_size, libvlc_time_t *pi_length )
+{
+    input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
+    int            i_count = 0;
+    size_t         i_size = 0;
+    mtime_t        i_length = 0;
+
+    if( p_input_thread )
+    {
+        input_Control( p_input_thread, INPUT_GET_DECODER_FIFO_STATE, &i_count, &i_size, &i_length );
+        vlc_object_release( p_input_thread );
+    }
+
+    if( pi_count )
+        *pi_count = i_count;
+    if( pi_size )
+        *pi_size = i_size;
+    if( pi_length )
+        *pi_length = i_length / 1000;
+}
+
 int libvlc_media_player_set_rate( libvlc_media_player_t *p_mi, float rate )
 {
     if (rate < 0.)
diff --git a/src/input/control.c b/src/input/control.c
index e1cd747..8b3d857 100644
--- a/src/input/control.c
+++ b/src/input/control.c
@@ -349,6 +349,15 @@ int input_vaControl( input_thread_t *p_input, int i_query, va_list args )
             vlc_mutex_unlock( &p_input->p->p_item->lock );
             return VLC_SUCCESS;
 
+        case INPUT_GET_DECODER_FIFO_STATE:
+	{
+            int *pi_count = (int*)va_arg( args, int * );
+            size_t *pi_size = (size_t*)va_arg( args, size_t * );
+            mtime_t *pi_length = (mtime_t*)va_arg( args, mtime_t * );
+
+            return es_out_Control( p_input->p->p_es_out_display, ES_OUT_GET_DECODER_FIFO_STATE, pi_count, pi_size, pi_length );
+	}
+
         case INPUT_ADD_SLAVE:
             psz = (char*)va_arg( args, char * );
             if( psz && *psz )
diff --git a/src/input/decoder.c b/src/input/decoder.c
index df6b781..20af4f4 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -635,6 +635,27 @@ size_t input_DecoderGetFifoSize( decoder_t *p_dec )
     return block_FifoSize( p_owner->p_fifo );
 }
 
+void input_DecoderGetFifoState( decoder_t *p_dec, int *pi_count, size_t *pi_size, mtime_t *pi_length )
+{
+    decoder_owner_sys_t *p_owner = p_dec->p_owner;
+
+    vlc_mutex_lock( &p_owner->lock );
+
+    /* avoid locking */
+    if(block_FifoSize( p_owner->p_fifo ) > 0) {
+        block_ChainProperties( block_FifoShow( p_owner->p_fifo ), pi_count, pi_size, pi_length );
+    } else {
+        if( pi_count )
+            *pi_count = 0;
+        if( pi_size )
+            *pi_size = 0;
+        if( pi_length )
+            *pi_length = 0;
+    }
+
+    vlc_mutex_unlock( &p_owner->lock );
+}
+
 void input_DecoderGetObjects( decoder_t *p_dec,
                               vout_thread_t **pp_vout, aout_instance_t **pp_aout )
 {
diff --git a/src/input/decoder.h b/src/input/decoder.h
index b113d22..3c119a4 100644
--- a/src/input/decoder.h
+++ b/src/input/decoder.h
@@ -105,6 +105,11 @@ bool input_DecoderHasFormatChanged( decoder_t *p_dec, es_format_t *p_fmt, vlc_me
 size_t input_DecoderGetFifoSize( decoder_t *p_dec );
 
 /**
+ * This function returns some information on the decoder fifo
+ */
+void input_DecoderGetFifoState( decoder_t *p_dec, int *pi_count, size_t *pi_size, mtime_t *pi_length );
+
+/**
  * This function returns the objects associated to a decoder
  *
  * They must be released using vlc_object_release().
diff --git a/src/input/es_out.c b/src/input/es_out.c
index afc8c47..8b7feee 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -452,6 +452,45 @@ static bool EsOutDecodersIsEmpty( es_out_t *out )
     return true;
 }
 
+static void EsOutGetDecoderFifoState( es_out_t *out, int *pi_count, size_t *pi_size, mtime_t *pi_length )
+{
+    es_out_sys_t      *p_sys = out->p_sys;
+
+    int               i_count = 0;
+    size_t            i_size = 0;
+    mtime_t           i_length = 0;
+
+    int i;
+
+    for( i = 0; i < p_sys->i_es; i++ )
+    {
+        es_out_id_t *p_es = p_sys->es[i];
+        int         i_thisCount = 0;
+	size_t      i_thisSize = 0;
+	mtime_t     i_thisLength = 0;
+
+
+        if( p_es->p_dec )
+            input_DecoderGetFifoState( p_es->p_dec, &i_thisCount, &i_thisSize, &i_thisLength );
+        if( p_es->p_dec_record )
+            input_DecoderGetFifoState( p_es->p_dec_record, &i_thisCount, &i_thisSize, &i_thisLength );
+
+	i_count += i_thisCount;
+	i_size += i_thisSize;
+
+        /* largest fifo wins */
+	if( i_thisLength > i_length )
+	    i_length = i_thisLength;
+    }
+
+    if( pi_count )
+        *pi_count = i_count;
+    if( pi_size )
+        *pi_size = i_size;
+    if( pi_length )
+        *pi_length = i_length;
+}
+
 static void EsOutSetDelay( es_out_t *out, int i_cat, int64_t i_delay )
 {
     es_out_sys_t *p_sys = out->p_sys;
@@ -2534,6 +2573,15 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
             return VLC_SUCCESS;
         }
 
+        case ES_OUT_GET_DECODER_FIFO_STATE:
+        {
+            int *pi_count = va_arg( args, int* );
+	    size_t *pi_size = va_arg( args, size_t* );
+	    mtime_t *pi_length = va_arg( args, mtime_t* );
+            EsOutGetDecoderFifoState( out, pi_count, pi_size, pi_length );
+            return VLC_SUCCESS;
+        }
+
         case ES_OUT_SET_DELAY:
         {
             const int i_cat = (int)va_arg( args, int );
diff --git a/src/input/es_out.h b/src/input/es_out.h
index 89ece06..1d4987c 100644
--- a/src/input/es_out.h
+++ b/src/input/es_out.h
@@ -80,6 +80,9 @@ enum es_out_query_private_e
 
     /* Set jitter */
     ES_OUT_SET_JITTER,                              /* arg1=mtime_t i_pts_delay arg2= mtime_t i_pts_jitter, arg2=int i_cr_average res=cannot fail */
+
+    /* Get Decoder FIFO state */
+    ES_OUT_GET_DECODER_FIFO_STATE,                  /* arg1=int* pi_count arg2=size_t* pi_size arg3=mtime_t* pi_length res=cannot fail */
 };
 
 static inline void es_out_SetMode( es_out_t *p_out, int i_mode )
@@ -111,6 +114,11 @@ static inline bool es_out_GetEmpty( es_out_t *p_out )
     assert( !i_ret );
     return b;
 }
+static inline void es_out_GetDecoderFifoState( es_out_t *p_out, int *pi_count, size_t *pi_size, mtime_t *pi_length )
+{
+    int i_ret = es_out_Control( p_out, ES_OUT_GET_DECODER_FIFO_STATE, pi_count, pi_size, pi_length );
+    assert( !i_ret );
+}
 static inline void es_out_SetDelay( es_out_t *p_out, int i_cat, mtime_t i_delay )
 {
     int i_ret = es_out_Control( p_out, ES_OUT_SET_DELAY, i_cat, i_delay );
diff --git a/src/input/es_out_timeshift.c b/src/input/es_out_timeshift.c
index 4aa997f..55f197d 100644
--- a/src/input/es_out_timeshift.c
+++ b/src/input/es_out_timeshift.c
@@ -484,6 +484,26 @@ static int ControlLockedGetBuffering( es_out_t *p_out, bool *pb_buffering )
 
     return VLC_SUCCESS;
 }
+static int ControlLockedGetDecoderFifoState( es_out_t *p_out, int *pi_count, size_t *pi_size, mtime_t *pi_length )
+{
+    es_out_sys_t *p_sys = p_out->p_sys;
+
+    if( p_sys->b_delayed )
+    {
+        if( pi_count )
+            *pi_count = 0;
+        if( pi_size )
+            *pi_size = 0;
+        if( pi_length )
+            *pi_length = 0;
+    }
+    else
+    {
+        es_out_GetDecoderFifoState( p_sys->p_out, pi_count, pi_size, pi_length );
+    }
+
+    return VLC_SUCCESS;
+}
 static int ControlLockedSetPauseState( es_out_t *p_out, bool b_source_paused, bool b_paused, mtime_t i_date )
 {
     es_out_sys_t *p_sys = p_out->p_sys;
@@ -650,6 +670,13 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args )
         bool *pb_buffering = (bool *)va_arg( args, bool* );
         return ControlLockedGetBuffering( p_out, pb_buffering );
     }
+    case ES_OUT_GET_DECODER_FIFO_STATE:
+    {
+        int *pi_count = (int *)va_arg( args, int* );
+        size_t *pi_size = (size_t *)va_arg( args, size_t* );
+	mtime_t *pi_length = (mtime_t *)va_arg( args, mtime_t* );
+        return ControlLockedGetDecoderFifoState( p_out, pi_count, pi_size, pi_length );
+    }
     case ES_OUT_SET_PAUSE_STATE:
     {
         const bool b_source_paused = (bool)va_arg( args, int );
diff --git a/src/libvlc.sym b/src/libvlc.sym
index d46a177..9bcaad1 100644
--- a/src/libvlc.sym
+++ b/src/libvlc.sym
@@ -108,6 +108,7 @@ libvlc_media_player_can_pause
 libvlc_media_player_next_frame
 libvlc_media_player_event_manager
 libvlc_media_player_get_agl
+libvlc_media_player_get_buffer_state
 libvlc_media_player_get_chapter
 libvlc_media_player_get_chapter_count
 libvlc_media_player_get_chapter_count_for_title
